From owner-p4-projects@FreeBSD.ORG Wed Mar 29 07:24:31 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 10CF416A425; Wed, 29 Mar 2006 07:24:31 +0000 (UTC) X-Original-To: perforce@freebsd.org 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 C50A516A422 for ; Wed, 29 Mar 2006 07:24:30 +0000 (UTC) (envelope-from imp@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 49AE143D49 for ; Wed, 29 Mar 2006 07:24:30 +0000 (GMT) (envelope-from imp@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id k2T7OU7C011021 for ; Wed, 29 Mar 2006 07:24:30 GMT (envelope-from imp@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id k2T7OTro011018 for perforce@freebsd.org; Wed, 29 Mar 2006 07:24:29 GMT (envelope-from imp@freebsd.org) Date: Wed, 29 Mar 2006 07:24:29 GMT Message-Id: <200603290724.k2T7OTro011018@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to imp@freebsd.org using -f From: Warner Losh To: Perforce Change Reviews Cc: Subject: PERFORCE change 94231 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Mar 2006 07:24:31 -0000 http://perforce.freebsd.org/chv.cgi?CH=94231 Change 94231 by imp@imp_Speedy on 2006/03/29 07:24:23 Use the PDC to transmit. The tx side is easy, since we don't try to double buffer. We get a bunch of bytes, and try to transmit them. Once it is done, we'll get more from the main uart driver. I think this works, but I've not tested it. The Rx side is harder. We don't know, a priori, the number of bytes we'll get. We have to deal with both ENDTRX interrupts, as well as TIMEOUT interrupts. We necessarily have to have double buffering. The uart infrastructure doesn't really have this concept, so more study is needed. We can fake it with really really large buffers, but that's just a statistical solution... Affected files ... .. //depot/projects/arm/src/sys/arm/at91/uart_dev_at91usart.c#19 edit Differences ... ==== //depot/projects/arm/src/sys/arm/at91/uart_dev_at91usart.c#19 (text+ko) ==== @@ -52,9 +52,11 @@ struct uart_softc base; bus_dma_tag_t dmatag; /* bus dma tag for mbufs */ bus_dmamap_t tx_map; + bus_dmamap_t rx_map; }; -#define DEFAULT_RCLK AT91C_MASTER_CLOCK +#define DEFAULT_RCLK AT91C_MASTER_CLOCK +#define USART_BUFFER_SIZE 128 #define RD4(bas, reg) \ bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg)) @@ -297,41 +299,59 @@ atsc = (struct at91_usart_softc *)sc; - sc->sc_txfifosz = 128; /* Really 64k, but 128 seems a good number */ - sc->sc_rxfifosz = 128; + sc->sc_txfifosz = USART_BUFFER_SIZE; + sc->sc_rxfifosz = USART_BUFFER_SIZE; sc->sc_hwiflow = 0; /* * Allocate DMA tags and maps */ err = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, MCLBYTES, - BUS_DMA_ALLOCNOW, NULL, NULL, &atsc->dmatag); + BUS_SPACE_MAXADDR, NULL, NULL, USART_BUFFER_SIZE, 1, + USART_BUFFER_SIZE, BUS_DMA_ALLOCNOW, NULL, NULL, &atsc->dmatag); if (err != 0) goto errout; err = bus_dmamap_create(atsc->dmatag, 0, &atsc->tx_map); if (err != 0) goto errout; + err = bus_dmamap_create(atsc->dmatag, 0, &atsc->rx_map); + if (err != 0) + goto errout; errout:; + // XXX bad return (err); } + +static void +at91_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + if (error != 0) + return; + *(bus_addr_t *)arg = segs[0].ds_addr; +} + + static int at91_usart_bus_transmit(struct uart_softc *sc) { - int i; + bus_addr_t addr; + struct at91_usart_softc *atsc; + + atsc = (struct at91_usart_softc *)sc; + if (bus_dmamap_load(atsc->dmatag, atsc->tx_map, sc->sc_txbuf, + sc->sc_txdatasz, at91_getaddr, &addr, 0) != 0) + return (EAGAIN); + bus_dmamap_sync(atsc->dmatag, atsc->tx_map, BUS_DMASYNC_PREWRITE); - /* XXX VERY sub-optimial */ mtx_lock_spin(&sc->sc_hwmtx); sc->sc_txbusy = 1; -#if 0 - /* XXX - * We can setup the PDC to transfer the whole buffer - * here. + /* + * Setup the PDC to transfer the data and interrupt us when it + * is done. We've already requested the interrupt. */ -#else - for (i = 0; i < sc->sc_txdatasz; i++) - at91_usart_putc(&sc->sc_bas, sc->sc_txbuf[i]); -#endif + WR4(&sc->sc_bas, PDC_TPR, addr); + WR4(&sc->sc_bas, PDC_TCR, sc->sc_txdatasz); + WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_TXTEN); mtx_unlock_spin(&sc->sc_hwmtx); #ifdef USART0_CONSOLE /* @@ -394,7 +414,9 @@ { int csr = RD4(&sc->sc_bas, USART_CSR); int ipend = 0; - + struct at91_usart_softc *atsc; + + atsc = (struct at91_usart_softc *)sc; #ifdef USART0_CONSOLE /* * XXX: We have to cheat for skyeye, as it will return 0xff for all @@ -404,6 +426,11 @@ return (0); #endif + if (csr & USART_CSR_ENDTX) { + bus_dmamap_sync(atsc->dmatag, atsc->tx_map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(atsc->dmatag, atsc->tx_map); + } mtx_lock_spin(&sc->sc_hwmtx); if (csr & USART_CSR_TXRDY && sc->sc_txbusy) ipend |= SER_INT_TXIDLE;