diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/gem.c | 119 |
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); } /* |