patch-2.0.36 linux/drivers/net/eepro.c

Next file: linux/drivers/net/eepro100.c
Previous file: linux/drivers/net/de4x5.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.35/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
@@ -1,19 +1,15 @@
 /* eepro.c: Intel EtherExpress Pro/10 device driver for Linux. */
 /*
-	Written 1994, 1995,1996 by Bao C. Ha.
-	Last Update, 2/7/98, Phillip R. Jaenke
+	Written 1994-1998 by Bao C. Ha.
 
-	Copyright (C) 1994, 1995,1996 by Bao C. Ha.
+	Copyright (C) 1994-1998 by Bao C. Ha.
 
 	This software may be used and distributed
 	according to the terms of the GNU Public License,
 	incorporated herein by reference.
 
-	The author may be reached at bao.ha@srs.gov 
-	or 418 Hastings Place, Martinez, GA 30907.
-
-	Phillip R. Jaenke may be reached at prj@nls.net
-	or P.O. Box 413, Twinsburg, OH 44087, ATTN: Linux
+	The author may be reached at bao@hacom.net 
+	or Hacom, 2477 Wrightsboro Rd., Augusta, GA 30904.
 
 	Things remaining to do:
 	Better record keeping of errors.
@@ -27,9 +23,19 @@
 	This is a compatibility hardware problem.
 
 	Versions:
-	
-	0.10	Added several I/O addresses previously not included.
-		(PRJ, 2/7/98)
+
+	0.10c	Some cosmetic changes. (9/28/98, BCH)
+
+        0.10b	Should work now with (some) Pro/10+. At least for 
+        	me (and my two cards) it does. _No_ guarantee for 
+        	function with non-Pro/10+ cards! (don't have any)
+        	(RMC, 9/11/96)
+
+	0.10	Added support for the Etherexpress Pro/10+.  The
+		IRQ map was changed significantly from the old
+		pro/10.  The new interrupt map was provided by
+		Rainer M. Canavan (Canavan@Zeus.cs.bonn.edu).
+		(BCH, 9/3/96)
 
 	0.09	Fixed a race condition in the transmit algorithm,
 		which causes crashes under heavy load with fast
@@ -67,7 +73,7 @@
 */
 
 static const char *version =
-	"eepro.c: v0.10 7/31/96 Bao C. Ha (bao.ha@srs.gov)\n";
+	"eepro.c: v0.10c 9/28/98 Bao C. Ha (bao@hacom.net)\n";
 
 #include <linux/module.h>
 
@@ -113,22 +119,26 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-
 /* 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[] =
-   { 0x200, 0x240, 0x260, 0x280, 0x2C0, 0x300, 0x310, 0x320, 0x340, 0x360, 0};
+   { 0x300, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
 
 /* use 0 for production, 1 for verification, >2 for debug */
+
 #ifndef NET_DEBUG
-#define NET_DEBUG 3
+#define NET_DEBUG 1
 #endif
+
 static unsigned int net_debug = NET_DEBUG;
 
 /* The number of low I/O ports used by the ethercard. */
+
 #define EEPRO_IO_EXTENT	16
 
 /* Different 82595 chips */
+
 #define	LAN595		0
 #define	LAN595TX	1
 #define	LAN595FX	2
@@ -140,18 +150,29 @@
 	unsigned tx_start; /* start of the transmit chain */
 	int tx_last;  /* pointer to last packet in the transmit chain */
 	unsigned tx_end;   /* end of the transmit chain (plus 1) */
-	int eepro;	/* a flag, TRUE=1 for the EtherExpress Pro/10,
-			   FALSE = 0 for other 82595-based lan cards. */
+	int eepro;	/* 1 for the EtherExpress Pro/10,
+			   2 for the EtherExpress Pro/10+,
+			   0 for other 82595-based lan cards. */
 	int version;	/* a flag to indicate if this is a TX or FX
 				   version of the 82595 chip. */
 	int stepping;
 };
 
 /* The station (ethernet) address prefix, used for IDing the board. */
-#define SA_ADDR0 0x00
+
+#define SA_ADDR0 0x00	/* Etherexpress Pro/10 */
 #define SA_ADDR1 0xaa
 #define SA_ADDR2 0x00
 
+#define SA2_ADDR0 0x00	/* Etherexpress Pro/10+ */
+#define SA2_ADDR1 0xa0
+#define SA2_ADDR2 0xc9
+
+#define SA3_ADDR0 0x00	/* more Etherexpress Pro/10+ */
+#define SA3_ADDR1 0xaa
+#define SA3_ADDR2 0x00
+#define SA3_ADDR3 0xc9
+
 /* Index to functions, as function prototypes. */
 
 extern int eepro_probe(struct device *dev);	
@@ -200,14 +221,18 @@
 buffer (transmit-buffer = 32K - receive-buffer).
 
 */
+
 #define	RAM_SIZE	0x8000
 #define	RCV_HEADER	8
 #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)   
+
 /* #define XMT_RAM         (RAM_SIZE - RCV_RAM) */    /* 8KB for XMT buffer */
 #define XMT_RAM         (RAM_SIZE - (rcv_ram))    /* 8KB for XMT buffer */
+
 /* #define XMT_LOWER_LIMIT (RCV_RAM >> 8) */  /* 0x6000 */
 #define XMT_LOWER_LIMIT ((rcv_ram) >> 8) 
 #define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8)   /* 0x7ffe */
@@ -228,6 +253,7 @@
 #define	BANK2_SELECT	0x80		
 
 /* Bank 0 registers */
+
 #define	COMMAND_REG	0x00	/* Register 0 */
 #define	MC_SETUP	0x03
 #define	XMT_CMD		0x04
@@ -263,6 +289,7 @@
 #define	IO_PORT_32_BIT	0x0c
 
 /* Bank 1 registers */
+
 #define	REG1	0x01
 #define	WORD_WIDTH	0x02
 #define	INT_ENABLE	0x80
@@ -273,6 +300,7 @@
 #define	XMT_UPPER_LIMIT_REG	0x0b
 
 /* Bank 2 registers */
+
 #define	XMT_Chain_Int	0x20	/* Interrupt at the end of the transmit chain */
 #define	XMT_Chain_ErrStop	0x40 /* Interrupt at the end of the chain even if there are errors */
 #define	RCV_Discard_BadFrame	0x80 /* Throw bad frames away, and continue to receive others */
@@ -285,7 +313,7 @@
 #define	REG13		0x0d
 #define	FDX		0x00
 #define	A_N_ENABLE	0x02
-	
+
 #define	I_ADD_REG0	0x04
 #define	I_ADD_REG1	0x05
 #define	I_ADD_REG2	0x06
@@ -299,20 +327,26 @@
 #define EEDI 0x04
 #define EEDO 0x08
 
+/* Check for a network adaptor of this type, and return '0' if one exists.
 
-/* Check for a network adaptor of this type, and return '0' iff one exists.
    If dev->base_addr == 0, probe all likely locations.
    If dev->base_addr == 1, always return failure.
    If dev->base_addr == 2, allocate space for the device and return success
    (detachable devices only).
+
    */
+
 #ifdef HAVE_DEVLIST
+
 /* Support for a alternate probe manager, which will eliminate the
    boilerplate below. */
+
 struct netdev_entry netcard_drv =
 {"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
+
 #else
-int
+
+int 
 eepro_probe(struct device *dev)
 {
 	int i;
@@ -327,6 +361,7 @@
 		int ioaddr = eepro_portlist[i];
 		if (check_region(ioaddr, EEPRO_IO_EXTENT))
 			continue;
+
 		if (eepro_probe1(dev, ioaddr) == 0)
 			return 0;
 	}
@@ -339,24 +374,23 @@
    probes on the ISA bus.  A good device probes avoids doing writes, and
    verifies that the correct device exists and functions.  */
 
-int eepro_probe1(struct device *dev, short ioaddr)
+int 
+eepro_probe1(struct device *dev, short ioaddr)
 {
 	unsigned short station_addr[6], id, counter;
 	int i;
-	int eepro;	/* a flag, TRUE=1 for the EtherExpress Pro/10,
-			   FALSE = 0 for other 82595-based lan cards. */
+	int eepro;
 	const char *ifmap[] = {"AUI", "10Base2", "10BaseT"};
 	enum iftype { AUI=0, BNC=1, TPE=2 };
 
 	/* Now, we are going to check for the signature of the
 	   ID_REG (register 2 of bank 0) */
-
 	if (((id=inb(ioaddr + ID_REG)) & ID_REG_MASK) == ID_REG_SIG) {
 
 		/* We seem to have the 82595 signature, let's
 		   play with its counter (last 2 bits of
 		   register 2 of bank 0) to be sure. */
-	
+
 		counter = (id & R_ROBIN_BITS);	
 		if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) == 
 			(counter + 0x40)) {
@@ -372,44 +406,54 @@
 
 			/* Check the station address for the manufacturer's code */
 
-			if (station_addr[2] != 0x00aa || (station_addr[1] & 0xff00) != 0x0000) {
-				eepro = 0;
-				printk("%s: Intel 82595-based lan card at %#x,", 
+			if ((station_addr[2] == 0x00aa) && (station_addr[1]!= 0x00c9)) {
+				eepro = 1;
+				printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", 
+					dev->name, ioaddr);
+			} else
+			if ( (station_addr[2] == 0x00a0)
+			     || ((station_addr[2] == 0x00aa) && (station_addr[1] == 0x00c9) )) {
+				eepro = 2;
+				printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", 
 					dev->name, ioaddr);
 			}
 			else {
-				eepro = 1;
-				printk("%s: Intel EtherExpress Pro/10 at %#x,", 
+				eepro = 0;
+				printk("%s: Intel 82595-based lan card at %#x,", 
 					dev->name, ioaddr);
 			}
 
    			/* Fill in the 'dev' fields. */
 			dev->base_addr = ioaddr;
-			
+
 			for (i=0; i < 6; i++) {
 				dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
 				printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
 			}
-			
+
 			if ((dev->mem_end & 0x3f) < 3 ||	/* RX buffer must be more than 3K */
 				(dev->mem_end & 0x3f) > 29)	/* and less than 29K */
 				dev->mem_end = RCV_RAM;		/* or it will be set to 24K */
 			else dev->mem_end = 1024*dev->mem_end;  /* Maybe I should shift << 10 */
 
 			/* From now on, dev->mem_end contains the actual size of rx buffer */
-			
+
 			if (net_debug > 3)
 				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 (net_debug>3) 
+				printk("id: %x\n", id);
+
 			if (dev->irq < 2 && eepro) {
 				i = read_eeprom(ioaddr, 1);
-				switch (i & 0x07) {
+				if (eepro == 1)
+				   switch (i & 0x07) {
 					case 0:	dev->irq = 9; break;
 					case 1:	dev->irq = 3; break;
 					case 2:	dev->irq = 5; break;
@@ -419,6 +463,16 @@
 						printk(" illegal interrupt vector stored in EEPROM.\n");
 						return ENODEV;
 					}
+				else switch (i & 0x07) {
+					case 0:	dev->irq = 3; break;
+					case 1:	dev->irq = 4; break;
+					case 2:	dev->irq = 5; break;
+					case 3:	dev->irq = 7; break;
+					case 4:	dev->irq = 9; break;
+					case 5:	dev->irq = 10; break;
+					case 6:	dev->irq = 11; break;
+					case 7:	dev->irq = 12; break;
+					}
 				}
 			else if (dev->irq == 2)
 				dev->irq = 9;
@@ -432,7 +486,7 @@
 				}
 			}
 			else printk(", %s.\n", ifmap[dev->if_port]);
-			
+
 			if ((dev->mem_start & 0xf) > 0)	/* I don't know if this is */
 				net_debug = dev->mem_start & 7; /* still useful or not */
 
@@ -486,9 +540,12 @@
    */
 
 static char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};
-static int	eepro_grab_irq(struct device *dev)
+static char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};
+
+static int	
+eepro_grab_irq(struct device *dev)
 {
-	int irqlist[] = { 5, 9, 10, 11, 4, 3, 0};	
+	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 */
@@ -496,32 +553,28 @@
 	/* Enable the interrupt line. */
 	temp_reg = inb(ioaddr + REG1);
 	outb(temp_reg | INT_ENABLE, ioaddr + REG1); 
-	
+
 	outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */
 
 	/* clear all interrupts */
 	outb(ALL_MASK, ioaddr + STATUS_REG); 
+
 	/* Let EXEC event to interrupt */
 	outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG); 
 
 	do {
 		outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
-
 		temp_reg = inb(ioaddr + INT_NO_REG);
 		outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG); 
-
 		outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
-
 		if (request_irq (*irqp, NULL, 0, "bogus", NULL) != EBUSY) {
 			/* Twinkle the interrupt, and check if it's seen */
 			autoirq_setup(0);
-
 			outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */
 				
 			if (*irqp == autoirq_report(2) &&  /* It's a good IRQ line */
 				(request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", NULL) == 0)) 
 					break;
-
 			/* clear all interrupts */
 			outb(ALL_MASK, ioaddr + STATUS_REG); 
 		}
@@ -532,7 +585,6 @@
 	/* Disable the physical interrupt line. */
 	temp_reg = inb(ioaddr + REG1);
 	outb(temp_reg & 0x7f, ioaddr + REG1); 
-
 	outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
 
 	/* Mask all the interrupts. */
@@ -554,10 +606,27 @@
 	if (net_debug > 3)
 		printk("eepro: entering eepro_open routine.\n");
 
-	if (dev->dev_addr[0] == SA_ADDR0 &&
+	if ((dev->dev_addr[0] == SA_ADDR0 &&
 			dev->dev_addr[1] == SA_ADDR1 &&
-			dev->dev_addr[2] == SA_ADDR2)
-		lp->eepro = 1; /* Yes, an Intel EtherExpress Pro/10 */
+			dev->dev_addr[2] == SA_ADDR2)&&
+			(dev->dev_addr[3] != SA3_ADDR3))
+		{ 
+			lp->eepro = 1;
+			if (net_debug > 3) printk("p->eepro = 1;\n"); 
+		}  /* Yes, an Intel EtherExpress Pro/10 */
+
+	else if ((dev->dev_addr[0] == SA2_ADDR0 &&
+			dev->dev_addr[1] == SA2_ADDR1 &&
+			dev->dev_addr[2] == SA2_ADDR2)||
+		(dev->dev_addr[0] == SA3_ADDR0 &&
+			dev->dev_addr[1] == SA3_ADDR1 &&
+			dev->dev_addr[2] == SA3_ADDR2 &&
+			dev->dev_addr[3] == SA3_ADDR3))
+		{
+		  	lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
+		  	if (net_debug > 3) printk("p->eepro = 2;\n"); 
+		}
+       
 	else lp->eepro = 0; /* No, it is a generic 82585 lan card */
 
 	/* Get the interrupt vector for the 82595 */	
@@ -571,15 +640,12 @@
 		return -EAGAIN;
 
 	/* Initialize the 82595. */
-
 	outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 	temp_reg = inb(ioaddr + EEPROM_REG);
-
 	lp->stepping = temp_reg >> 5;	/* Get the stepping number of the 595 */
 	
 	if (net_debug > 3)
 		printk("The stepping of the 82595 is %d\n", lp->stepping);
-
 	if (temp_reg & 0x10) /* Check the TurnOff Enable bit */
 		outb(temp_reg & 0xef, ioaddr + EEPROM_REG);
 	for (i=0; i < 6; i++) 
@@ -588,19 +654,31 @@
 	temp_reg = inb(ioaddr + REG1);    /* Setup Transmit Chaining */
 	outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */
 		| RCV_Discard_BadFrame, ioaddr + REG1);  
-
 	temp_reg = inb(ioaddr + REG2); /* Match broadcast */
 	outb(temp_reg | 0x14, ioaddr + REG2);
-
 	temp_reg = inb(ioaddr + REG3);
 	outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */
 
 	/* Set the receiving mode */
 	outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
+
+	/* Set the interrupt vector */	
+	temp_reg = inb(ioaddr + INT_NO_REG);
 	
+	if (lp->eepro == 2)
+		outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG); 
+	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); 
+    
 	temp_reg = inb(ioaddr + INT_NO_REG);
-	outb((temp_reg & 0xf8) | irqrmap[dev->irq], 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("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); 
 	outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); 
@@ -610,25 +688,26 @@
 	/* Enable the interrupt line. */
 	temp_reg = inb(ioaddr + REG1);
 	outb(temp_reg | INT_ENABLE, ioaddr + REG1); 
-
 	outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
-
+	
 	/* 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); 
-
+	
 	/* Initialize RCV */
 	outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR); 
 	lp->rx_start = (RCV_LOWER_LIMIT << 8) ;
 	outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP); 
-
+	
 	/* Initialize XMT */
 	outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR); 
-
+	
 	/* 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("i82595 detected!\n");
@@ -639,45 +718,55 @@
 		outb(old8, ioaddr + 8);
 		old9 = inb(ioaddr + 9);
 		outb(~old9, ioaddr + 9);
-		if ((temp_reg = inb(ioaddr + 9)) == ~old9) {
+	
+		if (((temp_reg = inb(ioaddr + 9)) == ( (~old9)&0xff) )) {
 			enum iftype { AUI=0, BNC=1, TPE=2 };
-			if (net_debug > 3)
+	
+			if (net_debug > 3) {
+			        printk("temp_reg: %#x  ~old9: %#x\n",temp_reg, ~old9);
 				printk("i82595FX detected!\n");
+			}
+	
 			lp->version = LAN595FX;
 			outb(old9, ioaddr + 9);
+	
 			if (dev->if_port != TPE) {	/* Hopefully, this will fix the
 							problem of using Pentiums and
 							pro/10 w/ BNC. */
 				outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 				temp_reg = inb(ioaddr + REG13);
+	
 				/* disable the full duplex mode since it is not
 				applicable with the 10Base2 cable. */
 				outb(temp_reg & ~(FDX | A_N_ENABLE), REG13);
 				outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */
 			}
 		}
-		else if (net_debug > 3)
+		else if (net_debug > 3) {
+		        printk("temp_reg: %#x  ~old9: %#x\n",temp_reg,((~old9)&0xff));
 			printk("i82595TX detected!\n");
+		}
 	}
 	
 	outb(SEL_RESET_CMD, ioaddr);
+	
 	/* We are supposed to wait for 2 us after a SEL_RESET */
 	SLOW_DOWN_IO;
 	SLOW_DOWN_IO;	
-
+	
 	lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
 	lp->tx_last = 0;  
 	
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
-
+	
 	if (net_debug > 3)
 		printk("eepro: exiting eepro_open routine.\n");
-
+	
 	outb(RCV_ENABLE_CMD, ioaddr);
-
 	MOD_INC_USE_COUNT;
+	
 	return 0;
 }
 
@@ -694,64 +783,68 @@
 	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");
+	
 		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_IO;
 		SLOW_DOWN_IO;
-
+	
 		/* 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 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;
 	}
-
+	
 	/* Block a timer-based transmit from overlapping. */
+	
 	if (set_bit(0, (void*)&dev->tbusy) != 0)
 		printk("%s: Transmitter access conflict.\n", dev->name);
 	else {
 		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 		unsigned char *buf = skb->data;
-
 		hardware_send_packet(dev, buf, length);
 		dev->trans_start = jiffies;
 	}
-
+	
 	dev_kfree_skb (skb, FREE_WRITE);
-
+	
 	/* You might need to clean up and record Tx statistics here. */
 	/* lp->stats.tx_aborted_errors++; */
-
+	
 	if (net_debug > 5)
 		printk("eepro: exiting eepro_send_packet routine.\n");
 	
 	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)
 {
@@ -765,38 +858,35 @@
 		printk ("eepro_interrupt(): irq %d for unknown device.\n", irq);
 		return;
 	}
+	
 	dev->interrupt = 1;
 	
 	ioaddr = dev->base_addr;
-
+	
 	do { 
 		status = inb(ioaddr + STATUS_REG);
 		
 		if (status & RX_INT) {
 			if (net_debug > 4)
 				printk("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("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);
 		}
 	
 	} while ((boguscount-- > 0) && (status & 0x06));
-
+	
 	dev->interrupt = 0;
+		
 	if (net_debug > 5)
 		printk("eepro: exiting eepro_interrupt routine.\n");
 	
@@ -813,41 +903,39 @@
 
 	dev->tbusy = 1;
 	dev->start = 0;
-
+	
 	outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */
-
+	
 	/* Disable the physical interrupt line. */
 	temp_reg = inb(ioaddr + REG1);
 	outb(temp_reg & 0x7f, ioaddr + REG1); 
-
 	outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
-
+	
 	/* Flush the Tx and disable Rx. */
 	outb(STOP_RCV_CMD, ioaddr); 
+	
 	lp->tx_start = lp->tx_end = rcv_ram ;
 	lp->tx_last = 0;  
-
+	
 	/* Mask all the interrupts. */
 	outb(ALL_MASK, ioaddr + INT_MASK_REG); 
-
+	
 	/* clear all interrupts */
 	outb(ALL_MASK, ioaddr + STATUS_REG); 
-
+	
 	/* Reset the 82595 */
 	outb(RESET_CMD, ioaddr); 
-
+	
 	/* release the interrupt */
 	free_irq(dev->irq, NULL);
-
 	irq2dev_map[dev->irq] = 0;
-
+	
 	/* Update the statistics here. What statistics? */
-
 	/* We are supposed to wait for 200 us after a RESET */
 	SLOW_DOWN_IO;
 	SLOW_DOWN_IO; /* May not be enough? */
-
 	MOD_DEC_USE_COUNT;
+	
 	return 0;
 }
 
@@ -857,12 +945,12 @@
 eepro_get_stats(struct device *dev)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
-
 	return &lp->stats;
 }
 
 /* Set or clear the multicast filter for this adaptor.
  */
+
 static void
 set_multicast_list(struct device *dev)
 {
@@ -870,7 +958,7 @@
 	short ioaddr = dev->base_addr;
 	unsigned short mode;
 	struct dev_mc_list *dmi=dev->mc_list;
-
+	
 	if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63) 
 	{
 		/*
@@ -880,7 +968,6 @@
 		 *	flag is already set. If not we assert it.
 		 */
 		dev->flags|=IFF_PROMISC;		
-
 		outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 		mode = inb(ioaddr + REG2);
 		outb(mode | PRMSC_Mode, ioaddr + REG2);	
@@ -889,6 +976,7 @@
 		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 */
@@ -898,6 +986,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;
@@ -907,7 +996,6 @@
 		   corruption of the HOST_ADDRESS_REG by interrupt
 		   service routines. */
 		outb(ALL_MASK, ioaddr + INT_MASK_REG);
-
 		outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 		mode = inb(ioaddr + REG2);
 		outb(mode | Multi_IA, ioaddr + REG2);	
@@ -919,6 +1007,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;
@@ -927,15 +1016,17 @@
 			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);
 		outw(eaddrs[2], ioaddr + IO_PORT);
 		outw(lp->tx_end, ioaddr + XMT_BAR);
 		outb(MC_SETUP, ioaddr);
-
+	
 		/* 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 
@@ -950,15 +1041,17 @@
 		else {
 			lp->tx_start = lp->tx_end = i ;
 		}
-
+	
 		/* Acknowledge that the MC setup is done */
 		do { /* We should be doing this in the eepro_interrupt()! */
 			SLOW_DOWN_IO;
 			SLOW_DOWN_IO;
+	
 			if (inb(ioaddr + STATUS_REG) & 0x08) 
 			{
 				i = inb(ioaddr);
 				outb(0x08, ioaddr + STATUS_REG);
+	
 				if (i & 0x20) { /* command ABORTed */
 					printk("%s: multicast setup failed.\n", 
 						dev->name);
@@ -970,7 +1063,7 @@
 				}
 			}
 		} while (++boguscount < 100);
-
+	
 		/* Re-enable RX and TX interrupts */
 		outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
 	
@@ -980,8 +1073,8 @@
 
 /* The horrible routine to read a word from the serial EEPROM. */
 /* 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_IO; }}
 #define EE_READ_CMD (6 << 6)
 
@@ -1014,7 +1107,6 @@
 		retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
 		outb(ctrl_val, ee_addr);  eeprom_delay();
 	}
-
 	/* Terminate the EEPROM access. */
 	ctrl_val &= ~EECS;
 	outb(ctrl_val | EESK, ee_addr);
@@ -1035,47 +1127,47 @@
 
 	if (net_debug > 5)
 		printk("eepro: entering hardware_send_packet routine.\n");
-
+	
 	while (boguscount-- > 0) {
-
+	
 		/* Disable RX and TX interrupts.  Necessary to avoid
 	   	corruption of the HOST_ADDRESS_REG by interrupt
 	   	service routines. */
 		outb(ALL_MASK, ioaddr + INT_MASK_REG);
-
+	
 		if (dev->interrupt == 1) {  
 			/* Enable RX and TX interrupts */
 			outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
 			continue;
 		}
-
+	
 		/* determine how much of the transmit buffer space is available */
 		if (lp->tx_end > lp->tx_start)
 			tx_available = XMT_RAM - (lp->tx_end - lp->tx_start);
 		else if (lp->tx_end < lp->tx_start)
 			tx_available = lp->tx_start - lp->tx_end;
 		else tx_available = XMT_RAM;
-
+	
 		if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) 
 			>= tx_available)   /* No space available ??? */
 			{
 			eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */
-
 			/* Enable RX and TX interrupts */
 			outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
 			continue;
 		}
-
+	
 		last = lp->tx_end;
 		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. */
 				last = rcv_ram;
 				end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
 			}	
+
 			else end = rcv_ram + (end - RAM_SIZE);
 		}
 
@@ -1084,19 +1176,20 @@
 		outw(0, ioaddr + IO_PORT);
 		outw(end, ioaddr + IO_PORT);
 		outw(length, ioaddr + IO_PORT);
-
+	
 		if (lp->version == LAN595)
 			outsw(ioaddr + IO_PORT, buf, (length + 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);
 			outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2);
 			outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
 		}
-
+	
 		/* A dummy read to flush the DRAM write pipeline */
 		status = inw(ioaddr + IO_PORT); 
-
+	
 		if (lp->tx_start == lp->tx_end) {	
 			outw(last, ioaddr + XMT_BAR);
 			outb(XMT_CMD, ioaddr);
@@ -1105,34 +1198,36 @@
 		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);
-
+	
 			/* Continue the transmit command */
 			outb(RESUME_XMT_CMD, ioaddr);
 		}
-
 		lp->tx_last = last;
 		lp->tx_end = end;
-
+	
 		/* Enable RX and TX interrupts */
 		outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
 	
 		if (dev->tbusy) {
 			dev->tbusy = 0;
 		}
-
+	
 		if (net_debug > 5)
 			printk("eepro: exiting hardware_send_packet routine.\n");
+	
 		return;
 	}
-
 	dev->tbusy = 1;
+	
 	if (net_debug > 5)
 		printk("eepro: exiting hardware_send_packet routine.\n");
 }
@@ -1151,68 +1246,78 @@
 	
 	/* 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_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);
-
 	} 
 	if (rcv_car == 0)
 		rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+	
 	outw(rcv_car - 1, ioaddr + RCV_STOP);
-
+	
 	if (net_debug > 5)
 		printk("eepro: exiting eepro_rx routine.\n");
 }
@@ -1226,17 +1331,17 @@
 	short xmt_status;
 
 	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 {
@@ -1246,41 +1351,45 @@
 			printk("%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
+
 static char devicename[9] = { 0, };
 static struct device dev_eepro = {
 	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
 	0, 0,
 	0, 0, 0, NULL, eepro_probe };
-
 static int io = 0x200;
 static int irq = 0;
 static int mem = (RCV_RAM/1024);	/* Size of the rx buffer in KB */
 
-int
+int 
 init_module(void)
 {
 	if (io == 0)
 		printk("eepro: You should not use auto-probing with insmod!\n");
+
 	dev_eepro.base_addr = io;
 	dev_eepro.irq       = irq;
 	dev_eepro.mem_end   = mem;
 
 	if (register_netdev(&dev_eepro) != 0)
 		return -EIO;
+
 	return 0;
 }
 
@@ -1288,6 +1397,7 @@
 cleanup_module(void)
 {
 	unregister_netdev(&dev_eepro);
+
 	kfree_s(dev_eepro.priv,sizeof(struct eepro_local));
 	dev_eepro.priv=NULL;
 

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