diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/uart/uart_bus.h | 2 | ||||
-rw-r--r-- | sys/dev/uart/uart_core.c | 2 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_i8251.c | 42 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_ns8250.c | 42 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_sab82532.c | 28 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_z8530.c | 25 | ||||
-rw-r--r-- | sys/dev/uart/uart_if.m | 3 |
7 files changed, 117 insertions, 27 deletions
diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h index bd0bab7..dde9ff8 100644 --- a/sys/dev/uart/uart_bus.h +++ b/sys/dev/uart/uart_bus.h @@ -113,6 +113,8 @@ struct uart_softc { struct uart_bas sc_bas; device_t sc_dev; + struct mtx sc_hwmtx; /* Spinlock protecting hardware. */ + struct resource *sc_rres; /* Register resource. */ int sc_rrid; int sc_rtype; /* SYS_RES_{IOPORT|MEMORY}. */ diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c index 883bea2..dd4f91c 100644 --- a/sys/dev/uart/uart_core.c +++ b/sys/dev/uart/uart_core.c @@ -309,6 +309,8 @@ uart_bus_attach(device_t dev) */ sc->sc_leaving = 1; + mtx_init(&sc->sc_hwmtx, "uart_hwmtx", NULL, MTX_SPIN); + /* * Re-allocate. We expect that the softc contains the information * collected by uart_bus_probe() intact. diff --git a/sys/dev/uart/uart_dev_i8251.c b/sys/dev/uart/uart_dev_i8251.c index a953b98..9e9a5b2 100644 --- a/sys/dev/uart/uart_dev_i8251.c +++ b/sys/dev/uart/uart_dev_i8251.c @@ -427,15 +427,19 @@ i8251_bus_flush(struct uart_softc *sc, int what) { struct i8251_softc *i8251 = (struct i8251_softc*)sc; struct uart_bas *bas; + int error; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); if (sc->sc_hasfifo) { i8251_flush(bas, what); uart_setreg(bas, REG_FCR, i8251->fcr); uart_barrier(bas); - return (0); - } - return (i8251_drain(bas, what)); + error = 0; + } else + error = i8251_drain(bas, what); + mtx_unlock_spin(&sc->sc_hwmtx); + return (error); } static int @@ -447,7 +451,9 @@ i8251_bus_getsig(struct uart_softc *sc) do { old = sc->sc_hwsig; sig = old; + mtx_lock_spin(&sc->sc_hwmtx); msr = uart_getreg(&sc->sc_bas, REG_MSR); + mtx_unlock_spin(&sc->sc_hwmtx); SIGCHG(msr & MSR_DSR, sig, UART_SIG_DSR, UART_SIG_DDSR); SIGCHG(msr & MSR_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS); SIGCHG(msr & MSR_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD); @@ -461,9 +467,12 @@ static int i8251_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) { struct uart_bas *bas; + int error; uint8_t lcr; bas = &sc->sc_bas; + error = 0; + mtx_lock_spin(&sc->sc_hwmtx); switch (request) { case UART_IOCTL_BREAK: lcr = uart_getreg(bas, REG_LCR); @@ -475,9 +484,11 @@ i8251_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) uart_barrier(bas); break; default: - return (EINVAL); + error = EINVAL; + break; } - return (0); + mtx_unlock_spin(&sc->sc_hwmtx); + return (error); } static int @@ -488,13 +499,16 @@ i8251_bus_ipend(struct uart_softc *sc) uint8_t iir, lsr; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); iir = uart_getreg(bas, REG_IIR); - if (iir & IIR_NOPEND) + if (iir & IIR_NOPEND) { + mtx_unlock_spin(&sc->sc_hwmtx); return (0); - + } ipend = 0; if (iir & IIR_RXRDY) { lsr = uart_getreg(bas, REG_LSR); + mtx_unlock_spin(&sc->sc_hwmtx); if (lsr & LSR_OE) ipend |= UART_IPEND_OVERRUN; if (lsr & LSR_BI) @@ -502,12 +516,12 @@ i8251_bus_ipend(struct uart_softc *sc) if (lsr & LSR_RXRDY) ipend |= UART_IPEND_RXREADY; } else { + mtx_unlock_spin(&sc->sc_hwmtx); if (iir & IIR_TXRDY) ipend |= UART_IPEND_TXIDLE; else ipend |= UART_IPEND_SIGCHG; } - return ((sc->sc_leaving) ? 0 : ipend); } @@ -516,9 +530,13 @@ i8251_bus_param(struct uart_softc *sc, int baudrate, int databits, int stopbits, int parity) { struct uart_bas *bas; + int error; bas = &sc->sc_bas; - return (i8251_param(bas, baudrate, databits, stopbits, parity)); + mtx_lock_spin(&sc->sc_hwmtx); + error = i8251_param(bas, baudrate, databits, stopbits, parity); + mtx_unlock_spin(&sc->sc_hwmtx); + return (error); } static int @@ -661,6 +679,7 @@ i8251_bus_receive(struct uart_softc *sc) uint8_t lsr; 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) @@ -672,6 +691,7 @@ i8251_bus_receive(struct uart_softc *sc) xc |= UART_STAT_PARERR; uart_rx_put(sc, xc); } + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -695,6 +715,7 @@ i8251_bus_setsig(struct uart_softc *sc, int sig) UART_SIG_DRTS); } } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); + mtx_lock_spin(&sc->sc_hwmtx); i8251->mcr &= ~(MCR_DTR|MCR_RTS); if (new & UART_SIG_DTR) i8251->mcr |= MCR_DTR; @@ -702,6 +723,7 @@ i8251_bus_setsig(struct uart_softc *sc, int sig) i8251->mcr |= MCR_RTS; uart_setreg(bas, REG_MCR, i8251->mcr); uart_barrier(bas); + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -713,6 +735,7 @@ i8251_bus_transmit(struct uart_softc *sc) int i; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0) ; uart_setreg(bas, REG_IER, i8251->ier | IER_ETXRDY); @@ -722,5 +745,6 @@ i8251_bus_transmit(struct uart_softc *sc) uart_barrier(bas); } sc->sc_txbusy = 1; + 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 ada5710..7c4d264 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -427,15 +427,19 @@ ns8250_bus_flush(struct uart_softc *sc, int what) { struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; struct uart_bas *bas; + int error; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); if (sc->sc_hasfifo) { ns8250_flush(bas, what); uart_setreg(bas, REG_FCR, ns8250->fcr); uart_barrier(bas); - return (0); - } - return (ns8250_drain(bas, what)); + error = 0; + } else + error = ns8250_drain(bas, what); + mtx_unlock_spin(&sc->sc_hwmtx); + return (error); } static int @@ -447,7 +451,9 @@ ns8250_bus_getsig(struct uart_softc *sc) do { old = sc->sc_hwsig; sig = old; + mtx_lock_spin(&sc->sc_hwmtx); msr = uart_getreg(&sc->sc_bas, REG_MSR); + mtx_unlock_spin(&sc->sc_hwmtx); SIGCHG(msr & MSR_DSR, sig, UART_SIG_DSR, UART_SIG_DDSR); SIGCHG(msr & MSR_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS); SIGCHG(msr & MSR_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD); @@ -461,9 +467,12 @@ static int ns8250_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) { struct uart_bas *bas; + int error; uint8_t efr, lcr; bas = &sc->sc_bas; + error = 0; + mtx_lock_spin(&sc->sc_hwmtx); switch (request) { case UART_IOCTL_BREAK: lcr = uart_getreg(bas, REG_LCR); @@ -505,9 +514,11 @@ ns8250_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) uart_barrier(bas); break; default: - return (EINVAL); + error = EINVAL; + break; } - return (0); + mtx_unlock_spin(&sc->sc_hwmtx); + return (error); } static int @@ -518,13 +529,16 @@ ns8250_bus_ipend(struct uart_softc *sc) uint8_t iir, lsr; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); iir = uart_getreg(bas, REG_IIR); - if (iir & IIR_NOPEND) + if (iir & IIR_NOPEND) { + mtx_unlock_spin(&sc->sc_hwmtx); return (0); - + } ipend = 0; if (iir & IIR_RXRDY) { lsr = uart_getreg(bas, REG_LSR); + mtx_unlock_spin(&sc->sc_hwmtx); if (lsr & LSR_OE) ipend |= UART_IPEND_OVERRUN; if (lsr & LSR_BI) @@ -532,12 +546,12 @@ ns8250_bus_ipend(struct uart_softc *sc) if (lsr & LSR_RXRDY) ipend |= UART_IPEND_RXREADY; } else { + mtx_unlock_spin(&sc->sc_hwmtx); if (iir & IIR_TXRDY) ipend |= UART_IPEND_TXIDLE; else ipend |= UART_IPEND_SIGCHG; } - return ((sc->sc_leaving) ? 0 : ipend); } @@ -546,9 +560,13 @@ ns8250_bus_param(struct uart_softc *sc, int baudrate, int databits, int stopbits, int parity) { struct uart_bas *bas; + int error; bas = &sc->sc_bas; - return (ns8250_param(bas, baudrate, databits, stopbits, parity)); + mtx_lock_spin(&sc->sc_hwmtx); + error = ns8250_param(bas, baudrate, databits, stopbits, parity); + mtx_unlock_spin(&sc->sc_hwmtx); + return (error); } static int @@ -697,6 +715,7 @@ ns8250_bus_receive(struct uart_softc *sc) uint8_t lsr; 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) @@ -708,6 +727,7 @@ ns8250_bus_receive(struct uart_softc *sc) xc |= UART_STAT_PARERR; uart_rx_put(sc, xc); } + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -731,6 +751,7 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig) UART_SIG_DRTS); } } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); + mtx_lock_spin(&sc->sc_hwmtx); ns8250->mcr &= ~(MCR_DTR|MCR_RTS); if (new & UART_SIG_DTR) ns8250->mcr |= MCR_DTR; @@ -738,6 +759,7 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig) ns8250->mcr |= MCR_RTS; uart_setreg(bas, REG_MCR, ns8250->mcr); uart_barrier(bas); + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -749,6 +771,7 @@ ns8250_bus_transmit(struct uart_softc *sc) int i; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0) ; uart_setreg(bas, REG_IER, ns8250->ier | IER_ETXRDY); @@ -758,5 +781,6 @@ ns8250_bus_transmit(struct uart_softc *sc) uart_barrier(bas); } sc->sc_txbusy = 1; + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } diff --git a/sys/dev/uart/uart_dev_sab82532.c b/sys/dev/uart/uart_dev_sab82532.c index 5345e97..ec1c9f5 100644 --- a/sys/dev/uart/uart_dev_sab82532.c +++ b/sys/dev/uart/uart_dev_sab82532.c @@ -425,7 +425,9 @@ static int sab82532_bus_flush(struct uart_softc *sc, int what) { + mtx_lock_spin(&sc->sc_hwmtx); sab82532_flush(&sc->sc_bas, what); + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -440,6 +442,7 @@ sab82532_bus_getsig(struct uart_softc *sc) do { old = sc->sc_hwsig; sig = old; + mtx_lock_spin(&sc->sc_hwmtx); star = uart_getreg(bas, SAB_STAR); SIGCHG(star & SAB_STAR_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS); vstr = uart_getreg(bas, SAB_VSTR); @@ -447,6 +450,7 @@ sab82532_bus_getsig(struct uart_softc *sc) pvr = uart_getreg(bas, SAB_PVR); pvr &= (IS_CHANNEL_A(bas)) ? SAB_PVR_DSR_A : SAB_PVR_DSR_B; SIGCHG(~pvr, sig, UART_SIG_DSR, UART_SIG_DDSR); + mtx_unlock_spin(&sc->sc_hwmtx); new = sig & ~UART_SIGMASK_DELTA; } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); return (sig); @@ -457,8 +461,11 @@ sab82532_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) { struct uart_bas *bas; uint8_t dafo, mode; + int error; bas = &sc->sc_bas; + error = 0; + mtx_lock_spin(&sc->sc_hwmtx); switch (request) { case UART_IOCTL_BREAK: dafo = uart_getreg(bas, SAB_DAFO); @@ -491,9 +498,11 @@ sab82532_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) uart_barrier(bas); break; default: - return (EINVAL); + error = EINVAL; + break; } - return (0); + mtx_unlock_spin(&sc->sc_hwmtx); + return (error); } static int @@ -504,16 +513,17 @@ sab82532_bus_ipend(struct uart_softc *sc) uint8_t isr0, isr1; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); isr0 = uart_getreg(bas, SAB_ISR0); isr1 = uart_getreg(bas, SAB_ISR1); uart_barrier(bas); - if (isr0 & SAB_ISR0_TIME) { while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC) ; uart_setreg(bas, SAB_CMDR, SAB_CMDR_RFRD); uart_barrier(bas); } + mtx_unlock_spin(&sc->sc_hwmtx); ipend = 0; if (isr1 & SAB_ISR1_BRKT) @@ -535,9 +545,13 @@ sab82532_bus_param(struct uart_softc *sc, int baudrate, int databits, int stopbits, int parity) { struct uart_bas *bas; + int error; bas = &sc->sc_bas; - return (sab82532_param(bas, baudrate, databits, stopbits, parity)); + mtx_lock_spin(&sc->sc_hwmtx); + error = sab82532_param(bas, baudrate, databits, stopbits, parity); + mtx_unlock_spin(&sc->sc_hwmtx); + return (error); } static int @@ -584,6 +598,7 @@ sab82532_bus_receive(struct uart_softc *sc) uint8_t s; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); if (uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE) { rbcl = uart_getreg(bas, SAB_RBCL) & 31; if (rbcl == 0) @@ -607,6 +622,7 @@ sab82532_bus_receive(struct uart_softc *sc) ; uart_setreg(bas, SAB_CMDR, SAB_CMDR_RMC); uart_barrier(bas); + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -631,6 +647,7 @@ sab82532_bus_setsig(struct uart_softc *sc, int sig) } } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); + mtx_lock_spin(&sc->sc_hwmtx); /* Set DTR pin. */ pvr = uart_getreg(bas, SAB_PVR); if (new & UART_SIG_DTR) @@ -647,6 +664,7 @@ sab82532_bus_setsig(struct uart_softc *sc, int sig) mode |= SAB_MODE_FRTS; uart_setreg(bas, SAB_MODE, mode); uart_barrier(bas); + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -657,6 +675,7 @@ sab82532_bus_transmit(struct uart_softc *sc) int i; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); while (!(uart_getreg(bas, SAB_STAR) & SAB_STAR_XFW)) ; for (i = 0; i < sc->sc_txdatasz; i++) @@ -666,5 +685,6 @@ sab82532_bus_transmit(struct uart_softc *sc) ; uart_setreg(bas, SAB_CMDR, SAB_CMDR_XF); sc->sc_txbusy = 1; + 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 a7c6e25..319783a 100644 --- a/sys/dev/uart/uart_dev_z8530.c +++ b/sys/dev/uart/uart_dev_z8530.c @@ -334,15 +334,15 @@ z8530_bus_flush(struct uart_softc *sc, int what) static int z8530_bus_getsig(struct uart_softc *sc) { - struct uart_bas *bas; uint32_t new, old, sig; uint8_t bes; - bas = &sc->sc_bas; do { old = sc->sc_hwsig; sig = old; - bes = uart_getmreg(bas, RR_BES); + mtx_lock_spin(&sc->sc_hwmtx); + bes = uart_getmreg(&sc->sc_bas, RR_BES); + mtx_unlock_spin(&sc->sc_hwmtx); SIGCHG(bes & BES_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS); SIGCHG(bes & BES_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD); new = sig & ~UART_SIGMASK_DELTA; @@ -355,8 +355,11 @@ z8530_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) { struct z8530_softc *z8530 = (struct z8530_softc*)sc; struct uart_bas *bas; + int error; bas = &sc->sc_bas; + error = 0; + mtx_lock_spin(&sc->sc_hwmtx); switch (request) { case UART_IOCTL_BREAK: if (data) @@ -367,9 +370,11 @@ z8530_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) uart_barrier(bas); break; default: - return (EINVAL); + error = EINVAL; + break; } - return (0); + mtx_unlock_spin(&sc->sc_hwmtx); + return (error); } static int @@ -382,6 +387,7 @@ z8530_bus_ipend(struct uart_softc *sc) bas = &sc->sc_bas; ipend = 0; + mtx_lock_spin(&sc->sc_hwmtx); uart_setreg(bas, REG_CTRL, CR_RSTIUS); uart_barrier(bas); bes = uart_getmreg(bas, RR_BES); @@ -405,6 +411,7 @@ z8530_bus_ipend(struct uart_softc *sc) uart_setreg(bas, REG_CTRL, CR_RSTERR); ipend |= UART_IPEND_OVERRUN; } + mtx_unlock_spin(&sc->sc_hwmtx); return (ipend); } @@ -415,8 +422,10 @@ z8530_bus_param(struct uart_softc *sc, int baudrate, int databits, struct z8530_softc *z8530 = (struct z8530_softc*)sc; int error; + mtx_lock_spin(&sc->sc_hwmtx); error = z8530_param(&sc->sc_bas, baudrate, databits, stopbits, parity, &z8530->tpc); + mtx_unlock_spin(&sc->sc_hwmtx); return (error); } @@ -447,6 +456,7 @@ z8530_bus_receive(struct uart_softc *sc) uint8_t bes, src; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); bes = uart_getmreg(bas, RR_BES); while ((bes & BES_RXA) && !uart_rx_full(sc)) { src = uart_getmreg(bas, RR_SRC); @@ -460,6 +470,7 @@ z8530_bus_receive(struct uart_softc *sc) uart_setreg(bas, REG_CTRL, CR_RSTERR); bes = uart_getmreg(bas, RR_BES); } + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -484,6 +495,7 @@ z8530_bus_setsig(struct uart_softc *sc, int sig) } } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); + mtx_lock_spin(&sc->sc_hwmtx); if (new & UART_SIG_DTR) z8530->tpc |= TPC_DTR; else @@ -494,6 +506,7 @@ z8530_bus_setsig(struct uart_softc *sc, int sig) z8530->tpc &= ~TPC_RTS; uart_setmreg(bas, WR_TPC, z8530->tpc); uart_barrier(bas); + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -503,10 +516,12 @@ z8530_bus_transmit(struct uart_softc *sc) struct uart_bas *bas; bas = &sc->sc_bas; + mtx_lock_spin(&sc->sc_hwmtx); while (!(uart_getmreg(bas, RR_BES) & BES_TXE)) ; uart_setreg(bas, REG_DATA, sc->sc_txbuf[0]); uart_barrier(bas); sc->sc_txbusy = 1; + mtx_unlock_spin(&sc->sc_hwmtx); return (0); } diff --git a/sys/dev/uart/uart_if.m b/sys/dev/uart/uart_if.m index 772883d..762c16e 100644 --- a/sys/dev/uart/uart_if.m +++ b/sys/dev/uart/uart_if.m @@ -24,6 +24,9 @@ # # $FreeBSD$ +#include <sys/param.h> +#include <sys/lock.h> +#include <sys/mutex.h> #include <sys/bus.h> #include <machine/bus.h> #include <dev/uart/uart.h> |