home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume21 / ecu / part30 < prev    next >
Encoding:
Text File  |  1991-08-05  |  53.8 KB  |  2,148 lines

  1. Newsgroups: comp.sources.misc
  2. From: Warren Tucker <wht@n4hgf.Mt-Park.GA.US>
  3. Subject:  v21i082:  ecu - ECU async comm package rev 3.10, Part30/37
  4. Message-ID: <1991Aug5.211912.8224@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: dc999e1f07e9e9979aefb18909481afd
  6. Date: Mon, 5 Aug 1991 21:19:12 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Warren Tucker <wht@n4hgf.Mt-Park.GA.US>
  10. Posting-number: Volume 21, Issue 82
  11. Archive-name: ecu/part30
  12. Environment: SCO, XENIX, ISC
  13. Supersedes: ecu3: Volume 16, Issue 25-59
  14.  
  15. ---- Cut Here and feed the following to sh ----
  16. #!/bin/sh
  17. # this is ecu310.30 (part 30 of ecu310)
  18. # do not concatenate these parts, unpack them in order with /bin/sh
  19. # file fasi/fas.c continued
  20. #
  21. if touch 2>&1 | fgrep 'amc' > /dev/null
  22.  then TOUCH=touch
  23.  else TOUCH=true
  24. fi
  25. if test ! -r _shar_seq_.tmp; then
  26.     echo 'Please unpack part 1 first!'
  27.     exit 1
  28. fi
  29. (read Scheck
  30.  if test "$Scheck" != 30; then
  31.     echo Please unpack part "$Scheck" next!
  32.     exit 1
  33.  else
  34.     exit 0
  35.  fi
  36. ) < _shar_seq_.tmp || exit 1
  37. if test ! -f _shar_wnt_.tmp; then
  38.     echo 'x - still skipping fasi/fas.c'
  39. else
  40. echo 'x - continuing file fasi/fas.c'
  41. sed 's/^X//' << 'SHAR_EOF' >> 'fasi/fas.c' &&
  42. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
  43. X                        | OS_HWI_HANDSHAKE,
  44. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE,
  45. X    OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
  46. X                        | OS_HDX_HANDSHAKE
  47. X};
  48. X
  49. X/* The following defines are used to access multiplexed ports. */
  50. X#define GET_PORT(port,num) \
  51. X    ((fip->device_flags.i & DF_CTL_EVERY)\
  52. X            ? (port)\
  53. X            : (port) + (num))
  54. X
  55. X#define fas_first_ctl(fip,port) \
  56. X    ((void) (((fip)->device_flags.i & DF_CTL_FIRST)\
  57. X            ? outb (CTL_PORT, (port).p.ctl)\
  58. X            : 0))
  59. X
  60. X#define fas_ctl(fip,port) \
  61. X    ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
  62. X            ? outb (CTL_PORT, (port).p.ctl)\
  63. X            : 0))
  64. X
  65. X#define fas_first_outb(fip,port,val) \
  66. X    ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
  67. X            ? outb (CTL_PORT, (port).p.ctl)\
  68. X            : 0),\
  69. X        (void) outb ((port).addr, (val)))
  70. X
  71. X#define fas_outb(fip,port,val) \
  72. X    ((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
  73. X            ? outb (CTL_PORT, (port).p.ctl)\
  74. X            : 0),\
  75. X        (void) outb ((port).addr, (val)))
  76. X
  77. X#define fas_first_inb(fip,port) \
  78. X    ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
  79. X            ? outb (CTL_PORT, (port).p.ctl)\
  80. X            : 0),\
  81. X        inb ((port).addr))
  82. X
  83. X#define fas_inb(fip,port) \
  84. X    ((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
  85. X            ? outb (CTL_PORT, (port).p.ctl)\
  86. X            : 0),\
  87. X        inb ((port).addr))
  88. X
  89. X/* The following defines are used to take apart the minor device numbers. */
  90. X#define GET_UNIT(dev)        ((dev) & 0x0f)
  91. X#define GET_OPEN_MODE(dev)    (fas_open_modes [((dev) >> 4) & 0x0f])
  92. X
  93. X/* lock device against concurrent use */
  94. X#define get_device_lock(fip,prio) \
  95. X{\
  96. X    /* sleep while device is used by an other process */\
  97. X    while ((fip)->device_flags.i & DF_DEVICE_LOCKED)\
  98. X        (void) sleep ((caddr_t) &(fip)->device_flags.i, (prio));\
  99. X    (fip)->device_flags.s |= DF_DEVICE_LOCKED;\
  100. X}
  101. X
  102. X/* release device */
  103. X#define release_device_lock(fip) \
  104. X{\
  105. X    (fip)->device_flags.s &= ~DF_DEVICE_LOCKED;\
  106. X    /* wakeup the process that may wait for this device */\
  107. X    (void) wakeup ((caddr_t) &(fip)->device_flags.i);\
  108. X}
  109. X
  110. X/* schedule event */
  111. X#define event_sched(fip,event) \
  112. X{\
  113. X    (fip)->event_flags.s |= (event);\
  114. X    if (!event_scheduled)\
  115. X    {\
  116. X        event_scheduled = TRUE;\
  117. X        (void) timeout (fas_event, (void *) NULL,\
  118. X                (EVENT_TIME) * (HZ) / 1000);\
  119. X    }\
  120. X}
  121. X
  122. X/* fasinit
  123. X   This routine checks for the presense of the devices in the fas_port
  124. X   array and if the device is present tests and initializes it.
  125. X   During the initialization if the device is determined to be an
  126. X   NS16550A chip the DF_DEVICE_IS_NS16550A flag is set and the FIFOs will
  127. X   be used. If the device is an i82510 chip the DF_DEVICE_IS_I82510 flag
  128. X   is set and the device will be handled accordingly.
  129. X*/
  130. X
  131. Xint
  132. Xfasinit ()
  133. X{
  134. X    register struct fas_info    *fip;
  135. X    register uint    unit;
  136. X    uint    logical_units, port, *seq_ptr;
  137. X    char    port_stat [MAX_UNITS + 1];
  138. X    REGVAR;
  139. X
  140. X    if (fas_is_initted)
  141. X        return (0);
  142. X
  143. X    fas_is_initted = TRUE;
  144. X
  145. X    /* execute the init sequence for the serial card */
  146. X    for (seq_ptr = fas_init_seq; *seq_ptr; seq_ptr++)
  147. X    {
  148. X        port = *seq_ptr;
  149. X        seq_ptr++;
  150. X        if (*seq_ptr & READ_PORT)
  151. X            (void) inb (port);
  152. X        else
  153. X            (void) outb (port, *seq_ptr);
  154. X    }
  155. X
  156. X    /* setup the list of pointers to the tty structures */
  157. X    for (unit = 0, logical_units = fas_physical_units * 2;
  158. X        unit < logical_units; unit++)
  159. X        fas_tty_ptr [unit] = &fas_tty [unit];
  160. X
  161. X    /* setup and initialize all serial ports */
  162. X    for (unit = 0; unit < fas_physical_units; unit++)
  163. X    {
  164. X        fas_info_ptr [unit] = fip = &fas_info [unit];
  165. X        port_stat [unit] = '-';
  166. X        if (port = (uint) ((ushort) (fas_port [unit])))
  167. X        {
  168. X            /* check the int vector */
  169. X            if (fas_vec [unit] >= NUM_INT_VECTORS)
  170. X            {
  171. X                port_stat [unit] = '>';
  172. X                continue;
  173. X            }
  174. X
  175. X            /* init all of its ports */
  176. X            if (fas_ctl_port [unit])
  177. X            {
  178. X                fip->ctl_port = fas_ctl_port [unit];
  179. X
  180. X                if (fas_ctl_val [unit] & 0xff00)
  181. X                    fip->device_flags.s |= DF_CTL_EVERY;
  182. X                else
  183. X                    fip->device_flags.s |= DF_CTL_FIRST;
  184. X            }
  185. X
  186. X            fip->port_0.p.addr = GET_PORT (port, 0);
  187. X            fip->port_1.p.addr = GET_PORT (port, 1);
  188. X            fip->port_2.p.addr = GET_PORT (port, 2);
  189. X            fip->port_3.p.addr = GET_PORT (port, 3);
  190. X            fip->port_4.p.addr = GET_PORT (port, 4);
  191. X            fip->port_5.p.addr = GET_PORT (port, 5);
  192. X            fip->port_6.p.addr = GET_PORT (port, 6);
  193. X            fip->port_0.p.ctl = fas_make_ctl_val (fip, unit, 0);
  194. X            fip->port_1.p.ctl = fas_make_ctl_val (fip, unit, 1);
  195. X            fip->port_2.p.ctl = fas_make_ctl_val (fip, unit, 2);
  196. X            fip->port_3.p.ctl = fas_make_ctl_val (fip, unit, 3);
  197. X            fip->port_4.p.ctl = fas_make_ctl_val (fip, unit, 4);
  198. X            fip->port_5.p.ctl = fas_make_ctl_val (fip, unit, 5);
  199. X            fip->port_6.p.ctl = fas_make_ctl_val (fip, unit, 6);
  200. X            fip->vec = fas_vec [unit];
  201. X            fip->modem.l = fas_modem [unit];
  202. X            fip->flow.l = fas_flow [unit];
  203. X
  204. X            /* mask off invalid bits */
  205. X            fip->modem.m.di &= MC_ANY_CONTROL;
  206. X            fip->modem.m.eo &= MC_ANY_CONTROL;
  207. X            fip->modem.m.ei &= MC_ANY_CONTROL;
  208. X            fip->modem.m.ca &= MS_ANY_PRESENT;
  209. X            fip->flow.m.ic &= MC_ANY_CONTROL;
  210. X            fip->flow.m.oc &= MS_ANY_PRESENT;
  211. X            fip->flow.m.oe &= MS_ANY_PRESENT;
  212. X            fip->flow.m.hc &= MC_ANY_CONTROL;
  213. X
  214. X            fip->recv_ring_put_ptr = fip->recv_buffer;
  215. X            fip->recv_ring_take_ptr = fip->recv_buffer;
  216. X            fip->xmit_ring_put_ptr = fip->xmit_buffer;
  217. X            fip->xmit_ring_take_ptr = fip->xmit_buffer;
  218. X            fip->xmit_fifo_size = 1;
  219. X
  220. X            fip->ier = IE_NONE;    /* disable all ints */
  221. X            fas_first_outb (fip, INT_ENABLE_PORT, fip->ier);
  222. X
  223. X            /* is there a serial chip ? */
  224. X            if (fas_inb (fip, INT_ENABLE_PORT) != fip->ier)
  225. X            {
  226. X                port_stat [unit] = '?';
  227. X                continue;    /* a hardware error */
  228. X            }
  229. X
  230. X            /* test the chip thoroughly */
  231. X            if ((port_stat [unit] = (fas_test_device (fip) + '0'))
  232. X                != '0')
  233. X            {
  234. X                continue;    /* a hardware error */
  235. X            }
  236. X
  237. X            fip->lcr = 0;
  238. X            fas_outb (fip, LINE_CTL_PORT, fip->lcr);
  239. X            fip->mcr = fas_mcb [unit] | fip->modem.m.di;
  240. X            fas_outb (fip, MDM_CTL_PORT, fip->mcr);
  241. X
  242. X            port_stat [unit] = '*';
  243. X
  244. X            /* let's see if it's an NS16550A */
  245. X            fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_INIT_CMD);
  246. X            if (!(~fas_inb (fip, INT_ID_PORT) & II_NS_FIFO_ENABLED))
  247. X            {
  248. X                fip->device_flags.s |= DF_DEVICE_IS_NS16550A;
  249. X                fip->xmit_fifo_size = OUTPUT_NS_FIFO_SIZE;
  250. X                port_stat [unit] = 'F';
  251. X                fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
  252. X            }
  253. X            else
  254. X            {
  255. X                fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
  256. X                /* or is it an i82510 ? */
  257. X                fas_outb (fip, I_BANK_PORT, I_BANK_2);
  258. X                if (!(~fas_inb (fip, I_BANK_PORT) & I_BANK_2))
  259. X                {
  260. X                    fip->device_flags.s |= DF_DEVICE_IS_I82510;
  261. X                    fip->xmit_fifo_size = OUTPUT_I_FIFO_SIZE;
  262. X                    port_stat [unit] = 'f';
  263. X                    fas_outb (fip, I_BANK_PORT, I_BANK_1);
  264. X                    fas_outb (fip, I_TCM_PORT, I_FIFO_CLR_XMIT);
  265. X                    fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
  266. X                }
  267. X                fas_outb (fip, I_BANK_PORT, I_BANK_0);
  268. X            }
  269. X
  270. X            /* disable FIFOs if requested in space.c */
  271. X            if ((fas_port [unit] & NO_FIFO) && (fip->device_flags.i
  272. X                        & (DF_DEVICE_IS_NS16550A
  273. X                            | DF_DEVICE_IS_I82510)))
  274. X            {
  275. X                fip->device_flags.s &= ~(DF_DEVICE_IS_NS16550A
  276. X                            | DF_DEVICE_IS_I82510);
  277. X                fip->xmit_fifo_size = 1;
  278. X                port_stat [unit] = '+';
  279. X            }
  280. X
  281. X            /* clear potential interrupts */
  282. X            (void) fas_inb (fip, MDM_STATUS_PORT);
  283. X            (void) fas_inb (fip, RCV_DATA_PORT);
  284. X            (void) fas_inb (fip, RCV_DATA_PORT);
  285. X            (void) fas_inb (fip, LINE_STATUS_PORT);
  286. X            (void) fas_inb (fip, INT_ID_PORT);
  287. X            if (port = fas_int_ack_port [fip->vec])
  288. X                (void) outb (port, fas_int_ack [fip->vec]);
  289. X
  290. X            /* show that it is present and configured */
  291. X            fip->device_flags.s |= DF_DEVICE_CONFIGURED;
  292. X        }
  293. X    }
  294. X
  295. X#if defined (NEED_PUT_GETCHAR)
  296. X    fip = &fas_info [0];
  297. X    fip->mcr &= ~fip->modem.m.di;
  298. X    fip->mcr |= INITIAL_MDM_CONTROL;
  299. X    fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  300. X
  301. X    fip->lcr = INITIAL_LINE_CONTROL;
  302. X    fas_outb (fip, LINE_CTL_PORT, fip->lcr | LC_ENABLE_DIVISOR);
  303. X    fas_outb (fip, DIVISOR_LSB_PORT, INITIAL_BAUD_RATE);
  304. X    fas_outb (fip, DIVISOR_MSB_PORT, (INITIAL_BAUD_RATE) >> 8);
  305. X    fas_outb (fip, LINE_CTL_PORT, fip->lcr);
  306. X#endif
  307. X
  308. X#if defined (SCO) || defined (XENIX)
  309. X    for (unit = 0; unit < fas_physical_units; unit++)
  310. X        (void) printcfg ("fas", (uint) ((ushort) (fas_port [unit])), 7,
  311. X                    fas_vec [unit], -1,
  312. X#if defined (FASI)
  313. X                    "unit=%d type=%c FAS/i 2.08.01",
  314. X#else
  315. X                    "unit=%d type=%c release=2.08.0",
  316. X#endif /* FASI */
  317. X                    unit, port_stat [unit]);
  318. X#else
  319. X    port_stat [unit] = '\0';
  320. X    (void) printf ("\nFAS 2.08.0 async driver: Unit 0-%d init state is [%s]\n\n",
  321. X            unit - 1,
  322. X            port_stat);
  323. X#endif
  324. X    return (0);
  325. X}
  326. X
  327. X/* Open a tty line. This function is called for every open, as opposed
  328. X   to the fasclose function which is called only with the last close.
  329. X*/
  330. Xint
  331. Xfasopen (dev, flag)
  332. Xint    dev;
  333. Xint    flag;
  334. X{
  335. X    register struct fas_info    *fip;
  336. X    register struct tty        *ttyp;
  337. X    register uint    open_mode;
  338. X    uint    physical_unit;
  339. X    int    old_level;
  340. X
  341. X    physical_unit = GET_UNIT (dev);
  342. X
  343. X    /* check for valid port number */
  344. X    if (physical_unit >= fas_physical_units)
  345. X    {
  346. X        u.u_error = ENXIO;
  347. X        return (-1);
  348. X    }
  349. X
  350. X    fip = fas_info_ptr [physical_unit];
  351. X
  352. X    /* was the port present at init time ? */
  353. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  354. X    {
  355. X        u.u_error = ENXIO;
  356. X        return (-1);
  357. X    }
  358. X
  359. X    open_mode = GET_OPEN_MODE (dev);
  360. X
  361. X    old_level = SPLINT ();
  362. X    get_device_lock (fip, TTIPRI);
  363. X
  364. X    /* If this is a getty open, the device is already open for
  365. X           dialout and the FNDELAY flag is not set, wait until device
  366. X           is closed.
  367. X    */
  368. X    while ((open_mode & OS_OPEN_FOR_GETTY)
  369. X            && (fip->o_state & OS_OPEN_FOR_DIALOUT)
  370. X            && !(flag & FNDELAY))
  371. X    {
  372. X        release_device_lock (fip);
  373. X        (void) sleep ((caddr_t) &fip->o_state, TTIPRI);
  374. X        get_device_lock (fip, TTIPRI);
  375. X    }
  376. X    
  377. X    /* If the device is already open and another open uses a different
  378. X       open mode or if a getty open waits for carrier and doesn't allow
  379. X       parallel dialout opens, return with EBUSY error.
  380. X    */
  381. X    if ((fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
  382. X                ? (OS_OPEN_STATES | OS_WAIT_OPEN)
  383. X                : (OS_OPEN_STATES | OS_NO_DIALOUT)))
  384. X        && ((flag & FEXCL)
  385. X            || ((open_mode ^ fip->o_state) & (u.u_uid
  386. X                        ? OS_TEST_MASK
  387. X                        : OS_SU_TEST_MASK))))
  388. X    {
  389. X        u.u_error = EBUSY;
  390. X        release_device_lock (fip);
  391. X        (void) splx (old_level);
  392. X        return (-1);
  393. X    }
  394. X
  395. X    /* disable subsequent opens */
  396. X    if (flag & FEXCL)
  397. X        open_mode |= OS_EXCLUSIVE_OPEN_1;
  398. X
  399. X    /* set up pointer to tty structure */
  400. X    ttyp = (open_mode & OS_OPEN_FOR_GETTY)
  401. X        ? fas_tty_ptr [physical_unit + fas_physical_units]
  402. X        : fas_tty_ptr [physical_unit];
  403. X
  404. X    /* things to do on first open only */
  405. X    if (!(fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
  406. X                ? (OS_OPEN_STATES | OS_WAIT_OPEN)
  407. X                : OS_OPEN_STATES)))
  408. X    {
  409. X        /* init data structures */
  410. X        fip->tty = ttyp;
  411. X        (void) ttinit (ttyp);
  412. X        ttyp->t_proc = fas_proc;
  413. X        fip->po_state = fip->o_state;
  414. X        fip->o_state = open_mode & ~OS_OPEN_STATES;
  415. X#if defined (HAVE_VPIX)
  416. X        /* initialize VP/ix related variables */
  417. X        fip->v86_proc = (v86_t *) NULL;
  418. X        fip->v86_intmask = 0;
  419. X        fip->v86_ss.ss_start = CSTART;
  420. X        fip->v86_ss.ss_stop = CSTOP;
  421. X#endif
  422. X        fas_open_device (fip);        /* open physical device */
  423. X        fas_param (fip, HARD_INIT);    /* set up port registers */
  424. X
  425. X        /* allow pending tty interrupts */
  426. X        (void) SPLWRK ();
  427. X        (void) SPLINT ();
  428. X    }
  429. X
  430. X    /* If getty open and the FNDELAY flag is not set,
  431. X       block and wait for carrier if device not yet open.
  432. X    */
  433. X    if ((open_mode & OS_OPEN_FOR_GETTY) && !(flag & FNDELAY))
  434. X    {
  435. X        /* sleep while open for dialout or no carrier */
  436. X        while ((fip->o_state & OS_OPEN_FOR_DIALOUT)
  437. X            || !(ttyp->t_state & (ISOPEN | CARR_ON)))
  438. X        {
  439. X            ttyp->t_state |= WOPEN;
  440. X            release_device_lock (fip);
  441. X            (void) sleep ((caddr_t) &ttyp->t_canq, TTIPRI);
  442. X            get_device_lock (fip, TTIPRI);
  443. X        }
  444. X        ttyp->t_state &= ~WOPEN;
  445. X    }
  446. X
  447. X    /* wakeup processes that are still sleeping in getty open */
  448. X    if (ttyp->t_state & WOPEN)
  449. X#if defined(FASI)
  450. X    {
  451. X#endif
  452. X        (void) wakeup ((caddr_t) &ttyp->t_canq);
  453. X#if defined(FASI)
  454. X        (void) wakeup ((caddr_t) &fip->device_flags.i);
  455. X    }
  456. X#endif
  457. X
  458. X    /* we need to flush the receiver with the first open */
  459. X    if (!(fip->o_state & OS_OPEN_STATES))
  460. X        fas_cmd (fip, ttyp, T_RFLUSH);
  461. X
  462. X    (*linesw [ttyp->t_line].l_open) (ttyp);
  463. X
  464. X    /* set open type flags */
  465. X    fip->o_state = open_mode;
  466. X
  467. X    release_device_lock (fip);
  468. X    (void) splx (old_level);
  469. X    return (0);
  470. X}
  471. X
  472. X/* Close a tty line. This is only called if there is no other
  473. X   concurrent open left. A blocked getty open is not counted as
  474. X   a concurrent open because in this state it isn't really open.
  475. X*/
  476. Xint
  477. Xfasclose (dev)
  478. Xint    dev;
  479. X{
  480. X    register struct fas_info    *fip;
  481. X    register struct tty        *ttyp;
  482. X    uint    physical_unit;
  483. X    uint    open_mode;
  484. X    int    old_level;
  485. X    void    (*old_sigkill)();
  486. X
  487. X    physical_unit = GET_UNIT (dev);
  488. X
  489. X    fip = fas_info_ptr [physical_unit];
  490. X
  491. X    open_mode = GET_OPEN_MODE (dev);
  492. X
  493. X    /* set up pointer to tty structure */
  494. X    ttyp = (open_mode & OS_OPEN_FOR_GETTY)
  495. X        ? fas_tty_ptr [physical_unit + fas_physical_units]
  496. X        : fas_tty_ptr [physical_unit];
  497. X    
  498. X    old_level = SPLINT ();
  499. X    get_device_lock (fip, TTIPRI);
  500. X
  501. X    /* wait for output buffer drain only if device was open */
  502. X    if (ttyp->t_state & ISOPEN)
  503. X    {
  504. X        /* flush the output buffer immediately if the device
  505. X           has been shut down because of an error
  506. X        */
  507. X        if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  508. X        {
  509. X            (void) ttyflush (ttyp, FWRITE);
  510. X        }
  511. X        /* wait for buffer drain and catch interrupts */
  512. X        while (ttyp->t_outq.c_cc || (ttyp->t_state & (BUSY | TIMEOUT)))
  513. X        {
  514. X            old_sigkill = u.u_signal [SIGKILL - 1];
  515. X            /* allow kill signal if close on exit */
  516. X            if (old_sigkill == SIG_IGN)
  517. X                u.u_signal [SIGKILL - 1] = SIG_DFL;
  518. X            ttyp->t_state |= TTIOW;
  519. X            if (sleep ((caddr_t) &ttyp->t_oflag, TTOPRI | PCATCH))
  520. X            {
  521. X                /* caught signal */
  522. X                ttyp->t_state &= ~TTIOW;
  523. X                /* If close on exit, flush output buffer to
  524. X                   allow completion of the fasclose() function.
  525. X                   Otherwise, do the normal signal handling.
  526. X                */
  527. X                if (old_sigkill == SIG_IGN)
  528. X                    (void) ttyflush (ttyp, FWRITE);
  529. X                else
  530. X                {
  531. X                    release_device_lock (fip);
  532. X                    (void) splx (old_level);
  533. X                    longjmp (u.u_qsav);
  534. X                }
  535. X            }
  536. X            if (old_sigkill == SIG_IGN)
  537. X                u.u_signal [SIGKILL - 1] = old_sigkill;
  538. X        }
  539. X    }
  540. X
  541. X    (*linesw [ttyp->t_line].l_close) (ttyp);
  542. X
  543. X    /* allow pending tty interrupts */
  544. X    (void) SPLWRK ();
  545. X    (void) SPLINT ();
  546. X
  547. X    if (open_mode & OS_OPEN_FOR_GETTY)
  548. X    {
  549. X        /* not waiting any more */
  550. X        ttyp->t_state &= ~WOPEN;
  551. X        if (!(fip->o_state & OS_OPEN_FOR_DIALOUT))
  552. X        {
  553. X            fas_close_device (fip);
  554. X            fip->o_state = OS_DEVICE_CLOSED;
  555. X        }
  556. X        else
  557. X            fip->po_state = OS_DEVICE_CLOSED;
  558. X    }
  559. X    else
  560. X    {
  561. X        fas_close_device (fip);
  562. X        fip->o_state = OS_DEVICE_CLOSED;
  563. X        /* If there is a waiting getty open on
  564. X           this port, reopen the physical device.
  565. X        */
  566. X        if (fip->po_state & OS_WAIT_OPEN)
  567. X        {
  568. X            /* get the getty version of the
  569. X               tty structure
  570. X            */
  571. X            fip->tty = fas_tty_ptr [physical_unit
  572. X                    + fas_physical_units];
  573. X            fip->o_state = fip->po_state;
  574. X            fip->po_state = OS_DEVICE_CLOSED;
  575. X#if defined (HAVE_VPIX)
  576. X            /* initialize VP/ix related variables */
  577. X            fip->v86_proc = (v86_t *) NULL;
  578. X            fip->v86_intmask = 0;
  579. X            fip->v86_ss.ss_start = CSTART;
  580. X            fip->v86_ss.ss_stop = CSTOP;
  581. X#endif
  582. X            if (!(fip->device_flags.i & DF_DO_HANGUP))
  583. X            {
  584. X                fas_open_device (fip);
  585. X                /* set up port registers */
  586. X                fas_param (fip, HARD_INIT);
  587. X            }
  588. X        }
  589. X        (void) wakeup ((caddr_t) &fip->o_state);
  590. X    }
  591. X
  592. X    if (!(fip->device_flags.i & DF_DO_HANGUP))
  593. X        release_device_lock (fip);
  594. X
  595. X#if defined(FASI)
  596. X    (void)wakeup((caddr_t)&fip->device_flags.i);
  597. X#endif
  598. X    (void) splx (old_level);
  599. X    return (0);
  600. X}
  601. X
  602. X/* read characters from the input buffer */
  603. Xint
  604. Xfasread (dev)
  605. Xint    dev;
  606. X{
  607. X    register struct fas_info    *fip;
  608. X    register struct tty    *ttyp;
  609. X    int    old_level;
  610. X
  611. X    fip = fas_info_ptr [GET_UNIT (dev)];
  612. X
  613. X    /* was the port present at init time ? */
  614. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  615. X    {
  616. X        u.u_error = ENXIO;
  617. X        return (-1);
  618. X    }
  619. X
  620. X    ttyp = fip->tty;
  621. X
  622. X    (*linesw [ttyp->t_line].l_read) (ttyp);
  623. X
  624. X    old_level = SPLINT ();
  625. X
  626. X    /* schedule character transfer to UNIX buffer */
  627. X    if (fip->recv_ring_cnt
  628. X#if defined (HAVE_VPIX)
  629. X        && (((fip->iflag & DOSMODE)
  630. X            ? MAX_VPIX_FILL - MIN_READ_CHUNK
  631. X            : MAX_UNIX_FILL - MIN_READ_CHUNK)
  632. X                >= ttyp->t_rawq.c_cc)
  633. X#else
  634. X        && ((MAX_UNIX_FILL - MIN_READ_CHUNK) >= ttyp->t_rawq.c_cc)
  635. X#endif
  636. X        && !(fip->flow_flags.i & FF_RXFER_STOPPED))
  637. X    {
  638. X        event_sched (fip, EF_DO_RXFER);
  639. X    }
  640. X
  641. X#if defined(FASI)
  642. X    (void)wakeup((caddr_t)&fip->device_flags.i);
  643. X#endif
  644. X    (void) splx (old_level);
  645. X    return (0);
  646. X}
  647. X
  648. X/* write characters to the output buffer */
  649. Xint
  650. Xfaswrite (dev)
  651. Xint    dev;
  652. X{
  653. X    register struct fas_info    *fip;
  654. X    register struct tty    *ttyp;
  655. X
  656. X    fip = fas_info_ptr [GET_UNIT (dev)];
  657. X
  658. X    /* was the port present at init time ? */
  659. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  660. X    {
  661. X        u.u_error = ENXIO;
  662. X        return (-1);
  663. X    }
  664. X
  665. X    ttyp = fip->tty;
  666. X
  667. X    (*linesw [ttyp->t_line].l_write) (ttyp);
  668. X    return (0);
  669. X}
  670. X
  671. X/*+-------------------------------------------------------------------------
  672. X    strlen(str)
  673. X--------------------------------------------------------------------------*/
  674. X#if defined(FASI)
  675. Xstatic int
  676. Xstrlen(str)
  677. Xregister char *str;
  678. X{
  679. Xregister len = 0;
  680. X    while(*str++)
  681. X        len++;
  682. X    return(len);
  683. X}    /* end of strlen */
  684. X#endif /* FASI */
  685. X
  686. X/* process ioctl calls */
  687. Xint
  688. Xfasioctl (dev, cmd, arg3, arg4)
  689. Xint    dev;
  690. Xint    cmd;
  691. Xunion ioctl_arg    arg3;
  692. Xint    arg4;
  693. X{
  694. X    register struct fas_info    *fip;
  695. X    register struct tty    *ttyp;
  696. X    int    v86_cmd, v86_data;
  697. X    int    old_level;
  698. X    REGVAR;
  699. X
  700. X    fip = fas_info_ptr [GET_UNIT (dev)];
  701. X
  702. X    /* was the port present at init time ? */
  703. X    if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
  704. X    {
  705. X        u.u_error = ENXIO;
  706. X        return (-1);
  707. X    }
  708. X
  709. X    ttyp = fip->tty;
  710. X
  711. X    /* process ioctl commands */
  712. X    switch (cmd)
  713. X    {
  714. X#if defined (FASI)
  715. X        case FASIC_SIP_CHANGE:
  716. X            (void) sleep ((caddr_t) &fip->device_flags.i, PZERO + 1);
  717. X        case FASIC_SIP:
  718. X            if(copyout((char *)fip,arg3.cparg,sizeof(*fip)))
  719. X            {
  720. X                u.u_error = EFAULT;
  721. X                return(-1);
  722. X            }
  723. X            return(fasiintr_entries);
  724. X        case FASIC_DVR_IDENT:
  725. X            if(copyout(fasi_driver_ident,arg3.cparg,
  726. X                strlen(fasi_driver_ident) + 1))
  727. X            {
  728. X                u.u_error = EFAULT;
  729. X                return(-1);
  730. X            }
  731. X            break;
  732. X        case FASIC_SPACE_IDENT:
  733. X            if(copyout(fasi_space_ident,arg3.cparg,
  734. X                strlen(fasi_space_ident) + 1))
  735. X            {
  736. X                u.u_error = EFAULT;
  737. X                return(-1);
  738. X            }
  739. X            break;
  740. X        case FASIC_MSR:
  741. X            return((unsigned int)fip->msr);
  742. X        case FASIC_LCR:
  743. X            return((unsigned int)fip->lcr);
  744. X        case FASIC_IER:
  745. X            return((unsigned int)fip->ier);
  746. X        case FASIC_MCR:
  747. X            return((unsigned int)fip->mcr);
  748. X        case FASIC_RESET_STAT:
  749. X            old_level = SPLINT();
  750. X            fip->characters_received = 0;
  751. X            fip->characters_transmitted = 0;
  752. X            fip->modem_status_events = 0;
  753. X            fip->overrun_errors = 0;
  754. X            fip->framing_errors = 0;
  755. X            fip->parity_errors = 0;
  756. X            fip->rings_detected = 0;
  757. X            fip->breaks_detected = 0;
  758. X            fip->xmtr_hw_flow_count = 0;
  759. X            fip->xmtr_sw_flow_count = 0;
  760. X            fip->rcvr_hw_flow_count = 0;
  761. X            fip->rcvr_sw_flow_count = 0;
  762. X            (void)splx(old_level);
  763. X            break;
  764. X#endif /* FASI */
  765. X#if defined (HAVE_VPIX)
  766. X        case AIOCINTTYPE:    /* set pseudorupt type */
  767. X            switch (arg3.iarg)
  768. X            {
  769. X                case V86VI_KBD:
  770. X                case V86VI_SERIAL0:
  771. X                case V86VI_SERIAL1:
  772. X                    intr_disable ();
  773. X                    fip->v86_intmask = arg3.iarg;
  774. X                    intr_restore ();
  775. X                    break;
  776. X
  777. X                default:
  778. X                    intr_disable ();
  779. X                    fip->v86_intmask = V86VI_SERIAL0;
  780. X                    intr_restore ();
  781. X                    break;
  782. X            }
  783. X            break;
  784. X
  785. X        case AIOCDOSMODE:    /* enable dos mode */
  786. X            if (!(fip->iflag & DOSMODE))
  787. X            {
  788. X                old_level = SPLINT ();
  789. X                fip->v86_proc = u.u_procp->p_v86;
  790. X                if (!(fip->v86_intmask))
  791. X                    fip->v86_intmask = V86VI_SERIAL0;
  792. X                ttyp->t_iflag |= DOSMODE;
  793. X                if (fip->v86_intmask != V86VI_KBD)
  794. X                    ttyp->t_cflag |= CLOCAL;
  795. X                fas_param (fip, SOFT_INIT);
  796. X                (void) splx (old_level);
  797. X            }
  798. X            u.u_r.r_reg.r_val1 = 0;
  799. X            break;
  800. X
  801. X        case AIOCNONDOSMODE:    /* disable dos mode */
  802. X            if (fip->iflag & DOSMODE)
  803. X            {
  804. X                old_level = SPLINT ();
  805. X                fip->v86_proc = (v86_t *) NULL;
  806. X                fip->v86_intmask = 0;
  807. X                ttyp->t_iflag &= ~DOSMODE;
  808. X                if (fip->flow_flags.i & FF_RXFER_STOPPED)
  809. X                {
  810. X                    fip->flow_flags.s &= ~FF_RXFER_STOPPED;
  811. X                    /* schedule character transfer
  812. X                       to UNIX buffer
  813. X                    */
  814. X                    if (fip->recv_ring_cnt)
  815. X                        event_sched (fip, EF_DO_RXFER);
  816. X                }
  817. X                fip->lcr &= ~LC_SET_BREAK_LEVEL;
  818. X                fas_param (fip, HARD_INIT);
  819. X                (void) splx (old_level);
  820. X            }
  821. X            u.u_r.r_reg.r_val1 = 0;
  822. X            break;
  823. X
  824. X        case AIOCSERIALOUT:    /* setup port registers for dos */
  825. X            if ((fip->iflag & DOSMODE) && fip->v86_proc)
  826. X            {
  827. X                /* wait until output is done */
  828. X                old_level = SPLINT ();
  829. X                while (ttyp->t_outq.c_cc
  830. X                    || (ttyp->t_state & (BUSY | TIMEOUT)))
  831. X                {
  832. X                    ttyp->t_state |= TTIOW;
  833. X                    (void) sleep ((caddr_t) &ttyp->t_oflag,
  834. X                                    TTOPRI);
  835. X                }
  836. X
  837. X                /* block transmitter and wait until it is
  838. X                   empty
  839. X                */
  840. X                fip->device_flags.s |= DF_XMIT_LOCKED;
  841. X                while (fip->device_flags.i & (DF_XMIT_BUSY
  842. X                            | DF_XMIT_BREAK
  843. X                            | DF_GUARD_TIMEOUT))
  844. X                    (void) sleep ((caddr_t) &fip->
  845. X                                device_flags.i,
  846. X                            PZERO - 1);
  847. X                (void) splx (old_level);
  848. X
  849. X                /* get port write command */
  850. X                v86_cmd = fubyte (arg3.cparg);
  851. X                /* set divisor lsb requested */
  852. X                if (v86_cmd & SIO_MASK(SO_DIVLLSB))
  853. X                {
  854. X                    v86_data = fubyte (arg3.cparg
  855. X                                + SO_DIVLLSB);
  856. X                    intr_disable ();
  857. X                    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
  858. X                            | LC_ENABLE_DIVISOR);
  859. X                    fas_outb (fip, DIVISOR_LSB_PORT, v86_data);
  860. X                    fas_outb (fip, LINE_CTL_PORT, fip->lcr
  861. X                            & ~LC_ENABLE_DIVISOR);
  862. X                    intr_restore ();
  863. X                }
  864. X                /* set divisor msb requested */
  865. X                if (v86_cmd & SIO_MASK(SO_DIVLMSB))
  866. X                {
  867. X                    v86_data = fubyte (arg3.cparg
  868. X                                + SO_DIVLMSB);
  869. X                    intr_disable ();
  870. X                    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
  871. X                            | LC_ENABLE_DIVISOR);
  872. X                    fas_outb (fip, DIVISOR_MSB_PORT, v86_data);
  873. X                    fas_outb (fip, LINE_CTL_PORT, fip->lcr
  874. X                            & ~LC_ENABLE_DIVISOR);
  875. X                    intr_restore ();
  876. X                }
  877. X                /* set lcr requested */
  878. X                if (v86_cmd & SIO_MASK(SO_LCR))
  879. X                {
  880. X                    v86_data = fubyte (arg3.cparg + SO_LCR);
  881. X                    intr_disable ();
  882. X                    fip->lcr = v86_data
  883. X                            & ~LC_ENABLE_DIVISOR;
  884. X                    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
  885. X                    intr_restore ();
  886. X                }
  887. X                /* set mcr requested */
  888. X                if (v86_cmd & SIO_MASK(SO_MCR))
  889. X                {
  890. X                    v86_data = fubyte (arg3.cparg + SO_MCR);
  891. X                    old_level = SPLINT ();
  892. X                    /* virtual dtr processing */
  893. X                    if (v86_data & MC_SET_DTR)
  894. X                    {
  895. X                        fip->device_flags.s
  896. X                            |= DF_MODEM_ENABLED;
  897. X                        fip->mcr |= (fip->o_state
  898. X                                & OS_WAIT_OPEN)
  899. X                            ? fip->modem.m.ei
  900. X                            : fip->modem.m.eo;
  901. X                    }
  902. X                    else
  903. X                    {
  904. X                        fip->device_flags.s
  905. X                            &= ~DF_MODEM_ENABLED;
  906. X                        fip->mcr &= (fip->o_state
  907. X                                & OS_WAIT_OPEN)
  908. X                            ? ~fip->modem.m.ei
  909. X                            : ~fip->modem.m.eo;
  910. X                    }
  911. X                    /* virtual rts processing */
  912. X                    if (fip->flow_flags.i
  913. X                            & FF_HWI_HANDSHAKE)
  914. X                    {
  915. X                      if (v86_data & MC_SET_RTS)
  916. X                      {
  917. X                        if (fip->flow_flags.i
  918. X                            & FF_RXFER_STOPPED)
  919. X                        {
  920. X                          fip->flow_flags.s
  921. X                            &= ~FF_RXFER_STOPPED;
  922. X                          /* schedule character transfer
  923. X                             to UNIX buffer
  924. X                          */
  925. X                          if (fip->recv_ring_cnt)
  926. X                            event_sched (fip,
  927. X                                EF_DO_RXFER);
  928. X                        }
  929. X                      }
  930. X                      else
  931. X                        fip->flow_flags.s
  932. X                            |= FF_RXFER_STOPPED;
  933. X                    }
  934. X                    else if (!(fip->flow_flags.i
  935. X                            & FF_HDX_HANDSHAKE))
  936. X                    {
  937. X                        if (v86_data & MC_SET_RTS)
  938. X                        {
  939. X                            fip->flow_flags.s
  940. X                              |= FF_HDX_STARTED;
  941. X                            fip->mcr
  942. X                              |= fip->flow.m.hc;
  943. X                        }
  944. X                        else
  945. X                        {
  946. X                            fip->flow_flags.s
  947. X                              &= ~FF_HDX_STARTED;
  948. X                            fip->mcr
  949. X                              &= ~fip->flow.m.hc;
  950. X                        }
  951. X                    }
  952. X                    fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  953. X                    (void) splx (old_level);
  954. X                }
  955. X
  956. X                old_level = SPLINT ();
  957. X                /* enable transmitter and restart output */
  958. X                fip->device_flags.s &= ~DF_XMIT_LOCKED;
  959. X                fas_xproc (fip);
  960. X                (void) splx (old_level);
  961. X            }
  962. X            break;
  963. X
  964. X        case AIOCSERIALIN:    /* read port registers for dos */
  965. X            if ((fip->iflag & DOSMODE) && fip->v86_proc)
  966. X            {
  967. X                v86_cmd = fubyte (arg3.cparg);
  968. X                if (v86_cmd & SIO_MASK(SI_MSR))
  969. X                {
  970. X                    (void) subyte (arg3.cparg + SI_MSR,
  971. X                            ((fip->flow_flags.i
  972. X                              & FF_HWO_HANDSHAKE)
  973. X                            ? fip->msr
  974. X                              | fip->flow.m.oc
  975. X                              | fip->flow.m.oe
  976. X                            : fip->msr)
  977. X                            & MS_ANY_PRESENT);
  978. X                }
  979. X            }
  980. X            break;
  981. X
  982. X        case AIOCSETSS:    /* set start/stop characters */
  983. X            intr_disable ();
  984. X            *((short *) (&fip->v86_ss)) = arg3.iarg;
  985. X            intr_restore ();
  986. X            break;
  987. X
  988. X        case AIOCINFO:    /* show what type of device we are */
  989. X            u.u_r.r_reg.r_val1 = ('a' << 8) | (uint) ((unchar) dev);
  990. X            break;
  991. X#endif
  992. X        default:    /* default ioctl processing */
  993. X            /* if it is a TCSETA* command, call fas_param () */
  994. X            if (ttiocom (ttyp, cmd, arg3, arg4))
  995. X            {
  996. X                old_level = SPLINT ();
  997. X                fas_param (fip, SOFT_INIT);
  998. X                (void) splx (old_level);
  999. X            }
  1000. X            break;
  1001. X    }
  1002. X    return (0);
  1003. X}
  1004. X
  1005. X/* pass fas commands to the fas multi-function procedure */
  1006. Xstatic int
  1007. Xfas_proc (ttyp, arg2)
  1008. Xstruct tty    *ttyp;
  1009. Xint    arg2;
  1010. X{
  1011. X    register uint    physical_unit;
  1012. X    int    old_level;
  1013. X
  1014. X    physical_unit = ttyp - &fas_tty [0];
  1015. X    if (physical_unit >= fas_physical_units)
  1016. X        physical_unit -= fas_physical_units;
  1017. X
  1018. X    old_level = SPLINT ();
  1019. X    fas_cmd (fas_info_ptr [physical_unit], ttyp, arg2);
  1020. X    (void) splx (old_level);
  1021. X    return (0);
  1022. X}
  1023. X
  1024. X/* set up a port according to the given termio structure */
  1025. Xstatic void
  1026. Xfas_param (fip, init_type)
  1027. Xregister struct    fas_info    *fip;
  1028. Xint    init_type;
  1029. X{
  1030. X    register uint    cflag;
  1031. X    uint    divisor;
  1032. X    int    xmit_ring_size;
  1033. X    REGVAR;
  1034. X
  1035. X    cflag = fip->tty->t_cflag;
  1036. X
  1037. X#if defined (HAVE_VPIX)
  1038. X    /* we don't set port registers if we are in dos mode */
  1039. X    if (fip->tty->t_iflag & DOSMODE)
  1040. X        goto setflags2;
  1041. X#endif
  1042. X    /* if soft init mode: don't set port registers if cflag didn't change */
  1043. X    if ((init_type == SOFT_INIT) && !((cflag ^ fip->cflag)
  1044. X                        & (CBAUD | CSIZE | CSTOPB
  1045. X                            | PARENB | PARODD)))
  1046. X        goto setflags;
  1047. X
  1048. X    /* lock transmitter and wait until it is empty */
  1049. X    fip->device_flags.s |= DF_XMIT_LOCKED;
  1050. X    while (fip->device_flags.i & (DF_XMIT_BUSY | DF_XMIT_BREAK
  1051. X                            | DF_GUARD_TIMEOUT))
  1052. X        (void) sleep ((caddr_t) &fip->device_flags.i, PZERO - 1);
  1053. X
  1054. X    /* hangup line if it is baud rate 0, else enable line */
  1055. X    if ((cflag & CBAUD) == B0)
  1056. X    {
  1057. X        fip->mcr &= (fip->o_state & OS_WAIT_OPEN)
  1058. X                ? ~fip->modem.m.ei
  1059. X                : ~fip->modem.m.eo;
  1060. X        fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1061. X        fip->device_flags.s &= ~DF_MODEM_ENABLED;
  1062. X    }
  1063. X    else
  1064. X    {
  1065. X        if (!(fip->device_flags.i & DF_MODEM_ENABLED))
  1066. X        {
  1067. X            fip->mcr |= (fip->o_state & OS_WAIT_OPEN)
  1068. X                    ? fip->modem.m.ei
  1069. X                    : fip->modem.m.eo;
  1070. X            fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
  1071. X            fip->device_flags.s |= DF_MODEM_ENABLED;
  1072. X        }
  1073. X    }
  1074. X
  1075. X    /* don't change break flag */
  1076. X    fip->lcr &= LC_SET_BREAK_LEVEL;
  1077. X
  1078. X    /* set character size */
  1079. X    switch (cflag & CSIZE)
  1080. X    {
  1081. X    case CS5:
  1082. X        fip->lcr |= LC_WORDLEN_5;
  1083. X        break;
  1084. X
  1085. X    case CS6:
  1086. X        fip->lcr |= LC_WORDLEN_6;
  1087. X        break;
  1088. X
  1089. X    case CS7:
  1090. X        fip->lcr |= LC_WORDLEN_7;
  1091. X        break;
  1092. X
  1093. X    default:
  1094. X        fip->lcr |= LC_WORDLEN_8;
  1095. X        break;
  1096. X    }
  1097. X
  1098. X    /* set # of stop bits */
  1099. X    if (cflag & CSTOPB)
  1100. X        fip->lcr |= LC_STOPBITS_LONG;
  1101. X
  1102. X    /* set parity */
  1103. X    if (cflag & PARENB)
  1104. X    {
  1105. X        fip->lcr |= LC_ENABLE_PARITY;
  1106. X
  1107. X        if (!(cflag & PARODD))
  1108. X            fip->lcr |= LC_EVEN_PARITY;
  1109. X    }
  1110. X
  1111. X    /* set divisor registers only if baud rate is valid */
  1112. X    if ((cflag & CBAUD) != B0)
  1113. X    {
  1114. X        /* get counter divisor for selected baud rate */
  1115. X        divisor = fas_speeds [cflag & CBAUD];
  1116. X        /* set LCR and baud rate */
  1117. X        fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
  1118. X                            | LC_ENABLE_DIVISOR);
  1119. X        fas_outb (fip, DIVISOR_LSB_PORT, divisor);
  1120. X        fas_outb (fip, DIVISOR_MSB_PORT, divisor >> 8);
  1121. X    }
  1122. X
  1123. X    fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
  1124. X
  1125. Xsetflags:
  1126. X    /* check dynamic xmit ring buffer size against boundaries,
  1127. X       modify it if necessary and update the fas_info structure
  1128. X    */
  1129. X    if ((cflag & CBAUD) != B0)
  1130. X    {
  1131. X        xmit_ring_size = fas_xbuf_size [cflag & CBAUD]
  1132. X                    - tthiwat [cflag & CBAUD];
  1133. X        if (xmit_ring_size < MAX_OUTPUT_FIFO_SIZE * 2)
  1134. X        {
  1135. Xsetflags2:
  1136. X            xmit_ring_size = MAX_OUTPUT_FIFO_SIZE * 2;
  1137. X        }
  1138. X        if (xmit_ring_size > XMIT_BUFF_SIZE)
  1139. X            xmit_ring_size = XMIT_BUFF_SIZE;
  1140. X        fip->xmit_ring_size = xmit_ring_size;
  1141. X    }
  1142. X
  1143. X    /* setup character time for B0 mode */
  1144. X    fas_ctimes [B0] = fas_ctimes [cflag & CBAUD];
  1145. X
  1146. X    /* disable modem control signals if required by open mode */
  1147. X    if (fip->o_state & OS_CLOCAL)
  1148. X        cflag |= CLOCAL;
  1149. X
  1150. X    /* Select hardware handshake depending on the minor device
  1151. X       number and the CTSFLOW and RTSFLOW flags (if they are
  1152. X       available).
  1153. X    */
  1154. X    fip->flow_flags.s &= ~(FF_HWO_HANDSHAKE
  1155. X                | FF_HWI_HANDSHAKE
  1156. X                | FF_HDX_HANDSHAKE);
  1157. X    if (fip->o_state & (OS_HWO_HANDSHAKE | OS_HWI_HANDSHAKE
  1158. X                    | OS_HDX_HANDSHAKE))
  1159. X    {
  1160. X        if (fip->o_state & OS_HWO_HANDSHAKE)
  1161. X            fip->flow_flags.s |= FF_HWO_HANDSHAKE;
  1162. X        if (fip->o_state & OS_HWI_HANDSHAKE)
  1163. X            fip->flow_flags.s |= FF_HWI_HANDSHAKE;
  1164. X        if (fip->o_state & OS_HDX_HANDSHAKE)
  1165. X            fip->flow_flags.s |= FF_HDX_HANDSHAKE;
  1166. X    }
  1167. X    else
  1168. X    {
  1169. X#if defined (CTSFLOW)    /* SYSV 3.2 Xenix compatibility */
  1170. X        if ((cflag & (CTSFLOW | CLOCAL)) == CTSFLOW)
  1171. X            fip->flow_flags.s |= FF_HWO_HANDSHAKE;
  1172. X#endif
  1173. X#if defined (RTSFLOW)    /* SYSV 3.2 Xenix compatibility */
  1174. X        if ((cflag & (RTSFLOW | CLOCAL)) == RTSFLOW)
  1175. X            fip->flow_flags.s |= FF_HDX_HANDSHAKE;
  1176. X#endif
  1177. X    }
  1178. X
  1179. X    /* Fake the carrier detect state flag if CLOCAL mode or if
  1180. X       requested by open mode.
  1181. X    */
  1182. X    if (!(~fip->msr & fip->modem.m.ca)
  1183. X        || (fip->o_state & OS_FAKE_CARR_ON)
  1184. X        || (cflag & CLOCAL))
  1185. X        fip->tty->t_state |= CARR_ON;
  1186. X    else
  1187. X        fip->tty->t_state &= ~CARR_ON;
  1188. X
  1189. X#if defined (XCLUDE)    /* SYSV 3.2 Xenix compatibility */
  1190. X    /* Permit exclusive use of this device. */
  1191. X    if (cflag & XCLUDE)
  1192. X        fip->o_state |= OS_EXCLUSIVE_OPEN_2;
  1193. X    else
  1194. X        fip->o_state &= ~OS_EXCLUSIVE_OPEN_2;
  1195. X#endif
  1196. X
  1197. X    fip->cflag = cflag;
  1198. X    fip->iflag = fip->tty->t_iflag;
  1199. X
  1200. X    /* enable transmitter */
  1201. X    fip->device_flags.s &= ~DF_XMIT_LOCKED;
  1202. X
  1203. X    /* setup handshake flags */
  1204. X    fas_hdx_check (fip);
  1205. X    fas_ihlw_check (fip);
  1206. X    fas_fproc (fip, fip->new_msr);
  1207. X
  1208. X    /* restart output */
  1209. X    fas_xproc (fip);
  1210. X}
  1211. X
  1212. X/* Main fas interrupt handler. Actual character processing is splitted
  1213. X   into sub-functions.
  1214. X*/
  1215. Xint
  1216. Xfasintr (vect)
  1217. Xint    vect;
  1218. X{
  1219. X    register struct fas_info    *fip;
  1220. X    register uint    status;
  1221. X    struct fas_info    *old_fip;
  1222. X    int    done, drop_mode;
  1223. X    uint    port, old_recv_count;
  1224. X    REGVAR;
  1225. X
  1226. X#if defined(FASI)
  1227. X    fasiintr_entries++;
  1228. X#endif /* FASI */
  1229. X
  1230. X    drop_mode = FALSE;
  1231. X
  1232. X    /* The 8259 interrupt controller is set up for edge trigger.
  1233. X       Therefor, we must loop until we make a complete pass without
  1234. X       getting any UARTs that are interrupting.
  1235. X    */
  1236. X    do
  1237. X    {
  1238. X        done = TRUE;
  1239. X        fip = fas_first_int_user [vect];
  1240. X
  1241. X        /* loop through all users of this interrupt vector */
  1242. X        for (;; fip = fip->next_int_user)
  1243. X        {
  1244. X            if (!fip)
  1245. X                break;    /* all users done */
  1246. X
  1247. X            /* process only ports that we expect ints from
  1248. X               and that actually need to be serviced
  1249. X            */
  1250. Xfastloop:
  1251. X            if (fas_first_inb (fip, INT_ID_PORT)
  1252. X                    & II_NO_INTS_PENDING)
  1253. X            {
  1254. X                /* restore the normal receiver trigger level */
  1255. X                if (fip->device_flags.i & DF_NS16550A_DROP_MODE)
  1256. X                {
  1257. X                    fip->device_flags.s &=
  1258. X                            ~DF_NS16550A_DROP_MODE;
  1259. X                    fas_outb (fip, NS_FIFO_CTL_PORT,
  1260. X                            NS_FIFO_SETUP_CMD);
  1261. X                }
  1262. X                /* speed beats beauty */
  1263. X                fip = fip->next_int_user;
  1264. X                if (fip)
  1265. X                    goto fastloop;
  1266. X                break;
  1267. X            }
  1268. X
  1269. X            /* restore the normal receiver trigger level */
  1270. X            if (fip->device_flags.i & DF_NS16550A_DROP_MODE)
  1271. X            {
  1272. X                fip->device_flags.s &= ~DF_NS16550A_DROP_MODE;
  1273. X                fas_outb (fip, NS_FIFO_CTL_PORT,
  1274. X                            NS_FIFO_SETUP_CMD);
  1275. X            }
  1276. X
  1277. X            done = FALSE;    /* not done if we got an int */
  1278. X            old_recv_count = fip->recv_ring_cnt;
  1279. X
  1280. X            do
  1281. X            {
  1282. X                /* read in all the characters from the FIFO */
  1283. X                if ((status = fas_inb (fip, LINE_STATUS_PORT))
  1284. X                            & LS_RCV_INT)
  1285. X                {
  1286. X                    if (!drop_mode && (fip->device_flags.i
  1287. X                        & DF_DEVICE_IS_NS16550A))
  1288. X                    {
  1289. X                    /* Drop receiver trigger levels to make
  1290. X                       sure that we will see all received
  1291. X                       characters in all NS16550A. This
  1292. X                       prevents multiple interrupts if we
  1293. X                       receive characters on more than one
  1294. X                       unit.
  1295. X                    */
  1296. X                    old_fip = fip;
  1297. X                    for (fip = fas_first_int_user [vect];
  1298. X                        fip; fip = fip->next_int_user)
  1299. X                    {
  1300. X                        if ((fip->device_flags.i
  1301. X                            & DF_DEVICE_IS_NS16550A)
  1302. X                        && (fip != old_fip))
  1303. X                        {
  1304. X                        fip->device_flags.s |=
  1305. X                            DF_NS16550A_DROP_MODE;
  1306. X                        fas_first_outb (fip,
  1307. X                            NS_FIFO_CTL_PORT,
  1308. X                            NS_FIFO_DROP_CMD);
  1309. X                        }
  1310. X                    }
  1311. X                    fip = old_fip;
  1312. X                    drop_mode = TRUE;
  1313. X                    }
  1314. X                    status = fas_rproc (fip, status);
  1315. X                    sysinfo.rcvint++;
  1316. X                }
  1317. X
  1318. X                /* Is it a transmitter empty int ? */
  1319. X                if ((status & LS_XMIT_AVAIL)
  1320. X                    && (fip->device_flags.i & DF_XMIT_BUSY))
  1321. X                {
  1322. X                    fip->device_flags.s &= ~DF_XMIT_BUSY;
  1323. X                    fas_xproc (fip);
  1324. X                    if (!(fip->device_flags.i
  1325. X                            & DF_XMIT_BUSY))
  1326. X                    {
  1327. X                        fip->device_flags.s |=
  1328. X                            DF_GUARD_TIMEOUT;
  1329. X                        fip->tty->t_state |=
  1330. X                            TIMEOUT;
  1331. X                        fip->timeout_idx =
  1332. X                            timeout (
  1333. X                            fas_timeout, fip,
  1334. X                            fas_ctimes [fip->cflag
  1335. X                                & CBAUD]);
  1336. X                    }
  1337. X                    sysinfo.xmtint++;
  1338. X                }
  1339. X
  1340. X                /* Has there been a polarity change on
  1341. X                   some of the modem lines ?
  1342. X                */
  1343. X                if ((status = fas_inb (fip, MDM_STATUS_PORT))
  1344. X                        & MS_ANY_DELTA)
  1345. X                {
  1346. X                    /* Do special RING line handling.
  1347. X                       RING generates an int only on the
  1348. X                       trailing edge.
  1349. X                    */
  1350. X                    status = (status & ~MS_RING_PRESENT)
  1351. X                        | (fip->new_msr
  1352. X                            & MS_RING_PRESENT);
  1353. X                    if (status & MS_RING_TEDGE)
  1354. X#if defined(FASI)
  1355. X                        fip->rings_detected++,
  1356. X#endif /* FASI */
  1357. X                        status |= MS_RING_PRESENT;
  1358. X                    if ((status ^ fip->new_msr)
  1359. X                            & MS_ANY_PRESENT)
  1360. X                    {
  1361. X                        /* check for excessive modem
  1362. X                           status interrupts
  1363. X                        */
  1364. X                        if (++fip->msi_cnt >
  1365. X                            (MAX_MSI_CNT / HZ)
  1366. X                              * (EVENT_TIME * HZ
  1367. X                                / 1000))
  1368. X                        {
  1369. X                            fip->ier = IE_NONE;
  1370. X                            fas_outb (fip,
  1371. X                                INT_ENABLE_PORT,
  1372. X                                fip->ier);
  1373. X                        }
  1374. X                        /* check hw flow flags */
  1375. X                        fas_fproc (fip, status);
  1376. X                        fip->new_msr = status;
  1377. X                        event_sched (fip, EF_DO_MPROC);
  1378. X                    }
  1379. X                    sysinfo.mdmint++;
  1380. X#if defined(FASI)
  1381. X                    fip->modem_status_events++;
  1382. X#endif /* FASI */
  1383. X                }
  1384. X            } while (!(fas_inb (fip, INT_ID_PORT)
  1385. X                        & II_NO_INTS_PENDING));
  1386. X
  1387. X            /* schedule character transfer to UNIX buffer */
  1388. X            if (fip->recv_ring_cnt
  1389. X#if defined (HAVE_VPIX)
  1390. X                && (((fip->iflag & DOSMODE)
  1391. X                    ? MAX_VPIX_FILL - MIN_READ_CHUNK
  1392. X                    : MAX_UNIX_FILL - MIN_READ_CHUNK)
  1393. X                        >= fip->tty->t_rawq.c_cc)
  1394. X#else
  1395. X                && ((MAX_UNIX_FILL - MIN_READ_CHUNK)
  1396. X                        >= fip->tty->t_rawq.c_cc)
  1397. X#endif
  1398. X                && !(fip->flow_flags.i & FF_RXFER_STOPPED))
  1399. X            {
  1400. X                event_sched (fip, EF_DO_RXFER);
  1401. X            }
  1402. X
  1403. X            /* check input buffer high/low water marks */
  1404. X            if (fip->recv_ring_cnt != old_recv_count)
  1405. X                fas_ihlw_check (fip);
  1406. X        }
  1407. X    } while (!done);
  1408. X
  1409. X    /* clear the shared interrupt since we have scanned all
  1410. X       of the ports that share this interrupt vector
  1411. X    */    
  1412. X    if (port = fas_int_ack_port [vect])
  1413. X        (void) outb (port, fas_int_ack [vect]);
  1414. X
  1415. X    return (0);
  1416. X}
  1417. X
  1418. X/* hardware flow control interrupt handler */
  1419. Xstatic void
  1420. Xfas_fproc (fip, mdm_status)
  1421. Xregister struct fas_info    *fip;
  1422. Xregister uint    mdm_status;
  1423. X{
  1424. X    /* Check the output flow control signals and set the state flag
  1425. X       accordingly.
  1426. X    */
  1427. X    if (!(~mdm_status & fip->flow.m.oc)
  1428. X        || (~mdm_status & fip->flow.m.oe)
  1429. X        || !(fip->flow_flags.i & FF_HWO_HANDSHAKE))
  1430. X    {
  1431. X        if (fip->flow_flags.i & FF_HWO_STOPPED)
  1432. X        {
  1433. X            fip->flow_flags.s &= ~FF_HWO_STOPPED;
  1434. X            fas_xproc (fip);
  1435. X        }
  1436. X    }
  1437. X    else
  1438. X#if defined(FASI)
  1439. X        fip->xmtr_hw_flow_count++,
  1440. X        wakeup((caddr_t)&fip->device_flags.i),
  1441. X#endif /* FASI */
  1442. X        fip->flow_flags.s |= FF_HWO_STOPPED;
  1443. X}
  1444. X
  1445. X/* modem status handler */
  1446. Xstatic void
  1447. Xfas_mproc (fip)
  1448. Xregister struct fas_info    *fip;
  1449. X{
  1450. X    register struct tty    *ttyp;
  1451. X    register uint    mdm_status;
  1452. X    uint    vpix_status;
  1453. X    int    old_level;
  1454. X
  1455. X    ttyp = fip->tty;
  1456. X    mdm_status = fip->new_msr;
  1457. X    fip->new_msr &= ~MS_RING_PRESENT;
  1458. X
  1459. X    /* Check the carrier detect signal and set the state flags
  1460. X       accordingly. Also, if not in clocal mode, send SIGHUP on
  1461. X       carrier loss and flush the buffers.
  1462. X    */
  1463. X    if (!(fip->cflag & CLOCAL))
  1464. X    {
  1465. X        if (!(~mdm_status & fip->modem.m.ca))
  1466. X        {
  1467. X            ttyp->t_state |= CARR_ON;
  1468. X            /* Unblock getty open only if it is ready to run. */
  1469. X            if ((ttyp->t_state & WOPEN)
  1470. X                && (~fip->msr & fip->modem.m.ca))
  1471. X#if defined(FASI)
  1472. X            {
  1473. X#endif
  1474. X                (void) wakeup ((caddr_t) &ttyp->t_canq);
  1475. X#if defined(FASI)
  1476. X                (void)wakeup((caddr_t)&fip->device_flags.i);
  1477. X            }
  1478. X#endif
  1479. X        }
  1480. X        else
  1481. X        {
  1482. X            if (!(~fip->msr & fip->modem.m.ca))
  1483. X            {
  1484. X                ttyp->t_state &= ~CARR_ON;
  1485. X                old_level = SPLWRK ();
  1486. X                if (ttyp->t_state & ISOPEN)
  1487. X                    (void) signal (ttyp->t_pgrp, SIGHUP);
  1488. X                (void) ttyflush (ttyp, FREAD | FWRITE);
  1489. X                (void) splx (old_level);
  1490. X            }
  1491. X        }
  1492. X    }
  1493. X
  1494. X#if defined (HAVE_VPIX)
  1495. X    if (((fip->iflag & (DOSMODE | PARMRK))
  1496. X            == (DOSMODE | PARMRK))
  1497. X        && (fip->v86_intmask != V86VI_KBD))
  1498. X    {
  1499. X        /* prepare status bits for VP/ix */
  1500. X        vpix_status = (((mdm_status ^ fip->msr) >> 4) & MS_ANY_DELTA)
  1501. X                | (mdm_status & (MS_CTS_PRESENT
  1502. X                            | MS_DSR_PRESENT
  1503. X                            | MS_DCD_PRESENT));
  1504. X        if (fip->flow_flags.i & FF_HWO_HANDSHAKE)
  1505. X        {
  1506. X            vpix_status &= ~((fip->flow.m.oc | fip->flow.m.oe)
  1507. X                            >> 4);
  1508. X            vpix_status |= fip->flow.m.oc | fip->flow.m.oe;
  1509. X        }
  1510. X        /* send status bits to VP/ix */
  1511. X        if ((vpix_status & MS_ANY_DELTA)
  1512. X            && fas_vpix_sr (fip, 2, vpix_status))
  1513. X            event_sched (fip, EF_DO_RXFER);
  1514. X    }
  1515. X#endif
  1516. X    fip->msr = mdm_status & ~MS_RING_PRESENT;
  1517. X
  1518. X    /* re-schedule if modem status flags have changed in the mean time */
  1519. X    if ((fip->new_msr ^ fip->msr) & MS_ANY_PRESENT)
  1520. X    {
  1521. X        event_sched (fip, EF_DO_MPROC)
  1522. X    }
  1523. X#if defined(FASI)
  1524. X    else
  1525. X        (void)wakeup((caddr_t)&fip->device_flags.i);
  1526. X#endif /* FASI */
  1527. X}
  1528. X
  1529. X/* Receiver interrupt handler. Translates input characters to character
  1530. X   sequences as described in TERMIO(7) man page.
  1531. X*/
  1532. Xstatic uint
  1533. Xfas_rproc (fip, line_status)
  1534. Xregister struct fas_info    *fip;
  1535. Xuint    line_status;
  1536. X{
  1537. X    struct tty    *ttyp;
  1538. X    uint    charac;
  1539. X    register uint    csize;
  1540. X    unchar    metta [4];
  1541. X    REGVAR;
  1542. X
  1543. X    ttyp = fip->tty;
  1544. X
  1545. X    fas_first_ctl (fip, RCV_DATA_PORT);
  1546. X
  1547. X    /* Translate characters from FIFO according to the TERMIO(7)
  1548. X       man page.
  1549. X    */
  1550. X    do
  1551. X    {
  1552. X        charac = (line_status & LS_RCV_AVAIL)
  1553. X#if defined(FASI)
  1554. X                ? (fip->characters_received++,fas_inb (fip, RCV_DATA_PORT))
  1555. X#else
  1556. X                ? fas_inb (fip, RCV_DATA_PORT)
  1557. X#endif /* FASI */
  1558. X                : 0;    /* was line status int only */
  1559. X
  1560. X        /* do we have to junk the character ? */
  1561. X        if (!(fip->cflag & CREAD)
  1562. X            || ((ttyp->t_state & (ISOPEN | CARR_ON)) !=
  1563. X                        (ISOPEN | CARR_ON)))
  1564. X        {
  1565. X            /* if there are FIFOs we take a short cut */
  1566. X            if (fip->device_flags.i & DF_DEVICE_IS_NS16550A)
  1567. X                fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_SETUP_CMD
  1568. X                            | NS_FIFO_CLR_RECV);
  1569. X            else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
  1570. X            {
  1571. X                fas_outb (fip, I_BANK_PORT, I_BANK_1);
  1572. X                fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
  1573. X                fas_outb (fip, I_BANK_PORT, I_BANK_0);
  1574. X            }
  1575. X            continue;
  1576. X        }
  1577. X
  1578. X        csize = 0;
  1579. X
  1580. X        /* strip off 8th bit ? */
  1581. X        if (fip->iflag & ISTRIP)
  1582. X            charac &= 0x7f;
  1583. X
  1584. X        /* ignore parity errors ? */
  1585. X        if ((line_status & LS_PARITY_ERROR)
  1586. X            && !(fip->iflag & INPCK))
  1587. X            line_status &= ~LS_PARITY_ERROR;
  1588. X
  1589. X#if defined(FASI)
  1590. X        if(line_status & LS_OVERRUN)
  1591. X            fip->overrun_errors++;
  1592. X#endif /* FASI */
  1593. X
  1594. X        /* do we have some kind of character error ? */
  1595. X        if (line_status & (LS_PARITY_ERROR
  1596. X                    | LS_FRAMING_ERROR
  1597. X                    | LS_BREAK_DETECTED))
  1598. X        {
  1599. X#if defined(FASI)
  1600. X            if(line_status & LS_PARITY_ERROR)
  1601. X                fip->parity_errors++;
  1602. X            if(line_status & LS_FRAMING_ERROR)
  1603. X                fip->framing_errors++;
  1604. X            if(line_status & LS_BREAK_DETECTED)
  1605. X                fip->breaks_detected++;
  1606. X#endif /* FASI */
  1607. X#if defined (HAVE_VPIX)
  1608. X            if ((fip->iflag & (DOSMODE | PARMRK))
  1609. X                    == (DOSMODE | PARMRK))
  1610. X            {
  1611. X                /* send status bits to VP/ix */
  1612. X                (void) fas_vpix_sr (fip, 1,
  1613. X                    (line_status & (LS_PARITY_ERROR
  1614. X                            | LS_FRAMING_ERROR
  1615. X                            | LS_BREAK_DETECTED))
  1616. X                        | LS_RCV_AVAIL
  1617. X                        | LS_XMIT_AVAIL
  1618. X                        | LS_XMIT_COMPLETE);
  1619. X                goto valid_char;
  1620. X            }
  1621. X#endif
  1622. X            /* is it a BREAK ? */
  1623. X            if (line_status & LS_BREAK_DETECTED)
  1624. X            {
  1625. X                if (!(fip->iflag & IGNBRK))
  1626. X                    if (fip->iflag & BRKINT)
  1627. X                    {
  1628. X                        /* do BREAK interrupt */
  1629. X                        event_sched (fip, EF_DO_BRKINT);
  1630. X                    }
  1631. X                    else
  1632. X                    {
  1633. X                        metta [csize] = 0;
  1634. X                        csize++;
  1635. X                        if (fip->iflag & PARMRK)
  1636. X                        {
  1637. X                            metta [csize] = 0;
  1638. X                            csize++;
  1639. X                            metta [csize] = 0xff;
  1640. X                            csize++;
  1641. X                        }
  1642. X                    }
  1643. X            }
  1644. X            else if (!(fip->iflag & IGNPAR))
  1645. X                if (fip->iflag & PARMRK)
  1646. X                {
  1647. X                    metta [csize] = charac;
  1648. X                    csize++;
  1649. X                    metta [csize] = 0;
  1650. X                    csize++;
  1651. X                    metta [csize] = 0xff;
  1652. X                    csize++;
  1653. X                }
  1654. X                else
  1655. X                {
  1656. X                    metta [csize] = 0;
  1657. X                    csize++;
  1658. X                }
  1659. X        }
  1660. X        else
  1661. X        /* is there a character to process ? */
  1662. X        if (line_status & LS_RCV_AVAIL)
  1663. X        {
  1664. X            if (fip->iflag & IXON)
  1665. X            {
  1666. X                /* do output start/stop handling */
  1667. X                if (fip->flow_flags.i & FF_SWO_STOPPED)
  1668. X                {
  1669. X#if defined (HAVE_VPIX)
  1670. X                    if ((charac == fip->v86_ss.ss_start)
  1671. X#else
  1672. X                    if ((charac == CSTART)
  1673. X#endif
  1674. X                        || (fip->iflag & IXANY))
  1675. X                    {
  1676. X                        fip->flow_flags.s &=
  1677. X                            ~FF_SWO_STOPPED;
  1678. X                        ttyp->t_state &= ~TTSTOP;
  1679. X                        /* restart output */
  1680. X                        fas_xproc (fip);
  1681. X                    }
  1682. X                }
  1683. X                else
  1684. X                {
  1685. X#if defined (HAVE_VPIX)
  1686. X                    if (charac == fip->v86_ss.ss_stop)
  1687. X#else
  1688. X                    if (charac == CSTOP)
  1689. X#endif
  1690. X                    {
  1691. X                        fip->flow_flags.s |=
  1692. X                            FF_SWO_STOPPED;
  1693. X                        ttyp->t_state |= TTSTOP;
  1694. X                    }
  1695. X                }
  1696. X                /* we don't put start/stop characters
  1697. X                   into the receiver buffer
  1698. X                */
  1699. X#if defined (HAVE_VPIX)
  1700. X                if ((charac == fip->v86_ss.ss_start)
  1701. X                    || (charac == fip->v86_ss.ss_stop))
  1702. X#else
  1703. X                if ((charac == CSTART)
  1704. X                    || (charac == CSTOP))
  1705. X#endif
  1706. X                    continue;
  1707. X            }
  1708. Xvalid_char:
  1709. X            if ((charac == 0xff) && (fip->iflag & PARMRK))
  1710. X            {
  1711. X                metta [csize] = 0xff;
  1712. X                csize++;
  1713. X                metta [csize] = 0xff;
  1714. X                csize++;
  1715. X            }
  1716. X            else
  1717. X            {
  1718. X                /* we take a short-cut if only one character
  1719. X                   has to be put into the receiver buffer
  1720. X                */
  1721. X                if (fip->recv_ring_cnt < RECV_BUFF_SIZE)
  1722. X                {
  1723. X                    fip->recv_ring_cnt++;
  1724. X                    *fip->recv_ring_put_ptr = charac;
  1725. X                    if (++fip->recv_ring_put_ptr
  1726. X                        != &fip->recv_buffer
  1727. X                            [RECV_BUFF_SIZE])
  1728. X                        continue;
  1729. X                    fip->recv_ring_put_ptr =
  1730. X                            &fip->recv_buffer [0];
  1731. X                }
  1732. X                continue;
  1733. X            }
  1734. X        }
  1735. X
  1736. X        if (!(csize) || (fip->recv_ring_cnt + csize > RECV_BUFF_SIZE))
  1737. X            continue;    /* nothing to put into recv buffer */
  1738. X
  1739. X        fip->recv_ring_cnt += csize;
  1740. X
  1741. X        /* store translation in ring buffer */
  1742. X        do
  1743. X        {
  1744. X            do
  1745. X            {
  1746. X                *fip->recv_ring_put_ptr = (metta - 1) [csize];
  1747. X                if (++fip->recv_ring_put_ptr
  1748. X                    == &fip->recv_buffer [RECV_BUFF_SIZE])
  1749. X                    break;
  1750. X            } while (--csize);
  1751. X            if (!csize)
  1752. X                break;
  1753. X            fip->recv_ring_put_ptr = &fip->recv_buffer [0];
  1754. X        } while (--csize);
  1755. X    } while ((line_status = fas_inb (fip, LINE_STATUS_PORT)) & LS_RCV_INT);
  1756. X
  1757. X    return (line_status);
  1758. X}
  1759. X
  1760. X/* Output characters to the transmitter register. */
  1761. Xstatic void
  1762. Xfas_xproc (fip)
  1763. Xregister struct fas_info    *fip;
  1764. X{
  1765. X    register uint    num_to_output;
  1766. X    REGVAR;
  1767. X
  1768. X    /* proceed only if transmitter is available */
  1769. X    if ((fip->device_flags.i & (DF_XMIT_BUSY | DF_XMIT_BREAK
  1770. X                        | DF_XMIT_LOCKED))
  1771. X        || (fip->flow_flags.i & FF_HWO_STOPPED))
  1772. X        goto sched;
  1773. X
  1774. X    num_to_output = fip->xmit_fifo_size;
  1775. X
  1776. X    /* handle XON/XOFF input flow control requests */
  1777. X    if (fip->flow_flags.i & FF_SW_FC_REQ)
  1778. X    {
  1779. X#if defined (HAVE_VPIX)
  1780. X        fas_first_outb (fip, XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED)
  1781. X                    ? fip->v86_ss.ss_stop
  1782. X                    : fip->v86_ss.ss_start);
  1783. X#else
  1784. X        fas_first_outb (fip, XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED)
  1785. X                    ? CSTOP
  1786. X                    : CSTART);
  1787. X#endif
  1788. X        fip->tty->t_state &= ~(TTXON | TTXOFF);
  1789. X        fip->device_flags.s |= DF_XMIT_BUSY;
  1790. X        fip->flow_flags.s &= ~FF_SW_FC_REQ;
  1791. X        /* disable guard timeout */
  1792. X        if (fip->device_flags.i & DF_GUARD_TIMEOUT)
  1793. X        {
  1794. X            fip->device_flags.s &= ~DF_GUARD_TIMEOUT;
  1795. X            fip->tty->t_state &= ~TIMEOUT;
  1796. X            (void) untimeout (fip->timeout_idx);
  1797. X        }
  1798. X        num_to_output--;
  1799. X    }
  1800. X
  1801. X    /* bail out if output is suspended by XOFF */
  1802. X    if (fip->flow_flags.i & FF_SWO_STOPPED)
  1803. X        goto sched;
  1804. X
  1805. X    /* Determine how many chars to put into the transmitter
  1806. X       register.
  1807. X    */
  1808. X    if (fip->xmit_ring_cnt < num_to_output)
  1809. X        num_to_output = fip->xmit_ring_cnt;
  1810. X
  1811. X    /* no characters available ? */
  1812. X    if (!num_to_output)
  1813. X        goto sched;
  1814. X
  1815. X    /* output characters */
  1816. X    fip->xmit_ring_cnt -= num_to_output;
  1817. X
  1818. X    fas_ctl (fip, XMT_DATA_PORT);
  1819. X
  1820. X#if defined(FASI)
  1821. X    fip->characters_transmitted += num_to_output;
  1822. X#endif /* FASI */
  1823. X
  1824. X    do
  1825. X    {
  1826. X        do
  1827. X        {
  1828. X            (void) outb (XMT_DATA_PORT.addr,
  1829. X                    *fip->xmit_ring_take_ptr);
  1830. X            if (++fip->xmit_ring_take_ptr
  1831. X                    == &fip->xmit_buffer [XMIT_BUFF_SIZE])
  1832. X                break;
  1833. X        } while (--num_to_output);
  1834. X        if (!num_to_output)
  1835. X            break;
  1836. X        fip->xmit_ring_take_ptr = &fip->xmit_buffer [0];
  1837. X    } while (--num_to_output);
  1838. X
  1839. X    /* signal that transmitter is busy now */
  1840. X    fip->device_flags.s |= DF_XMIT_BUSY;
  1841. X    /* disable guard timeout */
  1842. X    if (fip->device_flags.i & DF_GUARD_TIMEOUT)
  1843. X    {
  1844. X        fip->device_flags.s &= ~DF_GUARD_TIMEOUT;
  1845. X        fip->tty->t_state &= ~TIMEOUT;
  1846. X        (void) untimeout (fip->timeout_idx);
  1847. X    }
  1848. X
  1849. X    /* schedule fas_xxfer () if there are more characters to transfer
  1850. X       into the transmitter ring buffer
  1851. X    */
  1852. Xsched:
  1853. X    if ((fip->xmit_ring_size > fip->xmit_ring_cnt)
  1854. X        && (fip->tty->t_outq.c_cc || fip->tty->t_tbuf.c_count))
  1855. X    {
  1856. X        event_sched (fip, EF_DO_XXFER);
  1857. X    }
  1858. X}
  1859. X
  1860. X/* Asynchronous event handler. Scheduled by functions that can't do the
  1861. X   processing themselves because of execution time restrictions.
  1862. X*/
  1863. Xstatic void
  1864. Xfas_event (dummy)
  1865. Xvoid    *dummy;
  1866. X{
  1867. X    register struct fas_info    *fip;
  1868. X    register uint    unit;
  1869. X    int    old_level;
  1870. X
  1871. X    old_level = SPLINT ();
  1872. X
  1873. X    unit = 0;
  1874. X    fip = &fas_info [0];
  1875. X
  1876. X    /* loop through all fas_info structures */
  1877. X    for (;; fip++, unit++)
  1878. X    {
  1879. X        if (unit >= fas_physical_units)
  1880. X        break;    /* all structures done */
  1881. X
  1882. X        /* process only structures that actually need to
  1883. X           be serviced
  1884. X        */
  1885. Xfastloop2:
  1886. X        if (!fip->event_flags.i)
  1887. X        {
  1888. X        /* speed beats beauty */
  1889. X        fip++;
  1890. X        if (++unit < fas_physical_units)
  1891. X            goto fastloop2;
  1892. X        break;
  1893. X        }
  1894. X
  1895. X        do
  1896. X        {
  1897. X        /* check the modem signals */
  1898. X        if (fip->event_flags.i & EF_DO_MPROC)
  1899. X        {
  1900. X            fip->event_flags.s &= ~EF_DO_MPROC;
  1901. X            fas_mproc (fip);
  1902. X            /* disable the device if there were too many modem
  1903. X               status interrupts
  1904. X            */
  1905. X            if (fip->msi_cnt > (MAX_MSI_CNT / HZ)
  1906. X                        * (EVENT_TIME * HZ / 1000))
  1907. X            {
  1908. X                fip->device_flags.s &= ~(DF_DEVICE_CONFIGURED
  1909. X                            | DF_XMIT_BUSY
  1910. X                            | DF_XMIT_BREAK);
  1911. X                fip->device_flags.s |= DF_XMIT_LOCKED;
  1912. X                if (fip->device_flags.i & DF_GUARD_TIMEOUT)
  1913. X                {
  1914. X                    fip->device_flags.s &=
  1915. X                            ~DF_GUARD_TIMEOUT;
  1916. X                    fip->tty->t_state &= ~TIMEOUT;
  1917. X                    (void) untimeout (fip->timeout_idx);
  1918. X                    (void) wakeup ((caddr_t) &(fip)->
  1919. X                                device_flags.i);
  1920. X                }
  1921. X                fip->tty->t_state &= ~CARR_ON;
  1922. X                (void) SPLWRK ();
  1923. X                if (!(fip->cflag & CLOCAL)
  1924. X                    && (fip->tty->t_state & ISOPEN))
  1925. X                    (void) signal (fip->tty->t_pgrp,
  1926. X                                SIGHUP);
  1927. X                (void) ttyflush (fip->tty, FREAD | FWRITE);
  1928. X                (void) printf ("\nWARNING: Excessive modem status interrupts on FAS unit %d (check the cabling).\n",
  1929. X                            fip - &fas_info [0]);
  1930. X                (void) SPLINT ();
  1931. X            }
  1932. X            fip->msi_cnt = 0;
  1933. X        }
  1934. X
  1935. X        /* do the break interrupt */
  1936. X        if (fip->event_flags.i & EF_DO_BRKINT)
  1937. X        {
  1938. X            fip->event_flags.s &= ~EF_DO_BRKINT;
  1939. X            if (fip->tty->t_state & ISOPEN)
  1940. X            {
  1941. X                (void) SPLWRK ();
  1942. X                (*linesw [fip->tty->t_line].l_input)
  1943. X                            (fip->tty, L_BREAK);
  1944. X                (void) SPLINT ();
  1945. X            }
  1946. X        }
  1947. X
  1948. X        /* transfer characters to the UNIX input buffer */
  1949. X        if (fip->event_flags.i & EF_DO_RXFER)
  1950. X        {
  1951. X            fip->event_flags.s &= ~EF_DO_RXFER;
  1952. X            if (!(fip->flow_flags.i & FF_RXFER_STOPPED))
  1953. X            {
  1954. X                (void) SPLWRK ();
  1955. X                fas_rxfer (fip);
  1956. X                (void) SPLINT ();
  1957. X                /* check input buffer high/low water marks */
  1958. X                fas_ihlw_check (fip);
  1959. X            }
  1960. X        }
  1961. X
  1962. X        /* transfer characters to the output ring buffer */
  1963. X        if (fip->event_flags.i & EF_DO_XXFER)
  1964. X        {
  1965. X            fip->event_flags.s &= ~EF_DO_XXFER;
  1966. X            (void) SPLWRK ();
  1967. X            fas_xxfer (fip);
  1968. X            (void) SPLINT ();
  1969. X            fas_hdx_check (fip);
  1970. X            /* output characters */
  1971. X            fas_xproc (fip);
  1972. X        }
  1973. X
  1974. X#if defined (HAVE_VPIX)
  1975. X        /* send pseudorupt to VP/ix */
  1976. X        if (fip->event_flags.i & EF_SIGNAL_VPIX)
  1977. X        {
  1978. X            fip->event_flags.s &= ~EF_SIGNAL_VPIX;
  1979. X            if ((fip->iflag & DOSMODE) && fip->v86_proc)
  1980. X            {
  1981. X                (void) SPLWRK ();
  1982. X                (void) v86setint (fip->v86_proc,
  1983. X                            fip->v86_intmask);
  1984. X                (void) SPLINT ();
  1985. X            }
  1986. X        }
  1987. X#endif
  1988. X        } while (fip->event_flags.i);
  1989. X
  1990. X        /* allow pending tty interrupts */
  1991. X        (void) SPLWRK ();
  1992. X        (void) SPLINT ();
  1993. X    }
  1994. X
  1995. X    event_scheduled = FALSE;
  1996. X
  1997. X    /* check whether there have been new requests in the mean time */
  1998. X    for (unit = 0, fip = &fas_info [0]; unit < fas_physical_units;
  1999. X                            fip++, unit++)
  2000. X        if (fip->event_flags.i)
  2001. X        {
  2002. X            /* there is at least one new request, so
  2003. X               schedule the next event processing
  2004. X            */
  2005. X            event_scheduled = TRUE;
  2006. X            (void) timeout (fas_event, (void *) NULL,
  2007. X                    (EVENT_TIME) * (HZ) / 1000);
  2008. X            break;
  2009. X        }
  2010. X
  2011. X#if defined(FASI)
  2012. X    (void)wakeup((caddr_t)&fip->device_flags.i);
  2013. X#endif /* FASI */
  2014. X    (void) splx (old_level);
  2015. X}
  2016. X
  2017. X#if defined (HAVE_VPIX)
  2018. X/* Send port status register to VP/ix */
  2019. Xstatic int
  2020. Xfas_vpix_sr (fip, token, status)
  2021. Xregister struct fas_info    *fip;
  2022. Xuint    token;
  2023. Xuint    status;
  2024. X{
  2025. X    if ((fip->recv_ring_cnt <= RECV_BUFF_SIZE - 3)
  2026. X        && ((fip->tty->t_state & (ISOPEN | CARR_ON)) ==
  2027. X                        (ISOPEN | CARR_ON)))
  2028. X    {
  2029. X        /* sent the character sequence 0xff, <token>, <status>
  2030. X           to VP/ix
  2031. X        */
  2032. X        fip->recv_ring_cnt += 3;
  2033. X
  2034. X        *fip->recv_ring_put_ptr = 0xff;
  2035. X        if (++fip->recv_ring_put_ptr
  2036. X                == &fip->recv_buffer [RECV_BUFF_SIZE])
  2037. X            fip->recv_ring_put_ptr
  2038. X                = &fip->recv_buffer [0];
  2039. X        *fip->recv_ring_put_ptr = token;
  2040. X        if (++fip->recv_ring_put_ptr
  2041. X                == &fip->recv_buffer [RECV_BUFF_SIZE])
  2042. X            fip->recv_ring_put_ptr
  2043. X                = &fip->recv_buffer [0];
  2044. X        *fip->recv_ring_put_ptr = status;
  2045. X        if (++fip->recv_ring_put_ptr
  2046. X                == &fip->recv_buffer [RECV_BUFF_SIZE])
  2047. X            fip->recv_ring_put_ptr
  2048. X                = &fip->recv_buffer [0];
  2049. X        return (TRUE);
  2050. X    }
  2051. X    return (FALSE);
  2052. X}
  2053. X#endif
  2054. X
  2055. X/* Receiver ring buffer -> UNIX buffer transfer function. */
  2056. Xstatic void
  2057. Xfas_rxfer (fip)
  2058. Xregister struct fas_info    *fip;
  2059. X{
  2060. X    register struct tty    *ttyp;
  2061. X    register int    num_to_xfer;
  2062. X    int    num_save;
  2063. X    int    old_level;
  2064. X
  2065. X    ttyp = fip->tty;
  2066. X
  2067. X    for (;;)
  2068. X    {
  2069. X        if (!fip->recv_ring_cnt || !ttyp->t_rbuf.c_ptr)
  2070. X            break;    /* no characters to transfer */
  2071. X
  2072. X        /* determine how many characters to transfer */
  2073. X#if defined (HAVE_VPIX)
  2074. X        num_to_xfer = ((fip->iflag & DOSMODE)
  2075. X                ? MAX_VPIX_FILL
  2076. X                : MAX_UNIX_FILL) - ttyp->t_rawq.c_cc;
  2077. X#else
  2078. X        num_to_xfer = MAX_UNIX_FILL - ttyp->t_rawq.c_cc;
  2079. X#endif
  2080. X
  2081. X        if (num_to_xfer < MIN_READ_CHUNK)
  2082. X            break;    /* input buffer full */
  2083. X
  2084. X#if defined (HAVE_VPIX)
  2085. X        /* wakeup VP/ix */
  2086. X        if ((fip->iflag & DOSMODE) && !ttyp->t_rawq.c_cc)
  2087. X            event_sched (fip, EF_SIGNAL_VPIX);
  2088. X#endif
  2089. X
  2090. X        /* determine how many characters are in one contigous block */
  2091. X        if (fip->recv_ring_cnt < num_to_xfer)
  2092. X            num_to_xfer = fip->recv_ring_cnt;
  2093. X        if (&fip->recv_buffer [RECV_BUFF_SIZE] - fip->recv_ring_take_ptr
  2094. X            < num_to_xfer)
  2095. X            num_to_xfer = &fip->recv_buffer [RECV_BUFF_SIZE]
  2096. X                    - fip->recv_ring_take_ptr;
  2097. X        if (ttyp->t_rbuf.c_count < num_to_xfer)
  2098. X            num_to_xfer = ttyp->t_rbuf.c_count;
  2099. X
  2100. X        num_save = num_to_xfer;
  2101. X        ttyp->t_rbuf.c_count -= num_to_xfer;
  2102. X
  2103. X        /* do the transfer */
  2104. X        do
  2105. X        {
  2106. X            *ttyp->t_rbuf.c_ptr = *fip->recv_ring_take_ptr;
  2107. X            ttyp->t_rbuf.c_ptr++;
  2108. X            fip->recv_ring_take_ptr++;
  2109. X        } while (--num_to_xfer);
  2110. X
  2111. X        if (fip->recv_ring_take_ptr == &fip->recv_buffer [RECV_BUFF_SIZE])
  2112. X            fip->recv_ring_take_ptr = &fip->recv_buffer [0];
  2113. X
  2114. X        intr_disable ();
  2115. X        fip->recv_ring_cnt -= num_save;
  2116. X        intr_restore ();
  2117. X
  2118. X        ttyp->t_rbuf.c_ptr -= ttyp->t_rbuf.c_size
  2119. X                    - ttyp->t_rbuf.c_count;
  2120. X        (*linesw [ttyp->t_line].l_input) (ttyp, L_BUF);
  2121. X    }
  2122. X}
  2123. X
  2124. X/* UNIX buffer -> transmitter ring buffer transfer function. */
  2125. Xstatic void
  2126. Xfas_xxfer (fip)
  2127. Xregister struct fas_info    *fip;
  2128. X{
  2129. X    register struct tty    *ttyp;
  2130. X    register int    num_to_xfer;
  2131. SHAR_EOF
  2132. true || echo 'restore of fasi/fas.c failed'
  2133. fi
  2134. echo 'End of ecu310 part 30'
  2135. echo 'File fasi/fas.c is continued in part 31'
  2136. echo 31 > _shar_seq_.tmp
  2137. exit 0
  2138. --------------------------------------------------------------------
  2139. Warren Tucker, TuckerWare emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
  2140. Hacker Extraordinaire  d' async PADs,  pods,  proteins and protocols
  2141.  
  2142. exit 0 # Just in case...
  2143. -- 
  2144. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2145. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2146. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2147. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2148.