PERFORCE change 108550 for review
Warner Losh
imp at FreeBSD.org
Fri Oct 27 06:45:51 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=108550
Change 108550 by imp at 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)
{
More information about the p4-projects
mailing list