home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / sources / misc / 3959 < prev    next >
Encoding:
Text File  |  1992-09-15  |  57.1 KB  |  2,023 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: wht@n4hgf.Mt-Park.GA.US (Warren Tucker)
  4. Subject:  v32i067:  ecu - ECU Asynchronous Communications v3.20, Part32/40
  5. Message-ID: <1992Sep15.153107.19838@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 92638c50d41db08f422cb82039167f3a
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. References: <csm-v32i036=ecu.141245@sparky.IMD.Sterling.COM>
  11. Date: Tue, 15 Sep 1992 15:31:07 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 2008
  14.  
  15. Submitted-by: wht@n4hgf.Mt-Park.GA.US (Warren Tucker)
  16. Posting-number: Volume 32, Issue 67
  17. Archive-name: ecu/part32
  18. Environment: SCO,XENIX,ISC,SUNOS,SYSVR4,HDB,Curses
  19. Supersedes: ecu: Volume 21, Issue 53-89
  20.  
  21. ---- Cut Here and feed the following to sh ----
  22. #!/bin/sh
  23. # this is ecu320.32 (part 32 of ecu320)
  24. # do not concatenate these parts, unpack them in order with /bin/sh
  25. # file fasi/RELEASENOTES continued
  26. #
  27. if test ! -r _shar_seq_.tmp; then
  28.     echo 'Please unpack part 1 first!'
  29.     exit 1
  30. fi
  31. (read Scheck
  32.  if test "$Scheck" != 32; then
  33.     echo Please unpack part "$Scheck" next!
  34.     exit 1
  35.  else
  36.     exit 0
  37.  fi
  38. ) < _shar_seq_.tmp || exit 1
  39. if test ! -f _shar_wnt_.tmp; then
  40.     echo 'x - still skipping fasi/RELEASENOTES'
  41. else
  42. echo 'x - continuing file fasi/RELEASENOTES'
  43. sed 's/^X//' << 'SHAR_EOF' >> 'fasi/RELEASENOTES' &&
  44. X          but is checked by the kernel config program.
  45. X
  46. X          The gcc (GNU cc) support was removed because gcc's object
  47. X          file wants to link in some "helpful" functions that aren't
  48. X          contained in the kernel. But anyway, FAS is tuned so carefully
  49. X          and depends on the optimization behaviour of the AT&T
  50. X          standard C compiler that gcc won't have any advantages.
  51. X
  52. X          I changed the method with which the `fas_test_device' function
  53. X          waits for certain events. The `delay' function was used
  54. X          for that purpose but it turned out that with some flavors
  55. X          of UNIX it is prohibited to use this function during the
  56. X          xxinit phase of the boot process. Now a simple timeout loop
  57. X          is used instead.
  58. X
  59. X          Removed the ADAPT_TIME mechanismn introduced in release 2.05.
  60. X
  61. X          The open() call now returns an `EBUSY' error number if the
  62. X          device is already open and can't be opened in the desired
  63. X          mode at this time.
  64. X
  65. X          The handling of the RING signal needed fixing. Unlike the other
  66. X          three modem status lines RING generates an interrupt only at
  67. X          the trailing edge.
  68. X
  69. X          No SIGHUP signal is sent any more if an ioctl call clears
  70. X          the CLOCAL termio(7) flag while there is no carrier present.
  71. X          SIGHUP is only sent if the actual DCD modem line drops.
  72. X
  73. X          The files *-mux4 were renamed to *-ast4 because this type of
  74. X          card was originally developed by AST (AST 4-port card).
  75. X
  76. X     ------------------------------------------------------------
  77. X          
  78. X     release 2.08 Sun Jan 13, 1991
  79. X
  80. X     New Features:
  81. X
  82. X          Bell Tech/Intel UNIX 3.2 is supported.
  83. X
  84. X          SCO Xenix 286 is also supported now. Thanks to Nickolay Saukh
  85. X          (nms@saukh.rd.jvd.su) for providing the patches.
  86. X
  87. X          The Bell Tech HUB-6 card can be used with FAS. Thanks to
  88. X          Keith Walker (kew@cims2.UUCP) for the patches.
  89. X
  90. X          For AT&T derived flavors of UNIX there is a line automatically
  91. X          added to the kernel description file that makes the adding
  92. X          and removing of FAS possible via the `kconfig' program. Thanks
  93. X          to John Adams (johna@grumpy.boston.ma.us) for this idea.
  94. X
  95. X          There is a mechanismn now that prevents excessive modem status
  96. X          interrupts caused by crosstalking between wires or by a loose
  97. X          cable.
  98. X
  99. X          You can disable the FIFOs in a UART by "oring" the macro
  100. X          `NO_FIFO' to the base port address of this device. This is
  101. X          useful for mouse devices where you need immediate response
  102. X          to the mouse movement.
  103. X
  104. X          The meaning of the bit mapped part of the minor device
  105. X          numbers has changed. Some rather useless functions were
  106. X          removed in favor of more control over the hardware handshake
  107. X          modes. Even systems where the SCO RTSFLOW/CTSFLOW termio(7)
  108. X          flags are not available can now use half duplex hardware
  109. X          flow control (selected via the minor device number).
  110. X
  111. X          The assignment of RS232C lines to certain FAS functions
  112. X          is even more flexible now. This allows to connect two
  113. X          UNIX systems (with FAS) via a null modem cable, running
  114. X          a getty at both ends. For more details, read the paragraph
  115. X          about CABLING in the README file.
  116. X
  117. X          A special handling of the NS16550A input FIFO was introduced.
  118. X          This causes multiple receiver interrupts (on the same IRQ
  119. X          line) to be synchronized so that only one interrupt is
  120. X          necessary to process all receiving ports. This reduces the
  121. X          interrupt handling overhead and therefor results in lower
  122. X          CPU load for concurrent serial input at high speeds.
  123. X
  124. X          The `fas_event' function processes all scheduled events
  125. X          for all units with one single call. Previously, every unit
  126. X          launched its own timeout() call if there was work to
  127. X          do. This could lead to up to 16 timeouts at the same time,
  128. X          resulting in some timeout handling overhead. This overhead
  129. X          is minimized now.
  130. X
  131. X     Bug Fixes:
  132. X
  133. X          There were two bugs that could cause a port to lock up,
  134. X          resulting in an immortal process.
  135. X
  136. X          Almost any kernel sleep is killable now (at least with one or
  137. X          two `kill -9'). Therefor, there should be no more immortal
  138. X          processes. Even killing a process that is hanging in a
  139. X          close-on-exit call is possible.
  140. X
  141. X          The meaning of the RTSFLOW/CTSFLOW termio(7) flags was converted
  142. X          to what SCO had in mind (half duplex flow control). This is for
  143. X          compatibility reasons. Full duplex RTS/CTS hardware flow control
  144. X          is still possible via the minor device number method. Thanks to
  145. X          Dmitry V. Volodin (dvv@hq.demos.su) for providing me with the
  146. X          necessary knowledge.
  147. X
  148. X          If a process is already sleeping in a getty open it will only
  149. X          unblock on DCD low->high. In particular, if in the meantime
  150. X          the device was open for dialout and DCD is still present if
  151. X          the getty open takes over again this won't unblock the getty
  152. X          open any more.
  153. X
  154. X          And there were, as usual, a number of other small bug fixes.
  155. SHAR_EOF
  156. echo 'File fasi/RELEASENOTES is complete' &&
  157. chmod 0644 fasi/RELEASENOTES ||
  158. echo 'restore of fasi/RELEASENOTES failed'
  159. Wc_c="`wc -c < 'fasi/RELEASENOTES'`"
  160. test 23494 -eq "$Wc_c" ||
  161.     echo 'fasi/RELEASENOTES: original size 23494, current size' "$Wc_c"
  162. rm -f _shar_wnt_.tmp
  163. fi
  164. # ============= fasi/Space.c ==============
  165. if test -f 'fasi/Space.c' -a X"$1" != X"-c"; then
  166.     echo 'x - skipping fasi/Space.c (File already exists)'
  167.     rm -f _shar_wnt_.tmp
  168. else
  169. > _shar_wnt_.tmp
  170. echo 'x - extracting fasi/Space.c (Text)'
  171. sed 's/^X//' << 'SHAR_EOF' > 'fasi/Space.c' &&
  172. X/* Async device configuration file for the FAS async driver. */
  173. X
  174. X/* 
  175. X * COM1(STD) + COM2(DIGIBOARD PC-8)
  176. X */
  177. X/*+:EDITS:*/
  178. X/*:09-10-1992-13:59-wht@n4hgf-ECU release 3.20 */
  179. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  180. X/*:07-25-1991-12:57-wht@n4hgf-ECU release 3.10 */
  181. X/*:01-20-1991-16:17-wht@n4hgf-add fas_names */
  182. X/*:01-20-1991-05:01-wht@n4hgf-changed buffer sizes */
  183. X/*:01-16-1991-22:13-wht@n4hgf-creation */
  184. X/* FAS was developed by ( ==> BUT DO NOT CONTACT HIM ABOUT THIS HACK )
  185. XUwe Doering             INET : gemini@geminix.in-berlin.de
  186. XBillstedter Pfad 17 b   UUCP : ...!unido!fub!geminix.in-berlin.de!gemini
  187. X1000 Berlin 20
  188. XGermany
  189. X*/
  190. X
  191. X/* Alas, SCO idinstall has no -z (Define) option like ISC does */
  192. X#if !defined(FASI)
  193. X#define FASI
  194. X#endif
  195. X#if !defined(SCO)
  196. X#define SCO
  197. X#endif
  198. X
  199. X#if defined(FASI)
  200. X/* {quan,irq,addr1-addr2,type} */
  201. Xchar *fasi_space_ident =
  202. X"FAS/i 2.08:{1,4,03f8-03ff,COM1},{8,3,0210-024f,DIGI-PC8}";
  203. X#endif /* FASI */
  204. X
  205. X#if !defined (M_I286) && !defined(__STDC__) && !defined(__GNUC__)
  206. X#ident    "@(#)space.c    2.08.0 COM1(STD) + COM2(DIGIBOARD PC-8)";
  207. X#endif
  208. X
  209. X#include <sys/param.h>
  210. X#include <sys/types.h>
  211. X#include <sys/signal.h>
  212. X#include <sys/buf.h>
  213. X#include <sys/dir.h>
  214. X#if defined (XENIX)
  215. X#include <sys/page.h>
  216. X#include <sys/seg.h>
  217. X#endif
  218. X#include <sys/user.h>
  219. X#include <sys/errno.h>
  220. X#include <sys/tty.h>
  221. X#include <sys/conf.h>
  222. X#include <sys/sysinfo.h>
  223. X#include <sys/file.h>
  224. X#if !defined (XENIX) && !defined(CBAUD)
  225. X#include <sys/termio.h>
  226. X#endif
  227. X#include <sys/ioctl.h>
  228. X#if !defined(FASI)
  229. X#include <macros.h>
  230. X#endif
  231. X#if defined (HAVE_VPIX)
  232. X#if !defined (XENIX)
  233. X#include <sys/tss.h>
  234. X#include <sys/immu.h>
  235. X#include <sys/region.h>
  236. X#endif
  237. X#include <sys/proc.h>
  238. X#include <sys/v86.h>
  239. X#endif
  240. X
  241. X#if defined (XENIX)
  242. X#include "fas.h"
  243. X#include "digi-pc8.h"
  244. X#else
  245. X#include <local/fas.h>
  246. X#include <local/digi-pc8.h>
  247. X#endif
  248. X
  249. X/* This is the number of devices to be handled by this driver.
  250. X   You may define up to 16 devices.  If this number is changed
  251. X   the arrays below must be filled in accordingly.
  252. X*/
  253. X#define NUM_PHYSICAL_UNITS    9
  254. X
  255. X#if NUM_PHYSICAL_UNITS > MAX_UNITS
  256. X#undef NUM_PHYSICAL_UNITS
  257. X#define NUM_PHYSICAL_UNITS    MAX_UNITS
  258. X#endif
  259. X
  260. X/* let the driver know the number of devices */
  261. Xuint    fas_physical_units = NUM_PHYSICAL_UNITS;
  262. X
  263. X/* array of base port addresses
  264. X   If you deliberately want to force off the FIFOs of a UART you have
  265. X   to "or" the NO_FIFO macro to its base port address. This is useful
  266. X   for mouse devices where you need immediate response to the mouse
  267. X   movement.
  268. X*/
  269. Xulong    fas_port [NUM_PHYSICAL_UNITS] =
  270. X{
  271. X    0x3f8,
  272. X    COM21, COM22, COM23, COM24,COM25, COM26, COM27, COM28
  273. X};
  274. X
  275. X/*
  276. X * array of port names
  277. X * Note this is a kludge to enable kmem seeking programs to
  278. X * determine which tty is associated with which tty struct
  279. X * and is <yetch> duplication of information appearing in
  280. X * the Node (/etc/node.d/fas) file
  281. X */
  282. X#if defined(FASI)
  283. Xstruct fas_name    fas_names[NUM_PHYSICAL_UNITS * 2] =
  284. X{
  285. X    {"1a"},
  286. X    {"2a"}, {"2b"},{"2c"},{"2d"},{"2e"},{"2f"},{"2g"},{"2h"},
  287. X    {"1A"},
  288. X    {"2A"}, {"2B"},{"2C"},{"2D"},{"2E"},{"2F"},{"2G"},{"2H"}
  289. X};
  290. X#endif
  291. X
  292. X/* array of interrupt vectors */
  293. Xuint    fas_vec [NUM_PHYSICAL_UNITS] =
  294. X{
  295. X    4,
  296. X    3,3,3,3,3,3,3,3
  297. X};
  298. X
  299. X/* initialization sequence for serial card
  300. X   This array contains pairs of values of the form:
  301. X
  302. X        portaddress, value,
  303. X              :
  304. X              :
  305. X        portaddress, value,
  306. X        0
  307. X
  308. X   For every line `value' will be written to `portaddress'. If
  309. X   `value' is replaced with the macro `READ_PORT' then a value
  310. X   is read from `portaddress' instead. The value itself will be
  311. X   discarded. Therefor this makes only sense if the read access
  312. X   to the port has a side effect like setting or resetting
  313. X   certain flags.
  314. X
  315. X   NOTE: This array *must* be terminated with a value of 0
  316. X         in the portaddress column!
  317. X*/
  318. Xuint    fas_init_seq [] =
  319. X{
  320. X    0
  321. X};
  322. X
  323. X/* initial modem control port info
  324. X   This value is ored into the modem control value for each UART. This is
  325. X   normaly used to force out2 which is used to enable the interrupts of
  326. X   the standard com1 and com2 ports. Several brands of cards have modes
  327. X   that allow them to work in compatible mode like com1 and com2 or as a
  328. X   shared interrupts card. One of these cards is the AST 4-port card. When
  329. X   this card is used in shared interrupts mode out2 must _not_ be set.
  330. X
  331. X   Note: This is one of the major trouble-spots with shared interrupts
  332. X   cards. Check your manual.
  333. X*/
  334. Xuint    fas_mcb [NUM_PHYSICAL_UNITS] =
  335. X{
  336. X    MC_SET_OUT2,
  337. X    MC_SET_OUT2, MC_SET_OUT2, MC_SET_OUT2, MC_SET_OUT2,
  338. X    MC_SET_OUT2, MC_SET_OUT2, MC_SET_OUT2, MC_SET_OUT2
  339. X};
  340. X
  341. X/* array of modem control flags
  342. X   You can choose which signals to use for modem control. See fas.h
  343. X   for possible names and values. Whether or not modem control is
  344. X   used is determined by the minor device number at open time.
  345. X*/
  346. Xulong    fas_modem [NUM_PHYSICAL_UNITS] =
  347. X{
  348. X    EO_DTR | EI_DTR | CA_DCD,
  349. X    EO_DTR | EI_DTR | CA_DCD, EO_DTR | EI_DTR | CA_DCD,
  350. X    EO_DTR | EI_DTR | CA_DCD, EO_DTR | EI_DTR | CA_DCD,
  351. X    EO_DTR | EI_DTR | CA_DCD, EO_DTR | EI_DTR | CA_DCD,
  352. X    EO_DTR | EI_DTR | CA_DCD, EO_DTR | EI_DTR | CA_DCD
  353. X};
  354. X
  355. X/* array of hardware flow control flags
  356. X   You can choose which signals to use for hardware handshake. See fas.h
  357. X   for possible names and values. Whether or not hardware handshake is
  358. X   used is determined by the minor device number at open time and by the
  359. X   RTSFLOW/CTSFLOW termio(7) flags.
  360. X*/
  361. Xulong    fas_flow [NUM_PHYSICAL_UNITS] =
  362. X{
  363. X    HI_RTS | HO_CTS_ON_DSR | HX_RTS,
  364. X    HI_RTS | HO_CTS_ON_DSR | HX_RTS,
  365. X    HI_RTS | HO_CTS_ON_DSR | HX_RTS,
  366. X    HI_RTS | HO_CTS_ON_DSR | HX_RTS,
  367. X    HI_RTS | HO_CTS_ON_DSR | HX_RTS,
  368. X    HI_RTS | HO_CTS_ON_DSR | HX_RTS,
  369. X    HI_RTS | HO_CTS_ON_DSR | HX_RTS,
  370. X    HI_RTS | HO_CTS_ON_DSR | HX_RTS,
  371. X    HI_RTS | HO_CTS_ON_DSR | HX_RTS
  372. X};
  373. X
  374. X/* array of control register addresses
  375. X   There are serial boards available that have all serial ports
  376. X   multiplexed to one address location in order to save I/O address
  377. X   space (Bell Tech HUB-6 card etc.). This multiplexing is controlled
  378. X   by a special register that needs to be written to before the actual
  379. X   port registers can be accessed. This array contains the addresses
  380. X   of these special registers.
  381. X   Enter the addresses on a per unit base. An address of zero
  382. X   disables this feature.
  383. X*/
  384. Xuint    fas_ctl_port [NUM_PHYSICAL_UNITS] =
  385. X{
  386. X    0,
  387. X    0,    0, 0, 0, 0, 0, 0, 0
  388. X};
  389. X
  390. X/* array of control register values
  391. X   These values are written to the corresponding control register
  392. X   before the first access to the actual port registers. If not only
  393. X   entire UART chips (blocks of 8 contiguous addresses) but even the
  394. X   single registers of the UART chips need to be multiplexed to one
  395. X   address you have to "or" a bit mask (shifted 8 times to the left)
  396. X   to the control register value. This mask determines at which bit
  397. X   locations the UART chip register number is "xored" into the control
  398. X   register value at runtime. This implies that you can also use
  399. X   negative logic by setting the bits in the control register value
  400. X   to 1 at the locations corresponding to the bit mask.
  401. X*/
  402. Xuint    fas_ctl_val [NUM_PHYSICAL_UNITS] =
  403. X{
  404. X    0,
  405. X    0, 0, 0, 0, 0, 0, 0, 0
  406. X};
  407. X
  408. X/* additional configurations for shared interrupts boards
  409. X   If you have a shared interrupts board, you may have to acknowledge
  410. X   interrupts by writing to a special register. The following arrays
  411. X   contain the special register addresses and the corresponding values
  412. X   that are written to them in response to an interrupt.
  413. X*/
  414. X
  415. X/* array of int ack register addresses
  416. X   These registers are written to every time after all interrupt
  417. X   sources in all of the UARTs that are tied to the corresponding
  418. X   interrupt vector have been cleared.
  419. X   Enter the addresses on a per vector base. An address of zero
  420. X   disables this feature.
  421. X*/
  422. Xuint    fas_int_ack_port [NUM_INT_VECTORS] =
  423. X{
  424. X    0,    0,    0,    0,
  425. X    0,    0,    0,    0,
  426. X    0,    0,    0,    0,
  427. X    0,    0,    0,    0,
  428. X    0,    0,    0,    0,
  429. X    0,    0,    0,    0,
  430. X    0,    0,    0,    0,
  431. X    0,    0,    0,    0
  432. X};
  433. X
  434. X/* array of int ack values
  435. X   These values are written to the corresponding int ack register
  436. X   in response to an interrupt.
  437. X*/
  438. Xuint    fas_int_ack [NUM_INT_VECTORS] =
  439. X{
  440. X    0,    0,    0,    0,
  441. X    0,    0,    0,    0,
  442. X    0,    0,    0,    0,
  443. X    0,    0,    0,    0,
  444. X    0,    0,    0,    0,
  445. X    0,    0,    0,    0,
  446. X    0,    0,    0,    0,
  447. X    0,    0,    0,    0
  448. X};
  449. X
  450. X/* NOTHING NEEDS TO BE CHANGED BELOW THIS LINE.
  451. X   ============================================
  452. X*/
  453. X
  454. X/* array of structures to hold all info for a physical minor device */
  455. Xstruct fas_info    fas_info [NUM_PHYSICAL_UNITS];
  456. X
  457. X/* array of ttys for logical minor devices */
  458. Xstruct tty    fas_tty [NUM_PHYSICAL_UNITS * 2];
  459. X
  460. X/* array of pointers to fas_info structures
  461. X   this prevents time consuming multiplications for index calculation
  462. X*/
  463. Xstruct fas_info    *fas_info_ptr [NUM_PHYSICAL_UNITS];
  464. X
  465. X/* array of pointers to fas_tty structures
  466. X   this prevents time consuming multiplications for index calculation
  467. X*/
  468. Xstruct tty    *fas_tty_ptr [NUM_PHYSICAL_UNITS * 2];
  469. SHAR_EOF
  470. chmod 0644 fasi/Space.c ||
  471. echo 'restore of fasi/Space.c failed'
  472. Wc_c="`wc -c < 'fasi/Space.c'`"
  473. test 8785 -eq "$Wc_c" ||
  474.     echo 'fasi/Space.c: original size 8785, current size' "$Wc_c"
  475. rm -f _shar_wnt_.tmp
  476. fi
  477. # ============= fasi/System ==============
  478. if test -f 'fasi/System' -a X"$1" != X"-c"; then
  479.     echo 'x - skipping fasi/System (File already exists)'
  480.     rm -f _shar_wnt_.tmp
  481. else
  482. > _shar_wnt_.tmp
  483. echo 'x - extracting fasi/System (Text)'
  484. sed 's/^X//' << 'SHAR_EOF' > 'fasi/System' &&
  485. Xfas    Y    1    7    1    4    3f8    3ff    0    0
  486. Xfas    Y    1    7    1    3    210    250    0    0
  487. SHAR_EOF
  488. chmod 0644 fasi/System ||
  489. echo 'restore of fasi/System failed'
  490. Wc_c="`wc -c < 'fasi/System'`"
  491. test 52 -eq "$Wc_c" ||
  492.     echo 'fasi/System: original size 52, current size' "$Wc_c"
  493. rm -f _shar_wnt_.tmp
  494. fi
  495. # ============= fasi/digi-pc8.h ==============
  496. if test -f 'fasi/digi-pc8.h' -a X"$1" != X"-c"; then
  497.     echo 'x - skipping fasi/digi-pc8.h (File already exists)'
  498.     rm -f _shar_wnt_.tmp
  499. else
  500. > _shar_wnt_.tmp
  501. echo 'x - extracting fasi/digi-pc8.h (Text)'
  502. sed 's/^X//' << 'SHAR_EOF' > 'fasi/digi-pc8.h' &&
  503. X/*+-------------------------------------------------------------------------
  504. X    digi-pc8.h - Digiboard PC-8 with SCO COM2 addressing conventions
  505. X    wht@n4hgf.Mt-Park.GA.US
  506. X--------------------------------------------------------------------------*/
  507. X/*+:EDITS:*/
  508. X/*:09-10-1992-13:59-wht@n4hgf-ECU release 3.20 */
  509. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  510. X/*:07-25-1991-12:57-wht@n4hgf-ECU release 3.10 */
  511. X/*:12-24-1991-03:23-wht@n4hgf-creation */
  512. X
  513. X#define COM21    0x210        /* digi board */
  514. X#define COM22    0x218
  515. X#define COM23    0x220
  516. X#define COM24    0x228
  517. X#define COM25    0x230
  518. X#define COM26    0x238
  519. X#define COM27    0x240
  520. X#define COM28    0x248
  521. X#define COM2S    0x250
  522. X
  523. X/* vi: set tabstop=4 shiftwidth=4: */
  524. X/* end of digi-pc8.h */
  525. SHAR_EOF
  526. chmod 0644 fasi/digi-pc8.h ||
  527. echo 'restore of fasi/digi-pc8.h failed'
  528. Wc_c="`wc -c < 'fasi/digi-pc8.h'`"
  529. test 717 -eq "$Wc_c" ||
  530.     echo 'fasi/digi-pc8.h: original size 717, current size' "$Wc_c"
  531. rm -f _shar_wnt_.tmp
  532. fi
  533. # ============= fasi/fas.c ==============
  534. if test -f 'fasi/fas.c' -a X"$1" != X"-c"; then
  535.     echo 'x - skipping fasi/fas.c (File already exists)'
  536.     rm -f _shar_wnt_.tmp
  537. else
  538. > _shar_wnt_.tmp
  539. echo 'x - extracting fasi/fas.c (Text)'
  540. sed 's/^X//' << 'SHAR_EOF' > 'fasi/fas.c' &&
  541. X/* FAS Final Async Solution driver for 286/386 versions of system V UNIX */
  542. X
  543. X/* FAS was developed by
  544. XUwe Doering             INET : gemini@geminix.in-berlin.de
  545. XBillstedter Pfad 17 b   UUCP : ...!unido!fub!geminix.in-berlin.de!gemini
  546. X1000 Berlin 20
  547. XGermany
  548. X*/
  549. X/*+:EDITS:*/
  550. X/*:09-10-1992-13:59-wht@n4hgf-ECU release 3.20 */
  551. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  552. X/*:07-25-1991-12:57-wht@n4hgf-ECU release 3.10 */
  553. X/*:06-04-1991-19:41-wht@n4hgf-add FASIC_SIP_CHANGE */
  554. X/*:02-05-1991-12:13-wht@n4hgf-apply 2.08b2->2.08.0 diffs */
  555. X/*:01-20-1991-05:01-wht@n4hgf-changed buffer sizes */
  556. X
  557. X#if defined(FASI)
  558. Xchar *fasi_driver_ident = "FAS/i 2.08.01";
  559. X#endif /* FASI */
  560. X
  561. X#if !defined (M_I286) && !defined(__STDC__)
  562. X#ident    "@(#)fas.c    2.08"
  563. X#endif
  564. X
  565. X/* Note: This source code was quite heavily optimized for speed. You
  566. X         may wonder that register variables aren't used everywhere.
  567. X         This is because there is an overhead in memory accesses
  568. X         when using register variables. As you may know data accesses
  569. X         usually need much more wait states on the memory bus than
  570. X         code accesses (because of page or cache misses). Therefor,
  571. X         saving some data accesses has higher priority than saving
  572. X         code accesses.
  573. X
  574. X         You may also note some not very elegant constructions that
  575. X         may be intentional because they are faster. If you want to
  576. X         make style improvements you should check the assembler output
  577. X         whether this wouldn't slow things down.
  578. X
  579. X         Decisions for speed optimization were based on assembler
  580. X         listings produced by the standard UNIX V 3.X/386 C compiler.
  581. X*/
  582. X
  583. X#include <sys/param.h>
  584. X#include <sys/types.h>
  585. X#include <sys/signal.h>
  586. X#include <sys/buf.h>
  587. X#include <sys/dir.h>
  588. X#if defined (XENIX)
  589. X#include <sys/page.h>
  590. X#include <sys/seg.h>
  591. X#endif
  592. X#include <sys/user.h>
  593. X#include <sys/errno.h>
  594. X#include <sys/tty.h>
  595. X#include <sys/conf.h>
  596. X#include <sys/sysinfo.h>
  597. X#include <sys/file.h>
  598. X#if !defined (XENIX) && !defined(CBAUD)
  599. X#include <sys/termio.h>
  600. X#endif
  601. X#include <sys/ioctl.h>
  602. X#if !defined(FASI)
  603. X#include <macros.h>
  604. X#endif
  605. X#if defined (HAVE_VPIX)
  606. X#if !defined (XENIX)
  607. X#include <sys/tss.h>
  608. X#include <sys/immu.h>
  609. X#include <sys/region.h>
  610. X#endif
  611. X#include <sys/proc.h>
  612. X#include <sys/v86.h>
  613. X#endif
  614. X
  615. X#if defined (XENIX)
  616. X#include "fas.h"
  617. X#else
  618. X#include <local/fas.h>
  619. X#if !defined (NO_ASM)
  620. X#include <sys/inline.h>
  621. X#endif
  622. X#endif
  623. X
  624. X#if defined (SCO) || defined (XENIX)
  625. X#define asyputchar sioputchar
  626. X#define asygetchar siogetchar
  627. X#endif
  628. X
  629. X#if defined (XENIX) || defined (NO_ASM)
  630. X#define intr_disable()    old_level = SPLINT ()
  631. X#define intr_restore()    (void) splx (old_level)
  632. X#define REGVAR
  633. X#else
  634. X/* This is a terrible ugly kludge to speed up the `inb' and `outb'
  635. X   functions. I.e., originally, the `outb' inline function had an
  636. X   overhead of four data memory accesses for parameter passing. This
  637. X   parameter passing actually consumed more clock cycles than the
  638. X   assembler `outb' command itself. Although this solution can't
  639. X   prevent unnessessary register moves it limits them at least to
  640. X   register to register moves that are much faster. You need a
  641. X   line like the following in the declaration part of every
  642. X   function that uses `inb' or `outb' calls:
  643. X
  644. X    REGVAR;
  645. X
  646. X   This hack should work with every compiler that knows about the
  647. X   UNIX V 3.X/386 standard compiler's inline assembler directives.
  648. X*/
  649. X
  650. Xasm    void loadal (val)
  651. X{
  652. X%reg    val;
  653. X    movl    val,%eax
  654. X%mem    val;
  655. X    movb    val,%al
  656. X}
  657. X
  658. Xasm    void loaddx (val)
  659. X{
  660. X%reg    val;
  661. X    movl    val,%edx
  662. X%mem    val;
  663. X    movw    val,%dx
  664. X}
  665. X
  666. Xasm    int outbyte ()
  667. X{
  668. X    outb    (%dx)
  669. X}
  670. X
  671. Xasm    int inbyte ()
  672. X{
  673. X    xorl    %eax,%eax
  674. X    inb    (%dx)
  675. X}
  676. X
  677. X/* The port parameter of the `outb' macro must be one of the predefined
  678. X   port macros from `fas.h' or a simple uint variable (no indirection
  679. X   is allowed). Additionally, `fip' must be a register variable in the
  680. X   functions where `outb' is used. This prevents the destruction of the
  681. X   `eax' CPU register while loading the `edx' register with the port
  682. X   address. This is highly compiler implementation specific.
  683. X*/
  684. X#define outb(port,val) (regvar = (val), loadal (regvar), regvar = (port), loaddx (regvar), outbyte ())
  685. X
  686. X#define inb(port) (regvar = (port), loaddx (regvar), inbyte ())
  687. X
  688. X#define REGVAR register uint    regvar
  689. X
  690. X/* This function inserts the address optimization assembler pseudo-op
  691. X   wherever called.
  692. X*/
  693. X
  694. Xasm    void optim ()
  695. X{
  696. X    .optim
  697. X}
  698. X
  699. X/* This dummy function has nothing to do but to call optim so that
  700. X   the `.optim' assembler pseudo-op will be included in the assembler
  701. X   file. This must be the first of all functions.
  702. X*/
  703. X
  704. X#if defined (OPTIM)    /* Define for uPort, ISC doesn't know about */
  705. Xstatic void        /* `.optim', but has turned on optimization by */
  706. Xdummy ()        /* default, so we don't need it there anyway. */
  707. X{
  708. X    optim ();
  709. X}
  710. X#endif
  711. X#endif    /* XENIX || NO_ASM */
  712. X
  713. X/* functions provided by this driver */
  714. Xint        fasinit ();
  715. Xint        fasopen ();
  716. Xint        fasclose ();
  717. Xint        fasread ();
  718. Xint        faswrite ();
  719. Xint        fasioctl ();
  720. Xint        fasintr ();
  721. X#if defined (NEED_PUT_GETCHAR)
  722. Xint        asyputchar ();
  723. Xint        asygetchar ();
  724. X#endif
  725. X#if defined (NEED_INIT8250)
  726. Xint        init8250 ();
  727. X#endif
  728. Xstatic int    fas_proc ();
  729. Xstatic void    fas_param ();
  730. Xstatic void    fas_fproc ();
  731. Xstatic void    fas_mproc ();
  732. Xstatic uint    fas_rproc ();
  733. Xstatic void    fas_xproc ();
  734. Xstatic void    fas_event ();
  735. X#if defined (HAVE_VPIX)
  736. Xstatic int    fas_vpix_sr ();
  737. X#endif
  738. Xstatic void    fas_rxfer ();
  739. Xstatic void    fas_xxfer ();
  740. Xstatic void    fas_ihlw_check ();
  741. Xstatic void    fas_hdx_check ();
  742. Xstatic void    fas_hangup ();
  743. Xstatic void    fas_timeout ();
  744. Xstatic void    fas_cmd ();
  745. Xstatic void    fas_open_device ();
  746. Xstatic void    fas_close_device ();
  747. Xstatic uint    fas_make_ctl_val ();
  748. Xstatic int    fas_test_device ();
  749. X
  750. X/* external functions used by this driver */
  751. Xextern int    ttinit ();
  752. Xextern int    ttiocom ();
  753. Xextern int    ttyflush ();
  754. Xextern int    SPLINT ();
  755. Xextern int    SPLWRK ();
  756. Xextern int    splx ();
  757. Xextern int    sleep ();
  758. Xextern int    wakeup ();
  759. Xextern void    longjmp ();
  760. Xextern int    signal ();
  761. Xextern int    timeout ();
  762. Xextern int    untimeout ();
  763. Xextern int    printf ();
  764. X#if defined (SCO) || defined (XENIX)
  765. Xextern int    printcfg ();
  766. X#endif
  767. X#if defined (HAVE_VPIX)
  768. Xextern int    fubyte ();
  769. Xextern int    subyte ();
  770. Xextern int    v86setint ();
  771. X#endif
  772. X#if defined (XENIX)
  773. Xextern int    inb ();
  774. Xextern int    outb ();
  775. X#endif
  776. X
  777. X/* external data objects used by this driver */
  778. Xextern int    tthiwat [];
  779. X
  780. X/* the following stuff is defined in space.c */
  781. Xextern uint    fas_physical_units;
  782. Xextern ulong    fas_port [];
  783. Xextern uint    fas_vec [];
  784. Xextern uint    fas_init_seq [];
  785. Xextern uint    fas_mcb [];
  786. Xextern ulong    fas_modem [];
  787. Xextern ulong    fas_flow [];
  788. Xextern uint    fas_ctl_port [];
  789. Xextern uint    fas_ctl_val [];
  790. Xextern uint    fas_int_ack_port [];
  791. Xextern uint    fas_int_ack [];
  792. Xextern struct fas_info    fas_info [];
  793. Xextern struct tty    fas_tty [];
  794. Xextern struct fas_info    *fas_info_ptr [];
  795. Xextern struct tty    *fas_tty_ptr [];
  796. X/* end of space.c references */
  797. X
  798. X#if defined(FASI)
  799. Xint fasiintr_entries = 0;
  800. Xextern char *fasi_space_ident;
  801. X#endif /* FASI */
  802. X
  803. X/* fas_is_initted
  804. X   Flag to indicate that we have been thru init.
  805. X   This is realy only necessary for systems that use asyputchar
  806. X   and asygetchar but it doesn't hurt to have it anyway.
  807. X*/
  808. Xstatic int    fas_is_initted = FALSE;
  809. X
  810. X/* event_scheduled
  811. X   Flag to indicate that the event handler has been scheduled
  812. X   via the timeout() function.
  813. X*/
  814. Xstatic int    event_scheduled = FALSE;
  815. X
  816. X/* array of pointers to the first fas_info structure for each
  817. X   interrupt vector
  818. X*/
  819. Xstatic struct fas_info    *fas_first_int_user [NUM_INT_VECTORS];
  820. X
  821. X/* the values for the various baud rates */
  822. Xstatic uint    fas_speeds [CBAUD + 1] =
  823. X{    1,            BAUD_BASE/50,
  824. X    BAUD_BASE/75,        BAUD_BASE/110,
  825. X    (2*BAUD_BASE+134)/269,    BAUD_BASE/150,
  826. X    BAUD_BASE/200,        BAUD_BASE/300,
  827. X    BAUD_BASE/600,        BAUD_BASE/1200,
  828. X    BAUD_BASE/1800,        BAUD_BASE/2400,
  829. X    BAUD_BASE/4800,        BAUD_BASE/9600,
  830. X    BAUD_BASE/19200,    BAUD_BASE/38400
  831. X};
  832. X
  833. X/* time for one character to completely leave the transmitter shift register */
  834. Xstatic uint    fas_ctimes [CBAUD + 1] =
  835. X{    1,        HZ*15/50+2,
  836. X    HZ*15/75+2,    HZ*15/110+2,
  837. X    HZ*30/269+2,    HZ*15/150+2,
  838. X    HZ*15/200+2,    HZ*15/300+2,
  839. X    HZ*15/600+2,    HZ*15/1200+2,
  840. X    HZ*15/1800+2,    HZ*15/2400+2,
  841. X    HZ*15/4800+2,    HZ*15/9600+2,
  842. X    HZ*15/19200+2,    HZ*15/38400+2
  843. X};
  844. X
  845. X/* dynamically adapt xmit buffer size to baud rate to prevent long buffer
  846. X   drains at low speeds
  847. X   These values are checked against boundaries and will be modified if
  848. X   necessary before use. Checking is done in fas_param (). Drain time
  849. X   is about 5 seconds with continuous character flow.
  850. X*/
  851. Xstatic uint    fas_xbuf_size [CBAUD + 1] =
  852. X{    1,        50/2,
  853. X    75/2,        110/2,
  854. X    269/4,        150/2,
  855. X    200/2,        300/2,
  856. X    600/2,        1200/2,
  857. X    1800/2,        2400/2,
  858. X    4800/2,        9600/2,
  859. X    19200/2,    38400/2
  860. X};
  861. X
  862. X/* lookup table for minor device number -> open mode flags translation */
  863. Xstatic uint    fas_open_modes [16] =
  864. X{
  865. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL,
  866. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HWO_HANDSHAKE
  867. X                            | OS_HWI_HANDSHAKE,
  868. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HWO_HANDSHAKE,
  869. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HWO_HANDSHAKE
  870. X                            | OS_HDX_HANDSHAKE,
  871. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON,
  872. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HWO_HANDSHAKE
  873. X                        | OS_HWI_HANDSHAKE,
  874. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HWO_HANDSHAKE,
  875. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HWO_HANDSHAKE
  876. X                        | OS_HDX_HANDSHAKE,
  877. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT,
  878. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HWO_HANDSHAKE
  879. X                            | OS_HWI_HANDSHAKE,
  880. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HWO_HANDSHAKE,
  881. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HWO_HANDSHAKE
  882. X                            | OS_HDX_HANDSHAKE,
  883. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN,
  884. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
  885. X                        | OS_HWI_HANDSHAKE,
  886. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE,
  887. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
  888. X                        | OS_HDX_HANDSHAKE
  889. X};
  890. X
  891. X/* The following defines are used to access multiplexed ports. */
  892. X#define GET_PORT(port,num) \
  893. X    ((fip->device_flags.i & DF_CTL_EVERY)\
  894. X            ? (port)\
  895. X            : (port) + (num))
  896. X
  897. X#define fas_first_ctl(fip,port) \
  898. X    ((void) (((fip)->device_flags.i & DF_CTL_FIRST)\
  899. X            ? outb (CTL_PORT, (port).p.ctl)\
  900. X            : 0))
  901. X
  902. X#define fas_ctl(fip,port) \
  903. X    ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
  904. X            ? outb (CTL_PORT, (port).p.ctl)\
  905. X            : 0))
  906. X
  907. X#define fas_first_outb(fip,port,val) \
  908. X    ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
  909. X            ? outb (CTL_PORT, (port).p.ctl)\
  910. X            : 0),\
  911. X        (void) outb ((port).addr, (val)))
  912. X
  913. X#define fas_outb(fip,port,val) \
  914. X    ((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
  915. X            ? outb (CTL_PORT, (port).p.ctl)\
  916. X            : 0),\
  917. X        (void) outb ((port).addr, (val)))
  918. X
  919. X#define fas_first_inb(fip,port) \
  920. X    ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
  921. X            ? outb (CTL_PORT, (port).p.ctl)\
  922. X            : 0),\
  923. X        inb ((port).addr))
  924. X
  925. X#define fas_inb(fip,port) \
  926. X    ((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
  927. X            ? outb (CTL_PORT, (port).p.ctl)\
  928. X            : 0),\
  929. X        inb ((port).addr))
  930. X
  931. X/* The following defines are used to take apart the minor device numbers. */
  932. X#define GET_UNIT(dev)        ((dev) & 0x0f)
  933. X#define GET_OPEN_MODE(dev)    (fas_open_modes [((dev) >> 4) & 0x0f])
  934. X
  935. X/* lock device against concurrent use */
  936. X#define get_device_lock(fip,prio) \
  937. X{\
  938. X    /* sleep while device is used by an other process */\
  939. X    while ((fip)->device_flags.i & DF_DEVICE_LOCKED)\
  940. X        (void) sleep ((caddr_t) &(fip)->device_flags.i, (prio));\
  941. X    (fip)->device_flags.s |= DF_DEVICE_LOCKED;\
  942. X}
  943. X
  944. X/* release device */
  945. X#define release_device_lock(fip) \
  946. X{\
  947. X    (fip)->device_flags.s &= ~DF_DEVICE_LOCKED;\
  948. X    /* wakeup the process that may wait for this device */\
  949. X    (void) wakeup ((caddr_t) &(fip)->device_flags.i);\
  950. X}
  951. X
  952. X/* schedule event */
  953. X#define event_sched(fip,event) \
  954. X{\
  955. X    (fip)->event_flags.s |= (event);\
  956. X    if (!event_scheduled)\
  957. X    {\
  958. X        event_scheduled = TRUE;\
  959. X        (void) timeout (fas_event, (void *) NULL,\
  960. X                (EVENT_TIME) * (HZ) / 1000);\
  961. X    }\
  962. X}
  963. X
  964. X/* fasinit
  965. X   This routine checks for the presense of the devices in the fas_port
  966. X   array and if the device is present tests and initializes it.
  967. X   During the initialization if the device is determined to be an
  968. X   NS16550A chip the DF_DEVICE_IS_NS16550A flag is set and the FIFOs will
  969. X   be used. If the device is an i82510 chip the DF_DEVICE_IS_I82510 flag
  970. X   is set and the device will be handled accordingly.
  971. X*/
  972. X
  973. Xint
  974. Xfasinit ()
  975. X{
  976. X    register struct fas_info    *fip;
  977. X    register uint    unit;
  978. X    uint    logical_units, port, *seq_ptr;
  979. X    char    port_stat [MAX_UNITS + 1];
  980. X    REGVAR;
  981. X
  982. X    if (fas_is_initted)
  983. X        return (0);
  984. X
  985. X    fas_is_initted = TRUE;
  986. X
  987. X    /* execute the init sequence for the serial card */
  988. X    for (seq_ptr = fas_init_seq; *seq_ptr; seq_ptr++)
  989. X    {
  990. X        port = *seq_ptr;
  991. X        seq_ptr++;
  992. X        if (*seq_ptr & READ_PORT)
  993. X            (void) inb (port);
  994. X        else
  995. X            (void) outb (port, *seq_ptr);
  996. X    }
  997. X
  998. X    /* setup the list of pointers to the tty structures */
  999. X    for (unit = 0, logical_units = fas_physical_units * 2;
  1000. X        unit < logical_units; unit++)
  1001. X        fas_tty_ptr [unit] = &fas_tty [unit];
  1002. X
  1003. X    /* setup and initialize all serial ports */
  1004. X    for (unit = 0; unit < fas_physical_units; unit++)
  1005. X    {
  1006. X        fas_info_ptr [unit] = fip = &fas_info [unit];
  1007. X        port_stat [unit] = '-';
  1008. X        if (port = (uint) ((ushort) (fas_port [unit])))
  1009. X        {
  1010. X            /* check the int vector */
  1011. X            if (fas_vec [unit] >= NUM_INT_VECTORS)
  1012. X            {
  1013. X                port_stat [unit] = '>';
  1014. X                continue;
  1015. X            }
  1016. X
  1017. X            /* init all of its ports */
  1018. X            if (fas_ctl_port [unit])
  1019. X            {
  1020. X                fip->ctl_port = fas_ctl_port [unit];
  1021. X
  1022. X                if (fas_ctl_val [unit] & 0xff00)
  1023. X                    fip->device_flags.s |= DF_CTL_EVERY;
  1024. X                else
  1025. X                    fip->device_flags.s |= DF_CTL_FIRST;
  1026. X            }
  1027. X
  1028. X            fip->port_0.p.addr = GET_PORT (port, 0);
  1029. X            fip->port_1.p.addr = GET_PORT (port, 1);
  1030. X            fip->port_2.p.addr = GET_PORT (port, 2);
  1031. X            fip->port_3.p.addr = GET_PORT (port, 3);
  1032. X            fip->port_4.p.addr = GET_PORT (port, 4);
  1033. X            fip->port_5.p.addr = GET_PORT (port, 5);
  1034. X            fip->port_6.p.addr = GET_PORT (port, 6);
  1035. X            fip->port_0.p.ctl = fas_make_ctl_val (fip, unit, 0);
  1036. X            fip->port_1.p.ctl = fas_make_ctl_val (fip, unit, 1);
  1037. X            fip->port_2.p.ctl = fas_make_ctl_val (fip, unit, 2);
  1038. X            fip->port_3.p.ctl = fas_make_ctl_val (fip, unit, 3);
  1039. X            fip->port_4.p.ctl = fas_make_ctl_val (fip, unit, 4);
  1040. X            fip->port_5.p.ctl = fas_make_ctl_val (fip, unit, 5);
  1041. X            fip->port_6.p.ctl = fas_make_ctl_val (fip, unit, 6);
  1042. X            fip->vec = fas_vec [unit];
  1043. X            fip->modem.l = fas_modem [unit];
  1044. X            fip->flow.l = fas_flow [unit];
  1045. X
  1046. X            /* mask off invalid bits */
  1047. X            fip->modem.m.di &= MC_ANY_CONTROL;
  1048. X            fip->modem.m.eo &= MC_ANY_CONTROL;
  1049. X            fip->modem.m.ei &= MC_ANY_CONTROL;
  1050. X            fip->modem.m.ca &= MS_ANY_PRESENT;
  1051. X            fip->flow.m.ic &= MC_ANY_CONTROL;
  1052. X            fip->flow.m.oc &= MS_ANY_PRESENT;
  1053. X            fip->flow.m.oe &= MS_ANY_PRESENT;
  1054. X            fip->flow.m.hc &= MC_ANY_CONTROL;
  1055. X
  1056. X            fip->recv_ring_put_ptr = fip->recv_buffer;
  1057. X            fip->recv_ring_take_ptr = fip->recv_buffer;
  1058. X            fip->xmit_ring_put_ptr = fip->xmit_buffer;
  1059. X            fip->xmit_ring_take_ptr = fip->xmit_buffer;
  1060. X            fip->xmit_fifo_size = 1;
  1061. X
  1062. X            fip->ier = IE_NONE;    /* disable all ints */
  1063. X            fas_first_outb (fip, INT_ENABLE_PORT, fip->ier);
  1064. X
  1065. X            /* is there a serial chip ? */
  1066. X            if (fas_inb (fip, INT_ENABLE_PORT) != fip->ier)
  1067. X            {
  1068. X                port_stat [unit] = '?';
  1069. X                continue;    /* a hardware error */
  1070. X            }
  1071. X
  1072. X            /* test the chip thoroughly */
  1073. X            if ((port_stat [unit] = (fas_test_device (fip) + '0'))
  1074. X                != '0')
  1075. X            {
  1076. X                continue;    /* a hardware error */
  1077. X            }
  1078. X
  1079. X            fip->lcr = 0;
  1080. X            fas_outb (fip, LINE_CTL_PORT, fip->lcr);
  1081. X            fip->mcr = fas_mcb [unit] | fip->modem.m.di;
  1082. X            fas_outb (fip, MDM_CTL_PORT, fip->mcr);
  1083. X
  1084. X            port_stat [unit] = '*';
  1085. X
  1086. X            /* let's see if it's an NS16550A */
  1087. X            fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_INIT_CMD);
  1088. X            if (!(~fas_inb (fip, INT_ID_PORT) & II_NS_FIFO_ENABLED))
  1089. X            {
  1090. X                fip->device_flags.s |= DF_DEVICE_IS_NS16550A;
  1091. X                fip->xmit_fifo_size = OUTPUT_NS_FIFO_SIZE;
  1092. X                port_stat [unit] = 'F';
  1093. X                fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
  1094. X            }
  1095. X            else
  1096. X            {
  1097. X                fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
  1098. X                /* or is it an i82510 ? */
  1099. X                fas_outb (fip, I_BANK_PORT, I_BANK_2);
  1100. X                if (!(~fas_inb (fip, I_BANK_PORT) & I_BANK_2))
  1101. X                {
  1102. X                    fip->device_flags.s |= DF_DEVICE_IS_I82510;
  1103. X                    fip->xmit_fifo_size = OUTPUT_I_FIFO_SIZE;
  1104. X                    port_stat [unit] = 'f';
  1105. X                    fas_outb (fip, I_BANK_PORT, I_BANK_1);
  1106. X                    fas_outb (fip, I_TCM_PORT, I_FIFO_CLR_XMIT);
  1107. X                    fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
  1108. X                }
  1109. X                fas_outb (fip, I_BANK_PORT, I_BANK_0);
  1110. X            }
  1111. X
  1112. X            /* disable FIFOs if requested in space.c */
  1113. X            if ((fas_port [unit] & NO_FIFO) && (fip->device_flags.i
  1114. X                        & (DF_DEVICE_IS_NS16550A
  1115. X                            | DF_DEVICE_IS_I82510)))
  1116. X            {
  1117. X                fip->device_flags.s &= ~(DF_DEVICE_IS_NS16550A
  1118. X                            | DF_DEVICE_IS_I82510);
  1119. X                fip->xmit_fifo_size = 1;
  1120. X                port_stat [unit] = '+';
  1121. X            }
  1122. X
  1123. X            /* clear potential interrupts */
  1124. X            (void) fas_inb (fip, MDM_STATUS_PORT);
  1125. X            (void) fas_inb (fip, RCV_DATA_PORT);
  1126. X            (void) fas_inb (fip, RCV_DATA_PORT);
  1127. X            (void) fas_inb (fip, LINE_STATUS_PORT);
  1128. X            (void) fas_inb (fip, INT_ID_PORT);
  1129. X            if (port = fas_int_ack_port [fip->vec])
  1130. X                (void) outb (port, fas_int_ack [fip->vec]);
  1131. X
  1132. X            /* show that it is present and configured */
  1133. X            fip->device_flags.s |= DF_DEVICE_CONFIGURED;
  1134. X        }
  1135. X    }
  1136. X
  1137. X#if defined (NEED_PUT_GETCHAR)
  1138. X    fip = &fas_info [0];
  1139. X    fip->mcr &= ~fip->modem.m.di;
  1140. X    fip->mcr |= INITIAL_MDM_CONTROL;
  1141. X    fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1142. X
  1143. X    fip->lcr = INITIAL_LINE_CONTROL;
  1144. X    fas_outb (fip, LINE_CTL_PORT, fip->lcr | LC_ENABLE_DIVISOR);
  1145. X    fas_outb (fip, DIVISOR_LSB_PORT, INITIAL_BAUD_RATE);
  1146. X    fas_outb (fip, DIVISOR_MSB_PORT, (INITIAL_BAUD_RATE) >> 8);
  1147. X    fas_outb (fip, LINE_CTL_PORT, fip->lcr);
  1148. X#endif
  1149. X
  1150. X#if defined (SCO) || defined (XENIX)
  1151. X    for (unit = 0; unit < fas_physical_units; unit++)
  1152. X        (void) printcfg ("fas", (uint) ((ushort) (fas_port [unit])), 7,
  1153. X                    fas_vec [unit], -1,
  1154. X#if defined (FASI)
  1155. X                    "unit=%d type=%c FAS/i 2.08.01",
  1156. X#else
  1157. X                    "unit=%d type=%c release=2.08.0",
  1158. X#endif /* FASI */
  1159. X                    unit, port_stat [unit]);
  1160. X#else
  1161. X    port_stat [unit] = '\0';
  1162. X    (void) printf ("\nFAS 2.08.0 async driver: Unit 0-%d init state is [%s]\n\n",
  1163. X            unit - 1,
  1164. X            port_stat);
  1165. X#endif
  1166. X    return (0);
  1167. X}
  1168. X
  1169. X/* Open a tty line. This function is called for every open, as opposed
  1170. X   to the fasclose function which is called only with the last close.
  1171. X*/
  1172. Xint
  1173. Xfasopen (dev, flag)
  1174. Xint    dev;
  1175. Xint    flag;
  1176. X{
  1177. X    register struct fas_info    *fip;
  1178. X    register struct tty        *ttyp;
  1179. X    register uint    open_mode;
  1180. X    uint    physical_unit;
  1181. X    int    old_level;
  1182. X
  1183. X    physical_unit = GET_UNIT (dev);
  1184. X
  1185. X    /* check for valid port number */
  1186. X    if (physical_unit >= fas_physical_units)
  1187. X    {
  1188. X        u.u_error = ENXIO;
  1189. X        return (-1);
  1190. X    }
  1191. X
  1192. X    fip = fas_info_ptr [physical_unit];
  1193. X
  1194. X    /* was the port present at init time ? */
  1195. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  1196. X    {
  1197. X        u.u_error = ENXIO;
  1198. X        return (-1);
  1199. X    }
  1200. X
  1201. X    open_mode = GET_OPEN_MODE (dev);
  1202. X
  1203. X    old_level = SPLINT ();
  1204. X    get_device_lock (fip, TTIPRI);
  1205. X
  1206. X    /* If this is a getty open, the device is already open for
  1207. X           dialout and the FNDELAY flag is not set, wait until device
  1208. X           is closed.
  1209. X    */
  1210. X    while ((open_mode & OS_OPEN_FOR_GETTY)
  1211. X            && (fip->o_state & OS_OPEN_FOR_DIALOUT)
  1212. X            && !(flag & FNDELAY))
  1213. X    {
  1214. X        release_device_lock (fip);
  1215. X        (void) sleep ((caddr_t) &fip->o_state, TTIPRI);
  1216. X        get_device_lock (fip, TTIPRI);
  1217. X    }
  1218. X    
  1219. X    /* If the device is already open and another open uses a different
  1220. X       open mode or if a getty open waits for carrier and doesn't allow
  1221. X       parallel dialout opens, return with EBUSY error.
  1222. X    */
  1223. X    if ((fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
  1224. X                ? (OS_OPEN_STATES | OS_WAIT_OPEN)
  1225. X                : (OS_OPEN_STATES | OS_NO_DIALOUT)))
  1226. X        && ((flag & FEXCL)
  1227. X            || ((open_mode ^ fip->o_state) & (u.u_uid
  1228. X                        ? OS_TEST_MASK
  1229. X                        : OS_SU_TEST_MASK))))
  1230. X    {
  1231. X        u.u_error = EBUSY;
  1232. X        release_device_lock (fip);
  1233. X        (void) splx (old_level);
  1234. X        return (-1);
  1235. X    }
  1236. X
  1237. X    /* disable subsequent opens */
  1238. X    if (flag & FEXCL)
  1239. X        open_mode |= OS_EXCLUSIVE_OPEN_1;
  1240. X
  1241. X    /* set up pointer to tty structure */
  1242. X    ttyp = (open_mode & OS_OPEN_FOR_GETTY)
  1243. X        ? fas_tty_ptr [physical_unit + fas_physical_units]
  1244. X        : fas_tty_ptr [physical_unit];
  1245. X
  1246. X    /* things to do on first open only */
  1247. X    if (!(fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
  1248. X                ? (OS_OPEN_STATES | OS_WAIT_OPEN)
  1249. X                : OS_OPEN_STATES)))
  1250. X    {
  1251. X        /* init data structures */
  1252. X        fip->tty = ttyp;
  1253. X        (void) ttinit (ttyp);
  1254. X        ttyp->t_proc = fas_proc;
  1255. X        fip->po_state = fip->o_state;
  1256. X        fip->o_state = open_mode & ~OS_OPEN_STATES;
  1257. X#if defined (HAVE_VPIX)
  1258. X        /* initialize VP/ix related variables */
  1259. X        fip->v86_proc = (v86_t *) NULL;
  1260. X        fip->v86_intmask = 0;
  1261. X        fip->v86_ss.ss_start = CSTART;
  1262. X        fip->v86_ss.ss_stop = CSTOP;
  1263. X#endif
  1264. X        fas_open_device (fip);        /* open physical device */
  1265. X        fas_param (fip, HARD_INIT);    /* set up port registers */
  1266. X
  1267. X        /* allow pending tty interrupts */
  1268. X        (void) SPLWRK ();
  1269. X        (void) SPLINT ();
  1270. X    }
  1271. X
  1272. X    /* If getty open and the FNDELAY flag is not set,
  1273. X       block and wait for carrier if device not yet open.
  1274. X    */
  1275. X    if ((open_mode & OS_OPEN_FOR_GETTY) && !(flag & FNDELAY))
  1276. X    {
  1277. X        /* sleep while open for dialout or no carrier */
  1278. X        while ((fip->o_state & OS_OPEN_FOR_DIALOUT)
  1279. X            || !(ttyp->t_state & (ISOPEN | CARR_ON)))
  1280. X        {
  1281. X            ttyp->t_state |= WOPEN;
  1282. X            release_device_lock (fip);
  1283. X            (void) sleep ((caddr_t) &ttyp->t_canq, TTIPRI);
  1284. X            get_device_lock (fip, TTIPRI);
  1285. X        }
  1286. X        ttyp->t_state &= ~WOPEN;
  1287. X    }
  1288. X
  1289. X    /* wakeup processes that are still sleeping in getty open */
  1290. X    if (ttyp->t_state & WOPEN)
  1291. X#if defined(FASI)
  1292. X    {
  1293. X#endif
  1294. X        (void) wakeup ((caddr_t) &ttyp->t_canq);
  1295. X#if defined(FASI)
  1296. X        (void) wakeup ((caddr_t) &fip->device_flags.i);
  1297. X    }
  1298. X#endif
  1299. X
  1300. X    /* we need to flush the receiver with the first open */
  1301. X    if (!(fip->o_state & OS_OPEN_STATES))
  1302. X        fas_cmd (fip, ttyp, T_RFLUSH);
  1303. X
  1304. X    (*linesw [ttyp->t_line].l_open) (ttyp);
  1305. X
  1306. X    /* set open type flags */
  1307. X    fip->o_state = open_mode;
  1308. X
  1309. X    release_device_lock (fip);
  1310. X    (void) splx (old_level);
  1311. X    return (0);
  1312. X}
  1313. X
  1314. X/* Close a tty line. This is only called if there is no other
  1315. X   concurrent open left. A blocked getty open is not counted as
  1316. X   a concurrent open because in this state it isn't really open.
  1317. X*/
  1318. Xint
  1319. Xfasclose (dev)
  1320. Xint    dev;
  1321. X{
  1322. X    register struct fas_info    *fip;
  1323. X    register struct tty        *ttyp;
  1324. X    uint    physical_unit;
  1325. X    uint    open_mode;
  1326. X    int    old_level;
  1327. X    void    (*old_sigkill)();
  1328. X
  1329. X    physical_unit = GET_UNIT (dev);
  1330. X
  1331. X    fip = fas_info_ptr [physical_unit];
  1332. X
  1333. X    open_mode = GET_OPEN_MODE (dev);
  1334. X
  1335. X    /* set up pointer to tty structure */
  1336. X    ttyp = (open_mode & OS_OPEN_FOR_GETTY)
  1337. X        ? fas_tty_ptr [physical_unit + fas_physical_units]
  1338. X        : fas_tty_ptr [physical_unit];
  1339. X    
  1340. X    old_level = SPLINT ();
  1341. X    get_device_lock (fip, TTIPRI);
  1342. X
  1343. X    /* wait for output buffer drain only if device was open */
  1344. X    if (ttyp->t_state & ISOPEN)
  1345. X    {
  1346. X        /* flush the output buffer immediately if the device
  1347. X           has been shut down because of an error
  1348. X        */
  1349. X        if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  1350. X        {
  1351. X            (void) ttyflush (ttyp, FWRITE);
  1352. X        }
  1353. X        /* wait for buffer drain and catch interrupts */
  1354. X        while (ttyp->t_outq.c_cc || (ttyp->t_state & (BUSY | TIMEOUT)))
  1355. X        {
  1356. X            old_sigkill = u.u_signal [SIGKILL - 1];
  1357. X            /* allow kill signal if close on exit */
  1358. X            if (old_sigkill == SIG_IGN)
  1359. X                u.u_signal [SIGKILL - 1] = SIG_DFL;
  1360. X            ttyp->t_state |= TTIOW;
  1361. X            if (sleep ((caddr_t) &ttyp->t_oflag, TTOPRI | PCATCH))
  1362. X            {
  1363. X                /* caught signal */
  1364. X                ttyp->t_state &= ~TTIOW;
  1365. X                /* If close on exit, flush output buffer to
  1366. X                   allow completion of the fasclose() function.
  1367. X                   Otherwise, do the normal signal handling.
  1368. X                */
  1369. X                if (old_sigkill == SIG_IGN)
  1370. X                    (void) ttyflush (ttyp, FWRITE);
  1371. X                else
  1372. X                {
  1373. X                    release_device_lock (fip);
  1374. X                    (void) splx (old_level);
  1375. X                    longjmp (u.u_qsav);
  1376. X                }
  1377. X            }
  1378. X            if (old_sigkill == SIG_IGN)
  1379. X                u.u_signal [SIGKILL - 1] = old_sigkill;
  1380. X        }
  1381. X    }
  1382. X
  1383. X    (*linesw [ttyp->t_line].l_close) (ttyp);
  1384. X
  1385. X    /* allow pending tty interrupts */
  1386. X    (void) SPLWRK ();
  1387. X    (void) SPLINT ();
  1388. X
  1389. X    if (open_mode & OS_OPEN_FOR_GETTY)
  1390. X    {
  1391. X        /* not waiting any more */
  1392. X        ttyp->t_state &= ~WOPEN;
  1393. X        if (!(fip->o_state & OS_OPEN_FOR_DIALOUT))
  1394. X        {
  1395. X            fas_close_device (fip);
  1396. X            fip->o_state = OS_DEVICE_CLOSED;
  1397. X        }
  1398. X        else
  1399. X            fip->po_state = OS_DEVICE_CLOSED;
  1400. X    }
  1401. X    else
  1402. X    {
  1403. X        fas_close_device (fip);
  1404. X        fip->o_state = OS_DEVICE_CLOSED;
  1405. X        /* If there is a waiting getty open on
  1406. X           this port, reopen the physical device.
  1407. X        */
  1408. X        if (fip->po_state & OS_WAIT_OPEN)
  1409. X        {
  1410. X            /* get the getty version of the
  1411. X               tty structure
  1412. X            */
  1413. X            fip->tty = fas_tty_ptr [physical_unit
  1414. X                    + fas_physical_units];
  1415. X            fip->o_state = fip->po_state;
  1416. X            fip->po_state = OS_DEVICE_CLOSED;
  1417. X#if defined (HAVE_VPIX)
  1418. X            /* initialize VP/ix related variables */
  1419. X            fip->v86_proc = (v86_t *) NULL;
  1420. X            fip->v86_intmask = 0;
  1421. X            fip->v86_ss.ss_start = CSTART;
  1422. X            fip->v86_ss.ss_stop = CSTOP;
  1423. X#endif
  1424. X            if (!(fip->device_flags.i & DF_DO_HANGUP))
  1425. X            {
  1426. X                fas_open_device (fip);
  1427. X                /* set up port registers */
  1428. X                fas_param (fip, HARD_INIT);
  1429. X            }
  1430. X        }
  1431. X        (void) wakeup ((caddr_t) &fip->o_state);
  1432. X    }
  1433. X
  1434. X    if (!(fip->device_flags.i & DF_DO_HANGUP))
  1435. X        release_device_lock (fip);
  1436. X
  1437. X#if defined(FASI)
  1438. X    (void)wakeup((caddr_t)&fip->device_flags.i);
  1439. X#endif
  1440. X    (void) splx (old_level);
  1441. X    return (0);
  1442. X}
  1443. X
  1444. X/* read characters from the input buffer */
  1445. Xint
  1446. Xfasread (dev)
  1447. Xint    dev;
  1448. X{
  1449. X    register struct fas_info    *fip;
  1450. X    register struct tty    *ttyp;
  1451. X    int    old_level;
  1452. X
  1453. X    fip = fas_info_ptr [GET_UNIT (dev)];
  1454. X
  1455. X    /* was the port present at init time ? */
  1456. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  1457. X    {
  1458. X        u.u_error = ENXIO;
  1459. X        return (-1);
  1460. X    }
  1461. X
  1462. X    ttyp = fip->tty;
  1463. X
  1464. X    (*linesw [ttyp->t_line].l_read) (ttyp);
  1465. X
  1466. X    old_level = SPLINT ();
  1467. X
  1468. X    /* schedule character transfer to UNIX buffer */
  1469. X    if (fip->recv_ring_cnt
  1470. X#if defined (HAVE_VPIX)
  1471. X        && (((fip->iflag & DOSMODE)
  1472. X            ? MAX_VPIX_FILL - MIN_READ_CHUNK
  1473. X            : MAX_UNIX_FILL - MIN_READ_CHUNK)
  1474. X                >= ttyp->t_rawq.c_cc)
  1475. X#else
  1476. X        && ((MAX_UNIX_FILL - MIN_READ_CHUNK) >= ttyp->t_rawq.c_cc)
  1477. X#endif
  1478. X        && !(fip->flow_flags.i & FF_RXFER_STOPPED))
  1479. X    {
  1480. X        event_sched (fip, EF_DO_RXFER);
  1481. X    }
  1482. X
  1483. X#if defined(FASI)
  1484. X    (void)wakeup((caddr_t)&fip->device_flags.i);
  1485. X#endif
  1486. X    (void) splx (old_level);
  1487. X    return (0);
  1488. X}
  1489. X
  1490. X/* write characters to the output buffer */
  1491. Xint
  1492. Xfaswrite (dev)
  1493. Xint    dev;
  1494. X{
  1495. X    register struct fas_info    *fip;
  1496. X    register struct tty    *ttyp;
  1497. X
  1498. X    fip = fas_info_ptr [GET_UNIT (dev)];
  1499. X
  1500. X    /* was the port present at init time ? */
  1501. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  1502. X    {
  1503. X        u.u_error = ENXIO;
  1504. X        return (-1);
  1505. X    }
  1506. X
  1507. X    ttyp = fip->tty;
  1508. X
  1509. X    (*linesw [ttyp->t_line].l_write) (ttyp);
  1510. X    return (0);
  1511. X}
  1512. X
  1513. X/*+-------------------------------------------------------------------------
  1514. X    strlen(str)
  1515. X--------------------------------------------------------------------------*/
  1516. X#if defined(FASI)
  1517. Xstatic int
  1518. Xstrlen(str)
  1519. Xregister char *str;
  1520. X{
  1521. Xregister len = 0;
  1522. X    while(*str++)
  1523. X        len++;
  1524. X    return(len);
  1525. X}    /* end of strlen */
  1526. X#endif /* FASI */
  1527. X
  1528. X/* process ioctl calls */
  1529. Xint
  1530. Xfasioctl (dev, cmd, arg3, arg4)
  1531. Xint    dev;
  1532. Xint    cmd;
  1533. Xunion ioctl_arg    arg3;
  1534. Xint    arg4;
  1535. X{
  1536. X    register struct fas_info    *fip;
  1537. X    register struct tty    *ttyp;
  1538. X    int    v86_cmd, v86_data;
  1539. X    int    old_level;
  1540. X    REGVAR;
  1541. X
  1542. X    fip = fas_info_ptr [GET_UNIT (dev)];
  1543. X
  1544. X    /* was the port present at init time ? */
  1545. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  1546. X    {
  1547. X        u.u_error = ENXIO;
  1548. X        return (-1);
  1549. X    }
  1550. X
  1551. X    ttyp = fip->tty;
  1552. X
  1553. X    /* process ioctl commands */
  1554. X    switch (cmd)
  1555. X    {
  1556. X#if defined (FASI)
  1557. X        case FASIC_SIP_CHANGE:
  1558. X            (void) sleep ((caddr_t) &fip->device_flags.i, PZERO + 1);
  1559. X        case FASIC_SIP:
  1560. X            if(copyout((char *)fip,arg3.cparg,sizeof(*fip)))
  1561. X            {
  1562. X                u.u_error = EFAULT;
  1563. X                return(-1);
  1564. X            }
  1565. X            return(fasiintr_entries);
  1566. X        case FASIC_DVR_IDENT:
  1567. X            if(copyout(fasi_driver_ident,arg3.cparg,
  1568. X                strlen(fasi_driver_ident) + 1))
  1569. X            {
  1570. X                u.u_error = EFAULT;
  1571. X                return(-1);
  1572. X            }
  1573. X            break;
  1574. X        case FASIC_SPACE_IDENT:
  1575. X            if(copyout(fasi_space_ident,arg3.cparg,
  1576. X                strlen(fasi_space_ident) + 1))
  1577. X            {
  1578. X                u.u_error = EFAULT;
  1579. X                return(-1);
  1580. X            }
  1581. X            break;
  1582. X        case FASIC_MSR:
  1583. X            return((unsigned int)fip->msr);
  1584. X        case FASIC_LCR:
  1585. X            return((unsigned int)fip->lcr);
  1586. X        case FASIC_IER:
  1587. X            return((unsigned int)fip->ier);
  1588. X        case FASIC_MCR:
  1589. X            return((unsigned int)fip->mcr);
  1590. X        case FASIC_RESET_STAT:
  1591. X            old_level = SPLINT();
  1592. X            fip->characters_received = 0;
  1593. X            fip->characters_transmitted = 0;
  1594. X            fip->modem_status_events = 0;
  1595. X            fip->overrun_errors = 0;
  1596. X            fip->framing_errors = 0;
  1597. X            fip->parity_errors = 0;
  1598. X            fip->rings_detected = 0;
  1599. X            fip->breaks_detected = 0;
  1600. X            fip->xmtr_hw_flow_count = 0;
  1601. X            fip->xmtr_sw_flow_count = 0;
  1602. X            fip->rcvr_hw_flow_count = 0;
  1603. X            fip->rcvr_sw_flow_count = 0;
  1604. X            (void)splx(old_level);
  1605. X            break;
  1606. X#endif /* FASI */
  1607. X#if defined (HAVE_VPIX)
  1608. X        case AIOCINTTYPE:    /* set pseudorupt type */
  1609. X            switch (arg3.iarg)
  1610. X            {
  1611. X                case V86VI_KBD:
  1612. X                case V86VI_SERIAL0:
  1613. X                case V86VI_SERIAL1:
  1614. X                    intr_disable ();
  1615. X                    fip->v86_intmask = arg3.iarg;
  1616. X                    intr_restore ();
  1617. X                    break;
  1618. X
  1619. X                default:
  1620. X                    intr_disable ();
  1621. X                    fip->v86_intmask = V86VI_SERIAL0;
  1622. X                    intr_restore ();
  1623. X                    break;
  1624. X            }
  1625. X            break;
  1626. X
  1627. X        case AIOCDOSMODE:    /* enable dos mode */
  1628. X            if (!(fip->iflag & DOSMODE))
  1629. X            {
  1630. X                old_level = SPLINT ();
  1631. X                fip->v86_proc = u.u_procp->p_v86;
  1632. X                if (!(fip->v86_intmask))
  1633. X                    fip->v86_intmask = V86VI_SERIAL0;
  1634. X                ttyp->t_iflag |= DOSMODE;
  1635. X                if (fip->v86_intmask != V86VI_KBD)
  1636. X                    ttyp->t_cflag |= CLOCAL;
  1637. X                fas_param (fip, SOFT_INIT);
  1638. X                (void) splx (old_level);
  1639. X            }
  1640. X            u.u_r.r_reg.r_val1 = 0;
  1641. X            break;
  1642. X
  1643. X        case AIOCNONDOSMODE:    /* disable dos mode */
  1644. X            if (fip->iflag & DOSMODE)
  1645. X            {
  1646. X                old_level = SPLINT ();
  1647. X                fip->v86_proc = (v86_t *) NULL;
  1648. X                fip->v86_intmask = 0;
  1649. X                ttyp->t_iflag &= ~DOSMODE;
  1650. X                if (fip->flow_flags.i & FF_RXFER_STOPPED)
  1651. X                {
  1652. X                    fip->flow_flags.s &= ~FF_RXFER_STOPPED;
  1653. X                    /* schedule character transfer
  1654. X                       to UNIX buffer
  1655. X                    */
  1656. X                    if (fip->recv_ring_cnt)
  1657. X                        event_sched (fip, EF_DO_RXFER);
  1658. X                }
  1659. X                fip->lcr &= ~LC_SET_BREAK_LEVEL;
  1660. X                fas_param (fip, HARD_INIT);
  1661. X                (void) splx (old_level);
  1662. X            }
  1663. X            u.u_r.r_reg.r_val1 = 0;
  1664. X            break;
  1665. X
  1666. X        case AIOCSERIALOUT:    /* setup port registers for dos */
  1667. X            if ((fip->iflag & DOSMODE) && fip->v86_proc)
  1668. X            {
  1669. X                /* wait until output is done */
  1670. X                old_level = SPLINT ();
  1671. X                while (ttyp->t_outq.c_cc
  1672. X                    || (ttyp->t_state & (BUSY | TIMEOUT)))
  1673. X                {
  1674. X                    ttyp->t_state |= TTIOW;
  1675. X                    (void) sleep ((caddr_t) &ttyp->t_oflag,
  1676. X                                    TTOPRI);
  1677. X                }
  1678. X
  1679. X                /* block transmitter and wait until it is
  1680. X                   empty
  1681. X                */
  1682. X                fip->device_flags.s |= DF_XMIT_LOCKED;
  1683. X                while (fip->device_flags.i & (DF_XMIT_BUSY
  1684. X                            | DF_XMIT_BREAK
  1685. X                            | DF_GUARD_TIMEOUT))
  1686. X                    (void) sleep ((caddr_t) &fip->
  1687. X                                device_flags.i,
  1688. X                            PZERO - 1);
  1689. X                (void) splx (old_level);
  1690. X
  1691. X                /* get port write command */
  1692. X                v86_cmd = fubyte (arg3.cparg);
  1693. X                /* set divisor lsb requested */
  1694. X                if (v86_cmd & SIO_MASK(SO_DIVLLSB))
  1695. X                {
  1696. X                    v86_data = fubyte (arg3.cparg
  1697. X                                + SO_DIVLLSB);
  1698. X                    intr_disable ();
  1699. X                    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
  1700. X                            | LC_ENABLE_DIVISOR);
  1701. X                    fas_outb (fip, DIVISOR_LSB_PORT, v86_data);
  1702. X                    fas_outb (fip, LINE_CTL_PORT, fip->lcr
  1703. X                            & ~LC_ENABLE_DIVISOR);
  1704. X                    intr_restore ();
  1705. X                }
  1706. X                /* set divisor msb requested */
  1707. X                if (v86_cmd & SIO_MASK(SO_DIVLMSB))
  1708. X                {
  1709. X                    v86_data = fubyte (arg3.cparg
  1710. X                                + SO_DIVLMSB);
  1711. X                    intr_disable ();
  1712. X                    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
  1713. X                            | LC_ENABLE_DIVISOR);
  1714. X                    fas_outb (fip, DIVISOR_MSB_PORT, v86_data);
  1715. X                    fas_outb (fip, LINE_CTL_PORT, fip->lcr
  1716. X                            & ~LC_ENABLE_DIVISOR);
  1717. X                    intr_restore ();
  1718. X                }
  1719. X                /* set lcr requested */
  1720. X                if (v86_cmd & SIO_MASK(SO_LCR))
  1721. X                {
  1722. X                    v86_data = fubyte (arg3.cparg + SO_LCR);
  1723. X                    intr_disable ();
  1724. X                    fip->lcr = v86_data
  1725. X                            & ~LC_ENABLE_DIVISOR;
  1726. X                    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
  1727. X                    intr_restore ();
  1728. X                }
  1729. X                /* set mcr requested */
  1730. X                if (v86_cmd & SIO_MASK(SO_MCR))
  1731. X                {
  1732. X                    v86_data = fubyte (arg3.cparg + SO_MCR);
  1733. X                    old_level = SPLINT ();
  1734. X                    /* virtual dtr processing */
  1735. X                    if (v86_data & MC_SET_DTR)
  1736. X                    {
  1737. X                        fip->device_flags.s
  1738. X                            |= DF_MODEM_ENABLED;
  1739. X                        fip->mcr |= (fip->o_state
  1740. X                                & OS_WAIT_OPEN)
  1741. X                            ? fip->modem.m.ei
  1742. X                            : fip->modem.m.eo;
  1743. X                    }
  1744. X                    else
  1745. X                    {
  1746. X                        fip->device_flags.s
  1747. X                            &= ~DF_MODEM_ENABLED;
  1748. X                        fip->mcr &= (fip->o_state
  1749. X                                & OS_WAIT_OPEN)
  1750. X                            ? ~fip->modem.m.ei
  1751. X                            : ~fip->modem.m.eo;
  1752. X                    }
  1753. X                    /* virtual rts processing */
  1754. X                    if (fip->flow_flags.i
  1755. X                            & FF_HWI_HANDSHAKE)
  1756. X                    {
  1757. X                      if (v86_data & MC_SET_RTS)
  1758. X                      {
  1759. X                        if (fip->flow_flags.i
  1760. X                            & FF_RXFER_STOPPED)
  1761. X                        {
  1762. X                          fip->flow_flags.s
  1763. X                            &= ~FF_RXFER_STOPPED;
  1764. X                          /* schedule character transfer
  1765. X                             to UNIX buffer
  1766. X                          */
  1767. X                          if (fip->recv_ring_cnt)
  1768. X                            event_sched (fip,
  1769. X                                EF_DO_RXFER);
  1770. X                        }
  1771. X                      }
  1772. X                      else
  1773. X                        fip->flow_flags.s
  1774. X                            |= FF_RXFER_STOPPED;
  1775. X                    }
  1776. X                    else if (!(fip->flow_flags.i
  1777. X                            & FF_HDX_HANDSHAKE))
  1778. X                    {
  1779. X                        if (v86_data & MC_SET_RTS)
  1780. X                        {
  1781. X                            fip->flow_flags.s
  1782. X                              |= FF_HDX_STARTED;
  1783. X                            fip->mcr
  1784. X                              |= fip->flow.m.hc;
  1785. X                        }
  1786. X                        else
  1787. X                        {
  1788. X                            fip->flow_flags.s
  1789. X                              &= ~FF_HDX_STARTED;
  1790. X                            fip->mcr
  1791. X                              &= ~fip->flow.m.hc;
  1792. X                        }
  1793. X                    }
  1794. X                    fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1795. X                    (void) splx (old_level);
  1796. X                }
  1797. X
  1798. X                old_level = SPLINT ();
  1799. X                /* enable transmitter and restart output */
  1800. X                fip->device_flags.s &= ~DF_XMIT_LOCKED;
  1801. X                fas_xproc (fip);
  1802. X                (void) splx (old_level);
  1803. X            }
  1804. X            break;
  1805. X
  1806. X        case AIOCSERIALIN:    /* read port registers for dos */
  1807. X            if ((fip->iflag & DOSMODE) && fip->v86_proc)
  1808. X            {
  1809. X                v86_cmd = fubyte (arg3.cparg);
  1810. X                if (v86_cmd & SIO_MASK(SI_MSR))
  1811. X                {
  1812. X                    (void) subyte (arg3.cparg + SI_MSR,
  1813. X                            ((fip->flow_flags.i
  1814. X                              & FF_HWO_HANDSHAKE)
  1815. X                            ? fip->msr
  1816. X                              | fip->flow.m.oc
  1817. X                              | fip->flow.m.oe
  1818. X                            : fip->msr)
  1819. X                            & MS_ANY_PRESENT);
  1820. X                }
  1821. X            }
  1822. X            break;
  1823. X
  1824. X        case AIOCSETSS:    /* set start/stop characters */
  1825. X            intr_disable ();
  1826. X            *((short *) (&fip->v86_ss)) = arg3.iarg;
  1827. X            intr_restore ();
  1828. X            break;
  1829. X
  1830. X        case AIOCINFO:    /* show what type of device we are */
  1831. X            u.u_r.r_reg.r_val1 = ('a' << 8) | (uint) ((unchar) dev);
  1832. X            break;
  1833. X#endif
  1834. X        default:    /* default ioctl processing */
  1835. X            /* if it is a TCSETA* command, call fas_param () */
  1836. X            if (ttiocom (ttyp, cmd, arg3, arg4))
  1837. X            {
  1838. X                old_level = SPLINT ();
  1839. X                fas_param (fip, SOFT_INIT);
  1840. X                (void) splx (old_level);
  1841. X            }
  1842. X            break;
  1843. X    }
  1844. X    return (0);
  1845. X}
  1846. X
  1847. X/* pass fas commands to the fas multi-function procedure */
  1848. Xstatic int
  1849. Xfas_proc (ttyp, arg2)
  1850. Xstruct tty    *ttyp;
  1851. Xint    arg2;
  1852. X{
  1853. X    register uint    physical_unit;
  1854. X    int    old_level;
  1855. X
  1856. X    physical_unit = ttyp - &fas_tty [0];
  1857. X    if (physical_unit >= fas_physical_units)
  1858. X        physical_unit -= fas_physical_units;
  1859. X
  1860. X    old_level = SPLINT ();
  1861. X    fas_cmd (fas_info_ptr [physical_unit], ttyp, arg2);
  1862. X    (void) splx (old_level);
  1863. X    return (0);
  1864. X}
  1865. X
  1866. X/* set up a port according to the given termio structure */
  1867. Xstatic void
  1868. Xfas_param (fip, init_type)
  1869. Xregister struct    fas_info    *fip;
  1870. Xint    init_type;
  1871. X{
  1872. X    register uint    cflag;
  1873. X    uint    divisor;
  1874. X    int    xmit_ring_size;
  1875. X    REGVAR;
  1876. X
  1877. X    cflag = fip->tty->t_cflag;
  1878. X
  1879. X#if defined (HAVE_VPIX)
  1880. X    /* we don't set port registers if we are in dos mode */
  1881. X    if (fip->tty->t_iflag & DOSMODE)
  1882. X        goto setflags2;
  1883. X#endif
  1884. X    /* if soft init mode: don't set port registers if cflag didn't change */
  1885. X    if ((init_type == SOFT_INIT) && !((cflag ^ fip->cflag)
  1886. X                        & (CBAUD | CSIZE | CSTOPB
  1887. X                            | PARENB | PARODD)))
  1888. X        goto setflags;
  1889. X
  1890. X    /* lock transmitter and wait until it is empty */
  1891. X    fip->device_flags.s |= DF_XMIT_LOCKED;
  1892. X    while (fip->device_flags.i & (DF_XMIT_BUSY | DF_XMIT_BREAK
  1893. X                            | DF_GUARD_TIMEOUT))
  1894. X        (void) sleep ((caddr_t) &fip->device_flags.i, PZERO - 1);
  1895. X
  1896. X    /* hangup line if it is baud rate 0, else enable line */
  1897. X    if ((cflag & CBAUD) == B0)
  1898. X    {
  1899. X        fip->mcr &= (fip->o_state & OS_WAIT_OPEN)
  1900. X                ? ~fip->modem.m.ei
  1901. X                : ~fip->modem.m.eo;
  1902. X        fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1903. X        fip->device_flags.s &= ~DF_MODEM_ENABLED;
  1904. X    }
  1905. X    else
  1906. X    {
  1907. X        if (!(fip->device_flags.i & DF_MODEM_ENABLED))
  1908. X        {
  1909. X            fip->mcr |= (fip->o_state & OS_WAIT_OPEN)
  1910. X                    ? fip->modem.m.ei
  1911. X                    : fip->modem.m.eo;
  1912. X            fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1913. X            fip->device_flags.s |= DF_MODEM_ENABLED;
  1914. X        }
  1915. X    }
  1916. X
  1917. X    /* don't change break flag */
  1918. X    fip->lcr &= LC_SET_BREAK_LEVEL;
  1919. X
  1920. X    /* set character size */
  1921. X    switch (cflag & CSIZE)
  1922. X    {
  1923. X    case CS5:
  1924. X        fip->lcr |= LC_WORDLEN_5;
  1925. X        break;
  1926. X
  1927. X    case CS6:
  1928. X        fip->lcr |= LC_WORDLEN_6;
  1929. X        break;
  1930. X
  1931. X    case CS7:
  1932. X        fip->lcr |= LC_WORDLEN_7;
  1933. X        break;
  1934. X
  1935. X    default:
  1936. X        fip->lcr |= LC_WORDLEN_8;
  1937. X        break;
  1938. X    }
  1939. X
  1940. X    /* set # of stop bits */
  1941. X    if (cflag & CSTOPB)
  1942. X        fip->lcr |= LC_STOPBITS_LONG;
  1943. X
  1944. X    /* set parity */
  1945. X    if (cflag & PARENB)
  1946. X    {
  1947. X        fip->lcr |= LC_ENABLE_PARITY;
  1948. X
  1949. X        if (!(cflag & PARODD))
  1950. X            fip->lcr |= LC_EVEN_PARITY;
  1951. X    }
  1952. X
  1953. X    /* set divisor registers only if baud rate is valid */
  1954. X    if ((cflag & CBAUD) != B0)
  1955. X    {
  1956. X        /* get counter divisor for selected baud rate */
  1957. X        divisor = fas_speeds [cflag & CBAUD];
  1958. X        /* set LCR and baud rate */
  1959. X        fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
  1960. X                            | LC_ENABLE_DIVISOR);
  1961. X        fas_outb (fip, DIVISOR_LSB_PORT, divisor);
  1962. X        fas_outb (fip, DIVISOR_MSB_PORT, divisor >> 8);
  1963. X    }
  1964. X
  1965. X    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
  1966. X
  1967. Xsetflags:
  1968. X    /* check dynamic xmit ring buffer size against boundaries,
  1969. X       modify it if necessary and update the fas_info structure
  1970. X    */
  1971. X    if ((cflag & CBAUD) != B0)
  1972. X    {
  1973. X        xmit_ring_size = fas_xbuf_size [cflag & CBAUD]
  1974. X                    - tthiwat [cflag & CBAUD];
  1975. X        if (xmit_ring_size < MAX_OUTPUT_FIFO_SIZE * 2)
  1976. X        {
  1977. Xsetflags2:
  1978. X            xmit_ring_size = MAX_OUTPUT_FIFO_SIZE * 2;
  1979. X        }
  1980. X        if (xmit_ring_size > XMIT_BUFF_SIZE)
  1981. X            xmit_ring_size = XMIT_BUFF_SIZE;
  1982. X        fip->xmit_ring_size = xmit_ring_size;
  1983. X    }
  1984. X
  1985. X    /* setup character time for B0 mode */
  1986. X    fas_ctimes [B0] = fas_ctimes [cflag & CBAUD];
  1987. X
  1988. X    /* disable modem control signals if required by open mode */
  1989. X    if (fip->o_state & OS_CLOCAL)
  1990. X        cflag |= CLOCAL;
  1991. X
  1992. X    /* Select hardware handshake depending on the minor device
  1993. X       number and the CTSFLOW and RTSFLOW flags (if they are
  1994. X       available).
  1995. X    */
  1996. X    fip->flow_flags.s &= ~(FF_HWO_HANDSHAKE
  1997. X                | FF_HWI_HANDSHAKE
  1998. X                | FF_HDX_HANDSHAKE);
  1999. X    if (fip->o_state & (OS_HWO_HANDSHAKE | OS_HWI_HANDSHAKE
  2000. X                    | OS_HDX_HANDSHAKE))
  2001. X    {
  2002. X        if (fip->o_state & OS_HWO_HANDSHAKE)
  2003. X            fip->flow_flags.s |= FF_HWO_HANDSHAKE;
  2004. X        if (fip->o_state & OS_HWI_HANDSHAKE)
  2005. X            fip->flow_flags.s |= FF_HWI_HANDSHAKE;
  2006. X        if (fip->o_state & OS_HDX_HANDSHAKE)
  2007. X            fip->flow_flags.s |= FF_HDX_HANDSHAKE;
  2008. X    }
  2009. X    else
  2010. X    {
  2011. X#if defined (CTSFLOW)    /* SYSV 3.2 Xenix compatibility */
  2012. X        if ((cflag & (CTSFLOW | CLOCAL)) == CTSFLOW)
  2013. SHAR_EOF
  2014. true || echo 'restore of fasi/fas.c failed'
  2015. fi
  2016. echo 'End of ecu320 part 32'
  2017. echo 'File fasi/fas.c is continued in part 33'
  2018. echo 33 > _shar_seq_.tmp
  2019. exit 0
  2020.  
  2021. exit 0 # Just in case...
  2022.