PERFORCE change 94231 for review

Warner Losh imp at FreeBSD.org
Wed Mar 29 07:24:31 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=94231

Change 94231 by imp at 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;


More information about the p4-projects mailing list