home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3534 < prev    next >
Encoding:
Internet Message Format  |  1991-06-24  |  60.8 KB

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