home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / fas-2.11.0 / part05 < prev    next >
Text File  |  1993-10-12  |  62KB  |  2,335 lines

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