Pick up from OpenBSD:

The sab driver sometimes gets out of sync with the hardware.  This can
cause the serial console to hang.
This commit is contained in:
petrov 2003-06-13 01:33:32 +00:00
parent 34795551b8
commit 49d4047a8f
1 changed files with 42 additions and 31 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sab.c,v 1.10 2003/06/11 22:51:03 petrov Exp $ */
/* $NetBSD: sab.c,v 1.11 2003/06/13 01:33:32 petrov Exp $ */
/* $OpenBSD: sab.c,v 1.7 2002/04/08 17:49:42 jason Exp $ */
/*
@ -115,6 +115,8 @@ struct sabtty_softc *sabtty_cons_output;
bus_space_read_1((sc)->sc_bt, (sc)->sc_bh, (r))
#define SAB_WRITE(sc,r,v) \
bus_space_write_1((sc)->sc_bt, (sc)->sc_bh, (r), (v))
#define SAB_WRITE_BLOCK(sc,r,p,c) \
bus_space_write_region_1((sc)->sc_bt, (sc)->sc_bh, (r), (p), (c))
int sab_match(struct device *, struct cfdata *, void *);
void sab_attach(struct device *, struct device *, void *);
@ -276,6 +278,9 @@ sab_attach(parent, self, aux)
}
printf("\n");
/* Let current output drain */
DELAY(100000);
/* Set all pins, except DTR pins to be inputs */
SAB_WRITE(sc, SAB_PCR, ~(SAB_PVR_DTR_A | SAB_PVR_DTR_B));
/* Disable port interrupts */
@ -424,9 +429,6 @@ sabtty_attach(parent, self, aux)
break;
}
/* Let current output drain */
DELAY(100000);
t.c_ispeed= 0;
t.c_ospeed = 9600;
t.c_cflag = CREAD | CS8 | HUPCL;
@ -519,7 +521,41 @@ sabtty_intr(sc, needsoftp)
if (isr1 & SAB_ISR1_BRKT)
sabtty_abort(sc);
if (isr1 & SAB_ISR1_ALLS) {
if (isr1 & (SAB_ISR1_XPR | SAB_ISR1_ALLS)) {
if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_XFW) &&
(sc->sc_flags & SABTTYF_STOP) == 0) {
if (sc->sc_txc < 32)
len = sc->sc_txc;
else
len = 32;
if (len > 0) {
SAB_WRITE_BLOCK(sc, SAB_XFIFO, sc->sc_txp, len);
sc->sc_txp += len;
sc->sc_txc -= len;
sabtty_cec_wait(sc);
SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XF);
/*
* Prevent the false end of xmit from
* confusing things below.
*/
isr1 &= ~SAB_ISR1_ALLS;
}
}
if ((sc->sc_txc == 0) || (sc->sc_flags & SABTTYF_STOP)) {
if ((sc->sc_imr1 & SAB_IMR1_XPR) == 0) {
sc->sc_imr1 |= SAB_IMR1_XPR;
sc->sc_imr1 &= ~SAB_IMR1_ALLS;
SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
}
}
}
if ((isr1 & SAB_ISR1_ALLS) && ((sc->sc_txc == 0) ||
(sc->sc_flags & SABTTYF_STOP))) {
if (sc->sc_flags & SABTTYF_TXDRAIN)
wakeup(sc);
sc->sc_flags &= ~SABTTYF_STOP;
@ -529,31 +565,6 @@ sabtty_intr(sc, needsoftp)
needsoft = 1;
}
if (isr1 & SAB_ISR1_XPR) {
r = 1;
if ((sc->sc_flags & SABTTYF_STOP) == 0) {
if (sc->sc_txc < 32)
len = sc->sc_txc;
else
len = 32;
for (i = 0; i < len; i++) {
SAB_WRITE(sc, SAB_XFIFO + i, *sc->sc_txp);
sc->sc_txp++;
sc->sc_txc--;
}
if (i != 0) {
sabtty_cec_wait(sc);
SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XF);
}
}
if ((sc->sc_txc == 0) || (sc->sc_flags & SABTTYF_STOP)) {
sc->sc_imr1 |= SAB_IMR1_XPR;
sc->sc_imr1 &= ~SAB_IMR1_ALLS;
SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
}
}
if (needsoft)
*needsoftp = needsoft;
return (r);
@ -1079,7 +1090,7 @@ sabtty_start(tp)
sc->sc_txc = ndqb(&tp->t_outq, 0);
sc->sc_txp = tp->t_outq.c_cf;
tp->t_state |= TS_BUSY;
sc->sc_imr1 &= ~SAB_IMR1_XPR;
sc->sc_imr1 &= ~(SAB_ISR1_XPR | SAB_ISR1_ALLS);
SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
}
}