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:
parent
34795551b8
commit
49d4047a8f
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue