diff options
author | Henric Jungheim <henric@cvs.openbsd.org> | 2003-05-13 23:55:55 +0000 |
---|---|---|
committer | Henric Jungheim <henric@cvs.openbsd.org> | 2003-05-13 23:55:55 +0000 |
commit | b4dd55d103207347b453f69c731250bd549e6b5b (patch) | |
tree | ce207a7fc4dcecf3abb4110673d4eda35552e7fe /sys/arch/sparc64/dev | |
parent | 9f1874ae0ed270cc09f53906922475ab9322ce8f (diff) |
The sab driver sometimes gets out of sync with the hardware. This can
cause the serial console to hang.
ok jason@
Diffstat (limited to 'sys/arch/sparc64/dev')
-rw-r--r-- | sys/arch/sparc64/dev/sab.c | 81 |
1 files changed, 46 insertions, 35 deletions
diff --git a/sys/arch/sparc64/dev/sab.c b/sys/arch/sparc64/dev/sab.c index 23ffe9ced0c..58ae2541041 100644 --- a/sys/arch/sparc64/dev/sab.c +++ b/sys/arch/sparc64/dev/sab.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sab.c,v 1.10 2003/02/17 01:29:20 henric Exp $ */ +/* $OpenBSD: sab.c,v 1.11 2003/05/13 23:55:54 henric Exp $ */ /* * Copyright (c) 2001 Jason L. Wright (jason@thought.net) @@ -122,6 +122,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 *, void *, void *); void sab_attach(struct device *, struct device *, void *); @@ -139,8 +141,8 @@ int sabtty_param(struct tty *, struct termios *); int sabtty_intr(struct sabtty_softc *, int *); void sabtty_softintr(struct sabtty_softc *); int sabtty_mdmctrl(struct sabtty_softc *, int, int); -void sabtty_cec_wait(struct sabtty_softc *); -void sabtty_tec_wait(struct sabtty_softc *); +int sabtty_cec_wait(struct sabtty_softc *); +int sabtty_tec_wait(struct sabtty_softc *); void sabtty_reset(struct sabtty_softc *); void sabtty_flush(struct sabtty_softc *); int sabtty_speed(int); @@ -285,6 +287,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 */ @@ -431,9 +436,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; @@ -524,41 +526,50 @@ sabtty_intr(sc, needsoftp) if (isr1 & SAB_ISR1_BRKT) sabtty_abort(sc); - if (isr1 & SAB_ISR1_ALLS) { - if (sc->sc_flags & SABTTYF_TXDRAIN) - wakeup(sc); - sc->sc_flags &= ~SABTTYF_STOP; - sc->sc_flags |= SABTTYF_DONE; - sc->sc_imr1 |= SAB_IMR1_ALLS; - SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); - needsoft = 1; - } - - if (isr1 & SAB_ISR1_XPR) { - r = 1; - if ((sc->sc_flags & SABTTYF_STOP) == 0) { + 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; - for (i = 0; i < len; i++) { - SAB_WRITE(sc, SAB_XFIFO + i, *sc->sc_txp); - sc->sc_txp++; - sc->sc_txc--; - } - if (i != 0) { + + 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)) { - sc->sc_imr1 |= SAB_IMR1_XPR; - sc->sc_imr1 &= ~SAB_IMR1_ALLS; - SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); + 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; + sc->sc_flags |= SABTTYF_DONE; + sc->sc_imr1 |= SAB_IMR1_ALLS; + SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); + needsoft = 1; + } + if (needsoft) *needsoftp = needsoft; return (r); @@ -1093,14 +1104,14 @@ 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); } } splx(s); } -void +int sabtty_cec_wait(sc) struct sabtty_softc *sc; { @@ -1108,14 +1119,14 @@ sabtty_cec_wait(sc) for (;;) { if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_CEC) == 0) - return; + return (0); if (--i == 0) - break; + return (1); DELAY(1); } } -void +int sabtty_tec_wait(sc) struct sabtty_softc *sc; { @@ -1123,9 +1134,9 @@ sabtty_tec_wait(sc) for (;;) { if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_TEC) == 0) - return; + return (0); if (--i == 0) - break; + return (1); DELAY(1); } } |