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