summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/uart/uart_core.c26
-rw-r--r--sys/dev/uart/uart_dev_i8251.c15
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c15
-rw-r--r--sys/dev/uart/uart_dev_z8530.c20
4 files changed, 57 insertions, 19 deletions
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index dd4f91c..5889211 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -200,17 +200,21 @@ uart_intr(void *arg)
if (sc->sc_leaving)
return;
- ipend = UART_IPEND(sc);
- if (ipend & UART_IPEND_OVERRUN)
- uart_intr_overrun(sc);
- if (ipend & UART_IPEND_BREAK)
- uart_intr_break(sc);
- if (ipend & UART_IPEND_RXREADY)
- uart_intr_rxready(sc);
- if (ipend & UART_IPEND_SIGCHG)
- uart_intr_sigchg(sc);
- if (ipend & UART_IPEND_TXIDLE)
- uart_intr_txidle(sc);
+ do {
+ ipend = UART_IPEND(sc);
+ if (ipend == 0)
+ break;
+ if (ipend & UART_IPEND_OVERRUN)
+ uart_intr_overrun(sc);
+ if (ipend & UART_IPEND_BREAK)
+ uart_intr_break(sc);
+ if (ipend & UART_IPEND_RXREADY)
+ uart_intr_rxready(sc);
+ if (ipend & UART_IPEND_SIGCHG)
+ uart_intr_sigchg(sc);
+ if (ipend & UART_IPEND_TXIDLE)
+ uart_intr_txidle(sc);
+ } while (1);
if (sc->sc_opened && sc->sc_ttypend != 0)
swi_sched(sc->sc_softih, 0);
diff --git a/sys/dev/uart/uart_dev_i8251.c b/sys/dev/uart/uart_dev_i8251.c
index 9e9a5b2..0dd3afb 100644
--- a/sys/dev/uart/uart_dev_i8251.c
+++ b/sys/dev/uart/uart_dev_i8251.c
@@ -680,16 +680,25 @@ i8251_bus_receive(struct uart_softc *sc)
bas = &sc->sc_bas;
mtx_lock_spin(&sc->sc_hwmtx);
- while (!uart_rx_full(sc)) {
- lsr = uart_getreg(bas, REG_LSR);
- if ((lsr & LSR_RXRDY) == 0)
+ lsr = uart_getreg(bas, REG_LSR);
+ while (lsr & LSR_RXRDY) {
+ if (uart_rx_full(sc)) {
+ sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
break;
+ }
xc = uart_getreg(bas, REG_DATA);
if (lsr & LSR_FE)
xc |= UART_STAT_FRAMERR;
if (lsr & LSR_PE)
xc |= UART_STAT_PARERR;
uart_rx_put(sc, xc);
+ lsr = uart_getreg(bas, REG_LSR);
+ }
+ /* Discard everything left in the Rx FIFO. */
+ while (lsr & LSR_RXRDY) {
+ (void)uart_getreg(bas, REG_DATA);
+ uart_barrier(bas);
+ lsr = uart_getreg(bas, REG_LSR);
}
mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 7c4d264..44d1304 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -716,16 +716,25 @@ ns8250_bus_receive(struct uart_softc *sc)
bas = &sc->sc_bas;
mtx_lock_spin(&sc->sc_hwmtx);
- while (!uart_rx_full(sc)) {
- lsr = uart_getreg(bas, REG_LSR);
- if ((lsr & LSR_RXRDY) == 0)
+ lsr = uart_getreg(bas, REG_LSR);
+ while (lsr & LSR_RXRDY) {
+ if (uart_rx_full(sc)) {
+ sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
break;
+ }
xc = uart_getreg(bas, REG_DATA);
if (lsr & LSR_FE)
xc |= UART_STAT_FRAMERR;
if (lsr & LSR_PE)
xc |= UART_STAT_PARERR;
uart_rx_put(sc, xc);
+ lsr = uart_getreg(bas, REG_LSR);
+ }
+ /* Discard everything left in the Rx FIFO. */
+ while (lsr & LSR_RXRDY) {
+ (void)uart_getreg(bas, REG_DATA);
+ uart_barrier(bas);
+ lsr = uart_getreg(bas, REG_LSR);
}
mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c
index 319783a..eda35b8 100644
--- a/sys/dev/uart/uart_dev_z8530.c
+++ b/sys/dev/uart/uart_dev_z8530.c
@@ -458,7 +458,11 @@ z8530_bus_receive(struct uart_softc *sc)
bas = &sc->sc_bas;
mtx_lock_spin(&sc->sc_hwmtx);
bes = uart_getmreg(bas, RR_BES);
- while ((bes & BES_RXA) && !uart_rx_full(sc)) {
+ while (bes & BES_RXA) {
+ if (uart_rx_full(sc)) {
+ sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+ break;
+ }
src = uart_getmreg(bas, RR_SRC);
xc = uart_getreg(bas, REG_DATA);
if (src & SRC_FE)
@@ -466,8 +470,20 @@ z8530_bus_receive(struct uart_softc *sc)
if (src & SRC_PE)
xc |= UART_STAT_PARERR;
uart_rx_put(sc, xc);
- if (src & (SRC_FE | SRC_PE))
+ if (src & (SRC_FE | SRC_PE)) {
uart_setreg(bas, REG_CTRL, CR_RSTERR);
+ uart_barrier(bas);
+ }
+ bes = uart_getmreg(bas, RR_BES);
+ }
+ /* Discard everything left in the Rx FIFO. */
+ while (bes & BES_RXA) {
+ src = uart_getmreg(bas, RR_SRC);
+ (void)uart_getreg(bas, REG_DATA);
+ if (src & (SRC_FE | SRC_PE)) {
+ uart_setreg(bas, REG_CTRL, CR_RSTERR);
+ uart_barrier(bas);
+ }
bes = uart_getmreg(bas, RR_BES);
}
mtx_unlock_spin(&sc->sc_hwmtx);
OpenPOWER on IntegriCloud