Date: Fri, 25 Feb 2005 07:23:17 GMT From: John-Mark Gurney <jmg@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 71797 for review Message-ID: <200502250723.j1P7NH5j037630@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=71797 Change 71797 by jmg@jmg_carbon on 2005/02/25 07:22:17 fix up comments... store the interrupt mask since I need to disable interrupts (? should I really need to?) and restore, to prevent a storm... add a bit of debugging... add in some bits so that we don't wait till the RX fifo is full, but we do trigger on timeout.. Affected files ... .. //depot/projects/arm/src/sys/dev/uart/uart_dev_epuart.c#4 edit Differences ... ==== //depot/projects/arm/src/sys/dev/uart/uart_dev_epuart.c#4 (text+ko) ==== @@ -43,8 +43,7 @@ #include "uart_if.h" /* - * Clear pending interrupts. THRE is cleared by reading IIR. Data - * that may have been received gets lost here. + * Clear pending interrupts. */ static void epuart_clrint(struct uart_bas *bas) @@ -106,8 +105,8 @@ * limit high enough to handle large FIFOs. */ limit = 10*1024; - while (uart_getreg(bas, EP93XX_UART_Flag) & - EP93XX_UART_F_BUSY && --limit) + while ((uart_getreg(bas, EP93XX_UART_Flag) & EP93XX_UART_F_BUSY) + && --limit) DELAY(delay); if (limit == 0) { /* printf("epuart: transmitter appears stuck... "); */ @@ -261,6 +260,9 @@ uart_barrier(bas); } +/* + * Handle RxSts in _poll and _getc? + */ static int epuart_poll(struct uart_bas *bas) { @@ -288,6 +290,7 @@ */ struct epuart_softc { struct uart_softc base; + u_int32_t ctrl; }; static int epuart_bus_attach(struct uart_softc *); @@ -335,10 +338,11 @@ static int epuart_bus_attach(struct uart_softc *sc) { + struct epuart_softc *epsc; struct uart_bas *bas; int mdmctrl; - int ctrl; + epsc = (struct epuart_softc *)sc; bas = &sc->sc_bas; epuart_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER); @@ -354,19 +358,28 @@ } epuart_clrint(bas); - ctrl = EP93XX_UART_MSIE | EP93XX_UART_RIE | EP93XX_UART_UARTE; - uart_setreg(bas, EP93XX_UART_Ctrl, ctrl); + + epsc->ctrl = EP93XX_UART_MSIE | EP93XX_UART_RTIE | + EP93XX_UART_RIE | EP93XX_UART_UARTE; + uart_setreg(bas, EP93XX_UART_Ctrl, epsc->ctrl); uart_barrier(bas); + return (0); } static int epuart_bus_detach(struct uart_softc *sc) { + struct epuart_softc *epsc; struct uart_bas *bas; + epsc = (struct epuart_softc *)sc; bas = &sc->sc_bas; epuart_clrint(bas); + + /* disable UART and Ints */ + epsc->ctrl = 0; + uart_setreg(bas, EP93XX_UART_Ctrl, epsc->ctrl); uart_barrier(bas); return (0); } @@ -452,7 +465,8 @@ error = ENODEV; break; case UART_IOCTL_OFLOW: - /* XXX - hun? I can only read CTS */ + /* hun? I can only read CTS */ + error = EINVAL; break; case UART_IOCTL_BAUD: divisor = uart_getreg(bas, EP93XX_UART_LinCL); @@ -475,30 +489,45 @@ static int epuart_bus_ipend(struct uart_softc *sc) { + struct epuart_softc *epsc; struct uart_bas *bas; int ipend; uint8_t iidclr, rxsts; + epsc = (struct epuart_softc *)sc; bas = &sc->sc_bas; +#if 0 + iidclr = uart_getreg(bas, EP93XX_UART_IntIDCLR); + printf("%c%c", (int)('0' + iidclr), (int)('0' + + uart_getreg(bas, EP93XX_UART_RXSts))); mtx_lock_spin(&sc->sc_hwmtx); +#else + mtx_lock_spin(&sc->sc_hwmtx); iidclr = uart_getreg(bas, EP93XX_UART_IntIDCLR); - if (!(iidclr & (EP93XX_UART_TIS | EP93XX_UART_RIS | EP93XX_UART_MIS))) { +#endif + if (!(iidclr & (EP93XX_UART_TIS | EP93XX_UART_RIS | + EP93XX_UART_RTIS | EP93XX_UART_MIS))) { mtx_unlock_spin(&sc->sc_hwmtx); return (0); } ipend = 0; - if (iidclr & EP93XX_UART_RIS) { + if ((iidclr & EP93XX_UART_RIS) || (iidclr & EP93XX_UART_RTIS)) { rxsts = uart_getreg(bas, EP93XX_UART_RXSts); - uart_setreg(bas, EP93XX_UART_RXSts, 0); /* clear */ - if (rxsts & EP93XX_UART_OE) + if (rxsts & EP93XX_UART_OE) { ipend |= UART_IPEND_OVERRUN; + uart_setreg(bas, EP93XX_UART_RXSts, 0); /* clear */ + } if (rxsts & EP93XX_UART_BE) ipend |= UART_IPEND_BREAK; - if (iidclr & EP93XX_UART_RIS) - ipend |= UART_IPEND_RXREADY; + ipend |= UART_IPEND_RXREADY; + epsc->ctrl &= ~(EP93XX_UART_RIE | EP93XX_UART_RTIE); + uart_setreg(bas, EP93XX_UART_Ctrl, epsc->ctrl); } - if (iidclr & EP93XX_UART_TIS) + if (iidclr & EP93XX_UART_TIS) { ipend |= UART_IPEND_TXIDLE; + epsc->ctrl &= ~EP93XX_UART_TIE; + uart_setreg(bas, EP93XX_UART_Ctrl, epsc->ctrl); + } if (iidclr & EP93XX_UART_MIS) ipend |= UART_IPEND_SIGCHG; @@ -570,26 +599,30 @@ static int epuart_bus_receive(struct uart_softc *sc) { + struct epuart_softc *epsc; struct uart_bas *bas; int xc; uint8_t flag, rxsts; + epsc = (struct epuart_softc *)sc; bas = &sc->sc_bas; mtx_lock_spin(&sc->sc_hwmtx); - flag = uart_getreg(bas, EP93XX_UART_Flag); - while (!(flag & EP93XX_UART_F_RXFE)) { + while (!((flag = uart_getreg(bas, EP93XX_UART_Flag)) & + EP93XX_UART_F_RXFE)) { if (uart_rx_full(sc)) { sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; break; } xc = uart_getreg(bas, EP93XX_UART_Data); - rxsts = uart_getreg(bas, EP93XX_UART_Data); + printf("%c", (int)xc); + rxsts = uart_getreg(bas, EP93XX_UART_RXSts); + if (rxsts & EP93XX_UART_BE) + xc |= UART_STAT_BREAK; if (rxsts & EP93XX_UART_FE) xc |= UART_STAT_FRAMERR; if (rxsts & EP93XX_UART_PE) xc |= UART_STAT_PARERR; uart_rx_put(sc, xc); - flag = uart_getreg(bas, EP93XX_UART_Flag); } /* Discard everything left in the Rx FIFO. */ while (flag & EP93XX_UART_F_RXFE) { @@ -597,6 +630,9 @@ uart_barrier(bas); flag = uart_getreg(bas, EP93XX_UART_Flag); } + /* reenable RX interrupts */ + epsc->ctrl |= EP93XX_UART_RIE | EP93XX_UART_RTIE; + uart_setreg(bas, EP93XX_UART_Ctrl, epsc->ctrl); mtx_unlock_spin(&sc->sc_hwmtx); return (0); } @@ -636,17 +672,18 @@ static int epuart_bus_transmit(struct uart_softc *sc) { + struct epuart_softc *epsc; struct uart_bas *bas; int i; - int ctrl; + epsc = (struct epuart_softc *)sc; bas = &sc->sc_bas; mtx_lock_spin(&sc->sc_hwmtx); /* XXX - ugly, this sucks, but that's the way uart forces us to be */ while ((uart_getreg(bas, EP93XX_UART_Flag) & EP93XX_UART_F_TXFE) == 0) ; - ctrl = uart_getreg(bas, EP93XX_UART_Ctrl); - uart_setreg(bas, EP93XX_UART_Ctrl, ctrl | EP93XX_UART_TIE); + epsc->ctrl |= EP93XX_UART_TIE; + uart_setreg(bas, EP93XX_UART_Ctrl, epsc->ctrl); uart_barrier(bas); for (i = 0; i < sc->sc_txdatasz; i++) { uart_setreg(bas, EP93XX_UART_Data, sc->sc_txbuf[i]);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200502250723.j1P7NH5j037630>