Merge in 4.4BSD-Lite -> 4.4BSD-Lite2 changes. (untested).

The Lite2 changes  include:
  * Remove the last vestiges of high-bit-set-means-delay for output chars.
  * Handle the  2100/3100 having partial modem control on line 2 only,
    whereas the 5000/200 has modem control signals on lines 2 and 3.
  * Add RTS/CTS support for lines 2 and 3 on a 5000/200.
  * Add more s = spltty(); splx(s); where needed but not present.
This commit is contained in:
jonathan 1996-09-11 06:41:19 +00:00
parent 5d76f7cbac
commit 2bc8c4e5c2
1 changed files with 128 additions and 51 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: dc.c,v 1.21 1996/09/02 06:44:00 mycroft Exp $ */
/* $NetBSD: dc.c,v 1.22 1996/09/11 06:41:19 jonathan Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)dc.c 8.2 (Berkeley) 11/30/93
* @(#)dc.c 8.5 (Berkeley) 6/2/95
*/
/*
@ -421,7 +421,10 @@ dcopen(dev, flag, mode, p)
ttsetwater(tp);
} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
return (EBUSY);
(void) dcmctl(dev, DML_DTR, DMSET);
(void) dcmctl(dev, DML_DTR | DML_RTS, DMSET);
if ((dcsoftCAR[unit >> 2] & (1 << (unit & 03))) ||
(dcmctl(dev, 0, DMGET) & DML_CAR))
tp->t_state |= TS_CARR_ON;
s = spltty();
while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
!(tp->t_state & TS_CARR_ON)) {
@ -445,14 +448,18 @@ dcclose(dev, flag, mode, p)
{
register struct tty *tp;
register int unit, bit;
int s;
unit = minor(dev);
tp = dc_tty[unit];
bit = 1 << ((unit & 03) + 8);
s = spltty();
/* turn off the break bit if it is set */
if (dc_brk[unit >> 2] & bit) {
dc_brk[unit >> 2] &= ~bit;
ttyoutput(0, tp);
}
splx(s);
(*linesw[tp->t_line].l_close)(tp, flag);
if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
!(tp->t_state & TS_ISOPEN))
@ -468,6 +475,11 @@ dcread(dev, uio, flag)
register struct tty *tp;
tp = dc_tty[minor(dev)];
if ((tp->t_cflag & CRTS_IFLOW) && (tp->t_state & TS_TBLOCK) &&
tp->t_rawq.c_cc < TTYHOG/5) {
tp->t_state &= ~TS_TBLOCK;
(void) dcmctl(dev, DML_RTS, DMBIS);
}
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
@ -564,6 +576,7 @@ dcparam(tp, t)
register int cflag = t->c_cflag;
int unit = minor(tp->t_dev);
int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab);
int s;
/* check requested parameters */
if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
@ -575,28 +588,22 @@ dcparam(tp, t)
tp->t_ospeed = t->c_ospeed;
tp->t_cflag = cflag;
dcaddr = (dcregs *)dcpdma[unit].p_addr;
/*
* Handle console cases specially.
*/
if (raster_console()) {
if (unit == DCKBD_PORT) {
dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
LPR_B4800 | DCKBD_PORT;
wbflush();
return (0);
goto out;
} else if (unit == DCMOUSE_PORT) {
dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT;
wbflush();
return (0);
goto out;
}
} else if (tp->t_dev == cn_tab->cn_dev) {
dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR |
LPR_B9600 | unit;
wbflush();
return (0);
lpr = LPR_RXENAB | LPR_8_BIT_CHAR | LPR_B9600 | unit;
goto out;
}
if (ospeed == 0) {
(void) dcmctl(unit, 0, DMSET); /* hang up line */
@ -613,8 +620,12 @@ dcparam(tp, t)
lpr |= LPR_OPAR;
if (cflag & CSTOPB)
lpr |= LPR_2_STOP;
out:
dcaddr = (dcregs *)dcpdma[unit].p_addr;
s = spltty();
dcaddr->dc_lpr = lpr;
wbflush();
splx(s);
DELAY(10);
return (0);
}
@ -695,6 +706,11 @@ dcrint(unit)
cc |= TTY_FE;
if (c & RBUF_PERR)
cc |= TTY_PE;
if ((tp->t_cflag & CRTS_IFLOW) && !(tp->t_state & TS_TBLOCK) &&
tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
tp->t_state &= ~TS_TBLOCK;
(void) dcmctl(tp->t_dev, DML_RTS, DMBIC);
}
(*linesw[tp->t_line].l_rint)(cc, tp);
}
DELAY(10);
@ -706,12 +722,38 @@ dcxint(tp)
{
register struct pdma *dp;
register dcregs *dcaddr;
int unit = minor(tp->t_dev);
int unit;
unit = minor(tp->t_dev);
dp = &dcpdma[unit];
if (dp->p_mem < dp->p_end) {
dcaddr = (dcregs *)dp->p_addr;
dcaddr->dc_tdr = dc_brk[unit >> 2] | *dp->p_mem++;
/* check for hardware flow control of output */
if ((tp->t_cflag & CCTS_OFLOW) && pmax_boardtype != DS_PMAX) {
switch (unit) {
case DCCOMM_PORT:
if (dcaddr->dc_msr & MSR_CTS2)
break;
goto stop;
case DCPRINTER_PORT:
if (dcaddr->dc_msr & MSR_CTS3)
break;
stop:
tp->t_state &= ~TS_BUSY;
tp->t_state |= TS_TTSTOP;
ndflush(&tp->t_outq, dp->p_mem -
(caddr_t)tp->t_outq.c_cf);
dp->p_end = dp->p_mem = tp->t_outq.c_cf;
dcaddr->dc_tcr &= ~(1 << unit);
wbflush();
DELAY(10);
return;
}
}
dcaddr->dc_tdr = dc_brk[unit >> 2] | *(u_char *)dp->p_mem;
dp->p_mem++;
wbflush();
DELAY(10);
return;
@ -742,9 +784,9 @@ dcstart(tp)
register struct pdma *dp;
register dcregs *dcaddr;
register int cc;
int s;
int unit, s;
dp = &dcpdma[minor(tp->t_dev)];
dp = &dcpdma[unit = minor(tp->t_dev)];
dcaddr = (dcregs *)dp->p_addr;
s = spltty();
if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
@ -777,14 +819,11 @@ dcstart(tp)
}
goto out;
}
cc = ndqb(&tp->t_outq, 0);
if (cc == 0)
goto out;
cc = ndqb(&tp->t_outq, 0);
tp->t_state |= TS_BUSY;
dp->p_end = dp->p_mem = tp->t_outq.c_cf;
dp->p_end += cc;
dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03);
dcaddr->dc_tcr |= 1 << (unit & 03);
wbflush();
out:
splx(s);
@ -819,19 +858,22 @@ dcmctl(dev, bits, how)
register dcregs *dcaddr;
register int unit, mbits;
int b, s;
register int msr;
register int tcr, msr;
unit = minor(dev);
b = 1 << (unit & 03);
dcaddr = (dcregs *)dcpdma[unit].p_addr;
s = spltty();
/* only channel 2 has modem control (what about line 3?) */
mbits = DML_DTR | DML_DSR | DML_CAR;
/* only channel 2 has modem control on a DECstation 2100/3100 */
mbits = DML_DTR | DML_RTS | DML_DSR | DML_CAR;
switch (unit & 03) {
case 2:
mbits = 0;
if (dcaddr->dc_tcr & TCR_DTR2)
tcr = dcaddr->dc_tcr;
if (tcr & TCR_DTR2)
mbits |= DML_DTR;
if (pmax_boardtype != DS_PMAX && (tcr & TCR_RTS2))
mbits |= DML_RTS;
msr = dcaddr->dc_msr;
if (msr & MSR_CD2)
mbits |= DML_CAR;
@ -846,8 +888,11 @@ dcmctl(dev, bits, how)
case 3:
if (pmax_boardtype != DS_PMAX) {
mbits = 0;
if (dcaddr->dc_tcr & TCR_DTR3)
tcr = dcaddr->dc_tcr;
if (tcr & TCR_DTR3)
mbits |= DML_DTR;
if (tcr & TCR_RTS3)
mbits |= DML_RTS;
msr = dcaddr->dc_msr;
if (msr & MSR_CD3)
mbits |= DML_CAR;
@ -874,22 +919,34 @@ dcmctl(dev, bits, how)
}
switch (unit & 03) {
case 2:
tcr = dcaddr->dc_tcr;
if (mbits & DML_DTR)
dcaddr->dc_tcr |= TCR_DTR2;
tcr |= TCR_DTR2;
else
dcaddr->dc_tcr &= ~TCR_DTR2;
tcr &= ~TCR_DTR2;
if (pmax_boardtype != DS_PMAX) {
if (mbits & DML_RTS)
tcr |= TCR_RTS2;
else
tcr &= ~TCR_RTS2;
}
dcaddr->dc_tcr = tcr;
break;
case 3:
if (pmax_boardtype != DS_PMAX) {
tcr = dcaddr->dc_tcr;
if (mbits & DML_DTR)
dcaddr->dc_tcr |= TCR_DTR3;
tcr |= TCR_DTR3;
else
dcaddr->dc_tcr &= ~TCR_DTR3;
tcr &= ~TCR_DTR3;
if (mbits & DML_RTS)
tcr |= TCR_RTS3;
else
tcr &= ~TCR_RTS3;
dcaddr->dc_tcr = tcr;
}
}
if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b))
dc_tty[unit]->t_state |= TS_CARR_ON;
(void) splx(s);
return (mbits);
}
@ -904,25 +961,45 @@ dcscan(arg)
{
register dcregs *dcaddr;
register struct tty *tp;
register int i, bit, car;
register int unit, limit, dtr, dsr;
int s;
/* only channel 2 has modem control on a DECstation 2100/3100 */
dtr = TCR_DTR2;
dsr = MSR_DSR2;
limit = (pmax_boardtype == DS_PMAX) ? 2 : 3;
s = spltty();
/* only channel 2 has modem control (what about line 3?) */
dcaddr = (dcregs *)dcpdma[i = 2].p_addr;
tp = dc_tty[i];
bit = TCR_DTR2;
if (dcsoftCAR[i >> 2] & bit)
car = 1;
else
car = dcaddr->dc_msr & MSR_DSR2;
if (car) {
/* carrier present */
if (!(tp->t_state & TS_CARR_ON))
(void)(*linesw[tp->t_line].l_modem)(tp, 1);
} else if ((tp->t_state & TS_CARR_ON) &&
(*linesw[tp->t_line].l_modem)(tp, 0) == 0)
dcaddr->dc_tcr &= ~bit;
for (unit = 2; unit <= limit; unit++, dtr >>= 2, dsr >>= 8) {
tp = dc_tty[unit];
dcaddr = (dcregs *)dcpdma[unit].p_addr;
if ((dcaddr->dc_msr & dsr) || (dcsoftCAR[0] & (1 << unit))) {
/* carrier present */
if (!(tp->t_state & TS_CARR_ON))
(void)(*linesw[tp->t_line].l_modem)(tp, 1);
} else if ((tp->t_state & TS_CARR_ON) &&
(*linesw[tp->t_line].l_modem)(tp, 0) == 0)
dcaddr->dc_tcr &= ~dtr;
/*
* If we are using hardware flow control and output is stopped,
* then resume transmit.
*/
if ((tp->t_cflag & CCTS_OFLOW) && (tp->t_state & TS_TTSTOP) &&
pmax_boardtype != DS_PMAX) {
switch (unit) {
case DCCOMM_PORT:
if (dcaddr->dc_msr & MSR_CTS2)
break;
continue;
case DCPRINTER_PORT:
if (dcaddr->dc_msr & MSR_CTS3)
break;
continue;
}
tp->t_state &= ~TS_TTSTOP;
dcstart(tp);
}
}
splx(s);
timeout(dcscan, (void *)0, hz);
}