Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/cas/if_cas.c
Show First 20 Lines • Show All 2,492 Lines • ▼ Show 20 Lines | cas_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | ||||
default: | default: | ||||
error = ether_ioctl(ifp, cmd, data); | error = ether_ioctl(ifp, cmd, data); | ||||
break; | break; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
static u_int | |||||
cas_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) | |||||
{ | |||||
uint32_t crc, *hash = arg; | |||||
crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN); | |||||
/* We just want the 8 most significant bits. */ | |||||
crc >>= 24; | |||||
/* Set the corresponding bit in the filter. */ | |||||
hash[crc >> 4] |= 1 << (15 - (crc & 15)); | |||||
return (1); | |||||
} | |||||
static void | static void | ||||
cas_setladrf(struct cas_softc *sc) | cas_setladrf(struct cas_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ifnet *ifp = sc->sc_ifp; | ||||
struct ifmultiaddr *inm; | |||||
int i; | int i; | ||||
uint32_t hash[16]; | uint32_t hash[16]; | ||||
uint32_t crc, v; | uint32_t v; | ||||
CAS_LOCK_ASSERT(sc, MA_OWNED); | CAS_LOCK_ASSERT(sc, MA_OWNED); | ||||
/* | /* | ||||
* Turn off the RX MAC and the hash filter as required by the Sun | * Turn off the RX MAC and the hash filter as required by the Sun | ||||
* Cassini programming restrictions. | * Cassini programming restrictions. | ||||
*/ | */ | ||||
v = sc->sc_mac_rxcfg & ~(CAS_MAC_RX_CONF_HFILTER | | v = sc->sc_mac_rxcfg & ~(CAS_MAC_RX_CONF_HFILTER | | ||||
Show All 20 Lines | cas_setladrf(struct cas_softc *sc) | ||||
* Set up multicast address filter by passing all multicast | * Set up multicast address filter by passing all multicast | ||||
* addresses through a crc generator, and then using the high | * addresses through a crc generator, and then using the high | ||||
* order 8 bits as an index into the 256 bit logical address | * order 8 bits as an index into the 256 bit logical address | ||||
* filter. The high order 4 bits selects the word, while the | * filter. The high order 4 bits selects the word, while the | ||||
* other 4 bits select the bit within the word (where bit 0 | * other 4 bits select the bit within the word (where bit 0 | ||||
* is the MSB). | * is the MSB). | ||||
*/ | */ | ||||
/* Clear the hash table. */ | |||||
memset(hash, 0, sizeof(hash)); | memset(hash, 0, sizeof(hash)); | ||||
if_foreach_llmaddr(ifp, cas_hash_maddr, &hash); | |||||
if_maddr_rlock(ifp); | |||||
CK_STAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) { | |||||
if (inm->ifma_addr->sa_family != AF_LINK) | |||||
continue; | |||||
crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) | |||||
inm->ifma_addr), ETHER_ADDR_LEN); | |||||
/* We just want the 8 most significant bits. */ | |||||
crc >>= 24; | |||||
/* Set the corresponding bit in the filter. */ | |||||
hash[crc >> 4] |= 1 << (15 - (crc & 15)); | |||||
} | |||||
if_maddr_runlock(ifp); | |||||
v |= CAS_MAC_RX_CONF_HFILTER; | v |= CAS_MAC_RX_CONF_HFILTER; | ||||
/* Now load the hash table into the chip (if we are using it). */ | /* Now load the hash table into the chip (if we are using it). */ | ||||
for (i = 0; i < 16; i++) | for (i = 0; i < 16; i++) | ||||
CAS_WRITE_4(sc, | CAS_WRITE_4(sc, | ||||
CAS_MAC_HASH0 + i * (CAS_MAC_HASH1 - CAS_MAC_HASH0), | CAS_MAC_HASH0 + i * (CAS_MAC_HASH1 - CAS_MAC_HASH0), | ||||
hash[i]); | hash[i]); | ||||
▲ Show 20 Lines • Show All 354 Lines • Show Last 20 Lines |