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