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.