From owner-p4-projects@FreeBSD.ORG Wed Jul 23 20:26:25 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3E47037B404; Wed, 23 Jul 2003 20:26:24 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D123F37B401 for ; Wed, 23 Jul 2003 20:26:23 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3C6BE43F75 for ; Wed, 23 Jul 2003 20:26:23 -0700 (PDT) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id h6O3QN0U061271 for ; Wed, 23 Jul 2003 20:26:23 -0700 (PDT) (envelope-from marcel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id h6O3QM2v061268 for perforce@freebsd.org; Wed, 23 Jul 2003 20:26:22 -0700 (PDT) Date: Wed, 23 Jul 2003 20:26:22 -0700 (PDT) Message-Id: <200307240326.h6O3QM2v061268@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to marcel@freebsd.org using -f From: Marcel Moolenaar To: Perforce Change Reviews Subject: PERFORCE change 34914 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Jul 2003 03:26:25 -0000 http://perforce.freebsd.org/chv.cgi?CH=34914 Change 34914 by marcel@marcel_nfs on 2003/07/23 20:26:07 Further improve on the ns8250 driver: o Don't use the IIR register to figure out the cause of an interrupt. Instead, use the LSR to get a bitmap of the things that need attention. This avoids that we lose pending interrupt conditions while we talk to the UART. This fixes the lost transmit interrupts. o Differentiate between flushing and draining. Flushing implies losing data. Draining means that we wait for all data to be processed. Do not yet add a drain method. o Implement the getsig method. Don't depend on the delta bits that the UART maintains. Do it ourselves. This is mostly alpha code. We also need a setsig method to set modem signals. Affected files ... .. //depot/projects/uart/dev/uart/uart_bus.h#7 edit .. //depot/projects/uart/dev/uart/uart_dev_ns8250.c#8 edit Differences ... ==== //depot/projects/uart/dev/uart/uart_bus.h#7 (text+ko) ==== @@ -32,9 +32,11 @@ #include #include -/* Flush targets. */ -#define UART_FLUSH_RECEIVER 0x0001 -#define UART_FLUSH_TRANSMITTER 0x0002 +/* Drain and flush targets. */ +#define UART_DRAIN_RECEIVER 0x0001 +#define UART_DRAIN_TRANSMITTER 0x0002 +#define UART_FLUSH_RECEIVER UART_DRAIN_RECEIVER +#define UART_FLUSH_TRANSMITTER UART_DRAIN_TRANSMITTER /* Interrupt sources (in priority order). See also uart_core.c */ #define UART_IPEND_OVERRUN 0x0001 ==== //depot/projects/uart/dev/uart/uart_dev_ns8250.c#8 (text+ko) ==== @@ -83,13 +83,13 @@ } static int -ns8250_flush(struct uart_bas *bas, int what) +ns8250_drain(struct uart_bas *bas, int what) { int delay, limit; delay = ns8250_delay(bas); - if (what & UART_FLUSH_TRANSMITTER) { + if (what & UART_DRAIN_TRANSMITTER) { /* * Pick an arbitrary high limit to avoid getting stuck in * an infinite loop when the hardware is broken. Make the @@ -104,7 +104,7 @@ } } - if (what & UART_FLUSH_RECEIVER) { + if (what & UART_DRAIN_RECEIVER) { /* * Pick an arbitrary high limit to avoid getting stuck in * an infinite loop when the hardware is broken. Make the @@ -129,6 +129,24 @@ } /* + * We can only flush UARTs with FIFOs. UARTs without FIFOs should be + * drained. + */ +static void +ns8250_flush(struct uart_bas *bas, int what) +{ + uint8_t fcr; + + fcr = FCR_ENABLE; + if (what & UART_FLUSH_TRANSMITTER) + fcr |= FCR_XMT_RST; + if (what & UART_FLUSH_RECEIVER) + fcr |= FCR_RCV_RST; + uart_setreg(bas, REG_FCR, fcr); + uart_barrier(bas); +} + +/* * Low-level UART interface. */ static int ns8250_probe(struct uart_bas *bas); @@ -299,6 +317,8 @@ uint8_t fcr; uint8_t lcr; uint8_t mcr; + uint8_t signals; + uint8_t sigchg; }; static int ns8250_bus_attach(struct uart_softc *); @@ -345,6 +365,8 @@ uart_setreg(bas, REG_IER, IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC); uart_barrier(bas); + ns8250->signals = uart_getreg(bas, REG_MSR) >> 4; + ns8250->sigchg = 0; return (0); } @@ -359,40 +381,50 @@ ns8250_bus_flush(struct uart_softc *sc, int what) { - return (ns8250_flush(&sc->sc_bas, what)); + if (sc->sc_hasfifo) { + ns8250_flush(&sc->sc_bas, what); + return (0); + } + return (ns8250_drain(&sc->sc_bas, what)); } static int ns8250_bus_getsig(struct uart_softc *sc) { + struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; + struct uart_bas *bas; + uint8_t sig; - return (0); + bas = &sc->sc_bas; + sig = uart_getreg(bas, REG_MSR) >> 4; + ns8250->sigchg |= ns8250->signals ^ sig; + ns8250->signals = sig; + return ((ns8250->sigchg << 4) | ns8250->signals); } static int ns8250_bus_ipend(struct uart_softc *sc) { + struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; struct uart_bas *bas; int ipend; - uint8_t iir, lsr; + uint8_t lsr, sig; bas = &sc->sc_bas; ipend = 0; - iir = uart_getreg(bas, REG_IIR); - if (iir == IIR_RLS) { - lsr = uart_getreg(bas, REG_LSR); - if (lsr & LSR_OE) - ipend |= UART_IPEND_OVERRUN; - if (lsr & LSR_BI) - ipend |= UART_IPEND_BREAK; - uart_barrier(bas); - iir = uart_getreg(bas, REG_IIR); - } - if (iir == IIR_RXRDY || iir == IIR_RXTOUT) + lsr = uart_getreg(bas, REG_LSR); + if (lsr & LSR_OE) + ipend |= UART_IPEND_OVERRUN; + if (lsr & LSR_BI) + ipend |= UART_IPEND_BREAK; + if (lsr & LSR_RXRDY) ipend |= UART_IPEND_RXREADY; - if (iir == IIR_TXRDY) + if (lsr & LSR_TEMT) ipend |= UART_IPEND_TXIDLE; - if (iir == IIR_MLSC) + sig = uart_getreg(bas, REG_MSR) >> 4; + ns8250->sigchg |= ns8250->signals ^ sig; + ns8250->signals = sig; + if (ns8250->sigchg) ipend |= UART_IPEND_SIGCHG; return (ipend); } @@ -417,7 +449,7 @@ } else mcr |= MCR_DTR | MCR_RTS; - error = ns8250_flush(bas, UART_FLUSH_TRANSMITTER); + error = ns8250_drain(bas, UART_DRAIN_TRANSMITTER); if (error) return (error); @@ -458,8 +490,8 @@ count = 0; delay = ns8250_delay(bas); - /* We have FIFOs. Flush the transmitter and receiver. */ - error = ns8250_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER); + /* We have FIFOs. Drain the transmitter and receiver. */ + error = ns8250_drain(bas, UART_DRAIN_RECEIVER|UART_DRAIN_TRANSMITTER); if (error) { uart_setreg(bas, REG_MCR, mcr); uart_setreg(bas, REG_FCR, 0); @@ -499,8 +531,7 @@ uart_setreg(bas, REG_MCR, mcr); /* Reset FIFOs. */ - uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST); - uart_barrier(bas); + ns8250_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER); describe: if (count >= 14 && count < 16) { @@ -530,7 +561,7 @@ ns8250_bus_receive(struct uart_softc *sc) { struct uart_bas *bas; - int ptr, xc; + int xc; uint8_t lsr; bas = &sc->sc_bas;