Here is a diff for the mtd(4) Myson MTD800/MTD803/MTD891 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: mtd8xx.c
===================================================================
RCS file: /home/cvs/src/sys/dev/ic/mtd8xx.c,v
retrieving revision 1.21
diff -u -p -r1.21 mtd8xx.c
--- mtd8xx.c    26 Nov 2013 09:50:33 -0000      1.21
+++ mtd8xx.c    2 Dec 2013 01:34:24 -0000
@@ -68,7 +68,7 @@ static u_int32_t mtd_mii_command(struct 
 static int mtd_miibus_readreg(struct device *, int, int);
 static void mtd_miibus_writereg(struct device *, int, int, int);
 static void mtd_miibus_statchg(struct device *);
-static void mtd_setmulti(struct mtd_softc *);
+void mtd_iff(struct mtd_softc *);
 
 static int mtd_encap(struct mtd_softc *, struct mbuf *, u_int32_t *);
 static int mtd_list_rx_init(struct mtd_softc *);
@@ -313,42 +313,45 @@ mtd_miibus_statchg(struct device *self)
 
 
 void
-mtd_setmulti(struct mtd_softc *sc)
+mtd_iff(struct mtd_softc *sc)
 {
        struct arpcom *ac = &sc->sc_arpcom;
        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
-       u_int32_t rxfilt, crc, hash[2] = { 0, 0 };
        struct ether_multistep step;
        struct ether_multi *enm;
-       int mcnt = 0;
+       u_int32_t rxfilt, crc, hash[2];
 
-       if (ac->ac_multirangecnt > 0)
-               ifp->if_flags |= IFF_ALLMULTI;
+       rxfilt = CSR_READ_4(MTD_TCRRCR);
+       rxfilt &= ~(RCR_AB | RCR_AM | RCR_PROM);
+       ifp->if_flags &= ~IFF_ALLMULTI;
+
+       /*
+        * Always accept broadcast frames.
+        */
+       rxfilt |= RCR_AB;
 
-       rxfilt = CSR_READ_4(MTD_TCRRCR) & ~RCR_AM;
-       if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
+       if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
+               ifp->if_flags |= IFF_ALLMULTI;
                rxfilt |= RCR_AM;
-               CSR_WRITE_4(MTD_TCRRCR, rxfilt);
-               CSR_WRITE_4(MTD_MAR0, 0xffffffff);
-               CSR_WRITE_4(MTD_MAR4, 0xffffffff);
-               return;
-       }
+               if (ifp->if_flags & IFF_PROMISC)
+                       rxfilt |= RCR_PROM;
+               hash[0] = hash[1] = 0xffffffff;
+       } else {
+               rxfilt |= RCR_AM;
+               /* Program new filter. */
+               bzero(hash, sizeof(hash));
+
+               ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
+               while (enm != NULL) {
+                       crc = ether_crc32_be(enm->enm_addrlo,
+                           ETHER_ADDR_LEN) >> 26;
+
+                       hash[crc >> 5] |= 1 << (crc & 0xf);
 
-       /* First, zot all the existing hash bits. */
-       CSR_WRITE_4(MTD_MAR0, 0);
-       CSR_WRITE_4(MTD_MAR4, 0);
-
-       /* Now program new ones. */
-       ETHER_FIRST_MULTI(step, ac, enm);
-       while (enm != NULL) {
-               crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
-               hash[crc >> 5] |= 1 << (crc & 0xf);
-               ++mcnt;
-               ETHER_NEXT_MULTI(step, enm);
+                       ETHER_NEXT_MULTI(step, enm);
+               }
        }
 
-       if (mcnt)
-               rxfilt |= RCR_AM;
        CSR_WRITE_4(MTD_MAR0, hash[0]);
        CSR_WRITE_4(MTD_MAR4, hash[1]);
        CSR_WRITE_4(MTD_TCRRCR, rxfilt);
@@ -584,37 +587,39 @@ mtd_ioctl(struct ifnet *ifp, u_long comm
        switch (command) {
        case SIOCSIFADDR:
                ifp->if_flags |= IFF_UP;
-               mtd_init(ifp);
-               switch (ifa->ifa_addr->sa_family) {
+               if (!(ifp->if_flags & IFF_RUNNING))
+                       mtd_init(ifp);
+
 #ifdef INET
-               case AF_INET:
+               if (ifa->ifa_addr->sa_family == AF_INET)
                        arp_ifinit(&sc->sc_arpcom, ifa);
-                       break;
-#endif /* INET */
-               }
+#endif
                break;
 
        case SIOCSIFFLAGS:
-               if (ifp->if_flags & IFF_UP)
-                       mtd_init(ifp);
-               else {
+               if (ifp->if_flags & IFF_UP) {
+                       if (ifp->if_flags & IFF_RUNNING)
+                               error = ENETRESET;
+                       else
+                               mtd_init(ifp);
+               } else {
                        if (ifp->if_flags & IFF_RUNNING)
                                mtd_stop(ifp);
                }
-               error = 0;
                break;
 
        case SIOCGIFMEDIA:
        case SIOCSIFMEDIA:
                error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
                break;
+
        default:
                error = ether_ioctl(ifp, &sc->sc_arpcom, command, data);
        }
 
        if (error == ENETRESET) {
                if (ifp->if_flags & IFF_RUNNING)
-                       mtd_setmulti(sc);
+                       mtd_iff(sc);
                error = 0;
        }
 
@@ -646,17 +651,8 @@ mtd_init(struct ifnet *ifp)
                CSR_SETBIT(MTD_TCRRCR, TCR_ENHANCED);
        }
 
-       if (ifp->if_flags & IFF_PROMISC)
-               CSR_SETBIT(MTD_TCRRCR, RCR_PROM);
-       else
-               CSR_CLRBIT(MTD_TCRRCR, RCR_PROM);
-
-       if (ifp->if_flags & IFF_BROADCAST)
-               CSR_SETBIT(MTD_TCRRCR, RCR_AB);
-       else
-               CSR_CLRBIT(MTD_TCRRCR, RCR_AB);
-
-       mtd_setmulti(sc);
+       /* Program promiscuous mode and multicast filters. */
+       mtd_iff(sc);
 
        if (mtd_list_rx_init(sc)) {
                printf("%s: can't allocate memeory for rx buffers\n",

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to