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>