diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/uart/uart_core.c | 26 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_i8251.c | 15 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_ns8250.c | 15 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_z8530.c | 20 |
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); |