home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
fas-2.11.0
/
part06
< prev
next >
Wrap
Text File
|
1993-10-16
|
61KB
|
2,205 lines
Newsgroups: comp.sources.unix
From: fas@geminix.in-berlin.de (FAS Support Account)
Subject: REPOST v27i073: FAS-2.11.0 - asynch serial driver for System V, Part06/08
References: <1.750471074.20539@gw.home.vix.com>
Sender: unix-sources-moderator@gw.home.vix.com
Approved: vixie@gw.home.vix.com
Submitted-By: fas@geminix.in-berlin.de (FAS Support Account)
Posting-Number: Volume 27, Issue 73
Archive-Name: fas-2.11.0/part06
#!/bin/sh
# this is fas211pl0.06 (part 6 of a multipart archive)
# 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" != 6; 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 else
X#endif
X {
X if (cflag & CTSFLOW)
X fip->flow_flags |= FF_HWO_HANDSHAKE;
X if (cflag & RTSFLOW)
X fip->flow_flags |= (fip->flow_flags
X & FF_NEW_CTSRTS)
X ? FF_HWI_HANDSHAKE
X : FF_HDX_HANDSHAKE;
X }
X#endif
X }
X#endif
X#endif
X }
X
X /* Determine whether to enable MSI or not.
X Set the interrupt enable port accordingly.
X */
X#if defined (HAVE_VPIX)
X if ((cflag & CLOCAL) && !(fip->flow_flags & FF_HWO_HANDSHAKE)
X && !(fip->iflag & DOSMODE))
X#else
X if ((cflag & CLOCAL) && !(fip->flow_flags & FF_HWO_HANDSHAKE))
X#endif
X {
X if (fip->device_flags & DF_MSI_ENABLED)
X {
X FAS_FIRST_OUTB (fip, INT_ENABLE_PORT,
X IER &= ~IE_MODEM_STATUS);
X fip->device_flags &= ~DF_MSI_ENABLED;
X }
X fip->device_flags &= ~DF_MSI_NOISE;
X }
X else
X {
X if (!(fip->device_flags & (DF_MSI_ENABLED | DF_MSI_NOISE)))
X {
X /* read current modem status lines */
X MSR = NEW_MSR = FAS_FIRST_INB (fip, MDM_STATUS_PORT)
X & (MS_CTS_PRESENT
X | MS_DSR_PRESENT
X | MS_DCD_PRESENT);
X FAS_OUTB (fip, INT_ENABLE_PORT, IER |= IE_MODEM_STATUS);
X fip->device_flags |= DF_MSI_ENABLED;
X }
X }
X
X /* Fake the carrier detect state flag if CLOCAL mode or if
X requested by open mode.
X */
X if ((cflag & CLOCAL)
X || (fip->flow_flags & FF_CD_ENABLED
X && !(~MSR & fip->modem.m.ca))
X || ((fip->o_state & OS_FAKE_CARRIER_ON)
X && ((fip->flow_flags & FF_CARRIER_ON)
X || !(fip->o_state & OS_OPEN_STATES))))
X {
X fip->flow_flags |= FF_CD_ENABLED | FF_CARRIER_ON;
X ttyp->t_state |= CARR_ON;
X }
X else
X {
X if (fip->flow_flags & FF_CARRIER_ON)
X {
X fip->flow_flags &= ((fip->device_flags
X & DF_HUP_PROTECT)
X && (fip->o_state
X & OS_OPEN_STATES))
X ? ~(FF_CD_ENABLED
X | FF_CARRIER_ON)
X : ~FF_CARRIER_ON;
X /* flush buffers on carrier drop */
X do_flush = TRUE;
X }
X ttyp->t_state &= ~CARR_ON;
X }
X
X if ((fip->flow_flags & FF_CARRIER_ON) && (cflag & CREAD))
X {
X /* enable receiver data interrupts */
X if (!(fip->device_flags & DF_RDI_ENABLED))
X fas_rdi_enable (fip);
X }
X else
X {
X /* disable receiver data interrupts */
X if (fip->device_flags & DF_RDI_ENABLED)
X {
X FAS_FIRST_OUTB (fip, INT_ENABLE_PORT,
X IER &= ~IE_RECV_DATA_AVAILABLE);
X fip->device_flags &= ~DF_RDI_ENABLED;
X }
X }
X
X fip->cflag = cflag;
X }
X
X#if defined (XCLUDE) /* SYSV 3.2 Xenix compatibility */
X /* Permit exclusive use of this device. */
X if (ttyp->t_lflag & XCLUDE)
X fip->o_state |= OS_EXCLUSIVE_OPEN_2;
X else
X fip->o_state &= ~OS_EXCLUSIVE_OPEN_2;
X#endif
X
X /* re-link fas_internals structure */
X fas_pos_by_speed (fip);
X
X /* flush buffers if necessary */
X if (do_flush)
X {
X /* lock transmitter */
X fip->device_flags |= DF_XMIT_LOCKED;
X old_level = SPLWRK ();
X (void) ttyflush (ttyp, FREAD | FWRITE);
X (void) splx (old_level);
X /* enable transmitter */
X fip->device_flags &= ~DF_XMIT_LOCKED;
X }
X
X /* setup handshake flags */
X#if defined (HAVE_VPIX)
X if ((fip->flow_flags & (FF_HWI_HANDSHAKE | FF_HDX_HANDSHAKE))
X || !(fip->iflag & DOSMODE))
X#endif
X {
X register n_unchar mcr REG_BX;
X
X /* clear flow control output bits */
X mcr = MCR & ~(fip->flow.m.ic | fip->flow.m.hc);
X fip->flow_flags &= ~(FF_HWI_STARTED | FF_HDX_STARTED);
X
X /* raise flow control bits if necessary */
X if (fip->flow_flags & FF_HWI_HANDSHAKE)
X {
X if (fip->recv_ring_cnt < HW_LOW_WATER)
X {
X mcr |= fip->flow.m.ic;
X fip->flow_flags |= FF_HWI_STARTED;
X }
X }
X else if (fip->flow_flags & FF_HDX_HANDSHAKE)
X {
X if (fip->flow_flags & FF_OUTPUT_BUSY)
X {
X mcr |= fip->flow.m.hc;
X fip->flow_flags |= FF_HDX_STARTED;
X }
X }
X else if (!(fip->flow_flags & FF_DEF_HHO_LOW))
X mcr |= fip->flow.m.hc;
X
X /* set modem enable bits */
X#if defined (HAVE_VPIX)
X if (!(fip->iflag & DOSMODE))
X#endif
X {
X if ((ttyp->t_cflag & CBAUD) != B0
X && (fip->flow_flags & FF_CD_ENABLED))
X {
X mcr |= (fip->o_state & OS_WAIT_OPEN)
X ? fip->modem.m.ei
X : fip->modem.m.eo;
X }
X else
X {
X mcr &= (fip->o_state & OS_WAIT_OPEN)
X ? ~fip->modem.m.ei
X : ~fip->modem.m.eo;
X }
X }
X
X if ((init_type != SOFT_INIT) || (mcr != MCR))
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT, MCR = mcr);
X }
X
X /* set hardware output flow control flags */
X if (!(~NEW_MSR & fip->flow.m.oc)
X || (~NEW_MSR & fip->flow.m.oe)
X || !(fip->flow_flags & FF_HWO_HANDSHAKE))
X fip->flow_flags &= ~FF_HWO_STOPPED;
X else
X fip->flow_flags |= FF_HWO_STOPPED;
X
X /* check software input flow control */
X if (fip->flow_flags & FF_SWI_STOPPED)
X {
X if (!(fip->iflag & IXOFF)
X || (fip->recv_ring_cnt < SW_LOW_WATER))
X fas_send_xon (fip);
X }
X else
X {
X if ((fip->iflag & IXOFF)
X && (fip->recv_ring_cnt > SW_HIGH_WATER))
X fas_send_xoff (fip);
X }
X
X /* restart output */
X fas_xproc (fip);
X}
X
X/* Re-link fas_internals structure to interrupt users chain according
X to the baud rate (fastes port comes first).
X (called at SPLINT)
X*/
XSTATIC void
Xfas_pos_by_speed (fipp)
Xstruct fas_internals *fipp;
X{
X register struct fas_internals *fip REG_SI;
X
X {
X register n_unchar my_prio REG_BX;
X register n_unchar prio REG_CX;
X ulong my_speed;
X
X fip = fipp;
X
X /* compute our own speed */
X if (fip->flow_flags & FF_CARRIER_ON)
X {
X INT_PRIO = my_prio = (fip->device_flags & DF_NO_OVERRUN)
X ? NUMBER_OF_TYPES
X : DEVICE_TYPE;
X my_speed = fas_baud_ptr [BT_SELECT] [fip->cflag & CBAUD];
X }
X else
X {
X my_prio = NUMBER_OF_TYPES + 1;
X INT_PRIO = NUMBER_OF_TYPES + 1;
X my_speed = 0L;
X }
X
X /* unhook us from the 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->next_int_user;
X if (fip->next_int_user)
X fip->next_int_user->prev_int_user = fip->prev_int_user;
X else
X fas_last_int_user = fip->prev_int_user;
X
X /* find a new position for us */
X for (fip = fas_first_int_user; fip; fip = fip->next_int_user)
X {
Xfastloop4:
X if (my_prio > (prio = INT_PRIO))
X {
X /* speed beats beauty */
X fip = fip->next_int_user;
X if (fip)
X goto fastloop4;
X break;
X }
X
X if (my_prio < prio)
X break; /* found a new position */
X if (my_speed >= ((prio == NUMBER_OF_TYPES + 1)
X ? 0L
X : fas_baud_ptr [BT_SELECT]
X [fip->cflag & CBAUD]))
X break; /* found a new position */
X }
X }
X
X {
X register struct fas_internals *my_fip REG_DI;
X
X my_fip = fipp;
X
X /* now hook us into the new position */
X if (fip)
X {
X /* we are in front of another entry */
X if ((my_fip->prev_int_user = fip->prev_int_user))
X my_fip->prev_int_user->next_int_user = my_fip;
X else
X fas_first_int_user = my_fip;
X fip->prev_int_user = my_fip;
X my_fip->next_int_user = fip;
X }
X else
X {
X /* we are the last entry */
X if ((my_fip->prev_int_user = fas_last_int_user))
X my_fip->prev_int_user->next_int_user = my_fip;
X else
X fas_first_int_user = my_fip;
X fas_last_int_user = my_fip;
X my_fip->next_int_user = (struct fas_internals *) NULL;
X }
X }
X}
X
X/* Asynchronous event handler. Scheduled by functions that can't do the
X processing themselves because of execution time restrictions.
X (called via timeout () at an OS dependent SPL)
X*/
XSTATIC void
Xfas_event (dummy)
Xvoid *dummy;
X{
X register struct fas_internals *fip REG_SI;
X register struct tty *ttyp REG_DI;
X register uint count REG_BX;
X bool idle;
X int old_level;
X
X /* allow pending tty interrupts */
X old_level = SPLWRK ();
X (void) SPLINT ();
X
X idle = TRUE;
X
X /* loop through all fas_internals structures */
X for (fip = &fas_internals [0], count = fas_physical_units; count;
X ++fip, --count)
X {
Xfastloop3:
X /* process only structures that actually need service */
X if (!fip->event_flags)
X {
X /* speed beats beauty */
X ++fip;
X if (--count)
X goto fastloop3;
X break;
X }
X
X /* we have something to do */
X idle = FALSE;
X ttyp = fip->tty;
X
X /* check the modem signals */
X if (fip->event_flags & (EF_DO_MPROC | EF_RESET_DELTA_BITS))
X {
X NEW_MSR &= ~MS_ANY_DELTA;
X if (fip->event_flags & EF_DO_MPROC)
X {
X fip->event_flags &= ~(EF_DO_MPROC
X | EF_RESET_DELTA_BITS);
X fas_mproc (fip);
X }
X else
X fip->event_flags &= ~EF_RESET_DELTA_BITS;
X
X /* re-enable modem status interrupts if appropriate */
X if (fip->device_flags & DF_MSI_NOISE)
X {
X FAS_FIRST_OUTB (fip, INT_ENABLE_PORT,
X IER |= IE_MODEM_STATUS);
X fip->device_flags |= DF_MSI_ENABLED;
X fip->device_flags &= ~DF_MSI_NOISE;
X }
X }
X
X /* do the break interrupt */
X if (fip->event_flags & EF_DO_BRKINT)
X {
X fip->event_flags &= ~EF_DO_BRKINT;
X if (fip->flow_flags & FF_CARRIER_ON)
X {
X (void) SPLWRK ();
X (void) (*linesw [(unchar) ttyp->t_line].l_input)
X (ttyp, L_BREAK);
X (void) SPLINT ();
X }
X }
X
X /* transfer characters to the CLIST input buffer */
X if (fip->event_flags & EF_DO_RXFER)
X {
X#if defined (HAVE_VPIX)
X fip->event_flags &= ~(EF_DO_RXFER | EF_WAKEUP_VPIX);
X#else
X fip->event_flags &= ~EF_DO_RXFER;
X#endif
X if ((fip->flow_flags & (FF_CARRIER_ON
X | FF_RXFER_STOPPED))
X == FF_CARRIER_ON)
X {
X /* if not done, re-schedule this event */
X if (!fas_rxfer (fip))
X fip->event_flags |= EF_DO_RXFER;
X /* check input buffer low water marks */
X if ((fip->recv_ring_cnt < HW_LOW_WATER)
X && (fip->flow_flags & (FF_HWI_HANDSHAKE
X | FF_HWI_STARTED))
X == FF_HWI_HANDSHAKE)
X {
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT,
X MCR |= fip->flow.m.ic);
X fip->flow_flags |= FF_HWI_STARTED;
X }
X if ((fip->recv_ring_cnt < SW_LOW_WATER)
X && (fip->iflag & IXOFF)
X && (fip->flow_flags & FF_SWI_STOPPED))
X fas_send_xon (fip);
X }
X#if defined (HAVE_VPIX)
X /* send pseudorupt to VP/ix */
X if ((fip->iflag & DOSMODE) && fip->v86_proc
X && (ttyp->t_rawq.c_cc || ttyp->t_canq.c_cc))
X {
X (void) SPLWRK ();
X (void) v86setint (fip->v86_proc,
X fip->v86_intmask);
X (void) SPLINT ();
X fip->event_flags |= EF_WAKEUP_VPIX;
X }
X#endif
X }
X#if defined (HAVE_VPIX)
X else if (fip->event_flags & EF_WAKEUP_VPIX)
X {
X /* send pseudorupt to VP/ix */
X if ((fip->iflag & DOSMODE) && fip->v86_proc
X && (ttyp->t_rawq.c_cc || ttyp->t_canq.c_cc))
X {
X (void) SPLWRK ();
X (void) v86setint (fip->v86_proc,
X fip->v86_intmask);
X (void) SPLINT ();
X }
X else
X fip->event_flags &= ~EF_WAKEUP_VPIX;
X }
X#endif
X
X /* transfer characters to the output ring buffer */
X if (fip->event_flags & EF_DO_XXFER)
X {
X fip->event_flags &= ~EF_DO_XXFER;
X if (fip->flow_flags & FF_CARRIER_ON)
X {
X fas_xxfer (fip);
X if (fip->flow_flags & FF_OUTPUT_BUSY)
X ttyp->t_state |= BUSY;
X /* check half duplex output flow control */
X if ((fip->flow_flags & (FF_HDX_HANDSHAKE
X | FF_HDX_STARTED
X | FF_OUTPUT_BUSY))
X == (FF_HDX_HANDSHAKE
X | FF_OUTPUT_BUSY))
X {
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT,
X MCR |= fip->flow.m.hc);
X fip->flow_flags |= FF_HDX_STARTED;
X }
X /* output characters */
X fas_xproc (fip);
X }
X else
X {
X /* throw away characters in output queue */
X (void) SPLWRK ();
X (void) ttyflush (ttyp, FWRITE);
X (void) SPLINT ();
X }
X }
X
X /* allow pending tty interrupts */
X (void) SPLWRK ();
X (void) SPLINT ();
X }
X
X event_scheduled = FALSE;
X
X /* check whether there was something to do */
X if (!idle)
X {
X /* there was work to do, so it's likely that there
X also will be something to do in a short time from
X now, so we schedule the next event processing
X */
X event_scheduled = TRUE;
X (void) timeout (fas_event, (caddr_t) NULL,
X (EVENT_TIME) * (HZ) / 1000);
X }
X
X (void) splx (old_level);
X}
X
X/* Modem status handler.
X (called at SPLINT)
X*/
XSTATIC void
Xfas_mproc (fip)
Xregister struct fas_internals *fip REG_SI;
X{
X register n_unchar mdm_status REG_BX;
X int old_level;
X
X mdm_status = NEW_MSR;
X 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) && (fip->flow_flags & FF_CD_ENABLED))
X {
X register struct tty *ttyp REG_DI;
X
X ttyp = fip->tty;
X if (!(~mdm_status & fip->modem.m.ca))
X {
X /* Wake up dialin process on carrier low->high. */
X if (!(fip->flow_flags & FF_CARRIER_ON))
X {
X fip->flow_flags |= FF_CARRIER_ON;
X if ((ttyp->t_state |= CARR_ON) & WOPEN)
X (void) wakeup ((caddr_t) &ttyp->t_canq);
X /* enable receiver data interrupts */
X if ((fip->cflag & CREAD)
X && !(fip->device_flags
X & DF_RDI_ENABLED))
X fas_rdi_enable (fip);
X /* re-link fas_internals structure */
X fas_pos_by_speed (fip);
X }
X }
X else
X {
X if (!(~MSR & fip->modem.m.ca))
X {
X if ((fip->device_flags & DF_HUP_PROTECT)
X && (fip->o_state & OS_OPEN_STATES))
X {
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT,
X MCR &= (fip->o_state
X & OS_WAIT_OPEN)
X ? ~fip->modem.m.ei
X : ~fip->modem.m.eo);
X fip->flow_flags &= ~(FF_CD_ENABLED
X | FF_CARRIER_ON);
X }
X else
X fip->flow_flags &= ~FF_CARRIER_ON;
X ttyp->t_state &= ~CARR_ON;
X /* disable receiver data interrupts */
X if (fip->device_flags & DF_RDI_ENABLED)
X {
X FAS_FIRST_OUTB (fip, INT_ENABLE_PORT,
X IER &= ~IE_RECV_DATA_AVAILABLE);
X fip->device_flags &= ~DF_RDI_ENABLED;
X }
X /* re-link fas_internals structure */
X fas_pos_by_speed (fip);
X old_level = SPLWRK ();
X if (ttyp->t_pgrp)
X {
X (void) signal (ttyp->t_pgrp, SIGHUP);
X#if defined (SIGCONT)
X /* make sure processes are awake */
X (void) signal (ttyp->t_pgrp, SIGCONT);
X#endif
X }
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)) == (DOSMODE | PARMRK)
X && (fip->flow_flags & FF_CARRIER_ON)
X && fip->recv_ring_cnt < RECV_BUFF_SIZE - 2)
X {
X register n_unchar vpix_status REG_CX;
X
X /* prepare status bits for VP/ix */
X vpix_status = (((mdm_status ^ MSR) >> 4) & MS_ANY_DELTA)
X | (mdm_status & (MS_CTS_PRESENT
X | MS_DSR_PRESENT
X | MS_DCD_PRESENT));
X if (fip->flow_flags & FF_HWO_HANDSHAKE)
X {
X vpix_status &= ~((n_unchar) (fip->flow.m.oc
X | fip->flow.m.oe) >> 4);
X vpix_status |= fip->flow.m.oc | fip->flow.m.oe;
X }
X if (!(fip->cflag & CLOCAL))
X {
X vpix_status &= ~((n_unchar) fip->modem.m.ca >> 4);
X vpix_status |= fip->modem.m.ca;
X }
X /* send status bits to VP/ix */
X if (vpix_status & MS_ANY_DELTA)
X {
X fip->recv_ring_cnt += 3;
X PUT_RECV_BUFFER (fip, fip->recv_ring_put_ptr, 0xff);
X PUT_RECV_BUFFER (fip, fip->recv_ring_put_ptr, 2);
X PUT_RECV_BUFFER (fip, fip->recv_ring_put_ptr,
X vpix_status);
X EVENT_SCHED (fip, EF_DO_RXFER);
X /* check input buffer high water marks */
X if ((fip->recv_ring_cnt > HW_HIGH_WATER)
X && (fip->flow_flags & (FF_HWI_HANDSHAKE
X | FF_HWI_STARTED))
X == (FF_HWI_HANDSHAKE | FF_HWI_STARTED))
X {
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT,
X MCR &= ~fip->flow.m.ic);
X fip->flow_flags &= ~FF_HWI_STARTED;
X }
X if ((fip->recv_ring_cnt > SW_HIGH_WATER)
X && (fip->iflag & IXOFF)
X && !(fip->flow_flags & FF_SWI_STOPPED))
X fas_send_xoff (fip);
X }
X }
X#endif
X MSR = mdm_status & ~MS_RING_PRESENT;
X
X /* re-enable transmitter if it was stopped by carrier detect */
X if (fip->flow_flags & FF_CARR_STOPPED)
X {
X fip->flow_flags &= ~FF_CARR_STOPPED;
X fas_xproc (fip);
X }
X}
X
X/* Receiver ring buffer -> CLIST buffer transfer function.
X (called at SPLINT)
X*/
XSTATIC bool
Xfas_rxfer (fipp)
Xstruct fas_internals *fipp;
X{
X /* Defining register variables with function-wide scope would
X break the FAS_MEM_COPY () macro below. So don't do that!
X */
X unchar *tmp_srcptr, *tmp_destptr;
X uint num_save;
X uint recv_ring_cnt;
X int old_level;
X
X num_save = 0;
X
X for (;;)
X {
X /* determine how many characters we have to copy */
X {
X register struct fas_internals *fip REG_SI;
X register struct tty *ttyp REG_DI;
X register uint num_to_xfer REG_BX;
X
X old_level = SPLWRK ();
X fip = fipp;
X ttyp = fip->tty;
X
X /* if the target buffer is full, or if there is no
X target buffer available, try to get a new one,
X otherwise return
X */
X if (num_save || !ttyp->t_rbuf.c_ptr)
X {
X (void) (*linesw [(unchar) ttyp->t_line].l_input)
X (ttyp, L_BUF);
X if (!ttyp->t_rbuf.c_ptr)
X {
X (void) splx (old_level);
X return (FALSE);
X }
X }
X
X /* return if there aren't any characters to transfer */
X if (!(recv_ring_cnt = fip->recv_ring_cnt))
X {
X (void) splx (old_level);
X return (TRUE);
X }
X
X /* determine how many characters to transfer */
X#if defined (XENIX)
X if (ttyp->t_lflag & ICANON)
X#else
X if ((ttyp->t_lflag & ICANON) || ttyp->t_term)
X#endif
X {
X num_to_xfer = recv_ring_cnt;
X }
X else
X {
X num_to_xfer = max_rawq_count - (uint) ttyp->t_rawq.c_cc;
X if (!num_to_xfer)
X {
X (void) splx (old_level);
X return (FALSE); /* input buffer full */
X }
X if (recv_ring_cnt < num_to_xfer)
X num_to_xfer = recv_ring_cnt;
X /* if there are too few remaining characters to
X completely fill a CLIST buffer, postpone the
X transfer of these characters for a number of
X event cycles on the assumption that by then
X more characters have arrived
X */
X if (ttyp->t_rbuf.c_count > num_to_xfer
X && (num_save || --fip->rxfer_timeout))
X {
X (void) splx (old_level);
X return (FALSE); /* input buffer full */
X }
X }
X
X /* reset timeout counter */
X fip->rxfer_timeout = MAX_RXFER_DELAY / EVENT_TIME;
X
X /* determine how many characters are in one contiguous block */
X if (ttyp->t_rbuf.c_count < num_to_xfer)
X num_to_xfer = ttyp->t_rbuf.c_count;
X if ((uint) (&fip->recv_buffer [RECV_BUFF_SIZE]
X - 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
X if (!num_to_xfer)
X {
X /* invalid count, shouldn't happen */
X (void) splx (old_level);
X return (FALSE);
X }
X
X tmp_srcptr = fip->recv_ring_take_ptr;
X if ((fip->recv_ring_take_ptr += num_to_xfer)
X == &fip->recv_buffer [RECV_BUFF_SIZE])
X fip->recv_ring_take_ptr = &fip->recv_buffer [0];
X tmp_destptr = (unchar *) ttyp->t_rbuf.c_ptr;
X ttyp->t_rbuf.c_count -= num_to_xfer;
X num_save = num_to_xfer;
X }
X
X /* now copy from the ring buffer to the clist buffer */
X FAS_MEM_COPY (tmp_destptr, tmp_srcptr, num_save);
X
X (void) splx (old_level);
X fipp->recv_ring_cnt -= num_save;
X }
X}
X
X/* CLIST buffer -> transmitter ring buffer transfer function.
X (called at SPLINT)
X*/
XSTATIC void
Xfas_xxfer (fipp)
Xstruct fas_internals *fipp;
X{
X /* Defining register variables with function-wide scope would
X break the FAS_MEM_COPY () macro below. So don't do that!
X */
X unchar *tmp_srcptr, *tmp_destptr;
X uint num_save;
X uint xmit_ring_cnt;
X int old_level;
X
X for (;;)
X {
X /* determine how many characters we have to copy */
X {
X register struct fas_internals *fip REG_SI;
X register struct tty *ttyp REG_DI;
X register uint num_to_xfer REG_BX;
X
X old_level = SPLWRK ();
X fip = fipp;
X ttyp = fip->tty;
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 [(unchar) ttyp->t_line].l_output) (ttyp)
X & CPRES))
X {
X (void) splx (old_level);
X return;
X }
X }
X
X /* Return if transmitter ring buffer is full. */
X if (fip->xmit_ring_size <= (xmit_ring_cnt = fip->xmit_ring_cnt))
X {
X (void) splx (old_level);
X return;
X }
X
X /* set the maximum character limit */
X num_to_xfer = fip->xmit_ring_size - xmit_ring_cnt;
X
X /* Determine how many chars to transfer this time. */
X if (ttyp->t_tbuf.c_count < num_to_xfer)
X num_to_xfer = ttyp->t_tbuf.c_count;
X if ((uint) (&fip->xmit_buffer [XMIT_BUFF_SIZE]
X - 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 (!num_to_xfer)
X {
X /* invalid count, shouldn't happen */
X (void) splx (old_level);
X return;
X }
X
X fip->flow_flags |= FF_OUTPUT_BUSY;
X tmp_srcptr = (unchar *) ttyp->t_tbuf.c_ptr;
X ttyp->t_tbuf.c_ptr += num_to_xfer;
X ttyp->t_tbuf.c_count -= num_to_xfer;
X tmp_destptr = fip->xmit_ring_put_ptr;
X if ((fip->xmit_ring_put_ptr += num_to_xfer)
X == &fip->xmit_buffer [XMIT_BUFF_SIZE])
X fip->xmit_ring_put_ptr = &fip->xmit_buffer [0];
X num_save = num_to_xfer;
X }
X
X /* now copy from the clist buffer to the ring buffer */
X FAS_MEM_COPY (tmp_destptr, tmp_srcptr, num_save);
X
X (void) splx (old_level);
X fipp->xmit_ring_cnt += num_save;
X }
X}
X
X/* Handle hangup after last close.
X (called via timeout () at an OS dependent SPL)
X*/
XSTATIC void
Xfas_hangup (fip)
Xregister struct fas_internals *fip REG_SI;
X{
X int old_level;
X
X old_level = SPLINT ();
X
X if (fip->device_flags & DF_DO_HANGUP)
X {
X /* do the hangup */
X MCR &= ~(fip->modem.m.ei | fip->modem.m.eo);
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT, MCR |= fip->modem.m.di);
X fip->device_flags &= ~DF_DO_HANGUP;
X (void) timeout (fas_hangup, (caddr_t) fip,
X (HANGUP_TIME) * (HZ) / 1000);
X }
X else
X {
X /* If there was a waiting dialin process on this
X port, reopen the physical device.
X */
X if (fip->o_state & OS_WAIT_OPEN)
X {
X /* allow pending tty interrupts */
X (void) SPLWRK ();
X (void) SPLINT ();
X
X fas_open_device (fip);
X
X /* allow pending tty interrupts */
X (void) SPLWRK ();
X (void) SPLINT ();
X }
X RELEASE_DEVICE_LOCK (fip);
X }
X
X (void) splx (old_level);
X}
X
X/* Main timeout function.
X (called via timeout () at an OS dependent SPL)
X*/
XSTATIC void
Xfas_timeout (fip)
Xregister struct fas_internals *fip REG_SI;
X{
X int old_level;
X
X old_level = SPLINT ();
X
X /* handle break request */
X if (fip->device_flags & DF_DO_BREAK)
X {
X /* set up break request flags */
X FAS_FIRST_OUTB (fip, LINE_CTL_PORT,
X LCR |= LC_SET_BREAK_LEVEL);
X fip->device_flags &= ~(DF_DO_BREAK | DF_GUARD_TIMEOUT);
X (void) timeout (fas_timeout, (caddr_t) fip,
X (BREAK_TIME) * (HZ) / 1000);
X (void) splx (old_level);
X return;
X }
X
X /* reset break state */
X if ((fip->device_flags & DF_XMIT_BREAK)
X && (LCR & LC_SET_BREAK_LEVEL))
X {
X FAS_FIRST_OUTB (fip, LINE_CTL_PORT, LCR &= ~LC_SET_BREAK_LEVEL);
X fip->device_flags |= DF_GUARD_TIMEOUT;
X fip->timeout_idx = timeout (fas_timeout, (caddr_t) fip,
X fas_speed_ptr [BT_SELECT]
X [fip->cflag & CBAUD]
X .i.ctime);
X (void) splx (old_level);
X return;
X }
X
X fip->device_flags &= ~(DF_GUARD_TIMEOUT | DF_XMIT_BREAK);
X
X /* restart output */
X fas_xproc (fip);
X
X if ((fip->flow_flags & FF_OUTPUT_BUSY)
X && !fip->xmit_ring_cnt
X && !(fip->device_flags & DF_XMIT_BUSY))
X {
X fip->flow_flags &= ~FF_OUTPUT_BUSY;
X fip->tty->t_state &= ~BUSY;
X /* check half duplex output flow control */
X if ((fip->flow_flags & (FF_HDX_HANDSHAKE | FF_HDX_STARTED))
X == (FF_HDX_HANDSHAKE | FF_HDX_STARTED))
X {
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT,
X MCR &= ~fip->flow.m.hc);
X fip->flow_flags &= ~FF_HDX_STARTED;
X }
X EVENT_SCHED (fip, EF_DO_XXFER);
X }
X
X (void) wakeup ((caddr_t) &(fip)->device_flags);
X (void) splx (old_level);
X}
X
X/* Re-enable receiver data interrupts.
X (called at SPLINT)
X*/
XSTATIC void
Xfas_rdi_enable (fip)
Xregister struct fas_internals *fip REG_SI;
X{
X /* flush receiver register */
X if (DEVICE_TYPE == TYPE_NS16550A)
X FAS_FIRST_OUTB (fip, NS_FIFO_CTL_PORT, FCR | NS_FIFO_CLR_RECV);
X else if (DEVICE_TYPE == TYPE_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 (void) FAS_FIRST_INB (fip, RCV_DATA_PORT);
X if (FAS_INB (fip, LINE_STATUS_PORT) & LS_RCV_AVAIL)
X (void) FAS_INB (fip, RCV_DATA_PORT);
X
X FAS_OUTB (fip, INT_ENABLE_PORT, IER |= IE_RECV_DATA_AVAILABLE);
X fip->device_flags |= DF_RDI_ENABLED;
X}
X
X/* Start software input flow control.
X (called at SPLINT)
X*/
XSTATIC void
Xfas_send_xon (fip)
Xregister struct fas_internals *fip REG_SI;
X{
X fip->flow_flags &= ~FF_SWI_STOPPED;
X fip->flow_flags ^= FF_SW_FC_REQ;
X if (fip->flow_flags & FF_SW_FC_REQ)
X {
X if (fip->flow_flags & FF_CARRIER_ON)
X {
X /* start input */
X fip->flow_flags |= FF_OUTPUT_BUSY;
X fip->tty->t_state |= TTXON | BUSY;
X /* check half duplex output flow control */
X if ((fip->flow_flags & (FF_HDX_HANDSHAKE | FF_HDX_STARTED))
X == FF_HDX_HANDSHAKE)
X {
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT,
X MCR |= fip->flow.m.hc);
X fip->flow_flags |= FF_HDX_STARTED;
X }
X fas_xproc (fip);
X }
X else
X fip->flow_flags &= ~FF_SW_FC_REQ;
X }
X else
X {
X /* there is a yet unprocessed request for XOFF, so
X we just cancel it and don't need to send an XON
X */
X fip->tty->t_state &= ~TTXOFF;
X if ((fip->flow_flags & FF_OUTPUT_BUSY)
X && !fip->xmit_ring_cnt
X && !(fip->device_flags
X & (DF_XMIT_BUSY
X | DF_GUARD_TIMEOUT
X | DF_XMIT_BREAK)))
X {
X fip->flow_flags &= ~FF_OUTPUT_BUSY;
X fip->tty->t_state &= ~BUSY;
X /* check half duplex output flow control */
X if ((fip->flow_flags & (FF_HDX_HANDSHAKE
X | FF_HDX_STARTED))
X == (FF_HDX_HANDSHAKE | FF_HDX_STARTED))
X {
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT,
X MCR &= ~fip->flow.m.hc);
X fip->flow_flags &= ~FF_HDX_STARTED;
X }
X EVENT_SCHED (fip, EF_DO_XXFER);
X }
X }
X}
X
X/* Stop software input flow control.
X (called at SPLINT)
X*/
XSTATIC void
Xfas_send_xoff (fip)
Xregister struct fas_internals *fip REG_SI;
X{
X fip->flow_flags |= FF_SWI_STOPPED;
X fip->flow_flags ^= FF_SW_FC_REQ;
X if (fip->flow_flags & FF_SW_FC_REQ)
X {
X if (fip->flow_flags & FF_CARRIER_ON)
X {
X /* stop input */
X fip->flow_flags |= FF_OUTPUT_BUSY;
X fip->tty->t_state |= TTXOFF | BUSY;
X /* check half duplex output flow control */
X if ((fip->flow_flags & (FF_HDX_HANDSHAKE | FF_HDX_STARTED))
X == FF_HDX_HANDSHAKE)
X {
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT,
X MCR |= fip->flow.m.hc);
X fip->flow_flags |= FF_HDX_STARTED;
X }
X fas_xproc (fip);
X }
X else
X fip->flow_flags &= ~FF_SW_FC_REQ;
X }
X else
X {
X /* there is a yet unprocessed request for XON, so
X we just cancel it and don't need to send an XOFF
X */
X fip->tty->t_state &= ~TTXON;
X if ((fip->flow_flags & FF_OUTPUT_BUSY)
X && !fip->xmit_ring_cnt
X && !(fip->device_flags
X & (DF_XMIT_BUSY
X | DF_GUARD_TIMEOUT
X | DF_XMIT_BREAK)))
X {
X fip->flow_flags &= ~FF_OUTPUT_BUSY;
X fip->tty->t_state &= ~BUSY;
X /* check half duplex output flow control */
X if ((fip->flow_flags & (FF_HDX_HANDSHAKE
X | FF_HDX_STARTED))
X == (FF_HDX_HANDSHAKE | FF_HDX_STARTED))
X {
X FAS_FIRST_OUTB (fip, MDM_CTL_PORT,
X MCR &= ~fip->flow.m.hc);
X fip->flow_flags &= ~FF_HDX_STARTED;
X }
X EVENT_SCHED (fip, EF_DO_XXFER);
X }
X }
X}
X
X/* Compute the port access control value. */
XSTATIC uint
Xfas_make_ctl_val (fip, unit, num)
Xregister struct fas_internals *fip REG_SI;
Xuint unit;
Xuint num;
X{
X register uint val REG_DI;
X register uint mask REG_BX;
X uint i;
X
X if (fip->device_flags & DF_CTL_FIRST)
X return (fas_ctl_val [unit]);
X
X if (fip->device_flags & DF_CTL_EVERY)
X {
X for (i = 8, mask = fas_ctl_val [unit],
X val = fas_ctl_val [unit] << 8; i; --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/* Initialize memory with zeros. */
XSTATIC void
Xfas_mem_zero (ptr, size)
Xregister unchar *ptr REG_SI;
Xuint size;
X{
X register unchar *limptr REG_DI;
X
X for (limptr = ptr + size; ptr < limptr; ++ptr)
X *ptr = 0;
X}
X
X/* Test device thoroughly. */
XSTATIC uint
Xfas_test_device (fip)
Xregister struct fas_internals *fip REG_SI;
X{
X register unchar *cptr REG_DI;
X uint baud_rate, test_rate;
X ulong max_rate;
X uint errcode;
X register uint delay_count REG_BX;
X uint rep_count, i;
X n_unchar lsr, msr;
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
X /* find fastest baud rate for this port */
X max_rate = 0L;
X for (test_rate = baud_rate = B0 + 1; baud_rate <= CBAUD; ++baud_rate)
X if (fas_baud_ptr [BT_SELECT] [baud_rate] > max_rate)
X {
X max_rate = fas_baud_ptr [BT_SELECT] [baud_rate];
X test_rate = baud_rate;
X }
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_speed_ptr [BT_SELECT]
X [test_rate].div.b.low);
X FAS_OUTB (fip, DIVISOR_MSB_PORT, fas_speed_ptr [BT_SELECT]
X [test_rate].div.b.high);
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 errcode = 0;
X
X /* wait until the transmitter register is empty */
X FAS_EVERY_CTL (fip, LINE_STATUS_PORT);
X for (delay_count = TEST_DELAY_LOOPS;
X delay_count && (~FAS_SAME_INB (fip, LINE_STATUS_PORT)
X & (LS_XMIT_AVAIL | LS_XMIT_COMPLETE));
X --delay_count)
X ;
X
X if (!delay_count)
X errcode = 1;
X
X if (!errcode)
X {
X /* clear flags */
X (void) FAS_INB (fip, RCV_DATA_PORT);
X (void) FAS_SAME_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 FAS_EVERY_CTL (fip, LINE_STATUS_PORT);
X for (delay_count = TEST_DELAY_LOOPS;
X delay_count && !(FAS_SAME_INB (fip, LINE_STATUS_PORT)
X & LS_RCV_AVAIL);
X --delay_count)
X ;
X
X if (delay_count)
X (void) FAS_INB (fip, RCV_DATA_PORT);
X
X for (rep_count = TEST_CHAR_LOOPS; rep_count; --rep_count)
X {
X for (i = 0; i < 3; ++i)
X {
X /* test pattern */
X cptr = (unchar *) "\377\125\252\045\244\0\0";
X
X /* check LSR flags */
X if (FAS_INB (fip, LINE_STATUS_PORT)
X != (LS_XMIT_AVAIL | LS_XMIT_COMPLETE))
X {
X errcode = 2;
X break;
X }
X
X /* test transmitter and receiver
X with different line settings
X */
X FAS_OUTB (fip, LINE_CTL_PORT, lcrval [i]);
X
X /* send first test pattern */
X FAS_OUTB (fip, XMT_DATA_PORT, *cptr);
X
X /* wait until the transmitter holding register
X is empty
X */
X FAS_EVERY_CTL (fip, LINE_STATUS_PORT);
X for (delay_count = TEST_DELAY_LOOPS;
X delay_count
X && !((lsr = FAS_SAME_INB (fip,
X LINE_STATUS_PORT))
X & LS_XMIT_AVAIL);
X --delay_count)
X ;
X
X if (!delay_count)
X {
X errcode = 3;
X break;
X }
X
X /* check LSR flags */
X if (lsr != LS_XMIT_AVAIL)
X {
X errcode = 2;
X break;
X }
X
X do
X {
X if (*cptr)
X {
X /* send next test pattern */
X FAS_OUTB (fip, XMT_DATA_PORT, *(cptr + 1));
X
X /* check LSR flags */
X if (FAS_INB (fip, LINE_STATUS_PORT))
X {
X errcode = 2;
X break;
X }
X }
X
X /* wait until the test pattern is received */
X FAS_EVERY_CTL (fip, LINE_STATUS_PORT);
X for (delay_count = TEST_DELAY_LOOPS;
X delay_count
X && !((lsr = FAS_SAME_INB (fip,
X LINE_STATUS_PORT))
X & LS_RCV_AVAIL);
X --delay_count)
X ;
X
X if (!delay_count)
X {
X errcode = 4;
X break;
X }
X
X /* check LSR flags */
X if ((lsr & LS_RCV_INT) != LS_RCV_AVAIL)
X {
X errcode = 5;
X break;
X }
X
X /* check test pattern */
X if (FAS_INB (fip, RCV_DATA_PORT) != *cptr)
X {
X errcode = 6;
X break;
X }
X
X /* check LSR flags */
X if (FAS_INB (fip, LINE_STATUS_PORT)
X & LS_RCV_INT)
X {
X errcode = 5;
X break;
X }
X
X /* wait until the transmitter register
X is empty
X */
X if (*cptr)
X {
X FAS_EVERY_CTL (fip, LINE_STATUS_PORT);
X for (delay_count = TEST_DELAY_LOOPS;
X delay_count
X && !((lsr = FAS_SAME_INB (fip,
X LINE_STATUS_PORT))
X & LS_XMIT_AVAIL);
X --delay_count)
X ;
X
X if (!delay_count)
X {
X errcode = 7;
X break;
X }
X
X /* check LSR flags */
X if (lsr != LS_XMIT_AVAIL)
X {
X errcode = 8;
X break;
X }
X }
X else
X {
X FAS_EVERY_CTL (fip, LINE_STATUS_PORT);
X for (delay_count = TEST_DELAY_LOOPS;
X delay_count
X && !((lsr = FAS_SAME_INB (fip,
X LINE_STATUS_PORT))
X & LS_XMIT_COMPLETE);
X --delay_count)
X ;
X
X if (!delay_count)
X {
X errcode = 7;
X break;
X }
X
X /* check LSR flags */
X if (lsr != (LS_XMIT_AVAIL
X | LS_XMIT_COMPLETE))
X {
X errcode = 8;
X break;
X }
X }
X } while (*((ushort *) (cptr++)));
X
X if (errcode)
X break;
X }
X
X if (errcode)
X break;
X }
X }
X
X if (!errcode)
X {
X /* clear delta bits */
X (void) FAS_INB (fip, MDM_STATUS_PORT);
X
X for (rep_count = TEST_CTL_LOOPS; rep_count; --rep_count)
X {
X /* test pattern */
X cptr = (unchar *) "\005\142\012\237\006\130\011\257\017\361\0\017\0\0";
X
X for (; *((ushort *) cptr); cptr += 2)
X {
X /* test modem control and status lines */
X FAS_OUTB (fip, MDM_CTL_PORT, *cptr | MC_SET_LOOPBACK);
X
X /* wait for delta flags */
X FAS_EVERY_CTL (fip, MDM_STATUS_PORT);
X for (delay_count = TEST_DELAY_LOOPS;
X delay_count
X && !((msr = FAS_SAME_INB (fip,
X MDM_STATUS_PORT))
X & MS_ANY_DELTA);
X --delay_count)
X ;
X
X if (!delay_count)
X {
X errcode = 9;
X break;
X }
X
X /* check MSR flags */
X if (msr != *(cptr + 1))
X {
X errcode = 9;
X break;
X }
X
X /* check whether delta flags are cleared */
X if (FAS_SAME_INB (fip, MDM_STATUS_PORT)
X != (msr & ~MS_ANY_DELTA))
X {
X errcode = 9;
X break;
X }
X }
X
X if (errcode)
X break;
X }
X }
X
X /* switch back to normal operation */
X FAS_OUTB (fip, MDM_CTL_PORT, 0);
X
X return (errcode);
X}
X
X#if defined (NEED_PUT_GETCHAR)
Xint
XFASPUTCHAR (arg)
Xunchar arg;
X{
X register struct fas_internals *fip REG_SI;
X
X if (!fas_is_initted)
X fasinit ();
X
X fip = &fas_internals [0];
X if (fip->device_flags & DF_DEVICE_CONFIGURED)
X {
X if (arg == '\n')
X (void) FASPUTCHAR ('\r');
X FAS_CTL (fip, LINE_STATUS_PORT);
X while (!(FAS_SAME_INB (fip, LINE_STATUS_PORT) & LS_XMIT_AVAIL))
X ;
X FAS_OUTB (fip, XMT_DATA_PORT, arg);
X }
X return (0);
X}
X
Xint
XFASGETCHAR ()
X{
X register struct fas_internals *fip REG_SI;
X
X if (!fas_is_initted)
X fasinit ();
X
X fip = &fas_internals [0];
X if ((fip->device_flags & 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/* Reset the requested port to be used directly by a DOS process.
X (DosMerge only)
X*/
Xint
Xinit8250 (port, ier)
Xregister ushort port REG_BX;
Xushort ier; /* ier not used in this stub */
X{
X register struct fas_internals *fip REG_SI;
X register uint unit REG_DI;
X int old_level;
X
X /* See if the port address matches a port that is used by
X the FAS driver.
X */
X for (unit = 0; unit < fas_physical_units; ++unit)
X if (port == fas_port [unit])
X break;
X
X if (unit >= fas_physical_units)
X return (-1); /* port didn't match */
X
X fip = fas_internals_ptr [unit];
X
X old_level = SPLINT ();
X
X FAS_FIRST_OUTB (fip, INT_ENABLE_PORT, IER = IE_NONE);
X fip->device_flags &= ~(DF_RDI_ENABLED | DF_MSI_ENABLED | DF_MSI_NOISE);
X
X FAS_OUTB (fip, MDM_CTL_PORT, MCR &= ~(fip->flow.m.ic | fip->flow.m.hc));
X
X if (DEVICE_TYPE == TYPE_NS16550A)
X FAS_OUTB (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
X else if (DEVICE_TYPE == TYPE_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 if (FAS_INB (fip, LINE_STATUS_PORT) & LS_RCV_AVAIL)
X (void) FAS_INB (fip, RCV_DATA_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.11"
X#endif
X
X/* Uncomment the following line if you need (asy|sio)putchar and
X (asy|sio)getchar. This is only required if you link the kernel
X without the original asy or sio driver and these functions aren't
X provided by any other kernel 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 there is a tunable `ttyhog' variable
X in the kernel.
X*/
X#define TUNABLE_TTYHOG /* */
X
X/* Uncomment the following line if you want FAS to make sure that the
X thresholds in tthiwat [] and ttlowat [] are high enough to prevent
X the CLIST buffer functions to become a bottleneck at high baud rates.
X tthiwat [] and ttlowat [] are global resources and are used by other
X tty drivers as well, so in case that fixing these values causes
X problems with these drivers this feature is configurable.
X*/
X#define FIX_TTHILOWAT /* */
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 or sio driver.
X*/
X/* #define NEED_INIT8250 /* */
X
X/* Initial line control register. This value will only be meaningful if
X NEED_PUT_GETCHAR is defined.
X*/
X#define INITIAL_LINE_CONTROL LC_WORDLEN_8
X
X/* Initial baud rate. This value will only be meaningful if
X NEED_PUT_GETCHAR is defined.
X*/
X#define INITIAL_BAUD_RATE B9600
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 if 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/* The following section is, if necessary, automatically updated with
X OS dependent informations. Don't change it by hand!
X*/
X/* @@OS_DEP_BEGIN@@ */
X/* @@OS_DEP_END@@ */
X
X#if defined (VPIX)
X#undef VPIX
X#endif
X
X#if defined (HAVE_VPIX)
X#define VPIX
X#endif
X
X#if defined (SCO) && !defined (_NO_PROTOTYPE)
X#define _NO_PROTOTYPE 1
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#if defined (SCO) || defined (XENIX)
X#include <sys/select.h>
X#endif
X#include <sys/ioctl.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 (__GNUC__)
X/* in expressions GNU C is able to use operand sizes < native integer size */
Xtypedef unchar n_unchar;
X#else
X/* in expressions AT&T C extends smaller types to the native integer size */
Xtypedef uint n_unchar;
X#endif
X
X/* allow function prototypes in ANSI C */
X#if defined (__STDC__)
X#define P(x) x
X#else
X#define P(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
Xtypedef int bool;
X
X#define MAX_UNITS 16 /* max. number of physical units */
X#define MAX_BAUD_TABLES 256 /* max. number of baud rate tables */
X#define NUM_UART_REGS 7 /* number of UART registers */
X
X/* Miscellaneous Constants */
X
X#define HANGUP_DELAY 500 /* in milli-seconds */
X#define HANGUP_TIME 1000 /* in milli-seconds */
X#define BREAK_TIME 250 /* in milli-seconds */
X#define MAX_EVENT_TIME 10 /* in milli-seconds */
X#define MAX_RXFER_DELAY 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 10000 /* receiver ring buffer size (MAX) */
X#define SW_LOW_WATER 5000 /* 50% MAX sw flow control */
X#define SW_HIGH_WATER 8000 /* 80% MAX trigger levels */
X#define HW_LOW_WATER 8500 /* MAX - 1500 hw flow control */
X#define HW_HIGH_WATER 9500 /* MAX - 500 trigger levels */
X#define XMIT_BUFF_SIZE 10000 /* transmitter ring buffer size */
X#endif
X#define SOFT_INIT 0 /* init registers if cflag changed */
X#define HARD_INIT 1 /* init registers w/o checking cflag */
X#define TEST_CHAR_LOOPS 100 /* no. of character test loops */
X#define TEST_CTL_LOOPS 1000 /* no. of control line test loops */
X#define TEST_DELAY_LOOPS 60000 /* no. of delay loops */
X#if defined (SCO) || 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/* calculate EVENT_TIME from MAX_EVENT_TIME with regard to the
X clock tick granularity
X*/
X#define EVENT_TIME ((((MAX_EVENT_TIME) * (HZ) / 1000)\
X * 1000 + (HZ) - 1) / (HZ))
X#if EVENT_TIME == 0
X#undef EVENT_TIME
X#define EVENT_TIME ((1000 + (HZ) - 1) / (HZ))
X#endif
X
X#if MAX_RXFER_DELAY < EVENT_TIME
X#undef MAX_RXFER_DELAY
X#define MAX_RXFER_DELAY EVENT_TIME
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 ((ulong) MC_SET_RTS)
X#define DI_DTR ((ulong) MC_SET_DTR)
X#define DI_RTS_AND_DTR ((ulong) (MC_SET_RTS | MC_SET_DTR))
X
X/* modem enable for dialout (choose one) */
X#define EO_RTS ((ulong) MC_SET_RTS << 8)
X#define EO_DTR ((ulong) MC_SET_DTR << 8)
X#define EO_RTS_AND_DTR ((ulong) (MC_SET_RTS | MC_SET_DTR) << 8)
X
X/* modem enable for dialin (choose one) */
X#define EI_RTS ((ulong) MC_SET_RTS << 16)
X#define EI_DTR ((ulong) MC_SET_DTR << 16)
X#define EI_RTS_AND_DTR ((ulong) (MC_SET_RTS | MC_SET_DTR) << 16)
X
X/* carrier detect signal (choose one) */
X#define CA_DCD ((ulong) MS_DCD_PRESENT << 24)
X#define CA_CTS ((ulong) MS_CTS_PRESENT << 24)
X#define CA_DSR ((ulong) MS_DSR_PRESENT << 24)
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 ((ulong) MC_SET_RTS)
X#define HI_DTR ((ulong) MC_SET_DTR)
X#define HI_RTS_AND_DTR ((ulong) (MC_SET_RTS | MC_SET_DTR))
X
X/* output flow control (choose one) */
X#define HO_CTS ((ulong) MS_CTS_PRESENT << 8)
X#define HO_DSR ((ulong) MS_DSR_PRESENT << 8)
X#define HO_CTS_AND_DSR ((ulong) (MS_CTS_PRESENT | MS_DSR_PRESENT) \
X << 8)
X#define HO_CTS_ON_DSR (((ulong) MS_CTS_PRESENT << 8) \
X | ((ulong) MS_DSR_PRESENT << 16))
X#define HO_CTS_ON_DSR_AND_DCD (((ulong) MS_CTS_PRESENT << 8) \
X | ((ulong) (MS_DSR_PRESENT | MS_DCD_PRESENT) \
X << 16))
X
X/* output hdx flow control (choose one) */
X#define HX_RTS ((ulong) MC_SET_RTS << 24)
X#define HX_DTR ((ulong) MC_SET_DTR << 24)
X#define HX_RTS_AND_DTR ((ulong) (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_DIALIN 0x0002
X#define OS_WAIT_OPEN 0x0004
X#define OS_NO_DIALOUT 0x0008
X#define OS_FAKE_CARRIER_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_DIALIN)
X#define OS_TEST_MASK (OS_OPEN_FOR_DIALOUT | OS_NO_DIALOUT \
X | OS_FAKE_CARRIER_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_CARRIER_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_CTL_FIRST 0x0001 /* write ctl port at first access */
X#define DF_CTL_EVERY 0x0002 /* write ctl port at every access */
X#define DF_XMIT_BUSY 0x0004 /* transmitter busy */
X#define DF_XMIT_BREAK 0x0008 /* transmitter sends break */
X#define DF_XMIT_LOCKED 0x0010 /* transmitter locked against output */
X#define DF_GUARD_TIMEOUT 0x0020 /* protect last char from corruption */
X#define DF_MSI_NOISE 0x0040 /* modem status interrupts noise */
X#define DF_MSI_ENABLED 0x0080 /* modem status interrupts enabled */
X#define DF_RDI_ENABLED 0x0100 /* receiver data interrupts enabled */
X#define DF_HUP_PROTECT 0x0200 /* protect device after hangup */
X#define DF_NO_OVERRUN 0x0400 /* device is overrun protected */
X#define DF_DEVICE_CONFIGURED 0x0800 /* device is configured */
X#define DF_DEVICE_OPEN 0x1000 /* physical device is open */
X#define DF_DEVICE_LOCKED 0x2000 /* physical device locked */
X#define DF_DO_HANGUP 0x4000 /* delayed hangup request */
X#define DF_DO_BREAK 0x8000 /* delayed break request */
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_STARTED 0x0010 /* input started by hw handshake */
X#define FF_HDX_STARTED 0x0020 /* output buffer contains characters */
X#define FF_CARR_STOPPED 0x0040 /* output stopped by carrier detect */
X#define FF_SWO_STOPPED 0x0080 /* output stopped by sw flow control */
X#define FF_SWI_STOPPED 0x0100 /* input stopped by sw flow control */
X#define FF_SW_FC_REQ 0x0200 /* sw input flow control request */
X#define FF_RXFER_STOPPED 0x0400 /* rxfer function stopped */
X#define FF_NEW_CTSRTS 0x0800 /* CTS/RTSFLOW do fdx hw handshake */
X#define FF_DEF_HHO_LOW 0x1000 /* hw handshake outp. is low by deflt */
X#define FF_OUTPUT_BUSY 0x2000 /* output buffers/circuits are busy */
X#define FF_CD_ENABLED 0x4000 /* carrier detect enabled */
X#define FF_CARRIER_ON 0x8000 /* carrier detect */
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_RESET_DELTA_BITS 0x0010 /* reset accumulated msr delta bits */
X#define EF_WAKEUP_VPIX 0x0020 /* wakeup VP/ix until rawq is empty */
X
X/* define the device types
X The symbolic constant for the device type that allows the lowest interrupt
X latency (usually a 16450) has the lowest numerical value. Devices that
X allow a higher interrupt latency have a higher numerical value. With this
X ordering the device type can be used as a priority indicator during the
X interrupt processing, that is, devices that can't hold the received
X characters for very long are serviced first while devices with FIFOs
X are serviced only after all devices with higher priority are done.
X Usually, the following rule applies: The longer the FIFOs, the higher
X the assigned device type value should be, and the lower the interrupt
X priority will be.
X*/
X
X#define NUMBER_OF_TYPES 3 /* adjust this to the highest */
X /* device type + 1 */
X#define TYPE_NS16450 0
X#define TYPE_I82510 1
X#define TYPE_NS16550A 2
X
X/* modifier flags that can be set in fas_modify [] (`space.c') */
X
X#define NO_TEST 0x0001 /* don't test the UART */
X#define NO_HUP_PROTECT 0x0002 /* don't protect device after hangup */
X#define NO_OVERRUN 0x0004 /* device is overrun protected */
X#define NEW_CTSRTS 0x0008 /* CTS/RTSFLOW do fdx hw handshake */
X
X/* read from port rather than write to it (for fas_init_seq [] and
X fas_int_ack_seq [] in `space.c')
X*/
X
X#define READ_PORT 0x0100
X
X/* define the FIFO operating modes for the fas_fifo_ctl array in space.c
X (FIFO_POINTER_DEV and FIFO_TRIGGER_* apply to NS16550A UART, only)
X*/
X
X#define FIFO_DEFAULT 0 /* default mode (OS dependent) */
X#define FIFO_OFF 1 /* 16450 compatible mode */
X#define FIFO_EMUL_NS16450 2 /* emulate 16450 in FIFO mode */
X#define FIFO_POINTER_DEV 3 /* pointer device (mouse etc.) */
X#define FIFO_TRIGGER_1 4 /* set trigger level to 1 char */
X#define FIFO_TRIGGER_4 5 /* set trigger level to 4 chars */
X#define FIFO_TRIGGER_8 6 /* set trigger level to 8 chars */
X#define FIFO_TRIGGER_14 7 /* set trigger level to 14 chars */
X
X/* define an easy way to reference the port structures */
X
X#define RCV_DATA_PORT (fip->port [0])
X#define XMT_DATA_PORT (fip->port [0])
X#define INT_ENABLE_PORT (fip->port [1])
X#define INT_ID_PORT (fip->port [2])
X#define NS_FIFO_CTL_PORT (fip->port [2])
X#define I_BANK_PORT (fip->port [2])
X#define LINE_CTL_PORT (fip->port [3])
X#define MDM_CTL_PORT (fip->port [4])
X#define I_IDM_PORT (fip->port [4])
X#define LINE_STATUS_PORT (fip->port [5])
X#define I_RCM_PORT (fip->port [5])
X#define MDM_STATUS_PORT (fip->port [6])
X#define I_TCM_PORT (fip->port [6])
X#define DIVISOR_LSB_PORT (fip->port [0])
X#define DIVISOR_MSB_PORT (fip->port [1])
X#define CTL_PORT (fip->ctl_port)
X
X/* UART related variables */
X
X#define BT_SELECT (fip->port [0].p.val)
X#define IER (fip->port [1].p.val)
X#define FCR (fip->port [2].p.val)
X#define LCR (fip->port [3].p.val)
X#define MCR (fip->port [4].p.val)
X#define NEW_MSR (fip->port [5].p.val)
X#define MSR (fip->port [6].p.val)
X#define DEVICE_TYPE (fip->ctl_port.p.val1)
X#define INT_PRIO (fip->ctl_port.p.val2)
X
X/* modem control port */
X
X#define MC_SET_DTR 0x01
X#define MC_SET_RTS 0x02
X#define MC_SET_OUT1 0x04
X#define MC_SET_OUT2 0x08
X#define MC_SET_LOOPBACK 0x10
X
X#define MC_ANY_CONTROL (MC_SET_DTR | MC_SET_RTS | MC_SET_OUT1 | MC_SET_OUT2)
X
X/* modem status port */
X
X#define MS_CTS_DELTA 0x01
X#define MS_DSR_DELTA 0x02
X#define MS_RING_TEDGE 0x04
X#define MS_DCD_DELTA 0x08
X#define MS_CTS_PRESENT 0x10
X#define MS_DSR_PRESENT 0x20
X#define MS_RING_PRESENT 0x40
X#define MS_DCD_PRESENT 0x80
X
X#define MS_ANY_DELTA (MS_CTS_DELTA | MS_DSR_DELTA | MS_RING_TEDGE \
X | MS_DCD_DELTA)
X#define MS_ANY_PRESENT (MS_CTS_PRESENT | MS_DSR_PRESENT | MS_RING_PRESENT \
X | MS_DCD_PRESENT)
X
X/* interrupt enable port */
X
X#define IE_NONE 0x00
X#define IE_RECV_DATA_AVAILABLE 0x01
X#define IE_XMIT_HOLDING_BUFFER_EMPTY 0x02
X#define IE_LINE_STATUS 0x04
X#define IE_MODEM_STATUS 0x08
X
X/* interrupt id port */
X
X#define II_NO_INTS_PENDING 0x01
X#define II_CODE_MASK 0x07
X#define II_MODEM_STATE 0x00
X#define II_XMTD_CHAR 0x02
X#define II_RCVD_CHAR 0x04
X#define II_RCV_ERROR 0x06
X#define II_NS_FIFO_TIMEOUT 0x08
X#define II_NS_FIFO_ENABLED 0xC0
X
X/* line control port */
X
X#define LC_WORDLEN_MASK 0x03
X#define LC_WORDLEN_5 0x00
X#define LC_WORDLEN_6 0x01
X#define LC_WORDLEN_7 0x02
X#define LC_WORDLEN_8 0x03
X#define LC_STOPBITS_LONG 0x04
X#define LC_ENABLE_PARITY 0x08
X#define LC_EVEN_PARITY 0x10
X#define LC_STICK_PARITY 0x20
X#define LC_SET_BREAK_LEVEL 0x40
X#define LC_ENABLE_DIVISOR 0x80
X
X/* line status port */
X
X#define LS_RCV_AVAIL 0x01
X#define LS_OVERRUN 0x02
X#define LS_PARITY_ERROR 0x04
X#define LS_FRAMING_ERROR 0x08
X#define LS_BREAK_DETECTED 0x10
X#define LS_XMIT_AVAIL 0x20
X#define LS_XMIT_COMPLETE 0x40
X#define LS_ERROR_IN_NS_FIFO 0x80 /* NS16550A only */
X
X#define LS_RCV_INT (LS_RCV_AVAIL | LS_OVERRUN | LS_PARITY_ERROR \
X | LS_FRAMING_ERROR | LS_BREAK_DETECTED)
X
X/* fifo control port (NS16550A only) */
X
X#define NS_FIFO_ENABLE 0x01
X#define NS_FIFO_CLR_RECV 0x02
X#define NS_FIFO_CLR_XMIT 0x04
X#define NS_FIFO_START_DMA 0x08
X#define NS_FIFO_SIZE_1 0x00
X#define NS_FIFO_SIZE_4 0x40
X#define NS_FIFO_SIZE_8 0x80
X#define NS_FIFO_SIZE_14 0xC0
X#define NS_FIFO_SIZE_MASK 0xC0
X
X#define NS_FIFO_CLEAR_CMD 0
X#define NS_FIFO_INIT_CMD (NS_FIFO_SIZE_1 | NS_FIFO_ENABLE \
X | NS_FIFO_CLR_RECV | NS_FIFO_CLR_XMIT)
X
X#define INPUT_NS_FIFO_SIZE 16
X#define OUTPUT_NS_FIFO_SIZE 16
X
X/* fifo control ports (i82510 only) */
X
X#define I_BANK_0 0x00
X#define I_BANK_1 0x20
X#define I_BANK_2 0x40
X#define I_BANK_3 0x60
X#define I_FIFO_ENABLE 0x08
X#define I_FIFO_CLR_RECV 0x30
X#define I_FIFO_CLR_XMIT 0x0c
X
X#define I_FIFO_CLEAR_CMD 0
X#define I_FIFO_SETUP_CMD I_FIFO_ENABLE
X
X#define INPUT_I_FIFO_SIZE 4
X#define OUTPUT_I_FIFO_SIZE 4
X
X/* defines for ioctl calls (VP/ix) */
X
X#define AIOC ('A'<<8)
X#define AIOCINTTYPE (AIOC|60) /* set interrupt type */
X#define AIOCDOSMODE (AIOC|61) /* set DOS mode */
X#define AIOCNONDOSMODE (AIOC|62) /* reset DOS mode */
X#define AIOCSERIALOUT (AIOC|63) /* serial device data write */
X#define AIOCSERIALIN (AIOC|64) /* serial device data read */
X#define AIOCSETSS (AIOC|65) /* set start/stop chars */
X#define AIOCINFO (AIOC|66) /* tell us what device we are */
X
X/* ioctl alternate names used by VP/ix */
X
X#define VPC_SERIAL_DOS AIOCDOSMODE
X#define VPC_SERIAL_NONDOS AIOCNONDOSMODE
X#define VPC_SERIAL_INFO AIOCINFO
X#define VPC_SERIAL_OUT AIOCSERIALOUT
X#define VPC_SERIAL_IN AIOCSERIALIN
X
X/* serial in/out requests */
X
X#define SO_DIVLLSB 1
X#define SO_DIVLMSB 2
X#define SO_LCR 3
X#define SO_MCR 4
X#define SI_MSR 1
X#define SIO_MASK(x) (1<<((x)-1))
X
X
X/* This structure contains baud rate dependent informations. */
X
Xstruct fas_speed
X{
X union {
X uint ctime; /* kernel clock ticks until xmitter is empty */
X bool valid; /* the baud rate table contains valid data */
X } i;
X union { /* UART counter divisor value */
X struct {
X unchar low; /* low byte */
X unchar high; /* high byte */
X } b;
X ushort val;
X } div;
X ushort xbuf_size; /* xmit buffer size that fits the baud rate */
X};
X
X
X/* This structure contains everything one would like to know about
X an open device. There is one of it for each physical unit.
X
X Take care that the size of the area that contains the various
X structure fields (up to, but excluding the ring buffers)
X is <= 128 bytes. Otherwise a 4-byte offset is used to access
X some of the structure fields. For the first 128 bytes a 1-byte
X offset is used, which is faster.
X*/
X
Xstruct fas_internals
X{
X struct tty *tty; /* the tty structure */
X struct fas_internals *next_int_user; /* link to next struct */
X struct fas_internals *prev_int_user; /* link to previous struct */
X uint device_flags; /* flags about the device state */
SHAR_EOF
true || echo 'restore of fas.h failed'
fi
echo 'End of part 6'
echo 'File fas.h is continued in part 7'
echo 7 > _shar_seq_.tmp
exit 0