diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2006-11-09 18:29:20 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2006-11-09 18:29:20 +0000 |
commit | 9d292a8aee51e08ded968df577abd843ad164434 (patch) | |
tree | 5ae5badc478c0fd153432cad4e372213d6dd09eb /sys | |
parent | 00dfce02484d8649dc924620e5e9736632ca0de0 (diff) |
add multicast filter support instead of using ALLMULTI all the time
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_vic.c | 69 |
1 files changed, 51 insertions, 18 deletions
diff --git a/sys/dev/pci/if_vic.c b/sys/dev/pci/if_vic.c index 925110d533e..62c5fea10fb 100644 --- a/sys/dev/pci/if_vic.c +++ b/sys/dev/pci/if_vic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vic.c,v 1.32 2006/11/06 07:31:54 reyk Exp $ */ +/* $OpenBSD: if_vic.c,v 1.33 2006/11/09 18:29:19 reyk Exp $ */ /* * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org> @@ -322,7 +322,7 @@ void vic_free_dmamem(struct vic_softc *); void vic_link_state(struct vic_softc *); void vic_rx_proc(struct vic_softc *); void vic_tx_proc(struct vic_softc *); -void vic_iff(struct vic_softc *, u_int); +void vic_iff(struct vic_softc *); void vic_getlladdr(struct vic_softc *); void vic_setlladdr(struct vic_softc *); int vic_media_change(struct ifnet *); @@ -840,19 +840,51 @@ vic_tx_proc(struct vic_softc *sc) } void -vic_iff(struct vic_softc *sc, u_int flags) +vic_iff(struct vic_softc *sc) { - /* XXX ALLMULTI */ + struct arpcom *ac = &sc->sc_ac; + struct ifnet *ifp = &sc->sc_ac.ac_if; + struct ether_multi *enm; + struct ether_multistep step; + u_int32_t crc; + u_int flags = 0; + + bzero(&sc->sc_data->vd_mcastfil, sizeof(sc->sc_data->vd_mcastfil)); + ifp->if_flags &= ~IFF_ALLMULTI; + + if ((ifp->if_flags & IFF_RUNNING) == 0) + goto domulti; + if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) + goto allmulti; + + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) + goto allmulti; + + crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); + crc >>= 26; + sc->sc_data->vd_mcastfil[crc >> 4] |= htole16(1 << (crc & 0xf)); + + ETHER_NEXT_MULTI(step, enm); + } + + goto domulti; + + allmulti: + ifp->if_flags |= IFF_ALLMULTI; memset(&sc->sc_data->vd_mcastfil, 0xff, sizeof(sc->sc_data->vd_mcastfil)); - sc->sc_data->vd_iff = flags; - -/* - bus_dmamap_sync(sc->sc_dmat, sc->sc_map, 0, - sizeof(struct vic_data), BUS_DMASYNC_POSTWRITE); -*/ + domulti: vic_write(sc, VIC_CMD, VIC_CMD_MCASTFIL); + + if (ifp->if_flags & IFF_RUNNING) { + flags = (ifp->if_flags & IFF_PROMISC) ? + VIC_CMD_IFF_PROMISC : + (VIC_CMD_IFF_BROADCAST | VIC_CMD_IFF_MULTICAST); + } + sc->sc_data->vd_iff = flags; vic_write(sc, VIC_CMD, VIC_CMD_IFF); } @@ -1101,7 +1133,9 @@ vic_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) /* FALLTHROUGH */ case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - if ((ifp->if_flags & IFF_RUNNING) == 0) + if (ifp->if_flags & IFF_RUNNING) + vic_iff(sc); + else vic_init(ifp); } else { if (ifp->if_flags & IFF_RUNNING) @@ -1123,8 +1157,11 @@ vic_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) ether_addmulti(ifr, &sc->sc_ac) : ether_delmulti(ifr, &sc->sc_ac); - if (error == ENETRESET) + if (error == ENETRESET) { + if (ifp->if_flags & IFF_RUNNING) + vic_iff(sc); error = 0; + } break; case SIOCGIFMEDIA: @@ -1176,14 +1213,10 @@ vic_init(struct ifnet *ifp) vic_write(sc, VIC_DATA_ADDR, VIC_DMA_DVA(sc)); vic_write(sc, VIC_DATA_LENGTH, sc->sc_dma_size); - if (ifp->if_flags & IFF_PROMISC) - vic_iff(sc, VIC_CMD_IFF_PROMISC); - else - vic_iff(sc, VIC_CMD_IFF_BROADCAST | VIC_CMD_IFF_MULTICAST); - ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; + vic_iff(sc); vic_write(sc, VIC_CMD, VIC_CMD_INTR_ENABLE); splx(s); @@ -1217,7 +1250,7 @@ vic_stop(struct ifnet *ifp) vic_write(sc, VIC_CMD, VIC_CMD_INTR_DISABLE); - vic_iff(sc, 0); + vic_iff(sc); vic_write(sc, VIC_DATA_ADDR, 0); vic_uninit_data(sc); |