diff options
author | Christian Weisgerber <naddy@cvs.openbsd.org> | 2009-12-22 21:10:26 +0000 |
---|---|---|
committer | Christian Weisgerber <naddy@cvs.openbsd.org> | 2009-12-22 21:10:26 +0000 |
commit | 3577315b7c4436e4b96b8b9f1d54181b4451d77e (patch) | |
tree | b2eb97bdf872078a8fa214e5ce6dab6dfed67cbf /sys | |
parent | e78e8f08d27ba6c22389204d2ceacd391031aac1 (diff) |
rewrite promiscuous mode and multicast handling; from Brad
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/xl.c | 199 | ||||
-rw-r--r-- | sys/dev/ic/xlreg.h | 3 |
2 files changed, 81 insertions, 121 deletions
diff --git a/sys/dev/ic/xl.c b/sys/dev/ic/xl.c index 73d5f7ca63b..478166ee6a0 100644 --- a/sys/dev/ic/xl.c +++ b/sys/dev/ic/xl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xl.c,v 1.87 2009/10/15 17:54:54 deraadt Exp $ */ +/* $OpenBSD: xl.c,v 1.88 2009/12/22 21:10:25 naddy Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -178,9 +178,9 @@ int xl_mii_writereg(struct xl_softc *, struct xl_mii_frame *); void xl_setcfg(struct xl_softc *); void xl_setmode(struct xl_softc *, int); -void xl_setmulti(struct xl_softc *); -void xl_setmulti_hash(struct xl_softc *); -void xl_setpromisc(struct xl_softc *); +void xl_iff(struct xl_softc *); +void xl_iff_90x(struct xl_softc *); +void xl_iff_905b(struct xl_softc *); void xl_reset(struct xl_softc *); int xl_list_rx_init(struct xl_softc *); int xl_list_tx_init(struct xl_softc *); @@ -556,110 +556,110 @@ xl_read_eeprom(struct xl_softc *sc, caddr_t dest, int off, int cnt, int swap) return (err ? 1 : 0); } +void +xl_iff(struct xl_softc *sc) +{ + if (sc->xl_type == XL_TYPE_905B) + xl_iff_905b(sc); + else + xl_iff_90x(sc); +} + /* * NICs older than the 3c905B have only one multicast option, which * is to enable reception of all multicast frames. */ void -xl_setmulti(struct xl_softc *sc) +xl_iff_90x(struct xl_softc *sc) { - struct ifnet *ifp; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct arpcom *ac = &sc->sc_arpcom; u_int8_t rxfilt; - ifp = &sc->sc_arpcom.ac_if; - XL_SEL_WIN(5); + rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); + rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI | + XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL); + ifp->if_flags &= ~IFF_ALLMULTI; - if (ifp->if_flags & IFF_ALLMULTI) { - rxfilt |= XL_RXFILTER_ALLMULTI; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - return; + /* + * Always accept broadcast frames. + * Always accept frames destined to our station address. + */ + rxfilt |= XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL; + + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0 || + ac->ac_multicnt > 0) { + ifp->if_flags |= IFF_ALLMULTI; + if (ifp->if_flags & IFF_PROMISC) + rxfilt |= XL_RXFILTER_ALLFRAMES; + else + rxfilt |= XL_RXFILTER_ALLMULTI; } - if (ac->ac_multicnt > 0) - rxfilt |= XL_RXFILTER_ALLMULTI; - else - rxfilt &= ~XL_RXFILTER_ALLMULTI; + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT | rxfilt); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); + XL_SEL_WIN(7); } /* * 3c905B adapters have a hash filter that we can program. */ void -xl_setmulti_hash(struct xl_softc *sc) +xl_iff_905b(struct xl_softc *sc) { - struct ifnet *ifp; - int h = 0, i; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct arpcom *ac = &sc->sc_arpcom; + int h = 0, i; struct ether_multi *enm; struct ether_multistep step; u_int8_t rxfilt; - int mcnt = 0; - - ifp = &sc->sc_arpcom.ac_if; XL_SEL_WIN(5); - rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); - if (ifp->if_flags & IFF_ALLMULTI) { -allmulti: - rxfilt |= XL_RXFILTER_ALLMULTI; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - return; - } else - rxfilt &= ~XL_RXFILTER_ALLMULTI; - - - /* first, zot all the existing hash bits */ - for (i = 0; i < XL_HASHFILT_SIZE; i++) - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i); + rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); + rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI | + XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL | + XL_RXFILTER_MULTIHASH); + ifp->if_flags &= ~IFF_ALLMULTI; - /* 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) & - 0x000000FF; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|XL_HASH_SET|h); - mcnt++; - ETHER_NEXT_MULTI(step, enm); - } + /* + * Always accept broadcast frames. + * Always accept frames destined to our station address. + */ + rxfilt |= XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL; - if (mcnt) + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { + ifp->if_flags |= IFF_ALLMULTI; + if (ifp->if_flags & IFF_PROMISC) + rxfilt |= XL_RXFILTER_ALLFRAMES; + else + rxfilt |= XL_RXFILTER_ALLMULTI; + } else { rxfilt |= XL_RXFILTER_MULTIHASH; - else - rxfilt &= ~XL_RXFILTER_MULTIHASH; - - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); -} -void -xl_setpromisc(struct xl_softc *sc) -{ - struct ifnet *ifp; - u_int8_t rxfilt; + /* first, zot all the existing hash bits */ + for (i = 0; i < XL_HASHFILT_SIZE; i++) + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i); - ifp = &sc->sc_arpcom.ac_if; + /* now program new ones */ + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) & + 0x000000FF; + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH | + XL_HASH_SET | h); - XL_SEL_WIN(5); - rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); + ETHER_NEXT_MULTI(step, enm); + } + } - if (ifp->if_flags & IFF_PROMISC) - rxfilt |= XL_RXFILTER_ALLFRAMES; - else - rxfilt &= ~XL_RXFILTER_ALLFRAMES; + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT | rxfilt); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); + XL_SEL_WIN(7); } - #ifdef notdef void xl_testpacket(struct xl_softc *sc) @@ -1936,7 +1936,6 @@ xl_init(void *xsc) struct xl_softc *sc = xsc; struct ifnet *ifp = &sc->sc_arpcom.ac_if; int s, i; - u_int16_t rxfilt = 0; struct mii_data *mii = NULL; s = splnet(); @@ -2014,37 +2013,8 @@ xl_init(void *xsc) XL_CMD_SET_TX_RECLAIM|(XL_PACKET_SIZE >> 4)); } - /* Set RX filter bits. */ - XL_SEL_WIN(5); - rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); - - /* Set the individual bit to receive frames for this host only. */ - rxfilt |= XL_RXFILTER_INDIVIDUAL; - - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - - /* Set promiscuous mode. */ - xl_setpromisc(sc); - - rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); - - /* - * Set capture broadcast bit to capture broadcast frames. - */ - if (ifp->if_flags & IFF_BROADCAST) - rxfilt |= XL_RXFILTER_BROADCAST; - else - rxfilt &= ~XL_RXFILTER_BROADCAST; - - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - - /* - * Program the multicast filter, if necessary. - */ - if (sc->xl_type == XL_TYPE_905B) - xl_setmulti_hash(sc); - else - xl_setmulti(sc); + /* Program promiscuous mode and multicast filters. */ + xl_iff(sc); /* * Load the address of the RX list. We have to @@ -2278,27 +2248,21 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data) #ifdef INET if (ifa->ifa_addr->sa_family == AF_INET) arp_ifinit(&sc->sc_arpcom, ifa); -#endif /* INET */ +#endif break; case SIOCSIFFLAGS: - XL_SEL_WIN(5); if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING && - (ifp->if_flags ^ sc->xl_if_flags) & - IFF_PROMISC) { - xl_setpromisc(sc); - XL_SEL_WIN(7); - } else { - if (!(ifp->if_flags & IFF_RUNNING)) - xl_init(sc); - } + if (ifp->if_flags & IFF_RUNNING) + error = ENETRESET; + else + xl_init(sc); } else { if (ifp->if_flags & IFF_RUNNING) xl_stop(sc); } - sc->xl_if_flags = ifp->if_flags; break; + case SIOCGIFMEDIA: case SIOCSIFMEDIA: if (sc->xl_hasmii != 0) @@ -2310,17 +2274,14 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; + default: error = ether_ioctl(ifp, &sc->sc_arpcom, command, data); } if (error == ENETRESET) { - if (ifp->if_flags & IFF_RUNNING) { - if (sc->xl_type == XL_TYPE_905B) - xl_setmulti_hash(sc); - else - xl_setmulti(sc); - } + if (ifp->if_flags & IFF_RUNNING) + xl_iff(sc); error = 0; } diff --git a/sys/dev/ic/xlreg.h b/sys/dev/ic/xlreg.h index 3f4abcf6579..cacfde8cb9c 100644 --- a/sys/dev/ic/xlreg.h +++ b/sys/dev/ic/xlreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xlreg.h,v 1.19 2004/05/30 23:49:39 brad Exp $ */ +/* $OpenBSD: xlreg.h,v 1.20 2009/12/22 21:10:25 naddy Exp $ */ /* * Copyright (c) 1997, 1998 @@ -591,7 +591,6 @@ struct xl_softc { u_int16_t xl_caps; u_int8_t xl_stats_no_timeout; u_int16_t xl_tx_thresh; - int xl_if_flags; struct xl_list_data *xl_ldata; struct xl_chain_data xl_cdata; int xl_flags; |