Index: oldkernel/linux/drivers/net/eepro100.c
diff -u linux/drivers/net/eepro100.c:1.3 linux/drivers/net/eepro100.c:1.4
--- linux/drivers/net/eepro100.c:1.3	Thu Jun  1 16:52:50 2000
+++ linux/drivers/net/eepro100.c	Thu Jun  1 17:15:13 2000
@@ -1,6 +1,6 @@
 /* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */
 /*
-   NOTICE: this version tested with kernels 1.3.72 and later only!
+   NOTICE: this version of the driver is supposed to work with 2.2 kernels.
 	Written 1996-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
@@ -21,15 +21,14 @@
 	There is a Majordomo mailing list based at
 		linux-eepro100@cesdis.gsfc.nasa.gov
 	
-	This driver also contains updates by Andrey Savochkin and others.
-	For this specific driver variant please use linux-kernel for 
-	bug reports.
-
+	The driver also contains updates by different kernel developers.
+	This driver clone is maintained by Andrey V. Savochkin <saw@saw.sw.com.sg>.
+	Please use this email address and linux-kernel mailing list for bug reports.
 */
 
 static const char *version =
 "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"
-"eepro100.c: $Revision: 1.18 $ 1999/12/29 Modified by Andrey V. Savochkin <saw@msu.ru>\n";
+"eepro100.c: $Revision: 1.1.2.1 $ 2000/03/02 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
 
 /* A few user-configurable values that apply to all boards.
    First set is undocumented and spelled per Intel recommendations. */
@@ -360,19 +359,16 @@
 	CmdIntr = 0x20000000,		/* Interrupt after completion. */
 	CmdTxFlex = 0x00080000,		/* Use "Flexible mode" for CmdTx command. */
 };
-/* Clear CmdSuspend (1<<30) atomically.
-   Otherwise the command status in the lower 16 bits may be reset after
-   an asynchronous change.  Previous driver version used separate 16 bit fields
-   for commands and statuses.  --SAW
+/* Clear CmdSuspend (1<<30) avoiding interference with the card access to the
+   status bits.  Previous driver versions used separate 16 bit fields for
+   commands and statuses.  --SAW
  */
-#ifdef __i386__
-#define speedo_fool_gcc(x) (*(volatile struct { int a[100]; } *)x)
-#define speedo_clear_mask(mask, addr) \
-__asm__ __volatile__("lock; andl %0,%1" \
-: : "r" (~(mask)),"m" (speedo_fool_gcc(addr)) : "memory")
-#define clear_suspend(cmd)  speedo_clear_mask(CmdSuspend, &(cmd)->cmd_status)
+#if defined(__LITTLE_ENDIAN)
+#define clear_suspend(cmd)  ((__u16 *)&(cmd)->cmd_status)[1] &= ~0x4000
+#elif defined(__BIG_ENDIAN)
+#define clear_suspend(cmd)  ((__u16 *)&(cmd)->cmd_status)[0] &= ~0x4000
 #else
-#define clear_suspend(cmd)	(cmd)->cmd_status &= cpu_to_le32(~CmdSuspend)
+#error Unsupported byteorder
 #endif
 
 enum SCBCmdBits {
@@ -566,7 +562,7 @@
 
 	for (; pci_index < 8; pci_index++) {
 		unsigned char pci_bus, pci_device_fn, pci_latency;
-		u32 pciaddr;
+		unsigned long pciaddr;
 		long ioaddr;
 		int irq;
 
@@ -592,7 +588,7 @@
 			if (check_region(ioaddr, 32))
 				continue;
 		} else if ((ioaddr = (long)ioremap(pciaddr & ~0xfUL, 0x1000)) == 0) {
-			printk(KERN_INFO "Failed to map PCI address %#x.\n",
+			printk(KERN_INFO "Failed to map PCI address %#lx.\n",
 				   pciaddr);
 			continue;
 		}
@@ -1018,7 +1014,7 @@
 		sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4);
 
 	if (speedo_debug > 2) {
-		printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
+		printk(KERN_DEBUG "%s: Done speedo_open(), status %4.4x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
 	}
 
@@ -1193,6 +1189,7 @@
 	int i;
 
 	sp->cur_rx = 0;
+	sp->rx_ring_state = 0;
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb;
@@ -1491,13 +1488,13 @@
 	do {
 		status = inw(ioaddr + SCBStatus);
 		/* Acknowledge all of the current interrupt sources ASAP. */
-		outw(status & 0xfc00, ioaddr + SCBStatus);
+		outw(status & 0xfd00, ioaddr + SCBStatus);
 
 		if (speedo_debug > 4)
 			printk(KERN_DEBUG "%s: interrupt  status=%#4.4x.\n",
 				   dev->name, status);
 
-		if ((status & 0xfc00) == 0)
+		if ((status & 0xfd00) == 0)
 			break;
 
 		/* Always check if all rx buffers are allocated.  --SAW */
@@ -1512,8 +1509,9 @@
 			spin_lock(&sp->lock);
 			if ((status & 0x003c) == 0x0028) {		/* No more Rx buffers. */
 				struct RxFD *rxf;
-				printk(KERN_WARNING "%s: card reports no RX buffers.\n",
-						dev->name);
+				printk(KERN_WARNING "%s: card reports no RX buffers, status=%#4.4x, flow control=%s.\n",
+						dev->name, status,
+						sp->flow_ctrl ? "on" : "off");
 				rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
 				if (rxf == NULL) {
 					if (speedo_debug > 2)
@@ -1531,8 +1529,9 @@
 					outb(RxResumeNoResources, ioaddr + SCBCmd);
 			} else if ((status & 0x003c) == 0x0008) { /* No resources. */
 				struct RxFD *rxf;
-				printk(KERN_WARNING "%s: card reports no resources.\n",
-						dev->name);
+				printk(KERN_WARNING "%s: card reports no resources, status=%#4.4x, flow control=%s.\n",
+						dev->name, status,
+						sp->flow_ctrl ? "on" : "off");
 				rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
 				if (rxf == NULL) {
 					if (speedo_debug > 2)
@@ -1590,7 +1589,7 @@
 			printk(KERN_ERR "%s: Too much work at interrupt, status=0x%4.4x.\n",
 				   dev->name, status);
 			/* Clear all interrupt sources. */
-			outl(0xfc00, ioaddr + SCBStatus);
+			outw(0xfd00, ioaddr + SCBStatus);
 			break;
 		}
 	} while (1);
@@ -1991,7 +1990,16 @@
 		config_cmd_data[4] = rxdmacount;
 		config_cmd_data[5] = txdmacount + 0x80;
 		config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0;
-		config_cmd_data[19] = sp->flow_ctrl ? 0xBD : 0x80;
+		if (sp->flow_ctrl) {
+			config_cmd_data[16] = 0x1f;
+			config_cmd_data[17] = 0x01;
+			config_cmd_data[19] = 0xb8;
+		}
+		else {
+			config_cmd_data[16] = 0;
+			config_cmd_data[17] = 0x40;
+			config_cmd_data[19] = 0x84;
+		}
 		config_cmd_data[19] |= sp->full_duplex ? 0x40 : 0;
 		config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05;
 		if (sp->phy[0] & 0x8000) {			/* Use the AUI port instead. */
@@ -2162,9 +2170,8 @@
 	while (root_speedo_dev) {
 		struct speedo_private *sp = (void *)root_speedo_dev->priv;
 		unregister_netdev(root_speedo_dev);
-#ifdef USE_IO
 		release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE);
-#else
+#ifndef USE_IO
 		iounmap((char *)root_speedo_dev->base_addr);
 #endif
 #if defined(HAS_PCI_NETIF)
