home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-08-05 | 53.8 KB | 2,148 lines |
- Newsgroups: comp.sources.misc
- From: Warren Tucker <wht@n4hgf.Mt-Park.GA.US>
- Subject: v21i082: ecu - ECU async comm package rev 3.10, Part30/37
- Message-ID: <1991Aug5.211912.8224@sparky.IMD.Sterling.COM>
- X-Md4-Signature: dc999e1f07e9e9979aefb18909481afd
- Date: Mon, 5 Aug 1991 21:19:12 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Warren Tucker <wht@n4hgf.Mt-Park.GA.US>
- Posting-number: Volume 21, Issue 82
- Archive-name: ecu/part30
- Environment: SCO, XENIX, ISC
- Supersedes: ecu3: Volume 16, Issue 25-59
-
- ---- Cut Here and feed the following to sh ----
- #!/bin/sh
- # this is ecu310.30 (part 30 of ecu310)
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file fasi/fas.c continued
- #
- if touch 2>&1 | fgrep 'amc' > /dev/null
- then TOUCH=touch
- else TOUCH=true
- fi
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 30; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test ! -f _shar_wnt_.tmp; then
- echo 'x - still skipping fasi/fas.c'
- else
- echo 'x - continuing file fasi/fas.c'
- sed 's/^X//' << 'SHAR_EOF' >> 'fasi/fas.c' &&
- X OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
- X | OS_HWI_HANDSHAKE,
- X OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE,
- X OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
- X | OS_HDX_HANDSHAKE
- X};
- X
- X/* The following defines are used to access multiplexed ports. */
- X#define GET_PORT(port,num) \
- X ((fip->device_flags.i & DF_CTL_EVERY)\
- X ? (port)\
- X : (port) + (num))
- X
- X#define fas_first_ctl(fip,port) \
- X ((void) (((fip)->device_flags.i & DF_CTL_FIRST)\
- X ? outb (CTL_PORT, (port).p.ctl)\
- X : 0))
- X
- X#define fas_ctl(fip,port) \
- X ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
- X ? outb (CTL_PORT, (port).p.ctl)\
- X : 0))
- X
- X#define fas_first_outb(fip,port,val) \
- X ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
- X ? outb (CTL_PORT, (port).p.ctl)\
- X : 0),\
- X (void) outb ((port).addr, (val)))
- X
- X#define fas_outb(fip,port,val) \
- X ((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
- X ? outb (CTL_PORT, (port).p.ctl)\
- X : 0),\
- X (void) outb ((port).addr, (val)))
- X
- X#define fas_first_inb(fip,port) \
- X ((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
- X ? outb (CTL_PORT, (port).p.ctl)\
- X : 0),\
- X inb ((port).addr))
- X
- X#define fas_inb(fip,port) \
- X ((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
- X ? outb (CTL_PORT, (port).p.ctl)\
- X : 0),\
- X inb ((port).addr))
- X
- X/* The following defines are used to take apart the minor device numbers. */
- X#define GET_UNIT(dev) ((dev) & 0x0f)
- X#define GET_OPEN_MODE(dev) (fas_open_modes [((dev) >> 4) & 0x0f])
- X
- X/* lock device against concurrent use */
- X#define get_device_lock(fip,prio) \
- X{\
- X /* sleep while device is used by an other process */\
- X while ((fip)->device_flags.i & DF_DEVICE_LOCKED)\
- X (void) sleep ((caddr_t) &(fip)->device_flags.i, (prio));\
- X (fip)->device_flags.s |= DF_DEVICE_LOCKED;\
- X}
- X
- X/* release device */
- X#define release_device_lock(fip) \
- X{\
- X (fip)->device_flags.s &= ~DF_DEVICE_LOCKED;\
- X /* wakeup the process that may wait for this device */\
- X (void) wakeup ((caddr_t) &(fip)->device_flags.i);\
- X}
- X
- X/* schedule event */
- X#define event_sched(fip,event) \
- X{\
- X (fip)->event_flags.s |= (event);\
- X if (!event_scheduled)\
- X {\
- X event_scheduled = TRUE;\
- X (void) timeout (fas_event, (void *) NULL,\
- X (EVENT_TIME) * (HZ) / 1000);\
- X }\
- X}
- X
- X/* fasinit
- X This routine checks for the presense of the devices in the fas_port
- X array and if the device is present tests and initializes it.
- X During the initialization if the device is determined to be an
- X NS16550A chip the DF_DEVICE_IS_NS16550A flag is set and the FIFOs will
- X be used. If the device is an i82510 chip the DF_DEVICE_IS_I82510 flag
- X is set and the device will be handled accordingly.
- X*/
- X
- Xint
- Xfasinit ()
- X{
- X register struct fas_info *fip;
- X register uint unit;
- X uint logical_units, port, *seq_ptr;
- X char port_stat [MAX_UNITS + 1];
- X REGVAR;
- X
- X if (fas_is_initted)
- X return (0);
- X
- X fas_is_initted = TRUE;
- X
- X /* execute the init sequence for the serial card */
- X for (seq_ptr = fas_init_seq; *seq_ptr; seq_ptr++)
- X {
- X port = *seq_ptr;
- X seq_ptr++;
- X if (*seq_ptr & READ_PORT)
- X (void) inb (port);
- X else
- X (void) outb (port, *seq_ptr);
- X }
- X
- X /* setup the list of pointers to the tty structures */
- X for (unit = 0, logical_units = fas_physical_units * 2;
- X unit < logical_units; unit++)
- X fas_tty_ptr [unit] = &fas_tty [unit];
- X
- X /* setup and initialize all serial ports */
- X for (unit = 0; unit < fas_physical_units; unit++)
- X {
- X fas_info_ptr [unit] = fip = &fas_info [unit];
- X port_stat [unit] = '-';
- X if (port = (uint) ((ushort) (fas_port [unit])))
- X {
- X /* check the int vector */
- X if (fas_vec [unit] >= NUM_INT_VECTORS)
- X {
- X port_stat [unit] = '>';
- X continue;
- X }
- X
- X /* init all of its ports */
- X if (fas_ctl_port [unit])
- X {
- X fip->ctl_port = fas_ctl_port [unit];
- X
- X if (fas_ctl_val [unit] & 0xff00)
- X fip->device_flags.s |= DF_CTL_EVERY;
- X else
- X fip->device_flags.s |= DF_CTL_FIRST;
- X }
- X
- X fip->port_0.p.addr = GET_PORT (port, 0);
- X fip->port_1.p.addr = GET_PORT (port, 1);
- X fip->port_2.p.addr = GET_PORT (port, 2);
- X fip->port_3.p.addr = GET_PORT (port, 3);
- X fip->port_4.p.addr = GET_PORT (port, 4);
- X fip->port_5.p.addr = GET_PORT (port, 5);
- X fip->port_6.p.addr = GET_PORT (port, 6);
- X fip->port_0.p.ctl = fas_make_ctl_val (fip, unit, 0);
- X fip->port_1.p.ctl = fas_make_ctl_val (fip, unit, 1);
- X fip->port_2.p.ctl = fas_make_ctl_val (fip, unit, 2);
- X fip->port_3.p.ctl = fas_make_ctl_val (fip, unit, 3);
- X fip->port_4.p.ctl = fas_make_ctl_val (fip, unit, 4);
- X fip->port_5.p.ctl = fas_make_ctl_val (fip, unit, 5);
- X fip->port_6.p.ctl = fas_make_ctl_val (fip, unit, 6);
- X fip->vec = fas_vec [unit];
- X fip->modem.l = fas_modem [unit];
- X fip->flow.l = fas_flow [unit];
- X
- X /* mask off invalid bits */
- X fip->modem.m.di &= MC_ANY_CONTROL;
- X fip->modem.m.eo &= MC_ANY_CONTROL;
- X fip->modem.m.ei &= MC_ANY_CONTROL;
- X fip->modem.m.ca &= MS_ANY_PRESENT;
- X fip->flow.m.ic &= MC_ANY_CONTROL;
- X fip->flow.m.oc &= MS_ANY_PRESENT;
- X fip->flow.m.oe &= MS_ANY_PRESENT;
- X fip->flow.m.hc &= MC_ANY_CONTROL;
- X
- X fip->recv_ring_put_ptr = fip->recv_buffer;
- X fip->recv_ring_take_ptr = fip->recv_buffer;
- X fip->xmit_ring_put_ptr = fip->xmit_buffer;
- X fip->xmit_ring_take_ptr = fip->xmit_buffer;
- X fip->xmit_fifo_size = 1;
- X
- X fip->ier = IE_NONE; /* disable all ints */
- X fas_first_outb (fip, INT_ENABLE_PORT, fip->ier);
- X
- X /* is there a serial chip ? */
- X if (fas_inb (fip, INT_ENABLE_PORT) != fip->ier)
- X {
- X port_stat [unit] = '?';
- X continue; /* a hardware error */
- X }
- X
- X /* test the chip thoroughly */
- X if ((port_stat [unit] = (fas_test_device (fip) + '0'))
- X != '0')
- X {
- X continue; /* a hardware error */
- X }
- X
- X fip->lcr = 0;
- X fas_outb (fip, LINE_CTL_PORT, fip->lcr);
- X fip->mcr = fas_mcb [unit] | fip->modem.m.di;
- X fas_outb (fip, MDM_CTL_PORT, fip->mcr);
- X
- X port_stat [unit] = '*';
- X
- X /* let's see if it's an NS16550A */
- X fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_INIT_CMD);
- X if (!(~fas_inb (fip, INT_ID_PORT) & II_NS_FIFO_ENABLED))
- X {
- X fip->device_flags.s |= DF_DEVICE_IS_NS16550A;
- X fip->xmit_fifo_size = OUTPUT_NS_FIFO_SIZE;
- X port_stat [unit] = 'F';
- X fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
- X }
- X else
- X {
- X fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
- X /* or is it an i82510 ? */
- X fas_outb (fip, I_BANK_PORT, I_BANK_2);
- X if (!(~fas_inb (fip, I_BANK_PORT) & I_BANK_2))
- X {
- X fip->device_flags.s |= DF_DEVICE_IS_I82510;
- X fip->xmit_fifo_size = OUTPUT_I_FIFO_SIZE;
- X port_stat [unit] = 'f';
- X fas_outb (fip, I_BANK_PORT, I_BANK_1);
- X fas_outb (fip, I_TCM_PORT, I_FIFO_CLR_XMIT);
- X fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
- X }
- X fas_outb (fip, I_BANK_PORT, I_BANK_0);
- X }
- X
- X /* disable FIFOs if requested in space.c */
- X if ((fas_port [unit] & NO_FIFO) && (fip->device_flags.i
- X & (DF_DEVICE_IS_NS16550A
- X | DF_DEVICE_IS_I82510)))
- X {
- X fip->device_flags.s &= ~(DF_DEVICE_IS_NS16550A
- X | DF_DEVICE_IS_I82510);
- X fip->xmit_fifo_size = 1;
- X port_stat [unit] = '+';
- X }
- X
- X /* clear potential interrupts */
- X (void) fas_inb (fip, MDM_STATUS_PORT);
- X (void) fas_inb (fip, RCV_DATA_PORT);
- X (void) fas_inb (fip, RCV_DATA_PORT);
- X (void) fas_inb (fip, LINE_STATUS_PORT);
- X (void) fas_inb (fip, INT_ID_PORT);
- X if (port = fas_int_ack_port [fip->vec])
- X (void) outb (port, fas_int_ack [fip->vec]);
- X
- X /* show that it is present and configured */
- X fip->device_flags.s |= DF_DEVICE_CONFIGURED;
- X }
- X }
- X
- X#if defined (NEED_PUT_GETCHAR)
- X fip = &fas_info [0];
- X fip->mcr &= ~fip->modem.m.di;
- X fip->mcr |= INITIAL_MDM_CONTROL;
- X fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
- X
- X fip->lcr = INITIAL_LINE_CONTROL;
- X fas_outb (fip, LINE_CTL_PORT, fip->lcr | LC_ENABLE_DIVISOR);
- X fas_outb (fip, DIVISOR_LSB_PORT, INITIAL_BAUD_RATE);
- X fas_outb (fip, DIVISOR_MSB_PORT, (INITIAL_BAUD_RATE) >> 8);
- X fas_outb (fip, LINE_CTL_PORT, fip->lcr);
- X#endif
- X
- X#if defined (SCO) || defined (XENIX)
- X for (unit = 0; unit < fas_physical_units; unit++)
- X (void) printcfg ("fas", (uint) ((ushort) (fas_port [unit])), 7,
- X fas_vec [unit], -1,
- X#if defined (FASI)
- X "unit=%d type=%c FAS/i 2.08.01",
- X#else
- X "unit=%d type=%c release=2.08.0",
- X#endif /* FASI */
- X unit, port_stat [unit]);
- X#else
- X port_stat [unit] = '\0';
- X (void) printf ("\nFAS 2.08.0 async driver: Unit 0-%d init state is [%s]\n\n",
- X unit - 1,
- X port_stat);
- X#endif
- X return (0);
- X}
- X
- X/* Open a tty line. This function is called for every open, as opposed
- X to the fasclose function which is called only with the last close.
- X*/
- Xint
- Xfasopen (dev, flag)
- Xint dev;
- Xint flag;
- X{
- X register struct fas_info *fip;
- X register struct tty *ttyp;
- X register uint open_mode;
- X uint physical_unit;
- X int old_level;
- X
- X physical_unit = GET_UNIT (dev);
- X
- X /* check for valid port number */
- X if (physical_unit >= fas_physical_units)
- X {
- X u.u_error = ENXIO;
- X return (-1);
- X }
- X
- X fip = fas_info_ptr [physical_unit];
- X
- X /* was the port present at init time ? */
- X if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
- X {
- X u.u_error = ENXIO;
- X return (-1);
- X }
- X
- X open_mode = GET_OPEN_MODE (dev);
- X
- X old_level = SPLINT ();
- X get_device_lock (fip, TTIPRI);
- X
- X /* If this is a getty open, the device is already open for
- X dialout and the FNDELAY flag is not set, wait until device
- X is closed.
- X */
- X while ((open_mode & OS_OPEN_FOR_GETTY)
- X && (fip->o_state & OS_OPEN_FOR_DIALOUT)
- X && !(flag & FNDELAY))
- X {
- X release_device_lock (fip);
- X (void) sleep ((caddr_t) &fip->o_state, TTIPRI);
- X get_device_lock (fip, TTIPRI);
- X }
- X
- X /* If the device is already open and another open uses a different
- X open mode or if a getty open waits for carrier and doesn't allow
- X parallel dialout opens, return with EBUSY error.
- X */
- X if ((fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
- X ? (OS_OPEN_STATES | OS_WAIT_OPEN)
- X : (OS_OPEN_STATES | OS_NO_DIALOUT)))
- X && ((flag & FEXCL)
- X || ((open_mode ^ fip->o_state) & (u.u_uid
- X ? OS_TEST_MASK
- X : OS_SU_TEST_MASK))))
- X {
- X u.u_error = EBUSY;
- X release_device_lock (fip);
- X (void) splx (old_level);
- X return (-1);
- X }
- X
- X /* disable subsequent opens */
- X if (flag & FEXCL)
- X open_mode |= OS_EXCLUSIVE_OPEN_1;
- X
- X /* set up pointer to tty structure */
- X ttyp = (open_mode & OS_OPEN_FOR_GETTY)
- X ? fas_tty_ptr [physical_unit + fas_physical_units]
- X : fas_tty_ptr [physical_unit];
- X
- X /* things to do on first open only */
- X if (!(fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
- X ? (OS_OPEN_STATES | OS_WAIT_OPEN)
- X : OS_OPEN_STATES)))
- X {
- X /* init data structures */
- X fip->tty = ttyp;
- X (void) ttinit (ttyp);
- X ttyp->t_proc = fas_proc;
- X fip->po_state = fip->o_state;
- X fip->o_state = open_mode & ~OS_OPEN_STATES;
- X#if defined (HAVE_VPIX)
- X /* initialize VP/ix related variables */
- X fip->v86_proc = (v86_t *) NULL;
- X fip->v86_intmask = 0;
- X fip->v86_ss.ss_start = CSTART;
- X fip->v86_ss.ss_stop = CSTOP;
- X#endif
- X fas_open_device (fip); /* open physical device */
- X fas_param (fip, HARD_INIT); /* set up port registers */
- X
- X /* allow pending tty interrupts */
- X (void) SPLWRK ();
- X (void) SPLINT ();
- X }
- X
- X /* If getty open and the FNDELAY flag is not set,
- X block and wait for carrier if device not yet open.
- X */
- X if ((open_mode & OS_OPEN_FOR_GETTY) && !(flag & FNDELAY))
- X {
- X /* sleep while open for dialout or no carrier */
- X while ((fip->o_state & OS_OPEN_FOR_DIALOUT)
- X || !(ttyp->t_state & (ISOPEN | CARR_ON)))
- X {
- X ttyp->t_state |= WOPEN;
- X release_device_lock (fip);
- X (void) sleep ((caddr_t) &ttyp->t_canq, TTIPRI);
- X get_device_lock (fip, TTIPRI);
- X }
- X ttyp->t_state &= ~WOPEN;
- X }
- X
- X /* wakeup processes that are still sleeping in getty open */
- X if (ttyp->t_state & WOPEN)
- X#if defined(FASI)
- X {
- X#endif
- X (void) wakeup ((caddr_t) &ttyp->t_canq);
- X#if defined(FASI)
- X (void) wakeup ((caddr_t) &fip->device_flags.i);
- X }
- X#endif
- X
- X /* we need to flush the receiver with the first open */
- X if (!(fip->o_state & OS_OPEN_STATES))
- X fas_cmd (fip, ttyp, T_RFLUSH);
- X
- X (*linesw [ttyp->t_line].l_open) (ttyp);
- X
- X /* set open type flags */
- X fip->o_state = open_mode;
- X
- X release_device_lock (fip);
- X (void) splx (old_level);
- X return (0);
- X}
- X
- X/* Close a tty line. This is only called if there is no other
- X concurrent open left. A blocked getty open is not counted as
- X a concurrent open because in this state it isn't really open.
- X*/
- Xint
- Xfasclose (dev)
- Xint dev;
- X{
- X register struct fas_info *fip;
- X register struct tty *ttyp;
- X uint physical_unit;
- X uint open_mode;
- X int old_level;
- X void (*old_sigkill)();
- X
- X physical_unit = GET_UNIT (dev);
- X
- X fip = fas_info_ptr [physical_unit];
- X
- X open_mode = GET_OPEN_MODE (dev);
- X
- X /* set up pointer to tty structure */
- X ttyp = (open_mode & OS_OPEN_FOR_GETTY)
- X ? fas_tty_ptr [physical_unit + fas_physical_units]
- X : fas_tty_ptr [physical_unit];
- X
- X old_level = SPLINT ();
- X get_device_lock (fip, TTIPRI);
- X
- X /* wait for output buffer drain only if device was open */
- X if (ttyp->t_state & ISOPEN)
- X {
- X /* flush the output buffer immediately if the device
- X has been shut down because of an error
- X */
- X if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
- X {
- X (void) ttyflush (ttyp, FWRITE);
- X }
- X /* wait for buffer drain and catch interrupts */
- X while (ttyp->t_outq.c_cc || (ttyp->t_state & (BUSY | TIMEOUT)))
- X {
- X old_sigkill = u.u_signal [SIGKILL - 1];
- X /* allow kill signal if close on exit */
- X if (old_sigkill == SIG_IGN)
- X u.u_signal [SIGKILL - 1] = SIG_DFL;
- X ttyp->t_state |= TTIOW;
- X if (sleep ((caddr_t) &ttyp->t_oflag, TTOPRI | PCATCH))
- X {
- X /* caught signal */
- X ttyp->t_state &= ~TTIOW;
- X /* If close on exit, flush output buffer to
- X allow completion of the fasclose() function.
- X Otherwise, do the normal signal handling.
- X */
- X if (old_sigkill == SIG_IGN)
- X (void) ttyflush (ttyp, FWRITE);
- X else
- X {
- X release_device_lock (fip);
- X (void) splx (old_level);
- X longjmp (u.u_qsav);
- X }
- X }
- X if (old_sigkill == SIG_IGN)
- X u.u_signal [SIGKILL - 1] = old_sigkill;
- X }
- X }
- X
- X (*linesw [ttyp->t_line].l_close) (ttyp);
- X
- X /* allow pending tty interrupts */
- X (void) SPLWRK ();
- X (void) SPLINT ();
- X
- X if (open_mode & OS_OPEN_FOR_GETTY)
- X {
- X /* not waiting any more */
- X ttyp->t_state &= ~WOPEN;
- X if (!(fip->o_state & OS_OPEN_FOR_DIALOUT))
- X {
- X fas_close_device (fip);
- X fip->o_state = OS_DEVICE_CLOSED;
- X }
- X else
- X fip->po_state = OS_DEVICE_CLOSED;
- X }
- X else
- X {
- X fas_close_device (fip);
- X fip->o_state = OS_DEVICE_CLOSED;
- X /* If there is a waiting getty open on
- X this port, reopen the physical device.
- X */
- X if (fip->po_state & OS_WAIT_OPEN)
- X {
- X /* get the getty version of the
- X tty structure
- X */
- X fip->tty = fas_tty_ptr [physical_unit
- X + fas_physical_units];
- X fip->o_state = fip->po_state;
- X fip->po_state = OS_DEVICE_CLOSED;
- X#if defined (HAVE_VPIX)
- X /* initialize VP/ix related variables */
- X fip->v86_proc = (v86_t *) NULL;
- X fip->v86_intmask = 0;
- X fip->v86_ss.ss_start = CSTART;
- X fip->v86_ss.ss_stop = CSTOP;
- X#endif
- X if (!(fip->device_flags.i & DF_DO_HANGUP))
- X {
- X fas_open_device (fip);
- X /* set up port registers */
- X fas_param (fip, HARD_INIT);
- X }
- X }
- X (void) wakeup ((caddr_t) &fip->o_state);
- X }
- X
- X if (!(fip->device_flags.i & DF_DO_HANGUP))
- X release_device_lock (fip);
- X
- X#if defined(FASI)
- X (void)wakeup((caddr_t)&fip->device_flags.i);
- X#endif
- X (void) splx (old_level);
- X return (0);
- X}
- X
- X/* read characters from the input buffer */
- Xint
- Xfasread (dev)
- Xint dev;
- X{
- X register struct fas_info *fip;
- X register struct tty *ttyp;
- X int old_level;
- X
- X fip = fas_info_ptr [GET_UNIT (dev)];
- X
- X /* was the port present at init time ? */
- X if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
- X {
- X u.u_error = ENXIO;
- X return (-1);
- X }
- X
- X ttyp = fip->tty;
- X
- X (*linesw [ttyp->t_line].l_read) (ttyp);
- X
- X old_level = SPLINT ();
- X
- X /* schedule character transfer to UNIX buffer */
- X if (fip->recv_ring_cnt
- X#if defined (HAVE_VPIX)
- X && (((fip->iflag & DOSMODE)
- X ? MAX_VPIX_FILL - MIN_READ_CHUNK
- X : MAX_UNIX_FILL - MIN_READ_CHUNK)
- X >= ttyp->t_rawq.c_cc)
- X#else
- X && ((MAX_UNIX_FILL - MIN_READ_CHUNK) >= ttyp->t_rawq.c_cc)
- X#endif
- X && !(fip->flow_flags.i & FF_RXFER_STOPPED))
- X {
- X event_sched (fip, EF_DO_RXFER);
- X }
- X
- X#if defined(FASI)
- X (void)wakeup((caddr_t)&fip->device_flags.i);
- X#endif
- X (void) splx (old_level);
- X return (0);
- X}
- X
- X/* write characters to the output buffer */
- Xint
- Xfaswrite (dev)
- Xint dev;
- X{
- X register struct fas_info *fip;
- X register struct tty *ttyp;
- X
- X fip = fas_info_ptr [GET_UNIT (dev)];
- X
- X /* was the port present at init time ? */
- X if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
- X {
- X u.u_error = ENXIO;
- X return (-1);
- X }
- X
- X ttyp = fip->tty;
- X
- X (*linesw [ttyp->t_line].l_write) (ttyp);
- X return (0);
- X}
- X
- X/*+-------------------------------------------------------------------------
- X strlen(str)
- X--------------------------------------------------------------------------*/
- X#if defined(FASI)
- Xstatic int
- Xstrlen(str)
- Xregister char *str;
- X{
- Xregister len = 0;
- X while(*str++)
- X len++;
- X return(len);
- X} /* end of strlen */
- X#endif /* FASI */
- X
- X/* process ioctl calls */
- Xint
- Xfasioctl (dev, cmd, arg3, arg4)
- Xint dev;
- Xint cmd;
- Xunion ioctl_arg arg3;
- Xint arg4;
- X{
- X register struct fas_info *fip;
- X register struct tty *ttyp;
- X int v86_cmd, v86_data;
- X int old_level;
- X REGVAR;
- X
- X fip = fas_info_ptr [GET_UNIT (dev)];
- X
- X /* was the port present at init time ? */
- X if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
- X {
- X u.u_error = ENXIO;
- X return (-1);
- X }
- X
- X ttyp = fip->tty;
- X
- X /* process ioctl commands */
- X switch (cmd)
- X {
- X#if defined (FASI)
- X case FASIC_SIP_CHANGE:
- X (void) sleep ((caddr_t) &fip->device_flags.i, PZERO + 1);
- X case FASIC_SIP:
- X if(copyout((char *)fip,arg3.cparg,sizeof(*fip)))
- X {
- X u.u_error = EFAULT;
- X return(-1);
- X }
- X return(fasiintr_entries);
- X case FASIC_DVR_IDENT:
- X if(copyout(fasi_driver_ident,arg3.cparg,
- X strlen(fasi_driver_ident) + 1))
- X {
- X u.u_error = EFAULT;
- X return(-1);
- X }
- X break;
- X case FASIC_SPACE_IDENT:
- X if(copyout(fasi_space_ident,arg3.cparg,
- X strlen(fasi_space_ident) + 1))
- X {
- X u.u_error = EFAULT;
- X return(-1);
- X }
- X break;
- X case FASIC_MSR:
- X return((unsigned int)fip->msr);
- X case FASIC_LCR:
- X return((unsigned int)fip->lcr);
- X case FASIC_IER:
- X return((unsigned int)fip->ier);
- X case FASIC_MCR:
- X return((unsigned int)fip->mcr);
- X case FASIC_RESET_STAT:
- X old_level = SPLINT();
- X fip->characters_received = 0;
- X fip->characters_transmitted = 0;
- X fip->modem_status_events = 0;
- X fip->overrun_errors = 0;
- X fip->framing_errors = 0;
- X fip->parity_errors = 0;
- X fip->rings_detected = 0;
- X fip->breaks_detected = 0;
- X fip->xmtr_hw_flow_count = 0;
- X fip->xmtr_sw_flow_count = 0;
- X fip->rcvr_hw_flow_count = 0;
- X fip->rcvr_sw_flow_count = 0;
- X (void)splx(old_level);
- X break;
- X#endif /* FASI */
- X#if defined (HAVE_VPIX)
- X case AIOCINTTYPE: /* set pseudorupt type */
- X switch (arg3.iarg)
- X {
- X case V86VI_KBD:
- X case V86VI_SERIAL0:
- X case V86VI_SERIAL1:
- X intr_disable ();
- X fip->v86_intmask = arg3.iarg;
- X intr_restore ();
- X break;
- X
- X default:
- X intr_disable ();
- X fip->v86_intmask = V86VI_SERIAL0;
- X intr_restore ();
- X break;
- X }
- X break;
- X
- X case AIOCDOSMODE: /* enable dos mode */
- X if (!(fip->iflag & DOSMODE))
- X {
- X old_level = SPLINT ();
- X fip->v86_proc = u.u_procp->p_v86;
- X if (!(fip->v86_intmask))
- X fip->v86_intmask = V86VI_SERIAL0;
- X ttyp->t_iflag |= DOSMODE;
- X if (fip->v86_intmask != V86VI_KBD)
- X ttyp->t_cflag |= CLOCAL;
- X fas_param (fip, SOFT_INIT);
- X (void) splx (old_level);
- X }
- X u.u_r.r_reg.r_val1 = 0;
- X break;
- X
- X case AIOCNONDOSMODE: /* disable dos mode */
- X if (fip->iflag & DOSMODE)
- X {
- X old_level = SPLINT ();
- X fip->v86_proc = (v86_t *) NULL;
- X fip->v86_intmask = 0;
- X ttyp->t_iflag &= ~DOSMODE;
- X if (fip->flow_flags.i & FF_RXFER_STOPPED)
- X {
- X fip->flow_flags.s &= ~FF_RXFER_STOPPED;
- X /* schedule character transfer
- X to UNIX buffer
- X */
- X if (fip->recv_ring_cnt)
- X event_sched (fip, EF_DO_RXFER);
- X }
- X fip->lcr &= ~LC_SET_BREAK_LEVEL;
- X fas_param (fip, HARD_INIT);
- X (void) splx (old_level);
- X }
- X u.u_r.r_reg.r_val1 = 0;
- X break;
- X
- X case AIOCSERIALOUT: /* setup port registers for dos */
- X if ((fip->iflag & DOSMODE) && fip->v86_proc)
- X {
- X /* wait until output is done */
- X old_level = SPLINT ();
- X while (ttyp->t_outq.c_cc
- X || (ttyp->t_state & (BUSY | TIMEOUT)))
- X {
- X ttyp->t_state |= TTIOW;
- X (void) sleep ((caddr_t) &ttyp->t_oflag,
- X TTOPRI);
- X }
- X
- X /* block transmitter and wait until it is
- X empty
- X */
- X fip->device_flags.s |= DF_XMIT_LOCKED;
- X while (fip->device_flags.i & (DF_XMIT_BUSY
- X | DF_XMIT_BREAK
- X | DF_GUARD_TIMEOUT))
- X (void) sleep ((caddr_t) &fip->
- X device_flags.i,
- X PZERO - 1);
- X (void) splx (old_level);
- X
- X /* get port write command */
- X v86_cmd = fubyte (arg3.cparg);
- X /* set divisor lsb requested */
- X if (v86_cmd & SIO_MASK(SO_DIVLLSB))
- X {
- X v86_data = fubyte (arg3.cparg
- X + SO_DIVLLSB);
- X intr_disable ();
- X fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
- X | LC_ENABLE_DIVISOR);
- X fas_outb (fip, DIVISOR_LSB_PORT, v86_data);
- X fas_outb (fip, LINE_CTL_PORT, fip->lcr
- X & ~LC_ENABLE_DIVISOR);
- X intr_restore ();
- X }
- X /* set divisor msb requested */
- X if (v86_cmd & SIO_MASK(SO_DIVLMSB))
- X {
- X v86_data = fubyte (arg3.cparg
- X + SO_DIVLMSB);
- X intr_disable ();
- X fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
- X | LC_ENABLE_DIVISOR);
- X fas_outb (fip, DIVISOR_MSB_PORT, v86_data);
- X fas_outb (fip, LINE_CTL_PORT, fip->lcr
- X & ~LC_ENABLE_DIVISOR);
- X intr_restore ();
- X }
- X /* set lcr requested */
- X if (v86_cmd & SIO_MASK(SO_LCR))
- X {
- X v86_data = fubyte (arg3.cparg + SO_LCR);
- X intr_disable ();
- X fip->lcr = v86_data
- X & ~LC_ENABLE_DIVISOR;
- X fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
- X intr_restore ();
- X }
- X /* set mcr requested */
- X if (v86_cmd & SIO_MASK(SO_MCR))
- X {
- X v86_data = fubyte (arg3.cparg + SO_MCR);
- X old_level = SPLINT ();
- X /* virtual dtr processing */
- X if (v86_data & MC_SET_DTR)
- X {
- X fip->device_flags.s
- X |= DF_MODEM_ENABLED;
- X fip->mcr |= (fip->o_state
- X & OS_WAIT_OPEN)
- X ? fip->modem.m.ei
- X : fip->modem.m.eo;
- X }
- X else
- X {
- X fip->device_flags.s
- X &= ~DF_MODEM_ENABLED;
- X fip->mcr &= (fip->o_state
- X & OS_WAIT_OPEN)
- X ? ~fip->modem.m.ei
- X : ~fip->modem.m.eo;
- X }
- X /* virtual rts processing */
- X if (fip->flow_flags.i
- X & FF_HWI_HANDSHAKE)
- X {
- X if (v86_data & MC_SET_RTS)
- X {
- X if (fip->flow_flags.i
- X & FF_RXFER_STOPPED)
- X {
- X fip->flow_flags.s
- X &= ~FF_RXFER_STOPPED;
- X /* schedule character transfer
- X to UNIX buffer
- X */
- X if (fip->recv_ring_cnt)
- X event_sched (fip,
- X EF_DO_RXFER);
- X }
- X }
- X else
- X fip->flow_flags.s
- X |= FF_RXFER_STOPPED;
- X }
- X else if (!(fip->flow_flags.i
- X & FF_HDX_HANDSHAKE))
- X {
- X if (v86_data & MC_SET_RTS)
- X {
- X fip->flow_flags.s
- X |= FF_HDX_STARTED;
- X fip->mcr
- X |= fip->flow.m.hc;
- X }
- X else
- X {
- X fip->flow_flags.s
- X &= ~FF_HDX_STARTED;
- X fip->mcr
- X &= ~fip->flow.m.hc;
- X }
- X }
- X fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
- X (void) splx (old_level);
- X }
- X
- X old_level = SPLINT ();
- X /* enable transmitter and restart output */
- X fip->device_flags.s &= ~DF_XMIT_LOCKED;
- X fas_xproc (fip);
- X (void) splx (old_level);
- X }
- X break;
- X
- X case AIOCSERIALIN: /* read port registers for dos */
- X if ((fip->iflag & DOSMODE) && fip->v86_proc)
- X {
- X v86_cmd = fubyte (arg3.cparg);
- X if (v86_cmd & SIO_MASK(SI_MSR))
- X {
- X (void) subyte (arg3.cparg + SI_MSR,
- X ((fip->flow_flags.i
- X & FF_HWO_HANDSHAKE)
- X ? fip->msr
- X | fip->flow.m.oc
- X | fip->flow.m.oe
- X : fip->msr)
- X & MS_ANY_PRESENT);
- X }
- X }
- X break;
- X
- X case AIOCSETSS: /* set start/stop characters */
- X intr_disable ();
- X *((short *) (&fip->v86_ss)) = arg3.iarg;
- X intr_restore ();
- X break;
- X
- X case AIOCINFO: /* show what type of device we are */
- X u.u_r.r_reg.r_val1 = ('a' << 8) | (uint) ((unchar) dev);
- X break;
- X#endif
- X default: /* default ioctl processing */
- X /* if it is a TCSETA* command, call fas_param () */
- X if (ttiocom (ttyp, cmd, arg3, arg4))
- X {
- X old_level = SPLINT ();
- X fas_param (fip, SOFT_INIT);
- X (void) splx (old_level);
- X }
- X break;
- X }
- X return (0);
- X}
- X
- X/* pass fas commands to the fas multi-function procedure */
- Xstatic int
- Xfas_proc (ttyp, arg2)
- Xstruct tty *ttyp;
- Xint arg2;
- X{
- X register uint physical_unit;
- X int old_level;
- X
- X physical_unit = ttyp - &fas_tty [0];
- X if (physical_unit >= fas_physical_units)
- X physical_unit -= fas_physical_units;
- X
- X old_level = SPLINT ();
- X fas_cmd (fas_info_ptr [physical_unit], ttyp, arg2);
- X (void) splx (old_level);
- X return (0);
- X}
- X
- X/* set up a port according to the given termio structure */
- Xstatic void
- Xfas_param (fip, init_type)
- Xregister struct fas_info *fip;
- Xint init_type;
- X{
- X register uint cflag;
- X uint divisor;
- X int xmit_ring_size;
- X REGVAR;
- X
- X cflag = fip->tty->t_cflag;
- X
- X#if defined (HAVE_VPIX)
- X /* we don't set port registers if we are in dos mode */
- X if (fip->tty->t_iflag & DOSMODE)
- X goto setflags2;
- X#endif
- X /* if soft init mode: don't set port registers if cflag didn't change */
- X if ((init_type == SOFT_INIT) && !((cflag ^ fip->cflag)
- X & (CBAUD | CSIZE | CSTOPB
- X | PARENB | PARODD)))
- X goto setflags;
- X
- X /* lock transmitter and wait until it is empty */
- X fip->device_flags.s |= DF_XMIT_LOCKED;
- X while (fip->device_flags.i & (DF_XMIT_BUSY | DF_XMIT_BREAK
- X | DF_GUARD_TIMEOUT))
- X (void) sleep ((caddr_t) &fip->device_flags.i, PZERO - 1);
- X
- X /* hangup line if it is baud rate 0, else enable line */
- X if ((cflag & CBAUD) == B0)
- X {
- X fip->mcr &= (fip->o_state & OS_WAIT_OPEN)
- X ? ~fip->modem.m.ei
- X : ~fip->modem.m.eo;
- X fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
- X fip->device_flags.s &= ~DF_MODEM_ENABLED;
- X }
- X else
- X {
- X if (!(fip->device_flags.i & DF_MODEM_ENABLED))
- X {
- X fip->mcr |= (fip->o_state & OS_WAIT_OPEN)
- X ? fip->modem.m.ei
- X : fip->modem.m.eo;
- X fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
- X fip->device_flags.s |= DF_MODEM_ENABLED;
- X }
- X }
- X
- X /* don't change break flag */
- X fip->lcr &= LC_SET_BREAK_LEVEL;
- X
- X /* set character size */
- X switch (cflag & CSIZE)
- X {
- X case CS5:
- X fip->lcr |= LC_WORDLEN_5;
- X break;
- X
- X case CS6:
- X fip->lcr |= LC_WORDLEN_6;
- X break;
- X
- X case CS7:
- X fip->lcr |= LC_WORDLEN_7;
- X break;
- X
- X default:
- X fip->lcr |= LC_WORDLEN_8;
- X break;
- X }
- X
- X /* set # of stop bits */
- X if (cflag & CSTOPB)
- X fip->lcr |= LC_STOPBITS_LONG;
- X
- X /* set parity */
- X if (cflag & PARENB)
- X {
- X fip->lcr |= LC_ENABLE_PARITY;
- X
- X if (!(cflag & PARODD))
- X fip->lcr |= LC_EVEN_PARITY;
- X }
- X
- X /* set divisor registers only if baud rate is valid */
- X if ((cflag & CBAUD) != B0)
- X {
- X /* get counter divisor for selected baud rate */
- X divisor = fas_speeds [cflag & CBAUD];
- X /* set LCR and baud rate */
- X fas_first_outb (fip, LINE_CTL_PORT, fip->lcr
- X | LC_ENABLE_DIVISOR);
- X fas_outb (fip, DIVISOR_LSB_PORT, divisor);
- X fas_outb (fip, DIVISOR_MSB_PORT, divisor >> 8);
- X }
- X
- X fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
- X
- Xsetflags:
- X /* check dynamic xmit ring buffer size against boundaries,
- X modify it if necessary and update the fas_info structure
- X */
- X if ((cflag & CBAUD) != B0)
- X {
- X xmit_ring_size = fas_xbuf_size [cflag & CBAUD]
- X - tthiwat [cflag & CBAUD];
- X if (xmit_ring_size < MAX_OUTPUT_FIFO_SIZE * 2)
- X {
- Xsetflags2:
- X xmit_ring_size = MAX_OUTPUT_FIFO_SIZE * 2;
- X }
- X if (xmit_ring_size > XMIT_BUFF_SIZE)
- X xmit_ring_size = XMIT_BUFF_SIZE;
- X fip->xmit_ring_size = xmit_ring_size;
- X }
- X
- X /* setup character time for B0 mode */
- X fas_ctimes [B0] = fas_ctimes [cflag & CBAUD];
- X
- X /* disable modem control signals if required by open mode */
- X if (fip->o_state & OS_CLOCAL)
- X cflag |= CLOCAL;
- X
- X /* Select hardware handshake depending on the minor device
- X number and the CTSFLOW and RTSFLOW flags (if they are
- X available).
- X */
- X fip->flow_flags.s &= ~(FF_HWO_HANDSHAKE
- X | FF_HWI_HANDSHAKE
- X | FF_HDX_HANDSHAKE);
- X if (fip->o_state & (OS_HWO_HANDSHAKE | OS_HWI_HANDSHAKE
- X | OS_HDX_HANDSHAKE))
- X {
- X if (fip->o_state & OS_HWO_HANDSHAKE)
- X fip->flow_flags.s |= FF_HWO_HANDSHAKE;
- X if (fip->o_state & OS_HWI_HANDSHAKE)
- X fip->flow_flags.s |= FF_HWI_HANDSHAKE;
- X if (fip->o_state & OS_HDX_HANDSHAKE)
- X fip->flow_flags.s |= FF_HDX_HANDSHAKE;
- X }
- X else
- X {
- X#if defined (CTSFLOW) /* SYSV 3.2 Xenix compatibility */
- X if ((cflag & (CTSFLOW | CLOCAL)) == CTSFLOW)
- X fip->flow_flags.s |= FF_HWO_HANDSHAKE;
- X#endif
- X#if defined (RTSFLOW) /* SYSV 3.2 Xenix compatibility */
- X if ((cflag & (RTSFLOW | CLOCAL)) == RTSFLOW)
- X fip->flow_flags.s |= FF_HDX_HANDSHAKE;
- X#endif
- X }
- X
- X /* Fake the carrier detect state flag if CLOCAL mode or if
- X requested by open mode.
- X */
- X if (!(~fip->msr & fip->modem.m.ca)
- X || (fip->o_state & OS_FAKE_CARR_ON)
- X || (cflag & CLOCAL))
- X fip->tty->t_state |= CARR_ON;
- X else
- X fip->tty->t_state &= ~CARR_ON;
- X
- X#if defined (XCLUDE) /* SYSV 3.2 Xenix compatibility */
- X /* Permit exclusive use of this device. */
- X if (cflag & XCLUDE)
- X fip->o_state |= OS_EXCLUSIVE_OPEN_2;
- X else
- X fip->o_state &= ~OS_EXCLUSIVE_OPEN_2;
- X#endif
- X
- X fip->cflag = cflag;
- X fip->iflag = fip->tty->t_iflag;
- X
- X /* enable transmitter */
- X fip->device_flags.s &= ~DF_XMIT_LOCKED;
- X
- X /* setup handshake flags */
- X fas_hdx_check (fip);
- X fas_ihlw_check (fip);
- X fas_fproc (fip, fip->new_msr);
- X
- X /* restart output */
- X fas_xproc (fip);
- X}
- X
- X/* Main fas interrupt handler. Actual character processing is splitted
- X into sub-functions.
- X*/
- Xint
- Xfasintr (vect)
- Xint vect;
- X{
- X register struct fas_info *fip;
- X register uint status;
- X struct fas_info *old_fip;
- X int done, drop_mode;
- X uint port, old_recv_count;
- X REGVAR;
- X
- X#if defined(FASI)
- X fasiintr_entries++;
- X#endif /* FASI */
- X
- X drop_mode = FALSE;
- X
- X /* The 8259 interrupt controller is set up for edge trigger.
- X Therefor, we must loop until we make a complete pass without
- X getting any UARTs that are interrupting.
- X */
- X do
- X {
- X done = TRUE;
- X fip = fas_first_int_user [vect];
- X
- X /* loop through all users of this interrupt vector */
- X for (;; fip = fip->next_int_user)
- X {
- X if (!fip)
- X break; /* all users done */
- X
- X /* process only ports that we expect ints from
- X and that actually need to be serviced
- X */
- Xfastloop:
- X if (fas_first_inb (fip, INT_ID_PORT)
- X & II_NO_INTS_PENDING)
- X {
- X /* restore the normal receiver trigger level */
- X if (fip->device_flags.i & DF_NS16550A_DROP_MODE)
- X {
- X fip->device_flags.s &=
- X ~DF_NS16550A_DROP_MODE;
- X fas_outb (fip, NS_FIFO_CTL_PORT,
- X NS_FIFO_SETUP_CMD);
- X }
- X /* speed beats beauty */
- X fip = fip->next_int_user;
- X if (fip)
- X goto fastloop;
- X break;
- X }
- X
- X /* restore the normal receiver trigger level */
- X if (fip->device_flags.i & DF_NS16550A_DROP_MODE)
- X {
- X fip->device_flags.s &= ~DF_NS16550A_DROP_MODE;
- X fas_outb (fip, NS_FIFO_CTL_PORT,
- X NS_FIFO_SETUP_CMD);
- X }
- X
- X done = FALSE; /* not done if we got an int */
- X old_recv_count = fip->recv_ring_cnt;
- X
- X do
- X {
- X /* read in all the characters from the FIFO */
- X if ((status = fas_inb (fip, LINE_STATUS_PORT))
- X & LS_RCV_INT)
- X {
- X if (!drop_mode && (fip->device_flags.i
- X & DF_DEVICE_IS_NS16550A))
- X {
- X /* Drop receiver trigger levels to make
- X sure that we will see all received
- X characters in all NS16550A. This
- X prevents multiple interrupts if we
- X receive characters on more than one
- X unit.
- X */
- X old_fip = fip;
- X for (fip = fas_first_int_user [vect];
- X fip; fip = fip->next_int_user)
- X {
- X if ((fip->device_flags.i
- X & DF_DEVICE_IS_NS16550A)
- X && (fip != old_fip))
- X {
- X fip->device_flags.s |=
- X DF_NS16550A_DROP_MODE;
- X fas_first_outb (fip,
- X NS_FIFO_CTL_PORT,
- X NS_FIFO_DROP_CMD);
- X }
- X }
- X fip = old_fip;
- X drop_mode = TRUE;
- X }
- X status = fas_rproc (fip, status);
- X sysinfo.rcvint++;
- X }
- X
- X /* Is it a transmitter empty int ? */
- X if ((status & LS_XMIT_AVAIL)
- X && (fip->device_flags.i & DF_XMIT_BUSY))
- X {
- X fip->device_flags.s &= ~DF_XMIT_BUSY;
- X fas_xproc (fip);
- X if (!(fip->device_flags.i
- X & DF_XMIT_BUSY))
- X {
- X fip->device_flags.s |=
- X DF_GUARD_TIMEOUT;
- X fip->tty->t_state |=
- X TIMEOUT;
- X fip->timeout_idx =
- X timeout (
- X fas_timeout, fip,
- X fas_ctimes [fip->cflag
- X & CBAUD]);
- X }
- X sysinfo.xmtint++;
- X }
- X
- X /* Has there been a polarity change on
- X some of the modem lines ?
- X */
- X if ((status = fas_inb (fip, MDM_STATUS_PORT))
- X & MS_ANY_DELTA)
- X {
- X /* Do special RING line handling.
- X RING generates an int only on the
- X trailing edge.
- X */
- X status = (status & ~MS_RING_PRESENT)
- X | (fip->new_msr
- X & MS_RING_PRESENT);
- X if (status & MS_RING_TEDGE)
- X#if defined(FASI)
- X fip->rings_detected++,
- X#endif /* FASI */
- X status |= MS_RING_PRESENT;
- X if ((status ^ fip->new_msr)
- X & MS_ANY_PRESENT)
- X {
- X /* check for excessive modem
- X status interrupts
- X */
- X if (++fip->msi_cnt >
- X (MAX_MSI_CNT / HZ)
- X * (EVENT_TIME * HZ
- X / 1000))
- X {
- X fip->ier = IE_NONE;
- X fas_outb (fip,
- X INT_ENABLE_PORT,
- X fip->ier);
- X }
- X /* check hw flow flags */
- X fas_fproc (fip, status);
- X fip->new_msr = status;
- X event_sched (fip, EF_DO_MPROC);
- X }
- X sysinfo.mdmint++;
- X#if defined(FASI)
- X fip->modem_status_events++;
- X#endif /* FASI */
- X }
- X } while (!(fas_inb (fip, INT_ID_PORT)
- X & II_NO_INTS_PENDING));
- X
- X /* schedule character transfer to UNIX buffer */
- X if (fip->recv_ring_cnt
- X#if defined (HAVE_VPIX)
- X && (((fip->iflag & DOSMODE)
- X ? MAX_VPIX_FILL - MIN_READ_CHUNK
- X : MAX_UNIX_FILL - MIN_READ_CHUNK)
- X >= fip->tty->t_rawq.c_cc)
- X#else
- X && ((MAX_UNIX_FILL - MIN_READ_CHUNK)
- X >= fip->tty->t_rawq.c_cc)
- X#endif
- X && !(fip->flow_flags.i & FF_RXFER_STOPPED))
- X {
- X event_sched (fip, EF_DO_RXFER);
- X }
- X
- X /* check input buffer high/low water marks */
- X if (fip->recv_ring_cnt != old_recv_count)
- X fas_ihlw_check (fip);
- X }
- X } while (!done);
- X
- X /* clear the shared interrupt since we have scanned all
- X of the ports that share this interrupt vector
- X */
- X if (port = fas_int_ack_port [vect])
- X (void) outb (port, fas_int_ack [vect]);
- X
- X return (0);
- X}
- X
- X/* hardware flow control interrupt handler */
- Xstatic void
- Xfas_fproc (fip, mdm_status)
- Xregister struct fas_info *fip;
- Xregister uint mdm_status;
- X{
- X /* Check the output flow control signals and set the state flag
- X accordingly.
- X */
- X if (!(~mdm_status & fip->flow.m.oc)
- X || (~mdm_status & fip->flow.m.oe)
- X || !(fip->flow_flags.i & FF_HWO_HANDSHAKE))
- X {
- X if (fip->flow_flags.i & FF_HWO_STOPPED)
- X {
- X fip->flow_flags.s &= ~FF_HWO_STOPPED;
- X fas_xproc (fip);
- X }
- X }
- X else
- X#if defined(FASI)
- X fip->xmtr_hw_flow_count++,
- X wakeup((caddr_t)&fip->device_flags.i),
- X#endif /* FASI */
- X fip->flow_flags.s |= FF_HWO_STOPPED;
- X}
- X
- X/* modem status handler */
- Xstatic void
- Xfas_mproc (fip)
- Xregister struct fas_info *fip;
- X{
- X register struct tty *ttyp;
- X register uint mdm_status;
- X uint vpix_status;
- X int old_level;
- X
- X ttyp = fip->tty;
- X mdm_status = fip->new_msr;
- X fip->new_msr &= ~MS_RING_PRESENT;
- X
- X /* Check the carrier detect signal and set the state flags
- X accordingly. Also, if not in clocal mode, send SIGHUP on
- X carrier loss and flush the buffers.
- X */
- X if (!(fip->cflag & CLOCAL))
- X {
- X if (!(~mdm_status & fip->modem.m.ca))
- X {
- X ttyp->t_state |= CARR_ON;
- X /* Unblock getty open only if it is ready to run. */
- X if ((ttyp->t_state & WOPEN)
- X && (~fip->msr & fip->modem.m.ca))
- X#if defined(FASI)
- X {
- X#endif
- X (void) wakeup ((caddr_t) &ttyp->t_canq);
- X#if defined(FASI)
- X (void)wakeup((caddr_t)&fip->device_flags.i);
- X }
- X#endif
- X }
- X else
- X {
- X if (!(~fip->msr & fip->modem.m.ca))
- X {
- X ttyp->t_state &= ~CARR_ON;
- X old_level = SPLWRK ();
- X if (ttyp->t_state & ISOPEN)
- X (void) signal (ttyp->t_pgrp, SIGHUP);
- X (void) ttyflush (ttyp, FREAD | FWRITE);
- X (void) splx (old_level);
- X }
- X }
- X }
- X
- X#if defined (HAVE_VPIX)
- X if (((fip->iflag & (DOSMODE | PARMRK))
- X == (DOSMODE | PARMRK))
- X && (fip->v86_intmask != V86VI_KBD))
- X {
- X /* prepare status bits for VP/ix */
- X vpix_status = (((mdm_status ^ fip->msr) >> 4) & MS_ANY_DELTA)
- X | (mdm_status & (MS_CTS_PRESENT
- X | MS_DSR_PRESENT
- X | MS_DCD_PRESENT));
- X if (fip->flow_flags.i & FF_HWO_HANDSHAKE)
- X {
- X vpix_status &= ~((fip->flow.m.oc | fip->flow.m.oe)
- X >> 4);
- X vpix_status |= fip->flow.m.oc | fip->flow.m.oe;
- X }
- X /* send status bits to VP/ix */
- X if ((vpix_status & MS_ANY_DELTA)
- X && fas_vpix_sr (fip, 2, vpix_status))
- X event_sched (fip, EF_DO_RXFER);
- X }
- X#endif
- X fip->msr = mdm_status & ~MS_RING_PRESENT;
- X
- X /* re-schedule if modem status flags have changed in the mean time */
- X if ((fip->new_msr ^ fip->msr) & MS_ANY_PRESENT)
- X {
- X event_sched (fip, EF_DO_MPROC)
- X }
- X#if defined(FASI)
- X else
- X (void)wakeup((caddr_t)&fip->device_flags.i);
- X#endif /* FASI */
- X}
- X
- X/* Receiver interrupt handler. Translates input characters to character
- X sequences as described in TERMIO(7) man page.
- X*/
- Xstatic uint
- Xfas_rproc (fip, line_status)
- Xregister struct fas_info *fip;
- Xuint line_status;
- X{
- X struct tty *ttyp;
- X uint charac;
- X register uint csize;
- X unchar metta [4];
- X REGVAR;
- X
- X ttyp = fip->tty;
- X
- X fas_first_ctl (fip, RCV_DATA_PORT);
- X
- X /* Translate characters from FIFO according to the TERMIO(7)
- X man page.
- X */
- X do
- X {
- X charac = (line_status & LS_RCV_AVAIL)
- X#if defined(FASI)
- X ? (fip->characters_received++,fas_inb (fip, RCV_DATA_PORT))
- X#else
- X ? fas_inb (fip, RCV_DATA_PORT)
- X#endif /* FASI */
- X : 0; /* was line status int only */
- X
- X /* do we have to junk the character ? */
- X if (!(fip->cflag & CREAD)
- X || ((ttyp->t_state & (ISOPEN | CARR_ON)) !=
- X (ISOPEN | CARR_ON)))
- X {
- X /* if there are FIFOs we take a short cut */
- X if (fip->device_flags.i & DF_DEVICE_IS_NS16550A)
- X fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_SETUP_CMD
- X | NS_FIFO_CLR_RECV);
- X else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
- X {
- X fas_outb (fip, I_BANK_PORT, I_BANK_1);
- X fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
- X fas_outb (fip, I_BANK_PORT, I_BANK_0);
- X }
- X continue;
- X }
- X
- X csize = 0;
- X
- X /* strip off 8th bit ? */
- X if (fip->iflag & ISTRIP)
- X charac &= 0x7f;
- X
- X /* ignore parity errors ? */
- X if ((line_status & LS_PARITY_ERROR)
- X && !(fip->iflag & INPCK))
- X line_status &= ~LS_PARITY_ERROR;
- X
- X#if defined(FASI)
- X if(line_status & LS_OVERRUN)
- X fip->overrun_errors++;
- X#endif /* FASI */
- X
- X /* do we have some kind of character error ? */
- X if (line_status & (LS_PARITY_ERROR
- X | LS_FRAMING_ERROR
- X | LS_BREAK_DETECTED))
- X {
- X#if defined(FASI)
- X if(line_status & LS_PARITY_ERROR)
- X fip->parity_errors++;
- X if(line_status & LS_FRAMING_ERROR)
- X fip->framing_errors++;
- X if(line_status & LS_BREAK_DETECTED)
- X fip->breaks_detected++;
- X#endif /* FASI */
- X#if defined (HAVE_VPIX)
- X if ((fip->iflag & (DOSMODE | PARMRK))
- X == (DOSMODE | PARMRK))
- X {
- X /* send status bits to VP/ix */
- X (void) fas_vpix_sr (fip, 1,
- X (line_status & (LS_PARITY_ERROR
- X | LS_FRAMING_ERROR
- X | LS_BREAK_DETECTED))
- X | LS_RCV_AVAIL
- X | LS_XMIT_AVAIL
- X | LS_XMIT_COMPLETE);
- X goto valid_char;
- X }
- X#endif
- X /* is it a BREAK ? */
- X if (line_status & LS_BREAK_DETECTED)
- X {
- X if (!(fip->iflag & IGNBRK))
- X if (fip->iflag & BRKINT)
- X {
- X /* do BREAK interrupt */
- X event_sched (fip, EF_DO_BRKINT);
- X }
- X else
- X {
- X metta [csize] = 0;
- X csize++;
- X if (fip->iflag & PARMRK)
- X {
- X metta [csize] = 0;
- X csize++;
- X metta [csize] = 0xff;
- X csize++;
- X }
- X }
- X }
- X else if (!(fip->iflag & IGNPAR))
- X if (fip->iflag & PARMRK)
- X {
- X metta [csize] = charac;
- X csize++;
- X metta [csize] = 0;
- X csize++;
- X metta [csize] = 0xff;
- X csize++;
- X }
- X else
- X {
- X metta [csize] = 0;
- X csize++;
- X }
- X }
- X else
- X /* is there a character to process ? */
- X if (line_status & LS_RCV_AVAIL)
- X {
- X if (fip->iflag & IXON)
- X {
- X /* do output start/stop handling */
- X if (fip->flow_flags.i & FF_SWO_STOPPED)
- X {
- X#if defined (HAVE_VPIX)
- X if ((charac == fip->v86_ss.ss_start)
- X#else
- X if ((charac == CSTART)
- X#endif
- X || (fip->iflag & IXANY))
- X {
- X fip->flow_flags.s &=
- X ~FF_SWO_STOPPED;
- X ttyp->t_state &= ~TTSTOP;
- X /* restart output */
- X fas_xproc (fip);
- X }
- X }
- X else
- X {
- X#if defined (HAVE_VPIX)
- X if (charac == fip->v86_ss.ss_stop)
- X#else
- X if (charac == CSTOP)
- X#endif
- X {
- X fip->flow_flags.s |=
- X FF_SWO_STOPPED;
- X ttyp->t_state |= TTSTOP;
- X }
- X }
- X /* we don't put start/stop characters
- X into the receiver buffer
- X */
- X#if defined (HAVE_VPIX)
- X if ((charac == fip->v86_ss.ss_start)
- X || (charac == fip->v86_ss.ss_stop))
- X#else
- X if ((charac == CSTART)
- X || (charac == CSTOP))
- X#endif
- X continue;
- X }
- Xvalid_char:
- X if ((charac == 0xff) && (fip->iflag & PARMRK))
- X {
- X metta [csize] = 0xff;
- X csize++;
- X metta [csize] = 0xff;
- X csize++;
- X }
- X else
- X {
- X /* we take a short-cut if only one character
- X has to be put into the receiver buffer
- X */
- X if (fip->recv_ring_cnt < RECV_BUFF_SIZE)
- X {
- X fip->recv_ring_cnt++;
- X *fip->recv_ring_put_ptr = charac;
- X if (++fip->recv_ring_put_ptr
- X != &fip->recv_buffer
- X [RECV_BUFF_SIZE])
- X continue;
- X fip->recv_ring_put_ptr =
- X &fip->recv_buffer [0];
- X }
- X continue;
- X }
- X }
- X
- X if (!(csize) || (fip->recv_ring_cnt + csize > RECV_BUFF_SIZE))
- X continue; /* nothing to put into recv buffer */
- X
- X fip->recv_ring_cnt += csize;
- X
- X /* store translation in ring buffer */
- X do
- X {
- X do
- X {
- X *fip->recv_ring_put_ptr = (metta - 1) [csize];
- X if (++fip->recv_ring_put_ptr
- X == &fip->recv_buffer [RECV_BUFF_SIZE])
- X break;
- X } while (--csize);
- X if (!csize)
- X break;
- X fip->recv_ring_put_ptr = &fip->recv_buffer [0];
- X } while (--csize);
- X } while ((line_status = fas_inb (fip, LINE_STATUS_PORT)) & LS_RCV_INT);
- X
- X return (line_status);
- X}
- X
- X/* Output characters to the transmitter register. */
- Xstatic void
- Xfas_xproc (fip)
- Xregister struct fas_info *fip;
- X{
- X register uint num_to_output;
- X REGVAR;
- X
- X /* proceed only if transmitter is available */
- X if ((fip->device_flags.i & (DF_XMIT_BUSY | DF_XMIT_BREAK
- X | DF_XMIT_LOCKED))
- X || (fip->flow_flags.i & FF_HWO_STOPPED))
- X goto sched;
- X
- X num_to_output = fip->xmit_fifo_size;
- X
- X /* handle XON/XOFF input flow control requests */
- X if (fip->flow_flags.i & FF_SW_FC_REQ)
- X {
- X#if defined (HAVE_VPIX)
- X fas_first_outb (fip, XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED)
- X ? fip->v86_ss.ss_stop
- X : fip->v86_ss.ss_start);
- X#else
- X fas_first_outb (fip, XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED)
- X ? CSTOP
- X : CSTART);
- X#endif
- X fip->tty->t_state &= ~(TTXON | TTXOFF);
- X fip->device_flags.s |= DF_XMIT_BUSY;
- X fip->flow_flags.s &= ~FF_SW_FC_REQ;
- X /* disable guard timeout */
- X if (fip->device_flags.i & DF_GUARD_TIMEOUT)
- X {
- X fip->device_flags.s &= ~DF_GUARD_TIMEOUT;
- X fip->tty->t_state &= ~TIMEOUT;
- X (void) untimeout (fip->timeout_idx);
- X }
- X num_to_output--;
- X }
- X
- X /* bail out if output is suspended by XOFF */
- X if (fip->flow_flags.i & FF_SWO_STOPPED)
- X goto sched;
- X
- X /* Determine how many chars to put into the transmitter
- X register.
- X */
- X if (fip->xmit_ring_cnt < num_to_output)
- X num_to_output = fip->xmit_ring_cnt;
- X
- X /* no characters available ? */
- X if (!num_to_output)
- X goto sched;
- X
- X /* output characters */
- X fip->xmit_ring_cnt -= num_to_output;
- X
- X fas_ctl (fip, XMT_DATA_PORT);
- X
- X#if defined(FASI)
- X fip->characters_transmitted += num_to_output;
- X#endif /* FASI */
- X
- X do
- X {
- X do
- X {
- X (void) outb (XMT_DATA_PORT.addr,
- X *fip->xmit_ring_take_ptr);
- X if (++fip->xmit_ring_take_ptr
- X == &fip->xmit_buffer [XMIT_BUFF_SIZE])
- X break;
- X } while (--num_to_output);
- X if (!num_to_output)
- X break;
- X fip->xmit_ring_take_ptr = &fip->xmit_buffer [0];
- X } while (--num_to_output);
- X
- X /* signal that transmitter is busy now */
- X fip->device_flags.s |= DF_XMIT_BUSY;
- X /* disable guard timeout */
- X if (fip->device_flags.i & DF_GUARD_TIMEOUT)
- X {
- X fip->device_flags.s &= ~DF_GUARD_TIMEOUT;
- X fip->tty->t_state &= ~TIMEOUT;
- X (void) untimeout (fip->timeout_idx);
- X }
- X
- X /* schedule fas_xxfer () if there are more characters to transfer
- X into the transmitter ring buffer
- X */
- Xsched:
- X if ((fip->xmit_ring_size > fip->xmit_ring_cnt)
- X && (fip->tty->t_outq.c_cc || fip->tty->t_tbuf.c_count))
- X {
- X event_sched (fip, EF_DO_XXFER);
- X }
- X}
- X
- X/* Asynchronous event handler. Scheduled by functions that can't do the
- X processing themselves because of execution time restrictions.
- X*/
- Xstatic void
- Xfas_event (dummy)
- Xvoid *dummy;
- X{
- X register struct fas_info *fip;
- X register uint unit;
- X int old_level;
- X
- X old_level = SPLINT ();
- X
- X unit = 0;
- X fip = &fas_info [0];
- X
- X /* loop through all fas_info structures */
- X for (;; fip++, unit++)
- X {
- X if (unit >= fas_physical_units)
- X break; /* all structures done */
- X
- X /* process only structures that actually need to
- X be serviced
- X */
- Xfastloop2:
- X if (!fip->event_flags.i)
- X {
- X /* speed beats beauty */
- X fip++;
- X if (++unit < fas_physical_units)
- X goto fastloop2;
- X break;
- X }
- X
- X do
- X {
- X /* check the modem signals */
- X if (fip->event_flags.i & EF_DO_MPROC)
- X {
- X fip->event_flags.s &= ~EF_DO_MPROC;
- X fas_mproc (fip);
- X /* disable the device if there were too many modem
- X status interrupts
- X */
- X if (fip->msi_cnt > (MAX_MSI_CNT / HZ)
- X * (EVENT_TIME * HZ / 1000))
- X {
- X fip->device_flags.s &= ~(DF_DEVICE_CONFIGURED
- X | DF_XMIT_BUSY
- X | DF_XMIT_BREAK);
- X fip->device_flags.s |= DF_XMIT_LOCKED;
- X if (fip->device_flags.i & DF_GUARD_TIMEOUT)
- X {
- X fip->device_flags.s &=
- X ~DF_GUARD_TIMEOUT;
- X fip->tty->t_state &= ~TIMEOUT;
- X (void) untimeout (fip->timeout_idx);
- X (void) wakeup ((caddr_t) &(fip)->
- X device_flags.i);
- X }
- X fip->tty->t_state &= ~CARR_ON;
- X (void) SPLWRK ();
- X if (!(fip->cflag & CLOCAL)
- X && (fip->tty->t_state & ISOPEN))
- X (void) signal (fip->tty->t_pgrp,
- X SIGHUP);
- X (void) ttyflush (fip->tty, FREAD | FWRITE);
- X (void) printf ("\nWARNING: Excessive modem status interrupts on FAS unit %d (check the cabling).\n",
- X fip - &fas_info [0]);
- X (void) SPLINT ();
- X }
- X fip->msi_cnt = 0;
- X }
- X
- X /* do the break interrupt */
- X if (fip->event_flags.i & EF_DO_BRKINT)
- X {
- X fip->event_flags.s &= ~EF_DO_BRKINT;
- X if (fip->tty->t_state & ISOPEN)
- X {
- X (void) SPLWRK ();
- X (*linesw [fip->tty->t_line].l_input)
- X (fip->tty, L_BREAK);
- X (void) SPLINT ();
- X }
- X }
- X
- X /* transfer characters to the UNIX input buffer */
- X if (fip->event_flags.i & EF_DO_RXFER)
- X {
- X fip->event_flags.s &= ~EF_DO_RXFER;
- X if (!(fip->flow_flags.i & FF_RXFER_STOPPED))
- X {
- X (void) SPLWRK ();
- X fas_rxfer (fip);
- X (void) SPLINT ();
- X /* check input buffer high/low water marks */
- X fas_ihlw_check (fip);
- X }
- X }
- X
- X /* transfer characters to the output ring buffer */
- X if (fip->event_flags.i & EF_DO_XXFER)
- X {
- X fip->event_flags.s &= ~EF_DO_XXFER;
- X (void) SPLWRK ();
- X fas_xxfer (fip);
- X (void) SPLINT ();
- X fas_hdx_check (fip);
- X /* output characters */
- X fas_xproc (fip);
- X }
- X
- X#if defined (HAVE_VPIX)
- X /* send pseudorupt to VP/ix */
- X if (fip->event_flags.i & EF_SIGNAL_VPIX)
- X {
- X fip->event_flags.s &= ~EF_SIGNAL_VPIX;
- X if ((fip->iflag & DOSMODE) && fip->v86_proc)
- X {
- X (void) SPLWRK ();
- X (void) v86setint (fip->v86_proc,
- X fip->v86_intmask);
- X (void) SPLINT ();
- X }
- X }
- X#endif
- X } while (fip->event_flags.i);
- X
- X /* allow pending tty interrupts */
- X (void) SPLWRK ();
- X (void) SPLINT ();
- X }
- X
- X event_scheduled = FALSE;
- X
- X /* check whether there have been new requests in the mean time */
- X for (unit = 0, fip = &fas_info [0]; unit < fas_physical_units;
- X fip++, unit++)
- X if (fip->event_flags.i)
- X {
- X /* there is at least one new request, so
- X schedule the next event processing
- X */
- X event_scheduled = TRUE;
- X (void) timeout (fas_event, (void *) NULL,
- X (EVENT_TIME) * (HZ) / 1000);
- X break;
- X }
- X
- X#if defined(FASI)
- X (void)wakeup((caddr_t)&fip->device_flags.i);
- X#endif /* FASI */
- X (void) splx (old_level);
- X}
- X
- X#if defined (HAVE_VPIX)
- X/* Send port status register to VP/ix */
- Xstatic int
- Xfas_vpix_sr (fip, token, status)
- Xregister struct fas_info *fip;
- Xuint token;
- Xuint status;
- X{
- X if ((fip->recv_ring_cnt <= RECV_BUFF_SIZE - 3)
- X && ((fip->tty->t_state & (ISOPEN | CARR_ON)) ==
- X (ISOPEN | CARR_ON)))
- X {
- X /* sent the character sequence 0xff, <token>, <status>
- X to VP/ix
- X */
- X fip->recv_ring_cnt += 3;
- X
- X *fip->recv_ring_put_ptr = 0xff;
- X if (++fip->recv_ring_put_ptr
- X == &fip->recv_buffer [RECV_BUFF_SIZE])
- X fip->recv_ring_put_ptr
- X = &fip->recv_buffer [0];
- X *fip->recv_ring_put_ptr = token;
- X if (++fip->recv_ring_put_ptr
- X == &fip->recv_buffer [RECV_BUFF_SIZE])
- X fip->recv_ring_put_ptr
- X = &fip->recv_buffer [0];
- X *fip->recv_ring_put_ptr = status;
- X if (++fip->recv_ring_put_ptr
- X == &fip->recv_buffer [RECV_BUFF_SIZE])
- X fip->recv_ring_put_ptr
- X = &fip->recv_buffer [0];
- X return (TRUE);
- X }
- X return (FALSE);
- X}
- X#endif
- X
- X/* Receiver ring buffer -> UNIX buffer transfer function. */
- Xstatic void
- Xfas_rxfer (fip)
- Xregister struct fas_info *fip;
- X{
- X register struct tty *ttyp;
- X register int num_to_xfer;
- X int num_save;
- X int old_level;
- X
- X ttyp = fip->tty;
- X
- X for (;;)
- X {
- X if (!fip->recv_ring_cnt || !ttyp->t_rbuf.c_ptr)
- X break; /* no characters to transfer */
- X
- X /* determine how many characters to transfer */
- X#if defined (HAVE_VPIX)
- X num_to_xfer = ((fip->iflag & DOSMODE)
- X ? MAX_VPIX_FILL
- X : MAX_UNIX_FILL) - ttyp->t_rawq.c_cc;
- X#else
- X num_to_xfer = MAX_UNIX_FILL - ttyp->t_rawq.c_cc;
- X#endif
- X
- X if (num_to_xfer < MIN_READ_CHUNK)
- X break; /* input buffer full */
- X
- X#if defined (HAVE_VPIX)
- X /* wakeup VP/ix */
- X if ((fip->iflag & DOSMODE) && !ttyp->t_rawq.c_cc)
- X event_sched (fip, EF_SIGNAL_VPIX);
- X#endif
- X
- X /* determine how many characters are in one contigous block */
- X if (fip->recv_ring_cnt < num_to_xfer)
- X num_to_xfer = fip->recv_ring_cnt;
- X if (&fip->recv_buffer [RECV_BUFF_SIZE] - fip->recv_ring_take_ptr
- X < num_to_xfer)
- X num_to_xfer = &fip->recv_buffer [RECV_BUFF_SIZE]
- X - fip->recv_ring_take_ptr;
- X if (ttyp->t_rbuf.c_count < num_to_xfer)
- X num_to_xfer = ttyp->t_rbuf.c_count;
- X
- X num_save = num_to_xfer;
- X ttyp->t_rbuf.c_count -= num_to_xfer;
- X
- X /* do the transfer */
- X do
- X {
- X *ttyp->t_rbuf.c_ptr = *fip->recv_ring_take_ptr;
- X ttyp->t_rbuf.c_ptr++;
- X fip->recv_ring_take_ptr++;
- X } while (--num_to_xfer);
- X
- X if (fip->recv_ring_take_ptr == &fip->recv_buffer [RECV_BUFF_SIZE])
- X fip->recv_ring_take_ptr = &fip->recv_buffer [0];
- X
- X intr_disable ();
- X fip->recv_ring_cnt -= num_save;
- X intr_restore ();
- X
- X ttyp->t_rbuf.c_ptr -= ttyp->t_rbuf.c_size
- X - ttyp->t_rbuf.c_count;
- X (*linesw [ttyp->t_line].l_input) (ttyp, L_BUF);
- X }
- X}
- X
- X/* UNIX buffer -> transmitter ring buffer transfer function. */
- Xstatic void
- Xfas_xxfer (fip)
- Xregister struct fas_info *fip;
- X{
- X register struct tty *ttyp;
- X register int num_to_xfer;
- SHAR_EOF
- true || echo 'restore of fasi/fas.c failed'
- fi
- echo 'End of ecu310 part 30'
- echo 'File fasi/fas.c is continued in part 31'
- echo 31 > _shar_seq_.tmp
- exit 0
- --------------------------------------------------------------------
- Warren Tucker, TuckerWare emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
- Hacker Extraordinaire d' async PADs, pods, proteins and protocols
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-