summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-11-17 20:47:43 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-11-17 20:47:43 +0000
commit5cfc84e03fb8b67423babab08dbc786daa25358b (patch)
treeb3518f4292b911915a9033b16be76de4451472e3 /sys
parent1d4196bb0957e0cd42eaac1b59e6cc02c39e0d02 (diff)
Tidy up promisc/multicast handing. From Brad. Tested by me.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_cas.c115
1 files changed, 45 insertions, 70 deletions
diff --git a/sys/dev/pci/if_cas.c b/sys/dev/pci/if_cas.c
index 019c9bc3591..7e967470523 100644
--- a/sys/dev/pci/if_cas.c
+++ b/sys/dev/pci/if_cas.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_cas.c,v 1.27 2009/07/23 19:35:32 kettenis Exp $ */
+/* $OpenBSD: if_cas.c,v 1.28 2009/11/17 20:47:42 kettenis Exp $ */
/*
*
@@ -125,7 +125,7 @@ int cas_disable_rx(struct cas_softc *);
int cas_disable_tx(struct cas_softc *);
void cas_rxdrain(struct cas_softc *);
int cas_add_rxbuf(struct cas_softc *, int idx);
-void cas_setladrf(struct cas_softc *);
+void cas_iff(struct cas_softc *);
int cas_encap(struct cas_softc *, struct mbuf *, u_int32_t *);
/* MII methods & callbacks */
@@ -982,7 +982,7 @@ cas_init(struct ifnet *ifp)
bus_space_write_4(t, h, CAS_MAC_MAC_MAX_FRAME, v);
/* step 5. RX MAC registers & counters */
- cas_setladrf(sc);
+ cas_iff(sc);
/* step 6 & 7. Program Descriptor Ring Base Addresses */
KASSERT((CAS_CDTXADDR(sc, 0) & 0x1fff) == 0);
@@ -1718,7 +1718,7 @@ cas_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
if (error == ENETRESET) {
if (ifp->if_flags & IFF_RUNNING)
- cas_setladrf(sc);
+ cas_iff(sc);
error = 0;
}
@@ -1736,93 +1736,68 @@ cas_shutdown(void *arg)
cas_stop(ifp, 1);
}
-/*
- * Set up the logical address filter.
- */
void
-cas_setladrf(struct cas_softc *sc)
+cas_iff(struct cas_softc *sc)
{
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ struct arpcom *ac = &sc->sc_arpcom;
struct ether_multi *enm;
struct ether_multistep step;
- struct arpcom *ac = &sc->sc_arpcom;
bus_space_tag_t t = sc->sc_memt;
bus_space_handle_t h = sc->sc_memh;
- u_int32_t crc, hash[16], v;
+ u_int32_t crc, hash[16], rxcfg;
int i;
- /* Get current RX configuration */
- v = bus_space_read_4(t, h, CAS_MAC_RX_CONFIG);
-
-
- /*
- * Turn off promiscuous mode, promiscuous group mode (all multicast),
- * and hash filter. Depending on the case, the right bit will be
- * enabled.
- */
- v &= ~(CAS_MAC_RX_PROMISCUOUS|CAS_MAC_RX_HASH_FILTER|
+ rxcfg = bus_space_read_4(t, h, CAS_MAC_RX_CONFIG);
+ rxcfg &= ~(CAS_MAC_RX_HASH_FILTER | CAS_MAC_RX_PROMISCUOUS |
CAS_MAC_RX_PROMISC_GRP);
+ ifp->if_flags &= ~IFF_ALLMULTI;
- if ((ifp->if_flags & IFF_PROMISC) != 0) {
- /* Turn on promiscuous mode */
- v |= CAS_MAC_RX_PROMISCUOUS;
+ if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
ifp->if_flags |= IFF_ALLMULTI;
- goto chipit;
- }
-
- /*
- * Set up multicast address filter by passing all multicast addresses
- * through a crc generator, and then using the high order 8 bits as an
- * index into the 256 bit logical address filter. The high order 4
- * bits selects the word, while the other 4 bits select the bit within
- * the word (where bit 0 is the MSB).
- */
-
- /* Clear hash table */
- for (i = 0; i < 16; i++)
- hash[i] = 0;
+ if (ifp->if_flags & IFF_PROMISC)
+ rxcfg |= CAS_MAC_RX_PROMISCUOUS;
+ else
+ rxcfg |= CAS_MAC_RX_PROMISC_GRP;
+ } else {
+ /*
+ * Set up multicast address filter by passing all multicast
+ * addresses through a crc generator, and then using the
+ * high order 8 bits as an index into the 256 bit logical
+ * address filter. The high order 4 bits selects the word,
+ * while the other 4 bits select the bit within the word
+ * (where bit 0 is the MSB).
+ */
+ rxcfg |= CAS_MAC_RX_HASH_FILTER;
- ETHER_FIRST_MULTI(step, ac, enm);
- while (enm != NULL) {
- if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
- /*
- * We must listen to a range of multicast addresses.
- * For now, just accept all multicasts, rather than
- * trying to set only those filter bits needed to match
- * the range. (At this time, the only use of address
- * ranges is for IP multicast routing, for which the
- * range is big enough to require all bits set.)
- * XXX use the addr filter for this
- */
- ifp->if_flags |= IFF_ALLMULTI;
- v |= CAS_MAC_RX_PROMISC_GRP;
- goto chipit;
- }
+ /* Clear hash table */
+ for (i = 0; i < 16; i++)
+ hash[i] = 0;
- crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
+ ETHER_FIRST_MULTI(step, ac, enm);
+ while (enm != NULL) {
+ crc = ether_crc32_le(enm->enm_addrlo,
+ ETHER_ADDR_LEN);
- /* Just want the 8 most significant bits. */
- crc >>= 24;
+ /* Just want the 8 most significant bits. */
+ crc >>= 24;
- /* Set the corresponding bit in the filter. */
- hash[crc >> 4] |= 1 << (15 - (crc & 15));
+ /* Set the corresponding bit in the filter. */
+ hash[crc >> 4] |= 1 << (15 - (crc & 15));
- ETHER_NEXT_MULTI(step, enm);
- }
-
- v |= CAS_MAC_RX_HASH_FILTER;
- ifp->if_flags &= ~IFF_ALLMULTI;
+ ETHER_NEXT_MULTI(step, enm);
+ }
- /* Now load the hash table into the chip (if we are using it) */
- for (i = 0; i < 16; i++) {
- bus_space_write_4(t, h,
- CAS_MAC_HASH0 + i * (CAS_MAC_HASH1-CAS_MAC_HASH0),
- hash[i]);
+ /* Now load the hash table into the chip (if we are using it) */
+ for (i = 0; i < 16; i++) {
+ bus_space_write_4(t, h,
+ CAS_MAC_HASH0 + i * (CAS_MAC_HASH1 - CAS_MAC_HASH0),
+ hash[i]);
+ }
}
-chipit:
- bus_space_write_4(t, h, CAS_MAC_RX_CONFIG, v);
+ bus_space_write_4(t, h, CAS_MAC_RX_CONFIG, rxcfg);
}
int