summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_stge.c119
1 files changed, 46 insertions, 73 deletions
diff --git a/sys/dev/pci/if_stge.c b/sys/dev/pci/if_stge.c
index 76be8fae8c8..eaf3d013a02 100644
--- a/sys/dev/pci/if_stge.c
+++ b/sys/dev/pci/if_stge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_stge.c,v 1.45 2008/11/28 02:44:18 brad Exp $ */
+/* $OpenBSD: if_stge.c,v 1.46 2009/07/21 17:27:46 sthen Exp $ */
/* $NetBSD: if_stge.c,v 1.27 2005/05/16 21:35:32 bouyer Exp $ */
/*-
@@ -101,7 +101,7 @@ void stge_tick(void *);
void stge_stats_update(struct stge_softc *);
-void stge_set_filter(struct stge_softc *);
+void stge_iff(struct stge_softc *);
int stge_intr(void *);
void stge_txintr(struct stge_softc *);
@@ -720,19 +720,14 @@ stge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
- if (ifp->if_flags & IFF_RUNNING &&
- (ifp->if_flags ^ sc->stge_if_flags) &
- IFF_PROMISC) {
- stge_set_filter(sc);
- } else {
- if (!(ifp->if_flags & IFF_RUNNING))
- stge_init(ifp);
- }
+ if (ifp->if_flags & IFF_RUNNING)
+ error = ENETRESET;
+ else
+ stge_init(ifp);
} else {
if (ifp->if_flags & IFF_RUNNING)
stge_stop(ifp, 1);
}
- sc->stge_if_flags = ifp->if_flags;
break;
case SIOCSIFMEDIA:
@@ -746,7 +741,7 @@ stge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
if (error == ENETRESET) {
if (ifp->if_flags & IFF_RUNNING)
- stge_set_filter(sc);
+ stge_iff(sc);
error = 0;
}
@@ -1226,8 +1221,8 @@ stge_init(struct ifnet *ifp)
(1U << 13) | (1U << 14) | (1U << 15) | (1U << 19) | (1U << 20) |
(1U << 21));
- /* Set up the receive filter. */
- stge_set_filter(sc);
+ /* Program promiscuous mode and multicast filters. */
+ stge_iff(sc);
/*
* Give the transmit and receive ring to the chip.
@@ -1521,12 +1516,12 @@ stge_add_rxbuf(struct stge_softc *sc, int idx)
}
/*
- * stge_set_filter:
+ * stge_iff:
*
* Set up the receive filter.
*/
void
-stge_set_filter(struct stge_softc *sc)
+stge_iff(struct stge_softc *sc)
{
struct arpcom *ac = &sc->sc_arpcom;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
@@ -1535,75 +1530,53 @@ stge_set_filter(struct stge_softc *sc)
uint32_t crc;
uint32_t mchash[2];
- sc->sc_ReceiveMode = RM_ReceiveUnicast;
- if (ifp->if_flags & IFF_BROADCAST)
- sc->sc_ReceiveMode |= RM_ReceiveBroadcast;
+ memset(mchash, 0, sizeof(mchash));
+ ifp->if_flags &= ~IFF_ALLMULTI;
+
+ /*
+ * Always accept broadcast packets.
+ * Always accept frames destined to our station address.
+ */
+ sc->sc_ReceiveMode = RM_ReceiveBroadcast | RM_ReceiveUnicast;
/* XXX: ST1023 only works in promiscuous mode */
if (sc->sc_stge1023)
ifp->if_flags |= IFF_PROMISC;
- if (ifp->if_flags & IFF_PROMISC) {
- sc->sc_ReceiveMode |= RM_ReceiveAllFrames;
- goto allmulti;
- }
+ if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ if (ifp->if_flags & IFF_PROMISC)
+ sc->sc_ReceiveMode |= RM_ReceiveAllFrames;
+ else
+ sc->sc_ReceiveMode |= RM_ReceiveMulticast;
+ } else {
+ /*
+ * Set up the multicast address filter by passing all
+ * multicast addresses through a CRC generator, and then
+ * using the low-order 6 bits as an index into the 64 bit
+ * multicast hash table. The high order bits select the
+ * register, while the rest of the bits select the bit
+ * within the register.
+ */
+ sc->sc_ReceiveMode |= RM_ReceiveMulticastHash;
- /*
- * Set up the multicast address filter by passing all multicast
- * addresses through a CRC generator, and then using the low-order
- * 6 bits as an index into the 64 bit multicast hash table. The
- * high order bits select the register, while the rest of the bits
- * select the bit within the register.
- */
+ ETHER_FIRST_MULTI(step, ac, enm);
+ while (enm != NULL) {
+ crc = ether_crc32_be(enm->enm_addrlo,
+ ETHER_ADDR_LEN);
- memset(mchash, 0, sizeof(mchash));
+ /* Just want the 6 least significant bits. */
+ crc &= 0x3f;
- ETHER_FIRST_MULTI(step, ac, enm);
- if (enm == NULL)
- goto done;
+ /* Set the corresponding bit in the hash table. */
+ mchash[crc >> 5] |= 1 << (crc & 0x1f);
- while (enm != NULL) {
- if (memcmp(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.)
- */
- goto allmulti;
+ ETHER_NEXT_MULTI(step, enm);
}
-
- crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);
-
- /* Just want the 6 least significant bits. */
- crc &= 0x3f;
-
- /* Set the corresponding bit in the hash table. */
- mchash[crc >> 5] |= 1 << (crc & 0x1f);
-
- ETHER_NEXT_MULTI(step, enm);
- }
-
- sc->sc_ReceiveMode |= RM_ReceiveMulticastHash;
-
- ifp->if_flags &= ~IFF_ALLMULTI;
- goto done;
-
- allmulti:
- ifp->if_flags |= IFF_ALLMULTI;
- sc->sc_ReceiveMode |= RM_ReceiveMulticast;
-
- done:
- if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
- /*
- * Program the multicast hash table.
- */
- CSR_WRITE_4(sc, STGE_HashTable0, mchash[0]);
- CSR_WRITE_4(sc, STGE_HashTable1, mchash[1]);
}
+ CSR_WRITE_4(sc, STGE_HashTable0, mchash[0]);
+ CSR_WRITE_4(sc, STGE_HashTable1, mchash[1]);
CSR_WRITE_2(sc, STGE_ReceiveMode, sc->sc_ReceiveMode);
}