PERFORCE change 91040 for review
Warner Losh
imp at FreeBSD.org
Sat Feb 4 00:48:17 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=91040
Change 91040 by imp at imp_hammer on 2006/02/04 08:46:55
first cut at multicast support.
Affected files ...
.. //depot/projects/arm/src/sys/arm/at91/if_ate.c#25 edit
Differences ...
==== //depot/projects/arm/src/sys/arm/at91/if_ate.c#25 (text+ko) ====
@@ -24,11 +24,11 @@
/* TODO: (in no order)
*
+ * 5) Setup RX buffers in ateinit_locked
+ *
* 1) detach
* 2) Free dma setup
* 3) Turn on the clock in pmc and turn on pins? Turn off?
- * 4) Setup multicast filters
- * 5) Setup RX buffers in ateinit_locked
* 6) Interrupt bits as appropriate
* 7) Keep track of the mbufs in flight on TX and free them in the ISR.
* 8) Need to sync busdma goo in atestop
@@ -241,6 +241,36 @@
sc->rx_desc_phys = segs[0].ds_addr;
}
+/*
+ * Compute the multicast filter for this device using the standard
+ * algorithm. I wonder why this isn't in ether somewhere as a lot
+ * of different MAC chips use this method (or the reverse the bits)
+ * method.
+ */
+static void
+ate_setmcaf(struct ate_softc *sc)
+{
+ uint32_t index;
+ uint32_t mcaf[2];
+ u_char *af = (u_char *) mcaf;
+ struct ifmultiaddr *ifma;
+
+ mcaf[0] = 0;
+ mcaf[1] = 0;
+
+ IF_ADDR_LOCK(sc->ifp);
+ TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ index = ether_crc32_be(LLADDR((struct sockaddr_dl *)
+ ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
+ af[index >> 3] |= 1 << (index & 7);
+ }
+ IF_ADDR_UNLOCK(sc->ifp);
+ WR4(sc, ETH_HSL, mcaf[0]);
+ WR4(sc, ETH_HSH, mcaf[1]);
+}
+
static int
ate_activate(device_t dev)
{
@@ -303,8 +333,8 @@
&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(eth_rx_desc_t), ate_getaddr,
- sc, 0) != 0)
+ sc->rx_descs, ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t),
+ ate_getaddr, sc, 0) != 0)
goto errout;
for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) {
bus_dma_segment_t seg;
@@ -640,6 +670,12 @@
#else
WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_RMII);
#endif
+ /*
+ * Turn on the multicast hash, and write 0's to it.
+ */
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_MTI);
+ WR4(sc, ETH_HSH, 0);
+ WR4(sc, ETH_HSL, 0);
WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE | ETH_CTL_RE);
WR4(sc, ETH_IER, /*ETH_ISR_RCOM | ETH_ISR_TCOM | ETH_ISR_RBNA*/
@@ -681,11 +717,6 @@
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
@@ -846,19 +877,7 @@
ATE_UNLOCK(sc);
break;
-#ifdef notyet
- case SIOCGHWADDR:
- bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data,
- sizeof(sc->sc_addr));
- break;
-
case SIOCADDMULTI:
- /* update multicast filter list. */
- ATE_LOCK(sc);
- ate_setmcast(sc);
- error = 0;
- ATE_UNLOCK(sc);
- break;
case SIOCDELMULTI:
/* update multicast filter list. */
ATE_LOCK(sc);
@@ -866,9 +885,8 @@
error = 0;
ATE_UNLOCK(sc);
break;
-#endif
+
default:
- error = EINVAL;
error = ether_ioctl(ifp, cmd, data);
break;
}
More information about the p4-projects
mailing list