<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">diff -urN v2.4.9-ac15/drivers/net/ns83820.c ns-v2.4.9-ac15/drivers/net/ns83820.c
--- v2.4.9-ac15/drivers/net/ns83820.c	Mon Sep 24 21:16:20 2001
+++ ns-v2.4.9-ac15/drivers/net/ns83820.c	Tue Sep 25 03:31:23 2001
@@ -1,7 +1,7 @@
-#define VERSION "0.11"
+#define VERSION "0.12pre"
 /* ns83820.c by Benjamin LaHaise &lt;bcrl@redhat.com&gt;
  *
- * $Revision: 1.34.2.2 $
+ * $Revision: 1.34.2.6 $
  *
  * Copyright 2001 Benjamin LaHaise.
  * Copyright 2001 Red Hat.
@@ -41,7 +41,9 @@
  *	20010827	0.10 - fix ia64 unaligned access.
  *	20010906	0.11 - accept all packets with checksum errors as
  *			       otherwise fragments get lost
-			     - fix &gt;&gt; 32 bugs
+ *			     - fix &gt;&gt; 32 bugs
+ *			0.12 - add statistics counters
+ *			     not yet- add multicast support
  *
  * Driver Overview
  * ===============
@@ -61,7 +63,9 @@
  *	Cameo		SOHO-GA2000T	SOHO-GA2500T
  *	D-Link		DGE-500T
  *	PureData	PDP8023Z-TG
- *	SMC		SMC9462TX
+ *	SMC		SMC9452TX	SMC9462TX
+ *
+ * Special thanks to SMC for providing hardware to test this driver on.
  *
  * Reports of success or failure would be greatly appreciated.
  */
@@ -80,16 +84,15 @@
 #include &lt;linux/ip.h&gt;	/* for iph */
 #include &lt;linux/in.h&gt;	/* for IPPROTO_... */
 #include &lt;linux/eeprom.h&gt;
+#include &lt;linux/compiler.h&gt;
 //#include &lt;linux/skbrefill.h&gt;
 
+#include &lt;asm/io.h&gt;
+
 /* Dprintk is used for more interesting debug events */
 #undef Dprintk
 #define	Dprintk			dprintk
 
-#if !defined(GCC_VERSION) || (GCC_VERSION &lt; 2096)
-#define __builtin_expect(x,y)	(x)
-#endif
-
 #ifdef CONFIG_HIGHMEM64G
 #define USE_64BIT_ADDR
 #elif defined(__ia64__)
@@ -367,6 +370,7 @@
 
 struct ns83820 {
 	struct net_device	net_dev;
+	struct net_device_stats	stats;
 	u8			*base;
 
 	struct pci_dev		*pci_dev;
@@ -733,39 +737,22 @@
 			kfree_skb(skb);
 			skb = tmp;
 #endif
+			if (cmdsts &amp; CMDSTS_DEST_MULTI)
+				dev-&gt;stats.multicast ++;
+			dev-&gt;stats.rx_packets ++;
+			dev-&gt;stats.rx_bytes += len;
 			if ((extsts &amp; 0x002a0000) &amp;&amp; !(extsts &amp; 0x00540000)) {
 				skb-&gt;ip_summed = CHECKSUM_UNNECESSARY;
 			} else {
 				skb-&gt;ip_summed = CHECKSUM_NONE;
 			}
 			skb-&gt;protocol = eth_type_trans(skb, &amp;dev-&gt;net_dev);
-			switch (netif_rx(skb)) {
-			case NET_RX_SUCCESS:
-				dev-&gt;ihr = 3;
-				break;
-			case NET_RX_CN_LOW:
-				dev-&gt;ihr = 3;
-				break;
-			case NET_RX_CN_MOD:
-				dev-&gt;ihr = dev-&gt;ihr + 1;
-				break;
-			case NET_RX_CN_HIGH:
-				dev-&gt;ihr += dev-&gt;ihr/2 + 1;
-				break;
-			case NET_RX_DROP:
-				dev-&gt;ihr = 255;
-				break;
-			}
-			if (dev-&gt;ihr &gt; 255)
-				dev-&gt;ihr = 255;
+			if (NET_RX_DROP == netif_rx(skb))
+				dev-&gt;stats.rx_dropped ++;
 #ifndef __i386__
 		done:;
 #endif
 		} else {
-			static int err;
-			if (err++ &lt; 20) {
-				Dprintk("error packet: cmdsts: %08x extsts: %08x\n", cmdsts, extsts);
-			}
 			kfree_skb(skb);
 		}
 
@@ -808,6 +795,13 @@
 	       !(CMDSTS_OWN &amp; (cmdsts = desc[CMDSTS])) ) {
 		struct sk_buff *skb;
 
+		if (cmdsts &amp; CMDSTS_ERR)
+			dev-&gt;stats.tx_errors ++;
+		if (cmdsts &amp; CMDSTS_OK)
+			dev-&gt;stats.tx_packets ++;
+		if (cmdsts &amp; CMDSTS_OK)
+			dev-&gt;stats.tx_bytes += cmdsts &amp; 0xffff;
+
 		dprintk("tx_done_idx=%d free_idx=%d cmdsts=%08x\n",
 			tx_done_idx, dev-&gt;tx_free_idx, desc[CMDSTS]);
 		skb = dev-&gt;tx_skbs[tx_done_idx];
@@ -986,6 +980,35 @@
 	return 0;
 }
 
+static void ns83820_update_stats(struct ns83820 *dev)
+{
+	u8 *base = dev-&gt;base;
+
+	dev-&gt;stats.rx_errors		+= readl(base + 0x60) &amp; 0xffff;
+	dev-&gt;stats.rx_crc_errors	+= readl(base + 0x64) &amp; 0xffff;
+	dev-&gt;stats.rx_missed_errors	+= readl(base + 0x68) &amp; 0xffff;
+	dev-&gt;stats.rx_frame_errors	+= readl(base + 0x6c) &amp; 0xffff;
+	/*dev-&gt;stats.rx_symbol_errors +=*/ readl(base + 0x70);
+	dev-&gt;stats.rx_length_errors	+= readl(base + 0x74) &amp; 0xffff;
+	dev-&gt;stats.rx_length_errors	+= readl(base + 0x78) &amp; 0xffff;
+	/*dev-&gt;stats.rx_badopcode_errors += */ readl(base + 0x7c);
+	/*dev-&gt;stats.rx_pause_count += */  readl(base + 0x80);
+	/*dev-&gt;stats.tx_pause_count += */  readl(base + 0x84);
+	dev-&gt;stats.tx_carrier_errors	+= readl(base + 0x88) &amp; 0xff;
+}
+
+static struct net_device_stats *ns83820_get_stats(struct net_device *_dev)
+{
+	struct ns83820 *dev = (void *)_dev;
+
+	/* somewhat overkill */
+	spin_lock_irq(&amp;dev-&gt;misc_lock);
+	ns83820_update_stats(dev);
+	spin_unlock_irq(&amp;dev-&gt;misc_lock);
+
+	return &amp;dev-&gt;stats;
+}
+
 static void ns83820_irq(int foo, void *data, struct pt_regs *regs)
 {
 	struct ns83820 *dev = data;
@@ -1061,6 +1084,12 @@
 	if ((ISR_TXDESC | ISR_TXIDLE) &amp; isr)
 		do_tx_done(dev);
 
+	if (ISR_MIB &amp; isr) {
+		spin_lock(&amp;dev-&gt;misc_lock);
+		ns83820_update_stats(dev);
+		spin_unlock(&amp;dev-&gt;misc_lock);
+	}
+
 	if (ISR_PHY &amp; isr)
 		phy_intr(dev);
 	}
@@ -1179,6 +1208,28 @@
 	return 0;
 }
 
+static void ns83820_set_multicast(struct net_device *_dev)
+{
+	struct ns83820 *dev = (void *)_dev;
+	u8 *rfcr = dev-&gt;base + RFCR;
+	u32 and_mask = 0xffffffff;
+	u32 or_mask = 0;
+
+	if (dev-&gt;net_dev.flags &amp; IFF_PROMISC)
+		or_mask |= RFCR_AAU | RFCR_AAM;
+	else
+		and_mask &amp;= ~(RFCR_AAU | RFCR_AAM);
+
+	if (dev-&gt;net_dev.flags &amp; IFF_ALLMULTI)
+		or_mask |= RFCR_AAM;
+	else
+		and_mask &amp;= ~RFCR_AAM;
+
+	spin_lock_irq(&amp;dev-&gt;misc_lock);
+	writel((readl(rfcr) &amp; and_mask) | or_mask, rfcr);
+	spin_unlock_irq(&amp;dev-&gt;misc_lock);
+}
+
 static int ns83820_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
 	struct ns83820 *dev;
@@ -1242,6 +1293,9 @@
 	dev-&gt;net_dev.stop = ns83820_stop;
 	dev-&gt;net_dev.hard_start_xmit = ns83820_hard_start_xmit;
 	dev-&gt;net_dev.change_mtu = ns83820_change_mtu;
+	dev-&gt;net_dev.get_stats = ns83820_get_stats;
+	dev-&gt;net_dev.change_mtu = ns83820_change_mtu;
+	dev-&gt;net_dev.set_multicast_list = ns83820_set_multicast;
 	//FIXME: dev-&gt;net_dev.tx_timeout = ns83820_tx_timeout;
 
 	lock_kernel();
diff -urN v2.4.9-ac15/include/linux/compiler.h ns-v2.4.9-ac15/include/linux/compiler.h
--- v2.4.9-ac15/include/linux/compiler.h	Wed Dec 31 19:00:00 1969
+++ ns-v2.4.9-ac15/include/linux/compiler.h	Tue Sep 25 03:31:09 2001
@@ -0,0 +1,16 @@
+#ifndef __LINUX_COMPILER_H
+#define __LINUX_COMPILER_H
+
+/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented
+   a mechanism by which the user can annotate likely branch directions and
+   expect the blocks to be reordered appropriately.  Define __builtin_expect
+   to nothing for earlier compilers.  */
+
+#if __GNUC__ == 2 &amp;&amp; __GNUC_MINOR__ &lt; 96
+#define __builtin_expect(x, expected_value) (x)
+#endif
+
+#define likely(x)	__builtin_expect((x),1)
+#define unlikely(x)	__builtin_expect((x),0)
+
+#endif /* __LINUX_COMPILER_H */
</pre></body></html>