summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2012-10-22 03:23:20 +0000
committerBrad Smith <brad@cvs.openbsd.org>2012-10-22 03:23:20 +0000
commit1838174698015be18ab381c6a3c08fe751b47886 (patch)
treecc366f63e48c419e2ccb5d03e2c41ba5e59c4221
parent135858d9d657af51e59554a2194a240f86589d40 (diff)
Rewrite the receive filter handling code and cleanup the ioctl bits.
Tested by and ok stsp@
-rw-r--r--sys/dev/usb/if_mos.c116
-rw-r--r--sys/dev/usb/if_mosreg.h3
2 files changed, 37 insertions, 82 deletions
diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c
index c96146f60e6..cecf66beca2 100644
--- a/sys/dev/usb/if_mos.c
+++ b/sys/dev/usb/if_mos.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_mos.c,v 1.16 2012/02/28 08:58:30 jsg Exp $ */
+/* $OpenBSD: if_mos.c,v 1.17 2012/10/22 03:23:19 brad Exp $ */
/*
* Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net>
@@ -180,7 +180,7 @@ int mos_readmac(struct mos_softc *, u_char *);
int mos_writemac(struct mos_softc *, u_char *);
int mos_write_mcast(struct mos_softc *, u_char *);
-void mos_setmulti(struct mos_softc *);
+void mos_iff(struct mos_softc *);
void mos_lock_mii(struct mos_softc *);
void mos_unlock_mii(struct mos_softc *);
@@ -531,46 +531,41 @@ mos_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
}
void
-mos_setmulti(struct mos_softc *sc)
+mos_iff(struct mos_softc *sc)
{
- struct ifnet *ifp;
+ struct ifnet *ifp = GET_IFP(sc);
+ struct arpcom *ac = &sc->arpcom;
struct ether_multi *enm;
struct ether_multistep step;
u_int32_t h = 0;
- u_int8_t rxmode;
- u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ u_int8_t rxmode, hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
if (usbd_is_dying(sc->mos_udev))
return;
- ifp = GET_IFP(sc);
-
rxmode = mos_reg_read_1(sc, MOS_CTL);
+ rxmode &= ~(MOS_CTL_ALLMULTI | MOS_CTL_RX_PROMISC);
+ ifp->if_flags &= ~IFF_ALLMULTI;
- if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
-allmulti:
+ if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
+ ifp->if_flags |= IFF_ALLMULTI;
rxmode |= MOS_CTL_ALLMULTI;
- mos_reg_write_1(sc, MOS_CTL, rxmode);
- return;
- } else
- rxmode &= ~MOS_CTL_ALLMULTI;
-
- /* now program new ones */
- ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
- while (enm != NULL) {
- if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
- ETHER_ADDR_LEN) != 0)
- goto allmulti;
-
- h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
- hashtbl[h / 8] |= 1 << (h % 8);
- ETHER_NEXT_MULTI(step, enm);
+ if (ifp->if_flags & IFF_PROMISC)
+ rxmode |= MOS_CTL_RX_PROMISC;
+ } else {
+ /* now program new ones */
+ ETHER_FIRST_MULTI(step, ac, enm);
+ while (enm != NULL) {
+ h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
+
+ hashtbl[h / 8] |= 1 << (h % 8);
+
+ ETHER_NEXT_MULTI(step, enm);
+ }
}
- ifp->if_flags &= ~IFF_ALLMULTI;
mos_write_mcast(sc, (void *)&hashtbl);
mos_reg_write_1(sc, MOS_CTL, rxmode);
- return;
}
void
@@ -1241,22 +1236,15 @@ mos_init(void *xsc)
mos_reg_write_1(sc, MOS_IPG0, sc->mos_ipgs[0]);
mos_reg_write_1(sc, MOS_IPG1, sc->mos_ipgs[1]);
+ /* Program promiscuous mode and multicast filters. */
+ mos_iff(sc);
+
/* Enable receiver and transmitter, bridge controls speed/duplex mode */
rxmode = mos_reg_read_1(sc, MOS_CTL);
rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB;
rxmode &= ~(MOS_CTL_SLEEP);
-
- /* If we want promiscuous mode, set the allframes bit. */
- if (ifp->if_flags & IFF_PROMISC)
- rxmode |= MOS_CTL_RX_PROMISC;
-
- /* XXX: broadcast mode? */
-
mos_reg_write_1(sc, MOS_CTL, rxmode);
- /* Load the multicast filter. */
- mos_setmulti(sc);
-
mii_mediachg(GET_MII(sc));
/* Open RX and TX pipes. */
@@ -1303,8 +1291,6 @@ mos_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
struct mos_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct ifaddr *ifa = (struct ifaddr *)data;
- struct mii_data *mii;
- u_int8_t rxmode;
int s, error = 0;
s = splnet();
@@ -1320,63 +1306,33 @@ mos_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
#endif
break;
- case SIOCSIFMTU:
- if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
- error = EINVAL;
- else if (ifp->if_mtu != ifr->ifr_mtu)
- ifp->if_mtu = ifr->ifr_mtu;
- break;
-
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
- if (ifp->if_flags & IFF_RUNNING &&
- ifp->if_flags & IFF_PROMISC &&
- !(sc->mos_if_flags & IFF_PROMISC)) {
- rxmode = mos_reg_read_1(sc, MOS_CTL);
- rxmode |= MOS_CTL_RX_PROMISC;
- mos_reg_write_1(sc, MOS_CTL, rxmode);
- mos_setmulti(sc);
- } else if (ifp->if_flags & IFF_RUNNING &&
- !(ifp->if_flags & IFF_PROMISC) &&
- !(sc->mos_if_flags & IFF_PROMISC)) {
- rxmode = mos_reg_read_1(sc, MOS_CTL);
- rxmode |= MOS_CTL_RX_PROMISC;
- mos_reg_write_1(sc, MOS_CTL, rxmode);
- mos_setmulti(sc);
- } else if (!(ifp->if_flags & IFF_RUNNING))
+ if (ifp->if_flags & IFF_RUNNING)
+ error = ENETRESET;
+ else
mos_init(sc);
} else {
if (ifp->if_flags & IFF_RUNNING)
mos_stop(sc);
}
- sc->mos_if_flags = ifp->if_flags;
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- error = (cmd == SIOCADDMULTI) ?
- ether_addmulti(ifr, &sc->arpcom) :
- ether_delmulti(ifr, &sc->arpcom);
-
- if (error == ENETRESET) {
- /*
- * Multicast list has changed; set the hardware
- * filter accordingly.
- */
- if (ifp->if_flags & IFF_RUNNING)
- mos_setmulti(sc);
- error = 0;
- }
break;
+
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
- mii = GET_MII(sc);
- error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ error = ifmedia_ioctl(ifp, ifr, &sc->mos_mii.mii_media, cmd);
break;
default:
error = ether_ioctl(ifp, &sc->arpcom, cmd, data);
}
+ if (error == ENETRESET) {
+ if (ifp->if_flags & IFF_RUNNING)
+ mos_iff(sc);
+ error = 0;
+ }
+
splx(s);
return(error);
}
diff --git a/sys/dev/usb/if_mosreg.h b/sys/dev/usb/if_mosreg.h
index c1732ece7bc..19f7205a3d3 100644
--- a/sys/dev/usb/if_mosreg.h
+++ b/sys/dev/usb/if_mosreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_mosreg.h,v 1.5 2012/02/28 08:58:30 jsg Exp $ */
+/* $OpenBSD: if_mosreg.h,v 1.6 2012/10/22 03:23:19 brad Exp $ */
/*
* Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net>
@@ -179,7 +179,6 @@ struct mos_softc {
int mos_ed[MOS_ENDPT_MAX];
usbd_pipe_handle mos_ep[MOS_ENDPT_MAX];
int mos_unit;
- int mos_if_flags;
struct mos_cdata mos_cdata;
struct timeout mos_stat_ch;