Date: Sat, 4 Feb 2006 08:48:16 GMT From: Warner Losh <imp@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 91040 for review Message-ID: <200602040848.k148mGe8092825@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=91040 Change 91040 by imp@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; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200602040848.k148mGe8092825>