home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1844 < prev    next >
Internet Message Format  |  1990-12-28  |  62KB

  1. From: gemini@geminix.in-berlin.de (Uwe Doering)
  2. Newsgroups: comp.unix.sysv386,comp.unix.xenix.sco,alt.sources
  3. Subject: FAS 2.07 async driver, part 2/3
  4. Message-ID: <4SKJFUU@geminix.in-berlin.de>
  5. Date: 18 Sep 90 19:14:08 GMT
  6.  
  7. #!/bin/sh
  8. # this is fas207.02 (part 2 of a multipart archive)
  9. # do not concatenate these parts, unpack them in order with /bin/sh
  10. # file fas.c continued
  11. #
  12. if test ! -r _shar_seq_.tmp; then
  13.     echo 'Please unpack part 1 first!'
  14.     exit 1
  15. fi
  16. (read Scheck
  17.  if test "$Scheck" != 2; then
  18.     echo Please unpack part "$Scheck" next!
  19.     exit 1
  20.  else
  21.     exit 0
  22.  fi
  23. ) < _shar_seq_.tmp || exit 1
  24. if test ! -f _shar_wnt_.tmp; then
  25.     echo 'x - still skipping fas.c'
  26. else
  27. echo 'x - continuing file fas.c'
  28. sed 's/^X//' << 'SHAR_EOF' >> 'fas.c' &&
  29. X{
  30. X%reg    val;
  31. X    movl    val,%eax
  32. X%mem    val;
  33. X    movb    val,%al
  34. X}
  35. X
  36. Xasm    void loaddx (val)
  37. X{
  38. X%reg    val;
  39. X    movl    val,%edx
  40. X%mem    val;
  41. X    movw    val,%dx
  42. X}
  43. X
  44. Xasm    void outbyte ()
  45. X{
  46. X    outb    (%dx)
  47. X}
  48. X
  49. Xasm    int inbyte ()
  50. X{
  51. X    xorl    %eax,%eax
  52. X    inb    (%dx)
  53. X}
  54. X
  55. X/* The port parameter of the `outb' macro must be one of the predefined
  56. X   port macros from `fas.h' or a simple uint variable (no indirection
  57. X   is allowed). Additionally, `fip' must be a register variable in the
  58. X   functions where `outb' is used. This prevents the destruction of the
  59. X   `eax' CPU register while loading the `edx' register with the port
  60. X   address. This is highly compiler implementation specific.
  61. X*/
  62. X#define outb(port,val) (regvar = (val), loadal (regvar), regvar = (port), loaddx (regvar), outbyte ())
  63. X
  64. X#define inb(port) (regvar = (port), loaddx (regvar), inbyte ())
  65. X
  66. X#define REGVAR register uint    regvar
  67. X
  68. X/* This function inserts the address optimization assembler pseudo-op
  69. X   wherever called.
  70. X*/
  71. X
  72. Xasm    void optim ()
  73. X{
  74. X    .optim
  75. X}
  76. X
  77. X/* This dummy function has nothing to do but to call optim so that
  78. X   the `.optim' assembler pseudo-op will be included in the assembler
  79. X   file. This must be the first of all functions.
  80. X*/
  81. X
  82. X#if defined (OPTIM)    /* Define for uPort, ISC doesn't know about */
  83. Xstatic void        /* `.optim', but has turned on optimization by */
  84. Xdummy ()        /* default, so we don't need it there anyway. */
  85. X{
  86. X    optim ();
  87. X}
  88. X#endif
  89. X#endif    /* XENIX */
  90. X
  91. X/* functions provided by this driver */
  92. Xint        fasinit ();
  93. Xint        fasopen ();
  94. Xint        fasclose ();
  95. Xint        fasread ();
  96. Xint        faswrite ();
  97. Xint        fasioctl ();
  98. Xint        fasintr ();
  99. X#if defined (NEED_PUT_GETCHAR)
  100. Xint        asyputchar ();
  101. Xint        asygetchar ();
  102. X#endif
  103. X#if defined (NEED_INIT8250)
  104. Xint        init8250 ();
  105. X#endif
  106. Xstatic int    fas_proc ();
  107. Xstatic void    fas_param ();
  108. Xstatic void    fas_fproc ();
  109. Xstatic void    fas_mproc ();
  110. Xstatic uint    fas_rproc ();
  111. Xstatic void    fas_xproc ();
  112. Xstatic void    fas_event ();
  113. X#if defined (HAVE_VPIX)
  114. Xstatic int    fas_vpix_sr ();
  115. X#endif
  116. Xstatic void    fas_rxfer ();
  117. Xstatic void    fas_xxfer ();
  118. Xstatic void    fas_ihlw_check ();
  119. Xstatic void    fas_hangup ();
  120. Xstatic void    fas_timeout ();
  121. Xstatic void    fas_cmd ();
  122. Xstatic void    fas_open_device ();
  123. Xstatic void    fas_close_device ();
  124. Xstatic int    fas_test_device ();
  125. X
  126. X/* functions used by this driver */
  127. Xextern int    ttinit ();
  128. Xextern int    ttiocom ();
  129. Xextern int    ttyflush ();
  130. Xextern int    SPLINT ();
  131. Xextern int    SPLWRK ();
  132. Xextern int    splx ();
  133. Xextern int    sleep ();
  134. Xextern int    wakeup ();
  135. Xextern int    signal ();
  136. Xextern int    timeout ();
  137. Xextern int    untimeout ();
  138. X#if defined (SCO)
  139. Xextern int    printcfg ();
  140. X#else
  141. Xextern int    printf ();
  142. X#endif
  143. X#if defined (HAVE_VPIX)
  144. Xextern int    ttywait ();
  145. Xextern int    fubyte ();
  146. Xextern int    subyte ();
  147. Xextern int    v86setint ();
  148. X#endif
  149. X#if defined (XENIX)
  150. Xextern int    inb ();
  151. Xextern void    outb ();
  152. X#endif
  153. X
  154. X/* the following stuff is defined in space.c */
  155. Xextern uint    fas_physical_units;
  156. Xextern uint    fas_port [];
  157. Xextern uint    fas_vec [];
  158. Xextern uint    fas_init_seq [];
  159. Xextern uint    fas_mcb [];
  160. Xextern uint    fas_modem [];
  161. Xextern uint    fas_flow [];
  162. Xextern uint    fas_int_ack_port [];
  163. Xextern uint    fas_int_ack [];
  164. Xextern uint    fas_mux_ack_port [];
  165. Xextern uint    fas_mux_ack [];
  166. Xextern struct fas_info    fas_info [];
  167. Xextern struct tty    fas_tty [];
  168. Xextern struct fas_info    *fas_info_ptr [];
  169. Xextern struct tty    *fas_tty_ptr [];
  170. X/* end of space.c references */
  171. X
  172. X/* fas_is_initted
  173. X   Flag to indicate that we have been thru init.
  174. X   This is realy only necessary for systems that use asyputchar
  175. X   and asygetchar but it doesn't hurt to have it anyway.
  176. X*/
  177. Xstatic int    fas_is_initted = FALSE;
  178. X
  179. X/* array of pointers to the first fas_info structure for each
  180. X   interrupt vector
  181. X*/
  182. Xstatic struct fas_info    *fas_first_int_user [NUM_INT_VECTORS];
  183. X
  184. X/* the values for the various baud rates */
  185. Xstatic uint    fas_speeds [CBAUD + 1] =
  186. X{    1,            BAUD_BASE/50,
  187. X    BAUD_BASE/75,        BAUD_BASE/110,
  188. X    (2*BAUD_BASE+134)/269,    BAUD_BASE/150,
  189. X    BAUD_BASE/200,        BAUD_BASE/300,
  190. X    BAUD_BASE/600,        BAUD_BASE/1200,
  191. X    BAUD_BASE/1800,        BAUD_BASE/2400,
  192. X    BAUD_BASE/4800,        BAUD_BASE/9600,
  193. X    BAUD_BASE/19200,    BAUD_BASE/38400
  194. X};
  195. X
  196. X/* time for one character to completely leave the transmitter shift register */
  197. Xstatic uint    fas_ctimes [CBAUD + 1] =
  198. X{    1,        HZ*15/50+2,
  199. X    HZ*15/75+2,    HZ*15/110+2,
  200. X    HZ*30/269+2,    HZ*15/150+2,
  201. X    HZ*15/200+2,    HZ*15/300+2,
  202. X    HZ*15/600+2,    HZ*15/1200+2,
  203. X    HZ*15/1800+2,    HZ*15/2400+2,
  204. X    HZ*15/4800+2,    HZ*15/9600+2,
  205. X    HZ*15/19200+2,    HZ*15/38400+2
  206. X};
  207. X
  208. X/* dynamically adapt xmit buffer size to baud rate to prevent long buffer
  209. X   drains at low speeds
  210. X   These values are checked against boundaries and will be modified if
  211. X   necessary before use. Checking is done in fas_param (). Drain time
  212. X   is about 5 seconds with continuous character flow.
  213. X*/
  214. Xstatic uint    fas_xbuf_size [CBAUD + 1] =
  215. X{    1,        50/2,
  216. X    75/2,        110/2,
  217. X    269/4,        150/2,
  218. X    200/2,        300/2,
  219. X    600/2,        1200/2,
  220. X    1800/2,        2400/2,
  221. X    4800/2,        9600/2,
  222. X    19200/2,    38400/2
  223. X};
  224. X
  225. X/* lookup table for minor device number -> open mode flags translation */
  226. Xstatic uint    fas_open_modes [16] =
  227. X{
  228. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL,
  229. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HW_HANDSHAKE,
  230. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON,
  231. X    OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HW_HANDSHAKE,
  232. X    OS_OPEN_FOR_DIALOUT | OS_CHECK_CARR_ON_OPEN,
  233. X    OS_OPEN_FOR_DIALOUT | OS_CHECK_CARR_ON_OPEN | OS_HW_HANDSHAKE,
  234. X    OS_OPEN_FOR_DIALOUT | OS_CHECK_CARR_ON_OPEN | OS_FAKE_CARR_ON,
  235. X    OS_OPEN_FOR_DIALOUT | OS_CHECK_CARR_ON_OPEN | OS_FAKE_CARR_ON | OS_HW_HANDSHAKE,
  236. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT,
  237. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HW_HANDSHAKE,
  238. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_UNBLOCK_ENABLE,
  239. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_UNBLOCK_ENABLE | OS_HW_HANDSHAKE,
  240. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN,
  241. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HW_HANDSHAKE,
  242. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_UNBLOCK_ENABLE,
  243. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_UNBLOCK_ENABLE | OS_HW_HANDSHAKE
  244. X};
  245. X
  246. X/* The following defines are used to take apart the minor device numbers. */
  247. X#define GET_UNIT(dev)        ((dev) & 0x0f)
  248. X#define GET_OPEN_MODE(dev)    (fas_open_modes [((dev) >> 4) & 0x0f])
  249. X
  250. X/* lock device against concurrent use */
  251. X#define get_device_lock(fip) \
  252. X{\
  253. X    /* sleep while device is used by an other process */\
  254. X    while ((fip)->device_flags.i & DF_DEVICE_LOCKED)\
  255. X        (void) sleep ((caddr_t) &(fip)->device_flags.i, PZERO - 1);\
  256. X    (fip)->device_flags.s |= DF_DEVICE_LOCKED;\
  257. X}
  258. X
  259. X/* release device */
  260. X#define release_device_lock(fip) \
  261. X{\
  262. X    (fip)->device_flags.s &= ~DF_DEVICE_LOCKED;\
  263. X    /* wakeup the process that may wait for this device */\
  264. X    (void) wakeup ((caddr_t) &(fip)->device_flags.i);\
  265. X}
  266. X
  267. X/* schedule event */
  268. X#define event_sched(fip,event) \
  269. X{\
  270. X    (fip)->event_flags.s |= (event);\
  271. X    if (!((fip)->event_flags.i & EF_EVENT_SCHEDULED))\
  272. X    {\
  273. X        (fip)->event_flags.s |= EF_EVENT_SCHEDULED;\
  274. X        (void) timeout (fas_event, (fip), EVENT_TIME);\
  275. X    }\
  276. X}
  277. X
  278. X/* fasinit
  279. X   This routine checks for the presense of the devices in the fas_port
  280. X   array and if the device is present tests and initializes it.
  281. X   During the initialization if the device is determined to be an
  282. X   NS16550A chip the DF_DEVICE_IS_NS16550 flag is set and the FIFOs will
  283. X   be used. If the device is an i82510 chip the DF_DEVICE_IS_I82510 flag
  284. X   is set and the device will be handled accordingly.
  285. X*/
  286. X
  287. Xint
  288. Xfasinit ()
  289. X{
  290. X    register struct fas_info    *fip;
  291. X    register uint    unit;
  292. X    uint    logical_units;
  293. X    uint    port, *seq_ptr;
  294. X    char    port_stat [MAX_UNITS + 1];
  295. X    REGVAR;
  296. X
  297. X    if (fas_is_initted)
  298. X        return (0);
  299. X
  300. X    fas_is_initted = TRUE;
  301. X
  302. X    /* execute the init sequence for the serial card */
  303. X    for (seq_ptr = fas_init_seq; *seq_ptr; seq_ptr++)
  304. X    {
  305. X        port = *seq_ptr;
  306. X        seq_ptr++;
  307. X        if (*seq_ptr > 0xff)
  308. X            inb (port);
  309. X        else
  310. X            outb (port, *seq_ptr);
  311. X    }
  312. X
  313. X    /* setup the list of pointers to the tty structures */
  314. X    for (unit = 0, logical_units = fas_physical_units * 2;
  315. X        unit < logical_units; unit++)
  316. X        fas_tty_ptr [unit] = &fas_tty [unit];
  317. X
  318. X    /* setup and initialize all serial ports */
  319. X    for (unit = 0; unit < fas_physical_units; unit++)
  320. X    {
  321. X        fas_info_ptr [unit] = fip = &fas_info [unit];
  322. X        port_stat [unit] = '-';
  323. X        if (port = fas_port [unit])
  324. X        {
  325. X            /* init all of its ports */
  326. X            fip->uart_port_0 = port;
  327. X            fip->uart_port_1 = port + 1;
  328. X            fip->uart_port_2 = port + 2;
  329. X            fip->uart_port_3 = port + 3;
  330. X            fip->uart_port_4 = port + 4;
  331. X            fip->uart_port_5 = port + 5;
  332. X            fip->uart_port_6 = port + 6;
  333. X            fip->int_ack_port = fas_int_ack_port [unit];
  334. X            fip->int_ack = fas_int_ack [unit];
  335. X            fip->vec = fas_vec [unit];
  336. X            fip->modem.i = fas_modem [unit];
  337. X            fip->flow.i = fas_flow [unit];
  338. X            fip->recv_ring_put_ptr = fip->recv_buffer;
  339. X            fip->recv_ring_take_ptr = fip->recv_buffer;
  340. X            fip->xmit_ring_put_ptr = fip->xmit_buffer;
  341. X            fip->xmit_ring_take_ptr = fip->xmit_buffer;
  342. X
  343. X            fip->ier = IE_NONE;    /* disable all ints */
  344. X            outb (INT_ENABLE_PORT, fip->ier);
  345. X
  346. X            /* is there a serial chip ? */
  347. X            if (inb (INT_ENABLE_PORT) != fip->ier)
  348. X            {
  349. X                port_stat [unit] = '?';
  350. X                continue;    /* a hardware error */
  351. X            }
  352. X
  353. X            /* test the chip thoroughly */
  354. X            if ((port_stat [unit] = (fas_test_device (fip) + '0'))
  355. X                != '0')
  356. X            {
  357. X                continue;    /* a hardware error */
  358. X            }
  359. X
  360. X            fip->lcr = 0;
  361. X            outb (LINE_CTL_PORT, fip->lcr);
  362. X            fip->mcr = fas_mcb [unit];
  363. X            outb (MDM_CTL_PORT, fip->mcr);
  364. X
  365. X            port_stat [unit] = '*';
  366. X
  367. X            /* let's see if it's an NS16550 */
  368. X            outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_INIT);
  369. X            if (!(~inb (INT_ID_PORT) & II_NS_FIFO_ENABLED))
  370. X            {
  371. X                fip->device_flags.s |= DF_DEVICE_IS_NS16550;
  372. X                port_stat [unit] = 'F';
  373. X                outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_CLEAR);
  374. X            }
  375. X            else
  376. X            {
  377. X                outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_CLEAR);
  378. X                /* or is it an i82510 ? */
  379. X                outb (I_BANK_PORT, I_BANK_2);
  380. X                if (!(~inb (I_BANK_PORT) & I_BANK_2))
  381. X                {
  382. X                    fip->device_flags.s |= DF_DEVICE_IS_I82510;
  383. X                    port_stat [unit] = 'f';
  384. X                    outb (I_BANK_PORT, I_BANK_1);
  385. X                    outb (I_TCM_PORT, I_FIFO_CLR_XMIT);
  386. X                    outb (I_RCM_PORT, I_FIFO_CLR_RECV);
  387. X                }
  388. X                outb (I_BANK_PORT, I_BANK_0);
  389. X            }
  390. X
  391. X            /* clear potential interrupts */
  392. X            inb (MDM_STATUS_PORT);
  393. X            inb (RCV_DATA_PORT);
  394. X            inb (RCV_DATA_PORT);
  395. X            inb (LINE_STATUS_PORT);
  396. X            inb (INT_ID_PORT);
  397. X            if (INT_ACK_PORT)
  398. X                outb (INT_ACK_PORT, fip->int_ack);
  399. X            if (port = fas_mux_ack_port [fip->vec])
  400. X                outb (port, fas_mux_ack [fip->vec]);
  401. X
  402. X            /* show that it is present and configured */
  403. X            fip->device_flags.s |= DF_DEVICE_CONFIGURED;
  404. X        }
  405. X    }
  406. X
  407. X#if defined (NEED_PUT_GETCHAR)
  408. X    fip = &fas_info [0];
  409. X    fip->mcr |= INITIAL_MDM_CONTROL;
  410. X    outb (MDM_CTL_PORT, fip->mcr);
  411. X
  412. X    fip->lcr = INITIAL_LINE_CONTROL;
  413. X    outb (LINE_CTL_PORT, fip->lcr | LC_ENABLE_DIVISOR);
  414. X    outb (DIVISOR_LSB_PORT, INITIAL_BAUD_RATE);
  415. X    outb (DIVISOR_MSB_PORT, (INITIAL_BAUD_RATE) >> 8);
  416. X    outb (LINE_CTL_PORT, fip->lcr);
  417. X#endif
  418. X
  419. X#if defined (SCO)
  420. X    for (unit = 0; unit < fas_physical_units; unit++)
  421. X        (void) printcfg ("fas", fas_port [unit], 7, fas_vec [unit], -1,
  422. X                    "unit=%d type=%c release=2.07.0",
  423. X                    unit, port_stat [unit]);
  424. X#else
  425. X    port_stat [unit] = '\0';
  426. X    (void) printf ("\nFAS 2.07.0 async driver: Port 0-%d init state is [%s]\n\n",
  427. X            unit - 1,
  428. X            port_stat);
  429. X#endif
  430. X    return (0);
  431. X}
  432. X
  433. X/* Open a tty line. This function is called for every open, as opposed
  434. X   to the fasclose function which is called only with the last close.
  435. X*/
  436. Xint
  437. Xfasopen (dev, flag)
  438. Xint    dev;
  439. Xint    flag;
  440. X{
  441. X    register struct fas_info    *fip;
  442. X    register struct tty        *ttyp;
  443. X    register uint    open_mode;
  444. X    uint    physical_unit;
  445. X    int    old_level;
  446. X
  447. X    physical_unit = GET_UNIT (dev);
  448. X
  449. X    /* check for valid port number */
  450. X    if (physical_unit >= fas_physical_units)
  451. X    {
  452. X        u.u_error = ENXIO;
  453. X        return (-1);
  454. X    }
  455. X
  456. X    fip = fas_info_ptr [physical_unit];
  457. X
  458. X    /* was the port present at init time ? */
  459. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  460. X    {
  461. X        u.u_error = ENXIO;
  462. X        return (-1);
  463. X    }
  464. X
  465. X    open_mode = GET_OPEN_MODE (dev);
  466. X
  467. X    old_level = SPLINT ();
  468. X    get_device_lock (fip);
  469. X
  470. X    /* If this is a getty open, the device is already open for
  471. X           dialout and the FNDELAY flag is not set, wait until device
  472. X           is closed.
  473. X    */
  474. X    while ((open_mode & OS_OPEN_FOR_GETTY)
  475. X            && (fip->o_state & OS_OPEN_FOR_DIALOUT)
  476. X            && !(flag & FNDELAY))
  477. X    {
  478. X        release_device_lock (fip);
  479. X        (void) sleep ((caddr_t) &fip->o_state, TTIPRI);
  480. X        get_device_lock (fip);
  481. X    }
  482. X    
  483. X    /* If the device is already open and another open uses a different
  484. X       open mode or if a getty open waits for carrier and doesn't allow
  485. X       parallel dialout opens, return with EBUSY error.
  486. X    */
  487. X    if ((fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
  488. X                ? (OS_OPEN_STATES | OS_WAIT_OPEN)
  489. X                : (OS_OPEN_STATES | OS_NO_DIALOUT)))
  490. X        && ((flag & FEXCL)
  491. X            || ((open_mode ^ fip->o_state) & (u.u_uid
  492. X                        ? OS_TEST_MASK
  493. X                        : OS_SU_TEST_MASK))))
  494. X    {
  495. X        u.u_error = EBUSY;
  496. X        release_device_lock (fip);
  497. X        (void) splx (old_level);
  498. X        return (-1);
  499. X    }
  500. X
  501. X    /* disable subsequent opens */
  502. X    if (flag & FEXCL)
  503. X        open_mode |= OS_EXCLUSIVE_OPEN_1;
  504. X
  505. X    /* set up pointer to tty structure */
  506. X    ttyp = (open_mode & OS_OPEN_FOR_GETTY)
  507. X        ? fas_tty_ptr [physical_unit + fas_physical_units]
  508. X        : fas_tty_ptr [physical_unit];
  509. X
  510. X    /* things to do on first open only */
  511. X    if (!(fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
  512. X                ? (OS_OPEN_STATES | OS_WAIT_OPEN)
  513. X                : OS_OPEN_STATES)))
  514. X    {
  515. X        /* init data structures */
  516. X        fip->tty = ttyp;
  517. X        (void) ttinit (ttyp);
  518. X        ttyp->t_proc = fas_proc;
  519. X        fip->po_state = fip->o_state;
  520. X        fip->o_state = open_mode & ~OS_OPEN_STATES;
  521. X#if defined (HAVE_VPIX)
  522. X        /* initialize VP/ix related variables */
  523. X        fip->v86_proc = (v86_t *) NULL;
  524. X        fip->v86_intmask = 0;
  525. X        fip->v86_ss.ss_start = CSTART;
  526. X        fip->v86_ss.ss_stop = CSTOP;
  527. X#endif
  528. X        /* open physical device if not yet open */
  529. X        if (!(fip->device_flags.i & DF_DEVICE_OPEN))
  530. X            fas_open_device (fip);
  531. X        fas_param (fip);    /* set up port registers */
  532. X        fas_mproc (fip);    /* set up modem status flags */
  533. X
  534. X        /* allow pending tty interrupts */
  535. X        (void) SPLWRK ();
  536. X        (void) SPLINT ();
  537. X    }
  538. X
  539. X    /* If getty open and the FNDELAY flag is not set,
  540. X       block and wait for carrier if device not yet open.
  541. X    */
  542. X    if ((open_mode & OS_OPEN_FOR_GETTY) && !(flag & FNDELAY))
  543. X    {
  544. X        /* sleep while open for dialout or no carrier */
  545. X        while ((fip->o_state & OS_OPEN_FOR_DIALOUT)
  546. X            || !(ttyp->t_state & (ISOPEN | CARR_ON)))
  547. X        {
  548. X            ttyp->t_state |= WOPEN;
  549. X            release_device_lock (fip);
  550. X            (void) sleep ((caddr_t) &ttyp->t_canq, TTIPRI);
  551. X            get_device_lock (fip);
  552. X        }
  553. X        ttyp->t_state &= ~WOPEN;
  554. X    }
  555. X
  556. X    /* wakeup processes that are still sleeping in getty open */
  557. X    if (ttyp->t_state & WOPEN)
  558. X        (void) wakeup ((caddr_t) &ttyp->t_canq);
  559. X
  560. X    /* we need to flush the receiver with the first open */
  561. X    if (!(fip->o_state & OS_OPEN_STATES))
  562. X        fas_cmd (fip, ttyp, T_RFLUSH);
  563. X
  564. X    (*linesw [ttyp->t_line].l_open) (ttyp);
  565. X
  566. X    /* set open type flags */
  567. X    fip->o_state = open_mode;
  568. X
  569. X    if ((open_mode & OS_CHECK_CARR_ON_OPEN)
  570. X        && (~fip->msr & fip->modem.m.ca)
  571. X        && !(fip->cflag & CLOCAL))
  572. X    {
  573. X        (void) SPLWRK ();
  574. X        (void) signal (ttyp->t_pgrp, SIGHUP);
  575. X        (void) ttyflush (ttyp, FREAD | FWRITE);
  576. X        (void) SPLINT ();
  577. X    }
  578. X
  579. X    release_device_lock (fip);
  580. X    (void) splx (old_level);
  581. X    return (0);
  582. X}
  583. X
  584. X/* Close a tty line. This is only called if there is no other
  585. X   concurrent open left. A blocked getty open is not counted as
  586. X   a concurrent open because in this state it isn't really open.
  587. X*/
  588. Xint
  589. Xfasclose (dev)
  590. Xint    dev;
  591. X{
  592. X    register struct fas_info    *fip;
  593. X    register struct tty        *ttyp;
  594. X    uint    open_mode;
  595. X    uint    physical_unit;
  596. X    int    old_level;
  597. X
  598. X    physical_unit = GET_UNIT (dev);
  599. X
  600. X    fip = fas_info_ptr [physical_unit];
  601. X
  602. X    open_mode = GET_OPEN_MODE (dev);
  603. X
  604. X    /* set up pointer to tty structure */
  605. X    ttyp = (open_mode & OS_OPEN_FOR_GETTY)
  606. X        ? fas_tty_ptr [physical_unit + fas_physical_units]
  607. X        : fas_tty_ptr [physical_unit];
  608. X    
  609. X    old_level = SPLINT ();
  610. X
  611. X    (*linesw [ttyp->t_line].l_close) (ttyp);
  612. X
  613. X    get_device_lock (fip);
  614. X
  615. X    /* allow pending tty interrupts */
  616. X    (void) SPLWRK ();
  617. X    (void) SPLINT ();
  618. X
  619. X    if (open_mode & OS_OPEN_FOR_GETTY)
  620. X    {
  621. X        /* not waiting any more */
  622. X        ttyp->t_state &= ~WOPEN;
  623. X        if (!(fip->o_state & OS_OPEN_FOR_DIALOUT))
  624. X        {
  625. X            fas_close_device (fip);
  626. X            fip->o_state = OS_DEVICE_CLOSED;
  627. X        }
  628. X        else
  629. X            fip->po_state = OS_DEVICE_CLOSED;
  630. X    }
  631. X    else
  632. X    {
  633. X        fas_close_device (fip);
  634. X        fip->o_state = OS_DEVICE_CLOSED;
  635. X        /* If there is a waiting getty open on
  636. X           this port, reopen the physical device.
  637. X        */
  638. X        if (fip->po_state & OS_WAIT_OPEN)
  639. X        {
  640. X            /* get the getty version of the
  641. X               tty structure
  642. X            */
  643. X            fip->tty = fas_tty_ptr [physical_unit
  644. X                    + fas_physical_units];
  645. X            fip->o_state = fip->po_state;
  646. X            fip->po_state = OS_DEVICE_CLOSED;
  647. X#if defined (HAVE_VPIX)
  648. X            /* initialize VP/ix related variables */
  649. X            fip->v86_proc = (v86_t *) NULL;
  650. X            fip->v86_intmask = 0;
  651. X            fip->v86_ss.ss_start = CSTART;
  652. X            fip->v86_ss.ss_stop = CSTOP;
  653. X#endif
  654. X            if (!(fip->device_flags.i & DF_DO_HANGUP))
  655. X            {
  656. X                fas_open_device (fip);
  657. X                /* set up port registers */
  658. X                fas_param (fip);
  659. X                /* set up modem status flags */
  660. X                fas_mproc (fip);
  661. X            }
  662. X        }
  663. X        (void) wakeup ((caddr_t) &fip->o_state);
  664. X    }
  665. X
  666. X    if (!(fip->device_flags.i & DF_DO_HANGUP))
  667. X        release_device_lock (fip);
  668. X
  669. X    (void) splx (old_level);
  670. X    return (0);
  671. X}
  672. X
  673. X/* read characters from the input buffer */
  674. Xint
  675. Xfasread (dev)
  676. Xint    dev;
  677. X{
  678. X    register struct fas_info    *fip;
  679. X    register struct tty    *ttyp;
  680. X    int    old_level;
  681. X
  682. X    fip = fas_info_ptr [GET_UNIT (dev)];
  683. X
  684. X    ttyp = fip->tty;
  685. X
  686. X    (*linesw [ttyp->t_line].l_read) (ttyp);
  687. X
  688. X    old_level = SPLINT ();
  689. X
  690. X#if defined (HAVE_VPIX)
  691. X    /* wakeup VP/ix */
  692. X    if ((fip->iflag & DOSMODE) && ttyp->t_rawq.c_cc)
  693. X        event_sched (fip, EF_SIGNAL_VPIX);
  694. X#endif
  695. X    /* schedule character transfer to UNIX buffer */
  696. X    if (fip->recv_ring_cnt
  697. X#if defined (HAVE_VPIX)
  698. X        && (((fip->iflag & DOSMODE)
  699. X            ? MAX_VPIX_FILL - MIN_READ_CHUNK
  700. X            : MAX_UNIX_FILL - MIN_READ_CHUNK)
  701. X                >= fip->tty->t_rawq.c_cc)
  702. X#else
  703. X        && ((MAX_UNIX_FILL - MIN_READ_CHUNK) >= fip->tty->t_rawq.c_cc)
  704. X#endif
  705. X        && !(fip->flow_flags.i & FF_RXFER_STOPPED))
  706. X    {
  707. X        event_sched (fip, EF_DO_RXFER);
  708. X    }
  709. X
  710. X    (void) splx (old_level);
  711. X    return (0);
  712. X}
  713. X
  714. X/* write characters to the output buffer */
  715. Xint
  716. Xfaswrite (dev)
  717. Xint    dev;
  718. X{
  719. X    register struct tty    *ttyp;
  720. X
  721. X    ttyp = fas_info_ptr [GET_UNIT (dev)]->tty;
  722. X    (*linesw [ttyp->t_line].l_write) (ttyp);
  723. X    return (0);
  724. X}
  725. X
  726. X/* process ioctl calls */
  727. Xint
  728. Xfasioctl (dev, cmd, arg3, arg4)
  729. Xint    dev;
  730. Xint    cmd;
  731. Xunion ioctl_arg    arg3;
  732. Xint    arg4;
  733. X{
  734. X    register struct fas_info    *fip;
  735. X    register struct tty    *ttyp;
  736. X    int    v86_cmd, v86_data;
  737. X    int    old_level;
  738. X    REGVAR;
  739. X
  740. X    fip = fas_info_ptr [GET_UNIT (dev)];
  741. X
  742. X    ttyp = fip->tty;
  743. X
  744. X    /* process ioctl commands */
  745. X    switch (cmd)
  746. X    {
  747. X#if defined (HAVE_VPIX)
  748. X        case AIOCINTTYPE:    /* set pseudorupt type */
  749. X            switch (arg3.iarg)
  750. X            {
  751. X                case V86VI_KBD:
  752. X                case V86VI_SERIAL0:
  753. X                case V86VI_SERIAL1:
  754. X                    intr_disable ();
  755. X                    fip->v86_intmask = arg3.iarg;
  756. X                    intr_restore ();
  757. X                    break;
  758. X
  759. X                default:
  760. X                    intr_disable ();
  761. X                    fip->v86_intmask = V86VI_SERIAL0;
  762. X                    intr_restore ();
  763. X                    break;
  764. X            }
  765. X            break;
  766. X
  767. X        case AIOCDOSMODE:    /* enable dos mode */
  768. X            if (!(fip->iflag & DOSMODE))
  769. X            {
  770. X                old_level = SPLINT ();
  771. X                fip->v86_proc = u.u_procp->p_v86;
  772. X                if (!(fip->v86_intmask))
  773. X                    fip->v86_intmask = V86VI_SERIAL0;
  774. X                ttyp->t_iflag |= DOSMODE;
  775. X                if (fip->v86_intmask != V86VI_KBD)
  776. X                    ttyp->t_cflag |= CLOCAL;
  777. X                fas_param (fip);
  778. X                (void) splx (old_level);
  779. X            }
  780. X            u.u_r.r_reg.r_val1 = 0;
  781. X            break;
  782. X
  783. X        case AIOCNONDOSMODE:    /* disable dos mode */
  784. X            if (fip->iflag & DOSMODE)
  785. X            {
  786. X                old_level = SPLINT ();
  787. X                fip->v86_proc = (v86_t *) NULL;
  788. X                fip->v86_intmask = 0;
  789. X                ttyp->t_iflag &= ~DOSMODE;
  790. X                if (fip->flow_flags.i & FF_RXFER_STOPPED)
  791. X                {
  792. X                    fip->flow_flags.s &= ~FF_RXFER_STOPPED;
  793. X                    /* schedule character transfer
  794. X                       to UNIX buffer
  795. X                    */
  796. X                    if (fip->recv_ring_cnt)
  797. X                        event_sched (fip, EF_DO_RXFER);
  798. X                }
  799. X                fip->lcr &= ~LC_SET_BREAK_LEVEL;
  800. X                fas_param (fip);
  801. X                (void) splx (old_level);
  802. X            }
  803. X            u.u_r.r_reg.r_val1 = 0;
  804. X            break;
  805. X
  806. X        case AIOCSERIALOUT:    /* setup port registers for dos */
  807. X            if ((fip->iflag & DOSMODE) && fip->v86_proc)
  808. X            {
  809. X                /* wait until output is done */
  810. X                (void) ttywait (ttyp);
  811. X
  812. X                /* block transmitter and wait until it is
  813. X                   empty
  814. X                */
  815. X                old_level = SPLINT ();
  816. X                fip->device_flags.s |= DF_XMIT_LOCKED;
  817. X                while (fip->device_flags.i & (DF_XMIT_BUSY
  818. X                            | DF_GUARD_TIMEOUT))
  819. X                    (void) sleep ((caddr_t) &(fip)->
  820. X                                device_flags.i,
  821. X                            PZERO - 1);
  822. X                (void) splx (old_level);
  823. X
  824. X                /* get port write command */
  825. X                v86_cmd = fubyte (arg3.cparg);
  826. X                /* set divisor lsb requested */
  827. X                if (v86_cmd & SIO_MASK(SO_DIVLLSB))
  828. X                {
  829. X                    v86_data = fubyte (arg3.cparg
  830. X                                + SO_DIVLLSB);
  831. X                    intr_disable ();
  832. X                    outb (LINE_CTL_PORT, fip->lcr
  833. X                            | LC_ENABLE_DIVISOR);
  834. X                    outb (DIVISOR_LSB_PORT, v86_data);
  835. X                    outb (LINE_CTL_PORT, fip->lcr
  836. X                            & ~LC_ENABLE_DIVISOR);
  837. X                    intr_restore ();
  838. X                }
  839. X                /* set divisor msb requested */
  840. X                if (v86_cmd & SIO_MASK(SO_DIVLMSB))
  841. X                {
  842. X                    v86_data = fubyte (arg3.cparg
  843. X                                + SO_DIVLMSB);
  844. X                    intr_disable ();
  845. X                    outb (LINE_CTL_PORT, fip->lcr
  846. X                            | LC_ENABLE_DIVISOR);
  847. X                    outb (DIVISOR_MSB_PORT, v86_data);
  848. X                    outb (LINE_CTL_PORT, fip->lcr
  849. X                            & ~LC_ENABLE_DIVISOR);
  850. X                    intr_restore ();
  851. X                }
  852. X                /* set lcr requested */
  853. X                if (v86_cmd & SIO_MASK(SO_LCR))
  854. X                {
  855. X                    v86_data = fubyte (arg3.cparg + SO_LCR);
  856. X                    intr_disable ();
  857. X                    fip->lcr = v86_data
  858. X                            & ~LC_ENABLE_DIVISOR;
  859. X                    outb (LINE_CTL_PORT, fip->lcr);
  860. X                    intr_restore ();
  861. X                }
  862. X                /* set mcr requested */
  863. X                if (v86_cmd & SIO_MASK(SO_MCR))
  864. X                {
  865. X                    v86_data = fubyte (arg3.cparg + SO_MCR);
  866. X                    old_level = SPLINT ();
  867. X                    /* virtual dtr processing */
  868. X                    if (v86_data & MC_SET_DTR)
  869. X                    {
  870. X                        fip->device_flags.s
  871. X                            |= DF_MODEM_ENABLED;
  872. X                        fip->mcr |= fip->modem.m.en;
  873. X                    }
  874. X                    else
  875. X                    {
  876. X                        fip->device_flags.s
  877. X                            &= ~DF_MODEM_ENABLED;
  878. X                        fip->mcr &= ~fip->modem.m.en;
  879. X                    }
  880. X                    /* virtual rts processing */
  881. X                    if (!(fip->flow_flags.i
  882. X                            & FF_HWI_HANDSHAKE))
  883. X                    {
  884. X                        if (v86_data & MC_SET_RTS)
  885. X                        {
  886. X                            fip->flow_flags.s
  887. X                              &= ~FF_HWI_STOPPED;
  888. X                            fip->mcr
  889. X                              |= fip->flow.m.ic;
  890. X                        }
  891. X                        else
  892. X                        {
  893. X                            fip->flow_flags.s
  894. X                              |= FF_HWI_STOPPED;
  895. X                            fip->mcr
  896. X                              &= ~fip->flow.m.ic;
  897. X                        }
  898. X                    }
  899. X                    else
  900. X                    {
  901. X                      if (v86_data & MC_SET_RTS)
  902. X                      {
  903. X                        if (fip->flow_flags.i
  904. X                            & FF_RXFER_STOPPED)
  905. X                        {
  906. X                          fip->flow_flags.s
  907. X                            &= ~FF_RXFER_STOPPED;
  908. X                          /* schedule character transfer
  909. X                             to UNIX buffer
  910. X                          */
  911. X                          if (fip->recv_ring_cnt)
  912. X                            event_sched (fip,
  913. X                                EF_DO_RXFER);
  914. X                        }
  915. X                      }
  916. X                      else
  917. X                        fip->flow_flags.s
  918. X                            |= FF_RXFER_STOPPED;
  919. X                    }
  920. X                    outb (MDM_CTL_PORT, fip->mcr);
  921. X                    (void) splx (old_level);
  922. X                }
  923. X
  924. X                old_level = SPLINT ();
  925. X                /* enable transmitter and restart output */
  926. X                fip->device_flags.s &= ~DF_XMIT_LOCKED;
  927. X                fas_xproc (fip);
  928. X                (void) splx (old_level);
  929. X            }
  930. X            break;
  931. X
  932. X        case AIOCSERIALIN:    /* read port registers for dos */
  933. X            if ((fip->iflag & DOSMODE) && fip->v86_proc)
  934. X            {
  935. X                v86_cmd = fubyte (arg3.cparg);
  936. X                if (v86_cmd & SIO_MASK(SI_MSR))
  937. X                {
  938. X                    (void) subyte (arg3.cparg + SI_MSR,
  939. X                                fip->msr);
  940. X                }
  941. X            }
  942. X            break;
  943. X
  944. X        case AIOCSETSS:    /* set start/stop characters */
  945. X            intr_disable ();
  946. X            *((short *) &fip->v86_ss) = arg3.iarg;
  947. X            intr_restore ();
  948. X            break;
  949. X
  950. X        case AIOCINFO:    /* show what type of device we are */
  951. X            u.u_r.r_reg.r_val1 = ('a' << 8) | (dev & 0xff);
  952. X            break;
  953. X#endif
  954. X        default:    /* default ioctl processing */
  955. X            /* if it is a TCSETA* command, call fas_param () */
  956. X            if (ttiocom (ttyp, cmd, arg3, arg4))
  957. X            {
  958. X                old_level = SPLINT ();
  959. X                fas_param (fip);
  960. X                (void) splx (old_level);
  961. X            }
  962. X            break;
  963. X    }
  964. X    return (0);
  965. X}
  966. X
  967. X/* pass fas commands to the fas multi-function procedure */
  968. Xstatic int
  969. Xfas_proc (ttyp, arg2)
  970. Xstruct tty    *ttyp;
  971. Xint    arg2;
  972. X{
  973. X    register uint    physical_unit;
  974. X    int    old_level;
  975. X
  976. X    physical_unit = ttyp - &fas_tty [0];
  977. X    if (physical_unit >= fas_physical_units)
  978. X        physical_unit -= fas_physical_units;
  979. X
  980. X    old_level = SPLINT ();
  981. X    fas_cmd (fas_info_ptr [physical_unit], ttyp, arg2);
  982. X    (void) splx (old_level);
  983. X    return (0);
  984. X}
  985. X
  986. X/* set up a port according to the given termio structure */
  987. Xstatic void
  988. Xfas_param (fip)
  989. Xregister struct fas_info    *fip;
  990. X{
  991. X    register uint    cflag;
  992. X    uint    divisor;
  993. X    int    xmit_ring_size;
  994. X    REGVAR;
  995. X
  996. X    /* lock transmitter and wait until it is empty */
  997. X    fip->device_flags.s |= DF_XMIT_LOCKED;
  998. X    while (fip->device_flags.i & (DF_XMIT_BUSY | DF_GUARD_TIMEOUT))
  999. X        (void) sleep ((caddr_t) &(fip)->device_flags.i, PZERO - 1);
  1000. X
  1001. X    cflag = fip->tty->t_cflag;
  1002. X
  1003. X#if defined (HAVE_VPIX)
  1004. X    /* we don't set port registers if we are in dos mode */
  1005. X    if (fip->tty->t_iflag & DOSMODE)
  1006. X        goto setflags;
  1007. X#endif
  1008. X    /* hangup line if it is baud rate 0, else enable line */
  1009. X    if ((cflag & CBAUD) == B0)
  1010. X    {
  1011. X        cflag = (cflag & ~CBAUD) | (fip->cflag & CBAUD);
  1012. X        fip->mcr &= ~fip->modem.m.en;
  1013. X        outb (MDM_CTL_PORT, fip->mcr);
  1014. X        fip->device_flags.s &= ~DF_MODEM_ENABLED;
  1015. X    }
  1016. X    else
  1017. X    {
  1018. X        if (!(fip->device_flags.i & DF_MODEM_ENABLED))
  1019. X        {
  1020. X            fip->mcr |= fip->modem.m.en;
  1021. X            outb (MDM_CTL_PORT, fip->mcr);
  1022. X            fip->device_flags.s |= DF_MODEM_ENABLED;
  1023. X        }
  1024. X    }
  1025. X
  1026. X    /* don't change break flag */
  1027. X    fip->lcr &= LC_SET_BREAK_LEVEL;
  1028. X
  1029. X    /* set character size */
  1030. X    switch (cflag & CSIZE)
  1031. X    {
  1032. X    case CS5:
  1033. X        fip->lcr |= LC_WORDLEN_5;
  1034. X        break;
  1035. X
  1036. X    case CS6:
  1037. X        fip->lcr |= LC_WORDLEN_6;
  1038. X        break;
  1039. X
  1040. X    case CS7:
  1041. X        fip->lcr |= LC_WORDLEN_7;
  1042. X        break;
  1043. X
  1044. X    default:
  1045. X        fip->lcr |= LC_WORDLEN_8;
  1046. X        break;
  1047. X    }
  1048. X
  1049. X    /* set # of stop bits */
  1050. X    if (cflag & CSTOPB)
  1051. X        fip->lcr |= LC_STOPBITS_LONG;
  1052. X
  1053. X    /* set parity */
  1054. X    if (cflag & PARENB)
  1055. X    {
  1056. X        fip->lcr |= LC_ENABLE_PARITY;
  1057. X
  1058. X        if (!(cflag & PARODD))
  1059. X            fip->lcr |= LC_EVEN_PARITY;
  1060. X    }
  1061. X
  1062. X    /* get counter divisor for selected baud rate */
  1063. X    divisor = fas_speeds [cflag & CBAUD];
  1064. X    /* set LCR and baud rate */
  1065. X    outb (LINE_CTL_PORT, fip->lcr | LC_ENABLE_DIVISOR);
  1066. X    outb (DIVISOR_LSB_PORT, divisor);
  1067. X    outb (DIVISOR_MSB_PORT, divisor >> 8);
  1068. X    outb (LINE_CTL_PORT, fip->lcr);
  1069. X
  1070. X    /* check dynamic xmit ring buffer size against boundaries,
  1071. X       modify it if necessary and update the fas_info structure
  1072. X    */
  1073. X    xmit_ring_size = fas_xbuf_size [cflag & CBAUD] - TTXOHI;
  1074. X    if (xmit_ring_size < OUTPUT_NS_FIFO_SIZE * 2)
  1075. X    {
  1076. Xsetflags:
  1077. X        xmit_ring_size = OUTPUT_NS_FIFO_SIZE * 2;
  1078. X    }
  1079. X    if (xmit_ring_size > XMIT_BUFF_SIZE)
  1080. X        xmit_ring_size = XMIT_BUFF_SIZE;
  1081. X    fip->xmit_ring_size = xmit_ring_size;
  1082. X
  1083. X    /* disable modem control signals if required by open mode */
  1084. X    if (fip->o_state & OS_CLOCAL)
  1085. X        cflag |= CLOCAL;
  1086. X
  1087. X    /* Fake the carrier detect state flag if CLOCAL mode or if
  1088. X       requested by open mode.
  1089. X    */
  1090. X    if (!(~fip->msr & fip->modem.m.ca)
  1091. X        || (fip->o_state & OS_FAKE_CARR_ON)
  1092. X        || (cflag & CLOCAL))
  1093. X        fip->tty->t_state |= CARR_ON;
  1094. X    else
  1095. X        fip->tty->t_state &= ~CARR_ON;
  1096. X
  1097. X#if defined (XCLUDE)    /* SYSV 3.2 Xenix compatibility */
  1098. X    /* Permit exclusive use of this device. */
  1099. X    if (cflag & XCLUDE)
  1100. X        fip->o_state |= OS_EXCLUSIVE_OPEN_2;
  1101. X    else
  1102. X        fip->o_state &= ~OS_EXCLUSIVE_OPEN_2;
  1103. X#endif
  1104. X
  1105. X    /* Select hardware handshake depending on the minor device
  1106. X       number and the CTSFLOW and RTSFLOW flags (if they are
  1107. X       available).
  1108. X    */
  1109. X    if (fip->o_state & OS_HW_HANDSHAKE)
  1110. X    {
  1111. X        fip->flow_flags.s |= FF_HWO_HANDSHAKE | FF_HWI_HANDSHAKE;
  1112. X    }
  1113. X    else
  1114. X    {
  1115. X        fip->flow_flags.s &= ~(FF_HWO_HANDSHAKE | FF_HWI_HANDSHAKE);
  1116. X#if defined (CTSFLOW)    /* SYSV 3.2 Xenix compatibility */
  1117. X        if (cflag & CTSFLOW)
  1118. X            fip->flow_flags.s |= FF_HWO_HANDSHAKE;
  1119. X#endif
  1120. X#if defined (RTSFLOW)    /* SYSV 3.2 Xenix compatibility */
  1121. X        if (cflag & RTSFLOW)
  1122. X            fip->flow_flags.s |= FF_HWI_HANDSHAKE;
  1123. X#endif
  1124. X    }
  1125. X
  1126. X    fip->cflag = cflag;
  1127. X    fip->iflag = fip->tty->t_iflag;
  1128. X
  1129. X    /* enable transmitter */
  1130. X    fip->device_flags.s &= ~DF_XMIT_LOCKED;
  1131. X
  1132. X    /* setup handshake flags */
  1133. X    fas_ihlw_check (fip);
  1134. X    fas_fproc (fip, fip->new_msr);
  1135. X
  1136. X    /* restart output */
  1137. X    fas_xproc (fip);
  1138. X}
  1139. X
  1140. X/* Main fas interrupt handler. Actual character processing is splitted
  1141. X   into sub-functions.
  1142. X*/
  1143. Xint
  1144. Xfasintr (vect)
  1145. Xint    vect;
  1146. X{
  1147. X    register struct fas_info    *fip;
  1148. X    register uint    status;
  1149. X    int    done;
  1150. X    uint    port, old_recv_count;
  1151. X    REGVAR;
  1152. X
  1153. X    /* The 8259 interrupt controller is set up for edge trigger.
  1154. X       Therefor we must loop until we make a complete pass without
  1155. X       getting any UARTs that are interrupting.
  1156. X    */
  1157. X    do
  1158. X    {
  1159. X        done = TRUE;
  1160. X        fip = fas_first_int_user [vect];
  1161. X
  1162. X        /* loop through all users of this interrupt vector */
  1163. X        for (;; fip = fip->next_int_user)
  1164. X        {
  1165. X            if (!fip)
  1166. X                break;    /* all users done */
  1167. X
  1168. X            /* process only ports that we expect ints from
  1169. X               and that actually need to be serviced
  1170. X            */
  1171. Xfastloop:
  1172. X            if (inb (INT_ID_PORT) & II_NO_INTS_PENDING)
  1173. X            {
  1174. X                /* speed beats beauty */
  1175. X                fip = fip->next_int_user;
  1176. X                if (fip)
  1177. X                    goto fastloop;
  1178. X                break;
  1179. X            }
  1180. X
  1181. X            done = FALSE;    /* not done if we got an int */
  1182. X            old_recv_count = fip->recv_ring_cnt;
  1183. X
  1184. X            do
  1185. X            {
  1186. X                /* read in all the characters from the FIFO */
  1187. X                if ((status = inb (LINE_STATUS_PORT))
  1188. X                    & LS_RCV_INT)
  1189. X                {
  1190. X                    status = fas_rproc (fip, status);
  1191. X                    sysinfo.rcvint++;
  1192. X                }
  1193. X
  1194. X                /* Is it a transmitter empty int ? */
  1195. X                if ((status & LS_XMIT_AVAIL)
  1196. X                    && (fip->device_flags.i & DF_XMIT_BUSY))
  1197. X                {
  1198. X                    fip->device_flags.s &= ~DF_XMIT_BUSY;
  1199. X                    fas_xproc (fip);
  1200. X                    if (!(fip->device_flags.i & DF_XMIT_BUSY)
  1201. X                        && !fip->xmit_ring_cnt)
  1202. X                    {
  1203. X                        fip->device_flags.s |=
  1204. X                            DF_GUARD_TIMEOUT;
  1205. X                        fip->tty->t_state |=
  1206. X                            TIMEOUT;
  1207. X                        fip->timeout_idx =
  1208. X                            timeout (
  1209. X                            fas_timeout, fip,
  1210. X                            fas_ctimes [fip->cflag
  1211. X                                & CBAUD]);
  1212. X                    }
  1213. X                    sysinfo.xmtint++;
  1214. X                }
  1215. X
  1216. X                /* Has there been a polarity change on
  1217. X                   some of the modem lines ?
  1218. X                */
  1219. X                if ((status = inb (MDM_STATUS_PORT))
  1220. X                        & MS_ANY_DELTA)
  1221. X                {
  1222. X                    /* Do special RING line handling.
  1223. X                       RING generates an int only on the
  1224. X                       trailing edge.
  1225. X                    */
  1226. X                    status = (status & ~MS_RING_PRESENT)
  1227. X                        | (fip->new_msr
  1228. X                            & MS_RING_PRESENT);
  1229. X                    if (status & MS_RING_TEDGE)
  1230. X                        status |= MS_RING_PRESENT;
  1231. X                    if ((status ^ fip->new_msr)
  1232. X                            & MS_ANY_PRESENT)
  1233. X                    {
  1234. X                        /* check hw flow flags */
  1235. X                        fas_fproc (fip, status);
  1236. X                        fip->new_msr = status;
  1237. X                        event_sched (fip, EF_DO_MPROC);
  1238. X                    }
  1239. X                    sysinfo.mdmint++;
  1240. X                }
  1241. X            } while (!(inb (INT_ID_PORT) & II_NO_INTS_PENDING));
  1242. X
  1243. X            /* clear the port interrupt */
  1244. X            if (INT_ACK_PORT)
  1245. X                outb (INT_ACK_PORT, fip->int_ack);
  1246. X
  1247. X            /* schedule character transfer to UNIX buffer */
  1248. X            if (fip->recv_ring_cnt
  1249. X#if defined (HAVE_VPIX)
  1250. X                && (((fip->iflag & DOSMODE)
  1251. X                    ? MAX_VPIX_FILL - MIN_READ_CHUNK
  1252. X                    : MAX_UNIX_FILL - MIN_READ_CHUNK)
  1253. X                        >= fip->tty->t_rawq.c_cc)
  1254. X#else
  1255. X                && ((MAX_UNIX_FILL - MIN_READ_CHUNK)
  1256. X                        >= fip->tty->t_rawq.c_cc)
  1257. X#endif
  1258. X                && !(fip->flow_flags.i & FF_RXFER_STOPPED))
  1259. X            {
  1260. X                event_sched (fip, EF_DO_RXFER);
  1261. X            }
  1262. X
  1263. X            /* check input buffer high/low water marks */
  1264. X            if (fip->recv_ring_cnt != old_recv_count)
  1265. X                fas_ihlw_check (fip);
  1266. X        }
  1267. X    } while (!done);
  1268. X
  1269. X    /* clear the mux interrupt since we have scanned all
  1270. X       of the ports that share this interrupt vector
  1271. X    */    
  1272. X    if (port = fas_mux_ack_port [vect])
  1273. X        outb (port, fas_mux_ack [vect]);
  1274. X
  1275. X    return (0);
  1276. X}
  1277. X
  1278. X/* hardware flow control interrupt handler */
  1279. Xstatic void
  1280. Xfas_fproc (fip, mdm_status)
  1281. Xregister struct fas_info    *fip;
  1282. Xregister uint    mdm_status;
  1283. X{
  1284. X    /* Check the output flow control signals and set the state flag
  1285. X       accordingly.
  1286. X    */
  1287. X    if (!(~mdm_status & fip->flow.m.oc)
  1288. X        || (~mdm_status & fip->flow.m.oe)
  1289. X        || !(fip->flow_flags.i & FF_HWO_HANDSHAKE))
  1290. X    {
  1291. X        if (fip->flow_flags.i & FF_HWO_STOPPED)
  1292. X        {
  1293. X            fip->flow_flags.s &= ~FF_HWO_STOPPED;
  1294. X            fas_xproc (fip);
  1295. X        }
  1296. X    }
  1297. X    else
  1298. X        fip->flow_flags.s |= FF_HWO_STOPPED;
  1299. X}
  1300. X
  1301. X/* modem status handler */
  1302. Xstatic void
  1303. Xfas_mproc (fip)
  1304. Xregister struct fas_info    *fip;
  1305. X{
  1306. X    register struct tty    *ttyp;
  1307. X    register uint    mdm_status;
  1308. X    int    old_level;
  1309. X
  1310. X    ttyp = fip->tty;
  1311. X    mdm_status = fip->new_msr;
  1312. X    fip->new_msr &= ~MS_RING_PRESENT;
  1313. X
  1314. X    /* Check the carrier detect signal and set the state flags
  1315. X       accordingly. Also, if not in clocal mode, send SIGHUP on
  1316. X       carrier loss and flush the buffers.
  1317. X    */
  1318. X    if (!(fip->cflag & CLOCAL))
  1319. X    {
  1320. X        if (!(~mdm_status & fip->modem.m.ca))
  1321. X        {
  1322. X            ttyp->t_state |= CARR_ON;
  1323. X            /* Unblock getty open only if it is ready to run. */
  1324. X            if (ttyp->t_state & WOPEN)
  1325. X                (void) wakeup ((caddr_t) &ttyp->t_canq);
  1326. X        }
  1327. X        else
  1328. X        {
  1329. X            if (!(~fip->msr & fip->modem.m.ca))
  1330. X            {
  1331. X                ttyp->t_state &= ~CARR_ON;
  1332. X                old_level = SPLWRK ();
  1333. X                if (ttyp->t_state & ISOPEN)
  1334. X                    (void) signal (ttyp->t_pgrp, SIGHUP);
  1335. X                (void) ttyflush (ttyp, FREAD | FWRITE);
  1336. X                (void) splx (old_level);
  1337. X            }
  1338. X        }
  1339. X    }
  1340. X
  1341. X    /* Check the unblock signal. If low->high edge, fake CARR_ON state
  1342. X       flag and wake up getty open.
  1343. X    */
  1344. X    if ((fip->o_state & OS_UNBLOCK_ENABLE)
  1345. X        && !(fip->cflag & CLOCAL)
  1346. X        && !(~mdm_status & fip->modem.m.ub)
  1347. X        && (~fip->msr & fip->modem.m.ub)
  1348. X        && (ttyp->t_state & WOPEN))
  1349. X    {
  1350. X        ttyp->t_state |= CARR_ON;
  1351. X        (void) wakeup ((caddr_t) &ttyp->t_canq);
  1352. X    }
  1353. X
  1354. X    fip->msr = mdm_status & ~MS_RING_PRESENT;
  1355. X
  1356. X    /* re-schedule if modem status flags have changed in the mean time */
  1357. X    if ((fip->new_msr ^ fip->msr) & MS_ANY_PRESENT)
  1358. X        event_sched (fip, EF_DO_MPROC);
  1359. X}
  1360. X
  1361. X/* Receiver interrupt handler. Translates input characters to character
  1362. X   sequences as described in TERMIO(7) man page.
  1363. X*/
  1364. Xstatic uint
  1365. Xfas_rproc (fip, line_status)
  1366. Xregister struct fas_info    *fip;
  1367. Xuint    line_status;
  1368. X{
  1369. X    struct tty    *ttyp;
  1370. X    uint    charac;
  1371. X    register uint    csize;
  1372. X    unchar    metta [4];
  1373. X    REGVAR;
  1374. X
  1375. X    ttyp = fip->tty;
  1376. X
  1377. X    /* Translate characters from FIFO according to the TERMIO(7)
  1378. X       man page.
  1379. X    */
  1380. X    do
  1381. X    {
  1382. X        charac = (line_status & LS_RCV_AVAIL)
  1383. X                ? inb (RCV_DATA_PORT)
  1384. X                : 0;    /* was line status int only */
  1385. X
  1386. X        /* do we have to junk the character ? */
  1387. X        if (!(fip->cflag & CREAD) || !(ttyp->t_state & ISOPEN))
  1388. X        {
  1389. X            /* if there are FIFOs we take a short cut */
  1390. X            if (fip->device_flags.i & DF_DEVICE_IS_NS16550)
  1391. X                outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_SETUP
  1392. X                            | NS_FIFO_CLR_RECV);
  1393. X            else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
  1394. X            {
  1395. X                outb (I_BANK_PORT, I_BANK_1);
  1396. X                outb (I_RCM_PORT, I_FIFO_CLR_RECV);
  1397. X                outb (I_BANK_PORT, I_BANK_0);
  1398. X            }
  1399. X            continue;
  1400. X        }
  1401. X
  1402. X        csize = 0;
  1403. X
  1404. X        /* strip off 8th bit ? */
  1405. X        if (fip->iflag & ISTRIP)
  1406. X            charac &= 0x7f;
  1407. X
  1408. X        /* ignore parity errors ? */
  1409. X        if ((line_status & LS_PARITY_ERROR)
  1410. X            && !(fip->iflag & INPCK))
  1411. X            line_status &= ~LS_PARITY_ERROR;
  1412. X
  1413. X        /* do we have some kind of character error ? */
  1414. X        if (line_status & (LS_PARITY_ERROR
  1415. X                    | LS_FRAMING_ERROR
  1416. X                    | LS_BREAK_DETECTED))
  1417. X        {
  1418. X#if defined (HAVE_VPIX)
  1419. X            if ((fip->iflag & (DOSMODE | PARMRK))
  1420. X                    == (DOSMODE | PARMRK))
  1421. X            {
  1422. X                /* send status bits to VP/ix */
  1423. X                (void) fas_vpix_sr (fip, 1,
  1424. X                    line_status & (LS_PARITY_ERROR
  1425. X                            | LS_FRAMING_ERROR
  1426. X                            | LS_BREAK_DETECTED));
  1427. X                /* we don't handle character errors in
  1428. X                   this routine if we are in DOS mode
  1429. X                */
  1430. X                line_status &= ~(LS_PARITY_ERROR
  1431. X                        | LS_FRAMING_ERROR
  1432. X                        | LS_BREAK_DETECTED);
  1433. X                goto valid_char;
  1434. X            }
  1435. X#endif
  1436. X            /* is it a BREAK ? */
  1437. X            if (line_status & LS_BREAK_DETECTED)
  1438. X            {
  1439. X                if (!(fip->iflag & IGNBRK))
  1440. X                    if (fip->iflag & BRKINT)
  1441. X                    {
  1442. X                        /* do BREAK interrupt */
  1443. X                        event_sched (fip, EF_DO_BRKINT);
  1444. X                    }
  1445. X                    else
  1446. X                    {
  1447. X                        metta [csize] = 0;
  1448. X                        csize++;
  1449. X                        if (fip->iflag & PARMRK)
  1450. X                        {
  1451. X                            metta [csize] = 0;
  1452. X                            csize++;
  1453. X                            metta [csize] = 0xff;
  1454. X                            csize++;
  1455. X                        }
  1456. X                    }
  1457. X            }
  1458. X            else if (!(fip->iflag & IGNPAR))
  1459. X                if (fip->iflag & PARMRK)
  1460. X                {
  1461. X                    metta [csize] = charac;
  1462. X                    csize++;
  1463. X                    metta [csize] = 0;
  1464. X                    csize++;
  1465. X                    metta [csize] = 0xff;
  1466. X                    csize++;
  1467. X                }
  1468. X                else
  1469. X                {
  1470. X                    metta [csize] = 0;
  1471. X                    csize++;
  1472. X                }
  1473. X        }
  1474. X        else
  1475. Xvalid_char:
  1476. X        /* is there a character to process ? */
  1477. X        if (line_status & LS_RCV_AVAIL)
  1478. X        {
  1479. X            if (fip->iflag & IXON)
  1480. X            {
  1481. X                /* do output start/stop handling */
  1482. X                if (fip->flow_flags.i & FF_SWO_STOPPED)
  1483. X                {
  1484. X#if defined (HAVE_VPIX)
  1485. X                    if ((charac == fip->v86_ss.ss_start)
  1486. X#else
  1487. X                    if ((charac == CSTART)
  1488. X#endif
  1489. X                        || (fip->iflag & IXANY))
  1490. X                    {
  1491. X                        fip->flow_flags.s &=
  1492. X                            ~FF_SWO_STOPPED;
  1493. X                        ttyp->t_state &= ~TTSTOP;
  1494. X                        /* restart output */
  1495. X                        fas_xproc (fip);
  1496. X                    }
  1497. X                }
  1498. X                else
  1499. X                {
  1500. X#if defined (HAVE_VPIX)
  1501. X                    if (charac == fip->v86_ss.ss_stop)
  1502. X#else
  1503. X                    if (charac == CSTOP)
  1504. X#endif
  1505. X                    {
  1506. X                        fip->flow_flags.s |=
  1507. X                            FF_SWO_STOPPED;
  1508. X                        ttyp->t_state |= TTSTOP;
  1509. X                    }
  1510. X                }
  1511. X                /* we don't put start/stop characters
  1512. X                   into the receiver buffer
  1513. X                */
  1514. X#if defined (HAVE_VPIX)
  1515. X                if ((charac == fip->v86_ss.ss_start)
  1516. X                    || (charac == fip->v86_ss.ss_stop))
  1517. X#else
  1518. X                if ((charac == CSTART)
  1519. X                    || (charac == CSTOP))
  1520. X#endif
  1521. X                    continue;
  1522. X            }
  1523. X
  1524. X            if ((charac == 0xff) && (fip->iflag & PARMRK))
  1525. X            {
  1526. X                metta [csize] = 0xff;
  1527. X                csize++;
  1528. X                metta [csize] = 0xff;
  1529. X                csize++;
  1530. X            }
  1531. X            else
  1532. X            {
  1533. X                /* we take a short-cut if only one character
  1534. X                   has to be put into the receiver buffer
  1535. X                */
  1536. X                if (fip->recv_ring_cnt < RECV_BUFF_SIZE)
  1537. X                {
  1538. X                    fip->recv_ring_cnt++;
  1539. X                    *fip->recv_ring_put_ptr = charac;
  1540. X                    if (++fip->recv_ring_put_ptr
  1541. X                        != &fip->recv_buffer
  1542. X                            [RECV_BUFF_SIZE])
  1543. X                        continue;
  1544. X                    fip->recv_ring_put_ptr =
  1545. X                            &fip->recv_buffer [0];
  1546. X                }
  1547. X                continue;
  1548. X            }
  1549. X        }
  1550. X
  1551. X        if (!(csize) || (fip->recv_ring_cnt + csize > RECV_BUFF_SIZE))
  1552. X            continue;    /* nothing to put into recv buffer */
  1553. X
  1554. X        fip->recv_ring_cnt += csize;
  1555. X
  1556. X        /* store translation in ring buffer */
  1557. X        do
  1558. X        {
  1559. X            do
  1560. X            {
  1561. X                *fip->recv_ring_put_ptr = (metta - 1) [csize];
  1562. X                if (++fip->recv_ring_put_ptr
  1563. X                    == &fip->recv_buffer [RECV_BUFF_SIZE])
  1564. X                    break;
  1565. X            } while (--csize);
  1566. X            if (!csize)
  1567. X                break;
  1568. X            fip->recv_ring_put_ptr = &fip->recv_buffer [0];
  1569. X        } while (--csize);
  1570. X    } while ((line_status = inb (LINE_STATUS_PORT)) & LS_RCV_INT);
  1571. X
  1572. X    return (line_status);
  1573. X}
  1574. X
  1575. X/* Output characters to the transmitter register. */
  1576. Xstatic void
  1577. Xfas_xproc (fip)
  1578. Xregister struct fas_info    *fip;
  1579. X{
  1580. X    register uint    num_to_output;
  1581. X    REGVAR;
  1582. X
  1583. X    /* proceed only if transmitter is available */
  1584. X    if ((fip->device_flags.i & (DF_XMIT_BUSY | DF_XMIT_BREAK
  1585. X                        | DF_XMIT_LOCKED))
  1586. X        || (fip->flow_flags.i & FF_HWO_STOPPED))
  1587. X        goto sched;
  1588. X
  1589. X    /* determine the transmitter FIFO size */
  1590. X    if (fip->device_flags.i & (DF_DEVICE_IS_NS16550
  1591. X                    | DF_DEVICE_IS_I82510))
  1592. X    {
  1593. X        if (fip->device_flags.i & DF_DEVICE_IS_NS16550)
  1594. X            num_to_output = OUTPUT_NS_FIFO_SIZE;
  1595. X        else
  1596. X            num_to_output = OUTPUT_I_FIFO_SIZE;
  1597. X    }
  1598. X    else
  1599. X        num_to_output = 1;
  1600. X
  1601. X    /* handle XON/XOFF input flow control requests */
  1602. X    if (fip->flow_flags.i & FF_SW_FC_REQ)
  1603. X    {
  1604. X#if defined (HAVE_VPIX)
  1605. X        outb (XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED)
  1606. X                    ? fip->v86_ss.ss_stop
  1607. X                    : fip->v86_ss.ss_start);
  1608. X#else
  1609. X        outb (XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED)
  1610. X                    ? CSTOP
  1611. X                    : CSTART);
  1612. X#endif
  1613. X        fip->tty->t_state &= ~(TTXON | TTXOFF);
  1614. X        fip->device_flags.s |= DF_XMIT_BUSY;
  1615. X        fip->flow_flags.s &= ~FF_SW_FC_REQ;
  1616. X        /* disable guard timeout */
  1617. X        if (fip->device_flags.i & DF_GUARD_TIMEOUT)
  1618. X        {
  1619. X            fip->device_flags.s &= ~DF_GUARD_TIMEOUT;
  1620. X            fip->tty->t_state &= ~TIMEOUT;
  1621. X            (void) untimeout (fip->timeout_idx);
  1622. X        }
  1623. X        num_to_output--;
  1624. X    }
  1625. X
  1626. X    /* bail out if output is suspended by XOFF */
  1627. X    if (fip->flow_flags.i & FF_SWO_STOPPED)
  1628. X        goto sched;
  1629. X
  1630. X    /* Determine how many chars to put into the transmitter
  1631. X       register.
  1632. X    */
  1633. X    if (fip->xmit_ring_cnt < num_to_output)
  1634. X        num_to_output = fip->xmit_ring_cnt;
  1635. X
  1636. X    /* no characters available ? */
  1637. X    if (!num_to_output)
  1638. X        goto sched;
  1639. X
  1640. X    /* output characters */
  1641. X    fip->xmit_ring_cnt -= num_to_output;
  1642. X
  1643. X    do
  1644. X    {
  1645. X        do
  1646. X        {
  1647. X            outb (XMT_DATA_PORT, *fip->xmit_ring_take_ptr);
  1648. X            if (++fip->xmit_ring_take_ptr
  1649. X                    == &fip->xmit_buffer [XMIT_BUFF_SIZE])
  1650. X                break;
  1651. X        } while (--num_to_output);
  1652. X        if (!num_to_output)
  1653. X            break;
  1654. X        fip->xmit_ring_take_ptr = &fip->xmit_buffer [0];
  1655. X    } while (--num_to_output);
  1656. X
  1657. X    /* signal that transmitter is busy now */
  1658. X    fip->device_flags.s |= DF_XMIT_BUSY;
  1659. X    /* disable guard timeout */
  1660. X    if (fip->device_flags.i & DF_GUARD_TIMEOUT)
  1661. X    {
  1662. X        fip->device_flags.s &= ~DF_GUARD_TIMEOUT;
  1663. X        fip->tty->t_state &= ~TIMEOUT;
  1664. X        (void) untimeout (fip->timeout_idx);
  1665. X    }
  1666. X
  1667. X    /* schedule fas_xxfer () if there are more characters to transfer
  1668. X       into the transmitter ring buffer
  1669. X    */
  1670. Xsched:
  1671. X    if ((fip->xmit_ring_size > fip->xmit_ring_cnt)
  1672. X        && (fip->tty->t_outq.c_cc || fip->tty->t_tbuf.c_count))
  1673. X    {
  1674. X        event_sched (fip, EF_DO_XXFER);
  1675. X    }
  1676. X}
  1677. X
  1678. X/* Asynchronous event handler. Scheduled by functions that can't do the
  1679. X   processing themselves because of execution time restrictions.
  1680. X*/
  1681. Xstatic void
  1682. Xfas_event (fip)
  1683. Xregister struct fas_info    *fip;
  1684. X{
  1685. X    int    old_level;
  1686. X
  1687. X    old_level = SPLINT ();
  1688. X
  1689. X    do
  1690. X    {
  1691. X        /* do the break interrupt */
  1692. X        if (fip->event_flags.i & EF_DO_BRKINT)
  1693. X        {
  1694. X            fip->event_flags.s &= ~EF_DO_BRKINT;
  1695. X            if (fip->tty->t_state & ISOPEN)
  1696. X            {
  1697. X                (void) SPLWRK ();
  1698. X                (*linesw [fip->tty->t_line].l_input)
  1699. X                            (fip->tty, L_BREAK);
  1700. X                (void) SPLINT ();
  1701. X            }
  1702. X        }
  1703. X
  1704. X        /* transfer characters to the UNIX input buffer */
  1705. X        if (fip->event_flags.i & EF_DO_RXFER)
  1706. X        {
  1707. X            fip->event_flags.s &= ~EF_DO_RXFER;
  1708. X            if (!(fip->flow_flags.i & FF_RXFER_STOPPED))
  1709. X            {
  1710. X                (void) SPLWRK ();
  1711. X                fas_rxfer (fip);
  1712. X                (void) SPLINT ();
  1713. X                /* check input buffer high/low water marks */
  1714. X                fas_ihlw_check (fip);
  1715. X            }
  1716. X        }
  1717. X
  1718. X        /* transfer characters to the output ring buffer */
  1719. X        if (fip->event_flags.i & EF_DO_XXFER)
  1720. X        {
  1721. X            fip->event_flags.s &= ~EF_DO_XXFER;
  1722. X            (void) SPLWRK ();
  1723. X            fas_xxfer (fip);
  1724. X            (void) SPLINT ();
  1725. X            /* output characters */
  1726. X            fas_xproc (fip);
  1727. X        }
  1728. X
  1729. X        /* check the modem signals */
  1730. X        if (fip->event_flags.i & EF_DO_MPROC)
  1731. X        {
  1732. X            fip->event_flags.s &= ~EF_DO_MPROC;
  1733. X            fas_mproc (fip);
  1734. X#if defined (HAVE_VPIX)
  1735. X            if (((fip->iflag & (DOSMODE | PARMRK))
  1736. X                    == (DOSMODE | PARMRK))
  1737. X                && (fip->v86_intmask != V86VI_KBD))
  1738. X            {
  1739. X                /* send status bits to VP/ix */
  1740. X                if (fas_vpix_sr (fip, 2, fip->msr))
  1741. X                    fip->event_flags.s |= EF_DO_RXFER;
  1742. X            }
  1743. X#endif
  1744. X        }
  1745. X
  1746. X#if defined (HAVE_VPIX)
  1747. X        /* send pseudorupt to VP/ix */
  1748. X        if (fip->event_flags.i & EF_SIGNAL_VPIX)
  1749. X        {
  1750. X            fip->event_flags.s &= ~EF_SIGNAL_VPIX;
  1751. X            if ((fip->iflag & DOSMODE) && fip->v86_proc)
  1752. X            {
  1753. X                (void) SPLWRK ();
  1754. X                (void) v86setint (fip->v86_proc,
  1755. X                            fip->v86_intmask);
  1756. X                (void) SPLINT ();
  1757. X            }
  1758. X        }
  1759. X#endif
  1760. X    } while (fip->event_flags.i & EF_EVENT_MASK);    /* all done ? */
  1761. X
  1762. X    fip->event_flags.s &= ~EF_EVENT_SCHEDULED;
  1763. X    (void) splx (old_level);
  1764. X}
  1765. X
  1766. X#if defined (HAVE_VPIX)
  1767. X/* Send port status register to VP/ix */
  1768. Xstatic int
  1769. Xfas_vpix_sr (fip, token, status)
  1770. Xregister struct fas_info    *fip;
  1771. Xuint    token;
  1772. Xuint    status;
  1773. X{
  1774. X    if ((fip->recv_ring_cnt <= RECV_BUFF_SIZE - 3)
  1775. X        && (fip->tty->t_state & ISOPEN))
  1776. X    {
  1777. X        /* sent the character sequence 0xff, <token>, <status>
  1778. X           to VP/ix
  1779. X        */
  1780. X        fip->recv_ring_cnt += 3;
  1781. X
  1782. X        *fip->recv_ring_put_ptr = 0xff;
  1783. X        if (++fip->recv_ring_put_ptr
  1784. X                == &fip->recv_buffer [RECV_BUFF_SIZE])
  1785. X            fip->recv_ring_put_ptr
  1786. X                = &fip->recv_buffer [0];
  1787. X        *fip->recv_ring_put_ptr = token;
  1788. X        if (++fip->recv_ring_put_ptr
  1789. X                == &fip->recv_buffer [RECV_BUFF_SIZE])
  1790. X            fip->recv_ring_put_ptr
  1791. X                = &fip->recv_buffer [0];
  1792. X        *fip->recv_ring_put_ptr = status;
  1793. X        if (++fip->recv_ring_put_ptr
  1794. X                == &fip->recv_buffer [RECV_BUFF_SIZE])
  1795. X            fip->recv_ring_put_ptr
  1796. X                = &fip->recv_buffer [0];
  1797. X        return (TRUE);
  1798. X    }
  1799. X    return (FALSE);
  1800. X}
  1801. X#endif
  1802. X
  1803. X/* Receiver ring buffer -> UNIX buffer transfer function. */
  1804. Xstatic void
  1805. Xfas_rxfer (fip)
  1806. Xregister struct fas_info    *fip;
  1807. X{
  1808. X    register struct tty    *ttyp;
  1809. X    register int    num_to_xfer;
  1810. X    int    num_save;
  1811. X    int    old_level;
  1812. X
  1813. X    ttyp = fip->tty;
  1814. X
  1815. X    for (;;)
  1816. X    {
  1817. X        if (!fip->recv_ring_cnt || !ttyp->t_rbuf.c_ptr)
  1818. X            break;    /* no characters to transfer */
  1819. X
  1820. X        /* determine how many characters to transfer */
  1821. X#if defined (HAVE_VPIX)
  1822. X        num_to_xfer = ((fip->iflag & DOSMODE)
  1823. X                ? MAX_VPIX_FILL
  1824. X                : MAX_UNIX_FILL) - ttyp->t_rawq.c_cc;
  1825. X#else
  1826. X        num_to_xfer = MAX_UNIX_FILL - ttyp->t_rawq.c_cc;
  1827. X#endif
  1828. X
  1829. X        if (num_to_xfer < MIN_READ_CHUNK)
  1830. X            break;    /* input buffer full */
  1831. X
  1832. X#if defined (HAVE_VPIX)
  1833. X        /* wakeup VP/ix */
  1834. X        if ((fip->iflag & DOSMODE) && !ttyp->t_rawq.c_cc)
  1835. X            event_sched (fip, EF_SIGNAL_VPIX);
  1836. X#endif
  1837. X
  1838. X        /* determine how many characters are in one contigous block */
  1839. X        if (fip->recv_ring_cnt < num_to_xfer)
  1840. X            num_to_xfer = fip->recv_ring_cnt;
  1841. X        if (&fip->recv_buffer [RECV_BUFF_SIZE] - fip->recv_ring_take_ptr
  1842. X            < num_to_xfer)
  1843. X            num_to_xfer = &fip->recv_buffer [RECV_BUFF_SIZE]
  1844. X                    - fip->recv_ring_take_ptr;
  1845. X        if (ttyp->t_rbuf.c_count < num_to_xfer)
  1846. X            num_to_xfer = ttyp->t_rbuf.c_count;
  1847. X
  1848. X        num_save = num_to_xfer;
  1849. X        ttyp->t_rbuf.c_count -= num_to_xfer;
  1850. X
  1851. X        /* do the transfer */
  1852. X        do
  1853. X        {
  1854. X            *ttyp->t_rbuf.c_ptr = *fip->recv_ring_take_ptr;
  1855. X            ttyp->t_rbuf.c_ptr++;
  1856. X            fip->recv_ring_take_ptr++;
  1857. X        } while (--num_to_xfer);
  1858. X
  1859. X        if (fip->recv_ring_take_ptr == &fip->recv_buffer [RECV_BUFF_SIZE])
  1860. X            fip->recv_ring_take_ptr = &fip->recv_buffer [0];
  1861. X
  1862. X        intr_disable ();
  1863. X        fip->recv_ring_cnt -= num_save;
  1864. X        intr_restore ();
  1865. X
  1866. X        ttyp->t_rbuf.c_ptr -= ttyp->t_rbuf.c_size
  1867. X                    - ttyp->t_rbuf.c_count;
  1868. X        (*linesw [ttyp->t_line].l_input) (ttyp, L_BUF);
  1869. X    }
  1870. X}
  1871. X
  1872. X/* UNIX buffer -> transmitter ring buffer transfer function. */
  1873. Xstatic void
  1874. Xfas_xxfer (fip)
  1875. Xregister struct fas_info    *fip;
  1876. X{
  1877. X    register struct tty    *ttyp;
  1878. X    register int    num_to_xfer;
  1879. X    int    num_save;
  1880. X    int    old_level;
  1881. X
  1882. X    ttyp = fip->tty;
  1883. X
  1884. X    for (;;)
  1885. X    {
  1886. X        /* Check if tbuf is empty. If it is empty, reset buffer
  1887. X           pointer and counter and get the next chunk of output
  1888. X           characters.
  1889. X        */
  1890. X        if (!ttyp->t_tbuf.c_ptr || !ttyp->t_tbuf.c_count)
  1891. X        {
  1892. X            if (ttyp->t_tbuf.c_ptr)
  1893. X                ttyp->t_tbuf.c_ptr -= ttyp->t_tbuf.c_size;
  1894. X            if (!((*linesw [ttyp->t_line].l_output) (ttyp)
  1895. X                    & CPRES))
  1896. X                break;
  1897. X        }
  1898. X
  1899. X        /* set the maximum character limit */
  1900. X        num_to_xfer = fip->xmit_ring_size - fip->xmit_ring_cnt;
  1901. X
  1902. X        /* Return if transmitter ring buffer is full. */
  1903. X        if (num_to_xfer < 1)
  1904. X            break;
  1905. X
  1906. X        /* Determine how many chars to transfer this time. */
  1907. X        if (&fip->xmit_buffer [XMIT_BUFF_SIZE] - fip->xmit_ring_put_ptr
  1908. X            < num_to_xfer)
  1909. X            num_to_xfer = &fip->xmit_buffer [XMIT_BUFF_SIZE]
  1910. X                    - fip->xmit_ring_put_ptr;
  1911. X        if (ttyp->t_tbuf.c_count < num_to_xfer)
  1912. X            num_to_xfer = ttyp->t_tbuf.c_count;
  1913. X
  1914. X        num_save = num_to_xfer;
  1915. X        ttyp->t_tbuf.c_count -= num_to_xfer;
  1916. X        ttyp->t_state |= BUSY;
  1917. X
  1918. X        /* do the transfer */
  1919. X        do
  1920. X        {
  1921. X            *fip->xmit_ring_put_ptr = *ttyp->t_tbuf.c_ptr;
  1922. X            ttyp->t_tbuf.c_ptr++;
  1923. X            fip->xmit_ring_put_ptr++;
  1924. X        } while (--num_to_xfer);
  1925. X
  1926. X        if (fip->xmit_ring_put_ptr == &fip->xmit_buffer [XMIT_BUFF_SIZE])
  1927. X            fip->xmit_ring_put_ptr = &fip->xmit_buffer [0];
  1928. X
  1929. X        intr_disable ();
  1930. X        fip->xmit_ring_cnt += num_save;
  1931. X        intr_restore ();
  1932. X    }
  1933. X}
  1934. X
  1935. X/* Input buffer high/low water mark check. */
  1936. Xstatic void
  1937. Xfas_ihlw_check (fip)
  1938. Xregister struct fas_info    *fip;
  1939. X{
  1940. X    REGVAR;
  1941. X
  1942. X#if defined (HAVE_VPIX)
  1943. X    /* don't touch the mcr if we are in dos mode and hardware input
  1944. X       handshake is disabled (dos handles the handshake line(s)
  1945. X       on its own in this mode)
  1946. X    */
  1947. X    if ((fip->iflag & DOSMODE) && !(fip->flow_flags.i & FF_HWI_HANDSHAKE))
  1948. X        goto swflow;
  1949. X#endif
  1950. X    if (fip->flow_flags.i & FF_HWI_STOPPED)
  1951. X    {
  1952. X        /* If input buffer level has dropped below
  1953. X           the low water mark and input was stopped
  1954. X           by hardware handshake, restart input.
  1955. X        */
  1956. X        if (!(fip->flow_flags.i & FF_HWI_HANDSHAKE)
  1957. X            || (fip->recv_ring_cnt < HW_LOW_WATER))
  1958. X        {
  1959. X            fip->mcr |= fip->flow.m.ic;
  1960. X            outb (MDM_CTL_PORT, fip->mcr);
  1961. X            fip->flow_flags.s &= ~FF_HWI_STOPPED;
  1962. X        }
  1963. X    }
  1964. X    else
  1965. X    {
  1966. X        /* If input buffer level has risen above the
  1967. X           high water mark and input is not yet
  1968. X           stopped, stop input by hardware handshake.
  1969. X        */
  1970. X        if ((fip->flow_flags.i & FF_HWI_HANDSHAKE)
  1971. X            && (fip->recv_ring_cnt > HW_HIGH_WATER))
  1972. X        {
  1973. X            fip->mcr &= ~fip->flow.m.ic;
  1974. X            outb (MDM_CTL_PORT, fip->mcr);
  1975. X            fip->flow_flags.s |= FF_HWI_STOPPED;
  1976. X        }
  1977. X    }
  1978. X
  1979. Xswflow:
  1980. X    if (fip->flow_flags.i & FF_SWI_STOPPED)
  1981. X    {
  1982. X        /* If input buffer level has dropped below
  1983. X           the low water mark and input was stopped
  1984. X           by XOFF, send XON to restart input.
  1985. X        */
  1986. X        if (!(fip->iflag & IXOFF)
  1987. X            || (fip->recv_ring_cnt < SW_LOW_WATER))
  1988. X        {
  1989. X            fip->flow_flags.s &= ~FF_SWI_STOPPED;
  1990. X            fip->flow_flags.s ^= FF_SW_FC_REQ;
  1991. X            if (fip->flow_flags.i & FF_SW_FC_REQ)
  1992. X            {
  1993. X                fip->tty->t_state |= TTXON;
  1994. X                fas_xproc (fip);
  1995. X            }
  1996. X            else
  1997. X                fip->tty->t_state &= ~TTXOFF;
  1998. X        }
  1999. X    }
  2000. X    else
  2001. X    {
  2002. X        /* If input buffer level has risen above the
  2003. X           high water mark and input is not yet
  2004. X           stopped, send XOFF to stop input.
  2005. X        */
  2006. X        if ((fip->iflag & IXOFF)
  2007. X            && (fip->recv_ring_cnt > SW_HIGH_WATER))
  2008. X        {
  2009. X            fip->flow_flags.s |= FF_SWI_STOPPED;
  2010. X            fip->flow_flags.s ^= FF_SW_FC_REQ;
  2011. X            if (fip->flow_flags.i & FF_SW_FC_REQ)
  2012. X            {
  2013. X                fip->tty->t_state |= TTXOFF;
  2014. X                fas_xproc (fip);
  2015. X            }
  2016. X            else
  2017. X                fip->tty->t_state &= ~TTXON;
  2018. X        }
  2019. X    }
  2020. X}
  2021. X
  2022. X/* Handle hangup after last close */
  2023. Xstatic void
  2024. Xfas_hangup (fip)
  2025. Xregister struct fas_info    *fip;
  2026. X{
  2027. X    int    old_level;
  2028. X    REGVAR;
  2029. X
  2030. X    old_level = SPLINT ();
  2031. X
  2032. X    if (fip->device_flags.i & DF_MODEM_ENABLED)
  2033. X    {
  2034. X        fip->mcr &= ~(fip->modem.m.en
  2035. X                | fip->flow.m.ic);
  2036. X        outb (MDM_CTL_PORT, fip->mcr);
  2037. X        fip->device_flags.s &= ~DF_MODEM_ENABLED;
  2038. X        (void) timeout (fas_hangup, fip, HANGUP_TIME);
  2039. X    }
  2040. X    else
  2041. X    {
  2042. X        fip->device_flags.s &= ~DF_DO_HANGUP;
  2043. X        /* If there was a waiting getty open on this
  2044. X           port, reopen the physical device.
  2045. X        */
  2046. X        if (fip->o_state & OS_WAIT_OPEN)
  2047. X        {
  2048. X            fas_open_device (fip);
  2049. X            fas_param (fip);    /* set up port regs */
  2050. X            fas_mproc (fip);    /* set up mdm stat flags */
  2051. X        }
  2052. X        release_device_lock (fip);
  2053. X    }
  2054. X    (void) splx (old_level);
  2055. X}
  2056. X
  2057. X/* main timeout function */
  2058. Xstatic void
  2059. Xfas_timeout (fip)
  2060. Xregister struct fas_info    *fip;
  2061. X{
  2062. X    int    old_level;
  2063. X    REGVAR;
  2064. X
  2065. X    old_level = SPLINT ();
  2066. X
  2067. X    /* handle break request */
  2068. X    if (fip->device_flags.i & DF_DO_BREAK)
  2069. X    {
  2070. X        /* set up break request flags */
  2071. X        fip->lcr |= LC_SET_BREAK_LEVEL;
  2072. X        outb (LINE_CTL_PORT, fip->lcr);
  2073. X        fip->device_flags.s &= ~(DF_DO_BREAK | DF_GUARD_TIMEOUT);
  2074. X        (void) timeout (fas_timeout, fip, BREAK_TIME);
  2075. X        (void) splx (old_level);
  2076. X        return;
  2077. X    }
  2078. X
  2079. X    /* reset break state */
  2080. X    if (fip->device_flags.i & DF_XMIT_BREAK)
  2081. X    {
  2082. X        if (fip->lcr & LC_SET_BREAK_LEVEL)
  2083. X        {
  2084. X            fip->lcr &= ~LC_SET_BREAK_LEVEL;
  2085. X            outb (LINE_CTL_PORT, fip->lcr);
  2086. X            fip->device_flags.s |= DF_GUARD_TIMEOUT;
  2087. X            fip->timeout_idx = timeout (fas_timeout, fip,
  2088. X                    fas_ctimes [fip->cflag & CBAUD]);
  2089. X            (void) splx (old_level);
  2090. X            return;
  2091. X        }
  2092. X        fip->device_flags.s &= ~DF_XMIT_BREAK;
  2093. X        /* restart output after BREAK */
  2094. X        fas_xproc (fip);
  2095. X    }
  2096. X
  2097. X    /* handle character guard timeout */
  2098. X    if (fip->device_flags.i & DF_GUARD_TIMEOUT)
  2099. X    {
  2100. X        fip->device_flags.s &= ~DF_GUARD_TIMEOUT;
  2101. X        if (!fip->xmit_ring_cnt
  2102. X            && !fip->tty->t_outq.c_cc
  2103. X            && !fip->tty->t_tbuf.c_count)
  2104. X        {
  2105. X            fip->tty->t_state &= ~BUSY;
  2106. X        }
  2107. X    }
  2108. X
  2109. X    fip->tty->t_state &= ~TIMEOUT;
  2110. X
  2111. X    event_sched (fip, EF_DO_XXFER);
  2112. X
  2113. X    (void) wakeup ((caddr_t) &(fip)->device_flags.i);
  2114. X    (void) splx (old_level);
  2115. X}
  2116. X
  2117. X/* Several functions for flow control, character output and special event
  2118. X   requests and handling.
  2119. X*/
  2120. Xstatic void
  2121. Xfas_cmd (fip, ttyp, arg2)
  2122. Xregister struct fas_info    *fip;
  2123. Xregister struct tty    *ttyp;
  2124. Xint    arg2;
  2125. X{
  2126. X    REGVAR;
  2127. X
  2128. X    switch (arg2)
  2129. X    {
  2130. X    case T_TIME:    /* timeout */
  2131. X        goto start_output;
  2132. X
  2133. X    case T_OUTPUT:    /* output characters to the transmitter */
  2134. X        if (fip->xmit_ring_size > fip->xmit_ring_cnt)
  2135. X        {
  2136. Xstart_output:
  2137. X            event_sched (fip, EF_DO_XXFER);
  2138. X        }
  2139. X        break;
  2140. X
  2141. X    case T_SUSPEND:    /* suspend character output */
  2142. X        fip->flow_flags.s |= FF_SWO_STOPPED;
  2143. X        ttyp->t_state |= TTSTOP;
  2144. X        break;
  2145. X
  2146. X    case T_RESUME:    /* restart character output */
  2147. X        fip->flow_flags.s &= ~FF_SWO_STOPPED;
  2148. X        ttyp->t_state &= ~TTSTOP;
  2149. X        fas_xproc (fip);
  2150. X        break;
  2151. X
  2152. X    case T_BLOCK:    /* stop character input, request XOFF */
  2153. X        ttyp->t_state |= TBLOCK;
  2154. X        break;    /* note: we do our own XON/XOFF */
  2155. X
  2156. X    case T_UNBLOCK:    /* restart character input, request XON */
  2157. X        ttyp->t_state &= ~TBLOCK;
  2158. X        break;    /* note: we do our own XON/XOFF */
  2159. X
  2160. X    case T_RFLUSH:    /* flush input buffers and restart input */
  2161. X        if (fip->device_flags.i & DF_DEVICE_IS_NS16550)
  2162. X            outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_SETUP
  2163. X                        | NS_FIFO_CLR_RECV);
  2164. X        else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
  2165. X        {
  2166. X            outb (I_BANK_PORT, I_BANK_1);
  2167. X            outb (I_RCM_PORT, I_FIFO_CLR_RECV);
  2168. X            outb (I_BANK_PORT, I_BANK_0);
  2169. X        }
  2170. X
  2171. X        fip->recv_ring_take_ptr = fip->recv_ring_put_ptr;
  2172. X        fip->recv_ring_cnt = 0;
  2173. X
  2174. X        if (fip->flow_flags.i & FF_HWI_STOPPED)
  2175. X        {
  2176. X            fip->mcr |= fip->flow.m.ic;
  2177. X            outb (MDM_CTL_PORT, fip->mcr);
  2178. X            fip->flow_flags.s &= ~FF_HWI_STOPPED;
  2179. X        }
  2180. X
  2181. X        ttyp->t_state &= ~TBLOCK;
  2182. X
  2183. X        if (fip->flow_flags.i & FF_SWI_STOPPED)
  2184. X        {
  2185. X            fip->flow_flags.s &= ~FF_SWI_STOPPED;
  2186. X            fip->flow_flags.s ^= FF_SW_FC_REQ;
  2187. X            if (fip->flow_flags.i & FF_SW_FC_REQ)
  2188. X            {
  2189. X                ttyp->t_state |= TTXON;
  2190. X                fas_xproc (fip);
  2191. X            }
  2192. X            else
  2193. X                ttyp->t_state &= ~TTXOFF;
  2194. X        }
  2195. X        break;
  2196. X
  2197. X    case T_WFLUSH:    /* flush output buffer and restart output */
  2198. X        if (fip->device_flags.i & DF_DEVICE_IS_NS16550)
  2199. X            outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_SETUP
  2200. X                        | NS_FIFO_CLR_XMIT);
  2201. X        else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
  2202. X        {
  2203. X            outb (I_BANK_PORT, I_BANK_1);
  2204. X            outb (I_TCM_PORT, I_FIFO_CLR_XMIT);
  2205. X            outb (I_BANK_PORT, I_BANK_0);
  2206. X        }
  2207. X
  2208. X        fip->xmit_ring_take_ptr = fip->xmit_ring_put_ptr;
  2209. X        fip->xmit_ring_cnt = 0;
  2210. X
  2211. X        fip->flow_flags.s &= ~FF_SWO_STOPPED;
  2212. X        ttyp->t_state &= ~TTSTOP;
  2213. X
  2214. X        if (ttyp->t_tbuf.c_ptr)
  2215. X            ttyp->t_tbuf.c_ptr += ttyp->t_tbuf.c_count;
  2216. X        ttyp->t_tbuf.c_count = 0;
  2217. X
  2218. X        if (!(fip->device_flags.i & (DF_XMIT_BUSY | DF_GUARD_TIMEOUT))
  2219. X            && (ttyp->t_state & BUSY))
  2220. X        {
  2221. X            ttyp->t_state &= ~BUSY;
  2222. X            goto start_output;
  2223. X        }
  2224. X        break;
  2225. X
  2226. X    case T_BREAK:    /* do a break on the transmitter line */
  2227. X        fip->device_flags.s |= DF_XMIT_BREAK;
  2228. X        ttyp->t_state |= TIMEOUT;
  2229. X        if (fip->device_flags.i & (DF_XMIT_BUSY | DF_GUARD_TIMEOUT))
  2230. X        {
  2231. X            fip->device_flags.s |= DF_DO_BREAK;
  2232. X        }
  2233. X        else
  2234. X        {
  2235. X            /* set up break request flags */
  2236. X            fip->lcr |= LC_SET_BREAK_LEVEL;
  2237. X            outb (LINE_CTL_PORT, fip->lcr);
  2238. X            (void) timeout (fas_timeout, fip, BREAK_TIME);
  2239. X        }
  2240. X        break;
  2241. X
  2242. X    case T_PARM:    /* set up the port according to the termio structure */
  2243. X        fas_param (fip);
  2244. X        break;
  2245. X
  2246. X    case T_SWTCH:    /* handle layer switch request */
  2247. X        break;
  2248. X    }
  2249. X}
  2250. X
  2251. X/* open device physically */
  2252. Xstatic void
  2253. Xfas_open_device (fip)
  2254. Xregister struct fas_info    *fip;
  2255. X{
  2256. X    REGVAR;
  2257. X
  2258. X    fip->device_flags.s &= DF_DEVICE_CONFIGURED | DF_DEVICE_IS_NS16550
  2259. X                | DF_DEVICE_IS_I82510 | DF_DEVICE_LOCKED;
  2260. X    fip->flow_flags.s = 0;
  2261. X    fip->cflag = 0;
  2262. X    fip->iflag = 0;
  2263. X    fip->recv_ring_take_ptr = fip->recv_ring_put_ptr;
  2264. X    fip->recv_ring_cnt = 0;
  2265. X    fip->xmit_ring_take_ptr = fip->xmit_ring_put_ptr;
  2266. X    fip->xmit_ring_cnt = 0;
  2267. X
  2268. X    /* hook into the interrupt users chain */
  2269. X    fip->next_int_user = fas_first_int_user [fip->vec];
  2270. X    if (fip->next_int_user)
  2271. X        fip->next_int_user->prev_int_user = fip;
  2272. X    fas_first_int_user [fip->vec] = fip;
  2273. X    fip->prev_int_user = (struct fas_info *) NULL;
  2274. X
  2275. X    fip->lcr = 0;
  2276. X    outb (LINE_CTL_PORT, fip->lcr);
  2277. X
  2278. X    if (fip->device_flags.i & DF_DEVICE_IS_NS16550)
  2279. X        outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_CLEAR);
  2280. X    else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
  2281. X    {
  2282. X        outb (I_BANK_PORT, I_BANK_1);
  2283. X        outb (I_TCM_PORT, I_FIFO_CLR_XMIT);
  2284. X        outb (I_RCM_PORT, I_FIFO_CLR_RECV);
  2285. X        outb (I_BANK_PORT, I_BANK_2);
  2286. X        outb (I_IDM_PORT, STANDARD_I_FIFO_CLEAR);
  2287. X        outb (I_BANK_PORT, I_BANK_0);
  2288. X    }
  2289. X
  2290. X    /* clear interrupts */
  2291. X    inb (MDM_STATUS_PORT);
  2292. X    inb (RCV_DATA_PORT);
  2293. X    inb (RCV_DATA_PORT);
  2294. X    inb (LINE_STATUS_PORT);
  2295. X    inb (INT_ID_PORT);
  2296. X    if (INT_ACK_PORT)
  2297. X        outb (INT_ACK_PORT, fip->int_ack);
  2298. X
  2299. X    if (fip->device_flags.i & DF_DEVICE_IS_NS16550)
  2300. X        outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_SETUP);
  2301. X    else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
  2302. X    {
  2303. X        outb (I_BANK_PORT, I_BANK_2);
  2304. X        outb (I_IDM_PORT, STANDARD_I_FIFO_SETUP);
  2305. X        outb (I_BANK_PORT, I_BANK_0);
  2306. X    }
  2307. X
  2308. X    fip->msr = fip->new_msr = inb (MDM_STATUS_PORT)
  2309. X                    & (MS_CTS_PRESENT
  2310. X                        | MS_DSR_PRESENT
  2311. X                        | MS_DCD_PRESENT);
  2312. X
  2313. X    fip->ier = IE_INIT_MODE;
  2314. X    outb (INT_ENABLE_PORT, fip->ier);
  2315. X
  2316. X    fip->mcr |= fip->modem.m.en | fip->flow.m.ic;
  2317. X    outb (MDM_CTL_PORT, fip->mcr);
  2318. X
  2319. X    fip->device_flags.s |= DF_DEVICE_OPEN | DF_MODEM_ENABLED;
  2320. X}
  2321. X
  2322. X/* close device physically */
  2323. Xstatic void
  2324. Xfas_close_device (fip)
  2325. Xregister struct fas_info    *fip;
  2326. X{
  2327. X    REGVAR;
  2328. X
  2329. X    fip->device_flags.s &= ~DF_DEVICE_OPEN;
  2330. X    fip->ier = IE_NONE;    /* disable all ints from UART */
  2331. X    outb (INT_ENABLE_PORT, fip->ier);
  2332. X    if (INT_ACK_PORT)
  2333. X        outb (INT_ACK_PORT, fip->int_ack);
  2334. X
  2335. X    if (fip->device_flags.i & DF_DEVICE_IS_NS16550)
  2336. X        outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_CLEAR);
  2337. X    else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
  2338. X    {
  2339. X        outb (I_BANK_PORT, I_BANK_1);
  2340. X        outb (I_TCM_PORT, I_FIFO_CLR_XMIT);
  2341. X        outb (I_RCM_PORT, I_FIFO_CLR_RECV);
  2342. X        outb (I_BANK_PORT, I_BANK_2);
  2343. X        outb (I_IDM_PORT, STANDARD_I_FIFO_CLEAR);
  2344. X        outb (I_BANK_PORT, I_BANK_0);
  2345. X    }
  2346. X
  2347. X    /* reset break level */
  2348. X    fip->lcr &= ~LC_SET_BREAK_LEVEL;
  2349. X    outb (LINE_CTL_PORT, fip->lcr);
  2350. X
  2351. X    /* unhook from interrupt users chain */
  2352. X    if (fip->prev_int_user)
  2353. X        fip->prev_int_user->next_int_user = fip->next_int_user;
  2354. X    else
  2355. X        fas_first_int_user [fip->vec] = fip->next_int_user;
  2356. X    if (fip->next_int_user)
  2357. X        fip->next_int_user->prev_int_user = fip->prev_int_user;
  2358. X
  2359. X    if (fip->cflag & HUPCL)
  2360. X    {
  2361. X        /* request hangup */
  2362. X        fip->device_flags.s |= DF_DO_HANGUP;
  2363. X        (void) timeout (fas_hangup, fip, HANGUP_DELAY);
  2364. X    }
  2365. X}
  2366. X
  2367. X/* test device thoroughly */
  2368. Xstatic int
  2369. Xfas_test_device (fip)
  2370. Xregister struct fas_info    *fip;
  2371. X{
  2372. X    register unchar    *cptr;
  2373. X    int    done, delay_count, i;
  2374. X    static uint    lcrval [3] =
  2375. X    {
  2376. X        LC_WORDLEN_8,
  2377. X        LC_WORDLEN_8 | LC_ENABLE_PARITY,
  2378. X        LC_WORDLEN_8 | LC_ENABLE_PARITY | LC_EVEN_PARITY
  2379. X    };
  2380. X    REGVAR;
  2381. X
  2382. X    /* make sure FIFO is off */
  2383. X    outb (NS_FIFO_CTL_PORT, STANDARD_NS_FIFO_CLEAR);
  2384. X    outb (I_BANK_PORT, I_BANK_2);
  2385. X    outb (I_IDM_PORT, STANDARD_I_FIFO_CLEAR);
  2386. X    outb (I_BANK_PORT, I_BANK_0);
  2387. X
  2388. X    /* set counter divisor */
  2389. X    outb (LINE_CTL_PORT, LC_ENABLE_DIVISOR);
  2390. X    outb (DIVISOR_LSB_PORT, fas_speeds [B38400]);
  2391. X    outb (DIVISOR_MSB_PORT, fas_speeds [B38400] >> 8);
  2392. X    outb (LINE_CTL_PORT, 0);
  2393. X
  2394. X    /* switch to local loopback */
  2395. X    outb (MDM_CTL_PORT, MC_SET_LOOPBACK);
  2396. X
  2397. X    done = 0;
  2398. X
  2399. X    /* wait until the transmitter register is empty */
  2400. X    for (delay_count = 20000;
  2401. X        delay_count && (~inb (LINE_STATUS_PORT)
  2402. X                & (LS_XMIT_AVAIL | LS_XMIT_COMPLETE));
  2403. X        delay_count--)
  2404. X        ;
  2405. X
  2406. X    if (!delay_count)
  2407. X        done = 1;
  2408. X
  2409. X    if (!done)
  2410. X    {
  2411. X        /* clear flags */
  2412. X        inb (RCV_DATA_PORT);
  2413. X        inb (RCV_DATA_PORT);
  2414. X        inb (LINE_STATUS_PORT);
  2415. X
  2416. X        /* make sure there are no more characters in the
  2417. X           receiver register
  2418. X        */
  2419. X        for (delay_count = 20000;
  2420. X            delay_count && !(inb (LINE_STATUS_PORT) & LS_RCV_AVAIL);
  2421. X            delay_count--)
  2422. X            ;
  2423. X
  2424. X        if (delay_count)
  2425. X            inb (RCV_DATA_PORT);
  2426. X
  2427. X        /* test pattern */
  2428. X        cptr = (unchar *) "\377\125\252\045\244\0";
  2429. X
  2430. X        do
  2431. X        {
  2432. X            for (i = 0; i < 3; i++)
  2433. X            {
  2434. X                /* test transmitter and receiver
  2435. SHAR_EOF
  2436. true || echo 'restore of fas.c failed'
  2437. fi
  2438. echo 'End of  part 2'
  2439. echo 'File fas.c is continued in part 3'
  2440. echo 3 > _shar_seq_.tmp
  2441. exit 0
  2442. -- 
  2443. Uwe Doering  |  Domain   : gemini@geminix.in-berlin.de
  2444. Berlin       |----------------------------------------------------------------
  2445. Germany      |  Bangpath : ...!unido!fub!tmpmbx!geminix!gemini
  2446.