Revised patch for sk driver

Jung-uk Kim jkim at niksun.com
Tue Jan 13 08:05:38 PST 2004


On Tuesday 13 January 2004 11:02 am, Jung-uk Kim wrote:
> I updated my patch for the lastest src/sys/pci/if_sk.c (Rev. 1.73),
> which was originally posted here:
>
> http://docs.freebsd.org/cgi/mid.cgi?20031215231022.GA15082
>
> This also includes Keith Mitchell's patch (with some clean-ups):
>
> http://docs.freebsd.org/cgi/mid.cgi?20031217145924.GA12258
>
> This patch supposedly fixes problems with promiscuous mode,
> multicast, and rtsol.

My bad.  Attachment was missing.  Sorry.

Jung-uk Kim
-------------- next part --------------
--- src/sys/pci/if_sk.c.orig	Sun Dec 14 01:48:11 2003
+++ src/sys/pci/if_sk.c	Tue Jan 13 00:40:40 2004
@@ -224,9 +224,11 @@
 						int);
 static void sk_marv_miibus_statchg	(struct sk_if_softc *);
 
-static uint32_t sk_mchash	(const uint8_t *);
+static uint32_t sk_xmchash	(const uint8_t *);
+static uint32_t sk_gmchash	(const uint8_t *);
 static void sk_setfilt		(struct sk_if_softc *, caddr_t, int);
 static void sk_setmulti		(struct sk_if_softc *);
+static void sk_setpromisc	(struct sk_if_softc *);
 
 #ifdef SK_USEIOSPACE
 #define SK_RES		SYS_RES_IOPORT
@@ -709,11 +711,12 @@
 	return;
 }
 
-#define SK_POLY		0xEDB88320
-#define SK_BITS		6
+#define XMAC_POLY		0xEDB88320
+#define GMAC_POLY		0x04C11DB7L
+#define HASH_BITS		6
 
 static u_int32_t
-sk_mchash(addr)
+sk_xmchash(addr)
 	const uint8_t *addr;
 {
 	uint32_t crc;
@@ -725,10 +728,48 @@
 
 	for (idx = 0; idx < 6; idx++) {
 		for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1)
-			crc = (crc >> 1) ^ (((crc ^ data) & 1) ? SK_POLY : 0);
+			crc = (crc >> 1) ^ (((crc ^ data) & 1) ? XMAC_POLY : 0);
 	}
 
-	return (~crc & ((1 << SK_BITS) - 1));
+	return (~crc & ((1 << HASH_BITS) - 1));
+}
+
+static u_int32_t
+sk_gmchash(addr)
+	const uint8_t *addr;
+{
+	u_int32_t crc;
+	uint idx, bit;
+	uint8_t tmpData, data;
+
+	/* Compute CRC for the address value. */
+	crc = 0xFFFFFFFF; /* initial value */
+
+	for (idx = 0; idx < 6; idx++) {
+		data = *addr++;
+
+		/* Change bit order in byte. */
+		tmpData = data;
+		for (bit = 0; bit < 8; bit++) {
+			if (tmpData & 1) {
+				data |=  1 << (7 - bit);
+			} else {
+				data &= ~(1 << (7 - bit));
+			}
+			tmpData >>= 1;
+		}
+
+		crc ^= (data << 24);
+		for (bit = 0; bit < 8; bit++) {
+			if (crc & 0x80000000) {
+				crc = (crc << 1) ^ GMAC_POLY;
+			} else {
+				crc <<= 1;
+			}
+		}
+	}
+
+	return (crc & ((1 << HASH_BITS) - 1));
 }
 
 static void
@@ -755,7 +796,7 @@
 	struct sk_softc		*sc = sc_if->sk_softc;
 	struct ifnet		*ifp = &sc_if->arpcom.ac_if;
 	u_int32_t		hashes[2] = { 0, 0 };
-	int			h, i;
+	int			h = 0, i;
 	struct ifmultiaddr	*ifma;
 	u_int8_t		dummy[] = { 0, 0, 0, 0, 0 ,0 };
 
@@ -798,8 +839,16 @@
 				continue;
 			}
 
-			h = sk_mchash(
-				LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+			switch(sc->sk_type) {
+			case SK_GENESIS:
+				h = sk_xmchash(
+					LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+				break;
+			case SK_YUKON:
+				h = sk_gmchash(
+					LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+				break;
+			}
 			if (h < 32)
 				hashes[0] |= (1 << h);
 			else
@@ -825,6 +874,35 @@
 	return;
 }
 
+static void
+sk_setpromisc(sc_if)
+	struct sk_if_softc	*sc_if;
+{
+	struct sk_softc		*sc = sc_if->sk_softc;
+	struct ifnet		*ifp = &sc_if->arpcom.ac_if;
+
+	switch(sc->sk_type) {
+	case SK_GENESIS:
+		if (ifp->if_flags & IFF_PROMISC) {
+			SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC);
+		} else {
+			SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC);
+		}
+		break;
+	case SK_YUKON:
+		if (ifp->if_flags & IFF_PROMISC) {
+			SK_YU_CLRBIT_2(sc_if, YUKON_RCR,
+			    YU_RCR_UFLEN | YU_RCR_MUFLEN);
+		} else {
+			SK_YU_SETBIT_2(sc_if, YUKON_RCR,
+			    YU_RCR_UFLEN | YU_RCR_MUFLEN);
+		}
+		break;
+	}
+
+	return;
+}
+
 static int
 sk_init_rx_ring(sc_if)
 	struct sk_if_softc	*sc_if;
@@ -1107,7 +1185,6 @@
 	caddr_t			data;
 {
 	struct sk_if_softc	*sc_if = ifp->if_softc;
-	struct sk_softc		*sc = sc_if->sk_softc;
 	struct ifreq		*ifr = (struct ifreq *) data;
 	int			error = 0;
 	struct mii_data		*mii;
@@ -1125,34 +1202,12 @@
 		break;
 	case SIOCSIFFLAGS:
 		if (ifp->if_flags & IFF_UP) {
-			if (ifp->if_flags & IFF_RUNNING &&
-			    ifp->if_flags & IFF_PROMISC &&
-			    !(sc_if->sk_if_flags & IFF_PROMISC)) {
-				switch(sc->sk_type) {
-				case SK_GENESIS:
-					SK_XM_SETBIT_4(sc_if, XM_MODE,
-					    XM_MODE_RX_PROMISC);
-					break;
-				case SK_YUKON:
-					SK_YU_CLRBIT_2(sc_if, YUKON_RCR,
-					    YU_RCR_UFLEN | YU_RCR_MUFLEN);
-					break;
-				}
-				sk_setmulti(sc_if);
-			} else if (ifp->if_flags & IFF_RUNNING &&
-			    !(ifp->if_flags & IFF_PROMISC) &&
-			    sc_if->sk_if_flags & IFF_PROMISC) {
-				switch(sc->sk_type) {
-				case SK_GENESIS:
-					SK_XM_CLRBIT_4(sc_if, XM_MODE,
-					    XM_MODE_RX_PROMISC);
-					break;
-				case SK_YUKON:
-					SK_YU_SETBIT_2(sc_if, YUKON_RCR,
-					    YU_RCR_UFLEN | YU_RCR_MUFLEN);
-					break;
+			if (ifp->if_flags & IFF_RUNNING) {
+				if ((ifp->if_flags ^ sc_if->sk_if_flags)
+				    & IFF_PROMISC) {
+					sk_setpromisc(sc_if);
+					sk_setmulti(sc_if);
 				}
-				sk_setmulti(sc_if);
 			} else
 				sk_init(sc_if);
 		} else {
@@ -2258,12 +2313,6 @@
 	    *(u_int16_t *)(&sc_if->arpcom.ac_enaddr[4]));
 	SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_STATION);
 
-	if (ifp->if_flags & IFF_PROMISC) {
-		SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC);
-	} else {
-		SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC);
-	}
-
 	if (ifp->if_flags & IFF_BROADCAST) {
 		SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_NOBROAD);
 	} else {
@@ -2305,6 +2354,9 @@
 	 */
 	SK_XM_WRITE_2(sc_if, XM_TX_REQTHRESH, SK_XM_TX_FIFOTHRESH);
 
+	/* Set promiscuous mode */
+	sk_setpromisc(sc_if);
+
 	/* Set multicast filter */
 	sk_setmulti(sc_if);
 
@@ -2400,8 +2452,7 @@
 	SK_YU_WRITE_2(sc_if, YUKON_PAR, reg);
 
 	/* receive control reg */
-	SK_YU_WRITE_2(sc_if, YUKON_RCR, YU_RCR_UFLEN | YU_RCR_MUFLEN |
-		      YU_RCR_CRCR);
+	SK_YU_WRITE_2(sc_if, YUKON_RCR, YU_RCR_CRCR);
 
 	/* transmit parameter register */
 	SK_YU_WRITE_2(sc_if, YUKON_TPR, YU_TPR_JAM_LEN(0x3) |
@@ -2425,11 +2476,11 @@
 		SK_YU_WRITE_2(sc_if, YUKON_SAL2 + i * 4, reg);
 	}
 
-	/* clear all Multicast filter hash registers */
-	SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0);
-	SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0);
-	SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0);
-	SK_YU_WRITE_2(sc_if, YUKON_MCAH4, 0);
+	/* Set promiscuous mode */
+	sk_setpromisc(sc_if);
+
+	/* Set multicast filter */
+	sk_setmulti(sc_if);
 
 	/* enable interrupt mask for counter overflows */
 	SK_YU_WRITE_2(sc_if, YUKON_TIMR, 0);


More information about the freebsd-net mailing list