Here is a diff for the epic(4) SMC 83C170 driver to clean up and update the receive filter / ioctl handling code to be in line with the other drivers.
Anyone with hw and able to test? OK? Index: smc83c170.c =================================================================== RCS file: /home/cvs/src/sys/dev/ic/smc83c170.c,v retrieving revision 1.16 diff -u -p -r1.16 smc83c170.c --- smc83c170.c 26 Nov 2013 09:50:33 -0000 1.16 +++ smc83c170.c 1 Dec 2013 01:12:31 -0000 @@ -84,7 +84,7 @@ void epic_reset(struct epic_softc *); void epic_rxdrain(struct epic_softc *); int epic_add_rxbuf(struct epic_softc *, int); void epic_read_eeprom(struct epic_softc *, int, int, u_int16_t *); -void epic_set_mchash(struct epic_softc *); +void epic_iff(struct epic_softc *); void epic_fixup_clock_source(struct epic_softc *); int epic_mii_read(struct device *, int, int); void epic_mii_write(struct device *, int, int, int); @@ -536,31 +536,24 @@ epic_ioctl(struct ifnet *ifp, u_long cmd switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: + if (!(ifp->if_flags & IFF_RUNNING)) epic_init(ifp); +#ifdef INET + if (ifa->ifa_addr->sa_family == AF_INET) arp_ifinit(&sc->sc_arpcom, ifa); - break; #endif - default: - epic_init(ifp); - break; - } break; case SIOCSIFFLAGS: - /* - * If interface is marked up and not running, then start it. - * If it is marked down and running, stop it. - * XXX If it's up then re-initialize it. This is so flags - * such as IFF_PROMISC are handled. - */ - if (ifp->if_flags & IFF_UP) - epic_init(ifp); - else if (ifp->if_flags & IFF_RUNNING) - epic_stop(ifp, 1); + if (ifp->if_flags & IFF_UP) { + if (ifp->if_flags & IFF_RUNNING) + error = ENETRESET; + else + epic_init(ifp); + } else { + if (ifp->if_flags & IFF_RUNNING) + epic_stop(ifp, 1); + } break; case SIOCSIFMEDIA: @@ -575,7 +568,7 @@ epic_ioctl(struct ifnet *ifp, u_long cmd if (error == ENETRESET) { if (ifp->if_flags & IFF_RUNNING) { mii_pollstat(&sc->sc_mii); - epic_set_mchash(sc); + epic_iff(sc); } error = 0; } @@ -974,8 +967,8 @@ epic_init(struct ifnet *ifp) /* Set the current media. */ epic_mediachange(ifp); - /* Set up the multicast hash table. */ - epic_set_mchash(sc); + /* Program promiscuous mode and multicast filters. */ + epic_iff(sc); /* * Initialize the transmit descriptor ring. txlast is initialized @@ -1260,7 +1253,7 @@ epic_add_rxbuf(struct epic_softc *sc, in * NOTE: We rely on a recently-updated mii_media_active here! */ void -epic_set_mchash(struct epic_softc *sc) +epic_iff(struct epic_softc *sc) { struct arpcom *ac = &sc->sc_arpcom; struct ifnet *ifp = &sc->sc_arpcom.ac_if; @@ -1268,47 +1261,38 @@ epic_set_mchash(struct epic_softc *sc) 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; - } + ifp->if_flags &= ~IFF_ALLMULTI; - if (ac->ac_multirangecnt > 0) - goto allmulti; + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0 || + IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_10_T) { + ifp->if_flags |= IFF_ALLMULTI; + mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0xffff; + } else { + mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0; - mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0; + /* + * 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. + */ + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + hash = ether_crc32_be(enm->enm_addrlo, + ETHER_ADDR_LEN); - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - hash = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN); - hash >>= 26; + hash >>= 26; - /* Set the corresponding bit in the hash table. */ - mchash[hash >> 4] |= 1 << (hash & 0xf); + /* Set the corresponding bit in the hash table. */ + mchash[hash >> 4] |= 1 << (hash & 0xf); - ETHER_NEXT_MULTI(step, enm); + 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]); @@ -1407,7 +1391,7 @@ epic_statchg(struct device *self) * There is a multicast filter bug in 10Mbps mode. Kick the * multicast filter in case the speed changed. */ - epic_set_mchash(sc); + epic_iff(sc); } /* -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.