patch-2.1.126 linux/drivers/net/eth16i.c

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

diff -u --recursive --new-file v2.1.125/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
@@ -1,122 +1,207 @@
 /* eth16i.c An ICL EtherTeam 16i and 32 EISA ethernet driver for Linux
-
-   Written 1994-95 by Mika Kuoppala
-
-   Copyright (C) 1994, 1995 by Mika Kuoppala
-   Based on skeleton.c and at1700.c by Donald Becker
+   
+   Written 1994-1998 by Mika Kuoppala
+   
+   Copyright (C) 1994-1998 by Mika Kuoppala
+   Based on skeleton.c and heavily on at1700.c by Donald Becker
 
    This software may be used and distributed according to the terms
    of the GNU Public Licence, incorporated herein by reference.
 
-   The author may be reached as miku@elt.icl.fi
+   The author may be reached as miku@iki.fi
 
    This driver supports following cards :
 	- ICL EtherTeam 16i
-	- ICL EtherTeam 32 EISA
+	- ICL EtherTeam 32 EISA 
+	  (Uses true 32 bit transfers rather than 16i compability mode)
+
+   Example Module usage:
+        insmod eth16i.o ioaddr=0x2a0 mediatype=bnc
+
+	mediatype can be one of the following: bnc,tp,dix,auto,eprom
 
+	'auto' will try to autoprobe mediatype.
+	'eprom' will use whatever type defined in eprom.
+
+   I have benchmarked driver with PII/300Mhz as a ftp client
+   and 486/33Mhz as a ftp server. Top speed was 1128.37 kilobytes/sec.
+   
    Sources:
      - skeleton.c  a sample network driver core for linux,
        written by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
-     - at1700.c a driver for Allied Telesis AT1700, written
+     - at1700.c a driver for Allied Telesis AT1700, written 
        by Donald Becker.
      - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i
        written by Markku Viima
      - The Fujitsu MB86965 databook.
-
-   Valuable assistance from:
-	Markku Viima (ICL)
-	Ari Valve (ICL)
+   
+   Author thanks following persons due to their valueble assistance:    
+        Markku Viima (ICL)
+	Ari Valve (ICL)      
+	Donald Becker
+	Kurt Huwig <kurt@huwig.de>
 
    Revision history:
 
    Version	Date		Description
-
-   0.01		15.12-94	Initial version (card detection)
+   
+   0.01         15.12-94        Initial version (card detection)
    0.02         23.01-95        Interrupt is now hooked correctly
    0.03         01.02-95        Rewrote initialization part
    0.04         07.02-95        Base skeleton done...
-				Made a few changes to signature checking
-				to make it a bit reliable.
-				- fixed bug in tx_buf mapping
-				- fixed bug in initialization (DLC_EN
-				  wasn't enabled when initialization
-				  was done.)
-   0.05		08.02-95	If there were more than one packet to send,
-				transmit was jammed due to invalid
-				register write...now fixed
-   0.06         19.02-95        Rewrote interrupt handling
+                                Made a few changes to signature checking
+                                to make it a bit reliable.
+                                - fixed bug in tx_buf mapping
+                                - fixed bug in initialization (DLC_EN
+                                  wasn't enabled when initialization
+                                  was done.)
+   0.05         08.02-95        If there were more than one packet to send,
+                                transmit was jammed due to invalid
+                                register write...now fixed
+   0.06         19.02-95        Rewrote interrupt handling        
    0.07         13.04-95        Wrote EEPROM read routines
                                 Card configuration now set according to
-				data read from EEPROM
+                                data read from EEPROM
    0.08         23.06-95        Wrote part that tries to probe used interface
                                 port if AUTO is selected
 
-   0.09         01.09-95	Added module support
-
-   0.10         04.09-95	Fixed receive packet allocation to work
-        			with kernels > 1.3.x
+   0.09         01.09-95        Added module support
+   
+   0.10         04.09-95        Fixed receive packet allocation to work
+                                with kernels > 1.3.x
+      
+   0.20		20.09-95	Added support for EtherTeam32 EISA	
 
-   0.20		20.09-95	Added support for EtherTeam32 EISA
-
-   0.21         17.10-95        Removed the unnecessary extern
+   0.21         17.10-95        Removed the unnecessary extern 
 				init_etherdev() declaration. Some
 				other cleanups.
+   				
+   0.22		22.02-96	Receive buffer was not flushed
+				correctly when faulty packet was
+				received. Now fixed.
+
+   0.23		26.02-96	Made resetting the adapter	
+			 	more reliable.
+   
+   0.24		27.02-96	Rewrote faulty packet handling in eth16i_rx
+
+   0.25		22.05-96	kfree() was missing from cleanup_module.
+
+   0.26		11.06-96	Sometimes card was not found by 
+				check_signature(). Now made more reliable.
+   
+   0.27		23.06-96	Oops. 16 consecutive collisions halted 
+				adapter. Now will try to retransmit 
+				MAX_COL_16 times before finally giving up.
+   
+   0.28	        28.10-97	Added dev_id parameter (NULL) for free_irq
+
+   0.29         29.10-97        Multiple card support for module users
+
+   0.30         30.10-97        Fixed irq allocation bug.
+                                (request_irq moved from probe to open)
+
+   0.30a        21.08-98        Card detection made more relaxed. Driver
+                                had problems with some TCP/IP-PROM boots
+				to find the card. Suggested by 
+				Kurt Huwig <kurt@huwig.de>
+
+   0.31         28.08-98        Media interface port can now be selected
+                                with module parameters or kernel
+				boot parameters. 
+
+   0.32         31.08-98        IRQ was never freed if open/close 
+                                pair wasn't called. Now fixed.
+   
+   0.33         10.09-98        When eth16i_open() was called after
+                                eth16i_close() chip never recovered.
+				Now more shallow reset is made on
+				close.
+
    Bugs:
-	In some cases the interface autoprobing code doesn't find
-	the correct interface type. In this case you can
-	manually choose the interface type in DOS with E16IC.EXE which is
+	In some cases the media interface autoprobing code doesn't find 
+	the correct interface type. In this case you can 
+	manually choose the interface type in DOS with E16IC.EXE which is 
 	configuration software for EtherTeam16i and EtherTeam32 cards.
+	This is also true for IRQ setting. You cannot use module
+	parameter to configure IRQ of the card (yet). 
 
    To do:
 	- Real multicast support
+	- Rewrite the media interface autoprobing code. Its _horrible_ !
+	- Possibly merge all the MB86965 specific code to external
+	  module for use by eth16.c and Donald's at1700.c
+	- IRQ configuration with module parameter. I will do
+	  this when i will get enough info about setting
+	  irq without configuration utility.
 */
 
-static char *version =
-	"eth16i.c: v0.21 17-10-95 Mika Kuoppala (miku@elt.icl.fi)\n";
+static char *version = 
+    "eth16i.c: v0.33 10-09-98 Mika Kuoppala (miku@iki.fi)\n";
 
 #include <linux/module.h>
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
+#include <linux/types.h>		  
+#include <linux/fcntl.h>		  
+#include <linux/interrupt.h>		  
+#include <linux/ptrace.h>		  
+#include <linux/ioport.h>		  
+#include <linux/in.h>		  
+#include <linux/malloc.h>		  
+#include <linux/string.h>		  
 #include <linux/errno.h>
-#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
+#include <asm/system.h>		  
+#include <asm/bitops.h>		  
+#include <asm/io.h>		  
 #include <asm/dma.h>
-#include <asm/delay.h>
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#if LINUX_VERSION_CODE >= 0x20123
+#include <linux/init.h>
+#else
+#define __init
+#define __initdata
+#define __initfunc(x) x
+#endif
+
+#if LINUX_VERSION_CODE < 0x20138
+#define test_and_set_bit(val,addr) set_bit(val,addr)
+#endif
+
+#if LINUX_VERSION_CODE < 0x020100
+typedef struct enet_statistics eth16i_stats_type;
+#else
+typedef struct net_device_stats eth16i_stats_type;
+#endif
 
 /* Few macros */
-#define BIT(a)		        ( (1 << (a)) )
-#define BITSET(ioaddr, bnum)   ((outb(((inb(ioaddr)) | (bnum)), ioaddr)))
+#define BIT(a)		       ( (1 << (a)) )  
+#define BITSET(ioaddr, bnum)   ((outb(((inb(ioaddr)) | (bnum)), ioaddr))) 
 #define BITCLR(ioaddr, bnum)   ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr)))
 
 /* This is the I/O address space for Etherteam 16i adapter. */
-#define ETH16I_IO_EXTENT 32
+#define ETH16I_IO_EXTENT       32
 
 /* Ticks before deciding that transmit has timed out */
-#define TIMEOUT_TICKS          30
+#define TX_TIMEOUT             (400*HZ/1000)
 
 /* Maximum loop count when receiving packets */
-#define MAX_RX_LOOP            40
+#define MAX_RX_LOOP            20
 
 /* Some interrupt masks */
-#define ETH16I_INTR_ON	       0x8f82
+#define ETH16I_INTR_ON	       0xef8a       /* Higher is receive mask */
 #define ETH16I_INTR_OFF	       0x0000
-
+	 
 /* Buffers header status byte meanings */
 #define PKT_GOOD               BIT(5)
 #define PKT_GOOD_RMT           BIT(4)
@@ -131,6 +216,7 @@
 #define NET_BUSY               BIT(6)
 #define TX_PKT_RCD             BIT(5)
 #define CR_LOST                BIT(4)
+#define TX_JABBER_ERR	       BIT(3)
 #define COLLISION              BIT(2)
 #define COLLISIONS_16          BIT(1)
 
@@ -142,7 +228,7 @@
 #define ALIGN_ERR              BIT(2)
 #define CRC_ERR                BIT(1)
 #define RX_BUF_OVERFLOW        BIT(0)
-
+              
 /* Transmit Interrupt Enable Register (DLCR2) */
 #define TX_INTR_REG            2
 #define TX_INTR_DONE           BIT(7)
@@ -181,18 +267,18 @@
 #define SRAM_CYCLE_TIME_100NS  BIT(6)
 #define SYSTEM_BUS_WIDTH_8     BIT(5)       /* 1 = 8bit, 0 = 16bit */
 #define BUFFER_WIDTH_8         BIT(4)       /* 1 = 8bit, 0 = 16bit */
-#define TBS1                   BIT(3)
+#define TBS1                   BIT(3)       
 #define TBS0                   BIT(2)
-#define MBS1                   BIT(1)       /* 00=8kb,  01=16kb  */
-#define MBS0                   BIT(0)       /* 10=32kb, 11=64kb  */
+#define SRAM_BS1               BIT(1)       /* 00=8kb,  01=16kb  */
+#define SRAM_BS0               BIT(0)       /* 10=32kb, 11=64kb  */
 
-#ifndef ETH16I_TX_BUF_SIZE                   /* 0 = 2kb, 1 = 4kb  */
-#define ETH16I_TX_BUF_SIZE     2             /* 2 = 8kb, 3 = 16kb */
-#endif
-#define TX_BUF_1x2048            0
-#define TX_BUF_2x2048            1
-#define TX_BUF_2x4098            2
-#define TX_BUF_2x8192            3
+#ifndef ETH16I_TX_BUF_SIZE                   /* 0 = 2kb, 1 = 4kb  */ 
+#define ETH16I_TX_BUF_SIZE     3             /* 2 = 8kb, 3 = 16kb */
+#endif                                      
+#define TX_BUF_1x2048          0
+#define TX_BUF_2x2048          1
+#define TX_BUF_2x4098          2
+#define TX_BUF_2x8192          3
 
 /* Configuration Register 1 (DLCR7) */
 #define CONFIG_REG_1           7
@@ -212,18 +298,21 @@
 #define HASH_TABLE_RB          1
 
 /* Buffer memory ports */
-#define BUFFER_MEM_PORT_LB    8
-#define DATAPORT              BUFFER_MEM_PORT_LB
-#define BUFFER_MEM_PORT_HB    9
+#define BUFFER_MEM_PORT_LB     8
+#define DATAPORT               BUFFER_MEM_PORT_LB
+#define BUFFER_MEM_PORT_HB     9
 
 /* 16 Collision control register (BMPR11) */
 #define COL_16_REG             11
 #define HALT_ON_16             0x00
 #define RETRANS_AND_HALT_ON_16 0x02
 
+/* Maximum number of attempts to send after 16 concecutive collisions */
+#define MAX_COL_16	       10
+
 /* DMA Burst and Transceiver Mode Register (BMPR13) */
 #define TRANSCEIVER_MODE_REG   13
-#define TRANSCEIVER_MODE_RB    2
+#define TRANSCEIVER_MODE_RB    2         
 #define IO_BASE_UNLOCK	       BIT(7)
 #define LOWER_SQUELCH_TRESH    BIT(6)
 #define LINK_TEST_DISABLE      BIT(5)
@@ -232,9 +321,8 @@
 
 /* Filter Self Receive Register (BMPR14)  */
 #define FILTER_SELF_RX_REG     14
-#define SKIP_RECEIVE_PACKET    BIT(2)
+#define SKIP_RX_PACKET         BIT(2)
 #define FILTER_SELF_RECEIVE    BIT(0)
-#define RX_BUF_SKIP_PACKET     SKIP_RECEIVE_PACKET | FILTER_SELF_RECEIVE
 
 /* EEPROM Control Register (BMPR 16) */
 #define EEPROM_CTRL_REG        16
@@ -254,19 +342,20 @@
 #define EEPROM_READ            0x80
 
 /* NMC93CSx6 EEPROM Addresses */
-#define E_NODEID_0                     0x02
-#define E_NODEID_1                     0x03
-#define E_NODEID_2                     0x04
-#define E_PORT_SELECT                  0x14
-  #define E_PORT_BNC                   0
-  #define E_PORT_DIX                   1
-  #define E_PORT_TP                    2
-  #define E_PORT_AUTO                  3
-#define E_PRODUCT_CFG                  0x30
-
+#define E_NODEID_0             0x02
+#define E_NODEID_1             0x03
+#define E_NODEID_2             0x04
+#define E_PORT_SELECT          0x14
+  #define E_PORT_BNC           0x00
+  #define E_PORT_DIX           0x01
+  #define E_PORT_TP            0x02
+  #define E_PORT_AUTO          0x03
+  #define E_PORT_FROM_EPROM    0x04
+#define E_PRODUCT_CFG          0x30
+ 
 
 /* Macro to slow down io between EEPROM clock transitions */
-#define eeprom_slow_io() 	udelay(100)	/* FIXME: smaller but right value here */
+#define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { inb(0x80); }}while(0)
 
 /* Jumperless Configuration Register (BMPR19) */
 #define JUMPERLESS_CONFIG      19
@@ -277,31 +366,24 @@
 #define RESET                  ID_ROM_0
 
 /* This is the I/O address list to be probed when seeking the card */
-static unsigned int eth16i_portlist[] __initdata = {
-	0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
-};
+static unsigned int eth16i_portlist[] =
+   { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 };
 
-static unsigned int eth32i_portlist[] __initdata = {
-	0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
-	0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0
-};
+static unsigned int eth32i_portlist[] =
+   { 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
+     0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 };
 
 /* This is the Interrupt lookup table for Eth16i card */
-static unsigned int eth16i_irqmap[] __initdata = {
-	9, 10, 5, 15
-};
+static unsigned int eth16i_irqmap[] = { 9, 10, 5, 15, 0 };
+#define NUM_OF_ISA_IRQS    4
 
 /* This is the Interrupt lookup table for Eth32i card */
-static unsigned int eth32i_irqmap[] __initdata = {
-	3, 5, 7, 9, 10, 11, 12, 15
-};
-
+static unsigned int eth32i_irqmap[] = { 3, 5, 7, 9, 10, 11, 12, 15, 0 };  
 #define EISA_IRQ_REG	0xc89
+#define NUM_OF_EISA_IRQS   8
 
-static unsigned int eth16i_tx_buf_map[] = {
-	2048, 2048, 4096, 8192 
-};
-unsigned int boot = 1;
+static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 };
+static unsigned int boot = 1;
 
 /* Use 0 for production, 1 for verification, >2 for debug */
 #ifndef ETH16I_DEBUG
@@ -310,60 +392,76 @@
 static unsigned int eth16i_debug = ETH16I_DEBUG;
 
 /* Information for each board */
-struct eth16i_local
-{
-	struct net_device_stats stats;
-	unsigned int tx_started:1;
-	unsigned char tx_queue;	       /* Number of packets in transmit buffer */
-	unsigned short tx_queue_len;
-	unsigned int tx_buf_size;
-	unsigned long open_time;
+
+struct eth16i_local {
+	eth16i_stats_type stats;
+	unsigned char     tx_started;
+	unsigned char     tx_buf_busy;
+	unsigned short    tx_queue;  /* Number of packets in transmit buffer */
+	unsigned short    tx_queue_len;         
+	unsigned int      tx_buf_size;
+	unsigned long     open_time;
+	unsigned long     tx_buffered_packets;  
+	unsigned long     col_16;
 };
 
 /* Function prototypes */
 
-extern int eth16i_probe(struct device *dev);
+extern int     eth16i_probe(struct device *dev);
+
+static int     eth16i_probe1(struct device *dev, int ioaddr);
+static int     eth16i_check_signature(int ioaddr);
+static int     eth16i_probe_port(int ioaddr);
+static void    eth16i_set_port(int ioaddr, int porttype);
+static int     eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l);
+static int     eth16i_receive_probe_packet(int ioaddr);
+static int     eth16i_get_irq(int ioaddr);
+static int     eth16i_read_eeprom(int ioaddr, int offset);
+static int     eth16i_read_eeprom_word(int ioaddr);
+static void    eth16i_eeprom_cmd(int ioaddr, unsigned char command);
+static int     eth16i_open(struct device *dev);
+static int     eth16i_close(struct device *dev);
+static int     eth16i_tx(struct sk_buff *skb, struct device *dev);
+static void    eth16i_rx(struct device *dev);
+static void    eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void    eth16i_reset(struct device *dev);
+static void    eth16i_skip_packet(struct device *dev);
+static void    eth16i_multicast(struct device *dev); 
+static void    eth16i_select_regbank(unsigned char regbank, int ioaddr);
+static void    eth16i_initialize(struct device *dev);
+
+#if 0
+static int     eth16i_set_irq(struct device *dev);
+#endif
+
+#ifdef MODULE
+static ushort  eth16i_parse_mediatype(const char* s);
+#endif
 
-static int eth16i_probe1(struct device *dev, short ioaddr);
-static int eth16i_check_signature(short ioaddr);
-static int eth16i_probe_port(short ioaddr);
-static void eth16i_set_port(short ioaddr, int porttype);
-static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l);
-static int eth16i_receive_probe_packet(short ioaddr);
-static int eth16i_get_irq(short ioaddr);
-static int eth16i_read_eeprom(int ioaddr, int offset);
-static int eth16i_read_eeprom_word(int ioaddr);
-static void eth16i_eeprom_cmd(int ioaddr, unsigned char command);
-static int eth16i_open(struct device *dev);
-static int eth16i_close(struct device *dev);
-static int eth16i_tx(struct sk_buff *skb, struct device *dev);
-static void eth16i_rx(struct device *dev);
-static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void eth16i_multicast(struct device *dev);
-static void eth16i_select_regbank(unsigned char regbank, short ioaddr);
-static void eth16i_initialize(struct device *dev);
-static struct net_device_stats *eth16i_get_stats(struct device *dev);
+static struct enet_statistics *eth16i_get_stats(struct device *dev);
 
 static char *cardname = "ICL EtherTeam 16i/32";
 
-#ifdef HAVE_DEVLIST
+#ifdef HAVE_DEVLIST 
+
 /* Support for alternate probe manager */
-/struct netdev_entry eth16i_drv =
-   {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list};
+/struct netdev_entry eth16i_drv = 
+ {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list}; 
 
 #else  /* Not HAVE_DEVLIST */
+
 __initfunc(int eth16i_probe(struct device *dev))
 {
 	int i;
 	int ioaddr;
 	int base_addr = dev ? dev->base_addr : 0;
+    
+	if(eth16i_debug > 4) 
+		printk(KERN_DEBUG "Probing started for %s\n", cardname);
 
-	if(eth16i_debug > 4)
-		printk("Probing started for %s\n", cardname);
-
-	if(base_addr > 0x1ff)		/* Check only single location */
+	if(base_addr > 0x1ff)           /* Check only single location */
 		return eth16i_probe1(dev, base_addr);
-	else if(base_addr != 0)		/* Don't probe at all */
+	else if(base_addr != 0)         /* Don't probe at all */
 		return ENXIO;
 
 	/* Seek card from the ISA io address space */
@@ -377,88 +475,107 @@
 	/* Seek card from the EISA io address space */
 	for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) {
 		if(check_region(ioaddr, ETH16I_IO_EXTENT))
-	continue;
+			continue;
 		if(eth16i_probe1(dev, ioaddr) == 0)
-	return 0;
-	 }
+			return 0;
+	}
 
 	return ENODEV;
 }
-#endif	/* Not HAVE_DEVLIST */
+#endif  /* Not HAVE_DEVLIST */
 
-__initfunc(static int eth16i_probe1(struct device *dev, short ioaddr))
+__initfunc(static int eth16i_probe1(struct device *dev, int ioaddr))
 {
 	static unsigned version_printed = 0;
-	unsigned int irq = 0;
-	boot = 1;          /* To inform initialization that we are in boot probe */
+	boot = 1;  /* To inform initilization that we are in boot probe */
 
 	/*
-		 The MB86985 chip has on register which holds information in which
-		 io address the chip lies. First read this register and compare
-		 it to our current io address and if match then this could
-		 be our chip.
-	*/
+	  The MB86985 chip has on register which holds information in which 
+	  io address the chip lies. First read this register and compare
+	  it to our current io address and if match then this could
+	  be our chip.
+	  */
 
 	if(ioaddr < 0x1000) {
-		if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] != ioaddr)
+	
+		if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] 
+		   != ioaddr)
 			return -ENODEV;
 	}
 
 	/* Now we will go a bit deeper and try to find the chip's signature */
 
-	if(eth16i_check_signature(ioaddr) != 0) /* Can we find the signature here */
+	if(eth16i_check_signature(ioaddr) != 0) 
 		return -ENODEV;
 
-	/*
-		 Now it seems that we have found an ethernet chip in this particular
-		 ioaddr. The MB86985 chip has this feature, that when you read a
-		 certain register it will increase its io base address to next
-		 configurable slot. Now when we have found the chip, first thing is
-		 to make sure that the chip's ioaddr will hold still here.
-	*/
+	/* 
+	   Now it seems that we have found a ethernet chip in this particular
+	   ioaddr. The MB86985 chip has this feature, that when you read a 
+	   certain register it will increase it's io base address to next
+	   configurable slot. Now when we have found the chip, first thing is
+	   to make sure that the chip's ioaddr will hold still here.
+	   */
 
 	eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
 	outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
 
-	outb(0x00, ioaddr + RESET);             /* Will reset some parts of chip */
-	BITSET(ioaddr + CONFIG_REG_0, BIT(7));  /* This will disable the data link */
+	outb(0x00, ioaddr + RESET);             /* Reset some parts of chip */
+	BITSET(ioaddr + CONFIG_REG_0, BIT(7));  /* Disable the data link */
 
 	if(dev == NULL)
-		dev = init_etherdev(0, sizeof(struct eth16i_local));
+		dev = init_etherdev(0, 0);
 
 	if( (eth16i_debug & version_printed++) == 0)
-		printk(version);
+		printk(KERN_INFO "%s", version);
 
 	dev->base_addr = ioaddr;
+	
+#if 0
+	if(dev->irq) {
+		if(eth16i_set_irq(dev)) {
+			dev->irq = eth16i_get_irq(ioaddr);
+		}
+
+	}
+	else {
+#endif
 
-	irq = eth16i_get_irq(ioaddr);
-	dev->irq = irq;
+	dev->irq = eth16i_get_irq(ioaddr);
 
 	/* Try to obtain interrupt vector */
-	if(request_irq(dev->irq, &eth16i_interrupt, 0, "eth16i", dev)) {
-		printk("%s: %s at %#3x, but is unusable due
-		       conflict on IRQ %d.\n", dev->name, cardname, ioaddr, irq);
-		return EAGAIN;
+
+	if (request_irq(dev->irq, (void *)&eth16i_interrupt, 0, "eth16i", dev)) {	
+		printk(KERN_WARNING "%s: %s at %#3x, but is unusable due conflicting IRQ %d.\n", 
+		       dev->name, cardname, ioaddr, dev->irq);
+		return -EAGAIN;
 	}
 
-	printk("%s: %s at %#3x, IRQ %d, ",
-	 dev->name, cardname, ioaddr, dev->irq);
+#if 0
+	irq2dev_map[dev->irq] = dev;
+#endif
+
+	printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ",
+	       dev->name, cardname, ioaddr, dev->irq);
 
 	/* Let's grab the region */
 	request_region(ioaddr, ETH16I_IO_EXTENT, "eth16i");
 
 	/* Now we will have to lock the chip's io address */
 	eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
-	outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
+	outb(0x38, ioaddr + TRANSCEIVER_MODE_REG); 
 
-	eth16i_initialize(dev);	 /* Initialize rest of the chip's registers */
+	eth16i_initialize(dev);   /* Initialize rest of the chip's registers */
 
 	/* Now let's same some energy by shutting down the chip ;) */
 	BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
 
 	/* Initialize the device structure */
-	if(dev->priv == NULL)
+	if(dev->priv == NULL) {
 		dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL);
+		if(dev->priv == NULL)
+			return -ENOMEM;
+	}
+
 	memset(dev->priv, 0, sizeof(struct eth16i_local));
 
 	dev->open               = eth16i_open;
@@ -478,7 +595,7 @@
 
 static void eth16i_initialize(struct device *dev)
 {
-	short ioaddr = dev->base_addr;
+	int ioaddr = dev->base_addr;
 	int i, node_w = 0;
 	unsigned char node_byte = 0;
 
@@ -489,11 +606,9 @@
 		((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
 	}
 
-	for(i = 0; i < 6; i++) 
-	{
+	for(i = 0; i < 6; i++) { 
 		outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
-		if(boot) 
-		{
+		if(boot) {
 			printk("%02x", inb(ioaddr + NODE_ID_0 + i));
 			if(i != 5)
 				printk(":");
@@ -502,14 +617,14 @@
 
 	/* Now we will set multicast addresses to accept none */
 	eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
-	for(i = 0; i < 8; i++)
+	for(i = 0; i < 8; i++) 
 		outb(0x00, ioaddr + HASH_TABLE_0 + i);
 
 	/*
-		 Now let's disable the transmitter and receiver, set the buffer ram
-		 cycle time, bus width and buffer data path width. Also we shall
-		 set transmit buffer size and total buffer size.
-	*/
+	  Now let's disable the transmitter and receiver, set the buffer ram 
+	  cycle time, bus width and buffer data path width. Also we shall
+	  set transmit buffer size and total buffer size.
+	  */
 
 	eth16i_select_regbank(2, ioaddr);
 
@@ -519,38 +634,56 @@
 	if( (node_w & 0xFF00) == 0x0800)
 		node_byte |= BUFFER_WIDTH_8;
 
-	node_byte |= MBS1;
+	node_byte |= SRAM_BS1;
 
 	if( (node_w & 0x00FF) == 64)
-		node_byte |= MBS0;
+		node_byte |= SRAM_BS0;
 
 	node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
 
 	outb(node_byte, ioaddr + CONFIG_REG_0);
 
 	/* We shall halt the transmitting, if 16 collisions are detected */
-	outb(RETRANS_AND_HALT_ON_16, ioaddr + COL_16_REG);
+	outb(HALT_ON_16, ioaddr + COL_16_REG);
 
-	if(boot) /* Now set port type */
-	{
-		char *porttype[] = {"BNC", "DIX", "TP", "AUTO"};
+#ifdef MODULE
+	/* if_port already set by init_module() */
+#else
+	dev->if_port = (dev->mem_start < E_PORT_FROM_EPROM) ? 
+		dev->mem_start : E_PORT_FROM_EPROM;
+#endif
 
-		ushort ptype = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
-		dev->if_port = (ptype & 0x00FF);
+	/* Set interface port type */
+	if(boot) {
+		char *porttype[] = {"BNC", "DIX", "TP", "AUTO", "FROM_EPROM" };
 
-		printk(" %s interface.\n", porttype[dev->if_port]);
+		switch(dev->if_port)
+		{
+
+		case E_PORT_FROM_EPROM:
+			dev->if_port = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
+			break;
+
+		case E_PORT_AUTO:
+			dev->if_port = eth16i_probe_port(ioaddr);
+			break;
+			
+		case E_PORT_BNC:
+		case E_PORT_TP:
+		case E_PORT_DIX:
+			break;
+		}
 
-		if(ptype == E_PORT_AUTO)
-			ptype = eth16i_probe_port(ioaddr);
+		printk(" %s interface.\n", porttype[dev->if_port]);
 
-		eth16i_set_port(ioaddr, ptype);
+		eth16i_set_port(ioaddr, dev->if_port);
 	}
 
 	/* Set Receive Mode to normal operation */
 	outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
 }
 
-static int eth16i_probe_port(short ioaddr)
+static int eth16i_probe_port(int ioaddr)
 {
 	int i;
 	int retcode;
@@ -579,136 +712,163 @@
 		eth16i_set_port(ioaddr, i);
 
 		if(eth16i_debug > 1)
-			printk("Set port number %d\n", i);
+			printk(KERN_DEBUG "Set port number %d\n", i);
 
 		retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
-		if(retcode == 0) 
-		{
+		if(retcode == 0) {
 			retcode = eth16i_receive_probe_packet(ioaddr);
-			if(retcode != -1) 
-			{
+			if(retcode != -1) {
 				if(eth16i_debug > 1)
-					printk("Eth16i interface port found at %d\n", i);
+					printk(KERN_DEBUG "Eth16i interface port found at %d\n", i);
 				return i;
 			}
 		}
 		else {
 			if(eth16i_debug > 1)
-				printk("TRANSMIT_DONE timeout\n");
+				printk(KERN_DEBUG "TRANSMIT_DONE timeout when probing interface port\n");
 		}
 	}
 
 	if( eth16i_debug > 1)
-		printk("Using default port\n");
+		printk(KERN_DEBUG "Using default port\n");
 
 	return E_PORT_BNC;
 }
 
-static void eth16i_set_port(short ioaddr, int porttype)
-{
+static void eth16i_set_port(int ioaddr, int porttype)
+{ 
 	unsigned short temp = 0;
 
 	eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
 	outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
 
 	temp |= DIS_AUTO_PORT_SEL;
-	switch(porttype) 
-	{
 
-		case E_PORT_BNC :
-			temp |= AUI_SELECT;
-			break;
+	switch(porttype) {
 
-		case E_PORT_TP :
-			break;
+	case E_PORT_BNC :
+		temp |= AUI_SELECT;
+		break;
+
+	case E_PORT_TP :
+		break;
+
+	case E_PORT_DIX :
+		temp |= AUI_SELECT;
+		BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
+		break;
+	}  
 
-		case E_PORT_DIX :
-			temp |= AUI_SELECT;
-			BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
-			break;
-	}
 	outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
 
 	if(eth16i_debug > 1) {
-		printk("TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
-		printk("TRANSCEIVER_MODE_REG = %x\n", inb(ioaddr+TRANSCEIVER_MODE_REG));
+		printk(KERN_DEBUG "TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
+		printk(KERN_DEBUG "TRANSCEIVER_MODE_REG = %x\n", 
+		       inb(ioaddr+TRANSCEIVER_MODE_REG));
 	}
 }
 
-static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l)
+static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l)
 {
 	int starttime;
 
 	outb(0xff, ioaddr + TX_STATUS_REG);
 
 	outw(l, ioaddr + DATAPORT);
-	outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);
+	outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);  
 
 	starttime = jiffies;
-	outb(TX_START | 1, ioaddr + TRANSMIT_START_REG);
+	outb(TX_START | 1, ioaddr + TRANSMIT_START_REG); 
 
-	while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) 
-		if( (jiffies - starttime) > TIMEOUT_TICKS)
-			break;
-	return(0);
+	while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
+		if( (jiffies - starttime) > TX_TIMEOUT) {
+			return -1;
+		}
+	}
+
+	return 0;
 }
 
-static int eth16i_receive_probe_packet(short ioaddr)
+static int eth16i_receive_probe_packet(int ioaddr)
 {
 	int starttime;
 
 	starttime = jiffies;
 
-	while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) 
-	{
-		if( (jiffies - starttime) > TIMEOUT_TICKS) 
-		{
+	while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
+		if( (jiffies - starttime) > TX_TIMEOUT) {
+
 			if(eth16i_debug > 1)
-				printk("Timeout occurred waiting transmit packet received\n");
+				printk(KERN_DEBUG "Timeout occured waiting transmit packet received\n");
 			starttime = jiffies;
-			while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) 
-			{
-				if( (jiffies - starttime) > TIMEOUT_TICKS) 
-				{
+			while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
+				if( (jiffies - starttime) > TX_TIMEOUT) {
 					if(eth16i_debug > 1)
-						printk("Timeout occurred waiting receive packet\n");
+						printk(KERN_DEBUG "Timeout occured waiting receive packet\n");
 					return -1;
 				}
 			}
 
 			if(eth16i_debug > 1)
-				printk("RECEIVE_PACKET\n");
+				printk(KERN_DEBUG "RECEIVE_PACKET\n");
 			return(0); /* Found receive packet */
 		}
 	}
 
 	if(eth16i_debug > 1) {
-		printk("TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
-		printk("RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
+		printk(KERN_DEBUG "TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
+		printk(KERN_DEBUG "RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
 	}
 
 	return(0); /* Return success */
 }
 
-static int eth16i_get_irq(short ioaddr)
+#if 0
+static int eth16i_set_irq(struct device* dev)
+{
+	const int ioaddr = dev->base_addr;
+	const int irq = dev->irq;
+	int i = 0;
+
+	if(ioaddr < 0x1000) {		
+		while(eth16i_irqmap[i] && eth16i_irqmap[i] != irq)
+			i++;
+	
+		if(i < NUM_OF_ISA_IRQS) {
+			u8 cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
+			cbyte = (cbyte & 0x3F) | (i << 6);
+			outb(cbyte, ioaddr + JUMPERLESS_CONFIG);
+			return 0;
+		}
+	}
+	else {
+		printk(KERN_NOTICE "%s: EISA Interrupt cannot be set. Use EISA Configuration utility.\n", dev->name);
+	}
+	
+	return -1;
+
+}
+#endif
+
+static int eth16i_get_irq(int ioaddr)
 {
 	unsigned char cbyte;
 
 	if( ioaddr < 0x1000) {
 		cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
-	return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
-	} else {	/* Oh..the card is EISA so method getting IRQ different */
-	unsigned short index = 0;
-	cbyte = inb(ioaddr + EISA_IRQ_REG);
-	while( (cbyte & 0x01) == 0) {
-		cbyte = cbyte >> 1;
-		index++;
-				}
-	return( eth32i_irqmap[ index ] );
+		return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
+	} else {  /* Oh..the card is EISA so method getting IRQ different */
+		unsigned short index = 0;
+		cbyte = inb(ioaddr + EISA_IRQ_REG);
+		while( (cbyte & 0x01) == 0) {
+			cbyte = cbyte >> 1;
+			index++;
+		}
+		return( eth32i_irqmap[ index ] );
 	}
 }
 
-static int eth16i_check_signature(short ioaddr)
+static int eth16i_check_signature(int ioaddr)
 {
 	int i;
 	unsigned char creg[4] = { 0 };
@@ -718,36 +878,37 @@
 		creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
 
 		if(eth16i_debug > 1)
-	printk("eth16i: read signature byte %x at %x\n", creg[i],
-				 ioaddr + TRANSMIT_MODE_REG + i);
+			printk("eth16i: read signature byte %x at %x\n", 
+			       creg[i],
+			       ioaddr + TRANSMIT_MODE_REG + i);
 	}
 
 	creg[0] &= 0x0F;      /* Mask collision cnr */
 	creg[2] &= 0x7F;      /* Mask DCLEN bit */
 
-#if 0
-/*
-	This was removed because the card was sometimes left to state
-  	from which it couldn't be find anymore. If there is need
-	to have a more strict check still this have to be fixed.
-*/
-	if( !( (creg[0] == 0x06) && (creg[1] == 0x41)) ) {
+#ifdef 0
+	/* 
+	   This was removed because the card was sometimes left to state
+	   from which it couldn't be find anymore. If there is need
+	   to more strict check still this have to be fixed.
+	   */
+	if( ! ((creg[0] == 0x06) && (creg[1] == 0x41)) ) {
 		if(creg[1] != 0x42)
 			return -1;
 	}
 #endif
 
-	if( !( (creg[2] == 0x36) && (creg[3] == 0xE0)) ) 
-	{
-		creg[2] &= 0x42;
+	if( !((creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
+		creg[2] &= 0x40;
 		creg[3] &= 0x03;
-
-		if( !( (creg[2] == 0x42) && (creg[3] == 0x00)) )
+		
+		if( !((creg[2] == 0x40) && (creg[3] == 0x00)) )
 			return -1;
 	}
-
+	
 	if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
 		return -1;
+	
 	if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
 		return -1;
 
@@ -763,20 +924,22 @@
 	data = eth16i_read_eeprom_word(ioaddr);
 	outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
 
-	return(data);
+	return(data);  
 }
 
 static int eth16i_read_eeprom_word(int ioaddr)
 {
 	int i;
 	int data = 0;
-
+     
 	for(i = 16; i > 0; i--) {
 		outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
 		eeprom_slow_io();
 		outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
 		eeprom_slow_io();
-		data = (data << 1) | ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
+		data = (data << 1) | 
+			((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
+		
 		eeprom_slow_io();
 	}
 
@@ -800,25 +963,26 @@
 		eeprom_slow_io();
 		outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
 		eeprom_slow_io();
-	}
+	} 
 }
 
 static int eth16i_open(struct device *dev)
 {
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 	int ioaddr = dev->base_addr;
-
+	
 	/* Powerup the chip */
 	outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
 
 	/* Initialize the chip */
-	eth16i_initialize(dev);
+	eth16i_initialize(dev);  
 
 	/* Set the transmit buffer size */
 	lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
 
-	if(eth16i_debug > 3)
-		printk("%s: transmit buffer size %d\n", dev->name, lp->tx_buf_size);
+	if(eth16i_debug > 0)
+		printk(KERN_DEBUG "%s: transmit buffer size %d\n", 
+		       dev->name, lp->tx_buf_size);
 
 	/* Now enable Transmitter and Receiver sections */
 	BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
@@ -832,15 +996,13 @@
 	lp->tx_queue_len = 0;
 
 	/* Turn on interrupts*/
-	outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+	outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);  
 
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
 
-#ifdef MODULE
 	MOD_INC_USE_COUNT;
-#endif
 
 	return 0;
 }
@@ -850,23 +1012,26 @@
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 	int ioaddr = dev->base_addr;
 
-	lp->open_time = 0;
+	eth16i_reset(dev);
+
+	/* Turn off interrupts*/
+	outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);  
 
-	dev->tbusy = 1;
 	dev->start = 0;
+	dev->tbusy = 1;
+
+	lp->open_time = 0;
 
 	/* Disable transmit and receive */
 	BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
 
 	/* Reset the chip */
-	outb(0xff, ioaddr + RESET);
+	/* outb(0xff, ioaddr + RESET); */
+	/* outw(0xffff, ioaddr + TX_STATUS_REG);    */
+	
+	outb(0x00, ioaddr + CONFIG_REG_1);
 
-	/* Save some energy by switching off power */
-	BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
-
-#ifdef MODULE
 	MOD_DEC_USE_COUNT;
-#endif
 
 	return 0;
 }
@@ -875,88 +1040,120 @@
 {
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 	int ioaddr = dev->base_addr;
+	int status = 0;
 
 	if(dev->tbusy) {
-		/*
-			 If we get here, some higher level has decided that we are broken.
-			 There should really be a "kick me" function call instead.
-		*/
+		
+		/* 
+		   If we get here, some higher level has decided that 
+		   we are broken. There should really be a "kick me" 
+		   function call instead. 
+		   */
 
 		int tickssofar = jiffies - dev->trans_start;
-		if(tickssofar < TIMEOUT_TICKS)	/* Let's not rush with our timeout, */
-			return 1;                     /* wait a couple of ticks first     */
+		if(tickssofar < TX_TIMEOUT)  
+			return 1;                     
 
-		printk("%s: transmit timed out with status %04x, %s ?\n", dev->name,
-		 inw(ioaddr + TX_STATUS_REG),
-		 (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
-		 "IRQ conflict" : "network cable problem");
+		outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
 
-		/* Let's dump all registers */
-		if(eth16i_debug > 0) {
-			printk("%s: timeout regs: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
-			 dev->name, inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2),
-			 inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5),
-			 inb(ioaddr + 6), inb(ioaddr + 7));
+		printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n", 
+		       dev->name,
+		       inw(ioaddr + TX_STATUS_REG), 
+		       (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ? 
+		       "IRQ conflict" : "network cable problem");
 
+		dev->trans_start = jiffies;
 
-			printk("lp->tx_queue = %d\n", lp->tx_queue);
-			printk("lp->tx_queue_len = %d\n", lp->tx_queue_len);
-			printk("lp->tx_started = %d\n", lp->tx_started);
+		/* Let's dump all registers */
+		if(eth16i_debug > 0) { 
+			printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+			       dev->name, inb(ioaddr + 0), 
+			       inb(ioaddr + 1), inb(ioaddr + 2), 
+			       inb(ioaddr + 3), inb(ioaddr + 4), 
+			       inb(ioaddr + 5),
+			       inb(ioaddr + 6), inb(ioaddr + 7));
+
+			printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
+			       dev->name, inb(ioaddr + TRANSMIT_START_REG),
+			       inb(ioaddr + COL_16_REG));
+
+			printk(KERN_DEBUG "lp->tx_queue = %d\n", lp->tx_queue);
+			printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
+			printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
 
 		}
 
 		lp->stats.tx_errors++;
 
-		/* Now let's try to restart the adaptor */
-
-		BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-		outw(0xffff, ioaddr + RESET);
-		eth16i_initialize(dev);
-		outw(0xffff, ioaddr + TX_STATUS_REG);
-		BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+		eth16i_reset(dev);
 
-		lp->tx_started = 0;
-		lp->tx_queue = 0;
-		lp->tx_queue_len = 0;
+		dev->trans_start = jiffies;
 
 		outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
 
-		dev->tbusy = 0;
-		dev->trans_start = jiffies;
 	}
 
-	/* Block a timer based transmitter from overlapping. This could better be
-		 done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+	/* 
+	   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) {
+#if LINUX_VERSION_CODE < 0x020100
+		dev_tint(dev);
+#endif
+		if(eth16i_debug > 0) 
+			printk(KERN_WARNING "%s: Missed tx-done interrupt.\n", dev->name);
+		return 0;
+	}
+
+	/* Block a timer based transmitter from overlapping. 
+	   This could better be done with atomic_swap(1, dev->tbusy), 
+	   but set_bit() works as well. */
 
+	set_bit(0, (void *)&lp->tx_buf_busy);
+	
 	/* Turn off TX interrupts */
 	outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
 
-	if(test_and_set_bit(0, (void *)&dev->tbusy) != 0)
-		printk("%s: Transmitter access conflict.\n", dev->name);
+	if(test_and_set_bit(0, (void *)&dev->tbusy) != 0) {
+		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
+		status = -1;
+	}
 	else {
-		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+		ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 		unsigned char *buf = skb->data;
 
-		outw(length, ioaddr + DATAPORT);
-
-		if( ioaddr < 0x1000 )
-			outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-		else 
-		{
-			unsigned char frag = length % 4;
-
-			outsl(ioaddr + DATAPORT, buf, length >> 2);
+		if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
+			if(eth16i_debug > 0) 
+				printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);  
+		} 
+		else {
+			outw(length, ioaddr + DATAPORT);
 
-			if( frag != 0 ) 
-			{
-				outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
-				if( frag == 3 )
-					outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC) + 2), 1);
+			if( ioaddr < 0x1000 ) 
+				outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+			else {
+				unsigned char frag = length % 4;
+
+				outsl(ioaddr + DATAPORT, buf, length >> 2);
+
+				if( frag != 0 ) {
+					outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
+					if( frag == 3 ) 
+						outsw(ioaddr + DATAPORT, 
+						      (buf + (length & 0xFFFC) + 2), 1);
+				}
 			}
-		}
 
-		lp->tx_queue++;
-		lp->tx_queue_len += length + 2;
+			lp->tx_buffered_packets++;
+			lp->tx_queue++;
+			lp->tx_queue_len += length + 2;
+			
+		}
+		
+		lp->tx_buf_busy = 0;
 
 		if(lp->tx_started == 0) {
 			/* If the transmitter is idle..always trigger a transmit */
@@ -971,15 +1168,21 @@
 			/* There is still more room for one more packet in tx buffer */
 			dev->tbusy = 0;
 		}
-
+		
 		outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
+		
 		/* Turn TX interrupts back on */
 		/* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
-	}
+		status = 0;
+	} 
+
+#if LINUX_VERSION_CODE >= 0x020100
 	dev_kfree_skb(skb);
+#else
+	dev_kfree_skb(skb, FREE_WRITE);
+#endif
 
-	return 0;
+	return status;
 }
 
 static void eth16i_rx(struct device *dev)
@@ -989,71 +1192,63 @@
 	int boguscount = MAX_RX_LOOP;
 
 	/* Loop until all packets have been read */
-	while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) 
-	{
-		/* Read status byte from receive buffer */
+	while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) {
+
+		/* Read status byte from receive buffer */ 
 		ushort status = inw(ioaddr + DATAPORT);
 
-		if(eth16i_debug > 4)
-			printk("%s: Receiving packet mode %02x status %04x.\n",
-				dev->name, inb(ioaddr + RECEIVE_MODE_REG), status);
+		/* Get the size of the packet from receive buffer */
+		ushort pkt_len = inw(ioaddr + DATAPORT);
 
-		if( !(status & PKT_GOOD) ) 
-		{
-			/* Hmm..something went wrong. Let's check what error occurred */
+		if(eth16i_debug > 4)
+			printk(KERN_DEBUG "%s: Receiving packet mode %02x status %04x.\n", 
+			       dev->name, 
+			       inb(ioaddr + RECEIVE_MODE_REG), status);
+		
+		if( !(status & PKT_GOOD) ) {
 			lp->stats.rx_errors++;
-			if( status & PKT_SHORT)
+
+			if( (pkt_len < ETH_ZLEN) || (pkt_len > ETH_FRAME_LEN) ) {
 				lp->stats.rx_length_errors++;
-			if( status & PKT_ALIGN_ERR )
-				lp->stats.rx_frame_errors++;
-			if( status & PKT_CRC_ERR )
-				lp->stats.rx_crc_errors++;
-			if( status & PKT_RX_BUF_OVERFLOW)
-				lp->stats.rx_over_errors++;
+				eth16i_reset(dev);
+				return;		
+			}
+			else { 
+				eth16i_skip_packet(dev);
+				lp->stats.rx_dropped++;
+			}	
 		}
-		else
-		{	 /* Ok so now we should have a good packet */
+		else {   /* Ok so now we should have a good packet */
 			struct sk_buff *skb;
-			/* Get the size of the packet from receive buffer */
-			ushort pkt_len = inw(ioaddr + DATAPORT);
-
-			if(pkt_len > ETH_FRAME_LEN) 
-			{
-				printk("%s: %s claimed a very large packet, size of %d bytes.\n",
-				dev->name, cardname, pkt_len);
-				outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
-				lp->stats.rx_dropped++;
-				break;
-			}
 
 			skb = dev_alloc_skb(pkt_len + 3);
-			if( skb == NULL ) 
-			{
-				printk("%s: Couldn't allocate memory for packet (len %d)\n",
-				dev->name, pkt_len);
-				outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+			if( skb == NULL ) {
+				printk(KERN_WARNING "%s: Could'n allocate memory for packet (len %d)\n", 
+				       dev->name, pkt_len);
+				eth16i_skip_packet(dev);
 				lp->stats.rx_dropped++;
 				break;
 			}
+
 			skb->dev = dev;
 			skb_reserve(skb,2);
-			/*
-				Now let's get the packet out of buffer.
-				size is (pkt_len + 1) >> 1, cause we are now reading words
-				and it has to be even aligned.
-			*/
-
-			if( ioaddr < 0x1000)
-				insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), (pkt_len + 1) >> 1);
-			else 
-			{
+			
+			/* 
+			   Now let's get the packet out of buffer.
+			   size is (pkt_len + 1) >> 1, cause we are now reading words
+			   and it have to be even aligned.
+			   */ 
+			
+			if(ioaddr < 0x1000) 
+				insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), 
+				     (pkt_len + 1) >> 1);
+			else {	
 				unsigned char *buf = skb_put(skb, pkt_len);
 				unsigned char frag = pkt_len % 4;
 
 				insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
 
-				if(frag != 0) 
-				{
+				if(frag != 0) {
 					unsigned short rest[2];
 					rest[0] = inw( ioaddr + DATAPORT );
 					if(frag == 3)
@@ -1067,13 +1262,13 @@
 			netif_rx(skb);
 			lp->stats.rx_packets++;
 
-			if( eth16i_debug > 5 ) 
-			{
+			if( eth16i_debug > 5 ) {
 				int i;
-				printk("%s: Received packet of length %d.\n", dev->name, pkt_len);
-				for(i = 0; i < 14; i++)
-					printk(" %02x", skb->data[i]);
-				printk(".\n");
+				printk(KERN_DEBUG "%s: Received packet of length %d.\n", 
+				       dev->name, pkt_len);
+				for(i = 0; i < 14; i++) 
+					printk(KERN_DEBUG " %02x", skb->data[i]);
+				printk(KERN_DEBUG ".\n");
 			}
 
 		} /* else */
@@ -1087,16 +1282,16 @@
 	{
 		int i;
 
-		for(i = 0; i < 20; i++) 
-		{
-			if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == RX_BUFFER_EMPTY)
+		for(i = 0; i < 20; i++) {
+			if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 
+			    RX_BUFFER_EMPTY)
 				break;
 			inw(ioaddr + DATAPORT);
-			outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+			outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
 		}
 
 		if(eth16i_debug > 1)
-			printk("%s: Flushed receive buffer.\n", dev->name);
+			printk(KERN_DEBUG "%s: Flushed receive buffer.\n", dev->name);
 	}
 #endif
 
@@ -1108,126 +1303,302 @@
 	struct device *dev = dev_id;
 	struct eth16i_local *lp;
 	int ioaddr = 0,
-			status;
+		status;
 
 	if(dev == NULL) {
-		printk("eth16i_interrupt(): irq %d for unknown device. \n", irq);
+		printk(KERN_WARNING "eth16i_interrupt(): irq %d for unknown device. \n", irq);
 		return;
 	}
 
 	/* Turn off all interrupts from adapter */
 	outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
 
+	set_bit(0, (void *)&dev->tbusy);  	/* Set the device busy so that */
+	/* eth16i_tx wont be called */
+
+	if(dev->interrupt)
+		printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n", dev->name);
 	dev->interrupt = 1;
 
 	ioaddr = dev->base_addr;
 	lp = (struct eth16i_local *)dev->priv;
-	status = inw(ioaddr + TX_STATUS_REG);			/* Get the status */
-	outw(status, ioaddr + TX_STATUS_REG);			/* Clear status bits */
+	status = inw(ioaddr + TX_STATUS_REG);      /* Get the status */
+	outw(status, ioaddr + TX_STATUS_REG);      /* Clear status bits */
 
 	if(eth16i_debug > 3)
-		printk("%s: Interrupt with status %04x.\n", dev->name, status);
+		printk(KERN_DEBUG "%s: Interrupt with status %04x.\n", dev->name, status);
+
+	if( status & 0x7f00 ) {
+
+		lp->stats.rx_errors++;
+
+		if(status & (BUS_RD_ERR << 8) ) 
+			printk(KERN_WARNING "%s: Bus read error.\n",dev->name);
+		if(status & (SHORT_PKT_ERR << 8) )   lp->stats.rx_length_errors++;
+		if(status & (ALIGN_ERR << 8) )       lp->stats.rx_frame_errors++;
+		if(status & (CRC_ERR << 8) )	    lp->stats.rx_crc_errors++;
+		if(status & (RX_BUF_OVERFLOW << 8) ) lp->stats.rx_over_errors++;
+	}
+	if( status & 0x001a) {
+
+		lp->stats.tx_errors++;
+
+		if(status & CR_LOST) lp->stats.tx_carrier_errors++;
+		if(status & TX_JABBER_ERR) lp->stats.tx_window_errors++;
 
-	if( status & 0x00ff ) {			/* Let's check the transmit status reg */
-		if(status & TX_DONE) 
-		{	/* The transmit has been done */
-			lp->stats.tx_packets++; 
-			if(lp->tx_queue) 
-			{	/* Are there still packets ? */
+#if 0	       
+		if(status & COLLISION) {
+			lp->stats.collisions += 
+				((inb(ioaddr+TRANSMIT_MODE_REG) & 0xF0) >> 4);
+		}
+#endif
+		if(status & COLLISIONS_16) {
+			if(lp->col_16 < MAX_COL_16) { 
+				lp->col_16++;
+				lp->stats.collisions++;
+				/* Resume transmitting, skip failed packet */
+				outb(0x02, ioaddr + COL_16_REG);
+			}
+			else {
+				printk(KERN_WARNING "%s: bailing out due to many consecutive 16-in-a-row collisions. Network cable problem?\n", dev->name);
+			}
+		}
+	}
+
+	if( status & 0x00ff ) {          /* Let's check the transmit status reg */
+
+		if(status & TX_DONE) {         /* The transmit has been done */
+			lp->stats.tx_packets = lp->tx_buffered_packets;
+			lp->col_16 = 0;		   
+
+			if(lp->tx_queue) {           /* Is there still packets ? */
 				/* There was packet(s) so start transmitting and write also
-				   how many packets there is to be sent */
+				   how many packets there is to be sended */
 				outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
 				lp->tx_queue = 0;
 				lp->tx_queue_len = 0;
+				lp->tx_started = 1;
 				dev->trans_start = jiffies;
-				dev->tbusy = 0;
-				mark_bh(NET_BH);
+				mark_bh(NET_BH); 
 			}
-			else 
-			{
+			else {
 				lp->tx_started = 0;
-				dev->tbusy = 0;
 				mark_bh(NET_BH);
 			}
 		}
 	}
 
-	if( ( status & 0xff00 ) ||
-		 ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
-		eth16i_rx(dev);	/* We have packet in receive buffer */
-	}
-
+	if( ( status & 0x8000 ) || 
+	    ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
+		eth16i_rx(dev);  /* We have packet in receive buffer */
+	}  
+	
 	dev->interrupt = 0;
-
+	
 	/* Turn interrupts back on */
 	outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
+	
+	if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+		/* There is still more room for one more packet in tx buffer */
+		dev->tbusy = 0;
+	}
+	
 	return;
 }
 
-static void eth16i_multicast(struct device *dev)
+static void eth16i_skip_packet(struct device *dev)
+{	 
+	int ioaddr = dev->base_addr;
+
+	inw(ioaddr + DATAPORT);
+	inw(ioaddr + DATAPORT);
+	inw(ioaddr + DATAPORT);
+
+	outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
+	while( inb( ioaddr + FILTER_SELF_RX_REG ) != 0);
+}
+
+static void eth16i_reset(struct device *dev)
 {
-	short ioaddr = dev->base_addr;
+	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+	int ioaddr = dev->base_addr;
+
+	if(eth16i_debug > 1) 
+		printk(KERN_DEBUG "%s: Resetting device.\n", dev->name);
+
+	BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+	outw(0xffff, ioaddr + TX_STATUS_REG);    
+	eth16i_select_regbank(2, ioaddr);
+
+	lp->tx_started = 0;
+	lp->tx_buf_busy = 0;
+	lp->tx_queue = 0;
+	lp->tx_queue_len = 0;    
+
+	dev->interrupt = 0;
+	dev->start = 1;
+	dev->tbusy = 0;
+	BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+}
 
-	if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
+static void eth16i_multicast(struct device *dev)
+{
+	int ioaddr = dev->base_addr;
+  
+	if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) 
 	{
 		dev->flags|=IFF_PROMISC;	/* Must do this */
-		outb(3, ioaddr + RECEIVE_MODE_REG);
+		outb(3, ioaddr + RECEIVE_MODE_REG);    
 	} else {
 		outb(2, ioaddr + RECEIVE_MODE_REG);
 	}
 }
 
-static struct net_device_stats *eth16i_get_stats(struct device *dev)
+static struct enet_statistics *eth16i_get_stats(struct device *dev)
 {
 	struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 
 	return &lp->stats;
 }
 
-static void eth16i_select_regbank(unsigned char banknbr, short ioaddr)
+static void eth16i_select_regbank(unsigned char banknbr, int ioaddr)
 {
 	unsigned char data;
 
 	data = inb(ioaddr + CONFIG_REG_1);
-	outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1);
+	outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1); 
 }
 
 #ifdef MODULE
-static char devicename[9] = { 0, };
-static struct device dev_eth16i = {
-	devicename,
-	0, 0, 0, 0,
-	0, 0,
-	0, 0, 0, NULL, eth16i_probe
+
+static ushort eth16i_parse_mediatype(const char* s)
+{
+	if(!s)
+		return E_PORT_FROM_EPROM;
+	
+        if (!strncmp(s, "bnc", 3))
+		return E_PORT_BNC;
+        else if (!strncmp(s, "tp", 2))
+                return E_PORT_TP;
+        else if (!strncmp(s, "dix", 3))
+                return E_PORT_DIX;
+        else if (!strncmp(s, "auto", 4))
+		return E_PORT_AUTO;
+	else
+		return E_PORT_FROM_EPROM;
+}
+
+#define MAX_ETH16I_CARDS 4  /* Max number of Eth16i cards per module */
+#define NAMELEN          8  /* number of chars for storing dev->name */
+
+static char namelist[NAMELEN * MAX_ETH16I_CARDS] = { 0, };
+static struct device dev_eth16i[MAX_ETH16I_CARDS] = {
+	{
+		NULL,
+		0, 0, 0, 0,
+		0, 0,
+		0, 0, 0, NULL, NULL
+	},
 };
 
-int io = 0x2a0;
-int irq = 0;
+static int ioaddr[MAX_ETH16I_CARDS] = { 0, };
+#if 0
+static int irq[MAX_ETH16I_CARDS] = { 0, };
+#endif
+static char* mediatype[MAX_ETH16I_CARDS] = { 0, };
+static int debug = -1;
 
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
+#if (LINUX_VERSION_CODE >= 0x20115) 
+MODULE_AUTHOR("Mika Kuoppala <miku@iki.fi>");
+MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver");
+
+MODULE_PARM(ioaddr, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "i");
+MODULE_PARM_DESC(ioaddr, "eth16i io base address");
+
+#if 0
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "i");
+MODULE_PARM_DESC(irq, "eth16i interrupt request number");
+#endif
+
+MODULE_PARM(mediatype, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "s");
+MODULE_PARM_DESC(mediatype, "eth16i interfaceport mediatype");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "eth16i debug level (0-4)");
+#endif
 
 int init_module(void)
 {
-	if(io == 0)
-		printk("eth16i: You should not use auto-probing with insmod!\n");
+	int this_dev, found = 0;
 
-	dev_eth16i.base_addr = io;
-	dev_eth16i.irq = irq;
-	if( register_netdev( &dev_eth16i ) != 0 ) {
-		printk("eth16i: register_netdev() returned non-zero.\n");
-		return -EIO;
-	}
+	for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
+	{
+		struct device *dev = &dev_eth16i[this_dev];
+	
+		dev->name = namelist + (NAMELEN*this_dev);
+		dev->irq = 0; /* irq[this_dev]; */
+		dev->base_addr = ioaddr[this_dev];
+		dev->init = eth16i_probe;
+
+	        if(debug != -1)
+			eth16i_debug = debug;
+
+		if(eth16i_debug > 1)
+			printk(KERN_NOTICE "eth16i(%d): interface type %s\n", this_dev, mediatype[this_dev] ? mediatype[this_dev] : "none" );
 
+		dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]);
+
+		if(ioaddr[this_dev] == 0)
+		{
+			if(this_dev != 0) break; /* Only autoprobe 1st one */
+
+			printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n");
+		}
+
+		if(register_netdev(dev) != 0)
+		{
+			printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n",
+			       ioaddr[this_dev]);
+	    
+			if(found != 0) return 0;
+			return -ENXIO;
+		}
+
+		found++;
+	}
 	return 0;
 }
-
+	
 void cleanup_module(void)
 {
-	unregister_netdev( &dev_eth16i );
-	free_irq( dev_eth16i.irq, &dev_eth16i );
-	release_region( dev_eth16i.base_addr, ETH16I_IO_EXTENT );
-}
+	int this_dev;
 
+	for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
+	{
+		struct device* dev = &dev_eth16i[this_dev];
+		
+		if(dev->priv != NULL)
+		{
+			unregister_netdev(dev);
+			kfree(dev->priv);
+			dev->priv = NULL;
+			
+			free_irq(dev->irq, dev);
+			release_region(dev->base_addr, ETH16I_IO_EXTENT);
+			
+		}
+	}
+}
 #endif /* MODULE */
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eth16i.c"
+ *  alt-compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict -prototypes -O6 -c eth16i.c"
+ *  tab-width: 8
+ *  c-basic-offset: 8
+ *  c-indent-level: 8
+ * End:
+ */
+
+/* End of file eth16i.c */

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