コード例 #1
0
ファイル: smc83c170.c プロジェクト: orumin/openbsd-efivars
/*
 * 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]);
}
コード例 #2
0
ファイル: if_ste.c プロジェクト: darksoul42/bitrig
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);
}
コード例 #3
0
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;
}
コード例 #4
0
ファイル: if_tsec.c プロジェクト: bradla/OpenBSD-Hammer2
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);
}