Module Name: src
Committed By: nisimura
Date: Sun Mar 29 23:16:52 UTC 2020
Modified Files:
src/sys/dev/ic: dm9000.c
Log Message:
reorganise rcv frame address filter code
To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/sys/dev/ic/dm9000.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ic/dm9000.c
diff -u src/sys/dev/ic/dm9000.c:1.22 src/sys/dev/ic/dm9000.c:1.23
--- src/sys/dev/ic/dm9000.c:1.22 Wed Jan 29 14:14:55 2020
+++ src/sys/dev/ic/dm9000.c Sun Mar 29 23:16:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: dm9000.c,v 1.22 2020/01/29 14:14:55 thorpej Exp $ */
+/* $NetBSD: dm9000.c,v 1.23 2020/03/29 23:16:52 nisimura Exp $ */
/*
* Copyright (c) 2009 Paul Fleischer
@@ -879,7 +879,7 @@ dme_reset(struct dme_softc *sc)
dme_write(sc, DM9000_IMR,
DM9000_IMR_PAR | DM9000_IMR_PRM | DM9000_IMR_PTM);
- /* Setup multicast address filter, and enable RX. */
+ /* Setup multicast address filter, or run promisc. mode. */
dme_set_addr_filter(sc);
/* Obtain media information from PHY */
@@ -893,33 +893,30 @@ dme_reset(struct dme_softc *sc)
void
dme_set_addr_filter(struct dme_softc *sc)
{
- struct ether_multi *enm;
- struct ether_multistep step;
- struct ethercom *ec;
- struct ifnet *ifp;
- uint16_t af[4];
- int i;
-
- ec = &sc->sc_ethercom;
- ifp = &ec->ec_if;
+ struct ethercom *ec = &sc->sc_ethercom;
+ struct ifnet *ifp = &ec->ec_if;
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ uint8_t mchash[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* 64bit mchash */
+ uint32_t h = 0;
+ uint8_t rcr;
+
+ rcr = dme_read(sc, DM9000_RCR);
+ rcr &= ~(DM9000_RCR_PRMSC | DM9000_RCR_ALL);
+ dme_write(sc, DM9000_RCR, rcr &~ DM9000_RCR_RXEN);
+ ETHER_LOCK(ec);
if (ifp->if_flags & IFF_PROMISC) {
- dme_write(sc, DM9000_RCR, DM9000_RCR_RXEN |
- DM9000_RCR_WTDIS |
- DM9000_RCR_PRMSC);
- ifp->if_flags |= IFF_ALLMULTI;
- return;
+ ec->ec_flags |= ETHER_F_ALLMULTI;
+ ETHER_UNLOCK(ec);
+ /* run promisc. mode */
+ rcr |= DM9000_RCR_PRMSC;
+ goto update;
}
-
- af[0] = af[1] = af[2] = af[3] = 0x0000;
- ifp->if_flags &= ~IFF_ALLMULTI;
-
- ETHER_LOCK(ec);
+ ec->ec_flags &= ~ETHER_F_ALLMULTI;
ETHER_FIRST_MULTI(step, ec, enm);
while (enm != NULL) {
- uint16_t hash;
- if (memcpy(enm->enm_addrlo, enm->enm_addrhi,
- sizeof(enm->enm_addrlo))) {
+ if (memcpy(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
@@ -928,25 +925,25 @@ dme_set_addr_filter(struct dme_softc *sc
* ranges is for IP multicast routing, for which the
* range is big enough to require all bits set.)
*/
- ifp->if_flags |= IFF_ALLMULTI;
- af[0] = af[1] = af[2] = af[3] = 0xffff;
+ ec->ec_flags |= ETHER_F_ALLMULTI;
+ ETHER_UNLOCK(ec);
+ memset(mchash, 0xff, sizeof(mchash)); /* necessary? */
+ /* accept all mulicast frame */
+ rcr |= DM9000_RCR_ALL;
break;
- } else {
- hash = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) & 0x3F;
- af[(uint16_t)(hash>>4)] |= (uint16_t)(1 << (hash % 16));
- ETHER_NEXT_MULTI(step, enm);
}
+ h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) & 0x3f;
+ /* 3(5:3) and 3(2:0) sampling to make uint8_t[8] */
+ mchash[h / 8] |= 1 << (h % 8);
+ ETHER_NEXT_MULTI(step, enm);
}
ETHER_UNLOCK(ec);
-
- /* Write the multicast address filter */
- for (i = 0; i < 4; i++) {
- dme_write(sc, DM9000_MAB0+i*2, af[i] & 0xFF);
- dme_write(sc, DM9000_MAB0+i*2+1, (af[i] >> 8) & 0xFF);
- }
-
- /* Setup RX controls */
- dme_write(sc, DM9000_RCR, DM9000_RCR_RXEN | DM9000_RCR_WTDIS);
+ /* DM9000 receive filter is always on */
+ mchash[7] |= 0x80; /* to catch bcast frame */
+ update:
+ dme_write_c(sc, DM9000_MAB0, mchash, sizeof(mchash));
+ dme_write(sc, DM9000_RCR, rcr | DM9000_RCR_RXEN | DM9000_RCR_WTDIS);
+ return;
}
int