diff --git a/sys/arch/pmax/dev/dc.c b/sys/arch/pmax/dev/dc.c index 05c8065f1fdd..13557c42b425 100644 --- a/sys/arch/pmax/dev/dc.c +++ b/sys/arch/pmax/dev/dc.c @@ -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); }