/* * Set the EPIC multicast hash table. * * NOTE: We rely on a recently-updated mii_media_active here! */ void epic_set_mchash(struct epic_softc *sc) { struct arpcom *ac = &sc->sc_arpcom; struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct ether_multi *enm; struct ether_multistep step; u_int32_t hash, mchash[4]; /* * Set up the multicast address filter by passing all multicast * addresses through a CRC generator, and then using the low-order * 6 bits as an index into the 64 bit multicast hash table (only * the lower 16 bits of each 32 bit multicast hash register are * valid). The high order bits select the register, while the * rest of the bits select the bit within the register. */ if (ifp->if_flags & IFF_PROMISC) goto allmulti; if (IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_10_T) { /* XXX hardware bug in 10Mbps mode. */ goto allmulti; } if (ac->ac_multirangecnt > 0) goto allmulti; mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0; ETHER_FIRST_MULTI(step, ac, enm); while (enm != NULL) { hash = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN); hash >>= 26; /* Set the corresponding bit in the hash table. */ mchash[hash >> 4] |= 1 << (hash & 0xf); ETHER_NEXT_MULTI(step, enm); } ifp->if_flags &= ~IFF_ALLMULTI; goto sethash; allmulti: ifp->if_flags |= IFF_ALLMULTI; mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0xffff; sethash: bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC0, mchash[0]); bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC1, mchash[1]); bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC2, mchash[2]); bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC3, mchash[3]); }
void ste_iff(struct ste_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; struct arpcom *ac = &sc->arpcom; struct ether_multi *enm; struct ether_multistep step; u_int32_t rxmode, hashes[2]; int h = 0; rxmode = CSR_READ_1(sc, STE_RX_MODE); rxmode &= ~(STE_RXMODE_ALLMULTI | STE_RXMODE_BROADCAST | STE_RXMODE_MULTIHASH | STE_RXMODE_PROMISC | STE_RXMODE_UNICAST); bzero(hashes, sizeof(hashes)); ifp->if_flags &= ~IFF_ALLMULTI; /* * Always accept broadcast frames. * Always accept frames destined to our station address. */ rxmode |= STE_RXMODE_BROADCAST | STE_RXMODE_UNICAST; if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { ifp->if_flags |= IFF_ALLMULTI; rxmode |= STE_RXMODE_ALLMULTI; if (ifp->if_flags & IFF_PROMISC) rxmode |= STE_RXMODE_PROMISC; } else { rxmode |= STE_RXMODE_MULTIHASH; /* now program new ones */ ETHER_FIRST_MULTI(step, ac, enm); while (enm != NULL) { h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) & 0x3F; if (h < 32) hashes[0] |= (1 << h); else hashes[1] |= (1 << (h - 32)); ETHER_NEXT_MULTI(step, enm); } } CSR_WRITE_2(sc, STE_MAR0, hashes[0] & 0xFFFF); CSR_WRITE_2(sc, STE_MAR1, (hashes[0] >> 16) & 0xFFFF); CSR_WRITE_2(sc, STE_MAR2, hashes[1] & 0xFFFF); CSR_WRITE_2(sc, STE_MAR3, (hashes[1] >> 16) & 0xFFFF); CSR_WRITE_1(sc, STE_RX_MODE, rxmode); }
void ste_setmulti(struct ste_softc *sc) { struct ifnet *ifp; struct arpcom *ac = &sc->arpcom; struct ether_multi *enm; struct ether_multistep step; int h = 0; u_int32_t hashes[2] = { 0, 0 }; ifp = &sc->arpcom.ac_if; allmulti: if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI); STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH); return; } /* first, zot all the existing hash bits */ CSR_WRITE_2(sc, STE_MAR0, 0); CSR_WRITE_2(sc, STE_MAR1, 0); CSR_WRITE_2(sc, STE_MAR2, 0); CSR_WRITE_2(sc, STE_MAR3, 0); /* now program new ones */ ETHER_FIRST_MULTI(step, ac, enm); while (enm != NULL) { if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { ifp->if_flags |= IFF_ALLMULTI; goto allmulti; } h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) & 0x3F; if (h < 32) hashes[0] |= (1 << h); else hashes[1] |= (1 << (h - 32)); ETHER_NEXT_MULTI(step, enm); } CSR_WRITE_2(sc, STE_MAR0, hashes[0] & 0xFFFF); CSR_WRITE_2(sc, STE_MAR1, (hashes[0] >> 16) & 0xFFFF); CSR_WRITE_2(sc, STE_MAR2, hashes[1] & 0xFFFF); CSR_WRITE_2(sc, STE_MAR3, (hashes[1] >> 16) & 0xFFFF); STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI); STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH); return; }
void tsec_iff(struct tsec_softc *sc) { struct arpcom *ac = &sc->sc_ac; struct ifnet *ifp = &sc->sc_ac.ac_if; struct ether_multi *enm; struct ether_multistep step; uint32_t crc, hash[8]; uint32_t rctrl; int i; rctrl = tsec_read(sc, TSEC_RCTRL); rctrl &= ~TSEC_RCTRL_PROM; ifp->if_flags &= ~IFF_ALLMULTI; if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { ifp->if_flags |= IFF_ALLMULTI; rctrl |= TSEC_RCTRL_PROM; bzero(hash, sizeof(hash)); } else { ETHER_FIRST_MULTI(step, ac, enm); while (enm != NULL) { crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN); crc >>= 24; hash[crc / 32] |= 1 << (31 - (crc % 32)); ETHER_NEXT_MULTI(step, enm); } } for (i = 0; i < nitems(hash); i++) tsec_write(sc, TSEC_GADDR0 + i * 4, hash[i]); tsec_write(sc, TSEC_RCTRL, rctrl); }