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

Reply via email to