PERFORCE change 89554 for review
Olivier Houchard
cognet at FreeBSD.org
Thu Jan 12 08:01:03 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=89554
Change 89554 by cognet at cognet on 2006/01/12 16:00:13
- Setup the RX descriptors.
- Start an interrupt handler.
Affected files ...
.. //depot/projects/arm/src/sys/arm/at91/if_ate.c#20 edit
Differences ...
==== //depot/projects/arm/src/sys/arm/at91/if_ate.c#20 (text+ko) ====
@@ -62,6 +62,12 @@
#include "miibus_if.h"
#define ATE_MAX_TX_BUFFERS 2 /* We have ping-pong tx buffers */
+#define ATE_MAX_RX_BUFFERS 8
+
+typedef struct {
+ bus_addr_t addr;
+ int status;
+} rx_desc_t;
struct ate_softc
{
@@ -75,7 +81,15 @@
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];
+ bus_dma_tag_t rxtag;
+ bus_dmamap_t rx_map[ATE_MAX_RX_BUFFERS];
+ bus_dma_tag_t rx_desc_tag;
+ bus_dmamap_t rx_desc_map;
int txcur; /* current tx map pointer */
+ struct mbuf *sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */
+ struct mbuf *rx_mbuf[ATE_MAX_RX_BUFFERS]; /* RX mbufs */
+ bus_addr_t rx_desc_phys;
+ rx_desc_t *rx_descs;
// XXX bogus
int intr;
@@ -212,6 +226,17 @@
return EBUSY; /* XXX */
}
+static void
+ate_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct ate_softc *sc;
+
+ if (error != 0)
+ return;
+ sc = (struct ate_softc *)arg;
+ sc->rx_desc_phys = segs[0].ds_addr;
+}
+
static int
ate_activate(device_t dev)
{
@@ -243,14 +268,65 @@
if (err != 0)
goto errout;
}
-
+ /*
+ * Allocate our Rx buffers. This chip has a rx structure that's filled
+ * in
+ */
+
/*
- * Allocate our Rx buffers. This chip has a rx structure that's filled
- * in -- later XXX
+ * Allocate DMA tags and maps for RX.
*/
+ 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->rxtag);
+ if (err != 0)
+ goto errout;
+ for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) {
+ err = bus_dmamap_create(sc->rxtag, 0, &sc->rx_map[i]);
+ if (err != 0)
+ goto errout;
+ }
+ /* Dma TAG and MAP for the rx descriptors. */
+ err = bus_dma_tag_create(NULL, sizeof(rx_desc_t), 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ ATE_MAX_RX_BUFFERS * sizeof(rx_desc_t), 1,
+ ATE_MAX_RX_BUFFERS * sizeof(rx_desc_t), 0, busdma_lock_mutex,
+ &sc->sc_mtx, &sc->rx_desc_tag);
+ if (err != 0)
+ goto errout;
+ if (bus_dmamem_alloc(sc->rx_desc_tag, (void **)&sc->rx_descs, M_WAITOK,
+ &sc->rx_desc_map) != 0)
+ goto errout;
+ if (bus_dmamap_load(sc->rx_desc_tag, sc->rx_desc_map,
+ sc->rx_descs, ATE_MAX_RX_BUFFERS * sizeof(rx_desc_t), ate_getaddr,
+ sc, 0) != 0)
+ goto errout;
+ for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) {
+ bus_dma_segment_t seg;
+ int nsegs;
+
+ sc->rx_mbuf[i] = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
+ sc->rx_mbuf[i]->m_len = sc->rx_mbuf[i]->m_pkthdr.len =
+ MCLBYTES;
+ if (bus_dmamap_load_mbuf_sg(sc->rxtag, sc->rx_map[i],
+ sc->rx_mbuf[i], &seg, &nsegs, 0) != 0)
+ goto errout;
+ /*
+ * For the last buffer, set the wrap bit so the controller
+ * restarts from the first descriptor.
+ */
+ if (i == ATE_MAX_RX_BUFFERS - 1)
+ seg.ds_addr |= 1 << 1;
+ sc->rx_descs[i].addr = seg.ds_addr;
+ sc->rx_descs[i].status = 0;
+ bus_dmamap_sync(sc->rxtag, sc->rx_map[i], BUS_DMASYNC_PREWRITE);
+ }
+ bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE);
+ /* Write the descriptor queue address. */
+ WR4(sc, ETH_RBQP, sc->rx_desc_phys);
return (0);
-errout:;
+errout:
ate_deactivate(dev);
return (ENOMEM);
}
@@ -442,8 +518,86 @@
ate_intr(void *xsc)
{
struct ate_softc *sc = xsc;
+ int status;
+ int i;
+
+ sc->intr++;
+ status = RD4(sc, ETH_ISR);
+ if (status == 0)
+ return;
+ if (status & ETH_ISR_RCOM) {
+ bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
+ BUS_DMASYNC_POSTREAD);
+ for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) {
+ if (sc->rx_descs[i].addr & 1) {
+ struct mbuf *mb = sc->rx_mbuf[i];
+ bus_dma_segment_t seg;
+ int rx_stat = sc->rx_descs[i].status;
+ int nsegs;
+
+ bus_dmamap_sync(sc->rxtag,
+ sc->rx_map[i], BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->rxtag,
+ sc->rx_map[i]);
+ /*
+ * Clear the corresponding bits in RSR.
+ */
+ WR4(sc, ETH_RSR, RD4(sc, ETH_RSR));
+ sc->rx_mbuf[i] = m_getcl(M_DONTWAIT, MT_DATA,
+ M_PKTHDR);
+ if (!sc->rx_mbuf[i]) {
+ sc->rx_mbuf[i] = mb;
+ sc->rx_descs[i].addr &= ~1;
+ bus_dmamap_sync(sc->rx_desc_tag,
+ sc->rx_desc_map,
+ BUS_DMASYNC_PREWRITE);
+ break;
+ }
+ if (bus_dmamap_load_mbuf_sg(sc->rxtag,
+ sc->rx_map[i],
+ sc->rx_mbuf[i], &seg, &nsegs, 0) != 0) {
+ sc->rx_mbuf[i] = mb;
+ sc->rx_descs[i].addr &= ~1;
+ bus_dmamap_sync(sc->rx_desc_tag,
+ sc->rx_desc_map,
+ BUS_DMASYNC_PREWRITE);
+ break;
+ }
+ /*
+ * For the last buffer, set the wrap bit so the controller
+ * restarts from the first descriptor.
+ */
+ if (i == ATE_MAX_RX_BUFFERS - 1)
+ seg.ds_addr |= 1 << 1;
+ sc->rx_descs[i].addr = seg.ds_addr;
+ sc->rx_descs[i].status = 0;
+ /* Bits 0-10 of the status file == length. */
+ mb->m_len = rx_stat & 0x7ff;
+ (*sc->ifp->if_input)(sc->ifp, mb);
+ break;
- sc->intr++;
+
+ }
+ }
+ }
+ if (status & ETH_ISR_TCOM) {
+ if (sc->sent_mbuf[0])
+ m_freem(sc->sent_mbuf[0]);
+ if (sc->sent_mbuf[1]) {
+ if (RD4(sc, ETH_TSR) & ETH_TSR_IDLE) {
+ m_freem(sc->sent_mbuf[1]);
+ sc->txcur = 0;
+ sc->sent_mbuf[0] = sc->sent_mbuf[1] = NULL;
+ } else {
+ sc->sent_mbuf[0] = sc->sent_mbuf[1];
+ sc->sent_mbuf[1] = NULL;
+ sc->txcur = 1;
+ }
+ } else {
+ sc->sent_mbuf[0] = NULL;
+ sc->txcur = 0;
+ }
+ }
}
/*
@@ -477,7 +631,7 @@
WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_RMII);
#endif
- WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE);
+ WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE | ETH_CTL_RE);
/*
* Boot loader fills in MAC address. If that's not the case, then
@@ -516,7 +670,7 @@
if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
return;
-outloop:;
+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
@@ -545,6 +699,7 @@
goto outloop;
}
bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txcur], BUS_DMASYNC_PREWRITE);
+ sc->sent_mbuf[sc->txcur] = m;
sc->txcur++;
if (sc->txcur >= ATE_MAX_TX_BUFFERS)
sc->txcur = 0;
More information about the p4-projects
mailing list