home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / unix / sysv386 / 13240 < prev    next >
Encoding:
Internet Message Format  |  1992-08-17  |  60.1 KB

  1. Xref: sparky comp.unix.sysv386:13240 comp.unix.xenix.sco:2697 alt.sources:1886
  2. Newsgroups: comp.unix.sysv386,comp.unix.xenix.sco,alt.sources
  3. Path: sparky!uunet!mcsun!Germany.EU.net!news.netmbx.de!zrz.tu-berlin.de!math.fu-berlin.de!fub!geminix.in-berlin.de!gemini
  4. From: gemini@geminix.in-berlin.de (Uwe Doering)
  5. Subject: FAS 2.10 async driver, part 3/5
  6. Organization: Private UNIX Site
  7. Date: Mon, 17 Aug 1992 11:38:06 GMT
  8. Message-ID: <F555HSC@geminix.in-berlin.de>
  9. Lines: 2304
  10.  
  11. Submitted-by: gemini@geminix.in-berlin.de
  12. Archive-name: fas210/part03
  13.  
  14. #!/bin/sh
  15. # this is fas210.03 (part 3 of fas210)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file config-ast4c12 continued
  18. #
  19. if test ! -r _shar_seq_.tmp; then
  20.     echo 'Please unpack part 1 first!'
  21.     exit 1
  22. fi
  23. (read Scheck
  24.  if test "$Scheck" != 3; then
  25.     echo Please unpack part "$Scheck" next!
  26.     exit 1
  27.  else
  28.     exit 0
  29.  fi
  30. ) < _shar_seq_.tmp || exit 1
  31. if test ! -f _shar_wnt_.tmp; then
  32.     echo 'x - still skipping config-ast4c12'
  33. else
  34. echo 'x - continuing file config-ast4c12'
  35. sed 's/^X//' << 'SHAR_EOF' >> 'config-ast4c12' &&
  36. Xcharacter(4)
  37. X
  38. X* its name
  39. Xprefix = fas
  40. X
  41. X* The interrupt vectors handled by this controller
  42. Xintvec = 9,4,3
  43. X
  44. X* its mask level
  45. Xintpri = SPLTTY
  46. X
  47. X* the functions it supports
  48. Xfunctions = init, open, close, read, write, ioctl, tty
  49. SHAR_EOF
  50. echo 'File config-ast4c12 is complete' &&
  51. true || echo 'restore of config-ast4c12 failed'
  52. rm -f _shar_wnt_.tmp
  53. fi
  54. # ============= config-c12 ==============
  55. if test -f 'config-c12' -a X"$1" != X"-c"; then
  56.     echo 'x - skipping config-c12 (File already exists)'
  57.     rm -f _shar_wnt_.tmp
  58. else
  59. > _shar_wnt_.tmp
  60. echo 'x - extracting config-c12 (Text)'
  61. sed 's/^X//' << 'SHAR_EOF' > 'config-c12' &&
  62. X* its character device number 4
  63. Xcharacter(4)
  64. X
  65. X* its name
  66. Xprefix = fas
  67. X
  68. X* The interrupt vectors handled by this controller
  69. Xintvec = 4,3
  70. X
  71. X* its mask level
  72. Xintpri = SPLTTY
  73. X
  74. X* the functions it supports
  75. Xfunctions = init, open, close, read, write, ioctl, tty
  76. SHAR_EOF
  77. true || echo 'restore of config-c12 failed'
  78. rm -f _shar_wnt_.tmp
  79. fi
  80. # ============= config-c123 ==============
  81. if test -f 'config-c123' -a X"$1" != X"-c"; then
  82.     echo 'x - skipping config-c123 (File already exists)'
  83.     rm -f _shar_wnt_.tmp
  84. else
  85. > _shar_wnt_.tmp
  86. echo 'x - extracting config-c123 (Text)'
  87. sed 's/^X//' << 'SHAR_EOF' > 'config-c123' &&
  88. X* its character device number 4
  89. Xcharacter(4)
  90. X
  91. X* its name
  92. Xprefix = fas
  93. X
  94. X* The interrupt vectors handled by this controller
  95. Xintvec = 4,3,9
  96. X
  97. X* its mask level
  98. Xintpri = SPLTTY
  99. X
  100. X* the functions it supports
  101. Xfunctions = init, open, close, read, write, ioctl, tty
  102. SHAR_EOF
  103. true || echo 'restore of config-c123 failed'
  104. rm -f _shar_wnt_.tmp
  105. fi
  106. # ============= config-digi8c1 ==============
  107. if test -f 'config-digi8c1' -a X"$1" != X"-c"; then
  108.     echo 'x - skipping config-digi8c1 (File already exists)'
  109.     rm -f _shar_wnt_.tmp
  110. else
  111. > _shar_wnt_.tmp
  112. echo 'x - extracting config-digi8c1 (Text)'
  113. sed 's/^X//' << 'SHAR_EOF' > 'config-digi8c1' &&
  114. X* its character device number 4
  115. Xcharacter(4)
  116. X
  117. X* its name
  118. Xprefix = fas
  119. X
  120. X* The interrupt vectors handled by this controller
  121. Xintvec = 3,4
  122. X
  123. X* its mask level
  124. Xintpri = SPLTTY
  125. X
  126. X* the functions it supports
  127. Xfunctions = init, open, close, read, write, ioctl, tty
  128. SHAR_EOF
  129. true || echo 'restore of config-digi8c1 failed'
  130. rm -f _shar_wnt_.tmp
  131. fi
  132. # ============= config-hub6 ==============
  133. if test -f 'config-hub6' -a X"$1" != X"-c"; then
  134.     echo 'x - skipping config-hub6 (File already exists)'
  135.     rm -f _shar_wnt_.tmp
  136. else
  137. > _shar_wnt_.tmp
  138. echo 'x - extracting config-hub6 (Text)'
  139. sed 's/^X//' << 'SHAR_EOF' > 'config-hub6' &&
  140. X* its character device number 4
  141. Xcharacter(4)
  142. X
  143. X* its name
  144. Xprefix = fas
  145. X
  146. X* The interrupt vectors handled by this controller
  147. Xintvec = 3
  148. X
  149. X* its mask level
  150. Xintpri = SPLTTY
  151. X
  152. X* the functions it supports
  153. Xfunctions = init, open, close, read, write, ioctl, tty
  154. SHAR_EOF
  155. true || echo 'restore of config-hub6 failed'
  156. rm -f _shar_wnt_.tmp
  157. fi
  158. # ============= fas.c ==============
  159. if test -f 'fas.c' -a X"$1" != X"-c"; then
  160.     echo 'x - skipping fas.c (File already exists)'
  161.     rm -f _shar_wnt_.tmp
  162. else
  163. > _shar_wnt_.tmp
  164. echo 'x - extracting fas.c (Text)'
  165. sed 's/^X//' << 'SHAR_EOF' > 'fas.c' &&
  166. X/* FAS Final Async Solution driver for 286/386 versions of system V UNIX */
  167. X
  168. X/* FAS was developed by
  169. XUwe Doering             INET : gemini@geminix.in-berlin.de
  170. XBillstedter Pfad 17 b   UUCP : ...!unido!fub!geminix.in-berlin.de!gemini
  171. X1000 Berlin 20
  172. XGermany
  173. X*/
  174. X
  175. X#if !defined (M_I286)
  176. X#ident    "@(#)fas.c    2.10"
  177. X#endif
  178. X
  179. X/* Note: This source code has been quite heavily optimized for speed.
  180. X         You may wonder that register variables aren't used everywhere.
  181. X         This is because there is an overhead in memory accesses
  182. X         when using register variables. As you may know data accesses
  183. X         usually need much more wait states on the memory bus than
  184. X         code accesses (because of page or cache misses). Therefore,
  185. X         saving some data accesses has higher priority than saving
  186. X         code accesses.
  187. X
  188. X         You may also note some not very elegant constructions that
  189. X         may be intentional because they are faster. If you want to
  190. X         make style improvements you should check the assembler output
  191. X         whether this wouldn't slow things down.
  192. X
  193. X         Decisions for speed optimization were based on assembler
  194. X         listings produced by the standard UNIX V [34].X/386 C compiler.
  195. X*/
  196. X
  197. X#if defined (XENIX)
  198. X
  199. X#include "fas.h"
  200. X#if defined (__GNUC__) && !defined (NO_ASM)
  201. X#define outb(port,val) \
  202. X({\
  203. X    __asm__ volatile ("outb %1,%0" : : "d" ((ushort) (port)), "a" ((unchar) (val)));\
  204. X})
  205. X
  206. X#define inb(port) \
  207. X({\
  208. X    unchar __val;\
  209. X    __asm__ volatile ("inb %1,%0" : "=a" (__val) : "d" ((ushort) (port)));\
  210. X    __val;\
  211. X})
  212. X#endif    /* __GNUC__ && !NO_ASM */
  213. X#define REGVAR
  214. X
  215. X#else    /* XENIX */
  216. X
  217. X#include <sys/fas.h>
  218. X#if defined (__GNUC__)
  219. X#if !defined (NO_ASM)
  220. X#if defined (SCO)
  221. X#define outb(port,val) \
  222. X({\
  223. X    __asm__ volatile ("outb %1,%0" : : "d" ((ushort) (port)), "a" ((unchar) (val)));\
  224. X})
  225. X
  226. X#define inb(port) \
  227. X({\
  228. X    unchar __val;\
  229. X    __asm__ volatile ("inb %1,%0" : "=a" (__val) : "d" ((ushort) (port)));\
  230. X    __val;\
  231. X})
  232. X#else    /* SCO */
  233. X#define outb(port,val) \
  234. X({\
  235. X    __asm__ volatile ("outb (%0)" : : "d" ((ushort) (port)), "a" ((unchar) (val)));\
  236. X})
  237. X
  238. X#define inb(port) \
  239. X({\
  240. X    unchar __val;\
  241. X    __asm__ volatile ("inb (%1)" : "=a" (__val) : "d" ((ushort) (port)));\
  242. X    __val;\
  243. X})
  244. X#endif    /* SCO */
  245. X#endif    /* !NO_ASM */
  246. X
  247. X#define REGVAR
  248. X#else    /* __GNUC__ */
  249. X#if !defined (NO_ASM)
  250. X#include <sys/inline.h>
  251. X
  252. X/* This is a terrible ugly kludge to speed up the `inb' and `outb'
  253. X   functions. I.e., originally, the `outb' inline function had an
  254. X   overhead of four data memory accesses for parameter passing. This
  255. X   parameter passing actually consumed more clock cycles than the
  256. X   assembler `outb' command itself. Although this solution can't
  257. X   prevent unnessessary register moves it limits them at least to
  258. X   register to register moves that are much faster. You need a
  259. X   line like the following in the declaration part of every
  260. X   function that uses `inb' or `outb' calls:
  261. X
  262. X    REGVAR;
  263. X
  264. X   This hack should work with every compiler that knows about the
  265. X   UNIX V [34].X/386 standard compiler's inline assembler directives.
  266. X*/
  267. X
  268. Xasm    void loadal (val)
  269. X{
  270. X%reg    val;
  271. X    movl    val,%eax
  272. X%mem    val;
  273. X    movb    val,%al
  274. X}
  275. X
  276. Xasm    void loaddx (val)
  277. X{
  278. X%reg    val;
  279. X    movl    val,%edx
  280. X%mem    val;
  281. X    movw    val,%dx
  282. X}
  283. X
  284. Xasm    int outbyte ()
  285. X{
  286. X    outb    (%dx)
  287. X}
  288. X
  289. Xasm    int inbyte ()
  290. X{
  291. X    xorl    %eax,%eax
  292. X    inb    (%dx)
  293. X}
  294. X
  295. X/* The port parameter of the `outb' macro must be one of the predefined
  296. X   port macros from `fas.h' or a simple uint variable (no indirection
  297. X   is allowed). Additionally, `fip' must be a register variable in the
  298. X   functions where `outb' is used. This prevents the destruction of the
  299. X   `eax' CPU register while loading the `edx' register with the port
  300. X   address. This is highly compiler implementation specific.
  301. X*/
  302. X#define outb(port,val) (regvar = (val), loadal (regvar), regvar = (port), loaddx (regvar), outbyte ())
  303. X
  304. X#define inb(port) (regvar = (port), loaddx (regvar), inbyte ())
  305. X
  306. X#define REGVAR register uint    regvar
  307. X
  308. X/* This function inserts the address optimization assembler pseudo-op
  309. X   wherever called.
  310. X*/
  311. X
  312. Xasm    void optim ()
  313. X{
  314. X    .optim
  315. X}
  316. X
  317. X/* This dummy function has nothing to do but to call optim so that
  318. X   the `.optim' assembler pseudo-op will be included in the assembler
  319. X   file. This must be the first of all functions.
  320. X*/
  321. X
  322. X#if defined (OPTIM)    /* Define for uPort, ISC doesn't know about */
  323. Xstatic void        /* `.optim', but has turned on optimization by */
  324. Xdummy ()        /* default, so we don't need it there anyway. */
  325. X{
  326. X    optim ();
  327. X}
  328. X#endif    /* OPTIM */
  329. X#else    /* !NO_ASM */
  330. X#define REGVAR
  331. X#endif    /* !NO_ASM */
  332. X#endif    /* __GNUC__ */
  333. X
  334. X#endif    /* XENIX */
  335. X
  336. X#if defined (SCO) || defined (XENIX)
  337. X#define asyputchar sioputchar
  338. X#define asygetchar siogetchar
  339. X#endif
  340. X
  341. X/* functions provided by this driver */
  342. Xint        fasinit ();
  343. Xint        fasopen ();
  344. Xint        fasclose ();
  345. Xint        fasread ();
  346. Xint        faswrite ();
  347. Xint        fasioctl ();
  348. Xint        fasintr ();
  349. X#if defined (NEED_PUT_GETCHAR)
  350. Xint        asyputchar ();
  351. Xint        asygetchar ();
  352. X#endif
  353. X#if defined (NEED_INIT8250)
  354. Xint        init8250 ();
  355. X#endif
  356. Xstatic int    fas_proc ();
  357. Xstatic void    fas_param ();
  358. Xstatic void    fas_mproc ();
  359. Xstatic void    fas_rproc ();
  360. Xstatic void    fas_xproc ();
  361. Xstatic void    fas_event ();
  362. X#if defined (HAVE_VPIX)
  363. Xstatic bool    fas_vpix_sr ();
  364. X#endif
  365. Xstatic void    fas_msi_disable ();
  366. Xstatic void    fas_msi_enable ();
  367. Xstatic void    fas_rdi_disable ();
  368. Xstatic void    fas_rdi_enable ();
  369. Xstatic bool    fas_rxfer ();
  370. Xstatic void    fas_xxfer ();
  371. Xstatic void    fas_hwi_start ();
  372. Xstatic void    fas_hwi_stop ();
  373. Xstatic void    fas_send_xon ();
  374. Xstatic void    fas_send_xoff ();
  375. Xstatic void    fas_hdx_start ();
  376. Xstatic void    fas_hangup ();
  377. Xstatic void    fas_timeout ();
  378. Xstatic void    fas_cmd ();
  379. Xstatic void    fas_open_device ();
  380. Xstatic void    fas_close_device ();
  381. Xstatic void    fas_pos_by_speed ();
  382. Xstatic uint    fas_make_ctl_val ();
  383. Xstatic uint    fas_test_device ();
  384. X
  385. X/* external functions used by this driver */
  386. Xextern int    ttinit ();
  387. Xextern int    ttiocom ();
  388. Xextern int    ttyflush ();
  389. Xextern int    SPLINT ();
  390. Xextern int    SPLWRK ();
  391. Xextern int    splx ();
  392. Xextern int    sleep ();
  393. Xextern int    wakeup ();
  394. Xextern void    longjmp ();
  395. X#if !defined (SVR4)
  396. Xextern int    signal ();
  397. X#endif
  398. Xextern int    timeout ();
  399. Xextern int    untimeout ();
  400. X#if defined (SCO) || defined (XENIX)
  401. Xextern int    printcfg ();
  402. X#else
  403. Xextern int    printf ();
  404. X#endif
  405. X#if defined (HAVE_VPIX)
  406. Xextern int    fubyte ();
  407. Xextern int    subyte ();
  408. Xextern int    v86setint ();
  409. X#endif
  410. X#if defined (NO_ASM) || (defined (XENIX) && !defined (__GNUC__))
  411. Xextern int    inb ();
  412. Xextern int    outb ();
  413. X#endif
  414. X
  415. X/* external data objects used by this driver */
  416. Xextern int    tthiwat [];
  417. Xextern int    ttlowat [];
  418. Xextern int    ttyhog;
  419. X
  420. X/* the following stuff is defined in space.c */
  421. Xextern uint    fas_physical_units;
  422. Xextern ulong    fas_port [];
  423. Xextern uint    fas_init_seq [];
  424. Xextern uint    fas_int_ack_seq [];
  425. Xextern uint    fas_mcb [];
  426. Xextern ulong    fas_modem [];
  427. Xextern ulong    fas_flow [];
  428. Xextern uint    fas_ctl_port [];
  429. Xextern uint    fas_ctl_val [];
  430. Xextern struct fas_internals    fas_internals [];
  431. Xextern struct tty        fas_tty [];
  432. Xextern struct fas_internals    *fas_internals_ptr [];
  433. Xextern struct tty        *fas_tty_ptr [];
  434. X/* end of space.c references */
  435. X
  436. X/* fas_is_initted
  437. X   Flag to indicate that we have been thru init.
  438. X   This is realy only necessary for systems that use asyputchar
  439. X   and asygetchar but it doesn't hurt to have it anyway.
  440. X*/
  441. Xstatic bool    fas_is_initted = FALSE;
  442. X
  443. X/* event_scheduled
  444. X   Flag to indicate that the event handler has been scheduled
  445. X   via the timeout () function.
  446. X*/
  447. Xstatic bool    event_scheduled = FALSE;
  448. X
  449. X/* pointers to the first and last fas_internals structure of the
  450. X   interrupt users chain
  451. X*/
  452. Xstatic struct fas_internals    *fas_first_int_user, *fas_last_int_user;
  453. X
  454. X/* thresholds for the character transfer to the CLIST buffers */
  455. Xstatic uint    max_unix_fill;
  456. X#if defined (HAVE_VPIX)
  457. Xstatic uint    max_vpix_fill;
  458. X#endif
  459. Xstatic uint    min_read_chunk;
  460. X
  461. X/* counters for receiver overruns, each UART type has its own counter
  462. X   indexed by the device type
  463. X*/
  464. Xuint    fas_overrun [NUMBER_OF_TYPES];
  465. X
  466. X/* counter for temporarily disabled modem status interrupts due
  467. X   to noise on the modem status lines
  468. X*/
  469. Xuint    fas_msi_noise;
  470. X
  471. X/* UNIX to FAS mapping of baud rates (normal speed) */
  472. Xstatic n_ushort    fas_baud [CBAUD + 1] =
  473. X{    B38400,        B50,
  474. X    B75,        B110,
  475. X    B134,        B150,
  476. X    B200,        B300,
  477. X    B600,        B1200,
  478. X    B1800,        B2400,
  479. X    B4800,        B9600,
  480. X    B19200,        B38400
  481. X};
  482. X
  483. X/* UNIX to FAS mapping of baud rates (high speed) */
  484. Xstatic n_ushort    fas_hbaud [CBAUD + 1] =
  485. X{    B0,        B50,
  486. X    B75,        B110,
  487. X    B134,        B150,
  488. X    B200,        B300,
  489. X    B600,        B1200,
  490. X    B1800,        B2400,
  491. X    B4800,        B9600,
  492. X    B19200,        BHIGHSPEED
  493. X};
  494. X
  495. X/* Note: The baud rate in fas_hbaud that is overridden by BHIGHSPEED
  496. X         has to be entered at fas_baud [0] !
  497. X
  498. X   Note also: If you want to use a speed different from B38400 for
  499. X              BHIGHSPEED, you have to make sure that the tthiwat [] and
  500. X              ttlowat [] values for that baud rate are high enough
  501. X              to allow the CLIST function to keep the FAS transmit
  502. X              buffer filled. Look at fasinit () on how to do that.
  503. X*/
  504. X
  505. X/* the divisor values for the various baud rates */
  506. X/* 57600 bps version */
  507. Xstatic n_ushort    fas_speeds1 [CBAUD + 1] =
  508. X{    BAUD_BASE/57600,    BAUD_BASE/50,
  509. X    BAUD_BASE/75,        BAUD_BASE/110,
  510. X    (2*BAUD_BASE+134)/269,    BAUD_BASE/150,
  511. X    BAUD_BASE/200,        BAUD_BASE/300,
  512. X    BAUD_BASE/600,        BAUD_BASE/1200,
  513. X    BAUD_BASE/1800,        BAUD_BASE/2400,
  514. X    BAUD_BASE/4800,        BAUD_BASE/9600,
  515. X    BAUD_BASE/19200,    BAUD_BASE/38400
  516. X};
  517. X
  518. X/* 115200 bps version */
  519. Xstatic n_ushort    fas_speeds2 [CBAUD + 1] =
  520. X{    BAUD_BASE/115200,    BAUD_BASE/50,
  521. X    BAUD_BASE/75,        BAUD_BASE/110,
  522. X    (2*BAUD_BASE+134)/269,    BAUD_BASE/150,
  523. X    BAUD_BASE/200,        BAUD_BASE/300,
  524. X    BAUD_BASE/600,        BAUD_BASE/1200,
  525. X    BAUD_BASE/1800,        BAUD_BASE/2400,
  526. X    BAUD_BASE/4800,        BAUD_BASE/9600,
  527. X    BAUD_BASE/19200,    BAUD_BASE/38400
  528. X};
  529. X
  530. X/* time for one character to completely leave the transmitter shift register */
  531. X/* 57600 bps version */
  532. Xstatic n_ushort    fas_ctimes1 [CBAUD + 1] =
  533. X{    HZ*15/57600+2,    HZ*15/50+2,
  534. X    HZ*15/75+2,    HZ*15/110+2,
  535. X    HZ*30/269+2,    HZ*15/150+2,
  536. X    HZ*15/200+2,    HZ*15/300+2,
  537. X    HZ*15/600+2,    HZ*15/1200+2,
  538. X    HZ*15/1800+2,    HZ*15/2400+2,
  539. X    HZ*15/4800+2,    HZ*15/9600+2,
  540. X    HZ*15/19200+2,    HZ*15/38400+2
  541. X};
  542. X
  543. X/* time for one character to completely leave the transmitter shift register */
  544. X/* 115200 bps version */
  545. Xstatic n_ushort    fas_ctimes2 [CBAUD + 1] =
  546. X{    HZ*15/115200+2,    HZ*15/50+2,
  547. X    HZ*15/75+2,    HZ*15/110+2,
  548. X    HZ*30/269+2,    HZ*15/150+2,
  549. X    HZ*15/200+2,    HZ*15/300+2,
  550. X    HZ*15/600+2,    HZ*15/1200+2,
  551. X    HZ*15/1800+2,    HZ*15/2400+2,
  552. X    HZ*15/4800+2,    HZ*15/9600+2,
  553. X    HZ*15/19200+2,    HZ*15/38400+2
  554. X};
  555. X
  556. X/* dynamically adapt xmit buffer size to baud rate to prevent long buffer
  557. X   drains at low speeds
  558. X   These values are checked against boundaries and will be modified if
  559. X   necessary before use. Checking is done in fas_param (). Drain time
  560. X   is about 2 seconds with continuous character flow.
  561. X*/
  562. X/* 57600 bps version */
  563. Xstatic n_ushort    fas_xbuf_size1 [CBAUD + 1] =
  564. X{    57600/5,    50/5,
  565. X    75/5,        110/5,
  566. X    269/10,        150/5,
  567. X    200/5,        300/5,
  568. X    600/5,        1200/5,
  569. X    1800/5,        2400/5,
  570. X    4800/5,        9600/5,
  571. X    19200/5,    38400/5
  572. X};
  573. X
  574. X/* 115200 bps version */
  575. Xstatic n_ushort    fas_xbuf_size2 [CBAUD + 1] =
  576. X{    115200/5,    50/5,
  577. X    75/5,        110/5,
  578. X    269/10,        150/5,
  579. X    200/5,        300/5,
  580. X    600/5,        1200/5,
  581. X    1800/5,        2400/5,
  582. X    4800/5,        9600/5,
  583. X    19200/5,    38400/5
  584. X};
  585. X
  586. X/* lookup table for minor device number -> open mode flags translation */
  587. Xstatic n_ushort    fas_open_modes [16] =
  588. X{
  589. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL,
  590. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HWO_HANDSHAKE
  591. X                            | OS_HWI_HANDSHAKE,
  592. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HWO_HANDSHAKE,
  593. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HWO_HANDSHAKE
  594. X                            | OS_HDX_HANDSHAKE,
  595. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON,
  596. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HWO_HANDSHAKE
  597. X                        | OS_HWI_HANDSHAKE,
  598. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HWO_HANDSHAKE,
  599. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HWO_HANDSHAKE
  600. X                        | OS_HDX_HANDSHAKE,
  601. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT,
  602. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HWO_HANDSHAKE
  603. X                            | OS_HWI_HANDSHAKE,
  604. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HWO_HANDSHAKE,
  605. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HWO_HANDSHAKE
  606. X                            | OS_HDX_HANDSHAKE,
  607. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN,
  608. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
  609. X                        | OS_HWI_HANDSHAKE,
  610. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE,
  611. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
  612. X                        | OS_HDX_HANDSHAKE
  613. X};
  614. X
  615. X/* The following defines are used to access multiplexed ports. */
  616. X#define GET_PORT(port,num) \
  617. X    ((fip->device_flags.i & DF_CTL_EVERY)\
  618. X            ? (port)\
  619. X            : (port) + (num))
  620. X
  621. X#define fas_first_ctl(fip,port) \
  622. X    ((void) (((fip)->device_flags.i & DF_CTL_FIRST)\
  623. X            ? outb (CTL_PORT, (port).p.ctl)\
  624. X            : 0))
  625. X
  626. X#define fas_every_ctl(fip,port) \
  627. X    ((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
  628. X            ? outb (CTL_PORT, (port).p.ctl)\
  629. X            : 0))
  630. X
  631. X#define fas_ctl(fip,port) \
  632. X    ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
  633. X            ? outb (CTL_PORT, (port).p.ctl)\
  634. X            : 0))
  635. X
  636. X#define fas_first_outb(fip,port,val) \
  637. X    ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
  638. X            ? outb (CTL_PORT, (port).p.ctl)\
  639. X            : 0),\
  640. X        (void) outb ((port).addr, (val)))
  641. X
  642. X#define fas_outb(fip,port,val) \
  643. X    ((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
  644. X            ? outb (CTL_PORT, (port).p.ctl)\
  645. X            : 0),\
  646. X        (void) outb ((port).addr, (val)))
  647. X
  648. X#define fas_same_outb(fip,port,val) \
  649. X    ((void) outb ((port).addr, (val)))
  650. X
  651. X#define fas_first_inb(fip,port) \
  652. X    ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
  653. X            ? outb (CTL_PORT, (port).p.ctl)\
  654. X            : 0),\
  655. X        inb ((port).addr))
  656. X
  657. X#define fas_inb(fip,port) \
  658. X    ((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
  659. X            ? outb (CTL_PORT, (port).p.ctl)\
  660. X            : 0),\
  661. X        inb ((port).addr))
  662. X
  663. X#define fas_same_inb(fip,port) \
  664. X    (inb ((port).addr))
  665. X
  666. X/* The following defines are used to take apart the minor device numbers. */
  667. X#define GET_UNIT(dev)        ((dev) & 0x0f)
  668. X#define GET_OPEN_MODE(dev)    (fas_open_modes [((dev) >> 4) & 0x0f])
  669. X
  670. X/* lock device against concurrent use */
  671. X#define get_device_lock(fip,prio) \
  672. X{\
  673. X    /* sleep while device is used by an other process */\
  674. X    while ((fip)->device_flags.i & DF_DEVICE_LOCKED)\
  675. X        (void) sleep ((caddr_t) &(fip)->device_flags.i, (prio));\
  676. X    (fip)->device_flags.s |= DF_DEVICE_LOCKED;\
  677. X}
  678. X
  679. X/* release device */
  680. X#define release_device_lock(fip) \
  681. X{\
  682. X    (fip)->device_flags.s &= ~DF_DEVICE_LOCKED;\
  683. X    /* wakeup the process that may wait for this device */\
  684. X    (void) wakeup ((caddr_t) &(fip)->device_flags.i);\
  685. X}
  686. X
  687. X/* schedule event */
  688. X#define event_sched(fip,event) \
  689. X{\
  690. X    (fip)->event_flags.s |= (event);\
  691. X    if (!event_scheduled)\
  692. X    {\
  693. X        event_scheduled = TRUE;\
  694. X        (void) timeout (fas_event, (caddr_t) NULL, 1);\
  695. X    }\
  696. X}
  697. X
  698. X/* fasinit
  699. X   This routine checks for the presense of the devices in the fas_port
  700. X   array and if the device is present tests and initializes it.
  701. X   During the initialization the device type is automatically determined
  702. X   and the UART is handled according to its requirements.
  703. X*/
  704. X
  705. Xint
  706. Xfasinit ()
  707. X{
  708. X    register struct fas_internals    *fip;
  709. X    register uint    unit;
  710. X    uint    logical_units, port, *seq_ptr;
  711. X    uint    baud_rate;
  712. X    int    max_tthiwat, max_ttlowat;
  713. X    char    port_stat [MAX_UNITS + 1];
  714. X    REGVAR;
  715. X
  716. X    if (fas_is_initted)
  717. X        return (0);
  718. X
  719. X    fas_is_initted = TRUE;
  720. X
  721. X    /* kludge to make sure that the tty buffer high water levels
  722. X       for fast baud rates are high enough to ensure max. throughput
  723. X    */
  724. X    for (baud_rate = B50, max_tthiwat = 0; baud_rate <= B38400; ++baud_rate)
  725. X    {
  726. X        if (tthiwat [baud_rate] >= max_tthiwat)
  727. X        {
  728. X            max_tthiwat = tthiwat [baud_rate];
  729. X            max_ttlowat = ttlowat [baud_rate];
  730. X        }
  731. X        else
  732. X        {
  733. X            tthiwat [baud_rate] = max_tthiwat;
  734. X            ttlowat [baud_rate] = max_ttlowat;
  735. X        }
  736. X    }
  737. X
  738. X    /* initialize thresholds for the character transfer to
  739. X       the CLIST buffers
  740. X    */
  741. X    max_unix_fill = ttyhog - 1;
  742. X    min_read_chunk = (MIN_READ_CHUNK * 2 > max_unix_fill)
  743. X                ? max_unix_fill / 2
  744. X                : MIN_READ_CHUNK;
  745. X#if defined (HAVE_VPIX)
  746. X    max_vpix_fill = (MAX_VPIX_FILL > max_unix_fill)
  747. X                ? max_unix_fill
  748. X                : MAX_VPIX_FILL;
  749. X    if (min_read_chunk * 2 > max_vpix_fill)
  750. X        min_read_chunk = max_vpix_fill / 2;
  751. X#endif
  752. X
  753. X    /* execute the init sequence for the serial cards */
  754. X    for (seq_ptr = &fas_init_seq [0]; *seq_ptr; ++seq_ptr)
  755. X    {
  756. X        port = *seq_ptr;
  757. X        ++seq_ptr;
  758. X        if (*seq_ptr & READ_PORT)
  759. X            (void) inb (port);
  760. X        else
  761. X            (void) outb (port, *seq_ptr);
  762. X    }
  763. X
  764. X    /* setup the list of pointers to the tty structures */
  765. X    for (unit = 0, logical_units = fas_physical_units * 2;
  766. X        unit < logical_units; ++unit)
  767. X        fas_tty_ptr [unit] = &fas_tty [unit];
  768. X
  769. X    /* setup and initialize all serial ports */
  770. X    for (unit = 0; unit < fas_physical_units; ++unit)
  771. X    {
  772. X        fas_internals_ptr [unit] = fip = &fas_internals [unit];
  773. X        port_stat [unit] = '-';
  774. X        if (port = (uint) ((ushort) (fas_port [unit])))
  775. X        {
  776. X            /* init all of its ports */
  777. X            if (fas_ctl_port [unit])
  778. X            {
  779. X                fip->ctl_port = fas_ctl_port [unit];
  780. X
  781. X                if (fas_ctl_val [unit] & 0xff00)
  782. X                    fip->device_flags.s |= DF_CTL_EVERY;
  783. X                else
  784. X                    fip->device_flags.s |= DF_CTL_FIRST;
  785. X            }
  786. X
  787. X            fip->port_0.p.addr = GET_PORT (port, 0);
  788. X            fip->port_1.p.addr = GET_PORT (port, 1);
  789. X            fip->port_2.p.addr = GET_PORT (port, 2);
  790. X            fip->port_3.p.addr = GET_PORT (port, 3);
  791. X            fip->port_4.p.addr = GET_PORT (port, 4);
  792. X            fip->port_5.p.addr = GET_PORT (port, 5);
  793. X            fip->port_6.p.addr = GET_PORT (port, 6);
  794. X            fip->port_0.p.ctl = fas_make_ctl_val (fip, unit, 0);
  795. X            fip->port_1.p.ctl = fas_make_ctl_val (fip, unit, 1);
  796. X            fip->port_2.p.ctl = fas_make_ctl_val (fip, unit, 2);
  797. X            fip->port_3.p.ctl = fas_make_ctl_val (fip, unit, 3);
  798. X            fip->port_4.p.ctl = fas_make_ctl_val (fip, unit, 4);
  799. X            fip->port_5.p.ctl = fas_make_ctl_val (fip, unit, 5);
  800. X            fip->port_6.p.ctl = fas_make_ctl_val (fip, unit, 6);
  801. X            fip->modem.l = fas_modem [unit];
  802. X            fip->flow.l = fas_flow [unit];
  803. X            fip->po_state = fip->o_state = OS_DEVICE_CLOSED;
  804. X
  805. X            /* mask off invalid bits */
  806. X            fip->modem.m.di &= MC_ANY_CONTROL;
  807. X            fip->modem.m.eo &= MC_ANY_CONTROL;
  808. X            fip->modem.m.ei &= MC_ANY_CONTROL;
  809. X            fip->modem.m.ca &= MS_ANY_PRESENT;
  810. X            fip->flow.m.ic &= MC_ANY_CONTROL;
  811. X            fip->flow.m.oc &= MS_ANY_PRESENT;
  812. X            fip->flow.m.oe &= MS_ANY_PRESENT;
  813. X            fip->flow.m.hc &= MC_ANY_CONTROL;
  814. X
  815. X            fip->recv_ring_put_ptr = &fip->recv_buffer [0];
  816. X            fip->recv_ring_take_ptr = &fip->recv_buffer [0];
  817. X            fip->xmit_ring_put_ptr = &fip->xmit_buffer [0];
  818. X            fip->xmit_ring_take_ptr = &fip->xmit_buffer [0];
  819. X
  820. X            /* disable all ints */
  821. X            fas_first_outb (fip, INT_ENABLE_PORT,
  822. X                            fip->ier = IE_NONE);
  823. X
  824. X            /* is there a serial chip ? */
  825. X            if (fas_same_inb (fip, INT_ENABLE_PORT) != fip->ier)
  826. X            {
  827. X                port_stat [unit] = '?';
  828. X                continue;    /* a hardware error */
  829. X            }
  830. X
  831. X            /* test the chip thoroughly */
  832. X            if (!(fas_port [unit] & NO_TEST)
  833. X                && (port_stat [unit]
  834. X                        = (fas_test_device (fip) + '0'))
  835. X                    != '0')
  836. X                continue;    /* a hardware error */
  837. X
  838. X            fas_outb (fip, LINE_CTL_PORT, fip->lcr = 0);
  839. X            fas_outb (fip, MDM_CTL_PORT, fip->mcr
  840. X                    = fas_mcb [unit] | fip->modem.m.di);
  841. X
  842. X            fip->device_type = TYPE_NS16450;
  843. X            fip->xmit_fifo_size = 1;
  844. X            port_stat [unit] = '*';
  845. X
  846. X            /* let's see if it's an NS16550A */
  847. X            fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_INIT_CMD);
  848. X            if (!(~fas_inb (fip, INT_ID_PORT) & II_NS_FIFO_ENABLED))
  849. X            {
  850. X                fip->device_type = TYPE_NS16550A;
  851. X                fip->xmit_fifo_size = OUTPUT_NS_FIFO_SIZE;
  852. X                port_stat [unit] = 'F';
  853. X                fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
  854. X            }
  855. X            else
  856. X            {
  857. X                fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
  858. X                /* or is it an i82510 ? */
  859. X                fas_outb (fip, I_BANK_PORT, I_BANK_2);
  860. X                if (!(~fas_inb (fip, I_BANK_PORT) & I_BANK_2))
  861. X                {
  862. X                    fip->device_type = TYPE_I82510;
  863. X                    fip->xmit_fifo_size = OUTPUT_I_FIFO_SIZE;
  864. X                    port_stat [unit] = 'f';
  865. X                    fas_outb (fip, I_BANK_PORT, I_BANK_1);
  866. X                    fas_outb (fip, I_TCM_PORT, I_FIFO_CLR_XMIT);
  867. X                    fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
  868. X                }
  869. X                fas_outb (fip, I_BANK_PORT, I_BANK_0);
  870. X            }
  871. X
  872. X            /* disable FIFOs if requested in space.c */
  873. X            if ((fas_port [unit] & NO_FIFO)
  874. X                    && (fip->device_type != TYPE_NS16450))
  875. X            {
  876. X                fip->device_type = TYPE_NS16450;
  877. X                fip->xmit_fifo_size = 1;
  878. X                port_stat [unit] = '+';
  879. X            }
  880. X
  881. X            /* clear potential interrupts */
  882. X            (void) fas_inb (fip, MDM_STATUS_PORT);
  883. X            (void) fas_inb (fip, RCV_DATA_PORT);
  884. X            if (fas_inb (fip, LINE_STATUS_PORT) & LS_RCV_AVAIL)
  885. X                (void) fas_inb (fip, RCV_DATA_PORT);
  886. X            fip->lsr = 0;
  887. X            (void) fas_inb (fip, INT_ID_PORT);
  888. X
  889. X            /* do we want a high speed port ? */
  890. X            if (fas_port [unit] & HS_115200)
  891. X                fip->device_flags.s |= DF_HIGH_SPEED | DF_115K;
  892. X            else if (fas_port [unit] & HS_57600)
  893. X                fip->device_flags.s |= DF_HIGH_SPEED;
  894. X
  895. X            /* do we want the fdx meaning of CTSFLOW/RTSFLOW ? */
  896. X            if (fas_port [unit] & NEW_CTSRTS)
  897. X                fip->flow_flags.s |= FF_NEW_CTSRTS;
  898. X
  899. X            /* show that it is present and configured */
  900. X            fip->device_flags.s |= DF_DEVICE_CONFIGURED;
  901. X        }
  902. X    }
  903. X
  904. X    /* execute the interrupt acknowledge sequence for the serial cards */
  905. X    for (seq_ptr = &fas_int_ack_seq [0]; *seq_ptr; ++seq_ptr)
  906. X    {
  907. X        port = *seq_ptr;
  908. X        ++seq_ptr;
  909. X        if (*seq_ptr & READ_PORT)
  910. X            (void) inb (port);
  911. X        else
  912. X            (void) outb (port, *seq_ptr);
  913. X    }
  914. X
  915. X#if defined (NEED_PUT_GETCHAR)
  916. X    fip = &fas_internals [0];
  917. X    fip->mcr &= ~fip->modem.m.di;
  918. X    fas_first_outb (fip, MDM_CTL_PORT, fip->mcr |= INITIAL_MDM_CONTROL);
  919. X
  920. X    fip->lcr = INITIAL_LINE_CONTROL;
  921. X    fas_outb (fip, LINE_CTL_PORT, fip->lcr | LC_ENABLE_DIVISOR);
  922. X    fas_outb (fip, DIVISOR_LSB_PORT, INITIAL_BAUD_RATE);
  923. X    fas_outb (fip, DIVISOR_MSB_PORT, (INITIAL_BAUD_RATE) >> 8);
  924. X    fas_outb (fip, LINE_CTL_PORT, fip->lcr);
  925. X#endif
  926. X
  927. X#if defined (SCO) || defined (XENIX)
  928. X    for (unit = 0; unit < fas_physical_units; ++unit)
  929. X        (void) printcfg ("fas", (uint) ((ushort) (fas_port [unit])), 7,
  930. X                    -1, -1,
  931. X                    "unit=%d type=%c release=2.10.0",
  932. X                    unit, port_stat [unit]);
  933. X#else
  934. X    port_stat [unit] = '\0';
  935. X    (void) printf ("\nFAS 2.10.0 async driver: Unit 0-%d init state is [%s]\n\n",
  936. X            unit - 1,
  937. X            port_stat);
  938. X#endif
  939. X    return (0);
  940. X}
  941. X
  942. X/* Open a tty line. This function is called for every open, as opposed
  943. X   to the fasclose function which is called only with the last close.
  944. X   (called at SPL0)
  945. X*/
  946. Xint
  947. Xfasopen (dev, flag)
  948. Xint    dev;
  949. Xint    flag;
  950. X{
  951. X    register struct fas_internals    *fip;
  952. X    register struct tty    *ttyp;
  953. X    register n_ushort    open_mode;
  954. X    uint    unit;
  955. X    bool    have_lock;
  956. X    int    old_level;
  957. X
  958. X    /* check for valid port number */
  959. X    if ((unit = GET_UNIT (dev)) >= fas_physical_units)
  960. X    {
  961. X        u.u_error = ENXIO;
  962. X        return (-1);
  963. X    }
  964. X
  965. X    fip = fas_internals_ptr [unit];
  966. X
  967. X    /* was the port present at init time ? */
  968. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  969. X    {
  970. X        u.u_error = ENXIO;
  971. X        return (-1);
  972. X    }
  973. X
  974. X    open_mode = GET_OPEN_MODE (dev);
  975. X    have_lock = FALSE;
  976. X    old_level = SPLINT ();
  977. X
  978. X    /* loop until we've got the device lock and, owning the lock, we've
  979. X       checked whether the current open mode permits us to open the
  980. X       device
  981. X    */
  982. X    for (;;)
  983. X    {
  984. X        /* If this is a getty open, the FNDELAY flag is not set,
  985. X           and the device is already open for dialout, wait until
  986. X           device is closed.
  987. X        */
  988. X        while ((open_mode & OS_OPEN_FOR_GETTY)
  989. X#if defined (FNONBLOCK)
  990. X                && !(flag & (FNDELAY | FNONBLOCK))
  991. X#else
  992. X                && !(flag & FNDELAY)
  993. X#endif
  994. X                && (fip->o_state & OS_OPEN_FOR_DIALOUT))
  995. X        {
  996. X            if (have_lock)
  997. X            {
  998. X                release_device_lock (fip);
  999. X                have_lock = FALSE;
  1000. X            }
  1001. X            (void) sleep ((caddr_t) &fip->o_state, TTIPRI);
  1002. X        }
  1003. X        
  1004. X        /* If the device is already open and another open uses a
  1005. X           different open mode or if a getty open waits for carrier
  1006. X           and doesn't allow parallel dialout opens, return with
  1007. X           EBUSY error.
  1008. X        */
  1009. X        if ((fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
  1010. X                    ? (OS_OPEN_STATES | OS_WAIT_OPEN)
  1011. X                    : (OS_OPEN_STATES | OS_NO_DIALOUT)))
  1012. X            && ((flag & FEXCL)
  1013. X                || ((open_mode ^ fip->o_state) & (u.u_uid
  1014. X                            ? OS_TEST_MASK
  1015. X                            : OS_SU_TEST_MASK))))
  1016. X        {
  1017. X            if (have_lock)
  1018. X                release_device_lock (fip);
  1019. X            (void) splx (old_level);
  1020. X            u.u_error = EBUSY;
  1021. X            return (-1);
  1022. X        }
  1023. X
  1024. X        /* If device is already open and the FAPPEND flag is set,
  1025. X           flush the output buffers. This may be used to release
  1026. X           processes that got stuck in fasclose () during an
  1027. X           exit () call.
  1028. X        */
  1029. X        if ((fip->o_state & OS_OPEN_STATES) && (flag & FAPPEND))
  1030. X        {
  1031. X            flag &= ~FAPPEND;    /* flush only once */
  1032. X            (void) SPLWRK ();
  1033. X            (void) ttyflush (fip->tty, FWRITE);
  1034. X            (void) SPLINT ();
  1035. X        }
  1036. X
  1037. X        /* if we don't have the device lock, yet, try to get it */
  1038. X        if (!have_lock)
  1039. X        {
  1040. X            if (fip->device_flags.i & DF_DEVICE_LOCKED)
  1041. X            {
  1042. X                get_device_lock (fip, TTIPRI);
  1043. X                have_lock = TRUE;
  1044. X                /* we had to sleep for some time to get the
  1045. X                   lock, therefore, re-check whether the
  1046. X                   current open mode still permits us to
  1047. X                   open the device
  1048. X                */
  1049. X                continue;
  1050. X            }
  1051. X            else
  1052. X                get_device_lock (fip, TTIPRI);
  1053. X        }
  1054. X
  1055. X        break;
  1056. X    }
  1057. X
  1058. X    /* disable subsequent opens */
  1059. X    if (flag & FEXCL)
  1060. X        open_mode |= OS_EXCLUSIVE_OPEN_1;
  1061. X
  1062. X    /* set up pointer to tty structure */
  1063. X    ttyp = (open_mode & OS_OPEN_FOR_GETTY)
  1064. X        ? fas_tty_ptr [unit + fas_physical_units]
  1065. X        : fas_tty_ptr [unit];
  1066. X
  1067. X    /* things to do on first open only */
  1068. X    if (!(fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
  1069. X                ? (OS_OPEN_STATES | OS_WAIT_OPEN)
  1070. X                : OS_OPEN_STATES)))
  1071. X    {
  1072. X        /* clear carrier of getty device */
  1073. X        if (fip->o_state & OS_WAIT_OPEN)
  1074. X            fip->tty->t_state &= ~CARR_ON;
  1075. X        /* init data structures */
  1076. X        fip->tty = ttyp;
  1077. X        (void) ttinit (ttyp);
  1078. X        ttyp->t_proc = fas_proc;
  1079. X        fip->po_state = fip->o_state;
  1080. X        fip->o_state = open_mode & ~OS_OPEN_STATES;
  1081. X        fas_open_device (fip);        /* open physical device */
  1082. X
  1083. X        /* allow pending tty interrupts */
  1084. X        (void) SPLWRK ();
  1085. X        (void) SPLINT ();
  1086. X    }
  1087. X
  1088. X    /* If getty open and the FNDELAY flag is not set,
  1089. X       block and wait for carrier if device not yet open.
  1090. X    */
  1091. X    if ((open_mode & OS_OPEN_FOR_GETTY)
  1092. X#if defined (FNONBLOCK)
  1093. X            && !(flag & (FNDELAY | FNONBLOCK)))
  1094. X#else
  1095. X            && !(flag & FNDELAY))
  1096. X#endif
  1097. X    {
  1098. X        /* sleep while open for dialout or no carrier */
  1099. X        while ((fip->o_state & OS_OPEN_FOR_DIALOUT)
  1100. X            || !(ttyp->t_state & (ISOPEN | CARR_ON)))
  1101. X        {
  1102. X            ttyp->t_state |= WOPEN;
  1103. X            release_device_lock (fip);
  1104. X            (void) sleep ((caddr_t) &ttyp->t_canq, TTIPRI);
  1105. X            get_device_lock (fip, TTIPRI);
  1106. X            ttyp->t_state &= ~WOPEN;
  1107. X        }
  1108. X    }
  1109. X
  1110. X    /* we can't have concurrent ISOPEN and WOPEN states, so
  1111. X       wake up gettys as we are about to set the ISOPEN flag
  1112. X    */
  1113. X    if (ttyp->t_state & WOPEN)
  1114. X        (void) wakeup ((caddr_t) &ttyp->t_canq);
  1115. X
  1116. X    (*linesw [ttyp->t_line].l_open) (ttyp);
  1117. X
  1118. X    /* set open type flags */
  1119. X    fip->o_state = open_mode;
  1120. X
  1121. X    release_device_lock (fip);
  1122. X    (void) splx (old_level);
  1123. X    return (0);
  1124. X}
  1125. X
  1126. X/* Close a tty line. This is only called if there is no other
  1127. X   concurrent open left. A blocked getty open is not counted as
  1128. X   a concurrent open because in this state it isn't really open.
  1129. X   (called at SPL0)
  1130. X*/
  1131. Xint
  1132. Xfasclose (dev)
  1133. Xint    dev;
  1134. X{
  1135. X    register struct fas_internals    *fip;
  1136. X    register struct tty    *ttyp;
  1137. X    register n_ushort    open_mode;
  1138. X    uint    unit;
  1139. X    bool    was_signal = FALSE;
  1140. X    int    old_level;
  1141. X
  1142. X    fip = fas_internals_ptr [unit = GET_UNIT (dev)];
  1143. X
  1144. X    /* set up pointer to tty structure */
  1145. X    ttyp = ((open_mode = GET_OPEN_MODE (dev)) & OS_OPEN_FOR_GETTY)
  1146. X        ? fas_tty_ptr [unit + fas_physical_units]
  1147. X        : fas_tty_ptr [unit];
  1148. X    
  1149. X    old_level = SPLINT ();
  1150. X    get_device_lock (fip, PZERO - 1);
  1151. X
  1152. X    if ((fip->o_state == OS_DEVICE_CLOSED)
  1153. X            || ((open_mode & OS_OPEN_FOR_GETTY)
  1154. X                && (fip->o_state & OS_OPEN_FOR_DIALOUT)
  1155. X                && (fip->po_state == OS_DEVICE_CLOSED)))
  1156. X    {
  1157. X        /* device is not open on the driver level */
  1158. X        release_device_lock (fip);
  1159. X        (void) splx (old_level);
  1160. X        return (0);
  1161. X    }
  1162. X
  1163. X    if (!((open_mode & OS_OPEN_FOR_GETTY)
  1164. X                && (fip->o_state & OS_OPEN_FOR_DIALOUT)))
  1165. X    {
  1166. X        /* wait for buffer drain and catch interrupts */
  1167. X        while ((ttyp->t_state & CARR_ON) && (ttyp->t_outq.c_cc
  1168. X                    || (ttyp->t_state & (BUSY | TIMEOUT))))
  1169. X        {
  1170. X            ttyp->t_state |= TTIOW;
  1171. X            if (sleep ((caddr_t) &ttyp->t_oflag, was_signal
  1172. X                            ? PZERO - 1
  1173. X                            : TTOPRI | PCATCH))
  1174. X            {
  1175. X                /* caught signal */
  1176. X                was_signal = TRUE;
  1177. X                ttyp->t_state &= ~TTIOW;
  1178. X                (void) SPLWRK ();
  1179. X                (void) ttyflush (ttyp, FWRITE);
  1180. X                (void) SPLINT ();
  1181. X            }
  1182. X        }
  1183. X
  1184. X        /* block transmitter and wait until it is
  1185. X           empty
  1186. X        */
  1187. X        fip->device_flags.s |= DF_XMIT_LOCKED;
  1188. X        while (fip->device_flags.i & (DF_XMIT_BUSY
  1189. X                        | DF_XMIT_BREAK
  1190. X                        | DF_GUARD_TIMEOUT))
  1191. X            (void) sleep ((caddr_t) &fip->device_flags.i,
  1192. X                                PZERO - 1);
  1193. X
  1194. X        ttyp->t_state &= ~(WOPEN | CARR_ON);
  1195. X        /* disable receiver data interrupts */
  1196. X        if (fip->device_flags.i & DF_RDI_ENABLED)
  1197. X            fas_rdi_disable (fip);
  1198. X        /* re-link fas_internals structure */
  1199. X        fas_pos_by_speed (fip);
  1200. X        (void) SPLWRK ();
  1201. X        (void) ttyflush (ttyp, FREAD | FWRITE);
  1202. X        (void) SPLINT ();
  1203. X    }
  1204. X    else
  1205. X        ttyp->t_state &= ~(WOPEN | CARR_ON);
  1206. X
  1207. X    (*linesw [ttyp->t_line].l_close) (ttyp);
  1208. X
  1209. X    if (open_mode & OS_OPEN_FOR_GETTY)
  1210. X    {
  1211. X        if (!(fip->o_state & OS_OPEN_FOR_DIALOUT))
  1212. X        {
  1213. X            fas_close_device (fip);
  1214. X            fip->o_state = OS_DEVICE_CLOSED;
  1215. X        }
  1216. X        else    /* a parallel dialout open is active */
  1217. X            fip->po_state = OS_DEVICE_CLOSED;
  1218. X    }
  1219. X    else
  1220. X    {
  1221. X        fas_close_device (fip);
  1222. X        fip->o_state = OS_DEVICE_CLOSED;
  1223. X        /* If there is a waiting getty open on
  1224. X           this port, reopen the physical device.
  1225. X        */
  1226. X        if (fip->po_state & OS_WAIT_OPEN)
  1227. X        {
  1228. X            /* get the getty version of the
  1229. X               tty structure
  1230. X            */
  1231. X            fip->tty = fas_tty_ptr [unit + fas_physical_units];
  1232. X            fip->o_state = fip->po_state;
  1233. X            fip->po_state = OS_DEVICE_CLOSED;
  1234. X            if (!(fip->device_flags.i & DF_DO_HANGUP))
  1235. X                fas_open_device (fip);
  1236. X        }
  1237. X
  1238. X        /* wake up getty open (if any) */
  1239. X        (void) wakeup ((caddr_t) &fip->o_state);
  1240. X    }
  1241. X
  1242. X    if (!(fip->device_flags.i & DF_DO_HANGUP))
  1243. X        release_device_lock (fip);
  1244. X
  1245. X    (void) splx (old_level);
  1246. X
  1247. X    if (was_signal)
  1248. X#if defined (SVR4)
  1249. X        longjmp (&u.u_qsav);
  1250. X#else
  1251. X        longjmp (u.u_qsav);
  1252. X#endif
  1253. X    
  1254. X    return (0);
  1255. X}
  1256. X
  1257. X/* Read characters from the input buffer.
  1258. X   (called at SPL0)
  1259. X*/
  1260. Xint
  1261. Xfasread (dev)
  1262. Xint    dev;
  1263. X{
  1264. X    register struct fas_internals    *fip;
  1265. X    register struct tty    *ttyp;
  1266. X
  1267. X    fip = fas_internals_ptr [GET_UNIT (dev)];
  1268. X    ttyp = fip->tty;
  1269. X
  1270. X    (*linesw [ttyp->t_line].l_read) (ttyp);
  1271. X    return (0);
  1272. X}
  1273. X
  1274. X/* Write characters to the output buffer.
  1275. X   (called at SPL0)
  1276. X*/
  1277. Xint
  1278. Xfaswrite (dev)
  1279. Xint    dev;
  1280. X{
  1281. X    register struct fas_internals    *fip;
  1282. X    register struct tty    *ttyp;
  1283. X
  1284. X    fip = fas_internals_ptr [GET_UNIT (dev)];
  1285. X    ttyp = fip->tty;
  1286. X
  1287. X    (*linesw [ttyp->t_line].l_write) (ttyp);
  1288. X    return (0);
  1289. X}
  1290. X
  1291. X/* Process ioctl calls.
  1292. X   (called at SPL0)
  1293. X*/
  1294. Xint
  1295. Xfasioctl (dev, cmd, arg3, arg4)
  1296. Xint    dev;
  1297. Xint    cmd;
  1298. Xunion ioctl_arg    arg3;
  1299. Xint    arg4;
  1300. X{
  1301. X    register struct fas_internals    *fip;
  1302. X    register struct tty    *ttyp;
  1303. X    int    v86_cmd, v86_data;
  1304. X    int    old_level;
  1305. X    REGVAR;
  1306. X
  1307. X    fip = fas_internals_ptr [GET_UNIT (dev)];
  1308. X    ttyp = fip->tty;
  1309. X
  1310. X    /* process ioctl commands */
  1311. X    switch (cmd)
  1312. X    {
  1313. X#if defined (HAVE_VPIX)
  1314. X        case AIOCINTTYPE:    /* set pseudorupt type */
  1315. X            switch (arg3.iarg)
  1316. X            {
  1317. X                case V86VI_KBD:
  1318. X                case V86VI_SERIAL0:
  1319. X                case V86VI_SERIAL1:
  1320. X                    old_level = SPLINT ();
  1321. X                    fip->v86_intmask = arg3.iarg;
  1322. X                    (void) splx (old_level);
  1323. X                    break;
  1324. X
  1325. X                default:
  1326. X                    old_level = SPLINT ();
  1327. X                    fip->v86_intmask = V86VI_SERIAL0;
  1328. X                    (void) splx (old_level);
  1329. X                    break;
  1330. X            }
  1331. X            break;
  1332. X
  1333. X        case AIOCDOSMODE:    /* enable dos mode */
  1334. X            if (!(fip->iflag & DOSMODE))
  1335. X            {
  1336. X                old_level = SPLINT ();
  1337. X                fip->v86_proc = u.u_procp->p_v86;
  1338. X                if (!(fip->v86_intmask))
  1339. X                    fip->v86_intmask = V86VI_SERIAL0;
  1340. X                ttyp->t_iflag |= DOSMODE;
  1341. X                if (fip->v86_intmask != V86VI_KBD)
  1342. X                    ttyp->t_cflag |= CLOCAL;
  1343. X                fas_param (fip, SOFT_INIT);
  1344. X                (void) splx (old_level);
  1345. X            }
  1346. X            u.u_rval1 = 0;
  1347. X            break;
  1348. X
  1349. X        case AIOCNONDOSMODE:    /* disable dos mode */
  1350. X            if (fip->iflag & DOSMODE)
  1351. X            {
  1352. X                old_level = SPLINT ();
  1353. X                fip->v86_proc = (v86_t *) NULL;
  1354. X                fip->v86_intmask = 0;
  1355. X                ttyp->t_iflag &= ~DOSMODE;
  1356. X                if (fip->flow_flags.i & FF_RXFER_STOPPED)
  1357. X                {
  1358. X                    fip->flow_flags.s &= ~FF_RXFER_STOPPED;
  1359. X                    /* schedule character transfer
  1360. X                       to UNIX buffer
  1361. X                    */
  1362. X                    if (fip->recv_ring_cnt)
  1363. X                        event_sched (fip, EF_DO_RXFER);
  1364. X                }
  1365. X                fip->lcr &= ~LC_SET_BREAK_LEVEL;
  1366. X                fas_param (fip, HARD_INIT);
  1367. X                (void) splx (old_level);
  1368. X            }
  1369. X            u.u_rval1 = 0;
  1370. X            break;
  1371. X
  1372. X        case AIOCSERIALOUT:    /* setup port registers for dos */
  1373. X            if (fip->iflag & DOSMODE)
  1374. X            {
  1375. X                /* wait until output is done */
  1376. X                old_level = SPLINT ();
  1377. X                while (ttyp->t_outq.c_cc
  1378. X                    || (ttyp->t_state & (BUSY | TIMEOUT)))
  1379. X                {
  1380. X                    ttyp->t_state |= TTIOW;
  1381. X                    (void) sleep ((caddr_t) &ttyp->t_oflag,
  1382. X                                    TTOPRI);
  1383. X                }
  1384. X
  1385. X                /* block transmitter and wait until it is
  1386. X                   empty
  1387. X                */
  1388. X                fip->device_flags.s |= DF_XMIT_LOCKED;
  1389. X                while (fip->device_flags.i & (DF_XMIT_BUSY
  1390. X                            | DF_XMIT_BREAK
  1391. X                            | DF_GUARD_TIMEOUT))
  1392. X                    (void) sleep ((caddr_t) &fip->
  1393. X                                device_flags.i,
  1394. X                            PZERO - 1);
  1395. X                (void) splx (old_level);
  1396. X
  1397. X                /* get port write command */
  1398. X                v86_cmd = fubyte (arg3.cparg);
  1399. X                /* set divisor lsb requested */
  1400. X                if (v86_cmd & SIO_MASK (SO_DIVLLSB))
  1401. X                {
  1402. X                    v86_data = fubyte (arg3.cparg
  1403. X                                + SO_DIVLLSB);
  1404. X                    old_level = SPLINT ();
  1405. X                    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
  1406. X                            | LC_ENABLE_DIVISOR);
  1407. X                    fas_outb (fip, DIVISOR_LSB_PORT, v86_data);
  1408. X                    fas_outb (fip, LINE_CTL_PORT, fip->lcr
  1409. X                            & ~LC_ENABLE_DIVISOR);
  1410. X                    (void) splx (old_level);
  1411. X                }
  1412. X                /* set divisor msb requested */
  1413. X                if (v86_cmd & SIO_MASK (SO_DIVLMSB))
  1414. X                {
  1415. X                    v86_data = fubyte (arg3.cparg
  1416. X                                + SO_DIVLMSB);
  1417. X                    old_level = SPLINT ();
  1418. X                    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
  1419. X                            | LC_ENABLE_DIVISOR);
  1420. X                    fas_outb (fip, DIVISOR_MSB_PORT, v86_data);
  1421. X                    fas_outb (fip, LINE_CTL_PORT, fip->lcr
  1422. X                            & ~LC_ENABLE_DIVISOR);
  1423. X                    (void) splx (old_level);
  1424. X                }
  1425. X                /* set lcr requested */
  1426. X                if (v86_cmd & SIO_MASK (SO_LCR))
  1427. X                {
  1428. X                    v86_data = fubyte (arg3.cparg + SO_LCR);
  1429. X                    old_level = SPLINT ();
  1430. X                    fip->lcr = v86_data
  1431. X                            & ~LC_ENABLE_DIVISOR;
  1432. X                    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
  1433. X                    (void) splx (old_level);
  1434. X                }
  1435. X                /* set mcr requested */
  1436. X                if (v86_cmd & SIO_MASK (SO_MCR))
  1437. X                {
  1438. X                    v86_data = fubyte (arg3.cparg + SO_MCR);
  1439. X                    old_level = SPLINT ();
  1440. X                    /* virtual dtr processing */
  1441. X                    if (v86_data & MC_SET_DTR)
  1442. X                    {
  1443. X                        fip->device_flags.s
  1444. X                            |= DF_MODEM_ENABLED;
  1445. X                        fip->mcr |= (fip->o_state
  1446. X                                & OS_WAIT_OPEN)
  1447. X                            ? fip->modem.m.ei
  1448. X                            : fip->modem.m.eo;
  1449. X                    }
  1450. X                    else
  1451. X                    {
  1452. X                        fip->device_flags.s
  1453. X                            &= ~DF_MODEM_ENABLED;
  1454. X                        fip->mcr &= (fip->o_state
  1455. X                                & OS_WAIT_OPEN)
  1456. X                            ? ~fip->modem.m.ei
  1457. X                            : ~fip->modem.m.eo;
  1458. X                    }
  1459. X                    /* virtual rts processing */
  1460. X                    if (fip->flow_flags.i
  1461. X                            & FF_HWI_HANDSHAKE)
  1462. X                    {
  1463. X                      if (v86_data & MC_SET_RTS)
  1464. X                      {
  1465. X                        if (fip->flow_flags.i
  1466. X                            & FF_RXFER_STOPPED)
  1467. X                        {
  1468. X                          fip->flow_flags.s
  1469. X                            &= ~FF_RXFER_STOPPED;
  1470. X                          /* schedule character transfer
  1471. X                             to UNIX buffer
  1472. X                          */
  1473. X                          if (fip->recv_ring_cnt)
  1474. X                            event_sched (fip,
  1475. X                                EF_DO_RXFER);
  1476. X                        }
  1477. X                      }
  1478. X                      else
  1479. X                        fip->flow_flags.s
  1480. X                            |= FF_RXFER_STOPPED;
  1481. X                    }
  1482. X                    else if (!(fip->flow_flags.i
  1483. X                            & FF_HDX_HANDSHAKE))
  1484. X                    {
  1485. X                        if (v86_data & MC_SET_RTS)
  1486. X                            fip->mcr
  1487. X                              |= fip->flow.m.hc;
  1488. X                        else
  1489. X                            fip->mcr
  1490. X                              &= ~fip->flow.m.hc;
  1491. X                    }
  1492. X                    fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1493. X                    (void) splx (old_level);
  1494. X                }
  1495. X
  1496. X                old_level = SPLINT ();
  1497. X                /* enable transmitter and restart output */
  1498. X                fip->device_flags.s &= ~DF_XMIT_LOCKED;
  1499. X                fas_xproc (fip);
  1500. X                (void) splx (old_level);
  1501. X            }
  1502. X            break;
  1503. X
  1504. X        case AIOCSERIALIN:    /* read port registers for dos */
  1505. X            if (fip->iflag & DOSMODE)
  1506. X            {
  1507. X                v86_cmd = fubyte (arg3.cparg);
  1508. X                if (v86_cmd & SIO_MASK (SI_MSR))
  1509. X                {
  1510. X                    (void) subyte (arg3.cparg + SI_MSR,
  1511. X                            ((fip->flow_flags.i
  1512. X                              & FF_HWO_HANDSHAKE)
  1513. X                            ? fip->msr
  1514. X                              | fip->flow.m.oc
  1515. X                              | fip->flow.m.oe
  1516. X                            : fip->msr)
  1517. X                            & MS_ANY_PRESENT);
  1518. X                }
  1519. X            }
  1520. X            break;
  1521. X
  1522. X        case AIOCSETSS:    /* set start/stop characters */
  1523. X            old_level = SPLINT ();
  1524. X            fip->start_char =
  1525. X                ((struct termss *) &arg3.iarg)->ss_start;
  1526. X            fip->stop_char =
  1527. X                ((struct termss *) &arg3.iarg)->ss_stop;
  1528. X            (void) splx (old_level);
  1529. X            break;
  1530. X
  1531. X        case AIOCINFO:    /* show what type of device we are */
  1532. X            u.u_rval1 = ('a' << 8) | GET_UNIT (dev);
  1533. X            break;
  1534. X#endif
  1535. X#if defined (RTS_TOG)
  1536. X        case RTS_TOG:    /* set hardware handshake output */
  1537. X            if (arg3.iarg == 0)
  1538. X            {
  1539. X                /* low level */
  1540. X                old_level = SPLINT ();
  1541. X                /* set hardware handshake output only if unused */
  1542. X                if (!(fip->flow_flags.i & (FF_HWI_HANDSHAKE
  1543. X                            | FF_HDX_HANDSHAKE
  1544. X                            | FF_DEF_HHO_LOW))
  1545. X#if defined (HAVE_VPIX)
  1546. X                    && !(fip->iflag & DOSMODE)
  1547. X#endif
  1548. X                    )
  1549. X                {
  1550. X                fas_first_outb (fip, MDM_CTL_PORT,
  1551. X                        fip->mcr &= ~fip->flow.m.hc);
  1552. X                }
  1553. X                fip->flow_flags.s |= FF_DEF_HHO_LOW;
  1554. X                (void) splx (old_level);
  1555. X            }
  1556. X            else if (arg3.iarg == 1)
  1557. X            {
  1558. X                /* high level */
  1559. X                old_level = SPLINT ();
  1560. X                /* set hardware handshake output only if unused */
  1561. X                if ((fip->flow_flags.i & (FF_HWI_HANDSHAKE
  1562. X                            | FF_HDX_HANDSHAKE
  1563. X                            | FF_DEF_HHO_LOW))
  1564. X                    == FF_DEF_HHO_LOW
  1565. X#if defined (HAVE_VPIX)
  1566. X                    && !(fip->iflag & DOSMODE)
  1567. X#endif
  1568. X                    )
  1569. X                {
  1570. X                fas_first_outb (fip, MDM_CTL_PORT,
  1571. X                        fip->mcr |= fip->flow.m.hc);
  1572. X                }
  1573. X                fip->flow_flags.s &= ~FF_DEF_HHO_LOW;
  1574. X                (void) splx (old_level);
  1575. X            }
  1576. X            break;
  1577. X#endif
  1578. X        default:    /* default ioctl processing */
  1579. X            /* If it is a TCSETA* command, call fas_param ().
  1580. X               There is a bug in ttiocom with TCSELE. It
  1581. X               always tells the tty driver to reprogram the
  1582. X               port. This will cause lost input characters.
  1583. X               So we don't do it. SCO UNIX and Xenix use
  1584. X               IOC_SELECT instead of TCSELE!
  1585. X            */
  1586. X#if defined (TCSELE)
  1587. X            if (ttiocom (ttyp, cmd, arg3, arg4) && cmd != TCSELE)
  1588. X#else
  1589. X#if defined (IOC_SELECT)
  1590. X            if (ttiocom (ttyp, cmd, arg3, arg4)
  1591. X                        && cmd != IOC_SELECT)
  1592. X#else
  1593. X            if (ttiocom (ttyp, cmd, arg3, arg4))
  1594. X#endif
  1595. X#endif
  1596. X            {
  1597. X                /* reprogram the port */
  1598. X                old_level = SPLINT ();
  1599. X                fas_param (fip, SOFT_INIT);
  1600. X                (void) splx (old_level);
  1601. X            }
  1602. X            /* restart input if we are in cooked mode */
  1603. X            if (fip->recv_ring_cnt
  1604. X                && (ttyp->t_line || (ttyp->t_lflag & ICANON)))
  1605. X            {
  1606. X                old_level = SPLINT ();
  1607. X                event_sched (fip, EF_DO_RXFER);
  1608. X                (void) splx (old_level);
  1609. X            }
  1610. X            break;
  1611. X    }
  1612. X    return (0);
  1613. X}
  1614. X
  1615. X/* Pass FAS commands to the FAS multi-function procedure.
  1616. X   (called at SPL0)
  1617. X*/
  1618. Xstatic int
  1619. Xfas_proc (ttyp, arg2)
  1620. Xstruct tty    *ttyp;
  1621. Xint    arg2;
  1622. X{
  1623. X    register uint    unit;
  1624. X    int    old_level;
  1625. X
  1626. X    unit = ttyp - &fas_tty [0];
  1627. X    if (unit >= fas_physical_units)
  1628. X        unit -= fas_physical_units;
  1629. X
  1630. X    old_level = SPLINT ();
  1631. X    fas_cmd (fas_internals_ptr [unit], ttyp, arg2);
  1632. X    (void) splx (old_level);
  1633. X    return (0);
  1634. X}
  1635. X
  1636. X/* Set up a port according to the given termio structure.
  1637. X   (called at >= SPLINT)
  1638. X*/
  1639. Xstatic void
  1640. Xfas_param (fip, init_type)
  1641. Xregister struct    fas_internals    *fip;
  1642. Xint    init_type;
  1643. X{
  1644. X    register n_ushort    cflag;
  1645. X    n_ushort    fake_cflag;
  1646. X    n_ushort    divisor;
  1647. X    int    xmit_ring_size;
  1648. X    bool    do_flush;
  1649. X    int    old_level;
  1650. X    REGVAR;
  1651. X
  1652. X    cflag = fip->tty->t_cflag;
  1653. X    fip->iflag = fip->tty->t_iflag;
  1654. X    do_flush = FALSE;
  1655. X
  1656. X#if defined (HAVE_VPIX)
  1657. X    /* we don't set port registers if we are in dos mode */
  1658. X    if (fip->iflag & DOSMODE)
  1659. X    {
  1660. X        /* This is a kludge. We don't know what baud rate
  1661. X           DOS will use. Therefore, we assume a rather low
  1662. X           one to be on the safe side.
  1663. X        */
  1664. X        cflag = (cflag & ~CBAUD) | B300;
  1665. X        goto setflags2;
  1666. X    }
  1667. X#endif
  1668. X    /* Make sure that we have a valid baud rate. If we don't
  1669. X       get one, take the previous baud rate.
  1670. X    */
  1671. X    fake_cflag = (cflag & ~CBAUD)
  1672. X            | (((cflag & CBAUD) == B0)
  1673. X                ? (fip->cflag & CBAUD)
  1674. X                : (fip->device_flags.i & DF_HIGH_SPEED)
  1675. X                    ? fas_hbaud [cflag & CBAUD]
  1676. X                    : fas_baud [cflag & CBAUD]);
  1677. X
  1678. X    /* if soft init mode: don't set port registers if cflag didn't change */
  1679. X    if ((init_type == SOFT_INIT)
  1680. X        && !((cflag ^ ((fip->cflag & ~CBAUD)
  1681. X                | ((fip->device_flags.i & DF_MODEM_ENABLED)
  1682. X                    ? fas_baud [fip->cflag & CBAUD]
  1683. X                    : B0)))
  1684. X            & (CBAUD | CSIZE | CSTOPB | PARENB | PARODD)))
  1685. X    {
  1686. X        cflag = fake_cflag;
  1687. X        goto setflags;
  1688. X    }
  1689. X
  1690. X    /* hangup line if it is baud rate 0, else enable line */
  1691. X    if ((cflag & CBAUD) == B0)
  1692. X    {
  1693. X        if (fip->device_flags.i & DF_MODEM_ENABLED)
  1694. X        {
  1695. X            fip->mcr &= (fip->o_state & OS_WAIT_OPEN)
  1696. X                    ? ~fip->modem.m.ei
  1697. X                    : ~fip->modem.m.eo;
  1698. X            fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1699. X            fip->device_flags.s &= ~DF_MODEM_ENABLED;
  1700. X        }
  1701. X    }
  1702. X    else
  1703. X    {
  1704. X        if (!(fip->device_flags.i & DF_MODEM_ENABLED))
  1705. X        {
  1706. X            fip->mcr |= (fip->o_state & OS_WAIT_OPEN)
  1707. X                    ? fip->modem.m.ei
  1708. X                    : fip->modem.m.eo;
  1709. X            fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1710. X            fip->device_flags.s |= DF_MODEM_ENABLED;
  1711. X        }
  1712. X    }
  1713. X
  1714. X    cflag = fake_cflag;
  1715. X
  1716. X    /* don't change break flag */
  1717. X    fip->lcr &= LC_SET_BREAK_LEVEL;
  1718. X
  1719. X    /* set character size */
  1720. X    switch (cflag & CSIZE)
  1721. X    {
  1722. X    case CS5:
  1723. X        fip->lcr |= LC_WORDLEN_5;
  1724. X        break;
  1725. X
  1726. X    case CS6:
  1727. X        fip->lcr |= LC_WORDLEN_6;
  1728. X        break;
  1729. X
  1730. X    case CS7:
  1731. X        fip->lcr |= LC_WORDLEN_7;
  1732. X        break;
  1733. X
  1734. X    default:
  1735. X        fip->lcr |= LC_WORDLEN_8;
  1736. X        break;
  1737. X    }
  1738. X
  1739. X    /* set # of stop bits */
  1740. X    if (cflag & CSTOPB)
  1741. X        fip->lcr |= LC_STOPBITS_LONG;
  1742. X
  1743. X    /* set parity */
  1744. X    if (cflag & PARENB)
  1745. X    {
  1746. X        fip->lcr |= LC_ENABLE_PARITY;
  1747. X
  1748. X        if (!(cflag & PARODD))
  1749. X            fip->lcr |= LC_EVEN_PARITY;
  1750. X    }
  1751. X
  1752. X    /* set LCR and baud rate */
  1753. X    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr | LC_ENABLE_DIVISOR);
  1754. X    fas_outb (fip, DIVISOR_LSB_PORT,
  1755. X                divisor = (fip->device_flags.i & DF_115K)
  1756. X                        ? fas_speeds2 [cflag & CBAUD]
  1757. X                        : fas_speeds1 [cflag & CBAUD]);
  1758. X    fas_outb (fip, DIVISOR_MSB_PORT, divisor >> 8);
  1759. X    fas_outb (fip, LINE_CTL_PORT, fip->lcr);
  1760. X
  1761. Xsetflags:
  1762. X    /* check dynamic xmit ring buffer size against boundaries,
  1763. X       modify it if necessary and update the fas_internals structure
  1764. X    */
  1765. X    if ((xmit_ring_size = ((fip->device_flags.i & DF_115K)
  1766. X                ? fas_xbuf_size2 [cflag & CBAUD]
  1767. X                : fas_xbuf_size1 [cflag & CBAUD])
  1768. X                - tthiwat [fas_baud [cflag & CBAUD]])
  1769. X            < MAX_OUTPUT_FIFO_SIZE * 2)
  1770. X    {
  1771. Xsetflags2:
  1772. X        xmit_ring_size = MAX_OUTPUT_FIFO_SIZE * 2;
  1773. X    }
  1774. X    fip->xmit_ring_size = (xmit_ring_size > XMIT_BUFF_SIZE)
  1775. X                ? XMIT_BUFF_SIZE
  1776. X                : xmit_ring_size;
  1777. X
  1778. X    /* disable modem control signals if required by open mode */
  1779. X    if (fip->o_state & OS_CLOCAL)
  1780. X        cflag |= CLOCAL;
  1781. X
  1782. X    /* Select hardware handshake depending on the minor device
  1783. X       number and various termio flags (if they are available).
  1784. X    */
  1785. X    fip->flow_flags.s &= ~(FF_HWO_HANDSHAKE
  1786. X                | FF_HWI_HANDSHAKE
  1787. X                | FF_HDX_HANDSHAKE);
  1788. X    if (fip->o_state & (OS_HWO_HANDSHAKE | OS_HWI_HANDSHAKE
  1789. X                    | OS_HDX_HANDSHAKE))
  1790. X    {
  1791. X        if (fip->o_state & OS_HWO_HANDSHAKE)
  1792. X            fip->flow_flags.s |= FF_HWO_HANDSHAKE;
  1793. X        if (fip->o_state & OS_HWI_HANDSHAKE)
  1794. X            fip->flow_flags.s |= FF_HWI_HANDSHAKE;
  1795. X        if (fip->o_state & OS_HDX_HANDSHAKE)
  1796. X            fip->flow_flags.s |= FF_HDX_HANDSHAKE;
  1797. X    }
  1798. X    else
  1799. X    {
  1800. X#if defined (CTSXON) && defined (RTSXOFF)    /* SysVr4 compatibility */
  1801. X        if (fip->iflag & CTSXON)
  1802. X            fip->flow_flags.s |= FF_HWO_HANDSHAKE;
  1803. X        if (fip->iflag & RTSXOFF)
  1804. X            fip->flow_flags.s |= FF_HWI_HANDSHAKE;
  1805. X#else
  1806. X#if defined (CTSFLOW) && defined (RTSFLOW)    /* SCO Xenix compatibility */
  1807. X        if (!(cflag & CLOCAL) || (fip->flow_flags.i & FF_NEW_CTSRTS))
  1808. X        {
  1809. X#if defined (CRTSFL)    /* SCO UNIX 3.2.4 compatibility */
  1810. X            if ((cflag & (CRTSFL | CTSFLOW | RTSFLOW)) == CRTSFL)
  1811. X                fip->flow_flags.s |= FF_HWO_HANDSHAKE
  1812. X                            | FF_HWI_HANDSHAKE;
  1813. X            else
  1814. X#endif
  1815. X            {
  1816. X                if (cflag & CTSFLOW)
  1817. X                    fip->flow_flags.s |= FF_HWO_HANDSHAKE;
  1818. X                if (cflag & RTSFLOW)
  1819. X                    fip->flow_flags.s |= (fip->flow_flags.i
  1820. X                                & FF_NEW_CTSRTS)
  1821. X                                ? FF_HWI_HANDSHAKE
  1822. X                                : FF_HDX_HANDSHAKE;
  1823. X            }
  1824. X        }
  1825. X#endif
  1826. X#endif
  1827. X    }
  1828. X
  1829. X    /* Determine whether to enable MSI, or not.
  1830. X       Set the interrupt enable port accordingly.
  1831. X    */
  1832. X#if defined (HAVE_VPIX)
  1833. X    if ((cflag & CLOCAL) && !(fip->flow_flags.i & FF_HWO_HANDSHAKE)
  1834. X        && !(fip->iflag & DOSMODE))
  1835. X#else
  1836. X    if ((cflag & CLOCAL) && !(fip->flow_flags.i & FF_HWO_HANDSHAKE))
  1837. X#endif
  1838. X    {
  1839. X        if (fip->device_flags.i & DF_MSI_ENABLED)
  1840. X            fas_msi_disable (fip);
  1841. X    }
  1842. X    else
  1843. X    {
  1844. X        if (!(fip->device_flags.i & DF_MSI_ENABLED))
  1845. X            fas_msi_enable (fip);
  1846. X    }
  1847. X
  1848. X    /* Fake the carrier detect state flag if CLOCAL mode or if
  1849. X       requested by open mode.
  1850. X    */
  1851. X    if (!(~fip->msr & fip->modem.m.ca)
  1852. X        || (cflag & CLOCAL)
  1853. X        || ((fip->o_state & OS_FAKE_CARR_ON)
  1854. X            && (!(fip->o_state & OS_OPEN_STATES)
  1855. X                || (fip->tty->t_state & CARR_ON))))
  1856. X        fip->tty->t_state |= CARR_ON;
  1857. X    else if (fip->tty->t_state & CARR_ON)
  1858. X    {
  1859. X        fip->tty->t_state &= ~CARR_ON;
  1860. X        /* flush buffers on carrier drop */
  1861. X        do_flush = TRUE;
  1862. X    }
  1863. X
  1864. X    if ((fip->tty->t_state & CARR_ON) && (cflag & CREAD))
  1865. X    {
  1866. X        /* enable receiver data interrupts */
  1867. X        if (!(fip->device_flags.i & DF_RDI_ENABLED))
  1868. X            fas_rdi_enable (fip);
  1869. X    }
  1870. X    else
  1871. X    {
  1872. X        /* disable receiver data interrupts */
  1873. X        if (fip->device_flags.i & DF_RDI_ENABLED)
  1874. X            fas_rdi_disable (fip);
  1875. X    }
  1876. X
  1877. X#if defined (XCLUDE)    /* SYSV 3.2 Xenix compatibility */
  1878. X    /* Permit exclusive use of this device. */
  1879. X    if (cflag & XCLUDE)
  1880. X        fip->o_state |= OS_EXCLUSIVE_OPEN_2;
  1881. X    else
  1882. X        fip->o_state &= ~OS_EXCLUSIVE_OPEN_2;
  1883. X#endif
  1884. X
  1885. X    fip->cflag = cflag;
  1886. X
  1887. X    /* re-link fas_internals structure */
  1888. X    fas_pos_by_speed (fip);
  1889. X
  1890. X    /* flush buffers if necessary */
  1891. X    if (do_flush)
  1892. X    {
  1893. X        /* lock transmitter */
  1894. X        fip->device_flags.s |= DF_XMIT_LOCKED;
  1895. X        old_level = SPLWRK ();
  1896. X        (void) ttyflush (fip->tty, FREAD | FWRITE);
  1897. X        (void) splx (old_level);
  1898. X        /* enable transmitter */
  1899. X        fip->device_flags.s &= ~DF_XMIT_LOCKED;
  1900. X    }
  1901. X
  1902. X    /* setup handshake flags */
  1903. X#if defined (HAVE_VPIX)
  1904. X    if ((fip->flow_flags.i & (FF_HWI_HANDSHAKE | FF_HDX_HANDSHAKE))
  1905. X        || !(fip->iflag & DOSMODE))
  1906. X#endif
  1907. X    {
  1908. X        /* clear flow control output bits */
  1909. X        fip->mcr &= ~(fip->flow.m.ic | fip->flow.m.hc);
  1910. X        fip->flow_flags.s &= ~(FF_HWI_STARTED | FF_HDX_STARTED);
  1911. X
  1912. X        /* raise flow control bits if necessary */
  1913. X        if (fip->flow_flags.i & FF_HWI_HANDSHAKE)
  1914. X        {
  1915. X            if (fip->recv_ring_cnt < HW_LOW_WATER)
  1916. X            {
  1917. X                fip->mcr |= fip->flow.m.ic;
  1918. X                fip->flow_flags.s |= FF_HWI_STARTED;
  1919. X            }
  1920. X        }
  1921. X        else if (fip->flow_flags.i & FF_HDX_HANDSHAKE)
  1922. X        {
  1923. X            if (fip->tty->t_state & BUSY)
  1924. X            {
  1925. X                fip->mcr |= fip->flow.m.hc;
  1926. X                fip->flow_flags.s |= FF_HDX_STARTED;
  1927. X            }
  1928. X        }
  1929. X        else if (!(fip->flow_flags.i & FF_DEF_HHO_LOW))
  1930. X            fip->mcr |= fip->flow.m.hc;
  1931. X
  1932. X        fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1933. X    }
  1934. X
  1935. X    /* set hardware output flow control flags */
  1936. X    if (!(~fip->new_msr & fip->flow.m.oc)
  1937. X            || (~fip->new_msr & fip->flow.m.oe)
  1938. X            || !(fip->flow_flags.i & FF_HWO_HANDSHAKE))
  1939. X        fip->flow_flags.s &= ~FF_HWO_STOPPED;
  1940. X    else
  1941. X        fip->flow_flags.s |= FF_HWO_STOPPED;
  1942. X
  1943. X    /* check software input flow control */
  1944. X    if (fip->flow_flags.i & FF_SWI_STOPPED)
  1945. X    {
  1946. X        if (!(fip->iflag & IXOFF)
  1947. X                || (fip->recv_ring_cnt < SW_LOW_WATER))
  1948. X            fas_send_xon (fip);
  1949. X    }
  1950. X    else
  1951. X    {
  1952. X        if ((fip->iflag & IXOFF)
  1953. X                && (fip->recv_ring_cnt > SW_HIGH_WATER))
  1954. X            fas_send_xoff (fip);
  1955. X    }
  1956. X
  1957. X    /* restart output */
  1958. X    fas_xproc (fip);
  1959. X}
  1960. X
  1961. X/* Main FAS interrupt handler. Actual character processing is splitted
  1962. X   into sub-functions.
  1963. X   (called at SPLINT)
  1964. X*/
  1965. Xint
  1966. Xfasintr (vect)
  1967. Xint    vect;
  1968. X{
  1969. X    register struct fas_internals    *fip;
  1970. X    bool    done, was_rint, was_xint, was_mint, do_xproc;
  1971. X    REGVAR;
  1972. X
  1973. X    done = TRUE;
  1974. X    was_rint = was_xint = was_mint = FALSE;
  1975. X
  1976. X    /* The 8259 interrupt controller is set up for edge trigger.
  1977. X       Therefore, we must loop until we make a complete pass without
  1978. X       getting any UARTs that are interrupting.
  1979. X    */
  1980. X    do
  1981. X    {
  1982. X        /* We need a short delay if the previous loop
  1983. X           had work to do. This is necessary to ensure
  1984. X           that even with fast CPUs the time where the
  1985. X           UART interrupt line is low between two
  1986. X           interrupts is long enough that the PIC
  1987. X           gets a proper edge to trigger a new
  1988. X           interrupt. Therefore, we read the IER of
  1989. X           the first int user because this doesn't
  1990. X           have any side effects and causes a delay
  1991. X           that is rather CPU speed independent.
  1992. X           I HATE BRAIN-DEAD HARDWARE !
  1993. X        */
  1994. X
  1995. X        if (!(fip = fas_first_int_user))
  1996. X            break;    /* false alarm: must be a spurious int */
  1997. X
  1998. X        if (!done)
  1999. X        {
  2000. X            (void) fas_first_inb (fip, INT_ENABLE_PORT);
  2001. X            done = TRUE;
  2002. X        }
  2003. X
  2004. X        /* Loop through all users of the interrupt users chain
  2005. X           and look for characters in the receiver buffer.
  2006. X           We poll the line status register regardless of
  2007. X           whether the UART has interrupted or not. This
  2008. X           synchronizes concurrently running receiver FIFOs
  2009. X           and dramatically reduces the overall interrupt
  2010. X           frequency.
  2011. X        */
  2012. X        for (; fip; fip = fip->next_int_user)
  2013. X        {
  2014. X            register n_unchar    lstatus;
  2015. Xfastloop1:
  2016. X            /* read in all the characters from the FIFO */
  2017. X            if (!(fip->device_flags.i & DF_RDI_ENABLED)
  2018. X                || (!(fip->lsr & LS_RCV_AVAIL)
  2019. X                    && !((fip->lsr = lstatus
  2020. X                        = fas_first_inb (fip,
  2021. X                            LINE_STATUS_PORT),
  2022. X                                lstatus)
  2023. X                        & LS_RCV_AVAIL)))
  2024. X            {
  2025. X                /* speed beats beauty */
  2026. X                fip = fip->next_int_user;
  2027. X                if (fip)
  2028. X                    goto fastloop1;
  2029. X                break;
  2030. X            }
  2031. X
  2032. X            done = FALSE;
  2033. X
  2034. X            /* do the character processing */
  2035. X            fas_rproc (fip);
  2036. X
  2037. X            /* schedule character transfer to UNIX buffer */
  2038. X            if (!(fip->flow_flags.i & FF_RXFER_STOPPED))
  2039. X                event_sched (fip, EF_DO_RXFER);
  2040. X
  2041. X            /* check input buffer high water marks */
  2042. X            if ((fip->recv_ring_cnt > HW_HIGH_WATER)
  2043. X                && (fip->flow_flags.i & (FF_HWI_HANDSHAKE
  2044. X                            | FF_HWI_STARTED))
  2045. X                    == (FF_HWI_HANDSHAKE | FF_HWI_STARTED))
  2046. X            {
  2047. X                fas_first_outb (fip, MDM_CTL_PORT,
  2048. X                        fip->mcr &= ~fip->flow.m.ic);
  2049. X                fip->flow_flags.s &= ~FF_HWI_STARTED;
  2050. X            }
  2051. X            if ((fip->recv_ring_cnt > SW_HIGH_WATER)
  2052. X                    && (fip->iflag & IXOFF)
  2053. X                    && !(fip->flow_flags.i & FF_SWI_STOPPED))
  2054. X                fas_send_xoff (fip);
  2055. X
  2056. X            was_rint = TRUE;
  2057. X        }
  2058. X
  2059. X        /* loop through all users of the interrupt users chain
  2060. X           and look for interrupts
  2061. X        */
  2062. X        for (fip = fas_first_int_user; fip; fip = fip->next_int_user)
  2063. X        {
  2064. Xfastloop2:
  2065. X            /* process only ports that have an interrupt
  2066. X               pending
  2067. X            */
  2068. X            if (fas_first_inb (fip, INT_ID_PORT)
  2069. X                            & II_NO_INTS_PENDING)
  2070. X            {
  2071. X                /* speed beats beauty */
  2072. X                fip = fip->next_int_user;
  2073. X                if (fip)
  2074. X                    goto fastloop2;
  2075. X                break;
  2076. X            }
  2077. X
  2078. X            done = FALSE;
  2079. X
  2080. X            {
  2081. X                register n_unchar    mstatus;
  2082. X
  2083. X                /* Has there been a polarity change on
  2084. X                   some of the modem lines ?
  2085. X                */
  2086. X                if ((fip->device_flags.i & DF_MSI_ENABLED)
  2087. X                && ((mstatus = fas_inb (fip, MDM_STATUS_PORT))
  2088. X                        & MS_ANY_DELTA))
  2089. X                {
  2090. X                /* if the same modem status line
  2091. X                   is responsible for a modem status
  2092. X                   interrupt twice during two
  2093. X                   event scheduler runs, we disable
  2094. X                   modem status interrupts until we
  2095. X                   process this interrupt in the event
  2096. X                   scheduler
  2097. X                */
  2098. X                if (mstatus & fip->new_msr & MS_ANY_DELTA)
  2099. X                {
  2100. X                    fas_msi_disable (fip);
  2101. X                    ++fas_msi_noise;
  2102. X                }
  2103. X                /* Do special RING line handling.
  2104. X                   RING generates an int only on the
  2105. X                   trailing edge.
  2106. X                */
  2107. X                mstatus = (mstatus & ~MS_RING_PRESENT)
  2108. X                    | (fip->new_msr & MS_RING_PRESENT);
  2109. X                if (mstatus & MS_RING_TEDGE)
  2110. X                    mstatus |= MS_RING_PRESENT;
  2111. X                if ((mstatus ^ fip->new_msr) & MS_ANY_PRESENT)
  2112. X                {
  2113. X                    do_xproc = FALSE;
  2114. X                    /* check hw flow flags */
  2115. X                    if (!(~mstatus & fip->flow.m.oc)
  2116. X                        || (~mstatus & fip->flow.m.oe)
  2117. X                        || !(fip->flow_flags.i
  2118. X                            & FF_HWO_HANDSHAKE))
  2119. X                    {
  2120. X                    if (fip->flow_flags.i & FF_HWO_STOPPED)
  2121. X                    {
  2122. X                        fip->flow_flags.s &=
  2123. X                            ~FF_HWO_STOPPED;
  2124. X                        do_xproc = TRUE;
  2125. X                    }
  2126. X                    }
  2127. X                    else
  2128. X                    fip->flow_flags.s |= FF_HWO_STOPPED;
  2129. X                    /* check carrier detect
  2130. X                       note: the actual carrier detect
  2131. X                             processing is done in fas_mproc ()
  2132. X                    */
  2133. X                        if (!(fip->cflag & CLOCAL)
  2134. X                        && (fip->tty->t_state & CARR_ON))
  2135. X                        {
  2136. X                    if (!(~mstatus & fip->modem.m.ca))
  2137. X                    {
  2138. X                        if (fip->flow_flags.i
  2139. X                            & FF_CARR_STOPPED)
  2140. X                        {
  2141. X                        fip->flow_flags.s &=
  2142. X                            ~FF_CARR_STOPPED;
  2143. X                        do_xproc = TRUE;
  2144. X                        }
  2145. X                    }
  2146. X                    else if (!(~fip->new_msr
  2147. X                            & fip->modem.m.ca))
  2148. X                        fip->flow_flags.s
  2149. X                            |= FF_CARR_STOPPED;
  2150. X                    }
  2151. X                    if (do_xproc)
  2152. X                    fas_xproc (fip);
  2153. X                    event_sched (fip, EF_DO_MPROC);
  2154. X                }
  2155. X                else
  2156. X                    event_sched (fip, EF_RESET_DELTA_BITS);
  2157. X                /* "or" the delta flags to prevent
  2158. X                   excessive modem status interrupts
  2159. X                */
  2160. X                fip->new_msr = mstatus | (fip->new_msr
  2161. X                                & MS_ANY_DELTA);
  2162. X                was_mint = TRUE;
  2163. X                }
  2164. X            }
  2165. X
  2166. X            {
  2167. X                register n_unchar    lstatus;
  2168. X
  2169. X                /* Is it a transmitter empty int ? */
  2170. X                if ((fip->lsr = lstatus = fas_inb (fip,
  2171. X                            LINE_STATUS_PORT),
  2172. X                                lstatus)
  2173. X                        & LS_XMIT_AVAIL)
  2174. X                {
  2175. X                if (fip->device_flags.i & DF_XMIT_BUSY)
  2176. X                {
  2177. X                    fip->device_flags.s &= ~DF_XMIT_BUSY;
  2178. X                    /* do the character processing */
  2179. X                    fas_xproc (fip);
  2180. X                    if (!(fip->device_flags.i & DF_XMIT_BUSY))
  2181. X                    {
  2182. X                    fip->device_flags.s |= DF_GUARD_TIMEOUT;
  2183. X                    fip->timeout_idx = timeout (
  2184. X                        fas_timeout,
  2185. X                        (caddr_t) fip,
  2186. X                        (fip->device_flags.i & DF_115K)
  2187. X                            ? fas_ctimes2 [fip->cflag
  2188. X                                & CBAUD]
  2189. X                            : fas_ctimes1 [fip->cflag
  2190. X                                & CBAUD]);
  2191. X                    }
  2192. X                    was_xint = TRUE;
  2193. X                }
  2194. X                }
  2195. X            }
  2196. X        }
  2197. X
  2198. X        if (!done)
  2199. X        {
  2200. X            register uint    *seq_ptr;
  2201. X            uint    port;
  2202. X
  2203. X            /* execute the interrupt acknowledge sequence for the
  2204. X               serial cards
  2205. X            */
  2206. X            seq_ptr = &fas_int_ack_seq [0];
  2207. X            if (*seq_ptr)
  2208. X            {
  2209. X                do
  2210. X                {
  2211. X                    port = *seq_ptr;
  2212. X                    ++seq_ptr;
  2213. X                    if (*seq_ptr & READ_PORT)
  2214. X                        (void) inb (port);
  2215. X                    else
  2216. X                        (void) outb (port, *seq_ptr);
  2217. X                } while (*++seq_ptr);
  2218. X            }
  2219. X        }
  2220. X    } while (!done);
  2221. X        
  2222. X    /* provide statistical infos */
  2223. X    if (was_rint)
  2224. X        ++sysinfo.rcvint;
  2225. X    if (was_xint)
  2226. X        ++sysinfo.xmtint;
  2227. X    if (was_mint)
  2228. X        ++sysinfo.mdmint;
  2229. X    return (0);
  2230. X}
  2231. X
  2232. X/* Modem status handler.
  2233. X   (called at SPLHI)
  2234. X*/
  2235. Xstatic void
  2236. Xfas_mproc (fip)
  2237. Xregister struct fas_internals    *fip;
  2238. X{
  2239. X    register n_unchar    mdm_status;
  2240. X    int    old_level;
  2241. X
  2242. X    mdm_status = fip->new_msr;
  2243. X    fip->new_msr &= ~MS_RING_PRESENT;
  2244. X
  2245. X    {
  2246. X        register struct tty    *ttyp;
  2247. X
  2248. X        ttyp = fip->tty;
  2249. X
  2250. X        /* Check the carrier detect signal and set the state flags
  2251. X           accordingly. Also, if not in clocal mode, send SIGHUP on
  2252. X           carrier loss and flush the buffers.
  2253. X        */
  2254. X        if (!(fip->cflag & CLOCAL) && (ttyp->t_state & (WOPEN | ISOPEN)))
  2255. X        {
  2256. X        if (!(~mdm_status & fip->modem.m.ca))
  2257. X        {
  2258. X            /* Wake up getty open on carrier low->high. */
  2259. X            if (!(ttyp->t_state & CARR_ON))
  2260. X            {
  2261. X                if ((ttyp->t_state |= CARR_ON) & WOPEN)
  2262. X                    (void) wakeup ((caddr_t) &ttyp->t_canq);
  2263. X                /* enable receiver data interrupts */
  2264. X                if ((fip->cflag & CREAD)
  2265. X                        && !(fip->device_flags.i
  2266. X                            & DF_RDI_ENABLED))
  2267. X                    fas_rdi_enable (fip);
  2268. X                /* re-link fas_internals structure */
  2269. X                fas_pos_by_speed (fip);
  2270. X            }
  2271. X        }
  2272. X        else
  2273. X        {
  2274. X            if (!(~fip->msr & fip->modem.m.ca))
  2275. X            {
  2276. X                ttyp->t_state &= ~CARR_ON;
  2277. X                /* disable receiver data interrupts */
  2278. X                if (fip->device_flags.i & DF_RDI_ENABLED)
  2279. X                    fas_rdi_disable (fip);
  2280. X                /* re-link fas_internals structure */
  2281. X                fas_pos_by_speed (fip);
  2282. X                old_level = SPLWRK ();
  2283. X                if (ttyp->t_pgrp)
  2284. X                {
  2285. X                    (void) signal (ttyp->t_pgrp, SIGHUP);
  2286. X#if defined (SIGCONT)
  2287. X                    /* make sure processes are awake */
  2288. X                    (void) signal (ttyp->t_pgrp, SIGCONT);
  2289. X#endif
  2290. X                }
  2291. X                (void) ttyflush (ttyp, FREAD | FWRITE);
  2292. X                (void) splx (old_level);
  2293. X            }
  2294. X        }
  2295. X        }
  2296. X    }
  2297. X
  2298. X#if defined (HAVE_VPIX)
  2299. X    if (((fip->iflag & (DOSMODE | PARMRK))
  2300. X            == (DOSMODE | PARMRK))
  2301. X        && (fip->v86_intmask != V86VI_KBD))
  2302. X    {
  2303. X        register n_unchar    vpix_status;
  2304. SHAR_EOF
  2305. true || echo 'restore of fas.c failed'
  2306. fi
  2307. echo 'End of fas210 part 3'
  2308. echo 'File fas.c is continued in part 4'
  2309. echo 4 > _shar_seq_.tmp
  2310. exit 0
  2311. -- 
  2312. Uwe Doering  |  INET : gemini@geminix.in-berlin.de
  2313. Berlin       |----------------------------------------------------------------
  2314. Germany      |  UUCP : ...!unido!fub!geminix.in-berlin.de!gemini
  2315.