Index: sys/dev/uart/uart_dev_ns8250.h =================================================================== --- sys/dev/uart/uart_dev_ns8250.h +++ sys/dev/uart/uart_dev_ns8250.h @@ -41,6 +41,12 @@ uint8_t ier_mask; uint8_t ier_rxbits; uint8_t busy_detect; + + /* + * Save LSR register because error bits are cleared on read. They must + * be saved whenever the register is read but not immediately used. + */ + uint8_t lsr_saved_flags; }; extern struct uart_ops uart_ns8250_ops; Index: sys/dev/uart/uart_dev_ns8250.c =================================================================== --- sys/dev/uart/uart_dev_ns8250.c +++ sys/dev/uart/uart_dev_ns8250.c @@ -71,6 +71,8 @@ ns8250_clrint(struct uart_bas *bas) { uint8_t iir, lsr; + struct ns8250_softc *ns8250 = (struct ns8250_softc *)bas; + ns8250->lsr_saved_flags = 0; iir = uart_getreg(bas, REG_IIR); while ((iir & IIR_NOPEND) == 0) { @@ -138,6 +140,9 @@ int delay, limit; delay = ns8250_delay(bas); + + struct ns8250_softc *ns8250 = (struct ns8250_softc *)bas; + ns8250->lsr_saved_flags = 0; if (what & UART_DRAIN_TRANSMITTER) { /* @@ -190,8 +195,11 @@ fcr = FCR_ENABLE; if (what & UART_FLUSH_TRANSMITTER) fcr |= FCR_XMT_RST; - if (what & UART_FLUSH_RECEIVER) + if (what & UART_FLUSH_RECEIVER) { fcr |= FCR_RCV_RST; + struct ns8250_softc *ns8250 = (struct ns8250_softc *)bas; + ns8250->lsr_saved_flags = 0; + } uart_setreg(bas, REG_FCR, fcr); uart_barrier(bas); } @@ -203,6 +211,9 @@ int divisor; uint8_t lcr; + struct ns8250_softc *ns8250 = (struct ns8250_softc *)bas; + ns8250->lsr_saved_flags = 0; + lcr = 0; if (databits >= 8) lcr |= LCR_8BITS; @@ -333,8 +344,10 @@ static int ns8250_rxready(struct uart_bas *bas) { - - return ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) != 0 ? 1 : 0); + uint8_t lsr = uart_getreg(bas, REG_LSR); + struct ns8250_softc *ns8250 = (struct ns8250_softc *)bas; + ns8250->lsr_saved_flags = lsr; + return ((lsr & LSR_RXRDY) != 0 ? 1 : 0); } static int @@ -344,10 +357,16 @@ uart_lock(hwmtx); - while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0) { + uint8_t lsr = uart_getreg(bas, REG_LSR); + struct ns8250_softc *ns8250 = (struct ns8250_softc *)bas; + ns8250->lsr_saved_flags = lsr; + + while ((lsr & LSR_RXRDY) == 0) { uart_unlock(hwmtx); DELAY(4); uart_lock(hwmtx); + lsr = uart_getreg(bas, REG_LSR); + ns8250->lsr_saved_flags = lsr; } c = uart_getreg(bas, REG_DATA); @@ -683,6 +702,8 @@ ipend = 0; if (iir & IIR_RXRDY) { lsr = uart_getreg(bas, REG_LSR); + ns8250->lsr_saved_flags = lsr; + if (lsr & LSR_OE) ipend |= SER_INT_OVERRUN; if (lsr & LSR_BI) @@ -894,12 +915,18 @@ ns8250_bus_receive(struct uart_softc *sc) { struct uart_bas *bas; + struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; int xc; uint8_t lsr; bas = &sc->sc_bas; uart_lock(sc->sc_hwmtx); - lsr = uart_getreg(bas, REG_LSR); + if (ns8250->lsr_saved_flags != 0) { + lsr = ns8250->lsr_saved_flags; + } else { + lsr = uart_getreg(bas, REG_LSR); + } + ns8250->lsr_saved_flags = 0; while (lsr & LSR_RXRDY) { if (uart_rx_full(sc)) { sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;