FAS 2.08 async driver, part 3/4
Uwe Doering
gemini at geminix.in-berlin.de
Mon Feb 4 09:18:00 AEST 1991
Submitted-by: gemini at geminix.in-berlin.de
Archive-name: fas208/part03
#!/bin/sh
# this is fas208.03 (part 3 of fas208)
# do not concatenate these parts, unpack them in order with /bin/sh
# file fas.c continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 3; 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 fas.c'
else
echo 'x - continuing file fas.c'
sed 's/^X//' << 'SHAR_EOF' >> 'fas.c' &&
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 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 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 }
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 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 (void) wakeup ((caddr_t) &ttyp->t_canq);
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 event_sched (fip, EF_DO_MPROC);
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 ? fas_inb (fip, RCV_DATA_PORT)
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 /* 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 (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 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 (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;
X int num_save;
X int old_level;
X
X ttyp = fip->tty;
X
X for (;;)
X {
X /* Check if tbuf is empty. If it is empty, reset buffer
X pointer and counter and get the next chunk of output
X characters.
X */
X if (!ttyp->t_tbuf.c_ptr || !ttyp->t_tbuf.c_count)
X {
X if (ttyp->t_tbuf.c_ptr)
X ttyp->t_tbuf.c_ptr -= ttyp->t_tbuf.c_size;
X if (!((*linesw [ttyp->t_line].l_output) (ttyp)
X & CPRES))
X break;
X }
X
X /* set the maximum character limit */
X num_to_xfer = fip->xmit_ring_size - fip->xmit_ring_cnt;
X
X /* Return if transmitter ring buffer is full. */
X if (num_to_xfer < 1)
X break;
X
X /* Determine how many chars to transfer this time. */
X if (&fip->xmit_buffer [XMIT_BUFF_SIZE] - fip->xmit_ring_put_ptr
X < num_to_xfer)
X num_to_xfer = &fip->xmit_buffer [XMIT_BUFF_SIZE]
X - fip->xmit_ring_put_ptr;
X if (ttyp->t_tbuf.c_count < num_to_xfer)
X num_to_xfer = ttyp->t_tbuf.c_count;
X
X num_save = num_to_xfer;
X ttyp->t_tbuf.c_count -= num_to_xfer;
X ttyp->t_state |= BUSY;
X
X /* do the transfer */
X do
X {
X *fip->xmit_ring_put_ptr = *ttyp->t_tbuf.c_ptr;
X ttyp->t_tbuf.c_ptr++;
X fip->xmit_ring_put_ptr++;
X } while (--num_to_xfer);
X
X if (fip->xmit_ring_put_ptr == &fip->xmit_buffer [XMIT_BUFF_SIZE])
X fip->xmit_ring_put_ptr = &fip->xmit_buffer [0];
X
X intr_disable ();
X fip->xmit_ring_cnt += num_save;
X intr_restore ();
X }
X}
X
X/* Input buffer high/low water mark check. */
Xstatic void
Xfas_ihlw_check (fip)
Xregister struct fas_info *fip;
X{
X REGVAR;
X
X if (fip->flow_flags.i & FF_HWI_STOPPED)
X {
X /* If input buffer level has dropped below
X the low water mark and input was stopped
X by hardware handshake, restart input.
X */
X if (fip->recv_ring_cnt < HW_LOW_WATER)
X {
X fip->mcr |= fip->flow.m.ic;
X fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
X fip->flow_flags.s &= ~FF_HWI_STOPPED;
X }
X }
X else
X {
X /* If input buffer level has risen above the
X high water mark and input is not yet
X stopped, stop input by hardware handshake.
X */
X if ((fip->flow_flags.i & FF_HWI_HANDSHAKE)
X && (fip->recv_ring_cnt > HW_HIGH_WATER))
X {
X fip->mcr &= ~fip->flow.m.ic;
X fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
X fip->flow_flags.s |= FF_HWI_STOPPED;
X }
X }
X
X if (fip->flow_flags.i & FF_SWI_STOPPED)
X {
X /* If input buffer level has dropped below
X the low water mark and input was stopped
X by XOFF, send XON to restart input.
X */
X if (!(fip->iflag & IXOFF)
X || (fip->recv_ring_cnt < SW_LOW_WATER))
X {
X fip->flow_flags.s &= ~FF_SWI_STOPPED;
X fip->flow_flags.s ^= FF_SW_FC_REQ;
X if (fip->flow_flags.i & FF_SW_FC_REQ)
X {
X fip->tty->t_state |= TTXON;
X fas_xproc (fip);
X }
X else
X fip->tty->t_state &= ~TTXOFF;
X }
X }
X else
X {
X /* If input buffer level has risen above the
X high water mark and input is not yet
X stopped, send XOFF to stop input.
X */
X if ((fip->iflag & IXOFF)
X && (fip->recv_ring_cnt > SW_HIGH_WATER))
X {
X fip->flow_flags.s |= FF_SWI_STOPPED;
X fip->flow_flags.s ^= FF_SW_FC_REQ;
X if (fip->flow_flags.i & FF_SW_FC_REQ)
X {
X fip->tty->t_state |= TTXOFF;
X fas_xproc (fip);
X }
X else
X fip->tty->t_state &= ~TTXON;
X }
X }
X}
X
X/* Half-duplex hardware flow control check. */
Xstatic void
Xfas_hdx_check (fip)
Xregister struct fas_info *fip;
X{
X REGVAR;
X
X /* don't interfere with hardware input handshake */
X if (fip->flow_flags.i & FF_HWI_HANDSHAKE)
X return;
X
X#if defined (HAVE_VPIX)
X /* don't touch the mcr if we are in dos mode and hdx hardware
X handshake is disabled (dos handles the handshake line(s)
X on its own in this mode)
X */
X if ((fip->iflag & DOSMODE) && !(fip->flow_flags.i & FF_HDX_HANDSHAKE))
X return;
X#endif
X if (fip->flow_flags.i & FF_HDX_STARTED)
X {
X /* If output buffer is empty signal the connected
X device that all output is done.
X */
X if ((fip->flow_flags.i & FF_HDX_HANDSHAKE)
X && !(fip->tty->t_state & BUSY))
X {
X fip->mcr &= ~fip->flow.m.hc;
X fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
X fip->flow_flags.s &= ~FF_HDX_STARTED;
X }
X }
X else
X {
X /* If the output ring buffer contains characters
X and was previously empty signal the connected
X device that output is resumed.
X */
X if (!(fip->flow_flags.i & FF_HDX_HANDSHAKE)
X || (fip->tty->t_state & BUSY))
X {
X fip->mcr |= fip->flow.m.hc;
X fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
X fip->flow_flags.s |= FF_HDX_STARTED;
X }
X }
X}
X
X/* Handle hangup after last close */
Xstatic void
Xfas_hangup (fip)
Xregister struct fas_info *fip;
X{
X int old_level;
X REGVAR;
X
X old_level = SPLINT ();
X
X if (fip->device_flags.i & DF_DO_HANGUP)
X {
X /* do the hangup */
X fip->mcr &= ~(fip->modem.m.ei
X | fip->modem.m.eo);
X fip->mcr |= fip->modem.m.di;
X fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
X fip->device_flags.s &= ~(DF_MODEM_ENABLED | DF_DO_HANGUP);
X (void) timeout (fas_hangup, fip, (fip->device_flags.i
X & DF_DEVICE_CONFIGURED)
X ? (HANGUP_TIME) * (HZ) / 1000
X : (RECOVER_TIME) * (HZ));
X }
X else
X {
X /* unlock the device */
X fip->device_flags.s |= DF_DEVICE_CONFIGURED;
X /* If there was a waiting getty open on this
X port, reopen the physical device.
X */
X if (fip->o_state & OS_WAIT_OPEN)
X {
X fas_open_device (fip);
X fas_param (fip, HARD_INIT); /* set up port regs */
X }
X release_device_lock (fip);
X }
X (void) splx (old_level);
X}
X
X/* main timeout function */
Xstatic void
Xfas_timeout (fip)
Xregister struct fas_info *fip;
X{
X int old_level;
X REGVAR;
X
X old_level = SPLINT ();
X
X /* handle break request */
X if (fip->device_flags.i & DF_DO_BREAK)
X {
X /* set up break request flags */
X fip->lcr |= LC_SET_BREAK_LEVEL;
X fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
X fip->device_flags.s &= ~(DF_DO_BREAK | DF_GUARD_TIMEOUT);
X (void) timeout (fas_timeout, fip, (BREAK_TIME) * (HZ) / 1000);
X (void) splx (old_level);
X return;
X }
X
X /* reset break state */
X if (fip->device_flags.i & DF_XMIT_BREAK)
X {
X if (fip->lcr & LC_SET_BREAK_LEVEL)
X {
X fip->lcr &= ~LC_SET_BREAK_LEVEL;
X fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
X fip->device_flags.s |= DF_GUARD_TIMEOUT;
X fip->timeout_idx = timeout (fas_timeout, fip,
X fas_ctimes [fip->cflag & CBAUD]);
X (void) splx (old_level);
X return;
X }
X fip->device_flags.s &= ~DF_XMIT_BREAK;
X /* restart output after BREAK */
X fas_xproc (fip);
X }
X
X /* handle character guard timeout */
X if (fip->device_flags.i & DF_GUARD_TIMEOUT)
X {
X fip->device_flags.s &= ~DF_GUARD_TIMEOUT;
X if (!fip->xmit_ring_cnt)
X {
X fip->tty->t_state &= ~BUSY;
X fas_hdx_check (fip);
X }
X }
X
X fip->tty->t_state &= ~TIMEOUT;
X
X event_sched (fip, EF_DO_XXFER);
X
X (void) wakeup ((caddr_t) &(fip)->device_flags.i);
X (void) splx (old_level);
X}
X
X/* Several functions for flow control, character output and special event
X requests and handling.
X*/
Xstatic void
Xfas_cmd (fip, ttyp, arg2)
Xregister struct fas_info *fip;
Xregister struct tty *ttyp;
Xint arg2;
X{
X REGVAR;
X
X switch (arg2)
X {
X case T_TIME: /* timeout */
X goto start_output;
X
X case T_OUTPUT: /* output characters to the transmitter */
X if (fip->xmit_ring_size > fip->xmit_ring_cnt)
X {
Xstart_output:
X event_sched (fip, EF_DO_XXFER);
X }
X break;
X
X case T_SUSPEND: /* suspend character output */
X fip->flow_flags.s |= FF_SWO_STOPPED;
X ttyp->t_state |= TTSTOP;
X break;
X
X case T_RESUME: /* restart character output */
X fip->flow_flags.s &= ~FF_SWO_STOPPED;
X ttyp->t_state &= ~TTSTOP;
X fas_xproc (fip);
X break;
X
X case T_BLOCK: /* stop character input, request XOFF */
X ttyp->t_state |= TBLOCK;
X break; /* note: we do our own XON/XOFF */
X
X case T_UNBLOCK: /* restart character input, request XON */
X ttyp->t_state &= ~TBLOCK;
X break; /* note: we do our own XON/XOFF */
X
X case T_RFLUSH: /* flush input buffers and restart input */
X if (fip->device_flags.i & DF_DEVICE_IS_NS16550A)
X fas_first_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_first_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
X fip->recv_ring_take_ptr = fip->recv_ring_put_ptr;
X fip->recv_ring_cnt = 0;
X ttyp->t_state &= ~TBLOCK;
X
X fas_ihlw_check (fip);
X break;
X
X case T_WFLUSH: /* flush output buffer and restart output */
X if (fip->device_flags.i & DF_DEVICE_IS_NS16550A)
X fas_first_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_SETUP_CMD
X | NS_FIFO_CLR_XMIT);
X else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
X {
X fas_first_outb (fip, I_BANK_PORT, I_BANK_1);
X fas_outb (fip, I_TCM_PORT, I_FIFO_CLR_XMIT);
X fas_outb (fip, I_BANK_PORT, I_BANK_0);
X }
X
X fip->xmit_ring_take_ptr = fip->xmit_ring_put_ptr;
X fip->xmit_ring_cnt = 0;
X
X fip->flow_flags.s &= ~FF_SWO_STOPPED;
X ttyp->t_state &= ~TTSTOP;
X
X if (ttyp->t_tbuf.c_ptr)
X ttyp->t_tbuf.c_ptr += ttyp->t_tbuf.c_count;
X ttyp->t_tbuf.c_count = 0;
X
X if (!(fip->device_flags.i & (DF_XMIT_BUSY | DF_GUARD_TIMEOUT)))
X {
X ttyp->t_state &= ~BUSY;
X fas_hdx_check (fip);
X goto start_output;
X }
X break;
X
X case T_BREAK: /* do a break on the transmitter line */
X fip->device_flags.s |= DF_XMIT_BREAK;
X ttyp->t_state |= TIMEOUT;
X if (fip->device_flags.i & (DF_XMIT_BUSY | DF_GUARD_TIMEOUT))
X {
X fip->device_flags.s |= DF_DO_BREAK;
X }
X else
X {
X /* set up break request flags */
X fip->lcr |= LC_SET_BREAK_LEVEL;
X fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
X (void) timeout (fas_timeout, fip, (BREAK_TIME) * (HZ)
X / 1000);
X }
X break;
X
X case T_PARM: /* set up the port according to the termio structure */
X fas_param (fip, SOFT_INIT);
X break;
X
X case T_SWTCH: /* handle layer switch request */
X break;
X }
X}
X
X/* open device physically */
Xstatic void
Xfas_open_device (fip)
Xregister struct fas_info *fip;
X{
X REGVAR;
X
X /* if already open, set up the mcr register only */
X if (fip->device_flags.i & DF_DEVICE_OPEN)
X goto setmcr;
X
X /* init some variables */
X fip->device_flags.s &= DF_DEVICE_CONFIGURED | DF_DEVICE_IS_NS16550A
X | DF_DEVICE_IS_I82510 | DF_DEVICE_LOCKED
X | DF_CTL_FIRST | DF_CTL_EVERY;
X fip->flow_flags.s = 0;
X fip->cflag = 0;
X fip->iflag = 0;
X fip->recv_ring_take_ptr = fip->recv_ring_put_ptr;
X fip->recv_ring_cnt = 0;
X fip->xmit_ring_take_ptr = fip->xmit_ring_put_ptr;
X fip->xmit_ring_cnt = 0;
X
X /* hook into the interrupt users chain */
X fip->next_int_user = fas_first_int_user [fip->vec];
X if (fip->next_int_user)
X fip->next_int_user->prev_int_user = fip;
X fas_first_int_user [fip->vec] = fip;
X fip->prev_int_user = (struct fas_info *) NULL;
X
X fip->lcr = 0;
X fas_first_outb (fip, LINE_CTL_PORT, fip->lcr);
X
X /* clear and disable FIFOs */
X if (fip->device_flags.i & DF_DEVICE_IS_NS16550A)
X fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
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_TCM_PORT, I_FIFO_CLR_XMIT);
X fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
X fas_outb (fip, I_BANK_PORT, I_BANK_2);
X fas_outb (fip, I_IDM_PORT, I_FIFO_CLEAR_CMD);
X fas_outb (fip, I_BANK_PORT, I_BANK_0);
X }
X
X /* clear 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
X /* enable FIFOs */
X if (fip->device_flags.i & DF_DEVICE_IS_NS16550A)
X fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_SETUP_CMD);
X else if (fip->device_flags.i & DF_DEVICE_IS_I82510)
X {
X fas_outb (fip, I_BANK_PORT, I_BANK_2);
X fas_outb (fip, I_IDM_PORT, I_FIFO_SETUP_CMD);
X fas_outb (fip, I_BANK_PORT, I_BANK_0);
X }
X
X fip->msi_cnt = 0;
X fip->msr = fip->new_msr = fas_inb (fip, MDM_STATUS_PORT)
X & (MS_CTS_PRESENT
X | MS_DSR_PRESENT
X | MS_DCD_PRESENT);
X
X fip->ier = IE_INIT_MODE; /* enable UART interrupts */
X fas_outb (fip, INT_ENABLE_PORT, fip->ier);
X
Xsetmcr:
X /* set up modem and flow control lines */
X fip->mcr &= ~(fip->modem.m.di
X | fip->modem.m.ei
X | fip->modem.m.eo
X | fip->flow.m.ic
X | fip->flow.m.hc);
X
X fip->mcr |= (fip->o_state & OS_WAIT_OPEN)
X ? fip->modem.m.ei
X : fip->modem.m.eo;
X
X if (fip->o_state & OS_HWI_HANDSHAKE)
X fip->mcr |= fip->flow.m.ic;
X else if (!(fip->o_state & OS_HDX_HANDSHAKE))
X {
X fip->flow_flags.s |= FF_HDX_STARTED;
X fip->mcr |= fip->flow.m.hc;
X }
X
X fas_outb (fip, MDM_CTL_PORT, fip->mcr);
X
X fip->device_flags.s |= DF_DEVICE_OPEN | DF_MODEM_ENABLED;
X}
X
X/* close device physically */
Xstatic void
Xfas_close_device (fip)
Xregister struct fas_info *fip;
X{
X REGVAR;
X
X fip->device_flags.s &= ~DF_DEVICE_OPEN;
X
X fip->ier = IE_NONE; /* disable UART interrupts */
X fas_first_outb (fip, INT_ENABLE_PORT, fip->ier);
X
X /* drop flow control lines */
X fip->mcr &= (fip->o_state & OS_HWI_HANDSHAKE)
X ? ~fip->flow.m.ic
X : ~fip->flow.m.hc;
X fas_outb (fip, MDM_CTL_PORT, fip->mcr);
X
X /* clear and disable FIFOs */
X if (fip->device_flags.i & DF_DEVICE_IS_NS16550A)
X fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
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_TCM_PORT, I_FIFO_CLR_XMIT);
X fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
X fas_outb (fip, I_BANK_PORT, I_BANK_2);
X fas_outb (fip, I_IDM_PORT, I_FIFO_CLEAR_CMD);
X fas_outb (fip, I_BANK_PORT, I_BANK_0);
X }
X
X /* reset break level */
X fip->lcr &= ~LC_SET_BREAK_LEVEL;
X fas_outb (fip, LINE_CTL_PORT, fip->lcr);
X
X /* unhook from interrupt users chain */
X if (fip->prev_int_user)
X fip->prev_int_user->next_int_user = fip->next_int_user;
X else
X fas_first_int_user [fip->vec] = fip->next_int_user;
X if (fip->next_int_user)
X fip->next_int_user->prev_int_user = fip->prev_int_user;
X
X if ((fip->cflag & HUPCL)
X || !(fip->device_flags.i & DF_DEVICE_CONFIGURED))
X {
X /* request hangup */
X fip->device_flags.s |= DF_DO_HANGUP;
X (void) timeout (fas_hangup, fip, (HANGUP_DELAY) * (HZ) / 1000);
X }
X}
X
X/* compute the port access control value */
Xstatic uint
Xfas_make_ctl_val (fip, unit, num)
Xregister struct fas_info *fip;
Xuint unit;
Xuint num;
X{
X register uint mask, val;
X uint i;
X
X if (fip->device_flags.i & DF_CTL_FIRST)
X return (fas_ctl_val [unit]);
X
X if (fip->device_flags.i & DF_CTL_EVERY)
X {
X for (i = 0, mask = fas_ctl_val [unit],
X val = fas_ctl_val [unit] << 8; i < 8; i++)
X {
X if (mask & 0x100)
X {
X if (num & 0x01)
X val ^= 0x100;
X num >>= 1;
X }
X mask >>= 1;
X val >>= 1;
X }
X return (val);
X }
X return (0);
X}
X
X/* test device thoroughly */
Xstatic int
Xfas_test_device (fip)
Xregister struct fas_info *fip;
X{
X register unchar *cptr;
X int done;
X uint delay_count, i;
X static uint lcrval [3] =
X {
X LC_WORDLEN_8,
X LC_WORDLEN_8 | LC_ENABLE_PARITY,
X LC_WORDLEN_8 | LC_ENABLE_PARITY | LC_EVEN_PARITY
X };
X REGVAR;
X
X /* make sure FIFO is off */
X fas_first_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
X fas_outb (fip, I_BANK_PORT, I_BANK_2);
X fas_outb (fip, I_IDM_PORT, I_FIFO_CLEAR_CMD);
X fas_outb (fip, I_BANK_PORT, I_BANK_0);
X
X /* set counter divisor */
X fas_outb (fip, LINE_CTL_PORT, LC_ENABLE_DIVISOR);
X fas_outb (fip, DIVISOR_LSB_PORT, fas_speeds [B38400]);
X fas_outb (fip, DIVISOR_MSB_PORT, fas_speeds [B38400] >> 8);
X fas_outb (fip, LINE_CTL_PORT, 0);
X
X /* switch to local loopback */
X fas_outb (fip, MDM_CTL_PORT, MC_SET_LOOPBACK);
X
X done = 0;
X
X /* wait until the transmitter register is empty */
X for (delay_count = 20000;
X delay_count && (~fas_inb (fip, LINE_STATUS_PORT)
X & (LS_XMIT_AVAIL | LS_XMIT_COMPLETE));
X delay_count--)
X ;
X
X if (!delay_count)
X done = 1;
X
X if (!done)
X {
X /* clear flags */
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
X /* make sure there are no more characters in the
X receiver register
X */
X for (delay_count = 20000;
X delay_count && !(fas_inb (fip, LINE_STATUS_PORT) & LS_RCV_AVAIL);
X delay_count--)
X ;
X
X if (delay_count)
X (void) fas_inb (fip, RCV_DATA_PORT);
X
X /* test pattern */
X cptr = (unchar *) "\
X\377\125\252\045\244\0\
X\377\125\252\045\244\0\
X\377\125\252\045\244\0\
X\377\125\252\045\244\0\
X\377\125\252\045\244\0\0";
X
X do
X {
X for (i = 0; i < 3; i++)
X {
X /* test transmitter and receiver
X with different line settings
X */
X fas_outb (fip, LINE_CTL_PORT, lcrval [i]);
X
X /* wait until the transmitter register
X is empty
X */
X for (delay_count = 20000;
X delay_count && (~fas_inb (fip, LINE_STATUS_PORT)
X & (LS_XMIT_AVAIL
X | LS_XMIT_COMPLETE));
X delay_count--)
X ;
X
X if (!delay_count)
X {
X done = 2;
X break;
X }
X
X /* send test pattern */
X fas_outb (fip, XMT_DATA_PORT, *cptr);
X
X /* wait until the test pattern is received */
X for (delay_count = 20000;
X delay_count && ((fas_inb (fip, LINE_STATUS_PORT)
X & LS_RCV_INT)
X != LS_RCV_AVAIL);
X delay_count--)
X ;
X
X if (!delay_count)
X {
X done = 3;
X break;
X }
X
X /* check test pattern */
X if (fas_inb (fip, RCV_DATA_PORT) != *cptr)
X {
X done = 4;
X break;
X }
X }
X
X if (done)
X break;
X } while (*((ushort *) cptr++));
X }
X
X if (!done)
X {
X /* wait until the transmitter register is empty */
X for (delay_count = 20000;
X delay_count && (~fas_inb (fip, LINE_STATUS_PORT)
X & (LS_XMIT_AVAIL | LS_XMIT_COMPLETE));
X delay_count--)
X ;
X
X if (!delay_count)
X done = 5;
X }
X
X if (!done)
X {
X /* test pattern */
X cptr = (unchar *) "\
X\005\142\012\237\006\130\011\257\017\361\0\017\
X\005\142\012\237\006\130\011\257\017\361\0\017\
X\005\142\012\237\006\130\011\257\017\361\0\017\
X\005\142\012\237\006\130\011\257\017\361\0\017\
X\005\142\012\237\006\130\011\257\017\361\0\017\0\0";
X
X /* clear delta bits */
X (void) fas_inb (fip, MDM_STATUS_PORT);
X
X do
X {
X /* test modem control and status lines */
X fas_outb (fip, MDM_CTL_PORT, *cptr | MC_SET_LOOPBACK);
X if (fas_inb (fip, MDM_STATUS_PORT) != *(cptr + 1))
X {
X done = 6;
X break;
X }
X } while (*((ushort *) cptr)++);
X }
X
X /* switch back to normal operation */
X fas_outb (fip, MDM_CTL_PORT, 0);
X
X return (done);
X}
X
X#if defined (NEED_PUT_GETCHAR)
X
Xint
Xasyputchar (arg1)
Xunchar arg1;
X{
X register struct fas_info *fip;
X REGVAR;
X
X if (!fas_is_initted)
X (void) fasinit ();
X
X fip = &fas_info [0];
X if (fip->device_flags.i & DF_DEVICE_CONFIGURED)
X {
X fas_ctl (fip, LINE_STATUS_PORT);
X while (!(inb (LINE_STATUS_PORT.addr) & LS_XMIT_AVAIL))
X ;
X fas_outb (fip, XMT_DATA_PORT, arg1);
X if (arg1 == 10)
X (void) asyputchar (13);
X }
X return (0);
X}
X
Xint
Xasygetchar ()
X{
X register struct fas_info *fip;
X REGVAR;
X
X if (!fas_is_initted)
X (void) fasinit ();
X
X fip = &fas_info [0];
X if ((fip->device_flags.i & DF_DEVICE_CONFIGURED)
X && (fas_first_inb (fip, LINE_STATUS_PORT) & LS_RCV_AVAIL))
X return (fas_inb (fip, RCV_DATA_PORT));
X else
X return (-1);
X}
X#endif
X
X#if defined (NEED_INIT8250)
X
X/* reset the requested port to be used directly by a DOS process */
Xint
Xinit8250 (port, ier)
Xushort port, ier; /* ier not used in this stub */
X{
X register struct fas_info *fip;
X register uint physical_unit;
X int old_level;
X REGVAR;
X
X /* See if the port address matches a port that is used by
X the fas driver.
X */
X for (physical_unit = 0; physical_unit < fas_physical_units;
X physical_unit++)
X if (port == (ushort) (fas_port [physical_unit]))
X break;
X
X if (physical_unit >= fas_physical_units)
X return (-1); /* port didn't match */
X
X fip = fas_info_ptr [physical_unit];
X
X old_level = SPLINT ();
X
X fip->ier = IE_NONE;
X fas_first_outb (fip, INT_ENABLE_PORT, fip->ier);
X
X fip->mcr &= ~(fip->flow.m.ic | fip->flow.m.hc);
X fas_outb (fip, MDM_CTL_PORT, fip->mcr);
X
X if (fip->device_flags.i & DF_DEVICE_IS_NS16550A)
X fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
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_TCM_PORT, I_FIFO_CLR_XMIT);
X fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
X fas_outb (fip, I_BANK_PORT, I_BANK_2);
X fas_outb (fip, I_IDM_PORT, I_FIFO_CLEAR_CMD);
X fas_outb (fip, I_BANK_PORT, I_BANK_0);
X }
X
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 (void) splx (old_level);
X return (0);
X}
X#endif
SHAR_EOF
echo 'File fas.c is complete' &&
true || echo 'restore of fas.c failed'
rm -f _shar_wnt_.tmp
fi
# ============= fas.h ==============
if test -f 'fas.h' -a X"$1" != X"-c"; then
echo 'x - skipping fas.h (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting fas.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'fas.h' &&
X/* This file contains various defines for the FAS async driver.
X If you change anything here you have to recompile the driver module.
X*/
X
X#if !defined (M_I286)
X#ident "@(#)fas.h 2.08"
X#endif
X
X/* Uncomment the following line if you need asyputchar and asygetchar.
X This is only required if you link the kernel without the original
X asy driver and these functions aren't provided by any other kernel
X module.
X*/
X/* #define NEED_PUT_GETCHAR /* */
X
X/* Uncomment the following line if you have VP/ix support in the
X kernel.
X*/
X/* #define HAVE_VPIX /* */
X
X/* Uncomment the following line if you need init8250. DosMerge needs
X this function, but only if you link the kernel without the original
X asy driver.
X*/
X/* #define NEED_INIT8250 /* */
X
X#if defined (VPIX)
X#undef VPIX
X#endif
X
X#if defined (HAVE_VPIX)
X#define VPIX
X#endif
X
X#include <sys/param.h>
X#include <sys/types.h>
X#include <sys/signal.h>
X#include <sys/buf.h>
X#include <sys/dir.h>
X#if defined (XENIX)
X#include <sys/page.h>
X#include <sys/seg.h>
X#endif
X#include <sys/user.h>
X#include <sys/errno.h>
X#include <sys/tty.h>
X#include <sys/conf.h>
X#include <sys/sysinfo.h>
X#include <sys/file.h>
X#if !defined (XENIX)
X#include <sys/termio.h>
X#endif
X#include <sys/ioctl.h>
X#include <macros.h>
X#if defined (HAVE_VPIX)
X#if !defined (XENIX)
X#include <sys/tss.h>
X#include <sys/immu.h>
X#include <sys/region.h>
X#endif
X#include <sys/proc.h>
X#include <sys/v86.h>
X#endif
X
X#if defined (XENIX)
Xtypedef unsigned char unchar;
Xtypedef unsigned long ulong;
X/*
X** Union for use by all device handler ioctl routines.
X*/
Xunion ioctl_arg {
X struct termio *stparg; /* ptr to termio struct */
X char *cparg; /* ptr to character */
X char carg; /* character */
X int *iparg; /* ptr to integer */
X int iarg; /* integer */
X long *lparg; /* ptr to long */
X long larg; /* long */
X};
X#endif
X
X#if defined (TRUE)
X#undef TRUE
X#endif
X#define TRUE (1)
X
X#if defined (FALSE)
X#undef FALSE
X#endif
X#define FALSE (0)
X
X/* Initial line control register. Value will only be meaningful for
X asyputchar and asygetchar and they are only meaningful if
X NEED_PUT_GETCHAR is defined.
X*/
X#define INITIAL_LINE_CONTROL LC_WORDLEN_8
X
X/* Initial baud rate. Value will only be meaningful for
X asyputchar and asygetchar and they are only meaningful if
X NEED_PUT_GETCHAR is defined.
X*/
X#define INITIAL_BAUD_RATE (BAUD_BASE/9600)
X
X/* Initial modem control register. This should probably not have to
X be touched. It is here because some terminals used as the console
X require one or more of the modem signals set. It is only meaningful
X for asyputchar and asygetchar and they are only meaningful if
X NEED_PUT_GETCHAR is defined.
X*/
X#define INITIAL_MDM_CONTROL 0
X
X/****************************************************/
X/* Nothing past this line should have to be changed */
X/****************************************************/
X
X#define NUM_INT_VECTORS 32 /* number of possible int vectors, but
X only the first eight are normally used
X */
X
X#define MAX_UNITS 16 /* we will only use that many units */
X
X/* Miscellaneous Constants */
X
X#define BAUD_BASE (1843200 / 16) /* 115200 bps */
X#define HANGUP_DELAY 500 /* in milli-seconds */
X#define HANGUP_TIME 1000 /* in milli-seconds */
X#define RECOVER_TIME 30 /* in seconds */
X#define BREAK_TIME 250 /* in milli-seconds */
X#define EVENT_TIME 20 /* in milli-seconds */
X#if defined (M_I286)
X#define RECV_BUFF_SIZE 1000 /* receiver ring buffer size (MAX) */
X#define SW_LOW_WATER 500 /* 50% MAX sw flow control */
X#define SW_HIGH_WATER 800 /* 80% MAX trigger levels */
X#define HW_LOW_WATER 700 /* MAX - 300 hw flow control */
X#define HW_HIGH_WATER 900 /* MAX - 100 trigger levels */
X#define XMIT_BUFF_SIZE 500 /* transmitter ring buffer size */
X#else
X#define RECV_BUFF_SIZE 5000 /* receiver ring buffer size (MAX) */
X#define SW_LOW_WATER 2500 /* 50% MAX sw flow control */
X#define SW_HIGH_WATER 4000 /* 80% MAX trigger levels */
X#define HW_LOW_WATER 4200 /* MAX - 800 hw flow control */
X#define HW_HIGH_WATER 4700 /* MAX - 300 trigger levels */
X#define XMIT_BUFF_SIZE 2500 /* transmitter ring buffer size */
X#endif
X#define MAX_UNIX_FILL (TTYHOG) /* read buffer max UNIX fill level */
X#define MAX_VPIX_FILL 64 /* read buffer max VP/ix fill level */
X#define MIN_READ_CHUNK 32 /* must be <= MAX_????_FILL/2 */
X#define MAX_MSI_CNT 1000 /* max modem status ints per second */
X#define READ_PORT 0x0100 /* read command for fas_init_seq */
X#define NO_FIFO 0x10000 /* force FIFOs off */
X#define SOFT_INIT 0 /* init registers if cflag changed */
X#define HARD_INIT 1 /* init registers w/o checking cflag */
X#if defined (XENIX)
X#define SPLWRK spl5 /* SPL for character processing */
X#define SPLINT spl7 /* SPL to disable FAS interrupts */
X#else
X#define SPLWRK spl6 /* SPL for character processing */
X#define SPLINT spltty /* SPL to disable FAS interrupts */
X#endif
X
X#if ((EVENT_TIME) * (HZ) / 1000) == 0
X#undef EVENT_TIME
X#define EVENT_TIME (1000 / (HZ))
X#endif
X
X#if (MAX_UNIX_FILL) > (TTYHOG)
X#undef MAX_UNIX_FILL
X#define MAX_UNIX_FILL (TTYHOG)
X#endif
X
X#if (MAX_VPIX_FILL) > (TTYHOG)
X#undef MAX_VPIX_FILL
X#define MAX_VPIX_FILL (TTYHOG)
X#endif
X
X#if (MIN_READ_CHUNK) > ((MAX_UNIX_FILL) / 2)
X#undef MIN_READ_CHUNK
X#define MIN_READ_CHUNK ((MAX_UNIX_FILL) / 2)
X#endif
X
X#if (MIN_READ_CHUNK) > ((MAX_VPIX_FILL) / 2)
X#undef MIN_READ_CHUNK
X#define MIN_READ_CHUNK ((MAX_VPIX_FILL) / 2)
X#endif
X
X#define MAX_INPUT_FIFO_SIZE INPUT_NS_FIFO_SIZE
X#define MAX_OUTPUT_FIFO_SIZE OUTPUT_NS_FIFO_SIZE
X
X
X/* Here are the modem control flags for the fas_modem array in space.c.
X They are arranged in three 8-bit masks which are combined to a 32-bit
X word. Each of these 32-bit words represents one entry in the fas_modem
X array.
X
X The lowest byte is used as a mask to manipulate the modem control
X register for modem disable. Use the MC_* macros to build the mask.
X
X The second lowest byte is used as a mask to manipulate the modem control
X register for modem enable during dialout. Use the MC_* macros to build
X the mask and shift them 8 bits to the left.
X
X The second highest byte is used as a mask to manipulate the modem control
X register for modem enable during dialin. Use the MC_* macros to build
X the mask and shift them 16 bits to the left.
X
X The highest byte is used to mask signals from the modem status
X register that will be used as the carrier detect signal. Use the MS_*
X macros to build the mask and shift them 24 bits to the left. If you use
X more than one signal, carrier is considered on only when all signals
X are on.
X
X Here are some useful macros for the space.c file. You may create your
X own macros if you have some special requirements not met by the
X predefined ones.
X*/
X
X/* modem disable (choose one) */
X#define DI_RTS MC_SET_RTS /* RTS disables modem */
X#define DI_DTR MC_SET_DTR /* DTR disables modem */
X#define DI_RTS_AND_DTR (MC_SET_RTS | MC_SET_DTR)
X
X/* modem enable for dialout (choose one) */
X#define EO_RTS (MC_SET_RTS << 8) /* RTS enables modem */
X#define EO_DTR (MC_SET_DTR << 8) /* DTR enables modem */
X#define EO_RTS_AND_DTR ((MC_SET_RTS | MC_SET_DTR) << 8)
X
X/* modem enable for dialin (choose one) */
X#define EI_RTS (MC_SET_RTS << 16) /* RTS enables modem */
X#define EI_DTR (MC_SET_DTR << 16) /* DTR enables modem */
X#define EI_RTS_AND_DTR ((MC_SET_RTS | MC_SET_DTR) << 16)
X
X/* carrier detect signal (choose one) */
X#define CA_DCD (MS_DCD_PRESENT << 24) /* DCD is carr. detect */
X#define CA_CTS (MS_CTS_PRESENT << 24) /* CTS is carr. detect */
X#define CA_DSR (MS_DSR_PRESENT << 24) /* DSR is carr. detect */
X
X
X/* Here are the hardware handshake flags for the fas_flow array in space.c.
X They are arranged in three 8-bit masks which are combined to a 32-bit
X word. Each of these 32-bit words represents one entry in the fas_flow
X array.
X
X The lowest byte is used as a mask to manipulate the modem control
X register for input flow control. Use the MC_* macros to build the mask.
X
X The second lowest byte is used to mask signals from the modem status
X register that will be used for output flow control. Use the MS_* macros
X to build the mask and shift them 8 bits to the left. If you use more
X than one signal, output is allowed only when all signals are on.
X
X The second highest byte is used to mask signals from the modem status
X register that will be used to enable the output flow control selected
X by the second lowest byte. Use the MS_* macros to build the mask and
X shift them 16 bits to the left. If you use more than one signal, output
X flow control is enabled only when all signals are on.
X
X The highest byte is used as a mask to manipulate the modem control
X register for output half duplex flow control. Use the MC_* macros to
X build the mask and shift them 24 bits to the left.
X
X Here are some useful macros for the space.c file. You may create your
X own macros if you have some special requirements not met by the
X predefined ones.
X*/
X
X/* input flow control (choose one) */
X#define HI_RTS MC_SET_RTS /* RTS input flow ctrl */
X#define HI_DTR MC_SET_DTR /* DTR input flow ctrl */
X#define HI_RTS_AND_DTR (MC_SET_RTS | MC_SET_DTR)
X
X/* output flow control (choose one) */
X#define HO_CTS (MS_CTS_PRESENT << 8) /* CTS output flow ctrl */
X#define HO_DSR (MS_DSR_PRESENT << 8) /* DSR output flow ctrl */
X#define HO_CTS_AND_DSR ((MS_CTS_PRESENT | MS_DSR_PRESENT) << 8)
X#define HO_CTS_ON_DSR ((MS_CTS_PRESENT << 8) | (MS_DSR_PRESENT << 16))
X#define HO_CTS_ON_DSR_AND_DCD ((MS_CTS_PRESENT << 8) \
X | ((MS_DSR_PRESENT | MS_DCD_PRESENT) << 16))
X
X/* output hdx flow control (choose one) */
X#define HX_RTS (MC_SET_RTS << 24) /* RTS hdx flow ctrl */
X#define HX_DTR (MC_SET_DTR << 24) /* DTR hdx flow ctrl */
X#define HX_RTS_AND_DTR ((MC_SET_RTS | MC_SET_DTR) << 24)
X
X
X/* define the local open flags */
X
X#define OS_DEVICE_CLOSED 0x0000
X#define OS_OPEN_FOR_DIALOUT 0x0001
X#define OS_OPEN_FOR_GETTY 0x0002
X#define OS_WAIT_OPEN 0x0004
X#define OS_NO_DIALOUT 0x0008
X#define OS_FAKE_CARR_ON 0x0010
X#define OS_CLOCAL 0x0020
X#define OS_HWO_HANDSHAKE 0x0040
X#define OS_HWI_HANDSHAKE 0x0080
X#define OS_HDX_HANDSHAKE 0x0100
X#define OS_EXCLUSIVE_OPEN_1 0x0200
X#define OS_EXCLUSIVE_OPEN_2 0x0400 /* SYSV 3.2 Xenix compatibility */
X
X#define OS_OPEN_STATES (OS_OPEN_FOR_DIALOUT | OS_OPEN_FOR_GETTY)
X#define OS_TEST_MASK (OS_OPEN_FOR_DIALOUT | OS_NO_DIALOUT \
X | OS_FAKE_CARR_ON | OS_CLOCAL \
X | OS_HWO_HANDSHAKE | OS_HWI_HANDSHAKE \
X | OS_HDX_HANDSHAKE | OS_EXCLUSIVE_OPEN_1 \
X | OS_EXCLUSIVE_OPEN_2)
X#define OS_SU_TEST_MASK (OS_OPEN_FOR_DIALOUT | OS_NO_DIALOUT \
X | OS_FAKE_CARR_ON | OS_CLOCAL \
X | OS_HWO_HANDSHAKE | OS_HWI_HANDSHAKE \
X | OS_HDX_HANDSHAKE | OS_EXCLUSIVE_OPEN_1)
X
X/* define the device status flags */
X
X#define DF_DEVICE_CONFIGURED 0x0001 /* device is configured */
X#define DF_DEVICE_IS_NS16550A 0x0002 /* it's an NS16550A */
X#define DF_DEVICE_IS_I82510 0x0004 /* it's an I82510 */
X#define DF_CTL_FIRST 0x0008 /* write ctl port at first access */
X#define DF_CTL_EVERY 0x0010 /* write ctl port at every access */
X#define DF_DEVICE_OPEN 0x0020 /* physical device is open */
X#define DF_DEVICE_LOCKED 0x0040 /* physical device locked */
X#define DF_MODEM_ENABLED 0x0080 /* modem enabled */
X#define DF_XMIT_BUSY 0x0100 /* transmitter busy */
X#define DF_XMIT_BREAK 0x0200 /* transmitter sends break */
X#define DF_XMIT_LOCKED 0x0400 /* transmitter locked against output */
X#define DF_DO_HANGUP 0x0800 /* delayed hangup request */
X#define DF_DO_BREAK 0x1000 /* delayed break request */
X#define DF_GUARD_TIMEOUT 0x2000 /* protect last char from corruption */
X#define DF_NS16550A_DROP_MODE 0x4000 /* receiver trigger level is dropped */
X
X/* define the flow control status flags */
X
X#define FF_HWO_HANDSHAKE 0x0001 /* output hw handshake enabled */
X#define FF_HWI_HANDSHAKE 0x0002 /* input hw handshake enabled */
X#define FF_HDX_HANDSHAKE 0x0004 /* output hdx hw handshake enabled */
X#define FF_HWO_STOPPED 0x0008 /* output stopped by hw handshake */
X#define FF_HWI_STOPPED 0x0010 /* input stopped by hw handshake */
X#define FF_HDX_STARTED 0x0020 /* output buffer contains characters */
X#define FF_SWO_STOPPED 0x0040 /* output stopped by sw flow control */
X#define FF_SWI_STOPPED 0x0080 /* input stopped by sw flow control */
X#define FF_SW_FC_REQ 0x0100 /* sw input flow control request */
X#define FF_RXFER_STOPPED 0x0200 /* rxfer function stopped */
X
X/* define the scheduled events flags */
X
X#define EF_DO_RXFER 0x0001 /* rxfer function request */
X#define EF_DO_XXFER 0x0002 /* xxfer function request */
X#define EF_DO_BRKINT 0x0004 /* break int request */
X#define EF_DO_MPROC 0x0008 /* mproc function request */
X#define EF_SIGNAL_VPIX 0x0010 /* send pseudorupt to VP/ix */
SHAR_EOF
true || echo 'restore of fas.h failed'
fi
echo 'End of fas208 part 3'
echo 'File fas.h is continued in part 4'
echo 4 > _shar_seq_.tmp
exit 0
--
Uwe Doering | INET : gemini at geminix.in-berlin.de
Berlin |----------------------------------------------------------------
Germany | UUCP : ...!unido!fub!geminix.in-berlin.de!gemini
More information about the Comp.unix.sysv386
mailing list