1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-17 15:27:36 +00:00

Fix some outstanding bugs in the DCD modem control..

Implement the slip/ppp "hotchar" detection to improve latency
Debug the L_RINT bypass code..
Fix an interesting feature that caused 8-bit chars to loose their top bit
in some circumstances..

This finishes the remaining outstanding problems that I'm aware of, with
the exception of efficiency...  Optimizing can come later after it's fully
debugged.
This commit is contained in:
Peter Wemm 1995-08-22 00:48:17 +00:00
parent d3497bc8de
commit 5275513295
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=10161
2 changed files with 186 additions and 230 deletions

View File

@ -30,7 +30,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHORS BE LIABLE. * NO EVENT SHALL THE AUTHORS BE LIABLE.
* *
* $Id: si.c,v 1.3 1995/08/13 15:18:05 peter Exp $ * $Id: si.c,v 1.4 1995/08/13 15:44:37 peter Exp $
*/ */
#ifndef lint #ifndef lint
@ -86,7 +86,6 @@ enum si_mctl { GET, SET, BIS, BIC };
static void si_command __P((struct si_port *, int, int)); static void si_command __P((struct si_port *, int, int));
static int si_modem __P((struct si_port *, enum si_mctl, int)); static int si_modem __P((struct si_port *, enum si_mctl, int));
static void si_write_enable __P((struct si_port *, int)); static void si_write_enable __P((struct si_port *, int));
static int si_drainwait __P((struct si_port *, char *));
static int si_Sioctl __P((dev_t, int, caddr_t, int, struct proc *)); static int si_Sioctl __P((dev_t, int, caddr_t, int, struct proc *));
static void si_start __P((struct tty *)); static void si_start __P((struct tty *));
static void si_lstart __P((struct si_port *)); static void si_lstart __P((struct si_port *));
@ -1347,6 +1346,7 @@ siparam(tp, t)
int error = 0; /* shutup gcc */ int error = 0; /* shutup gcc */
int ispeed = 0; /* shutup gcc */ int ispeed = 0; /* shutup gcc */
int ospeed = 0; /* shutup gcc */ int ospeed = 0; /* shutup gcc */
BYTE val;
DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t)); DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t));
cflag = t->c_cflag; cflag = t->c_cflag;
@ -1373,91 +1373,120 @@ siparam(tp, t)
oldspl = spltty(); oldspl = spltty();
ccbp = pp->sp_ccb; ccbp = pp->sp_ccb;
if (iflag & IGNBRK) /* Breaks */
ccbp->hi_break = BR_IGN;
else
ccbp->hi_break = 0;
if (iflag & BRKINT) /* Interrupt on break? */
ccbp->hi_break |= BR_INT;
if (iflag & PARMRK) /* Parity mark? */
ccbp->hi_break |= BR_PARMRK;
if (iflag & IGNPAR) /* Ignore chars with parity errors? */
ccbp->hi_break |= BR_PARIGN;
/* ========== set hi_break ========== */
val = 0;
if (iflag & IGNBRK) /* Breaks */
val |= BR_IGN;
if (iflag & BRKINT) /* Interrupt on break? */
val |= BR_INT;
if (iflag & PARMRK) /* Parity mark? */
val |= BR_PARMRK;
if (iflag & IGNPAR) /* Ignore chars with parity errors? */
val |= BR_PARIGN;
ccbp->hi_break = val;
/* ========== set hi_csr ========== */
/* if not hung up.. */ /* if not hung up.. */
if (t->c_ospeed != 0) { if (t->c_ospeed != 0) {
/* Set I/O speeds */ /* Set I/O speeds */
ccbp->hi_csr = (ispeed << 4) | ospeed; val = (ispeed << 4) | ospeed;
} }
ccbp->hi_csr = val;
/* ========== set hi_mr2 ========== */
val = 0;
if (cflag & CSTOPB) /* Stop bits */ if (cflag & CSTOPB) /* Stop bits */
ccbp->hi_mr2 = MR2_2_STOP; val |= MR2_2_STOP;
else else
ccbp->hi_mr2 = MR2_1_STOP; val |= MR2_1_STOP;
/*
* Enable H/W RTS/CTS handshaking. The default TA/MTA is
* a DCE, hence the reverse sense of RTS and CTS
*/
/* Output Flow - RTS must be raised before data can be sent */
if (cflag & CCTS_OFLOW)
val |= MR2_RTSCONT;
ccbp->hi_mr1 = val;
/* ========== set hi_mr1 ========== */
val = 0;
if (!(cflag & PARENB)) /* Parity */ if (!(cflag & PARENB)) /* Parity */
ccbp->hi_mr1 = MR1_NONE; val |= MR1_NONE;
else else
ccbp->hi_mr1 = MR1_WITH; val |= MR1_WITH;
if (cflag & PARODD) if (cflag & PARODD)
ccbp->hi_mr1 |= MR1_ODD; val |= MR1_ODD;
if ((cflag & CS8) == CS8) { /* 8 data bits? */ if ((cflag & CS8) == CS8) { /* 8 data bits? */
ccbp->hi_mr1 |= MR1_8_BITS; val |= MR1_8_BITS;
ccbp->hi_mask = 0xFF;
} else if ((cflag & CS7) == CS7) { /* 7 data bits? */ } else if ((cflag & CS7) == CS7) { /* 7 data bits? */
ccbp->hi_mr1 |= MR1_7_BITS; val |= MR1_7_BITS;
ccbp->hi_mask = 0x7F;
} else if ((cflag & CS6) == CS6) { /* 6 data bits? */ } else if ((cflag & CS6) == CS6) { /* 6 data bits? */
ccbp->hi_mr1 |= MR1_6_BITS; val |= MR1_6_BITS;
ccbp->hi_mask = 0x3F;
} else { /* Must be 5 */ } else { /* Must be 5 */
ccbp->hi_mr1 |= MR1_5_BITS; val |= MR1_5_BITS;
ccbp->hi_mask = 0x1F;
} }
/*
* Enable H/W RTS/CTS handshaking. The default TA/MTA is
* a DCE, hence the reverse sense of RTS and CTS
*/
/* Input Flow - CTS is raised when port is ready to receive data */
if (cflag & CRTS_IFLOW)
val |= MR1_CTSCONT;
ccbp->hi_mr1 = val;
/* ========== set hi_mask ========== */
val = 0xff;
if ((cflag & CS8) == CS8) { /* 8 data bits? */
val &= 0xFF;
} else if ((cflag & CS7) == CS7) { /* 7 data bits? */
val &= 0x7F;
} else if ((cflag & CS6) == CS6) { /* 6 data bits? */
val &= 0x3F;
} else { /* Must be 5 */
val &= 0x1F;
}
if (iflag & ISTRIP) if (iflag & ISTRIP)
ccbp->hi_mask &= 0x7F; val &= 0x7F;
ccbp->hi_mask = val;
/* ========== set hi_prtcl ========== */
val = 0;
/* Monitor DCD etc. if a modem */ /* Monitor DCD etc. if a modem */
if (!(cflag & CLOCAL)) if (!(cflag & CLOCAL))
ccbp->hi_prtcl = SP_DCEN; val |= SP_DCEN;
else if (iflag & IXANY)
ccbp->hi_prtcl = 0; val |= SP_TANY;
if (iflag & IXON)
val |= SP_TXEN;
if (iflag & IXOFF)
val |= SP_RXEN;
if (iflag & INPCK)
val |= SP_PAEN;
/* XXX: the card handles all the flow control... */ ccbp->hi_prtcl = val;
/* ========== set hi_{rx|tx}{on|off} ========== */
/* XXX: the card TOTALLY shields us from the flow control... */
ccbp->hi_txon = t->c_cc[VSTART]; ccbp->hi_txon = t->c_cc[VSTART];
ccbp->hi_txoff = t->c_cc[VSTOP]; ccbp->hi_txoff = t->c_cc[VSTOP];
ccbp->hi_rxon = t->c_cc[VSTART]; ccbp->hi_rxon = t->c_cc[VSTART];
ccbp->hi_rxoff = t->c_cc[VSTOP]; ccbp->hi_rxoff = t->c_cc[VSTOP];
if (iflag & IXANY) /* ========== send settings to the card ========== */
ccbp->hi_prtcl |= SP_TANY;
if (iflag & IXON)
ccbp->hi_prtcl |= SP_TXEN;
if (iflag & IXOFF)
ccbp->hi_prtcl |= SP_RXEN;
if (iflag & INPCK)
ccbp->hi_prtcl |= SP_PAEN;
/*
* Enable H/W RTS/CTS handshaking. The default TA/MTA is
* a DCE, hence the reverse sense of RTS and CTS
*/
/* Output - RTS must be raised before data can be sent */
if (cflag & CCTS_OFLOW)
ccbp->hi_mr2 |= MR2_RTSCONT;
/* Input - CTS is raised when port is ready to receive data */
if (cflag & CRTS_IFLOW)
ccbp->hi_mr1 |= MR1_CTSCONT;
/* potential sleep here */ /* potential sleep here */
if (ccbp->hi_stat == IDLE_CLOSE) /* Not yet open */ if (ccbp->hi_stat == IDLE_CLOSE) /* Not yet open */
si_command(pp, LOPEN, SI_WAIT); /* open it */ si_command(pp, LOPEN, SI_WAIT); /* open it */
else else
si_command(pp, CONFIG, SI_WAIT); /* change params */ si_command(pp, CONFIG, SI_WAIT); /* change params */
/* ========== set DTR etc ========== */
/* Hangup if ospeed == 0 */ /* Hangup if ospeed == 0 */
if (t->c_ospeed == 0) { if (t->c_ospeed == 0) {
(void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS); (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);
@ -1477,65 +1506,6 @@ siparam(tp, t)
return(error); return(error);
} }
/*
* Wait for buffered TX characters to drain away.
* IT IS THE RESPONSIBILITY OF THE CALLER TO DISABLE/ENABLE WRITES.
*/
static int
si_drainwait(pp, msg)
register struct si_port *pp;
char *msg;
{
register struct tty *tp = pp->sp_tty;
volatile struct si_channel *ccbp = pp->sp_ccb;
int error, oldspl, time;
BYTE x;
DPRINT((pp, DBG_ENTRY|DBG_DRAIN, "si_drainwait(%x,%s)\n",
pp, msg));
error = 0;
oldspl = spltty();
/* number of pending characters in output buffer */
x = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
while ( (x != 0 && (tp->t_state & TS_BUSY))
|| (ccbp->hi_stat == IDLE_BREAK)) {
DPRINT((pp, DBG_DRAIN,
" x %d. t_state %x sp_state %x hi_stat %x\n",
x, tp->t_state, pp->sp_state, ccbp->hi_stat));
/* else waiting got chars */
/* guess how long */
time = ttspeedtab(tp->t_ospeed, chartimes);
if (time == 0 || time > x)
time = 1;
else
time = x/time + 1;
error = ttysleep(tp, (caddr_t)pp,
TTOPRI|PCATCH, msg, time);
if (error != EWOULDBLOCK) {
DPRINT((pp, DBG_DRAIN|DBG_FAIL,
"%s, wait for drain broken by signal %d\n",
msg, error));
break;
}
error = 0;
/* reload count */
x = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
}
tp->t_state &= ~TS_BUSY;
ttwwakeup(tp);
splx(oldspl);
return(error);
}
/* /*
* Enable or Disable the writes to this channel... * Enable or Disable the writes to this channel...
* "state" -> enabled = 1; disabled = 0; * "state" -> enabled = 1; disabled = 0;
@ -1688,7 +1658,7 @@ si_poll(void *nothing)
* it is called. * it is called.
*/ */
static char rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */ static BYTE rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */
int int
siintr(int bdnum) siintr(int bdnum)
@ -1701,7 +1671,7 @@ siintr(int bdnum)
register struct tty *tp; register struct tty *tp;
volatile caddr_t maddr; volatile caddr_t maddr;
BYTE op, ip, cc; BYTE op, ip, cc;
int x, card, port, n; int x, card, port, n, i;
volatile BYTE *z; volatile BYTE *z;
BYTE c; BYTE c;
static int in_poll = 0; static int in_poll = 0;
@ -1889,8 +1859,11 @@ siintr(int bdnum)
} }
} else { } else {
for(x = 0; x < n; x++) { for(x = 0; x < n; x++) {
(*linesw[tp->t_line].l_rint)( i = rxbuf[x];
rxbuf[x], tp); (*linesw[tp->t_line].l_rint)(rxbuf[x], tp);
if (pp->sp_hotchar && i == pp->sp_hotchar) {
setsofttty();
}
} }
} }
@ -2187,6 +2160,7 @@ si_disc_optim(tp, t, pp)
tp->t_state |= TS_CAN_BYPASS_L_RINT; tp->t_state |= TS_CAN_BYPASS_L_RINT;
else else
tp->t_state &= ~TS_CAN_BYPASS_L_RINT; tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
/* /*
* Prepare to reduce input latency for packet * Prepare to reduce input latency for packet
* discplines with a end of packet character. * discplines with a end of packet character.
@ -2197,6 +2171,10 @@ si_disc_optim(tp, t, pp)
pp->sp_hotchar = 0x7e; pp->sp_hotchar = 0x7e;
else else
pp->sp_hotchar = 0; pp->sp_hotchar = 0;
DPRINT((pp, DBG_OPTIM, "bypass: %s, hotchar: %x\n",
(tp->t_state & TS_CAN_BYPASS_L_RINT) ? "on" : "off",
pp->sp_hotchar));
} }

View File

@ -30,7 +30,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHORS BE LIABLE. * NO EVENT SHALL THE AUTHORS BE LIABLE.
* *
* $Id: si.c,v 1.3 1995/08/13 15:18:05 peter Exp $ * $Id: si.c,v 1.4 1995/08/13 15:44:37 peter Exp $
*/ */
#ifndef lint #ifndef lint
@ -86,7 +86,6 @@ enum si_mctl { GET, SET, BIS, BIC };
static void si_command __P((struct si_port *, int, int)); static void si_command __P((struct si_port *, int, int));
static int si_modem __P((struct si_port *, enum si_mctl, int)); static int si_modem __P((struct si_port *, enum si_mctl, int));
static void si_write_enable __P((struct si_port *, int)); static void si_write_enable __P((struct si_port *, int));
static int si_drainwait __P((struct si_port *, char *));
static int si_Sioctl __P((dev_t, int, caddr_t, int, struct proc *)); static int si_Sioctl __P((dev_t, int, caddr_t, int, struct proc *));
static void si_start __P((struct tty *)); static void si_start __P((struct tty *));
static void si_lstart __P((struct si_port *)); static void si_lstart __P((struct si_port *));
@ -1347,6 +1346,7 @@ siparam(tp, t)
int error = 0; /* shutup gcc */ int error = 0; /* shutup gcc */
int ispeed = 0; /* shutup gcc */ int ispeed = 0; /* shutup gcc */
int ospeed = 0; /* shutup gcc */ int ospeed = 0; /* shutup gcc */
BYTE val;
DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t)); DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t));
cflag = t->c_cflag; cflag = t->c_cflag;
@ -1373,91 +1373,120 @@ siparam(tp, t)
oldspl = spltty(); oldspl = spltty();
ccbp = pp->sp_ccb; ccbp = pp->sp_ccb;
if (iflag & IGNBRK) /* Breaks */
ccbp->hi_break = BR_IGN;
else
ccbp->hi_break = 0;
if (iflag & BRKINT) /* Interrupt on break? */
ccbp->hi_break |= BR_INT;
if (iflag & PARMRK) /* Parity mark? */
ccbp->hi_break |= BR_PARMRK;
if (iflag & IGNPAR) /* Ignore chars with parity errors? */
ccbp->hi_break |= BR_PARIGN;
/* ========== set hi_break ========== */
val = 0;
if (iflag & IGNBRK) /* Breaks */
val |= BR_IGN;
if (iflag & BRKINT) /* Interrupt on break? */
val |= BR_INT;
if (iflag & PARMRK) /* Parity mark? */
val |= BR_PARMRK;
if (iflag & IGNPAR) /* Ignore chars with parity errors? */
val |= BR_PARIGN;
ccbp->hi_break = val;
/* ========== set hi_csr ========== */
/* if not hung up.. */ /* if not hung up.. */
if (t->c_ospeed != 0) { if (t->c_ospeed != 0) {
/* Set I/O speeds */ /* Set I/O speeds */
ccbp->hi_csr = (ispeed << 4) | ospeed; val = (ispeed << 4) | ospeed;
} }
ccbp->hi_csr = val;
/* ========== set hi_mr2 ========== */
val = 0;
if (cflag & CSTOPB) /* Stop bits */ if (cflag & CSTOPB) /* Stop bits */
ccbp->hi_mr2 = MR2_2_STOP; val |= MR2_2_STOP;
else else
ccbp->hi_mr2 = MR2_1_STOP; val |= MR2_1_STOP;
/*
* Enable H/W RTS/CTS handshaking. The default TA/MTA is
* a DCE, hence the reverse sense of RTS and CTS
*/
/* Output Flow - RTS must be raised before data can be sent */
if (cflag & CCTS_OFLOW)
val |= MR2_RTSCONT;
ccbp->hi_mr1 = val;
/* ========== set hi_mr1 ========== */
val = 0;
if (!(cflag & PARENB)) /* Parity */ if (!(cflag & PARENB)) /* Parity */
ccbp->hi_mr1 = MR1_NONE; val |= MR1_NONE;
else else
ccbp->hi_mr1 = MR1_WITH; val |= MR1_WITH;
if (cflag & PARODD) if (cflag & PARODD)
ccbp->hi_mr1 |= MR1_ODD; val |= MR1_ODD;
if ((cflag & CS8) == CS8) { /* 8 data bits? */ if ((cflag & CS8) == CS8) { /* 8 data bits? */
ccbp->hi_mr1 |= MR1_8_BITS; val |= MR1_8_BITS;
ccbp->hi_mask = 0xFF;
} else if ((cflag & CS7) == CS7) { /* 7 data bits? */ } else if ((cflag & CS7) == CS7) { /* 7 data bits? */
ccbp->hi_mr1 |= MR1_7_BITS; val |= MR1_7_BITS;
ccbp->hi_mask = 0x7F;
} else if ((cflag & CS6) == CS6) { /* 6 data bits? */ } else if ((cflag & CS6) == CS6) { /* 6 data bits? */
ccbp->hi_mr1 |= MR1_6_BITS; val |= MR1_6_BITS;
ccbp->hi_mask = 0x3F;
} else { /* Must be 5 */ } else { /* Must be 5 */
ccbp->hi_mr1 |= MR1_5_BITS; val |= MR1_5_BITS;
ccbp->hi_mask = 0x1F;
} }
/*
* Enable H/W RTS/CTS handshaking. The default TA/MTA is
* a DCE, hence the reverse sense of RTS and CTS
*/
/* Input Flow - CTS is raised when port is ready to receive data */
if (cflag & CRTS_IFLOW)
val |= MR1_CTSCONT;
ccbp->hi_mr1 = val;
/* ========== set hi_mask ========== */
val = 0xff;
if ((cflag & CS8) == CS8) { /* 8 data bits? */
val &= 0xFF;
} else if ((cflag & CS7) == CS7) { /* 7 data bits? */
val &= 0x7F;
} else if ((cflag & CS6) == CS6) { /* 6 data bits? */
val &= 0x3F;
} else { /* Must be 5 */
val &= 0x1F;
}
if (iflag & ISTRIP) if (iflag & ISTRIP)
ccbp->hi_mask &= 0x7F; val &= 0x7F;
ccbp->hi_mask = val;
/* ========== set hi_prtcl ========== */
val = 0;
/* Monitor DCD etc. if a modem */ /* Monitor DCD etc. if a modem */
if (!(cflag & CLOCAL)) if (!(cflag & CLOCAL))
ccbp->hi_prtcl = SP_DCEN; val |= SP_DCEN;
else if (iflag & IXANY)
ccbp->hi_prtcl = 0; val |= SP_TANY;
if (iflag & IXON)
val |= SP_TXEN;
if (iflag & IXOFF)
val |= SP_RXEN;
if (iflag & INPCK)
val |= SP_PAEN;
/* XXX: the card handles all the flow control... */ ccbp->hi_prtcl = val;
/* ========== set hi_{rx|tx}{on|off} ========== */
/* XXX: the card TOTALLY shields us from the flow control... */
ccbp->hi_txon = t->c_cc[VSTART]; ccbp->hi_txon = t->c_cc[VSTART];
ccbp->hi_txoff = t->c_cc[VSTOP]; ccbp->hi_txoff = t->c_cc[VSTOP];
ccbp->hi_rxon = t->c_cc[VSTART]; ccbp->hi_rxon = t->c_cc[VSTART];
ccbp->hi_rxoff = t->c_cc[VSTOP]; ccbp->hi_rxoff = t->c_cc[VSTOP];
if (iflag & IXANY) /* ========== send settings to the card ========== */
ccbp->hi_prtcl |= SP_TANY;
if (iflag & IXON)
ccbp->hi_prtcl |= SP_TXEN;
if (iflag & IXOFF)
ccbp->hi_prtcl |= SP_RXEN;
if (iflag & INPCK)
ccbp->hi_prtcl |= SP_PAEN;
/*
* Enable H/W RTS/CTS handshaking. The default TA/MTA is
* a DCE, hence the reverse sense of RTS and CTS
*/
/* Output - RTS must be raised before data can be sent */
if (cflag & CCTS_OFLOW)
ccbp->hi_mr2 |= MR2_RTSCONT;
/* Input - CTS is raised when port is ready to receive data */
if (cflag & CRTS_IFLOW)
ccbp->hi_mr1 |= MR1_CTSCONT;
/* potential sleep here */ /* potential sleep here */
if (ccbp->hi_stat == IDLE_CLOSE) /* Not yet open */ if (ccbp->hi_stat == IDLE_CLOSE) /* Not yet open */
si_command(pp, LOPEN, SI_WAIT); /* open it */ si_command(pp, LOPEN, SI_WAIT); /* open it */
else else
si_command(pp, CONFIG, SI_WAIT); /* change params */ si_command(pp, CONFIG, SI_WAIT); /* change params */
/* ========== set DTR etc ========== */
/* Hangup if ospeed == 0 */ /* Hangup if ospeed == 0 */
if (t->c_ospeed == 0) { if (t->c_ospeed == 0) {
(void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS); (void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);
@ -1477,65 +1506,6 @@ siparam(tp, t)
return(error); return(error);
} }
/*
* Wait for buffered TX characters to drain away.
* IT IS THE RESPONSIBILITY OF THE CALLER TO DISABLE/ENABLE WRITES.
*/
static int
si_drainwait(pp, msg)
register struct si_port *pp;
char *msg;
{
register struct tty *tp = pp->sp_tty;
volatile struct si_channel *ccbp = pp->sp_ccb;
int error, oldspl, time;
BYTE x;
DPRINT((pp, DBG_ENTRY|DBG_DRAIN, "si_drainwait(%x,%s)\n",
pp, msg));
error = 0;
oldspl = spltty();
/* number of pending characters in output buffer */
x = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
while ( (x != 0 && (tp->t_state & TS_BUSY))
|| (ccbp->hi_stat == IDLE_BREAK)) {
DPRINT((pp, DBG_DRAIN,
" x %d. t_state %x sp_state %x hi_stat %x\n",
x, tp->t_state, pp->sp_state, ccbp->hi_stat));
/* else waiting got chars */
/* guess how long */
time = ttspeedtab(tp->t_ospeed, chartimes);
if (time == 0 || time > x)
time = 1;
else
time = x/time + 1;
error = ttysleep(tp, (caddr_t)pp,
TTOPRI|PCATCH, msg, time);
if (error != EWOULDBLOCK) {
DPRINT((pp, DBG_DRAIN|DBG_FAIL,
"%s, wait for drain broken by signal %d\n",
msg, error));
break;
}
error = 0;
/* reload count */
x = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
}
tp->t_state &= ~TS_BUSY;
ttwwakeup(tp);
splx(oldspl);
return(error);
}
/* /*
* Enable or Disable the writes to this channel... * Enable or Disable the writes to this channel...
* "state" -> enabled = 1; disabled = 0; * "state" -> enabled = 1; disabled = 0;
@ -1688,7 +1658,7 @@ si_poll(void *nothing)
* it is called. * it is called.
*/ */
static char rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */ static BYTE rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */
int int
siintr(int bdnum) siintr(int bdnum)
@ -1701,7 +1671,7 @@ siintr(int bdnum)
register struct tty *tp; register struct tty *tp;
volatile caddr_t maddr; volatile caddr_t maddr;
BYTE op, ip, cc; BYTE op, ip, cc;
int x, card, port, n; int x, card, port, n, i;
volatile BYTE *z; volatile BYTE *z;
BYTE c; BYTE c;
static int in_poll = 0; static int in_poll = 0;
@ -1889,8 +1859,11 @@ siintr(int bdnum)
} }
} else { } else {
for(x = 0; x < n; x++) { for(x = 0; x < n; x++) {
(*linesw[tp->t_line].l_rint)( i = rxbuf[x];
rxbuf[x], tp); (*linesw[tp->t_line].l_rint)(rxbuf[x], tp);
if (pp->sp_hotchar && i == pp->sp_hotchar) {
setsofttty();
}
} }
} }
@ -2187,6 +2160,7 @@ si_disc_optim(tp, t, pp)
tp->t_state |= TS_CAN_BYPASS_L_RINT; tp->t_state |= TS_CAN_BYPASS_L_RINT;
else else
tp->t_state &= ~TS_CAN_BYPASS_L_RINT; tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
/* /*
* Prepare to reduce input latency for packet * Prepare to reduce input latency for packet
* discplines with a end of packet character. * discplines with a end of packet character.
@ -2197,6 +2171,10 @@ si_disc_optim(tp, t, pp)
pp->sp_hotchar = 0x7e; pp->sp_hotchar = 0x7e;
else else
pp->sp_hotchar = 0; pp->sp_hotchar = 0;
DPRINT((pp, DBG_OPTIM, "bypass: %s, hotchar: %x\n",
(tp->t_state & TS_CAN_BYPASS_L_RINT) ? "on" : "off",
pp->sp_hotchar));
} }