PERFORCE change 89344 for review
Warner Losh
imp at FreeBSD.org
Sat Jan 7 12:05:37 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=89344
Change 89344 by imp at 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
More information about the p4-projects
mailing list