diff options
-rw-r--r-- | sys/arm/s3c2xx0/uart_dev_s3c2410.c | 24 | ||||
-rw-r--r-- | sys/arm/sa11x0/uart_dev_sa1110.c | 30 | ||||
-rw-r--r-- | sys/arm/xilinx/uart_dev_cdnc.c | 25 | ||||
-rw-r--r-- | sys/dev/uart/uart_core.c | 23 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu.h | 30 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_imx.c | 40 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_lpc.c | 35 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_ns8250.c | 33 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_ns8250.h | 2 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_pl011.c | 29 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_quicc.c | 35 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_sab82532.c | 33 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_z8530.c | 28 | ||||
-rw-r--r-- | sys/dev/uart/uart_if.m | 16 | ||||
-rw-r--r-- | sys/mips/adm5120/uart_dev_adm5120.c | 27 | ||||
-rw-r--r-- | sys/mips/atheros/uart_dev_ar933x.c | 32 | ||||
-rw-r--r-- | sys/mips/cavium/uart_dev_oct16550.c | 35 | ||||
-rw-r--r-- | sys/mips/rt305x/uart_dev_rt305x.c | 31 |
18 files changed, 466 insertions, 42 deletions
diff --git a/sys/arm/s3c2xx0/uart_dev_s3c2410.c b/sys/arm/s3c2xx0/uart_dev_s3c2410.c index 0f9f798..aadd835 100644 --- a/sys/arm/s3c2xx0/uart_dev_s3c2410.c +++ b/sys/arm/s3c2xx0/uart_dev_s3c2410.c @@ -203,7 +203,6 @@ s3c2410_getc(struct uart_bas *bas, struct mtx *mtx) return sscom_getc(bas->bst, bas->bsh); } - static int s3c2410_bus_probe(struct uart_softc *sc); static int s3c2410_bus_attach(struct uart_softc *sc); static int s3c2410_bus_flush(struct uart_softc *, int); @@ -214,6 +213,8 @@ static int s3c2410_bus_param(struct uart_softc *, int, int, int, int); static int s3c2410_bus_receive(struct uart_softc *); static int s3c2410_bus_setsig(struct uart_softc *, int); static int s3c2410_bus_transmit(struct uart_softc *); +static void s3c2410_bus_grab(struct uart_softc *); +static void s3c2410_bus_ungrab(struct uart_softc *); static kobj_method_t s3c2410_methods[] = { KOBJMETHOD(uart_probe, s3c2410_bus_probe), @@ -226,6 +227,8 @@ static kobj_method_t s3c2410_methods[] = { KOBJMETHOD(uart_receive, s3c2410_bus_receive), KOBJMETHOD(uart_setsig, s3c2410_bus_setsig), KOBJMETHOD(uart_transmit, s3c2410_bus_transmit), + KOBJMETHOD(uart_grab, s3c2410_bus_grab), + KOBJMETHOD(uart_ungrab, s3c2410_bus_ungrab), {0, 0 } }; @@ -373,6 +376,25 @@ s3c2410_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) return (EINVAL); } + +static void +s3c2410_bus_grab(struct uart_softc *sc) +{ + uintptr_t irq; + + irq = rman_get_start(sc->sc_ires); + arm_mask_irq(get_sub_irq(irq, RX_OFF)); +} + +static void +s3c2410_bus_ungrab(struct uart_softc *sc) +{ + uintptr_t irq; + + irq = rman_get_start(sc->sc_ires); + arm_unmask_irq(get_sub_irq(irq, RX_OFF)); +} + struct uart_class uart_s3c2410_class = { "s3c2410 class", s3c2410_methods, diff --git a/sys/arm/sa11x0/uart_dev_sa1110.c b/sys/arm/sa11x0/uart_dev_sa1110.c index 6765cf2..1df1009 100644 --- a/sys/arm/sa11x0/uart_dev_sa1110.c +++ b/sys/arm/sa11x0/uart_dev_sa1110.c @@ -137,6 +137,8 @@ static int sa1110_bus_param(struct uart_softc *, int, int, int, int); static int sa1110_bus_receive(struct uart_softc *); static int sa1110_bus_setsig(struct uart_softc *, int); static int sa1110_bus_transmit(struct uart_softc *); +static void sa1110_bus_grab(struct uart_softc *); +static void sa1110_bus_ungrab(struct uart_softc *); static kobj_method_t sa1110_methods[] = { KOBJMETHOD(uart_probe, sa1110_bus_probe), @@ -149,6 +151,8 @@ static kobj_method_t sa1110_methods[] = { KOBJMETHOD(uart_receive, sa1110_bus_receive), KOBJMETHOD(uart_setsig, sa1110_bus_setsig), KOBJMETHOD(uart_transmit, sa1110_bus_transmit), + KOBJMETHOD(uart_grab, sa1110_bus_grab), + KOBJMETHOD(uart_ungrab, sa1110_bus_ungrab), {0, 0 } }; @@ -164,10 +168,10 @@ sa1110_bus_probe(struct uart_softc *sc) static int sa1110_bus_attach(struct uart_softc *sc) { - bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); + bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); - sc->sc_hwiflow = 0; - uart_setreg(&sc->sc_bas, SACOM_CR3, CR3_RXE | CR3_TXE | CR3_RIE | CR3_TIE); + sc->sc_hwiflow = 0; + uart_setreg(&sc->sc_bas, SACOM_CR3, CR3_RXE | CR3_TXE | CR3_RIE | CR3_TIE); return (0); } static int @@ -273,6 +277,26 @@ sa1110_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) return (EINVAL); } +static void +sa1110_bus_grab(struct uart_softc *sc) +{ + + /* Turn off Rx interrupts */ + uart_lock(sc->sc_hwmtx); + uart_setreg(&sc->sc_bas, SACOM_CR3, CR3_TXE | CR3_TIE); + uart_unlock(sc->sc_hwmtx); +} + +static void +sa1110_bus_ungrab(struct uart_softc *sc) +{ + + /* Turn on Rx interrupts */ + uart_lock(sc->sc_hwmtx); + uart_setreg(&sc->sc_bas, SACOM_CR3, CR3_RXE | CR3_TXE | CR3_RIE | CR3_TIE); + uart_unlock(sc->sc_hwmtx); +} + struct uart_class uart_sa1110_class = { "sa1110", sa1110_methods, diff --git a/sys/arm/xilinx/uart_dev_cdnc.c b/sys/arm/xilinx/uart_dev_cdnc.c index a008853..6224503 100644 --- a/sys/arm/xilinx/uart_dev_cdnc.c +++ b/sys/arm/xilinx/uart_dev_cdnc.c @@ -398,6 +398,8 @@ static int cdnc_uart_bus_param(struct uart_softc *, int, int, int, int); static int cdnc_uart_bus_receive(struct uart_softc *); static int cdnc_uart_bus_setsig(struct uart_softc *, int); static int cdnc_uart_bus_transmit(struct uart_softc *); +static void cdnc_uart_bus_grab(struct uart_softc *); +static void cdnc_uart_bus_ungrab(struct uart_softc *); static kobj_method_t cdnc_uart_bus_methods[] = { KOBJMETHOD(uart_probe, cdnc_uart_bus_probe), @@ -410,6 +412,8 @@ static kobj_method_t cdnc_uart_bus_methods[] = { KOBJMETHOD(uart_receive, cdnc_uart_bus_receive), KOBJMETHOD(uart_setsig, cdnc_uart_bus_setsig), KOBJMETHOD(uart_transmit, cdnc_uart_bus_transmit), + KOBJMETHOD(uart_grab, cdnc_uart_bus_grab), + KOBJMETHOD(uart_ungrab, cdnc_uart_bus_ungrab), KOBJMETHOD_END }; @@ -675,6 +679,27 @@ cdnc_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) return (error); } +static void +cdnc_uart_bus_grab(struct uart_softc *sc) +{ + + /* Enable interrupts. */ + WR4(&sc->sc_bas, CDNC_UART_IEN_REG, + CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR | + CDNC_UART_INT_DMSI); +} + +static void +cdnc_uart_bus_ungrab(struct uart_softc *sc) +{ + + /* Enable interrupts. */ + WR4(&sc->sc_bas, CDNC_UART_IEN_REG, + CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT | + CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR | + CDNC_UART_INT_DMSI); +} + struct uart_class uart_cdnc_class = { "cdnc_uart", cdnc_uart_bus_methods, diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c index 17dabd7..eea2d8c 100644 --- a/sys/dev/uart/uart_core.c +++ b/sys/dev/uart/uart_core.c @@ -412,6 +412,13 @@ uart_bus_attach(device_t dev) sc = sc0; /* + * Now that we know the softc for this device, connect the back + * pointer from the sysdev for this device, if any + */ + if (sc->sc_sysdev != NULL) + sc->sc_sysdev->sc = sc; + + /* * Protect ourselves against interrupts while we're not completely * finished attaching and initializing. We don't expect interrupts * until after UART_ATTACH() though. @@ -617,3 +624,19 @@ uart_bus_resume(device_t dev) sc = device_get_softc(dev); return (UART_ATTACH(sc)); } + +void +uart_grab(struct uart_devinfo *di) +{ + + if (di->sc) + UART_GRAB(di->sc); +} + +void +uart_ungrab(struct uart_devinfo *di) +{ + + if (di->sc) + UART_UNGRAB(di->sc); +} diff --git a/sys/dev/uart/uart_cpu.h b/sys/dev/uart/uart_cpu.h index 99ced1a..2db0412 100644 --- a/sys/dev/uart/uart_cpu.h +++ b/sys/dev/uart/uart_cpu.h @@ -33,6 +33,8 @@ #include <sys/lock.h> #include <sys/mutex.h> +struct uart_softc; + /* * Low-level operations for use by console and/or debug port support. */ @@ -43,8 +45,6 @@ struct uart_ops { void (*putc)(struct uart_bas *, int); int (*rxready)(struct uart_bas *); int (*getc)(struct uart_bas *, struct mtx *); - void (*grab)(struct uart_bas *); - void (*ungrab)(struct uart_bas *); }; extern bus_space_tag_t uart_bus_space_io; @@ -53,7 +53,6 @@ extern bus_space_tag_t uart_bus_space_mem; /* * Console and debug port device info. */ -struct uart_softc; struct uart_devinfo { SLIST_ENTRY(uart_devinfo) next; struct uart_ops *ops; @@ -70,6 +69,7 @@ struct uart_devinfo { int (*detach)(struct uart_softc*); void *cookie; /* Type dependent use. */ struct mtx *hwmtx; + struct uart_softc *sc; /* valid only from start of attach */ }; int uart_cpu_eqres(struct uart_bas *, struct uart_bas *); @@ -137,27 +137,6 @@ uart_putc(struct uart_devinfo *di, int c) uart_unlock(di->hwmtx); } -static __inline void -uart_grab(struct uart_devinfo *di) -{ - - uart_lock(di->hwmtx); - if (di->ops->grab) - di->ops->grab(&di->bas); - uart_unlock(di->hwmtx); -} - -static __inline void -uart_ungrab(struct uart_devinfo *di) -{ - - uart_lock(di->hwmtx); - if (di->ops->ungrab) - di->ops->ungrab(&di->bas); - uart_unlock(di->hwmtx); -} - - static __inline int uart_rxready(struct uart_devinfo *di) { @@ -190,4 +169,7 @@ uart_getc(struct uart_devinfo *di) return (di->ops->getc(&di->bas, di->hwmtx)); } +void uart_grab(struct uart_devinfo *di); +void uart_ungrab(struct uart_devinfo *di); + #endif /* _DEV_UART_CPU_H_ */ diff --git a/sys/dev/uart/uart_dev_imx.c b/sys/dev/uart/uart_dev_imx.c index 1651a9f..e99cf77 100644 --- a/sys/dev/uart/uart_dev_imx.c +++ b/sys/dev/uart/uart_dev_imx.c @@ -140,6 +140,8 @@ static int imx_uart_bus_probe(struct uart_softc *); static int imx_uart_bus_receive(struct uart_softc *); static int imx_uart_bus_setsig(struct uart_softc *, int); static int imx_uart_bus_transmit(struct uart_softc *); +static void imx_uart_bus_grab(struct uart_softc *); +static void imx_uart_bus_ungrab(struct uart_softc *); static kobj_method_t imx_uart_methods[] = { KOBJMETHOD(uart_attach, imx_uart_bus_attach), @@ -153,6 +155,8 @@ static kobj_method_t imx_uart_methods[] = { KOBJMETHOD(uart_receive, imx_uart_bus_receive), KOBJMETHOD(uart_setsig, imx_uart_bus_setsig), KOBJMETHOD(uart_transmit, imx_uart_bus_transmit), + KOBJMETHOD(uart_grab, imx_uart_bus_grab), + KOBJMETHOD(uart_ungrab, imx_uart_bus_ungrab), { 0, 0 } }; @@ -189,12 +193,7 @@ imx_uart_bus_attach(struct uart_softc *sc) (void)imx_uart_bus_getsig(sc); - /* XXX workaround to have working console on manut prompt */ - if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE){ - DIS(bas, UCR4, DREN); - } else { - ENA(bas, UCR4, DREN); - } + ENA(bas, UCR4, DREN); DIS(bas, UCR1, RRDYEN); DIS(bas, UCR1, IDEN); DIS(bas, UCR3, RXDSEN); @@ -402,13 +401,6 @@ static int imx_uart_bus_setsig(struct uart_softc *sc, int sig) { - /* TODO: implement (?) */ - - /* XXX workaround to have working console on mount prompt */ - /* Enable RX interrupt */ - if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) - if (!IS(&sc->sc_bas, UCR4, DREN)) - ENA(&sc->sc_bas, UCR4, DREN); return (0); } @@ -434,3 +426,25 @@ imx_uart_bus_transmit(struct uart_softc *sc) return (0); } + +static void +imx_uart_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + DIS(bas, UCR4, DREN); + uart_unlock(sc->sc_hwmtx); +} + +static void +imx_uart_bus_ungrab(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + ENA(bas, UCR4, DREN); + uart_unlock(sc->sc_hwmtx); +} diff --git a/sys/dev/uart/uart_dev_lpc.c b/sys/dev/uart/uart_dev_lpc.c index fc981ec..ba87a17 100644 --- a/sys/dev/uart/uart_dev_lpc.c +++ b/sys/dev/uart/uart_dev_lpc.c @@ -400,6 +400,8 @@ static int lpc_ns8250_bus_probe(struct uart_softc *); static int lpc_ns8250_bus_receive(struct uart_softc *); static int lpc_ns8250_bus_setsig(struct uart_softc *, int); static int lpc_ns8250_bus_transmit(struct uart_softc *); +static void lpc_ns8250_bus_grab(struct uart_softc *); +static void lpc_ns8250_bus_ungrab(struct uart_softc *); static kobj_method_t lpc_ns8250_methods[] = { KOBJMETHOD(uart_attach, lpc_ns8250_bus_attach), @@ -413,6 +415,8 @@ static kobj_method_t lpc_ns8250_methods[] = { KOBJMETHOD(uart_receive, lpc_ns8250_bus_receive), KOBJMETHOD(uart_setsig, lpc_ns8250_bus_setsig), KOBJMETHOD(uart_transmit, lpc_ns8250_bus_transmit), + KOBJMETHOD(uart_grab, lpc_ns8250_bus_grab), + KOBJMETHOD(uart_ungrab, lpc_ns8250_bus_ungrab), { 0, 0 } }; @@ -889,3 +893,34 @@ lpc_ns8250_bus_transmit(struct uart_softc *sc) uart_unlock(sc->sc_hwmtx); return (0); } + +void +lpc_ns8250_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + + /* + * turn off all interrupts to enter polling mode. Leave the + * saved mask alone. We'll restore whatever it was in ungrab. + * All pending interupt signals are reset when IER is set to 0. + */ + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, REG_IER, 0); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} + +void +lpc_ns8250_bus_ungrab(struct uart_softc *sc) +{ + struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc; + struct uart_bas *bas = &sc->sc_bas; + + /* + * Restore previous interrupt mask + */ + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, REG_IER, lpc_ns8250->ier); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index 211d113..31b1aba 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -365,6 +365,8 @@ static kobj_method_t ns8250_methods[] = { KOBJMETHOD(uart_receive, ns8250_bus_receive), KOBJMETHOD(uart_setsig, ns8250_bus_setsig), KOBJMETHOD(uart_transmit, ns8250_bus_transmit), + KOBJMETHOD(uart_grab, ns8250_bus_grab), + KOBJMETHOD(uart_ungrab, ns8250_bus_ungrab), { 0, 0 } }; @@ -898,3 +900,34 @@ ns8250_bus_transmit(struct uart_softc *sc) uart_sched_softih(sc, SER_INT_TXIDLE); return (0); } + +void +ns8250_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + + /* + * turn off all interrupts to enter polling mode. Leave the + * saved mask alone. We'll restore whatever it was in ungrab. + * All pending interupt signals are reset when IER is set to 0. + */ + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, REG_IER, 0); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} + +void +ns8250_bus_ungrab(struct uart_softc *sc) +{ + struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; + struct uart_bas *bas = &sc->sc_bas; + + /* + * Restore previous interrupt mask + */ + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, REG_IER, ns8250->ier); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} diff --git a/sys/dev/uart/uart_dev_ns8250.h b/sys/dev/uart/uart_dev_ns8250.h index 39f4a0f..0046dfe 100644 --- a/sys/dev/uart/uart_dev_ns8250.h +++ b/sys/dev/uart/uart_dev_ns8250.h @@ -56,5 +56,7 @@ int ns8250_bus_probe(struct uart_softc *); int ns8250_bus_receive(struct uart_softc *); int ns8250_bus_setsig(struct uart_softc *, int); int ns8250_bus_transmit(struct uart_softc *); +void ns8250_bus_grab(struct uart_softc *); +void ns8250_bus_ungrab(struct uart_softc *); #endif /* _DEV_UART_DEV_NS8250_H_ */ diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c index 82e8b03..3253cd1 100644 --- a/sys/dev/uart/uart_dev_pl011.c +++ b/sys/dev/uart/uart_dev_pl011.c @@ -242,6 +242,8 @@ static int uart_pl011_bus_probe(struct uart_softc *); static int uart_pl011_bus_receive(struct uart_softc *); static int uart_pl011_bus_setsig(struct uart_softc *, int); static int uart_pl011_bus_transmit(struct uart_softc *); +static void uart_pl011_bus_grab(struct uart_softc *); +static void uart_pl011_bus_ungrab(struct uart_softc *); static kobj_method_t uart_pl011_methods[] = { KOBJMETHOD(uart_attach, uart_pl011_bus_attach), @@ -255,6 +257,9 @@ static kobj_method_t uart_pl011_methods[] = { KOBJMETHOD(uart_receive, uart_pl011_bus_receive), KOBJMETHOD(uart_setsig, uart_pl011_bus_setsig), KOBJMETHOD(uart_transmit, uart_pl011_bus_transmit), + KOBJMETHOD(uart_grab, uart_pl011_bus_grab), + KOBJMETHOD(uart_ungrab, uart_pl011_bus_ungrab), + { 0, 0 } }; @@ -441,3 +446,27 @@ uart_pl011_bus_transmit(struct uart_softc *sc) return (0); } + +static void +uart_pl011_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + __uart_setreg(bas, UART_IMSC, /* Switch to RX polling while grabbed */ + ~UART_RXREADY & __uart_getreg(bas, UART_IMSC)); + uart_unlock(sc->sc_hwmtx); +} + +static void +uart_pl011_bus_ungrab(struct uart_softc *sc) +{ + struct uart_bas *bas; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + __uart_setreg(bas, UART_IMSC, /* Switch to RX interrupts while not grabbed */ + UART_RXREADY | __uart_getreg(bas, UART_IMSC)); + uart_unlock(sc->sc_hwmtx); +} diff --git a/sys/dev/uart/uart_dev_quicc.c b/sys/dev/uart/uart_dev_quicc.c index 337591e..bbbc3bd 100644 --- a/sys/dev/uart/uart_dev_quicc.c +++ b/sys/dev/uart/uart_dev_quicc.c @@ -245,6 +245,8 @@ static int quicc_bus_probe(struct uart_softc *); static int quicc_bus_receive(struct uart_softc *); static int quicc_bus_setsig(struct uart_softc *, int); static int quicc_bus_transmit(struct uart_softc *); +static void quicc_bus_grab(struct uart_softc *); +static void quicc_bus_ungrab(struct uart_softc *); static kobj_method_t quicc_methods[] = { KOBJMETHOD(uart_attach, quicc_bus_attach), @@ -258,6 +260,8 @@ static kobj_method_t quicc_methods[] = { KOBJMETHOD(uart_receive, quicc_bus_receive), KOBJMETHOD(uart_setsig, quicc_bus_setsig), KOBJMETHOD(uart_transmit, quicc_bus_transmit), + KOBJMETHOD(uart_grab, quicc_bus_grab), + KOBJMETHOD(uart_ungrab, quicc_bus_ungrab), { 0, 0 } }; @@ -485,3 +489,34 @@ quicc_bus_transmit(struct uart_softc *sc) uart_unlock(sc->sc_hwmtx); return (0); } + +static void +quicc_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas; + uint16_t st, rb; + + /* Disable interrupts on the receive buffer. */ + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1)); + st = quicc_read2(bas, rb); + quicc_write2(bas, rb, st & ~0x9000); + uart_unlock(sc->sc_hwmtx); +} + +static void +quicc_bus_ungrab(struct uart_softc *sc) +{ + struct uart_bas *bas; + uint16_t st, rb; + + /* Enable interrupts on the receive buffer. */ + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1)); + st = quicc_read2(bas, rb); + quicc_write2(bas, rb, st | 0x9000); + uart_unlock(sc->sc_hwmtx); +} + diff --git a/sys/dev/uart/uart_dev_sab82532.c b/sys/dev/uart/uart_dev_sab82532.c index e2ec227..8caa7a7 100644 --- a/sys/dev/uart/uart_dev_sab82532.c +++ b/sys/dev/uart/uart_dev_sab82532.c @@ -365,6 +365,8 @@ static int sab82532_bus_probe(struct uart_softc *); static int sab82532_bus_receive(struct uart_softc *); static int sab82532_bus_setsig(struct uart_softc *, int); static int sab82532_bus_transmit(struct uart_softc *); +static void sab82532_bus_grab(struct uart_softc *); +static void sab82532_bus_ungrab(struct uart_softc *); static kobj_method_t sab82532_methods[] = { KOBJMETHOD(uart_attach, sab82532_bus_attach), @@ -378,6 +380,8 @@ static kobj_method_t sab82532_methods[] = { KOBJMETHOD(uart_receive, sab82532_bus_receive), KOBJMETHOD(uart_setsig, sab82532_bus_setsig), KOBJMETHOD(uart_transmit, sab82532_bus_transmit), + KOBJMETHOD(uart_grab, sab82532_bus_grab), + KOBJMETHOD(uart_ungrab, sab82532_bus_ungrab), { 0, 0 } }; @@ -724,3 +728,32 @@ sab82532_bus_transmit(struct uart_softc *sc) uart_unlock(sc->sc_hwmtx); return (0); } + +static void +sab82532_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas; + uint8_t imr0; + + bas = &sc->sc_bas; + imr0 = SAB_IMR0_TIME|SAB_IMR0_CDSC|SAB_IMR0_RFO; /* No TCD or RPF */ + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, SAB_IMR0, 0xff & ~imr0); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} + +static void +sab82532_bus_ungrab(struct uart_softc *sc) +{ + struct uart_bas *bas; + uint8_t imr0; + + bas = &sc->sc_bas; + imr0 = SAB_IMR0_TCD|SAB_IMR0_TIME|SAB_IMR0_CDSC|SAB_IMR0_RFO| + SAB_IMR0_RPF; + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, SAB_IMR0, 0xff & ~imr0); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c index f948b26..5cc24a8 100644 --- a/sys/dev/uart/uart_dev_z8530.c +++ b/sys/dev/uart/uart_dev_z8530.c @@ -281,6 +281,8 @@ static int z8530_bus_probe(struct uart_softc *); static int z8530_bus_receive(struct uart_softc *); static int z8530_bus_setsig(struct uart_softc *, int); static int z8530_bus_transmit(struct uart_softc *); +static void z8530_bus_grab(struct uart_softc *); +static void z8530_bus_ungrab(struct uart_softc *); static kobj_method_t z8530_methods[] = { KOBJMETHOD(uart_attach, z8530_bus_attach), @@ -294,6 +296,8 @@ static kobj_method_t z8530_methods[] = { KOBJMETHOD(uart_receive, z8530_bus_receive), KOBJMETHOD(uart_setsig, z8530_bus_setsig), KOBJMETHOD(uart_transmit, z8530_bus_transmit), + KOBJMETHOD(uart_grab, z8530_bus_grab), + KOBJMETHOD(uart_ungrab, z8530_bus_ungrab), { 0, 0 } }; @@ -621,3 +625,27 @@ z8530_bus_transmit(struct uart_softc *sc) uart_unlock(sc->sc_hwmtx); return (0); } + +static void +z8530_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} + +static void +z8530_bus_ungrab(struct uart_softc *sc) +{ + struct uart_bas *bas; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE | IDT_RIA); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} diff --git a/sys/dev/uart/uart_if.m b/sys/dev/uart/uart_if.m index bfac071..aab7771 100644 --- a/sys/dev/uart/uart_if.m +++ b/sys/dev/uart/uart_if.m @@ -141,3 +141,19 @@ METHOD int setsig { METHOD int transmit { struct uart_softc *this; }; + +# grab() - Up call from the console to the upper layers of the driver when +# the kernel asks to grab the console. This is valid only for console +# drivers. This method is responsible for transitioning the hardware +# from an interrupt driven state to a polled state that works with the +# low-level console interface defined for this device. The kernel +# currently only calls this when it wants to grab input from the +# console. Output can still happen asyncrhonously to these calls. +METHOD void grab { + struct uart_softc *this; +}; + +# ungrab() - Undoes the effects of grab(). +METHOD void ungrab { + struct uart_softc *this; +}; diff --git a/sys/mips/adm5120/uart_dev_adm5120.c b/sys/mips/adm5120/uart_dev_adm5120.c index 9f2dc02..5ec18c8 100644 --- a/sys/mips/adm5120/uart_dev_adm5120.c +++ b/sys/mips/adm5120/uart_dev_adm5120.c @@ -149,6 +149,8 @@ static int adm5120_uart_bus_probe(struct uart_softc *); static int adm5120_uart_bus_receive(struct uart_softc *); static int adm5120_uart_bus_setsig(struct uart_softc *, int); static int adm5120_uart_bus_transmit(struct uart_softc *); +static void adm5120_uart_bus_grab(struct uart_softc *); +static void adm5120_uart_bus_ungrab(struct uart_softc *); static kobj_method_t adm5120_uart_methods[] = { KOBJMETHOD(uart_attach, adm5120_uart_bus_attach), @@ -162,6 +164,8 @@ static kobj_method_t adm5120_uart_methods[] = { KOBJMETHOD(uart_receive, adm5120_uart_bus_receive), KOBJMETHOD(uart_setsig, adm5120_uart_bus_setsig), KOBJMETHOD(uart_transmit, adm5120_uart_bus_transmit), + KOBJMETHOD(uart_grab, adm5120_uart_bus_grab), + KOBJMETHOD(uart_ungrab, adm5120_uart_bus_ungrab), { 0, 0 } }; @@ -450,3 +454,26 @@ adm5120_uart_bus_transmit(struct uart_softc *sc) uart_unlock(sc->sc_hwmtx); return (0); } + +static void +adm5120_uart_bus_grab(struct uart_softc *sc) +{ + + /* Enable interrupts - no RX_INT or RX_TIMEOUT */ + uart_lock(sc->sc_hwmtx); + uart_setreg(&sc->sc_bas, UART_CR_REG, + UART_CR_PORT_EN | UART_CR_MODEM_STATUS_INT_EN); + uart_unlock(sc->sc_hwmtx); +} + +static void +adm5120_uart_bus_ungrab(struct uart_softc *sc) +{ + + /* Enable interrupts */ + uart_lock(sc->sc_hwmtx); + uart_setreg(&sc->sc_bas, UART_CR_REG, + UART_CR_PORT_EN|UART_CR_RX_INT_EN|UART_CR_RX_TIMEOUT_INT_EN| + UART_CR_MODEM_STATUS_INT_EN); + uart_unlock(sc->sc_hwmtx); +} diff --git a/sys/mips/atheros/uart_dev_ar933x.c b/sys/mips/atheros/uart_dev_ar933x.c index 30f05ba..f719805 100644 --- a/sys/mips/atheros/uart_dev_ar933x.c +++ b/sys/mips/atheros/uart_dev_ar933x.c @@ -325,6 +325,8 @@ static int ar933x_bus_probe(struct uart_softc *); static int ar933x_bus_receive(struct uart_softc *); static int ar933x_bus_setsig(struct uart_softc *, int); static int ar933x_bus_transmit(struct uart_softc *); +static void ar933x_bus_grab(struct uart_softc *); +static void ar933x_bus_ungrab(struct uart_softc *); static kobj_method_t ar933x_methods[] = { KOBJMETHOD(uart_attach, ar933x_bus_attach), @@ -338,6 +340,8 @@ static kobj_method_t ar933x_methods[] = { KOBJMETHOD(uart_receive, ar933x_bus_receive), KOBJMETHOD(uart_setsig, ar933x_bus_setsig), KOBJMETHOD(uart_transmit, ar933x_bus_transmit), + KOBJMETHOD(uart_grab, ar933x_bus_grab), + KOBJMETHOD(uart_ungrab, ar933x_bus_ungrab), { 0, 0 } }; @@ -752,3 +756,31 @@ ar933x_bus_transmit(struct uart_softc *sc) return (0); } + +static void +ar933x_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + uint32_t reg; + + /* Disable the host interrupt now */ + uart_lock(sc->sc_hwmtx); + reg = ar933x_getreg(bas, AR933X_UART_CS_REG); + reg &= ~AR933X_UART_CS_HOST_INT_EN; + ar933x_setreg(bas, AR933X_UART_CS_REG, reg); + uart_unlock(sc->sc_hwmtx); +} + +static void +ar933x_bus_ungrab(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + uint32_t reg; + + /* Enable the host interrupt now */ + uart_lock(sc->sc_hwmtx); + reg = ar933x_getreg(bas, AR933X_UART_CS_REG); + reg |= AR933X_UART_CS_HOST_INT_EN; + ar933x_setreg(bas, AR933X_UART_CS_REG, reg); + uart_unlock(sc->sc_hwmtx); +} diff --git a/sys/mips/cavium/uart_dev_oct16550.c b/sys/mips/cavium/uart_dev_oct16550.c index 753559f..f3d47ca 100644 --- a/sys/mips/cavium/uart_dev_oct16550.c +++ b/sys/mips/cavium/uart_dev_oct16550.c @@ -398,6 +398,8 @@ static int oct16550_bus_probe(struct uart_softc *); static int oct16550_bus_receive(struct uart_softc *); static int oct16550_bus_setsig(struct uart_softc *, int); static int oct16550_bus_transmit(struct uart_softc *); +static void oct16550_bus_grab(struct uart_softc *); +static void oct16550_bus_ungrab(struct uart_softc *); static kobj_method_t oct16550_methods[] = { KOBJMETHOD(uart_attach, oct16550_bus_attach), @@ -411,6 +413,8 @@ static kobj_method_t oct16550_methods[] = { KOBJMETHOD(uart_receive, oct16550_bus_receive), KOBJMETHOD(uart_setsig, oct16550_bus_setsig), KOBJMETHOD(uart_transmit, oct16550_bus_transmit), + KOBJMETHOD(uart_grab, oct16550_bus_grab), + KOBJMETHOD(uart_ungrab, oct16550_bus_ungrab), { 0, 0 } }; @@ -810,3 +814,34 @@ oct16550_bus_transmit (struct uart_softc *sc) uart_unlock(sc->sc_hwmtx); return (0); } + +static void +oct16550_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + + /* + * turn off all interrupts to enter polling mode. Leave the + * saved mask alone. We'll restore whatever it was in ungrab. + * All pending interupt signals are reset when IER is set to 0. + */ + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, REG_IER, 0); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} + +static void +oct16550_bus_ungrab(struct uart_softc *sc) +{ + struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc; + struct uart_bas *bas = &sc->sc_bas; + + /* + * Restore previous interrupt mask + */ + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, REG_IER, oct16550->ier); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} diff --git a/sys/mips/rt305x/uart_dev_rt305x.c b/sys/mips/rt305x/uart_dev_rt305x.c index 94d0386..3154cb9 100644 --- a/sys/mips/rt305x/uart_dev_rt305x.c +++ b/sys/mips/rt305x/uart_dev_rt305x.c @@ -195,6 +195,8 @@ static int rt305x_uart_bus_probe(struct uart_softc *); static int rt305x_uart_bus_receive(struct uart_softc *); static int rt305x_uart_bus_setsig(struct uart_softc *, int); static int rt305x_uart_bus_transmit(struct uart_softc *); +static void rt305x_uart_bus_grab(struct uart_softc *); +static void rt305x_uart_bus_ungrab(struct uart_softc *); static kobj_method_t rt305x_uart_methods[] = { KOBJMETHOD(uart_attach, rt305x_uart_bus_attach), @@ -208,6 +210,8 @@ static kobj_method_t rt305x_uart_methods[] = { KOBJMETHOD(uart_receive, rt305x_uart_bus_receive), KOBJMETHOD(uart_setsig, rt305x_uart_bus_setsig), KOBJMETHOD(uart_transmit, rt305x_uart_bus_transmit), + KOBJMETHOD(uart_grab, rt305x_uart_bus_grab), + KOBJMETHOD(uart_ungrab, rt305x_uart_bus_ungrab), { 0, 0 } }; @@ -278,7 +282,7 @@ rt305x_uart_bus_attach(struct uart_softc *sc) uart_setreg(bas, UART_FCR_REG, uart_getreg(bas, UART_FCR_REG) | UART_FCR_FIFOEN | UART_FCR_TXTGR_1 | UART_FCR_RXTGR_1); - uart_barrier(bas); + uart_barrier(bas); /* Enable interrupts */ uart_setreg(bas, UART_IER_REG, UART_IER_EDSSI | UART_IER_ELSI | UART_IER_ERBFI); @@ -505,3 +509,28 @@ rt305x_uart_bus_transmit(struct uart_softc *sc) uart_unlock(sc->sc_hwmtx); return (0); } + +static void +rt305x_uart_bus_grab(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + + /* disable interrupts -- XXX not sure which one is RX, so kill them all */ + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, UART_IER_REG, 0); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} + +static void +rt305x_uart_bus_ungrab(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + + /* Enable interrupts */ + uart_lock(sc->sc_hwmtx); + uart_setreg(bas, UART_IER_REG, + UART_IER_EDSSI | UART_IER_ELSI | UART_IER_ERBFI); + uart_barrier(bas); + uart_unlock(sc->sc_hwmtx); +} |