mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-17 15:27:36 +00:00
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:
parent
fd24fbdf21
commit
5d0bad8280
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=12174
322
sys/dev/si/si.c
322
sys/dev/si/si.c
@ -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 @@ siprobe(id)
|
||||
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 @@ siprobe(id)
|
||||
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 @@ siattach(id)
|
||||
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 @@ siattach(id)
|
||||
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 @@ siattach(id)
|
||||
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 @@ si_poll(void *nothing)
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 @@ siprobe(id)
|
||||
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 @@ siprobe(id)
|
||||
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 @@ siattach(id)
|
||||
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 @@ siattach(id)
|
||||
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 @@ siattach(id)
|
||||
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 @@ si_poll(void *nothing)
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user