summaryrefslogtreecommitdiff
path: root/sys/dev/ic/gem.c
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2009-07-18 12:56:17 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2009-07-18 12:56:17 +0000
commitce6ecdbd09cf3a2695da32cc776bbb21a4616db6 (patch)
tree6caa5a3b9e4414cab1e6abf1c6b59e3bfbf560bc /sys/dev/ic/gem.c
parentb1b5bd05a80cd0836d0f95dc88d3422f9fa8992d (diff)
Simplify receive filter handling, from Brad.
Tested by Brad on sparc64, todd@ on macppc.
Diffstat (limited to 'sys/dev/ic/gem.c')
-rw-r--r--sys/dev/ic/gem.c119
1 files changed, 47 insertions, 72 deletions
diff --git a/sys/dev/ic/gem.c b/sys/dev/ic/gem.c
index cd64232f7a8..93ae0db062d 100644
--- a/sys/dev/ic/gem.c
+++ b/sys/dev/ic/gem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gem.c,v 1.90 2009/03/29 11:53:47 kettenis Exp $ */
+/* $OpenBSD: gem.c,v 1.91 2009/07/18 12:56:16 sthen Exp $ */
/* $NetBSD: gem.c,v 1.1 2001/09/16 00:11:43 eeh Exp $ */
/*
@@ -101,7 +101,7 @@ void gem_rx_watchdog(void *);
void gem_rxdrain(struct gem_softc *);
void gem_fill_rx_ring(struct gem_softc *);
int gem_add_rxbuf(struct gem_softc *, int idx);
-void gem_setladrf(struct gem_softc *);
+void gem_iff(struct gem_softc *);
/* MII methods & callbacks */
int gem_mii_readreg(struct device *, int, int);
@@ -735,7 +735,7 @@ gem_init(struct ifnet *ifp)
bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME, v);
/* step 5. RX MAC registers & counters */
- gem_setladrf(sc);
+ gem_iff(sc);
/* step 6 & 7. Program Descriptor Ring Base Addresses */
bus_space_write_4(t, h, GEM_TX_RING_PTR_HI,
@@ -809,7 +809,7 @@ gem_init(struct ifnet *ifp)
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- ifp->if_timer = 0;
+
splx(s);
return (0);
@@ -1477,7 +1477,7 @@ gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if (ifp->if_flags & IFF_RUNNING)
- gem_setladrf(sc);
+ error = ENETRESET;
else
gem_init(ifp);
} else {
@@ -1500,7 +1500,7 @@ gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
if (error == ENETRESET) {
if (ifp->if_flags & IFF_RUNNING)
- gem_setladrf(sc);
+ gem_iff(sc);
error = 0;
}
@@ -1518,93 +1518,68 @@ gem_shutdown(void *arg)
gem_stop(ifp);
}
-/*
- * Set up the logical address filter.
- */
void
-gem_setladrf(struct gem_softc *sc)
+gem_iff(struct gem_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_bustag;
bus_space_handle_t h = sc->sc_h1;
- 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, GEM_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 &= ~(GEM_MAC_RX_PROMISCUOUS|GEM_MAC_RX_HASH_FILTER|
+ rxcfg = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG);
+ rxcfg &= ~(GEM_MAC_RX_HASH_FILTER | GEM_MAC_RX_PROMISCUOUS |
GEM_MAC_RX_PROMISC_GRP);
+ ifp->if_flags &= ~IFF_ALLMULTI;
- if ((ifp->if_flags & IFF_PROMISC) != 0) {
- /* Turn on promiscuous mode */
- v |= GEM_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 |= GEM_MAC_RX_PROMISCUOUS;
+ else
+ rxcfg |= GEM_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).
+ */
- 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 |= GEM_MAC_RX_PROMISC_GRP;
- goto chipit;
- }
+ rxcfg |= GEM_MAC_RX_HASH_FILTER;
- crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
+ /* Clear hash table */
+ for (i = 0; i < 16; i++)
+ hash[i] = 0;
- /* Just want the 8 most significant bits. */
- crc >>= 24;
+ ETHER_FIRST_MULTI(step, ac, enm);
+ while (enm != NULL) {
+ crc = ether_crc32_le(enm->enm_addrlo,
+ ETHER_ADDR_LEN);
- /* Set the corresponding bit in the filter. */
- hash[crc >> 4] |= 1 << (15 - (crc & 15));
+ /* Just want the 8 most significant bits. */
+ crc >>= 24;
- ETHER_NEXT_MULTI(step, enm);
- }
+ /* Set the corresponding bit in the filter. */
+ hash[crc >> 4] |= 1 << (15 - (crc & 15));
- v |= GEM_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,
- GEM_MAC_HASH0 + i * (GEM_MAC_HASH1-GEM_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,
+ GEM_MAC_HASH0 + i * (GEM_MAC_HASH1 - GEM_MAC_HASH0),
+ hash[i]);
+ }
}
-chipit:
- bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, v);
+ bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, rxcfg);
}
/*