Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/xl/if_xl.c
Show First 20 Lines • Show All 600 Lines • ▼ Show 20 Lines | xl_rxfilter(struct xl_softc *sc) | ||||
else | else | ||||
xl_rxfilter_90x(sc); | xl_rxfilter_90x(sc); | ||||
} | } | ||||
/* | /* | ||||
* NICs older than the 3c905B have only one multicast option, which | * NICs older than the 3c905B have only one multicast option, which | ||||
* is to enable reception of all multicast frames. | * is to enable reception of all multicast frames. | ||||
*/ | */ | ||||
static u_int | |||||
xl_check_maddr_90x(void *arg, struct sockaddr_dl *sdl, u_int cnt) | |||||
{ | |||||
uint8_t *rxfilt = arg; | |||||
*rxfilt |= XL_RXFILTER_ALLMULTI; | |||||
return (1); | |||||
} | |||||
static void | static void | ||||
xl_rxfilter_90x(struct xl_softc *sc) | xl_rxfilter_90x(struct xl_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ifmultiaddr *ifma; | |||||
u_int8_t rxfilt; | u_int8_t rxfilt; | ||||
XL_LOCK_ASSERT(sc); | XL_LOCK_ASSERT(sc); | ||||
ifp = sc->xl_ifp; | ifp = sc->xl_ifp; | ||||
XL_SEL_WIN(5); | XL_SEL_WIN(5); | ||||
rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); | rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); | ||||
rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI | | rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI | | ||||
XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL); | XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL); | ||||
/* Set the individual bit to receive frames for this host only. */ | /* Set the individual bit to receive frames for this host only. */ | ||||
rxfilt |= XL_RXFILTER_INDIVIDUAL; | rxfilt |= XL_RXFILTER_INDIVIDUAL; | ||||
/* Set capture broadcast bit to capture broadcast frames. */ | /* Set capture broadcast bit to capture broadcast frames. */ | ||||
if (ifp->if_flags & IFF_BROADCAST) | if (ifp->if_flags & IFF_BROADCAST) | ||||
rxfilt |= XL_RXFILTER_BROADCAST; | rxfilt |= XL_RXFILTER_BROADCAST; | ||||
/* If we want promiscuous mode, set the allframes bit. */ | /* If we want promiscuous mode, set the allframes bit. */ | ||||
if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { | if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { | ||||
if (ifp->if_flags & IFF_PROMISC) | if (ifp->if_flags & IFF_PROMISC) | ||||
rxfilt |= XL_RXFILTER_ALLFRAMES; | rxfilt |= XL_RXFILTER_ALLFRAMES; | ||||
if (ifp->if_flags & IFF_ALLMULTI) | if (ifp->if_flags & IFF_ALLMULTI) | ||||
rxfilt |= XL_RXFILTER_ALLMULTI; | rxfilt |= XL_RXFILTER_ALLMULTI; | ||||
} else { | } else | ||||
if_maddr_rlock(ifp); | if_foreach_llmaddr(sc->xl_ifp, xl_check_maddr_90x, &rxfilt); | ||||
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { | |||||
if (ifma->ifma_addr->sa_family != AF_LINK) | |||||
continue; | |||||
rxfilt |= XL_RXFILTER_ALLMULTI; | |||||
break; | |||||
} | |||||
if_maddr_runlock(ifp); | |||||
} | |||||
CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT); | CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT); | ||||
XL_SEL_WIN(7); | XL_SEL_WIN(7); | ||||
} | } | ||||
/* | /* | ||||
* 3c905B adapters have a hash filter that we can program. | * 3c905B adapters have a hash filter that we can program. | ||||
* Note: the 3c905B currently only supports a 64-bit | |||||
* hash table, which means we really only need 6 bits, | |||||
* but the manual indicates that future chip revisions | |||||
* will have a 256-bit hash table, hence the routine | |||||
* is set up to calculate 8 bits of position info in | |||||
* case we need it some day. | |||||
* Note II, The Sequel: _CURRENT_ versions of the | |||||
* 3c905B have a 256 bit hash table. This means we have | |||||
* to use all 8 bits regardless. On older cards, the | |||||
* upper 2 bits will be ignored. Grrrr.... | |||||
*/ | */ | ||||
static u_int | |||||
xl_check_maddr_90xB(void *arg, struct sockaddr_dl *sdl, u_int count) | |||||
{ | |||||
struct xl_softc *sc = arg; | |||||
uint16_t h; | |||||
h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) & 0xFF; | |||||
CSR_WRITE_2(sc, XL_COMMAND, h | XL_CMD_RX_SET_HASH | XL_HASH_SET); | |||||
return (1); | |||||
} | |||||
static void | static void | ||||
xl_rxfilter_90xB(struct xl_softc *sc) | xl_rxfilter_90xB(struct xl_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ifmultiaddr *ifma; | int i; | ||||
int i, mcnt; | |||||
u_int16_t h; | |||||
u_int8_t rxfilt; | u_int8_t rxfilt; | ||||
XL_LOCK_ASSERT(sc); | XL_LOCK_ASSERT(sc); | ||||
ifp = sc->xl_ifp; | ifp = sc->xl_ifp; | ||||
XL_SEL_WIN(5); | XL_SEL_WIN(5); | ||||
rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); | rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); | ||||
Show All 14 Lines | if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { | ||||
if (ifp->if_flags & IFF_ALLMULTI) | if (ifp->if_flags & IFF_ALLMULTI) | ||||
rxfilt |= XL_RXFILTER_ALLMULTI; | rxfilt |= XL_RXFILTER_ALLMULTI; | ||||
} else { | } else { | ||||
/* First, zot all the existing hash bits. */ | /* First, zot all the existing hash bits. */ | ||||
for (i = 0; i < XL_HASHFILT_SIZE; i++) | for (i = 0; i < XL_HASHFILT_SIZE; i++) | ||||
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH | i); | CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH | i); | ||||
/* Now program new ones. */ | /* Now program new ones. */ | ||||
mcnt = 0; | if (if_foreach_llmaddr(sc->xl_ifp, xl_check_maddr_90xB, sc) > 0) | ||||
if_maddr_rlock(ifp); | |||||
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { | |||||
if (ifma->ifma_addr->sa_family != AF_LINK) | |||||
continue; | |||||
/* | |||||
* Note: the 3c905B currently only supports a 64-bit | |||||
* hash table, which means we really only need 6 bits, | |||||
* but the manual indicates that future chip revisions | |||||
* will have a 256-bit hash table, hence the routine | |||||
* is set up to calculate 8 bits of position info in | |||||
* case we need it some day. | |||||
* Note II, The Sequel: _CURRENT_ versions of the | |||||
* 3c905B have a 256 bit hash table. This means we have | |||||
* to use all 8 bits regardless. On older cards, the | |||||
* upper 2 bits will be ignored. Grrrr.... | |||||
*/ | |||||
h = ether_crc32_be(LLADDR((struct sockaddr_dl *) | |||||
ifma->ifma_addr), ETHER_ADDR_LEN) & 0xFF; | |||||
CSR_WRITE_2(sc, XL_COMMAND, | |||||
h | XL_CMD_RX_SET_HASH | XL_HASH_SET); | |||||
mcnt++; | |||||
} | |||||
if_maddr_runlock(ifp); | |||||
if (mcnt > 0) | |||||
rxfilt |= XL_RXFILTER_MULTIHASH; | rxfilt |= XL_RXFILTER_MULTIHASH; | ||||
} | } | ||||
CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT); | CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT); | ||||
XL_SEL_WIN(7); | XL_SEL_WIN(7); | ||||
} | } | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 2,578 Lines • Show Last 20 Lines |