Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Oct 2006 06:45:50 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 108550 for review
Message-ID:  <200610270645.k9R6joV6050118@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=108550

Change 108550 by imp@imp_lighthouse on 2006/10/27 06:45:06

	Get the initialization and upper half of the driver going.
	The lower half, the part that implements d_read_t, needs to be
	written.

Affected files ...

.. //depot/projects/arm/src/sys/arm/at91/at91_ssc.c#16 edit

Differences ...

==== //depot/projects/arm/src/sys/arm/at91/at91_ssc.c#16 (text+ko) ====

@@ -42,6 +42,7 @@
 
 #define MAX_BUF	1024
 #define NRX_BUF	2
+#define ONE_BUF (MAX_BUF / NRX_BUF)
 
 struct at91_ssc_softc
 {
@@ -58,11 +59,20 @@
 	bus_dmamap_t tx_map;
 	int txdone;
 	uint8_t rx_buf[MAX_BUF];
-	uint8_t *rx_end;
+	uint8_t *rx_ptr;
 	bus_dmamap_t rx_map[NRX_BUF];
+	bus_addr_t rx_pa[NRX_BUF];
+	int rxcur;
 	int rxdone;
+	uint8_t	rd_buf[MAX_BUF];
+	uint8_t *rd_end;
 };
 
+static void at91_ssc_loadread(void *arg, bus_dma_segment_t *segs, int nsegs,
+    int error);
+static void at91_ssc_loadwrite(void *arg, bus_dma_segment_t *segs, int nsegs,
+    bus_size_t size, int error);
+
 static inline uint32_t
 RD4(struct at91_ssc_softc *sc, bus_size_t off)
 {
@@ -158,7 +168,13 @@
 		err = bus_dmamap_create(sc->tag, 0,  &sc->rx_map[i]);
 		if (err != 0)
 			goto out;
+		err = bus_dmamap_load(sc->tag, sc->rx_map[i], sc->rx_buf +
+		    ONE_BUF * i, ONE_BUF, at91_ssc_loadread, sc, 0);
+		if (err != 0)
+			goto out;
 	}
+	// We use two buffers for read, and we bounce between them.
+
 
 	sc->cdev = make_dev(&at91_ssc_cdevsw, device_get_unit(dev), UID_ROOT,
 	    GID_WHEEL, 0600, "ssc%d", device_get_unit(dev));
@@ -167,6 +183,7 @@
 		goto out;
 	}
 	sc->cdev->si_drv1 = sc;
+	sc->rd_end = sc->rd_buf;
 
 	// Init for TSC needs
 	WR4(sc, SSC_CR, SSC_CR_SWRST);
@@ -241,6 +258,7 @@
 {
 	struct at91_ssc_softc *sc = xsc;
 	uint32_t status;
+	int len;
 
 	/* Reading the status also clears the interrupt */
 	status = RD4(sc, SSC_SR);
@@ -252,6 +270,35 @@
 		sc->txdone++;
 		wakeup(&sc->txdone);
 	}
+	if (status & SSC_SR_ENDRX) {
+		// At this point we have at least one datum in the
+		// rx_buf.  Turn off the PDC, read the read pointer,
+		// move to the next set of buffers, turn on the PDC
+		// and then copy the data.  The data is likely to be
+		// short, so having an extra thread do this is too much
+		// overhead.
+		bus_dmamap_sync(sc->tag, sc->rx_map[sc->rxcur],
+		    BUS_DMASYNC_POSTREAD);
+		WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS);
+		len = ONE_BUF - RD4(sc, PDC_RCR) * 4 + 4;
+		sc->rxcur = (sc->rxcur + 1) % NRX_BUF;
+		WR4(sc, PDC_RPR, sc->rx_pa[sc->rxcur]);
+		WR4(sc, PDC_RCR, 1);
+		WR4(sc, PDC_RNPR, sc->rx_pa[sc->rxcur] + 4);
+		WR4(sc, PDC_RNCR, ONE_BUF / 4 - 1);
+		bus_dmamap_sync(sc->tag, sc->rx_map[sc->rxcur],
+		    BUS_DMASYNC_PREREAD);
+		WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN);
+		if (sc->rd_end - sc->rd_buf + len < sizeof(sc->rx_buf)) {
+			memcpy(sc->rd_end, sc->rx_ptr, len);
+			sc->rd_end += len;
+		}
+		sc->rx_ptr += ONE_BUF;
+		if (sc->rx_ptr >= sc->rx_buf + sizeof(sc->rx_buf))
+			sc->rx_ptr = sc->rx_buf;
+		sc->rxdone++;
+		wakeup(&sc->rxdone);
+	}
 	AT91_SSC_UNLOCK(sc);
 	wakeup(sc);
 	return;
@@ -284,6 +331,29 @@
 }
 
 static void
+at91_ssc_loadread(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	struct at91_ssc_softc *sc;
+
+	sc = arg;
+	if (error != 0)
+		return;
+	bus_dmamap_sync(sc->tag, sc->rx_map[sc->rxcur], BUS_DMASYNC_PREREAD);
+	sc->rx_pa[sc->rxcur] = segs[0].ds_addr;
+	if (sc->rx_ptr == NULL) {
+		WR4(sc, PDC_RPR, sc->rx_pa[sc->rxcur]);
+		WR4(sc, PDC_RCR, 1);
+		WR4(sc, PDC_RNPR, sc->rx_pa[sc->rxcur] + 4);
+		WR4(sc, PDC_RNCR, ONE_BUF / 4 - 1);
+		WR4(sc, SSC_IER, SSC_SR_ENDRX);
+		WR4(sc, SSC_CR, SSC_CR_RXEN);
+		WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN);
+		sc->rx_ptr = sc->rx_buf;
+	}
+	sc->rxcur = (sc->rxcur + 1) % NRX_BUF;
+}
+
+static void
 at91_ssc_loadwrite(void *arg, bus_dma_segment_t *segs, int nsegs,
     bus_size_t size, int error)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200610270645.k9R6joV6050118>