patch-2.2.0-pre6 linux/drivers/net/eepro.c

Next file: linux/drivers/net/eexpress.c
Previous file: linux/drivers/net/dgrs_i82596.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
@@ -23,10 +23,15 @@
 	This is a compatibility hardware problem.
 
 	Versions:
-	0.11b   Pascal Dupuis : works as a module under 2.1.xx
-	        debug messages are flagged as KERN_DEBUG to avoid console 
-		flooding 
-		added locking at critical parts
+	0.11d	added __initdata, __initfunc stuff; call spin_lock_init
+	        in eepro_probe1. Replaced "eepro" by dev->name. Augmented 
+		the code protected by spin_lock in interrupt routine 
+		(PdP, 12/12/1998)
+	0.11c   minor cleanup (PdP, RMC, 09/12/1998)  
+	0.11b   Pascal Dupuis (dupuis@lei.ucl.ac.be): works as a module 
+	        under 2.1.xx. Debug messages are flagged as KERN_DEBUG to 
+		avoid console flooding. Added locking at critical parts. Now 
+		the dawn thing is SMP safe.
 	0.11a   Attempt to get 2.1.xx support up (RMC)
 	0.11	Brian Candler added support for multiple cards. Tested as
 		a module, no idea if it works when compiled into kernel.
@@ -87,7 +92,7 @@
 */
 
 static const char *version =
-	"eepro.c: v0.11b 08/12/1998 dupuis@lei.ucl.ac.be\n";
+	"eepro.c: v0.11d 08/12/1998 dupuis@lei.ucl.ac.be\n";
 
 #include <linux/module.h>
 
@@ -127,9 +132,6 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-#include <asm/spinlock.h>
-#endif
 #include <linux/errno.h>
 
 #include <linux/netdevice.h>
@@ -147,6 +149,7 @@
 /* For linux 2.1.xx */
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 
+#include <asm/spinlock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 
@@ -154,6 +157,8 @@
 /* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
 #define SLOW_DOWN inb(0x80)
 /* udelay(2) */
+#define compat_init_func(X)  __initfunc(X)
+#define compat_init_data     __initdata
 
 #else 
 /* for 2.x */
@@ -161,13 +166,15 @@
 #define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb), (mode) )
 #define test_and_set_bit(a,b) set_bit((a),(b))
 #define SLOW_DOWN SLOW_DOWN_IO
+#define compat_init_func(X) X
+#define compat_init_data
 
 #endif
 
 
 /* First, a few definitions that the brave might change. */
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int eepro_portlist[] =
+static unsigned int eepro_portlist[] compat_init_data =
    { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
 /* note: 0x300 is default, the 595FX supports ALL IO Ports 
   from 0x000 to 0x3F0, some of which are reserved in PCs */
@@ -205,7 +212,7 @@
 				   version of the 82595 chip. */
 	int stepping;
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-        spinlock_t lock; /* to prevent interrupt within interrupts */ 
+	spinlock_t lock; /* Serializing lock  */ 
 #endif
 };
 
@@ -313,7 +320,7 @@
 static int	eepro_grab_irq(struct device *dev);
 
 /*
-  			Details of the i82595.
+			Details of the i82595.
 
 You will need either the datasheet or the user manual to understand what
 is going on here.  The 82595 is very different from the 82586, 82593.
@@ -344,7 +351,7 @@
 */
 #define	RAM_SIZE	0x8000
 #define	RCV_HEADER	8
-#define RCV_RAM         0x6000  /* 24KB default for RCV buffer */
+#define RCV_RAM 	0x6000  /* 24KB default for RCV buffer */
 #define RCV_LOWER_LIMIT 0x00    /* 0x0000 */
 /* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */    /* 0x5ffe */
 #define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)   
@@ -454,8 +461,7 @@
 struct netdev_entry netcard_drv =
 {"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
 #else
-int
-eepro_probe(struct device *dev)
+compat_init_func(int eepro_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -467,9 +473,9 @@
 	/* Wakeup: */
 	#define WakeupPort 0x279
 	#define WakeupSeq    {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\
-                              0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
-                              0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
-                              0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
+	                      0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
+	                      0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
+	                      0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
 
 	{
 		unsigned short int WS[32]=WakeupSeq;
@@ -485,19 +491,21 @@
 				outb_p(WS[i],WakeupPort);
 				if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
 			}
-		} else printk("Checkregion Failed!\n");
+		} else printk(KERN_WARNING "Checkregion Failed!\n");
 	}
 #endif
 
 
 	if (base_addr > 0x1ff)		/* Check a single specified location. */
 		return eepro_probe1(dev, base_addr);
+
 	else if (base_addr != 0)	/* Don't probe at all. */
 		return ENXIO;
 
 
 	for (i = 0; eepro_portlist[i]; i++) {
 		int ioaddr = eepro_portlist[i];
+
 		if (check_region(ioaddr, EEPRO_IO_EXTENT))
 			continue;
 		if (eepro_probe1(dev, ioaddr) == 0)
@@ -512,11 +520,11 @@
 {
 	unsigned short Word;
 	int i,j;
-  
+
 	for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
 		j+=read_eeprom(ioaddr,i);
 	printk("Checksum: %#x\n",j&0xffff);
-     
+
 	Word=read_eeprom(ioaddr, 0);
 	printk(KERN_DEBUG "Word0:\n");
 	printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
@@ -533,10 +541,10 @@
 		printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI));
 		printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber));
 		printk(KERN_DEBUG " AutoPort: %d\n", GetBit(!Word,ee_Jabber));
-		printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));  
+		printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
 	}
 
-  Word=read_eeprom(ioaddr, 5);
+	Word=read_eeprom(ioaddr, 5);
 	printk(KERN_DEBUG "Word5:\n");
 	printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
 	printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
@@ -546,18 +554,19 @@
 	if (GetBit(Word,ee_PortAUI)) printk("AUI ");
 	printk("port(s) \n");
 
-  Word=read_eeprom(ioaddr, 6);
+	Word=read_eeprom(ioaddr, 6);
 	printk(KERN_DEBUG "Word6:\n");
 	printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
 	printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
 
-  Word=read_eeprom(ioaddr, 7);
+	Word=read_eeprom(ioaddr, 7);
 	printk(KERN_DEBUG "Word7:\n");
 	printk(KERN_DEBUG " INT to IRQ:\n");
 
 	printk(KERN_DEBUG);
-  for (i=0, j=0; i<15; i++)
-     if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);
+
+	for (i=0, j=0; i<15; i++)
+		if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);
 
 	printk("\n");
 }
@@ -577,11 +586,10 @@
 	/* Now, we are going to check for the signature of the
 	   ID_REG (register 2 of bank 0) */
 
-
- id=inb(ioaddr + ID_REG);
+	id=inb(ioaddr + ID_REG);
  
- printk(KERN_DEBUG " id: %#x ",id);
- printk(" io: %#x ",ioaddr);
+	printk(KERN_DEBUG " id: %#x ",id);
+	printk(" io: %#x ",ioaddr);
  
 	if (((id) & ID_REG_MASK) == ID_REG_SIG) {
 
@@ -606,7 +614,7 @@
 			if (net_debug>3)
 				printEEPROMInfo(ioaddr);
 				
-		        if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ Mask */
+			if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ Mask */
 				eepro = 2;
 				printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", 
 					dev->name, ioaddr);
@@ -622,7 +630,7 @@
 					dev->name, ioaddr);
 			}
 
-   			/* Fill in the 'dev' fields. */
+			/* Fill in the 'dev' fields. */
 			dev->base_addr = ioaddr;
 			
 			for (i=0; i < 6; i++) {
@@ -641,24 +649,13 @@
 				printk(", %dK RCV buffer", (int)(dev->mem_end)/1024);
 				
 				
-//			outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
-//			id = inb(ioaddr + REG3);
-//			if (id & TPE_BIT)
-//				dev->if_port = TPE;
-//			else dev->if_port = BNC;
-			
-			
 			/* ............... */
 
-			if (GetBit(  read_eeprom(ioaddr, 5),ee_BNC_TPE))
+			if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE))
 				dev->if_port = BNC;
 			else dev->if_port = TPE;
-                
-			
-			/* ............... */
 
-//			if (net_debug>3) 
-//				printk("id: %x\n", id);
+			/* ............... */
 
 
 			if ((dev->irq < 2) && (eepro!=0)) {
@@ -668,14 +665,14 @@
 				
 				for (j=0; ((j<16) && (i>=0)); j++) {
 					if ((irqMask & (1<<j))!=0) {
-					        if (i==0) {
-					        	dev->irq = j;
-					        	break; /* found bit corresponding to irq */
-					        }
+						if (i==0) {
+							dev->irq = j;
+							break; /* found bit corresponding to irq */
+						}
 						i--; /* count bits set in irqMask */
- 					}
- 				}
- 				if (dev -> irq<2) {
+					}
+				}
+				if (dev -> irq<2) {
 					printk(" Duh! illegal interrupt vector stored in EEPROM.\n");
 						return ENODEV;
 				} else 
@@ -685,14 +682,10 @@
 				else if (dev->irq == 2)
 				dev->irq = 9;
 			}
-
+			
 			if (dev->irq > 2) {
 				printk(", IRQ %d, %s.\n", dev->irq,
 						ifmap[dev->if_port]);
-				/*if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro", dev)) {
-					printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
-					return -EAGAIN;
-				}*/
 			}
 			else printk(", %s.\n", ifmap[dev->if_port]);
 			
@@ -702,7 +695,7 @@
 			if (net_debug > 3) {
 				i = read_eeprom(ioaddr, 5);
 				if (i & 0x2000) /* bit 13 of EEPROM word 5 */
-				  printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",
+					printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",
 						dev->name);
 			}
 
@@ -710,7 +703,7 @@
 				printk(version);
 
 			/* Grab the region so we can find another board if autoIRQ fails. */
-			request_region(ioaddr, EEPRO_IO_EXTENT, "eepro");
+			request_region(ioaddr, EEPRO_IO_EXTENT, dev->name);
 
 			/* Initialize the device structure */
 			dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);
@@ -718,6 +711,9 @@
 				return -ENOMEM;
 			memset(dev->priv, 0, sizeof(struct eepro_local));
 
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+			spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));
+#endif
 			dev->open               = eepro_open;
 			dev->stop               = eepro_close;
 			dev->hard_start_xmit    = eepro_send_packet;
@@ -754,11 +750,8 @@
 {
 	int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 };
 	int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
-
-	outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
 	
-	/* Set the spinlock before activating  IRQ! */
-	((struct eepro_local *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
 
 	/* Enable the interrupt line. */
 	temp_reg = inb(ioaddr + REG1);
@@ -768,6 +761,7 @@
 
 	/* clear all interrupts */
 	outb(ALL_MASK, ioaddr + STATUS_REG);
+
 	/* Let EXEC event to interrupt */
 	outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG);
 
@@ -785,11 +779,8 @@
 
 			outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */
 				
-			if (*irqp == autoirq_report(2) )//&&  /* It's a good IRQ line */
-				/* We don't take irqs on detection anymore.
-					only when actually turning on the driver (ifconfig) */
-				/* //(request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", dev) == 0)) */
-					break;
+			if (*irqp == autoirq_report(2))  /* It's a good IRQ line */
+				break;
 
 			/* clear all interrupts */
 			outb(ALL_MASK, ioaddr + STATUS_REG); 
@@ -821,14 +812,14 @@
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 
 	if (net_debug > 3)
-		printk(KERN_DEBUG "eepro: entering eepro_open routine.\n");
+		printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
 
 	if ((irqMask=read_eeprom(ioaddr,7))== ee_FX_INT2IRQ) /* INT to IRQ Mask */
 		{
-		  	lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
-		  	if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); 
+			lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
+			if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); 
 		}
-       
+
 	else if ((dev->dev_addr[0] == SA_ADDR0 &&
 			dev->dev_addr[1] == SA_ADDR1 &&
 			dev->dev_addr[2] == SA_ADDR2))
@@ -845,7 +836,7 @@
 		return -EAGAIN;
 	}
 		
-	if (request_irq(dev->irq , &eepro_interrupt, 0, "eepro", dev)) {
+	if (request_irq(dev->irq , &eepro_interrupt, 0, dev->name, dev)) {
 		printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
 		return -EAGAIN;
 	}
@@ -854,8 +845,8 @@
 	if  (((irq2dev_map[dev->irq] != 0)
 		|| (irq2dev_map[dev->irq] = dev) == 0) && 
 		(irq2dev_map[dev->irq]!=dev)) {
-	    /* printk("%s: IRQ map wrong\n", dev->name); */
-	 	return -EAGAIN;
+		/* printk("%s: IRQ map wrong\n", dev->name); */
+		return -EAGAIN;
 	}
 #endif
 
@@ -894,15 +885,14 @@
 	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); 
 
 
-    temp_reg = inb(ioaddr + INT_NO_REG);
-    if (lp->eepro == 2)
-       outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
-    else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
-
-    if (net_debug > 3)
-       printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);
-       
-       
+	temp_reg = inb(ioaddr + INT_NO_REG);
+	if (lp->eepro == 2)
+		outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
+	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+
+	if (net_debug > 3)
+		printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);
+
 
 	/* Initialize the RCV and XMT upper and lower limits */
 	outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); 
@@ -918,6 +908,7 @@
 
 	/* Let RX and TX events to interrupt */
 	outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+
 	/* clear all interrupts */
 	outb(ALL_MASK, ioaddr + STATUS_REG); 
 
@@ -932,6 +923,7 @@
 	/* Check for the i82595TX and i82595FX */
 	old8 = inb(ioaddr + 8);
 	outb(~old8, ioaddr + 8);
+
 	if ((temp_reg = inb(ioaddr + 8)) == old8) {
 		if (net_debug > 3)
 			printk(KERN_DEBUG "i82595 detected!\n");
@@ -965,25 +957,26 @@
 			}
 		}
 		else if (net_debug > 3) {
-		        printk(KERN_DEBUG "temp_reg: %#x  ~old9: %#x\n",temp_reg,((~old9)&0xff));
+			printk(KERN_DEBUG "temp_reg: %#x  ~old9: %#x\n",temp_reg,((~old9)&0xff));
 			printk(KERN_DEBUG "i82595TX detected!\n");
 		}
 	}
 	
 	outb(SEL_RESET_CMD, ioaddr);
+
 	/* We are supposed to wait for 2 us after a SEL_RESET */
 	SLOW_DOWN;
 	SLOW_DOWN;
 
 	lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
-	lp->tx_last = 0;  
+	lp->tx_last = 0;
 	
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
 
 	if (net_debug > 3)
-		printk(KERN_DEBUG "eepro: exiting eepro_open routine.\n");
+		printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
 
 	outb(RCV_ENABLE_CMD, ioaddr);
 
@@ -997,39 +990,43 @@
 	int ioaddr = dev->base_addr;
 	int rcv_ram = dev->mem_end;
 
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+	unsigned long flags;
+#endif
+	
 	if (net_debug > 5)
-	  printk(KERN_DEBUG  "eepro: entering eepro_send_packet routine.\n");
+		printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
 	
 	if (dev->tbusy) {
-	  /* If we get here, some higher level has decided we are broken.
-	     There should really be a "kick me" function call instead. */
-	  int tickssofar = jiffies - dev->trans_start;
-	  if (tickssofar < 40)
-	    return 1;
-	 
-	  /* if (net_debug > 1) */
-	  printk("%s: transmit timed out, %s?\n", dev->name, 
-		 "network cable problem");
-	  /* This is not a duplicate. One message for the console, one for the
-	     the log file  */
-	  printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
-		 "network cable problem");
-	  lp->stats.tx_errors++;
-
-	  /* Try to restart the adaptor. */
-	  outb(SEL_RESET_CMD, ioaddr); 
-	  /* We are supposed to wait for 2 us after a SEL_RESET */
-	  SLOW_DOWN;
-	  SLOW_DOWN;
-	  
-	  /* Do I also need to flush the transmit buffers here? YES? */
-	  lp->tx_start = lp->tx_end = rcv_ram; 
-	  lp->tx_last = 0;
-	
-	  dev->tbusy=0;
-	  dev->trans_start = jiffies;
-	  
-	  outb(RCV_ENABLE_CMD, ioaddr);
+		/* If we get here, some higher level has decided we are broken.
+		   There should really be a "kick me" function call instead. */
+		int tickssofar = jiffies - dev->trans_start;
+		if (tickssofar < 40)
+			return 1;
+	
+		/* if (net_debug > 1) */
+		printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name, 
+			"network cable problem");
+		/* This is not a duplicate. One message for the console, 
+		   one for the the log file  */
+		printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
+			"network cable problem");
+		lp->stats.tx_errors++;
+
+		/* Try to restart the adaptor. */
+		outb(SEL_RESET_CMD, ioaddr); 
+		/* We are supposed to wait for 2 us after a SEL_RESET */
+		SLOW_DOWN;
+		SLOW_DOWN;
+
+		/* Do I also need to flush the transmit buffers here? YES? */
+		lp->tx_start = lp->tx_end = rcv_ram; 
+		lp->tx_last = 0;
+	
+		dev->tbusy=0;
+		dev->trans_start = jiffies;
+
+		outb(RCV_ENABLE_CMD, ioaddr);
 
 	}
 
@@ -1037,37 +1034,35 @@
 	/* If some higher layer thinks we've missed an tx-done interrupt
 	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
 	   itself. */
-	//	if (skb == NULL) {
-	//	dev_tint(dev);
-	//	return 0;
-	// FIXME : what's this code for ?
-	}
+	/*	if (skb == NULL) {
+		dev_tint(dev);
+	  	return 0;
+	}*/
+	/* according to A. Cox, this is obsolete since 1.0 */
 #endif
 
-	/* Block a timer-based transmit from overlapping. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-	  printk("%s: Transmitter access conflict.\n", dev->name);
-	else {
-          short length; unsigned char *buf;
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	  unsigned long flags;
-
-	  /* Spin on the lock, until we're clear of an IRQ */
-	  spin_lock_irqsave(&lp->lock, flags);     
+	spin_lock_irqsave(&lp->lock, flags);
 #endif
-	  length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-	  buf = skb->data;
+
+	/* Block a timer-based transmit from overlapping. */
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	  lp->stats.tx_bytes+=skb->len;
+		spin_unlock_irqrestore(&lp->lock, flags);
 #endif
-	  hardware_send_packet(dev, buf, length);
-	  
-	  dev->trans_start = jiffies;
+	} else {
+		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+		unsigned char *buf = skb->data;
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	  spin_unlock_irqrestore(&lp->lock, flags);     
-#endif	
+		lp->stats.tx_bytes+=skb->len;
+#endif
+
+		hardware_send_packet(dev, buf, length);
+		dev->trans_start = jiffies;
+
 	}
 
 	compat_dev_kfree_skb (skb, FREE_WRITE);
@@ -1076,75 +1071,83 @@
 	/* lp->stats.tx_aborted_errors++; */
 
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: exiting eepro_send_packet routine.\n");
+		printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+	spin_unlock_irqrestore(&lp->lock, flags);
+#endif
 	
 	return 0;
 }
 
+
 /*	The typical workload of the driver:
 	Handle the network interface interrupts. */
+
 static void
 eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct device *dev =  (struct device *)dev_id;
 	                      /* (struct device *)(irq2dev_map[irq]);*/
-#ifdef __SMP__
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
-#endif	
 	int ioaddr, status, boguscount = 20;
 
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) 
-	{
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-        		dev->name);
-		dev->interrupt = 0; /* Avoid halting machine. */
-        	return;
-	}
-
-	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: entering eepro_interrupt routine.\n");
-	
 	if (dev == NULL) {
-		printk ("eepro_interrupt(): irq %d for unknown device.\n", irq);
+                printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq);
+                return;
+        }
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+        spin_lock(&lp->lock);
+#endif
+
+	if (dev->interrupt) {
+		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+		spin_unlock(&lp->lock);
+		/* FIXME : with the lock, could this ever happen ? */
+#endif
+
 		return;
 	}
-	/* dev->interrupt = 1; */
+	dev->interrupt = 1;
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	spin_lock(&lp->lock);
-#endif	
-        ioaddr = dev->base_addr;
+	if (net_debug > 5)
+		printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);
+	
+	ioaddr = dev->base_addr;
 
-        do { 
-	  status = inb(ioaddr + STATUS_REG);
+	do { 
+		status = inb(ioaddr + STATUS_REG);
 		
-	  if (status & RX_INT) {
-	    if (net_debug > 4)
-	      printk(KERN_DEBUG "eepro: packet received interrupt.\n");
-
-	    /* Acknowledge the RX_INT */
-	    outb(RX_INT, ioaddr + STATUS_REG);   
-	    /* Get the received packets */
-	    eepro_rx(dev);
-	  }
-
-	  else if (status & TX_INT) {
-	    if (net_debug > 4)
-	      printk(KERN_DEBUG "eepro: packet transmit interrupt.\n");
-
-	    /* Acknowledge the TX_INT */
-	    outb(TX_INT, ioaddr + STATUS_REG); 
-	    
-	    /* Process the status of transmitted packets */
-	    eepro_transmit_interrupt(dev);
-	  }
+		if (status & RX_INT) {
+			if (net_debug > 4)
+			printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name);
+
+			/* Acknowledge the RX_INT */
+			outb(RX_INT, ioaddr + STATUS_REG);
+			/* Get the received packets */
+			eepro_rx(dev);
+		}
+
+		else if (status & TX_INT) {
+			if (net_debug > 4)
+			printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
+
+			/* Acknowledge the TX_INT */
+			outb(TX_INT, ioaddr + STATUS_REG); 
+
+			/* Process the status of transmitted packets */
+			eepro_transmit_interrupt(dev);
+		}
 	
 	} while ((boguscount-- > 0) && (status & 0x06));
 
 	dev->interrupt = 0; 
 
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: exiting eepro_interrupt routine.\n");
+		printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 	spin_unlock(&lp->lock);
@@ -1173,7 +1176,7 @@
 	/* Flush the Tx and disable Rx. */
 	outb(STOP_RCV_CMD, ioaddr); 
 	lp->tx_start = lp->tx_end = rcv_ram ;
-	lp->tx_last = 0;  
+	lp->tx_last = 0;
 
 	/* Mask all the interrupts. */
 	outb(ALL_MASK, ioaddr + INT_MASK_REG); 
@@ -1238,7 +1241,8 @@
 		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
 		outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
 		printk("%s: promiscuous mode enabled.\n", dev->name);
-	} 
+	}
+	
 	else if (dev->mc_count==0 ) 
 	{
 		outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
@@ -1248,6 +1252,7 @@
 		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
 		outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
 	}
+	
 	else 
 	{
 		unsigned short status, *eaddrs;
@@ -1269,6 +1274,7 @@
 		outw(0, ioaddr + IO_PORT);
 		outw(0, ioaddr + IO_PORT);
 		outw(6*(dev->mc_count + 1), ioaddr + IO_PORT);
+		
 		for (i = 0; i < dev->mc_count; i++) 
 		{
 			eaddrs=(unsigned short *)dmi->dmi_addr;
@@ -1277,6 +1283,7 @@
 			outw(*eaddrs++, ioaddr + IO_PORT);
 			outw(*eaddrs++, ioaddr + IO_PORT);
 		}
+		
 		eaddrs = (unsigned short *) dev->dev_addr;
 		outw(eaddrs[0], ioaddr + IO_PORT);
 		outw(eaddrs[1], ioaddr + IO_PORT);
@@ -1286,8 +1293,9 @@
 
 		/* Update the transmit queue */
 		i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1);
+		
 		if (lp->tx_start != lp->tx_end) 
-		{ 
+		{
 			/* update the next address and the chain bit in the 
 			   last packet */
 			outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
@@ -1309,14 +1317,15 @@
 			{
 				i = inb(ioaddr);
 				outb(0x08, ioaddr + STATUS_REG);
+				
 				if (i & 0x20) { /* command ABORTed */
 					printk("%s: multicast setup failed.\n", 
 						dev->name);
 					break;
 				} else if ((i & 0x0f) == 0x03)	{ /* MC-Done */
-				  printk("%s: set Rx mode to %d address%s.\n",
-					 dev->name, dev->mc_count,
-					 dev->mc_count > 1 ? "es":"");
+					printk("%s: set Rx mode to %d address%s.\n",
+						dev->name, dev->mc_count,
+						dev->mc_count > 1 ? "es":"");
 					break;
 				}
 			}
@@ -1333,7 +1342,7 @@
 /* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
 
 /* The delay between EEPROM clock transitions. */
-#define eeprom_delay()	{ int _i = 40; while (--_i > 0) { SLOW_DOWN; }}
+#define eeprom_delay() { udelay(40); }
 #define EE_READ_CMD (6 << 6)
 
 int
@@ -1385,16 +1394,16 @@
 	unsigned status, tx_available, last, end, boguscount = 100;
 
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: entering hardware_send_packet routine.\n");
+		printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
 
 	while (boguscount-- > 0) {
 
 		/* Disable RX and TX interrupts.  Necessary to avoid
-	   	corruption of the HOST_ADDRESS_REG by interrupt
-	   	service routines. */
+		corruption of the HOST_ADDRESS_REG by interrupt
+		service routines. */
 		outb(ALL_MASK, ioaddr + INT_MASK_REG);
 
-		if (dev->interrupt == 1) {  
+		if (dev->interrupt == 1) {
 			/* Enable RX and TX interrupts */
 			outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
 			continue;
@@ -1421,12 +1430,15 @@
 		end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
 
 		if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */
+		
 			if ((RAM_SIZE - last) <= XMT_HEADER) {	
-			/* Arrrr!!!, must keep the xmt header together,
-			  several days were lost to chase this one down. */
+				/* Arrrr!!!, must keep the xmt header together,
+				several days were lost to chase this one down. */
+				
 				last = rcv_ram;
 				end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
-			}	
+			}
+			
 			else end = rcv_ram + (end - RAM_SIZE);
 		}
 
@@ -1454,18 +1466,20 @@
 			lp->tx_start = last;   /* I don't like to change tx_start here */
 		}
 		else {
-		  /* update the next address and the chain bit in the 
-		     last packet */
-		  if (lp->tx_end != last) {
-		    outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
-		    outw(last, ioaddr + IO_PORT); 
-		  }
-		  outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
-		  status = inw(ioaddr + IO_PORT); 
-		  outw(status | CHAIN_BIT, ioaddr + IO_PORT);
+			/* update the next address and the chain bit in the 
+			last packet */
+			
+			if (lp->tx_end != last) {
+				outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
+				outw(last, ioaddr + IO_PORT); 
+			}
+			
+			outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
+			status = inw(ioaddr + IO_PORT); 
+			outw(status | CHAIN_BIT, ioaddr + IO_PORT);
 
-		  /* Continue the transmit command */
-		  outb(RESUME_XMT_CMD, ioaddr);
+			/* Continue the transmit command */
+			outb(RESUME_XMT_CMD, ioaddr);
 		}
 
 		lp->tx_last = last;
@@ -1476,16 +1490,16 @@
 		}
 		
 		/* Enable RX and TX interrupts */
-                outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+		outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
 
 		if (net_debug > 5)
-			printk(KERN_DEBUG "eepro: exiting hardware_send_packet routine.\n");
+			printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
 		return;
 	}
 
 	dev->tbusy = 1;
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: exiting hardware_send_packet routine.\n");
+		printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
 }
 
 static void
@@ -1498,77 +1512,88 @@
 	unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
 
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: entering eepro_rx routine.\n");
+		printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name);
 	
 	/* Set the read pointer to the start of the RCV */
 	outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
+	
 	rcv_event = inw(ioaddr + IO_PORT);
 
 	while (rcv_event == RCV_DONE) {
-	  rcv_status = inw(ioaddr + IO_PORT); 
-	  rcv_next_frame = inw(ioaddr + IO_PORT);
-	  rcv_size = inw(ioaddr + IO_PORT); 
-
-	  if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
-	    /* Malloc up new buffer. */
-	    struct sk_buff *skb;
+	
+		rcv_status = inw(ioaddr + IO_PORT); 
+		rcv_next_frame = inw(ioaddr + IO_PORT);
+		rcv_size = inw(ioaddr + IO_PORT); 
+
+		if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
+		
+			/* Malloc up new buffer. */
+			struct sk_buff *skb;
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	    lp->stats.rx_bytes+=rcv_size;
-#endif                        
-	    rcv_size &= 0x3fff;
-	    skb = dev_alloc_skb(rcv_size+5);
-	    if (skb == NULL) {
-	      printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-	      lp->stats.rx_dropped++;
-	      break;
-	    }
-	    skb->dev = dev;
-	    skb_reserve(skb,2);
-
-	    if (lp->version == LAN595)
-	      insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
-	    else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
-	      unsigned short temp = inb(ioaddr + INT_MASK_REG);
-	      outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
-	      insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), 
-		   (rcv_size + 3) >> 2);
-	      outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
-	    }
-	
-	    skb->protocol = eth_type_trans(skb,dev);	
-	    netif_rx(skb);
-	    lp->stats.rx_packets++;
-	  }
-	  else { /* Not sure will ever reach here, 
-		    I set the 595 to discard bad received frames */
-	    lp->stats.rx_errors++;
-	    if (rcv_status & 0x0100)
-	      lp->stats.rx_over_errors++;
-	    else if (rcv_status & 0x0400)
-	      lp->stats.rx_frame_errors++;
-	    else if (rcv_status & 0x0800)
-	      lp->stats.rx_crc_errors++;
-	    printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", 
-		   dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
-	  }
-	  if (rcv_status & 0x1000)
-	    lp->stats.rx_length_errors++;
-	  if (--boguscount == 0)
-	    break;
-	  
-	  rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
-	  lp->rx_start = rcv_next_frame;
-	  outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
-	  rcv_event = inw(ioaddr + IO_PORT);
-	  
+			lp->stats.rx_bytes+=rcv_size;
+#endif
+			rcv_size &= 0x3fff;
+			skb = dev_alloc_skb(rcv_size+5);
+			if (skb == NULL) {
+				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+				lp->stats.rx_dropped++;
+				break;
+			}
+			skb->dev = dev;
+			skb_reserve(skb,2);
+
+			if (lp->version == LAN595)
+				insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
+			else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
+				unsigned short temp = inb(ioaddr + INT_MASK_REG);
+				outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
+				insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), 
+					(rcv_size + 3) >> 2);
+				outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
+			}
+	
+			skb->protocol = eth_type_trans(skb,dev);	
+			netif_rx(skb);
+			lp->stats.rx_packets++;
+		}
+		
+		else { /* Not sure will ever reach here, 
+			I set the 595 to discard bad received frames */
+			lp->stats.rx_errors++;
+			
+			if (rcv_status & 0x0100)
+				lp->stats.rx_over_errors++;
+			
+			else if (rcv_status & 0x0400)
+				lp->stats.rx_frame_errors++;
+			
+			else if (rcv_status & 0x0800)
+				lp->stats.rx_crc_errors++;
+			
+			printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", 
+				dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
+		}
+
+		if (rcv_status & 0x1000)
+			lp->stats.rx_length_errors++;
+
+		if (--boguscount == 0)
+			break;
+
+		rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
+		lp->rx_start = rcv_next_frame;
+		outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
+		rcv_event = inw(ioaddr + IO_PORT);
+
 	} 
 	if (rcv_car == 0)
-	  rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+		rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+		
 	outw(rcv_car - 1, ioaddr + RCV_STOP);
 
 	if (net_debug > 5)
-	  printk(KERN_DEBUG "eepro: exiting eepro_rx routine.\n");
+		printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name);
 }
 
 static void
@@ -1581,47 +1606,53 @@
 	
 	/*
 	if (dev->tbusy == 0) {
-	  printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
-		 dev->name);
-	  printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n",
-		 dev->name);
+		printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
+			dev->name);
+		printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n",
+			dev->name);
 	}
 	*/
+
 	while (lp->tx_start != lp->tx_end) { 
-	  outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); 
-	  xmt_status = inw(ioaddr+IO_PORT);
-	  if ((xmt_status & TX_DONE_BIT) == 0) break;
-
-	  xmt_status = inw(ioaddr+IO_PORT); 
-	  lp->tx_start = inw(ioaddr+IO_PORT);
-
-	  dev->tbusy = 0;
-	  mark_bh(NET_BH);
-
-	  if (xmt_status & 0x2000)
-	    lp->stats.tx_packets++; 
-	  else {
-	    lp->stats.tx_errors++;
-	    if (xmt_status & 0x0400)
-	      lp->stats.tx_carrier_errors++;
-	    printk("%s: XMT status = %#x\n",
-		   dev->name, xmt_status);
-	    printk(KERN_DEBUG "%s: XMT status = %#x\n",
-		   dev->name, xmt_status);
-	  }
-	  if (xmt_status & 0x000f) {
-	    lp->stats.collisions += (xmt_status & 0x000f);
-	  }
-	  if ((xmt_status & 0x0040) == 0x0) {
-	    lp->stats.tx_heartbeat_errors++;
-	  }
-	  
-	  if (--boguscount == 0)
-	    break;  
+	
+		outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); 
+		xmt_status = inw(ioaddr+IO_PORT);
+		
+		if ((xmt_status & TX_DONE_BIT) == 0) break;
+
+		xmt_status = inw(ioaddr+IO_PORT); 
+		lp->tx_start = inw(ioaddr+IO_PORT);
+
+		dev->tbusy = 0;
+		mark_bh(NET_BH);
+
+		if (xmt_status & 0x2000)
+			lp->stats.tx_packets++; 
+		else {
+			lp->stats.tx_errors++;
+			if (xmt_status & 0x0400)
+				lp->stats.tx_carrier_errors++;
+			printk("%s: XMT status = %#x\n",
+				dev->name, xmt_status);
+			printk(KERN_DEBUG "%s: XMT status = %#x\n",
+				dev->name, xmt_status);
+		}
+		
+		if (xmt_status & 0x000f) {
+			lp->stats.collisions += (xmt_status & 0x000f);
+		}
+		
+		if ((xmt_status & 0x0040) == 0x0) {
+			lp->stats.tx_heartbeat_errors++;
+		}
+
+		if (--boguscount == 0)
+			break;
 	}
 }
 
 #ifdef MODULE
+
 #define MAX_EEPRO 8
 static char devicename[MAX_EEPRO][9];
 static struct device dev_eepro[MAX_EEPRO];
@@ -1655,10 +1686,12 @@
 MODULE_PARM(mem, "i");
 #endif 
 
-int init_module(void)
+int 
+init_module(void)
 {
 	if (io[0] == 0)
-		printk("eepro: You should not use auto-probing with insmod!\n");
+		printk("eepro_init_module: You should not use auto-probing with insmod!\n");
+
 	while (n_eepro < MAX_EEPRO && io[n_eepro] >= 0) {
 		struct device *d = &dev_eepro[n_eepro];
 		d->name		= devicename[n_eepro]; /* inserted by drivers/net/net_init.c */
@@ -1682,6 +1715,7 @@
 	for (i=0; i<n_eepro; i++) {
 		struct device *d = &dev_eepro[i];
 		unregister_netdev(d);
+
 		kfree_s(d->priv,sizeof(struct eepro_local));
 		d->priv=NULL;
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov