From 5af5c81544633cc95c6bcc564c36d1bdd2ab9320 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 10 Jan 2015 16:25:33 +0000 Subject: [PATCH] Add support for promiscuous mode and multicase. --- sys/dev/pci/if_nep.c | 115 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 20 deletions(-) diff --git a/sys/dev/pci/if_nep.c b/sys/dev/pci/if_nep.c index 09b137e9384..f256a8df86f 100644 --- a/sys/dev/pci/if_nep.c +++ b/sys/dev/pci/if_nep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_nep.c,v 1.11 2015/01/10 14:55:29 kettenis Exp $ */ +/* $OpenBSD: if_nep.c,v 1.12 2015/01/10 16:25:33 kettenis Exp $ */ /* * Copyright (c) 2014, 2015 Mark Kettenis * @@ -156,6 +156,9 @@ extern void myetheraddr(u_char *); #define XMAC_CONFIG_LOOPBACK (1ULL << 25) #define XMAC_CONFIG_TX_OUTPUT_EN (1ULL << 24) #define XMAC_CONFIG_SEL_POR_CLK_SRC (1ULL << 23) +#define XMAC_CONFIG_HASH_FILTER_EN (1ULL << 15) +#define XMAC_CONFIG_PROMISCUOUS_GROUP (1ULL << 10) +#define XMAC_CONFIG_PROMISCUOUS (1ULL << 9) #define XMAC_CONFIG_RX_MAC_ENABLE (1ULL << 8) #define XMAC_CONFIG_ALWAYS_NO_CRC (1ULL << 3) #define XMAC_CONFIG_VAR_MIN_IPG_EN (1ULL << 2) @@ -489,6 +492,8 @@ void nep_init_tx_mac(struct nep_softc *); void nep_init_tx_xmac(struct nep_softc *); void nep_init_tx_bmac(struct nep_softc *); void nep_init_tx_channel(struct nep_softc *, int); +void nep_enable_rx_mac(struct nep_softc *); +void nep_disable_rx_mac(struct nep_softc *); void nep_stop_dma(struct nep_softc *); void nep_fill_rx_ring(struct nep_softc *); @@ -606,7 +611,7 @@ nep_attach(struct device *parent, struct device *self, void *aux) strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof(ifp->if_xname)); ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = nep_ioctl; ifp->if_start = nep_start; ifp->if_watchdog = nep_watchdog; @@ -1325,6 +1330,57 @@ nep_init_tx_channel(struct nep_softc *sc, int chan) nep_write(sc, TX_CS(chan), 0); } +void +nep_enable_rx_mac(struct nep_softc *sc) +{ + struct ifnet *ifp = &sc->sc_ac.ac_if; + uint64_t val; + + if (sc->sc_port < 2) { + val = nep_read(sc, XMAC_CONFIG(sc->sc_port)); + val &= ~XMAC_CONFIG_PROMISCUOUS; + val &= ~XMAC_CONFIG_PROMISCUOUS_GROUP; + val &= ~XMAC_CONFIG_HASH_FILTER_EN; + if (ifp->if_flags & IFF_PROMISC) + val |= XMAC_CONFIG_PROMISCUOUS; + if (ifp->if_flags & IFF_ALLMULTI) + val |= XMAC_CONFIG_PROMISCUOUS_GROUP; + else + val |= XMAC_CONFIG_HASH_FILTER_EN; + val |= XMAC_CONFIG_RX_MAC_ENABLE; + nep_write(sc, XMAC_CONFIG(sc->sc_port), val); + } else { + val = nep_read(sc, RXMAC_CONFIG(sc->sc_port)); + val &= ~RXMAC_CONFIG_PROMISCUOUS; + val &= ~RXMAC_CONFIG_PROMISCUOUS_GROUP; + val &= ~RXMAC_CONFIG_HASH_FILTER_EN; + if (ifp->if_flags & IFF_PROMISC) + val |= RXMAC_CONFIG_PROMISCUOUS; + if (ifp->if_flags & IFF_ALLMULTI) + val |= RXMAC_CONFIG_PROMISCUOUS_GROUP; + else + val |= RXMAC_CONFIG_HASH_FILTER_EN; + val |= RXMAC_CONFIG_RX_ENABLE; + nep_write(sc, RXMAC_CONFIG(sc->sc_port), val); + } +} + +void +nep_disable_rx_mac(struct nep_softc *sc) +{ + uint64_t val; + + if (sc->sc_port < 2) { + val = nep_read(sc, XMAC_CONFIG(sc->sc_port)); + val &= ~XMAC_CONFIG_RX_MAC_ENABLE; + nep_write(sc, XMAC_CONFIG(sc->sc_port), val); + } else { + val = nep_read(sc, RXMAC_CONFIG(sc->sc_port)); + val &= ~RXMAC_CONFIG_RX_ENABLE; + nep_write(sc, RXMAC_CONFIG(sc->sc_port), val); + } +} + void nep_stop_dma(struct nep_softc *sc) { @@ -1447,19 +1503,12 @@ nep_up(struct nep_softc *sc) nep_fill_rx_ring(sc); + nep_enable_rx_mac(sc); if (sc->sc_port < 2) { - val = nep_read(sc, XMAC_CONFIG(sc->sc_port)); - val |= XMAC_CONFIG_RX_MAC_ENABLE; - nep_write(sc, XMAC_CONFIG(sc->sc_port), val); - val = nep_read(sc, XMAC_CONFIG(sc->sc_port)); val |= XMAC_CONFIG_TX_ENABLE; nep_write(sc, XMAC_CONFIG(sc->sc_port), val); } else { - val = nep_read(sc, RXMAC_CONFIG(sc->sc_port)); - val |= RXMAC_CONFIG_RX_ENABLE; - nep_write(sc, RXMAC_CONFIG(sc->sc_port), val); - val = nep_read(sc, TXMAC_CONFIG(sc->sc_port)); val |= TXMAC_CONFIG_TX_ENABLE; nep_write(sc, TXMAC_CONFIG(sc->sc_port), val); @@ -1505,15 +1554,7 @@ nep_down(struct nep_softc *sc) ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); ifp->if_timer = 0; - if (sc->sc_port < 2) { - val = nep_read(sc, XMAC_CONFIG(sc->sc_port)); - val &= ~XMAC_CONFIG_RX_MAC_ENABLE; - nep_write(sc, XMAC_CONFIG(sc->sc_port), val); - } else { - val = nep_read(sc, RXMAC_CONFIG(sc->sc_port)); - val &= ~RXMAC_CONFIG_RX_ENABLE; - nep_write(sc, RXMAC_CONFIG(sc->sc_port), val); - } + nep_disable_rx_mac(sc); val = nep_read(sc, IPP_CFIG(sc->sc_port)); val &= ~IPP_CFIG_IPP_ENABLE; @@ -1556,7 +1597,41 @@ nep_down(struct nep_softc *sc) void nep_iff(struct nep_softc *sc) { - printf("%s\n", __func__); + struct arpcom *ac = &sc->sc_ac; + struct ifnet *ifp = &sc->sc_ac.ac_if; + struct ether_multi *enm; + struct ether_multistep step; + uint32_t crc, hash[16]; + int i; + + nep_disable_rx_mac(sc); + + ifp->if_flags &= ~IFF_ALLMULTI; + memset(hash, 0, sizeof(hash)); + + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { + ifp->if_flags |= IFF_ALLMULTI; + } else { + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + crc = ether_crc32_le(enm->enm_addrlo, + ETHER_ADDR_LEN); + + crc >>= 24; + hash[crc >> 4] |= 1 << (15 - (crc & 15)); + + ETHER_NEXT_MULTI(step, enm); + } + } + + for (i = 0; i < nitems(hash); i++) { + if (sc->sc_port < 2) + nep_write(sc, XMAC_HASH_TBL(sc->sc_port, i), hash[i]); + else + nep_write(sc, MAC_HASH_TBL(sc->sc_port, i), hash[i]); + } + + nep_enable_rx_mac(sc); } int -- 2.20.1