Sync the public source with what I'm currently running.

Most of this is cleaning up, but there are some functional changes,
doc/comment improvements, error checking, gcc -Wall cleanups.  Input buffer
flushing is enabled now, although I'm still not quite certain it's right.
This commit is contained in:
Peter Wemm 1995-11-09 21:53:48 +00:00
parent fd24fbdf21
commit 5d0bad8280
4 changed files with 420 additions and 300 deletions

View File

@ -30,7 +30,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHORS BE LIABLE.
*
* $Id: si.c,v 1.12 1995/11/04 13:23:40 bde Exp $
* $Id: si.c,v 1.13 1995/11/04 17:07:47 bde Exp $
*/
#ifndef lint
@ -39,8 +39,6 @@ static char si_copyright1[] = "@(#) (C) Specialix International, 1990,1992",
si_copyright3[] = "@(#) (C) Peter Wemm 1995";
#endif /* not lint */
#define SI_DEBUG /* turn driver debugging on */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
@ -78,8 +76,9 @@ static char si_copyright1[] = "@(#) (C) Specialix International, 1990,1992",
*/
#define POLL /* turn on poller to generate buffer empty interrupt */
#undef FASTPOLL /* turn on 100Hz poller, (XXX: NOTYET!) */
#define SI_DEF_HWFLOW /* turn on default CRTSCTS flow control */
#define SI_I_HIGH_WATER (TTYHOG - SLXOS_BUFFERSIZE)
#define SI_I_HIGH_WATER (TTYHOG - 2 * SLXOS_BUFFERSIZE)
enum si_mctl { GET, SET, BIS, BIC };
@ -101,8 +100,9 @@ extern int siprobe __P((struct isa_device *id));
extern int siattach __P((struct isa_device *id));
static void si_modem_state __P((struct si_port *pp, struct tty *tp, int hi_ip));
#ifdef SI_DEBUG
static void si_dprintf __P((/* XXX should be varargs struct si_port *pp, int flags, char *str, int a1, int a2, int a3, int a4, int a5, int a6 */));
#ifdef SI_DEBUG /* use: ``options "SI_DEBUG"'' in your config file */
/* XXX: should be varargs, I know.. but where's vprintf()? */
static void si_dprintf __P((/* struct si_port *pp, int flags, char *str, int a1, int a2, int a3, int a4, int a5, int a6 */));
static char *si_mctl2str __P((enum si_mctl cmd));
#define DPRINT(x) si_dprintf x
#else
@ -115,7 +115,7 @@ static int si_debug = 0; /* data, not bss, so it's patchable */
static struct tty *si_tty;
/* where the firmware lives */
/* where the firmware lives; defined in si_code.c */
extern int si_dsize;
extern unsigned char si_download[];
@ -135,7 +135,7 @@ struct si_softc {
};
struct si_softc si_softc[NSI]; /* up to 4 elements */
#ifndef B2000 /* not standard */
#ifndef B2000 /* not standard, but the hardware knows it. */
# define B2000 2000
#endif
static struct speedtab bdrates[] = {
@ -192,6 +192,7 @@ static int si_default_cflag = TTYDEF_CFLAG;
#ifdef POLL
#define POLL_INTERVAL (hz/2)
static int init_finished = 0;
static int fastpoll = 0;
static void si_poll __P((void *));
#endif
@ -228,6 +229,7 @@ si_registerdev(id)
}
si_kdc[id->id_unit].kdc_unit = id->id_unit;
si_kdc[id->id_unit].kdc_isa = id;
si_kdc[id->id_unit].kdc_state = DC_UNCONFIGURED;
dev_attach(&si_kdc[id->id_unit]);
}
@ -257,8 +259,8 @@ siprobe(id)
*/
if ((caddr_t)paddr < (caddr_t)IOM_BEGIN ||
(caddr_t)paddr >= (caddr_t)IOM_END) {
printf("si%d: iomem (%x) out of range\n",
id->id_unit, paddr);
printf("si%d: iomem (%lx) out of range\n",
id->id_unit, (long)paddr);
return(0);
}
@ -375,7 +377,7 @@ got_card:
for (i=0; i<ramsize; i++, ux++) {
if ((was = *ux) != (BYTE)(i&0xff)) {
DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
"SLXOS si%d: match fail at phys 0x%x, was %x should be %x\n",
"si%d: match fail at phys 0x%x, was %x should be %x\n",
id->id_unit, paddr+i, was, i&0xff));
goto fail;
}
@ -389,7 +391,7 @@ got_card:
for (i=0; i<ramsize; i++) {
if ((was = *ux++) != 0) {
DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
"SLXOS si%d: clear fail at phys 0x%x, was %x\n",
"si%d: clear fail at phys 0x%x, was %x\n",
id->id_unit, paddr+i, was));
goto fail;
}
@ -446,6 +448,7 @@ siattach(id)
struct tty *tp;
struct speedtab *spt;
int nmodule, nport, x, y;
int uart_type;
DPRINT((0, DBG_AUTOBOOT, "SLXOS siattach\n"));
@ -474,8 +477,10 @@ siattach(id)
break;
#endif /* fall-through if not EISA */
case SI2:
/* must get around to writing the code for
* these one day */
/*
* must get around to converting the code for
* these one day, if FreeBSD ever supports it.
*/
return 0;
case SIHOST:
*(maddr+SIRESET_CL) = 0;
@ -509,10 +514,10 @@ siattach(id)
switch (regp->initstat) {
case 0:
printf("si%d: startup timeout - aborting\n", unit);
sc->sc_type = NULL;
sc->sc_type = SIEMPTY;
return 0;
case 1:
/* set throttle to 100 intr per second */
/* set throttle to 125 intr per second */
regp->int_count = 25000;
/* rx intr max of 25 timer per second */
regp->rx_int_count = 4;
@ -539,12 +544,12 @@ siattach(id)
nport = 0;
modp = (struct si_module *)(maddr + 0x80);
for (;;) {
DPRINT((0, DBG_DOWNLOAD, "SLXOS si%d: ccb addr 0x%x\n", unit, modp));
DPRINT((0, DBG_DOWNLOAD, "si%d: ccb addr 0x%x\n", unit, modp));
switch (modp->sm_type & (~MMASK)) {
case M232:
case M422:
DPRINT((0, DBG_DOWNLOAD,
"SLXOS si%d: Found 232/422 module, %d ports\n",
"si%d: Found 232/422 module, %d ports\n",
unit, (int)(modp->sm_type & MMASK)));
/* this is a firmware issue */
@ -597,6 +602,7 @@ mem_fail:
pp = sc->sc_ports;
nmodule = 0;
modp = (struct si_module *)(maddr + 0x80);
uart_type = 0;
for (;;) {
switch (modp->sm_type & (~MMASK)) {
case M232:
@ -604,11 +610,12 @@ mem_fail:
nmodule++;
nport = (modp->sm_type & MMASK);
ccbp = (struct si_channel *)((char *)modp+0x100);
if (uart_type == 0)
uart_type = ccbp->type;
for (x = 0; x < nport; x++, pp++, ccbp++) {
pp->sp_ccb = ccbp; /* save the address */
pp->sp_tty = tp++;
pp->sp_pend = IDLE_CLOSE;
pp->sp_flags = 0;
pp->sp_state = 0; /* internal flag */
pp->sp_dtr_wait = 3 * hz;
pp->sp_iin.c_iflag = si_default_iflag;
@ -625,11 +632,12 @@ mem_fail:
break;
}
if (modp->sm_next == 0) {
printf("si%d: card: %s, ports: %d, modules: %d\n",
printf("si%d: card: %s, ports: %d, modules: %d (type: %d)\n",
unit,
sc->sc_typename,
sc->sc_nport,
nmodule);
nmodule,
uart_type);
break;
}
modp = (struct si_module *)
@ -675,15 +683,15 @@ siopen(dev, flag, mode, p)
return (ENXIO);
sc = &si_softc[card];
if (sc->sc_type == NULL) {
DPRINT((0, DBG_OPEN|DBG_FAIL, "SLXOS si%d: type %s??\n",
if (sc->sc_type == SIEMPTY) {
DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: type %s??\n",
card, sc->sc_typename));
return(ENXIO);
}
port = SI_PORT(mynor);
if (port >= sc->sc_nport) {
DPRINT((0, DBG_OPEN|DBG_FAIL, "SLXOS si%d: nports %d\n",
DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: nports %d\n",
card, sc->sc_nport));
return(ENXIO);
}
@ -1246,7 +1254,7 @@ si_Sioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
sps = (struct si_pstat *)data;
card = dp->tc_card;
xsc = &si_softc[card]; /* check.. */
if (card < 0 || card >= NSI || xsc->sc_type == NULL) {
if (card < 0 || card >= NSI || xsc->sc_type == SIEMPTY) {
error = ENOENT;
goto out;
}
@ -1504,7 +1512,6 @@ siparam(tp, t)
ccbp->hi_mr1, ccbp->hi_mr2, ccbp->hi_mask, ccbp->hi_prtcl, ccbp->hi_break));
splx(oldspl);
out:
return(error);
}
@ -1610,6 +1617,9 @@ si_modem_state(pp, tp, hi_ip)
/*
* Poller to catch missed interrupts.
*
* Note that the SYSV SLXOS drivers poll at 100 times per second to get better
* response. We could really use a "periodic" version timeout(). :-)
*/
#ifdef POLL
static void
@ -1618,7 +1628,8 @@ si_poll(void *nothing)
register struct si_softc *sc;
register int i;
volatile struct si_reg *regp;
int lost, oldspl;
register struct si_port *pp;
int lost, oldspl, port;
DPRINT((0, DBG_POLL, "si_poll()\n"));
oldspl = spltty();
@ -1627,7 +1638,7 @@ si_poll(void *nothing)
lost = 0;
for (i=0; i<NSI; i++) {
sc = &si_softc[i];
if (sc->sc_type == NULL)
if (sc->sc_type == SIEMPTY)
continue;
regp = (struct si_reg *)sc->sc_maddr;
/*
@ -1638,13 +1649,24 @@ si_poll(void *nothing)
if (regp->int_pending != 0) {
if (regp->int_scounter >= 200 &&
regp->initstat == 1) {
printf("SLXOS si%d: lost intr\n", i);
printf("si%d: lost intr\n", i);
lost++;
}
} else {
regp->int_scounter = 0;
}
/*
* gripe about no input flow control..
*/
pp = sc->sc_ports;
for (port = 0; port < sc->sc_nport; pp++, port++) {
if (pp->sp_delta_overflows > 0) {
printf("si%d: %d tty level buffer overflows\n",
i, pp->sp_delta_overflows);
pp->sp_delta_overflows = 0;
}
}
}
if (lost)
siintr(-1); /* call intr with fake vector */
@ -1660,7 +1682,7 @@ out:
* it is called.
*/
static BYTE rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */
static BYTE si_rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */
void
siintr(int unit)
@ -1672,7 +1694,7 @@ siintr(int unit)
register struct tty *tp;
volatile caddr_t maddr;
BYTE op, ip;
int x, card, port, n, i;
int x, card, port, n, i, isopen;
volatile BYTE *z;
BYTE c;
@ -1680,7 +1702,7 @@ siintr(int unit)
if (in_intr) {
if (unit < 0) /* should never happen */
return;
printf("SLXOS si%d: Warning interrupt handler re-entered\n",
printf("si%d: Warning interrupt handler re-entered\n",
unit);
return;
}
@ -1693,8 +1715,12 @@ siintr(int unit)
*/
for (card=0; card < NSI; card++) {
sc = &si_softc[card];
if (sc->sc_type == NULL)
if (sc->sc_type == SIEMPTY)
continue;
/*
* First, clear the interrupt
*/
switch(sc->sc_type) {
case SIHOST :
maddr = sc->sc_maddr;
@ -1722,12 +1748,14 @@ siintr(int unit)
}
((volatile struct si_reg *)maddr)->int_scounter = 0;
for (pp = sc->sc_ports, port=0;
port < sc->sc_nport;
pp++, port++) {
/*
* check each port
*/
for (pp=sc->sc_ports,port=0; port < sc->sc_nport; pp++,port++) {
ccbp = pp->sp_ccb;
tp = pp->sp_tty;
/*
* See if a command has completed ?
*/
@ -1761,109 +1789,155 @@ siintr(int unit)
*/
si_modem_state(pp, tp, ccbp->hi_ip);
/*
* Check to see if there's we should 'receive'
* characters.
*/
if (tp->t_state & TS_CONNECTED &&
tp->t_state & TS_ISOPEN)
isopen = 1;
else
isopen = 0;
/*
* Do break processing
*/
if (ccbp->hi_state & ST_BREAK) {
if (tp->t_state & TS_CONNECTED &&
tp->t_state & TS_ISOPEN) {
(*linesw[tp->t_line].l_rint)(TTY_BI, tp);
if (isopen) {
(*linesw[tp->t_line].l_rint)(TTY_BI, tp);
}
ccbp->hi_state &= ~ST_BREAK; /* A Bit iffy this */
DPRINT((pp, DBG_INTR, "si_intr break\n"));
}
/*
* Do RX stuff - if not open then
* dump any characters.
* Do RX stuff - if not open then dump any characters.
* XXX: This is VERY messy and needs to be cleaned up.
*
* XXX: can we leave data in the host adapter buffer
* when the clists are full? That may be dangerous
* if the user cannot get an interrupt signal through.
*/
if ((tp->t_state & TS_CONNECTED) == 0 ||
(tp->t_state & TS_ISOPEN) == 0) {
more_rx: /* XXX Sorry. the nesting was driving me bats! :-( */
if (!isopen) {
ccbp->hi_rxopos = ccbp->hi_rxipos;
goto end_rx;
}
/*
* Process read characters if not skipped above
*/
c = ccbp->hi_rxipos - ccbp->hi_rxopos;
if (c == 0) {
goto end_rx;
}
op = ccbp->hi_rxopos;
ip = ccbp->hi_rxipos;
n = c & 0xff;
DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
n, op, ip));
/*
* Suck characters out of host card buffer into the
* "input staging buffer" - so that we dont leave the
* host card in limbo while we're possibly echoing
* characters and possibly flushing input inside the
* ldisc l_rint() routine.
*/
if (n <= SLXOS_BUFFERSIZE - op) {
DPRINT((pp, DBG_INTR, "\tsingle copy\n"));
z = ccbp->hi_rxbuf + op;
bcopy((caddr_t)z, si_rxbuf, n);
op += n;
} else {
while ((c = ccbp->hi_rxipos - ccbp->hi_rxopos) != 0) {
x = SLXOS_BUFFERSIZE - op;
op = ccbp->hi_rxopos;
ip = ccbp->hi_rxipos;
n = c & 0xff;
DPRINT((pp, DBG_INTR, "\tdouble part 1 %d\n", x));
z = ccbp->hi_rxbuf + op;
bcopy((caddr_t)z, si_rxbuf, x);
DPRINT((pp, DBG_INTR,
"n = %d, op = %d, ip = %d\n",
DPRINT((pp, DBG_INTR, "\tdouble part 2 %d\n", n-x));
z = ccbp->hi_rxbuf;
bcopy((caddr_t)z, si_rxbuf+x, n-x);
op += n;
}
/* clear collected characters from buffer */
ccbp->hi_rxopos = op;
DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
n, op, ip));
if (n <= SLXOS_BUFFERSIZE - op) {
DPRINT((pp, DBG_INTR,
"\tsingle copy\n"));
z = ccbp->hi_rxbuf + op;
bcopy((caddr_t)z, rxbuf, n);
/*
* at this point...
* n = number of chars placed in si_rxbuf
*/
op += n;
} else {
x = SLXOS_BUFFERSIZE - op;
/*
* Avoid the grotesquely inefficient lineswitch
* routine (ttyinput) in "raw" mode. It usually
* takes about 450 instructions (that's without
* canonical processing or echo!). slinput is
* reasonably fast (usually 40 instructions
* plus call overhead).
*/
if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
DPRINT((pp, DBG_INTR, "\tdouble part 1 %d\n", x));
z = ccbp->hi_rxbuf + op;
bcopy((caddr_t)z, rxbuf, x);
/* block if the driver supports it */
if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER
&& (tp->t_cflag & CRTS_IFLOW
|| tp->t_iflag & IXOFF)
&& !(tp->t_state & TS_TBLOCK))
ttyblock(tp);
DPRINT((pp, DBG_INTR, "\tdouble part 2 %d\n", n-x));
z = ccbp->hi_rxbuf;
bcopy((caddr_t)z, rxbuf+x, n-x);
tk_nin += n;
tk_rawcc += n;
tp->t_rawcc += n;
op += n;
pp->sp_delta_overflows +=
b_to_q((char *)si_rxbuf, n, &tp->t_rawq);
ttwakeup(tp);
if (tp->t_state & TS_TTSTOP
&& (tp->t_iflag & IXANY
|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
tp->t_state &= ~TS_TTSTOP;
tp->t_lflag &= ~FLUSHO;
si_start(tp);
}
} else {
/*
* It'd be nice to not have to go through the
* function call overhead for each char here.
* It'd be nice to block input it, saving a
* loop here and the call/return overhead.
*/
for(x = 0; x < n; x++) {
i = si_rxbuf[x];
if ((*linesw[tp->t_line].l_rint)(i, tp)
== -1) {
pp->sp_delta_overflows++;
}
ccbp->hi_rxopos = op;
DPRINT((pp, DBG_INTR,
"n = %d, op = %d, ip = %d\n",
n, op, ip));
/*
* at this point...
* n = number of chars placed in rxbuf
* doesn't seem to be much point doing
* this here.. this driver has no
* softtty processing! ??
*/
/*
* Avoid the grotesquely inefficient lineswitch routine
* (ttyinput) in "raw" mode. It usually takes about 450
* instructions (that's without canonical processing or echo!).
* slinput is reasonably fast (usually 40 instructions plus
* call overhead).
*/
if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
/* block if the driver supports it */
if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER
&& (tp->t_cflag & CRTS_IFLOW
|| tp->t_iflag & IXOFF)
&& !(tp->t_state & TS_TBLOCK))
ttyblock(tp);
tk_nin += n;
tk_rawcc += n;
tp->t_rawcc += n;
b_to_q((char *)rxbuf, n, &tp->t_rawq);
ttwakeup(tp);
if (tp->t_state & TS_TTSTOP
&& (tp->t_iflag & IXANY
|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
tp->t_state &= ~TS_TTSTOP;
tp->t_lflag &= ~FLUSHO;
si_start(tp);
}
} else {
for(x = 0; x < n; x++) {
i = rxbuf[x];
(*linesw[tp->t_line].l_rint)(rxbuf[x], tp);
if (pp->sp_hotchar && i == pp->sp_hotchar) {
setsofttty();
}
}
if (pp->sp_hotchar && i == pp->sp_hotchar) {
setsofttty();
}
}
}
goto more_rx; /* try for more until RXbuf is empty */
} /* end of RX while */
} /* end TS_CONNECTED */
end_rx: /* XXX: Again, sorry about the gotos.. :-) */
/*
* Do TX stuff
@ -1879,6 +1953,13 @@ siintr(int unit)
/*
* Nudge the transmitter...
*
* XXX: I inherited some funny code here. It implies the host card only
* interrupts when the transmit buffer reaches the low-water-mark, and does
* not interrupt when it's actually hits empty. In some cases, we have
* processes waiting for complete drain, and we need to simulate an interrupt
* about when we think the buffer is going to be empty (and retry if not).
* I really am not certain about this... I *need* the hardware manuals.
*/
static void
si_start(tp)
@ -1975,8 +2056,8 @@ si_start(tp)
else
time = 2;
} else {
printf("SLXOS si%d: bad char time value!!\n",
SI_CARD(tp->t_dev));
printf("si%d: bad char time value!!\n",
(int)SI_CARD(tp->t_dev));
goto out;
}
}
@ -2025,7 +2106,7 @@ si_lstart(pp)
/* deal with the process exit case */
ttwwakeup(tp);
/* nudge protocols */
/* nudge protocols - eg: ppp */
(*linesw[tp->t_line].l_start)(tp);
pp->sp_state &= ~SS_INLSTART;
@ -2057,7 +2138,12 @@ sistop(tp, rw)
ttwwakeup(tp); /* Bruce???? */
}
}
#if 0 /* this doesn't work right yet.. */
#if 1 /* XXX: this doesn't work right yet.. */
/* XXX: this may have been failing because we used to call l_rint()
* while we were looping based on these two counters. Now, we collect
* the data and then loop stuffing it into l_rint(), making this
* useless. Should we cause this to blow away the staging buffer?
*/
if (rw & FREAD) {
ccbp->hi_rxopos = ccbp->hi_rxipos;
}
@ -2184,8 +2270,8 @@ si_dprintf(pp, flags, str, a1, a2, a3, a4, a5, a6)
(pp != NULL && ((pp->sp_debug&flags) || (si_debug&flags)))) {
if (pp != NULL)
printf("SLXOS %ci%d(%d): ", 's',
SI_CARD(pp->sp_tty->t_dev),
SI_PORT(pp->sp_tty->t_dev));
(int)SI_CARD(pp->sp_tty->t_dev),
(int)SI_PORT(pp->sp_tty->t_dev));
printf(str, a1, a2, a3, a4, a5, a6);
}
}

View File

@ -30,7 +30,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHORS BE LIABLE.
*
* $Id: si.h,v 1.3 1995/08/22 00:42:07 peter Exp $
* $Id: si.h,v 1.4 1995/09/13 08:39:28 peter Exp $
*/
/*
@ -348,8 +348,8 @@ struct si_port {
int sp_last_hi_ip; /* cached DCD */
int sp_state;
int sp_active_out; /* callout is open */
int sp_flags;
int sp_dtr_wait; /* DTR holddown in hz */
int sp_delta_overflows;
u_int sp_wopeners; /* # procs waiting DCD */
u_char sp_hotchar; /* ldisc specific ASAP char */
/* Initial state. */
@ -381,27 +381,6 @@ struct si_port {
#define SS_BLOCKWRITE 0x2000
#define SS_DTR_OFF 0x4000 /* DTR held off */
/* sp_flags */
#define SPF_COOKMODE 0x0003
#define SPFC_WELL 0
#define SPFC_MEDIUM 1
#define SPFC_RAW 2
#define spfc_clear(pp) (pp)->sp_flags &= ~SPF_COOKMODE
#define SPF_COOK_WELL(pp) spfc_clear(pp)
#define SPF_COOK_MEDIUM(pp) {spfc_clear(pp);(pp)->sp_flags|=SPFC_MEDIUM;}
#define SPF_COOK_RAW(pp) {spfc_clear(pp);(pp)->sp_flags|=SPFC_RAW;}
#define SPF_SETCOOK(pp, c) {spfc_clear(pp);(pp)->sp_flags|=(c);}
#define SPF_ISCOOKWELL(pp) (((pp)->sp_flags & SPF_COOKMODE) == SPFC_WELL)
#define SPF_ISCOOKMEDIUM(pp) (((pp)->sp_flags & SPF_COOKMODE) == SPFC_MEDIUM)
#define SPF_ISCOOKRAW(pp) (((pp)->sp_flags & SPF_COOKMODE) == SPFC_RAW)
#define SPF_COOKWELL_ALWAYS 0x0004 /* always use line disc */
/* 0x0008 */
#define SPF_IXANY 0x0020 /* IXANY enable/disable flag */
#define SPF_CTSOFLOW 0x0040 /* use CTS to handle o/p flow */
#define SPF_RTSIFLOW 0x0080 /* use RTS to handle i/p flow */
#define SPF_PPP 0x0100 /* special handling for upper
* level protocol code */
/*
* Command post flags
*/
@ -479,13 +458,10 @@ struct si_pstat {
/* 101 defunct */
/* 102 defunct */
/* 103 defunct */
#define TCSIIXANY _IOW('S', 103, struct si_tcsi) /* enable ixany */
/* 104 defunct */
#define TCSISTATE _IOWR('S', 105, struct si_tcsi) /* get current state of RTS
DCD and DTR pins */
/* Set/reset/enquire cook mode, 1 = always use line disc
* -1 = enquire current setting */
#define TCSICOOKMODE _IOWR('S', 106, struct si_tcsi)
/* 106 defunct */
#define TCSIPORTS _IOR('S', 107, int) /* Number of ports found */
#define TCSISDBG_LEVEL _IOW('S', 108, struct si_tcsi) /* equivalent of TCSIDEBUG which sets a
* particular debug level (DBG_??? bit
@ -498,17 +474,15 @@ struct si_pstat {
/* 114 defunct */
/* 115 defunct */
/* 116 defunct */
#define TCSIMODEM _IOWR('S', 117, struct si_tcsi) /* set/clear/query the modem bit */
/* 117 defunct */
#define TCSISDBG_ALL _IOW('S', 118, int) /* set global debug level */
#define TCSIGDBG_ALL _IOR('S', 119, int) /* get global debug level */
#define TCSIFLOW _IOWR('S', 120, struct si_tcsi) /* set/get h/w flow state */
/* 120 defunct */
/* 121 defunct */
/* 122 defunct */
#define TCSIPPP _IOWR('S', 123, struct si_tcsi) /* set/get PPP flag bit */
/* 123 defunct */
#define TCSIMODULES _IOR('S', 124, int) /* Number of modules found */
/* Various stats and monitoring hooks per tty device */

View File

@ -30,7 +30,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHORS BE LIABLE.
*
* $Id: si.h,v 1.3 1995/08/22 00:42:07 peter Exp $
* $Id: si.h,v 1.4 1995/09/13 08:39:28 peter Exp $
*/
/*
@ -348,8 +348,8 @@ struct si_port {
int sp_last_hi_ip; /* cached DCD */
int sp_state;
int sp_active_out; /* callout is open */
int sp_flags;
int sp_dtr_wait; /* DTR holddown in hz */
int sp_delta_overflows;
u_int sp_wopeners; /* # procs waiting DCD */
u_char sp_hotchar; /* ldisc specific ASAP char */
/* Initial state. */
@ -381,27 +381,6 @@ struct si_port {
#define SS_BLOCKWRITE 0x2000
#define SS_DTR_OFF 0x4000 /* DTR held off */
/* sp_flags */
#define SPF_COOKMODE 0x0003
#define SPFC_WELL 0
#define SPFC_MEDIUM 1
#define SPFC_RAW 2
#define spfc_clear(pp) (pp)->sp_flags &= ~SPF_COOKMODE
#define SPF_COOK_WELL(pp) spfc_clear(pp)
#define SPF_COOK_MEDIUM(pp) {spfc_clear(pp);(pp)->sp_flags|=SPFC_MEDIUM;}
#define SPF_COOK_RAW(pp) {spfc_clear(pp);(pp)->sp_flags|=SPFC_RAW;}
#define SPF_SETCOOK(pp, c) {spfc_clear(pp);(pp)->sp_flags|=(c);}
#define SPF_ISCOOKWELL(pp) (((pp)->sp_flags & SPF_COOKMODE) == SPFC_WELL)
#define SPF_ISCOOKMEDIUM(pp) (((pp)->sp_flags & SPF_COOKMODE) == SPFC_MEDIUM)
#define SPF_ISCOOKRAW(pp) (((pp)->sp_flags & SPF_COOKMODE) == SPFC_RAW)
#define SPF_COOKWELL_ALWAYS 0x0004 /* always use line disc */
/* 0x0008 */
#define SPF_IXANY 0x0020 /* IXANY enable/disable flag */
#define SPF_CTSOFLOW 0x0040 /* use CTS to handle o/p flow */
#define SPF_RTSIFLOW 0x0080 /* use RTS to handle i/p flow */
#define SPF_PPP 0x0100 /* special handling for upper
* level protocol code */
/*
* Command post flags
*/
@ -479,13 +458,10 @@ struct si_pstat {
/* 101 defunct */
/* 102 defunct */
/* 103 defunct */
#define TCSIIXANY _IOW('S', 103, struct si_tcsi) /* enable ixany */
/* 104 defunct */
#define TCSISTATE _IOWR('S', 105, struct si_tcsi) /* get current state of RTS
DCD and DTR pins */
/* Set/reset/enquire cook mode, 1 = always use line disc
* -1 = enquire current setting */
#define TCSICOOKMODE _IOWR('S', 106, struct si_tcsi)
/* 106 defunct */
#define TCSIPORTS _IOR('S', 107, int) /* Number of ports found */
#define TCSISDBG_LEVEL _IOW('S', 108, struct si_tcsi) /* equivalent of TCSIDEBUG which sets a
* particular debug level (DBG_??? bit
@ -498,17 +474,15 @@ struct si_pstat {
/* 114 defunct */
/* 115 defunct */
/* 116 defunct */
#define TCSIMODEM _IOWR('S', 117, struct si_tcsi) /* set/clear/query the modem bit */
/* 117 defunct */
#define TCSISDBG_ALL _IOW('S', 118, int) /* set global debug level */
#define TCSIGDBG_ALL _IOR('S', 119, int) /* get global debug level */
#define TCSIFLOW _IOWR('S', 120, struct si_tcsi) /* set/get h/w flow state */
/* 120 defunct */
/* 121 defunct */
/* 122 defunct */
#define TCSIPPP _IOWR('S', 123, struct si_tcsi) /* set/get PPP flag bit */
/* 123 defunct */
#define TCSIMODULES _IOR('S', 124, int) /* Number of modules found */
/* Various stats and monitoring hooks per tty device */

View File

@ -30,7 +30,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHORS BE LIABLE.
*
* $Id: si.c,v 1.12 1995/11/04 13:23:40 bde Exp $
* $Id: si.c,v 1.13 1995/11/04 17:07:47 bde Exp $
*/
#ifndef lint
@ -39,8 +39,6 @@ static char si_copyright1[] = "@(#) (C) Specialix International, 1990,1992",
si_copyright3[] = "@(#) (C) Peter Wemm 1995";
#endif /* not lint */
#define SI_DEBUG /* turn driver debugging on */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
@ -78,8 +76,9 @@ static char si_copyright1[] = "@(#) (C) Specialix International, 1990,1992",
*/
#define POLL /* turn on poller to generate buffer empty interrupt */
#undef FASTPOLL /* turn on 100Hz poller, (XXX: NOTYET!) */
#define SI_DEF_HWFLOW /* turn on default CRTSCTS flow control */
#define SI_I_HIGH_WATER (TTYHOG - SLXOS_BUFFERSIZE)
#define SI_I_HIGH_WATER (TTYHOG - 2 * SLXOS_BUFFERSIZE)
enum si_mctl { GET, SET, BIS, BIC };
@ -101,8 +100,9 @@ extern int siprobe __P((struct isa_device *id));
extern int siattach __P((struct isa_device *id));
static void si_modem_state __P((struct si_port *pp, struct tty *tp, int hi_ip));
#ifdef SI_DEBUG
static void si_dprintf __P((/* XXX should be varargs struct si_port *pp, int flags, char *str, int a1, int a2, int a3, int a4, int a5, int a6 */));
#ifdef SI_DEBUG /* use: ``options "SI_DEBUG"'' in your config file */
/* XXX: should be varargs, I know.. but where's vprintf()? */
static void si_dprintf __P((/* struct si_port *pp, int flags, char *str, int a1, int a2, int a3, int a4, int a5, int a6 */));
static char *si_mctl2str __P((enum si_mctl cmd));
#define DPRINT(x) si_dprintf x
#else
@ -115,7 +115,7 @@ static int si_debug = 0; /* data, not bss, so it's patchable */
static struct tty *si_tty;
/* where the firmware lives */
/* where the firmware lives; defined in si_code.c */
extern int si_dsize;
extern unsigned char si_download[];
@ -135,7 +135,7 @@ struct si_softc {
};
struct si_softc si_softc[NSI]; /* up to 4 elements */
#ifndef B2000 /* not standard */
#ifndef B2000 /* not standard, but the hardware knows it. */
# define B2000 2000
#endif
static struct speedtab bdrates[] = {
@ -192,6 +192,7 @@ static int si_default_cflag = TTYDEF_CFLAG;
#ifdef POLL
#define POLL_INTERVAL (hz/2)
static int init_finished = 0;
static int fastpoll = 0;
static void si_poll __P((void *));
#endif
@ -228,6 +229,7 @@ si_registerdev(id)
}
si_kdc[id->id_unit].kdc_unit = id->id_unit;
si_kdc[id->id_unit].kdc_isa = id;
si_kdc[id->id_unit].kdc_state = DC_UNCONFIGURED;
dev_attach(&si_kdc[id->id_unit]);
}
@ -257,8 +259,8 @@ siprobe(id)
*/
if ((caddr_t)paddr < (caddr_t)IOM_BEGIN ||
(caddr_t)paddr >= (caddr_t)IOM_END) {
printf("si%d: iomem (%x) out of range\n",
id->id_unit, paddr);
printf("si%d: iomem (%lx) out of range\n",
id->id_unit, (long)paddr);
return(0);
}
@ -375,7 +377,7 @@ got_card:
for (i=0; i<ramsize; i++, ux++) {
if ((was = *ux) != (BYTE)(i&0xff)) {
DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
"SLXOS si%d: match fail at phys 0x%x, was %x should be %x\n",
"si%d: match fail at phys 0x%x, was %x should be %x\n",
id->id_unit, paddr+i, was, i&0xff));
goto fail;
}
@ -389,7 +391,7 @@ got_card:
for (i=0; i<ramsize; i++) {
if ((was = *ux++) != 0) {
DPRINT((0, DBG_AUTOBOOT|DBG_FAIL,
"SLXOS si%d: clear fail at phys 0x%x, was %x\n",
"si%d: clear fail at phys 0x%x, was %x\n",
id->id_unit, paddr+i, was));
goto fail;
}
@ -446,6 +448,7 @@ siattach(id)
struct tty *tp;
struct speedtab *spt;
int nmodule, nport, x, y;
int uart_type;
DPRINT((0, DBG_AUTOBOOT, "SLXOS siattach\n"));
@ -474,8 +477,10 @@ siattach(id)
break;
#endif /* fall-through if not EISA */
case SI2:
/* must get around to writing the code for
* these one day */
/*
* must get around to converting the code for
* these one day, if FreeBSD ever supports it.
*/
return 0;
case SIHOST:
*(maddr+SIRESET_CL) = 0;
@ -509,10 +514,10 @@ siattach(id)
switch (regp->initstat) {
case 0:
printf("si%d: startup timeout - aborting\n", unit);
sc->sc_type = NULL;
sc->sc_type = SIEMPTY;
return 0;
case 1:
/* set throttle to 100 intr per second */
/* set throttle to 125 intr per second */
regp->int_count = 25000;
/* rx intr max of 25 timer per second */
regp->rx_int_count = 4;
@ -539,12 +544,12 @@ siattach(id)
nport = 0;
modp = (struct si_module *)(maddr + 0x80);
for (;;) {
DPRINT((0, DBG_DOWNLOAD, "SLXOS si%d: ccb addr 0x%x\n", unit, modp));
DPRINT((0, DBG_DOWNLOAD, "si%d: ccb addr 0x%x\n", unit, modp));
switch (modp->sm_type & (~MMASK)) {
case M232:
case M422:
DPRINT((0, DBG_DOWNLOAD,
"SLXOS si%d: Found 232/422 module, %d ports\n",
"si%d: Found 232/422 module, %d ports\n",
unit, (int)(modp->sm_type & MMASK)));
/* this is a firmware issue */
@ -597,6 +602,7 @@ mem_fail:
pp = sc->sc_ports;
nmodule = 0;
modp = (struct si_module *)(maddr + 0x80);
uart_type = 0;
for (;;) {
switch (modp->sm_type & (~MMASK)) {
case M232:
@ -604,11 +610,12 @@ mem_fail:
nmodule++;
nport = (modp->sm_type & MMASK);
ccbp = (struct si_channel *)((char *)modp+0x100);
if (uart_type == 0)
uart_type = ccbp->type;
for (x = 0; x < nport; x++, pp++, ccbp++) {
pp->sp_ccb = ccbp; /* save the address */
pp->sp_tty = tp++;
pp->sp_pend = IDLE_CLOSE;
pp->sp_flags = 0;
pp->sp_state = 0; /* internal flag */
pp->sp_dtr_wait = 3 * hz;
pp->sp_iin.c_iflag = si_default_iflag;
@ -625,11 +632,12 @@ mem_fail:
break;
}
if (modp->sm_next == 0) {
printf("si%d: card: %s, ports: %d, modules: %d\n",
printf("si%d: card: %s, ports: %d, modules: %d (type: %d)\n",
unit,
sc->sc_typename,
sc->sc_nport,
nmodule);
nmodule,
uart_type);
break;
}
modp = (struct si_module *)
@ -675,15 +683,15 @@ siopen(dev, flag, mode, p)
return (ENXIO);
sc = &si_softc[card];
if (sc->sc_type == NULL) {
DPRINT((0, DBG_OPEN|DBG_FAIL, "SLXOS si%d: type %s??\n",
if (sc->sc_type == SIEMPTY) {
DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: type %s??\n",
card, sc->sc_typename));
return(ENXIO);
}
port = SI_PORT(mynor);
if (port >= sc->sc_nport) {
DPRINT((0, DBG_OPEN|DBG_FAIL, "SLXOS si%d: nports %d\n",
DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: nports %d\n",
card, sc->sc_nport));
return(ENXIO);
}
@ -1246,7 +1254,7 @@ si_Sioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
sps = (struct si_pstat *)data;
card = dp->tc_card;
xsc = &si_softc[card]; /* check.. */
if (card < 0 || card >= NSI || xsc->sc_type == NULL) {
if (card < 0 || card >= NSI || xsc->sc_type == SIEMPTY) {
error = ENOENT;
goto out;
}
@ -1504,7 +1512,6 @@ siparam(tp, t)
ccbp->hi_mr1, ccbp->hi_mr2, ccbp->hi_mask, ccbp->hi_prtcl, ccbp->hi_break));
splx(oldspl);
out:
return(error);
}
@ -1610,6 +1617,9 @@ si_modem_state(pp, tp, hi_ip)
/*
* Poller to catch missed interrupts.
*
* Note that the SYSV SLXOS drivers poll at 100 times per second to get better
* response. We could really use a "periodic" version timeout(). :-)
*/
#ifdef POLL
static void
@ -1618,7 +1628,8 @@ si_poll(void *nothing)
register struct si_softc *sc;
register int i;
volatile struct si_reg *regp;
int lost, oldspl;
register struct si_port *pp;
int lost, oldspl, port;
DPRINT((0, DBG_POLL, "si_poll()\n"));
oldspl = spltty();
@ -1627,7 +1638,7 @@ si_poll(void *nothing)
lost = 0;
for (i=0; i<NSI; i++) {
sc = &si_softc[i];
if (sc->sc_type == NULL)
if (sc->sc_type == SIEMPTY)
continue;
regp = (struct si_reg *)sc->sc_maddr;
/*
@ -1638,13 +1649,24 @@ si_poll(void *nothing)
if (regp->int_pending != 0) {
if (regp->int_scounter >= 200 &&
regp->initstat == 1) {
printf("SLXOS si%d: lost intr\n", i);
printf("si%d: lost intr\n", i);
lost++;
}
} else {
regp->int_scounter = 0;
}
/*
* gripe about no input flow control..
*/
pp = sc->sc_ports;
for (port = 0; port < sc->sc_nport; pp++, port++) {
if (pp->sp_delta_overflows > 0) {
printf("si%d: %d tty level buffer overflows\n",
i, pp->sp_delta_overflows);
pp->sp_delta_overflows = 0;
}
}
}
if (lost)
siintr(-1); /* call intr with fake vector */
@ -1660,7 +1682,7 @@ out:
* it is called.
*/
static BYTE rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */
static BYTE si_rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */
void
siintr(int unit)
@ -1672,7 +1694,7 @@ siintr(int unit)
register struct tty *tp;
volatile caddr_t maddr;
BYTE op, ip;
int x, card, port, n, i;
int x, card, port, n, i, isopen;
volatile BYTE *z;
BYTE c;
@ -1680,7 +1702,7 @@ siintr(int unit)
if (in_intr) {
if (unit < 0) /* should never happen */
return;
printf("SLXOS si%d: Warning interrupt handler re-entered\n",
printf("si%d: Warning interrupt handler re-entered\n",
unit);
return;
}
@ -1693,8 +1715,12 @@ siintr(int unit)
*/
for (card=0; card < NSI; card++) {
sc = &si_softc[card];
if (sc->sc_type == NULL)
if (sc->sc_type == SIEMPTY)
continue;
/*
* First, clear the interrupt
*/
switch(sc->sc_type) {
case SIHOST :
maddr = sc->sc_maddr;
@ -1722,12 +1748,14 @@ siintr(int unit)
}
((volatile struct si_reg *)maddr)->int_scounter = 0;
for (pp = sc->sc_ports, port=0;
port < sc->sc_nport;
pp++, port++) {
/*
* check each port
*/
for (pp=sc->sc_ports,port=0; port < sc->sc_nport; pp++,port++) {
ccbp = pp->sp_ccb;
tp = pp->sp_tty;
/*
* See if a command has completed ?
*/
@ -1761,109 +1789,155 @@ siintr(int unit)
*/
si_modem_state(pp, tp, ccbp->hi_ip);
/*
* Check to see if there's we should 'receive'
* characters.
*/
if (tp->t_state & TS_CONNECTED &&
tp->t_state & TS_ISOPEN)
isopen = 1;
else
isopen = 0;
/*
* Do break processing
*/
if (ccbp->hi_state & ST_BREAK) {
if (tp->t_state & TS_CONNECTED &&
tp->t_state & TS_ISOPEN) {
(*linesw[tp->t_line].l_rint)(TTY_BI, tp);
if (isopen) {
(*linesw[tp->t_line].l_rint)(TTY_BI, tp);
}
ccbp->hi_state &= ~ST_BREAK; /* A Bit iffy this */
DPRINT((pp, DBG_INTR, "si_intr break\n"));
}
/*
* Do RX stuff - if not open then
* dump any characters.
* Do RX stuff - if not open then dump any characters.
* XXX: This is VERY messy and needs to be cleaned up.
*
* XXX: can we leave data in the host adapter buffer
* when the clists are full? That may be dangerous
* if the user cannot get an interrupt signal through.
*/
if ((tp->t_state & TS_CONNECTED) == 0 ||
(tp->t_state & TS_ISOPEN) == 0) {
more_rx: /* XXX Sorry. the nesting was driving me bats! :-( */
if (!isopen) {
ccbp->hi_rxopos = ccbp->hi_rxipos;
goto end_rx;
}
/*
* Process read characters if not skipped above
*/
c = ccbp->hi_rxipos - ccbp->hi_rxopos;
if (c == 0) {
goto end_rx;
}
op = ccbp->hi_rxopos;
ip = ccbp->hi_rxipos;
n = c & 0xff;
DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
n, op, ip));
/*
* Suck characters out of host card buffer into the
* "input staging buffer" - so that we dont leave the
* host card in limbo while we're possibly echoing
* characters and possibly flushing input inside the
* ldisc l_rint() routine.
*/
if (n <= SLXOS_BUFFERSIZE - op) {
DPRINT((pp, DBG_INTR, "\tsingle copy\n"));
z = ccbp->hi_rxbuf + op;
bcopy((caddr_t)z, si_rxbuf, n);
op += n;
} else {
while ((c = ccbp->hi_rxipos - ccbp->hi_rxopos) != 0) {
x = SLXOS_BUFFERSIZE - op;
op = ccbp->hi_rxopos;
ip = ccbp->hi_rxipos;
n = c & 0xff;
DPRINT((pp, DBG_INTR, "\tdouble part 1 %d\n", x));
z = ccbp->hi_rxbuf + op;
bcopy((caddr_t)z, si_rxbuf, x);
DPRINT((pp, DBG_INTR,
"n = %d, op = %d, ip = %d\n",
DPRINT((pp, DBG_INTR, "\tdouble part 2 %d\n", n-x));
z = ccbp->hi_rxbuf;
bcopy((caddr_t)z, si_rxbuf+x, n-x);
op += n;
}
/* clear collected characters from buffer */
ccbp->hi_rxopos = op;
DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",
n, op, ip));
if (n <= SLXOS_BUFFERSIZE - op) {
DPRINT((pp, DBG_INTR,
"\tsingle copy\n"));
z = ccbp->hi_rxbuf + op;
bcopy((caddr_t)z, rxbuf, n);
/*
* at this point...
* n = number of chars placed in si_rxbuf
*/
op += n;
} else {
x = SLXOS_BUFFERSIZE - op;
/*
* Avoid the grotesquely inefficient lineswitch
* routine (ttyinput) in "raw" mode. It usually
* takes about 450 instructions (that's without
* canonical processing or echo!). slinput is
* reasonably fast (usually 40 instructions
* plus call overhead).
*/
if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
DPRINT((pp, DBG_INTR, "\tdouble part 1 %d\n", x));
z = ccbp->hi_rxbuf + op;
bcopy((caddr_t)z, rxbuf, x);
/* block if the driver supports it */
if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER
&& (tp->t_cflag & CRTS_IFLOW
|| tp->t_iflag & IXOFF)
&& !(tp->t_state & TS_TBLOCK))
ttyblock(tp);
DPRINT((pp, DBG_INTR, "\tdouble part 2 %d\n", n-x));
z = ccbp->hi_rxbuf;
bcopy((caddr_t)z, rxbuf+x, n-x);
tk_nin += n;
tk_rawcc += n;
tp->t_rawcc += n;
op += n;
pp->sp_delta_overflows +=
b_to_q((char *)si_rxbuf, n, &tp->t_rawq);
ttwakeup(tp);
if (tp->t_state & TS_TTSTOP
&& (tp->t_iflag & IXANY
|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
tp->t_state &= ~TS_TTSTOP;
tp->t_lflag &= ~FLUSHO;
si_start(tp);
}
} else {
/*
* It'd be nice to not have to go through the
* function call overhead for each char here.
* It'd be nice to block input it, saving a
* loop here and the call/return overhead.
*/
for(x = 0; x < n; x++) {
i = si_rxbuf[x];
if ((*linesw[tp->t_line].l_rint)(i, tp)
== -1) {
pp->sp_delta_overflows++;
}
ccbp->hi_rxopos = op;
DPRINT((pp, DBG_INTR,
"n = %d, op = %d, ip = %d\n",
n, op, ip));
/*
* at this point...
* n = number of chars placed in rxbuf
* doesn't seem to be much point doing
* this here.. this driver has no
* softtty processing! ??
*/
/*
* Avoid the grotesquely inefficient lineswitch routine
* (ttyinput) in "raw" mode. It usually takes about 450
* instructions (that's without canonical processing or echo!).
* slinput is reasonably fast (usually 40 instructions plus
* call overhead).
*/
if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
/* block if the driver supports it */
if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER
&& (tp->t_cflag & CRTS_IFLOW
|| tp->t_iflag & IXOFF)
&& !(tp->t_state & TS_TBLOCK))
ttyblock(tp);
tk_nin += n;
tk_rawcc += n;
tp->t_rawcc += n;
b_to_q((char *)rxbuf, n, &tp->t_rawq);
ttwakeup(tp);
if (tp->t_state & TS_TTSTOP
&& (tp->t_iflag & IXANY
|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
tp->t_state &= ~TS_TTSTOP;
tp->t_lflag &= ~FLUSHO;
si_start(tp);
}
} else {
for(x = 0; x < n; x++) {
i = rxbuf[x];
(*linesw[tp->t_line].l_rint)(rxbuf[x], tp);
if (pp->sp_hotchar && i == pp->sp_hotchar) {
setsofttty();
}
}
if (pp->sp_hotchar && i == pp->sp_hotchar) {
setsofttty();
}
}
}
goto more_rx; /* try for more until RXbuf is empty */
} /* end of RX while */
} /* end TS_CONNECTED */
end_rx: /* XXX: Again, sorry about the gotos.. :-) */
/*
* Do TX stuff
@ -1879,6 +1953,13 @@ siintr(int unit)
/*
* Nudge the transmitter...
*
* XXX: I inherited some funny code here. It implies the host card only
* interrupts when the transmit buffer reaches the low-water-mark, and does
* not interrupt when it's actually hits empty. In some cases, we have
* processes waiting for complete drain, and we need to simulate an interrupt
* about when we think the buffer is going to be empty (and retry if not).
* I really am not certain about this... I *need* the hardware manuals.
*/
static void
si_start(tp)
@ -1975,8 +2056,8 @@ si_start(tp)
else
time = 2;
} else {
printf("SLXOS si%d: bad char time value!!\n",
SI_CARD(tp->t_dev));
printf("si%d: bad char time value!!\n",
(int)SI_CARD(tp->t_dev));
goto out;
}
}
@ -2025,7 +2106,7 @@ si_lstart(pp)
/* deal with the process exit case */
ttwwakeup(tp);
/* nudge protocols */
/* nudge protocols - eg: ppp */
(*linesw[tp->t_line].l_start)(tp);
pp->sp_state &= ~SS_INLSTART;
@ -2057,7 +2138,12 @@ sistop(tp, rw)
ttwwakeup(tp); /* Bruce???? */
}
}
#if 0 /* this doesn't work right yet.. */
#if 1 /* XXX: this doesn't work right yet.. */
/* XXX: this may have been failing because we used to call l_rint()
* while we were looping based on these two counters. Now, we collect
* the data and then loop stuffing it into l_rint(), making this
* useless. Should we cause this to blow away the staging buffer?
*/
if (rw & FREAD) {
ccbp->hi_rxopos = ccbp->hi_rxipos;
}
@ -2184,8 +2270,8 @@ si_dprintf(pp, flags, str, a1, a2, a3, a4, a5, a6)
(pp != NULL && ((pp->sp_debug&flags) || (si_debug&flags)))) {
if (pp != NULL)
printf("SLXOS %ci%d(%d): ", 's',
SI_CARD(pp->sp_tty->t_dev),
SI_PORT(pp->sp_tty->t_dev));
(int)SI_CARD(pp->sp_tty->t_dev),
(int)SI_PORT(pp->sp_tty->t_dev));
printf(str, a1, a2, a3, a4, a5, a6);
}
}