Date: Sat, 7 Jan 2006 20:05:35 GMT From: Warner Losh <imp@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 89344 for review Message-ID: <200601072005.k07K5ZI7045530@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=89344 Change 89344 by imp@imp_plunger on 2006/01/07 20:05:32 Attempt to create a atestart routine. Start to bring in the busdma goo too. Affected files ... .. //depot/projects/arm/src/sys/arm/at91/if_ate.c#16 edit Differences ... ==== //depot/projects/arm/src/sys/arm/at91/if_ate.c#16 (text+ko) ==== @@ -61,6 +61,8 @@ #include "miibus_if.h" +#define ATE_MAX_TX_BUFFERS 2 /* We have ping-pong tx buffers */ + struct ate_softc { struct ifnet *ifp; /* ifnet pointer */ @@ -71,6 +73,9 @@ struct resource *irq_res; /* IRQ resource */ struct resource *mem_res; /* Memory resource */ struct callout tick_ch; /* Tick callout */ + bus_dma_tag_t mtag; /* bus dma tag for mbufs */ + bus_dmamap_t tx_map[ATE_MAX_TX_BUFFERS]; + int txcur; /* current tx map pointer */ // XXX bogus int intr; @@ -208,7 +213,7 @@ ate_activate(device_t dev) { struct ate_softc *sc; - int rid; + int rid, err, i; sc = device_get_softc(dev); rid = 0; @@ -221,6 +226,26 @@ RF_ACTIVE); if (sc->mem_res == NULL) goto errout; + + /* + * 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, 0, + busdma_lock_mutex, &sc->sc_mtx, &sc->mtag); + if (err != 0) + goto errout; + for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { + err = bus_dmamap_create(sc->mtag, 0, &sc->tx_map[i]); + if (err != 0) + goto errout; + } + + /* + * Allocate our Rx buffers. This chip has a rx structure that's filled + * in -- later XXX + */ + return (0); errout:; ate_deactivate(dev); @@ -233,6 +258,39 @@ struct ate_softc *sc; sc = device_get_softc(dev); + /* XXX teardown busdma junk, below from fxp -- customize */ +#if 0 + if (sc->fxp_mtag) { + for (i = 0; i < FXP_NRFABUFS; i++) { + rxp = &sc->fxp_desc.rx_list[i]; + if (rxp->rx_mbuf != NULL) { + bus_dmamap_sync(sc->fxp_mtag, rxp->rx_map, + BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->fxp_mtag, rxp->rx_map); + m_freem(rxp->rx_mbuf); + } + bus_dmamap_destroy(sc->fxp_mtag, rxp->rx_map); + } + bus_dmamap_destroy(sc->fxp_mtag, sc->spare_map); + for (i = 0; i < FXP_NTXCB; i++) { + txp = &sc->fxp_desc.tx_list[i]; + if (txp->tx_mbuf != NULL) { + bus_dmamap_sync(sc->fxp_mtag, txp->tx_map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->fxp_mtag, txp->tx_map); + m_freem(txp->tx_mbuf); + } + bus_dmamap_destroy(sc->fxp_mtag, txp->tx_map); + } + bus_dma_tag_destroy(sc->fxp_mtag); + } + if (sc->fxp_stag) + bus_dma_tag_destroy(sc->fxp_stag); + if (sc->cbl_tag) + bus_dma_tag_destroy(sc->cbl_tag); + if (sc->mcs_tag) + bus_dma_tag_destroy(sc->mcs_tag); +#endif if (sc->intrhand) bus_teardown_intr(dev, sc->irq_res, sc->intrhand); sc->intrhand = 0; @@ -324,7 +382,8 @@ * once a second is often enough. Some don't map well to * the dot3Stats mib, so for those we just count them as general * errors. Stats for iframes, ibutes, oframes and obytes are - * collected elsewhere. + * collected elsewhere. These registers zero on a read to prevent + * races. */ sc->mibdata.dot3StatsAlignmentErrors += RD4(sc, ETH_ALE); sc->mibdata.dot3StatsFCSErrors += RD4(sc, ETH_SEQE); @@ -346,12 +405,6 @@ RD4(sc, ETH_USF); /* - * Note: I think there's a race btn the use of the stats above and - * clearing them here. The datasheet is a bit vague on the topic. - */ - WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_CSR); - - /* * Schedule another timeout one second from now. */ callout_reset(&sc->tick_ch, hz, ate_tick, sc); @@ -397,6 +450,8 @@ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_RMII); #endif + WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE); + /* XXX need to setup multicast filters */ /* XXX need to setup rx buffers and assoc structures */ /* XXX need to enable appropriate interrupt masks */ @@ -421,11 +476,64 @@ atestart_locked(struct ifnet *ifp) { struct ate_softc *sc = ifp->if_softc; + struct mbuf *m; + bus_dma_segment_t segs[1]; + int nseg; ATE_ASSERT_LOCKED(sc); - if (sc->ifp->if_drv_flags & IFF_DRV_OACTIVE) + if (ifp->if_drv_flags & IFF_DRV_OACTIVE) + return; + +outloop:; + /* XXX ed checks to see if there are buffered packets and an idle + * transmitter and kicks something if so. This shouldn't happen + * for this device, and I note it here only in passing + */ + + /* + * check to see if there's room to put another packet into the + * xmit queue. The EMAC chip has a ping-pong buffer for xmit + * packets. We use OACTIVE to indicate "we can stuff more into + * our buffers (clear) or not (set)." + */ + if (!(RD4(sc, ETH_TSR) & ETH_TSR_BNQ)) { + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + return; + } + IFQ_DRV_DEQUEUE(&ifp->if_snd, m); + if (m == 0) { + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; return; - /* XXX deque packets and transmit */ + } + + m = m_pullup(m, m_length(m, NULL)); + if (bus_dmamap_load_mbuf_sg(sc->mtag, sc->tx_map[sc->txcur], m, segs, + &nseg, 0) != 0) { + m_free(m); + goto outloop; + } + bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txcur], BUS_DMASYNC_PREWRITE); + sc->txcur++; + if (sc->txcur >= ATE_MAX_TX_BUFFERS) + sc->txcur = 0; + + /* + * tell the hardware to xmit the packet. + */ + WR4(sc, ETH_TAR, segs[0].ds_addr); + WR4(sc, ETH_TCR, segs[0].ds_len); + + /* + * Tap off here if there is a bpf listener. + */ + BPF_MTAP(ifp, m); + + m_freem(m); + + /* + * Loop back to the top to possibly buffer more packets + */ + goto outloop; } static void
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200601072005.k07K5ZI7045530>