home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume32 / ecu / part32 < prev    next >
Text File  |  1992-09-15  |  58KB  |  2,017 lines

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