diff -ru --new-file 2.3.40.clean/Documentation/Configure.help 2.3.40/Documentation/Configure.help
--- 2.3.40.clean/Documentation/Configure.help	Sun Jan 23 05:30:47 2000
+++ 2.3.40/Documentation/Configure.help	Sun Jan 23 01:07:10 2000
@@ -7513,14 +7513,16 @@
   Linux Token Ring Project site for the latest information at
   http://www.linuxtr.net
 
-Generic TMS380 Token Ring ISA/PCI adapter support
+Generic TMS380 Token Ring ISA/PCI/MCA/EISA adapter support
 CONFIG_TMS380TR
   This driver provides generic support for token ring adapters
   based on the Texas Instruments TMS380 series chipsets.  This
   includes the SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect
   TR4/16(+) PCI (SK-4590), SysKonnect TR4/16 PCI (SK-4591),
-  Compaq 4/16 PCI, Thomas-Conrad TC4048 4/16 PCI, and Intel 
-  TokenExpress 4/16 and PRO ISA adapters.
+  Compaq 4/16 PCI, Thomas-Conrad TC4048 4/16 PCI, and several
+  Madge adapters.  If selected, you will be asked to select
+  which cards to support below.  If you're using modules, each
+  class of card will be supported by a seperate module.
 
   If you have such an adapter and would like to use it, say Y or M and
   read the Token-Ring mini-HOWTO, available from
@@ -7528,6 +7530,25 @@
 
   Also read the file linux/Documentation/networking/tms380tr.txt or check
   http://www.auk.cx/tms380tr/
+
+Generic TMS380 PCI support
+CONFIG_TMSPCI
+  This tms380 module supports generic TMS380-based PCI cards.
+
+  These cards are known to work:
+     - Compaq 4/16 TR PCI
+     - SysKonnect TR4/16 PCI (SK-4590/SK-4591)
+     - Thomas-Conrad TC4048 PCI 4/16
+     - 3Com Token Link Velocity
+
+Madge Smart 16/4 PCI Mk2 support
+CONFIG_ABYSS
+  This tms380 module supports the Madge Smart 16/4 PCI Mk2 cards (51-02).
+
+Madge Smart 16/4 Ringode MicroChannel 
+CONFIG_MADGEMC
+  This tms380 module supports the Madge Smart 16/4 MC16 and MC32
+  MicroChannel adapters
 
 SMC ISA TokenRing adapter support
 CONFIG_SMCTR
diff -ru --new-file 2.3.40.clean/Makefile 2.3.40/Makefile
--- 2.3.40.clean/Makefile	Sun Jan 23 05:30:47 2000
+++ 2.3.40/Makefile	Sun Jan 23 01:07:11 2000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 3
 SUBLEVEL = 41
-EXTRAVERSION =
+EXTRAVERSION = mid1
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -ru --new-file 2.3.40.clean/arch/i386/kernel/mca.c 2.3.40/arch/i386/kernel/mca.c
--- 2.3.40.clean/arch/i386/kernel/mca.c	Sat Nov 20 05:16:10 1999
+++ 2.3.40/arch/i386/kernel/mca.c	Sun Jan 23 01:07:11 2000
@@ -274,11 +274,15 @@
 	 * read its POS registers. Then put adapter setup off.
 	 */
 
+	printk("MCA Bus Devices:\n");
 	for(i=0; i<MCA_MAX_SLOT_NR; i++) {
 		outb_p(0x8|(i&0xf), MCA_ADAPTER_SETUP_REG);
+		printk("    Slot %d: ", i);
 		for(j=0; j<8; j++) {
 			mca_info->slot[i].pos[j]=inb_p(MCA_POS_REG(j));
+			printk("%02x ", mca_info->slot[i].pos[j]);
 		}
+		printk("\n");
 		mca_info->slot[i].name[0] = 0;
 		mca_info->slot[i].driver_loaded = 0;
 		mca_configure_adapter_status(i);
diff -ru --new-file 2.3.40.clean/drivers/net/Space.c 2.3.40/drivers/net/Space.c
--- 2.3.40.clean/drivers/net/Space.c	Thu Jan  6 23:01:56 2000
+++ 2.3.40/drivers/net/Space.c	Sun Jan 23 01:07:11 2000
@@ -569,7 +569,6 @@
 /* Token-ring device probe */
 extern int ibmtr_probe(struct net_device *);
 extern int olympic_probe(struct net_device *);
-extern int tms380tr_probe(struct net_device *);
 extern int smctr_probe(struct net_device *);
 
 static int
@@ -581,9 +580,6 @@
 #endif
 #ifdef CONFIG_IBMOL
 	&& olympic_probe(dev)
-#endif
-#ifdef CONFIG_SKTR
-	&& tms380tr_probe(dev)
 #endif
 #ifdef CONFIG_SMCTR
 	&& smctr_probe(dev)
diff -ru --new-file 2.3.40.clean/drivers/net/eexpress.c 2.3.40/drivers/net/eexpress.c
--- 2.3.40.clean/drivers/net/eexpress.c	Wed Sep  8 18:51:22 1999
+++ 2.3.40/drivers/net/eexpress.c	Sun Jan 23 01:07:11 2000
@@ -9,6 +9,7 @@
  * Many modifications, and currently maintained, by
  *  Philip Blundell <Philip.Blundell@pobox.com>
  * Added the Compaq LTE  Alan Cox <alan@redhat.com>
+ * Added MCA support Adam Fritzler <mid@auk.cx>
  *
  * Note - this driver is experimental still - it has problems on faster
  * machines. Someone needs to sit down and go through it line by line with
@@ -121,6 +122,10 @@
 #include <linux/skbuff.h>
 #include <linux/malloc.h>
 
+#ifdef CONFIG_MCA
+#include <linux/mca.h>
+#endif
+
 #include <linux/spinlock.h>
 
 #ifndef NET_DEBUG
@@ -232,6 +237,16 @@
 /* maps irq number to EtherExpress magic value */
 static char irqrmap[] = { 0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0 };
 
+#ifdef CONFIG_MCA
+/* mapping of the first four bits of the second POS register */
+static unsigned short mca_iomap[] = {
+	0x270, 0x260, 0x250, 0x240, 0x230, 0x220, 0x210, 0x200,
+	0x370, 0x360, 0x350, 0x340, 0x330, 0x320, 0x310, 0x300
+};
+/* bits 5-7 of the second POS register */
+static char mca_irqmap[] = { 12, 9, 3, 4, 5, 10, 11, 15 };
+#endif 
+
 /*
  * Prototypes for Linux interface
  */
@@ -331,6 +346,55 @@
 	static unsigned short ports[] = { 0x300,0x310,0x270,0x320,0x340,0 };
 	unsigned short ioaddr = dev->base_addr;
 
+	dev->if_port = 0xff; /* not set */
+
+#ifdef CONFIG_MCA
+	if (MCA_bus) {
+		int slot = 0;
+
+		/*
+		 * Only find one card at a time.  Subsequent calls
+		 * will find others, however, proper multicard MCA
+		 * probing and setup can't be done with the
+		 * old-style Space.c init routines.  -- ASF
+		 */
+		while (slot != MCA_NOTFOUND) {
+			int pos0, pos1;
+			
+			slot = mca_find_unused_adapter(0x628B, slot);
+			if (slot == MCA_NOTFOUND)
+				break;
+
+			pos0 = mca_read_stored_pos(slot, 2);
+			pos1 = mca_read_stored_pos(slot, 3);
+			ioaddr = mca_iomap[pos1&0xf];
+
+			dev->irq = mca_irqmap[(pos1>>4)&0x7];
+			
+			/*
+			 * XXX: Transciever selection is done
+			 * differently on the MCA version.  
+			 * How to get it to select something
+			 * other than external/AUI is currently
+			 * unknown.  This code is just for looks. -- ASF
+			 */
+			if ((pos0 & 0x7) == 0x1)
+				dev->if_port = AUI;
+			else if ((pos0 & 0x7) == 0x5) {
+				if (pos1 & 0x80)
+					dev->if_port = BNC;
+				else
+					dev->if_port = TPE;
+			}
+
+			mca_set_adapter_name(slot, "Intel EtherExpress 16 MCA");
+			mca_set_adapter_procfn(slot, NULL, dev);
+			mca_mark_as_used(slot);
+
+			break;
+		}
+	}
+#endif
 	if (ioaddr&0xfe00)
 		return eexp_hw_probe(dev,ioaddr);
 	else if (ioaddr)
@@ -522,7 +586,9 @@
 static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
+#ifdef CONFIG_SMP
 	unsigned long flags;
+#endif
 
 #if NET_DEBUG > 6
 	printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name);
@@ -1010,8 +1076,10 @@
 		if (!dev->irq)
 			dev->irq = irqmap[setupval>>13];
 
-		dev->if_port = !(setupval & 0x1000) ? AUI :
-			eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TPE : BNC;
+		if (dev->if_port == 0xff) {
+			dev->if_port = !(setupval & 0x1000) ? AUI :
+				eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TPE : BNC;
+		}
 
 		buswidth = !((setupval & 0x400) >> 10);
 	}
diff -ru --new-file 2.3.40.clean/drivers/net/setup.c 2.3.40/drivers/net/setup.c
--- 2.3.40.clean/drivers/net/setup.c	Sun Jan 23 05:30:50 2000
+++ 2.3.40/drivers/net/setup.c	Sun Jan 23 01:07:11 2000
@@ -58,6 +58,10 @@
 extern int via_rhine_probe(void); 
 extern int yellowfin_probe(void);
 
+extern int abyss_probe(void);
+extern int madgemc_probe(void);
+extern int tms_pci_probe(void);
+
 /* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is tring of 9 zeros. */
 #define __PAD6 "\0\0\0\0\0\0\0\0\0"
 #define __PAD5 __PAD6 "\0"
@@ -250,7 +254,19 @@
 #ifdef CONFIG_YAM
 	{yam_init, 0},
 #endif	/* CONFIG_YAM */
-  
+
+/*
+ *	Token Ring Drivers
+ */  
+#ifdef CONFIG_ABYSS
+	{abyss_probe, 0},
+#endif
+#ifdef CONFIG_MADGEMC
+	{madgemc_probe, 0},
+#endif
+#ifdef CONFIG_TMSPCI
+	{tms_pci_probe, 0},
+#endif
  
 	{NULL, 0},
 };
diff -ru --new-file 2.3.40.clean/drivers/net/tokenring/Config.in 2.3.40/drivers/net/tokenring/Config.in
--- 2.3.40.clean/drivers/net/tokenring/Config.in	Thu Jan  6 23:01:56 2000
+++ 2.3.40/drivers/net/tokenring/Config.in	Sun Jan 23 01:07:11 2000
@@ -6,11 +6,16 @@
 comment 'Token Ring driver support'
 
 bool 'Token Ring driver support' CONFIG_TR
-if [ "$CONFIG_TR" = "y" ]; then
-   tristate '  IBM Tropic chipset based adapter support' CONFIG_IBMTR
-   tristate '  IBM Olympic chipset PCI adapter support' CONFIG_IBMOL
-   tristate '  Generic TMS380 Token Ring ISA/PCI adapter support' CONFIG_TMS380TR
-   tristate '  SMC ISA adapter support' CONFIG_SMCTR
+if [ "$CONFIG_TR" != "n" ]; then
+   dep_tristate '  IBM Tropic chipset based adapter support' CONFIG_IBMTR $CONFIG_TR
+   dep_tristate '  IBM Olympic chipset PCI adapter support' CONFIG_IBMOL $CONFIG_TR
+   dep_tristate '  Generic TMS380 Token Ring ISA/PCI adapter support' CONFIG_TMS380TR $CONFIG_TR
+   if [ "$CONFIG_TMS380TR" != "n" ]; then
+      dep_tristate '    Generic TMS380 PCI support' CONFIG_TMSPCI $CONFIG_TMS380TR
+      dep_tristate '    Madge Smart 16/4 PCI Mk2 support' CONFIG_ABYSS $CONFIG_TMS380TR
+      dep_tristate '    Madge Smart 16/4 Ringnode MicroChannel' CONFIG_MADGEMC $CONFIG_TMS380TR
+   fi
+   dep_tristate '  SMC ISA adapter support' CONFIG_SMCTR $CONFIG_TR
 fi
 
 endmenu
diff -ru --new-file 2.3.40.clean/drivers/net/tokenring/Makefile 2.3.40/drivers/net/tokenring/Makefile
--- 2.3.40.clean/drivers/net/tokenring/Makefile	Thu Jan  6 23:01:56 2000
+++ 2.3.40/drivers/net/tokenring/Makefile	Sun Jan 23 01:07:11 2000
@@ -41,9 +41,27 @@
 
 ifeq ($(CONFIG_TMS380TR),y)
   L_OBJS += tms380tr.o
+  ifeq ($(CONFIG_ABYSS),y)
+    L_OBJS += abyss.o
+  endif
+ ifeq ($(CONFIG_MADGEMC),y)
+    L_OBJS += madgemc.o
+  endif
+  ifeq ($(CONFIG_TMSPCI),y)
+    L_OBJS += tmspci.o
+  endif
 else
   ifeq ($(CONFIG_TMS380TR),m)
     M_OBJS += tms380tr.o
+    ifeq ($(CONFIG_ABYSS),m)
+      M_OBJS += abyss.o
+    endif
+    ifeq ($(CONFIG_MADGEMC),m)
+      M_OBJS += madgemc.o
+    endif
+    ifeq ($(CONFIG_TMSPCI),m)
+      M_OBJS += tmspci.o
+    endif
   endif
 endif
 
diff -ru --new-file 2.3.40.clean/drivers/net/tokenring/abyss.c 2.3.40/drivers/net/tokenring/abyss.c
--- 2.3.40.clean/drivers/net/tokenring/abyss.c	Thu Jan  1 00:00:00 1970
+++ 2.3.40/drivers/net/tokenring/abyss.c	Sun Jan 23 05:10:52 2000
@@ -0,0 +1,512 @@
+/*
+ *  abyss.c: Network driver for the Madge Smart 16/4 PCI Mk2 token ring card.
+ *
+ *  Written 1999-2000 by Adam Fritzler
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU Public License, incorporated herein by reference.
+ *
+ *  This driver module supports the following cards:
+ *      - Madge Smart 16/4 PCI Mk2
+ *
+ *  Maintainer(s):
+ *    AF	Adam Fritzler		mid@auk.cx
+ *
+ *  Modification History:
+ *	30-Dec-99	AF	Split off from the tms380tr driver.
+ *	22-Jan-00	AF	Updated to use indirect read/writes 
+ *
+ *
+ *  TODO:
+ *	1. See if we can use MMIO instead of inb/outb/inw/outw
+ *	2. Add support for Mk1 (has AT24 attached to the PCI
+ *		config registers)
+ *
+ */
+static const char *version = "abyss.c: v1.01 22/01/2000 by Adam Fritzler\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include "tms380tr.h"
+#include "abyss.h"            /* Madge-specific constants */
+
+#define ABYSS_IO_EXTENT 64
+
+int abyss_probe(void);
+static int abyss_open(struct net_device *dev);
+static int abyss_close(struct net_device *dev);
+static void abyss_enable(struct net_device *dev);
+static int abyss_chipset_init(struct net_device *dev);
+static void abyss_read_eeprom(struct net_device *dev);
+static unsigned short abyss_setnselout_pins(struct net_device *dev);
+
+void at24_writedatabyte(unsigned long regaddr, unsigned char byte);
+int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr);
+int at24_sendcmd(unsigned long regaddr, unsigned char cmd);
+unsigned char at24_readdatabit(unsigned long regaddr);
+unsigned char at24_readdatabyte(unsigned long regaddr);
+int at24_waitforack(unsigned long regaddr);
+int at24_waitfornack(unsigned long regaddr);
+void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data);
+void at24_start(unsigned long regaddr);
+void at24_stop(unsigned long regaddr);
+unsigned char at24_readb(unsigned long regaddr, unsigned char addr);
+
+static unsigned short abyss_sifreadb(struct net_device *dev, unsigned short reg)
+{
+	return inb(dev->base_addr + reg);
+}
+
+static unsigned short abyss_sifreadw(struct net_device *dev, unsigned short reg)
+{
+	return inw(dev->base_addr + reg);
+}
+
+static void abyss_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+	outb(val, dev->base_addr + reg);
+}
+
+static void abyss_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+	outw(val, dev->base_addr + reg);
+}
+
+struct tms_abyss_card {
+	struct net_device *dev;
+	struct pci_dev *pci_dev;
+	struct tms_abyss_card *next;
+};
+static struct tms_abyss_card *abyss_card_list = NULL;
+
+int __init abyss_probe(void)
+{	
+	static int versionprinted = 0;
+	struct pci_dev *pdev = NULL ; 
+	struct net_device *dev;
+	struct net_local *tp;
+	int i;
+	
+	if (!pci_present())
+		return (-1);	/* No PCI present. */
+	
+	while ( (pdev=pci_find_class(PCI_CLASS_NETWORK_TOKEN_RING<<8, pdev))) { 
+		unsigned int pci_irq_line;
+		unsigned long pci_ioaddr;
+		struct tms_abyss_card *card;
+		
+		/* We only support Madge Smart 16/4 PCI Mk2 (Abyss) cards */
+		if ( (pdev->vendor != PCI_VENDOR_ID_MADGE) ||
+		     (pdev->device != PCI_DEVICE_ID_MADGE_MK2) )
+			continue;
+		
+		if (versionprinted++ == 0)
+			printk("%s", version);
+
+		pci_enable_device(pdev);
+
+		/* Remove I/O space marker in bit 0. */
+		pci_irq_line = pdev->irq;
+		pci_ioaddr = pdev->resource[0].start ; 
+		
+		if(check_region(pci_ioaddr, ABYSS_IO_EXTENT))
+			continue;
+		
+		/* At this point we have found a valid card. */
+		
+		dev = init_trdev(NULL, 0);
+		
+		request_region(pci_ioaddr, ABYSS_IO_EXTENT, "abyss");
+		if(request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,
+			       "abyss", dev)) { 
+			release_region(pci_ioaddr, ABYSS_IO_EXTENT) ; 
+			continue; /*return (-ENODEV);*/ /* continue; ?? */
+		}
+		
+		/*
+		  if (load_tms380_module("abyss.c")) {
+		  return 0;
+		  }
+		*/
+
+		pci_ioaddr &= ~3 ; 
+		dev->base_addr	= pci_ioaddr;
+		dev->irq 		= pci_irq_line;
+		dev->dma		= 0;
+		
+		printk("%s: Madge Smart 16/4 PCI Mk2 (Abyss)\n", dev->name);
+		printk("%s:    IO: %#4lx  IRQ: %d\n",
+		       dev->name, pci_ioaddr, dev->irq);
+		/*
+		 * The TMS SIF registers lay 0x10 above the card base address.
+		 */
+		dev->base_addr += 0x10;
+		
+		if (tmsdev_init(dev)) {
+			printk("%s: unable to get memory for dev->priv.\n", 
+			       dev->name);
+			return 0;
+		}
+
+		abyss_read_eeprom(dev);
+		
+		printk("%s:    Ring Station Address: ", dev->name);
+		printk("%2.2x", dev->dev_addr[0]);
+		for (i = 1; i < 6; i++)
+			printk(":%2.2x", dev->dev_addr[i]);
+		printk("\n");
+
+		tp = (struct net_local *)dev->priv;
+		tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */
+		tp->setnselout = abyss_setnselout_pins;
+		tp->sifreadb = abyss_sifreadb;
+		tp->sifreadw = abyss_sifreadw;
+		tp->sifwriteb = abyss_sifwriteb;
+		tp->sifwritew = abyss_sifwritew;
+
+		memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1);
+		
+		dev->open = abyss_open;
+		dev->stop = abyss_close;
+		
+		if (register_trdev(dev) == 0) {
+			/* Enlist in the card list */
+			card = kmalloc(sizeof(struct tms_abyss_card), 
+				       GFP_KERNEL);
+			card->next = abyss_card_list;
+			abyss_card_list = card;
+			card->dev = dev;
+			card->pci_dev = pdev;
+		} else {
+			printk("abyss: register_trdev() returned non-zero.\n");
+			kfree(dev->priv);
+			kfree(dev);
+			return -1;
+		}
+	}
+	
+	if (abyss_card_list)
+		return 0;
+	return (-1);
+}
+
+unsigned short abyss_setnselout_pins(struct net_device *dev)
+{
+	unsigned short val = 0;
+	struct net_local *tp = (struct net_local *)dev->priv;
+	
+	if(tp->DataRate == SPEED_4)
+		val |= 0x01;  /* Set 4Mbps */
+	else
+		val |= 0x00;  /* Set 16Mbps */
+	
+	return val;
+}
+
+/*
+ * The following Madge boards should use this code:
+ *   - Smart 16/4 PCI Mk2 (Abyss)
+ *   - Smart 16/4 PCI Mk1 (PCI T)
+ *   - Smart 16/4 Client Plus PnP (Big Apple)
+ *   - Smart 16/4 Cardbus Mk2
+ *
+ * These access an Atmel AT24 SEEPROM using their glue chip registers. 
+ *
+ */
+void at24_writedatabyte(unsigned long regaddr, unsigned char byte)
+{
+	int i;
+	
+	for (i = 0; i < 8; i++) {
+		at24_setlines(regaddr, 0, (byte >> (7-i))&0x01);
+		at24_setlines(regaddr, 1, (byte >> (7-i))&0x01);
+		at24_setlines(regaddr, 0, (byte >> (7-i))&0x01);
+	}
+}
+
+int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr)
+{
+	if (at24_sendcmd(regaddr, cmd)) {
+		at24_writedatabyte(regaddr, addr);
+		return at24_waitforack(regaddr);
+	}
+	return 0;
+}
+
+int at24_sendcmd(unsigned long regaddr, unsigned char cmd)
+{
+	int i;
+	
+	for (i = 0; i < 10; i++) {
+		at24_start(regaddr);
+		at24_writedatabyte(regaddr, cmd);
+		if (at24_waitforack(regaddr))
+			return 1;
+	}
+	return 0;
+}
+
+unsigned char at24_readdatabit(unsigned long regaddr)
+{
+	unsigned char val;
+
+	at24_setlines(regaddr, 0, 1);
+	at24_setlines(regaddr, 1, 1);
+	val = (inb(regaddr) & AT24_DATA)?1:0;
+	at24_setlines(regaddr, 1, 1);
+	at24_setlines(regaddr, 0, 1);
+	return val;
+}
+
+unsigned char at24_readdatabyte(unsigned long regaddr)
+{
+	unsigned char data = 0;
+	int i;
+	
+	for (i = 0; i < 8; i++) {
+		data <<= 1;
+		data |= at24_readdatabit(regaddr);
+	}
+
+	return data;
+}
+
+int at24_waitforack(unsigned long regaddr)
+{
+	int i;
+	
+	for (i = 0; i < 10; i++) {
+		if ((at24_readdatabit(regaddr) & 0x01) == 0x00)
+			return 1;
+	}
+	return 0;
+}
+
+int at24_waitfornack(unsigned long regaddr)
+{
+	int i;
+	for (i = 0; i < 10; i++) {
+		if ((at24_readdatabit(regaddr) & 0x01) == 0x01)
+			return 1;
+	}
+	return 0;
+}
+
+void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data)
+{
+	unsigned char val;
+	val = AT24_ENABLE;
+	if (clock)
+		val |= AT24_CLOCK;
+	if (data)
+		val |= AT24_DATA;
+
+	outb(val, regaddr); 
+	tms380tr_wait(20); /* Very necessary. */
+}
+
+void at24_start(unsigned long regaddr)
+{
+	at24_setlines(regaddr, 0, 1);
+	at24_setlines(regaddr, 1, 1);
+	at24_setlines(regaddr, 1, 0);
+	at24_setlines(regaddr, 0, 1);
+	return;
+}
+
+void at24_stop(unsigned long regaddr)
+{
+	at24_setlines(regaddr, 0, 0);
+	at24_setlines(regaddr, 1, 0);
+	at24_setlines(regaddr, 1, 1);
+	at24_setlines(regaddr, 0, 1);
+	return;
+}
+     
+unsigned char at24_readb(unsigned long regaddr, unsigned char addr)
+{
+	unsigned char data = 0xff;
+	
+	if (at24_sendfullcmd(regaddr, AT24_WRITE, addr)) {
+		if (at24_sendcmd(regaddr, AT24_READ)) {
+			data = at24_readdatabyte(regaddr);
+			if (!at24_waitfornack(regaddr))
+				data = 0xff;
+		}
+	}
+	return data;
+}
+
+
+/*
+ * Enable basic functions of the Madge chipset needed
+ * for initialization.
+ */
+static void abyss_enable(struct net_device *dev)
+{
+	unsigned char reset_reg;
+	unsigned long ioaddr;
+	
+	ioaddr = dev->base_addr;
+	reset_reg = inb(ioaddr + PCIBM2_RESET_REG);
+	reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
+	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+	tms380tr_wait(100);
+	return;
+}
+
+/*
+ * Enable the functions of the Madge chipset needed for
+ * full working order. 
+ */
+static int abyss_chipset_init(struct net_device *dev)
+{
+	unsigned char reset_reg;
+	unsigned long ioaddr;
+	
+	ioaddr = dev->base_addr;
+	
+	reset_reg = inb(ioaddr + PCIBM2_RESET_REG);
+	
+	reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
+	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+	
+	reset_reg &= ~(PCIBM2_RESET_REG_CHIP_NRES |
+		       PCIBM2_RESET_REG_FIFO_NRES | 
+		       PCIBM2_RESET_REG_SIF_NRES);
+	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+	
+	tms380tr_wait(100);
+	
+	reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
+	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+	
+	reset_reg |= PCIBM2_RESET_REG_SIF_NRES;
+	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+
+	reset_reg |= PCIBM2_RESET_REG_FIFO_NRES;
+	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+
+	outb(PCIBM2_INT_CONTROL_REG_SINTEN | 
+	     PCIBM2_INT_CONTROL_REG_PCI_ERR_ENABLE, 
+	     ioaddr + PCIBM2_INT_CONTROL_REG);
+  
+	outb(30, ioaddr + PCIBM2_FIFO_THRESHOLD);
+	
+	return 0;
+}
+
+void abyss_chipset_close(struct net_device *dev)
+{
+	unsigned long ioaddr;
+	
+	ioaddr = dev->base_addr;
+	outb(0, ioaddr + PCIBM2_RESET_REG);
+	
+	return;
+}
+
+/*
+ * Read configuration data from the AT24 SEEPROM on Madge cards.
+ *
+ */
+static void abyss_read_eeprom(struct net_device *dev)
+{
+	struct net_local *tp;
+	unsigned long ioaddr;
+	unsigned short val;
+	int i;
+	
+	tp = (struct net_local *)dev->priv;
+	ioaddr = dev->base_addr;
+	
+	/* Must enable glue chip first */
+	abyss_enable(dev);
+	
+	val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG, 
+			 PCIBM2_SEEPROM_RING_SPEED);
+	tp->DataRate = val?SPEED_4:SPEED_16; /* set open speed */
+	printk("%s:    SEEPROM: ring speed: %dMb/sec\n", dev->name, tp->DataRate);
+	
+	val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG,
+			 PCIBM2_SEEPROM_RAM_SIZE) * 128;
+	printk("%s:    SEEPROM: adapter RAM: %dkb\n", dev->name, val);
+	
+	dev->addr_len = 6;
+	for (i = 0; i < 6; i++) 
+		dev->dev_addr[i] = at24_readb(ioaddr + PCIBM2_SEEPROM_REG, 
+					      PCIBM2_SEEPROM_BIA+i);
+	
+	return;
+}
+
+static int abyss_open(struct net_device *dev)
+{  
+	abyss_chipset_init(dev);
+	tms380tr_open(dev);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int abyss_close(struct net_device *dev)
+{
+	tms380tr_close(dev);
+	abyss_chipset_close(dev);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+	/* Probe for cards. */
+	if (abyss_probe()) {
+		printk(KERN_NOTICE "abyss.c: No cards found.\n");
+	}
+	/* lock_tms380_module(); */
+	return (0);
+}
+
+void cleanup_module(void)
+{
+	struct net_device *dev;
+	struct tms_abyss_card *this_card;
+	
+	while (abyss_card_list) {
+		dev = abyss_card_list->dev;
+		unregister_netdev(dev);
+		release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
+		free_irq(dev->irq, dev);
+		kfree(dev->priv);
+		kfree(dev);
+		this_card = abyss_card_list;
+		abyss_card_list = this_card->next;
+		kfree(this_card);
+	}
+	/* unlock_tms380_module(); */
+}
+#endif /* MODULE */
+
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c"
+ *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c"
+ *  c-set-style "K&R"
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -ru --new-file 2.3.40.clean/drivers/net/tokenring/abyss.h 2.3.40/drivers/net/tokenring/abyss.h
--- 2.3.40.clean/drivers/net/tokenring/abyss.h	Thu Jan  1 00:00:00 1970
+++ 2.3.40/drivers/net/tokenring/abyss.h	Sun Jan 23 01:07:11 2000
@@ -0,0 +1,58 @@
+/* 
+ * abyss.h: Header for the abyss tms380tr module
+ *
+ * Authors:
+ * - Adam Fritzler <mid@auk.cx>
+ */
+
+#ifndef __LINUX_MADGETR_H
+#define __LINUX_MADGETR_H
+
+#ifdef __KERNEL__
+
+/*
+ * For Madge Smart 16/4 PCI Mk2.  Since we increment the base address
+ * to get everything correct for the TMS SIF, we do these as negatives
+ * as they fall below the SIF in addressing.
+ */
+#define PCIBM2_INT_STATUS_REG          ((short)-15)/* 0x01 */
+#define PCIBM2_INT_CONTROL_REG         ((short)-14)/* 0x02 */
+#define PCIBM2_RESET_REG               ((short)-12)/* 0x04 */
+#define PCIBM2_SEEPROM_REG             ((short)-9) /* 0x07 */
+
+#define PCIBM2_INT_CONTROL_REG_SINTEN           0x02
+#define PCIBM2_INT_CONTROL_REG_PCI_ERR_ENABLE   0x80
+#define PCIBM2_INT_STATUS_REG_PCI_ERR           0x80
+
+#define PCIBM2_RESET_REG_CHIP_NRES              0x01
+#define PCIBM2_RESET_REG_FIFO_NRES              0x02
+#define PCIBM2_RESET_REG_SIF_NRES               0x04
+
+#define PCIBM2_FIFO_THRESHOLD   0x21
+#define PCIBM2_BURST_LENGTH     0x22
+
+/*
+ * Bits in PCIBM2_SEEPROM_REG.
+ */
+#define AT24_ENABLE             0x04
+#define AT24_DATA               0x02
+#define AT24_CLOCK              0x01
+
+/*
+ * AT24 Commands.
+ */
+#define AT24_WRITE              0xA0
+#define AT24_READ               0xA1
+
+/*
+ * Addresses in AT24 SEEPROM.
+ */
+#define PCIBM2_SEEPROM_BIA          0x12
+#define PCIBM2_SEEPROM_RING_SPEED   0x18
+#define PCIBM2_SEEPROM_RAM_SIZE     0x1A
+#define PCIBM2_SEEPROM_HWF1         0x1C
+#define PCIBM2_SEEPROM_HWF2         0x1E
+
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_MADGETR_H */
diff -ru --new-file 2.3.40.clean/drivers/net/tokenring/madgemc.c 2.3.40/drivers/net/tokenring/madgemc.c
--- 2.3.40.clean/drivers/net/tokenring/madgemc.c	Thu Jan  1 00:00:00 1970
+++ 2.3.40/drivers/net/tokenring/madgemc.c	Sun Jan 23 05:21:10 2000
@@ -0,0 +1,806 @@
+/*
+ *  madgemc.c: Driver for the Madge Smart 16/4 MC16 MCA token ring card.
+ *
+ *  Written 2000 by Adam Fritzler
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU Public License, incorporated herein by reference.
+ *
+ *  This driver module supports the following cards:
+ *      - Madge Smart 16/4 Ringnode MC16
+ *	- Madge Smart 16/4 Ringnode MC32 (??)
+ *
+ *  Maintainer(s):
+ *    AF	Adam Fritzler		mid@auk.cx
+ *
+ *  Modification History:
+ *	16-Jan-00	AF	Created
+ *
+ */
+static const char *version = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
+
+#include <linux/module.h>
+#include <linux/mca.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include "tms380tr.h"
+#include "madgemc.h"            /* Madge-specific constants */
+
+#define MADGEMC_IO_EXTENT 32
+#define MADGEMC_SIF_OFFSET 0x08
+
+struct madgemc_card {
+	struct net_device *dev;
+
+	/*
+	 * These are read from the BIA ROM.
+	 */
+	unsigned int manid;
+	unsigned int cardtype;
+	unsigned int cardrev;
+	unsigned int ramsize;
+	
+	/*
+	 * These are read from the MCA POS registers.  
+	 */
+	unsigned int burstmode:2;
+	unsigned int fairness:1; /* 0 = Fair, 1 = Unfair */
+	unsigned int arblevel:4;
+	unsigned int ringspeed:2; /* 0 = 4mb, 1 = 16, 2 = Auto/none */
+	unsigned int cabletype:1; /* 0 = RJ45, 1 = DB9 */
+
+	struct madgemc_card *next;
+};
+static struct madgemc_card *madgemc_card_list = NULL;
+
+
+int madgemc_probe(void);
+static int madgemc_open(struct net_device *dev);
+static int madgemc_close(struct net_device *dev);
+static int madgemc_chipset_init(struct net_device *dev);
+static void madgemc_read_rom(struct madgemc_card *card);
+static unsigned short madgemc_setnselout_pins(struct net_device *dev);
+static void madgemc_setcabletype(struct net_device *dev, int type);
+
+static int madgemc_mcaproc(char *buf, int slot, void *d);
+
+static void madgemc_setregpage(struct net_device *dev, int page);
+static void madgemc_setsifsel(struct net_device *dev, int val);
+static void madgemc_setint(struct net_device *dev, int val);
+
+static void madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+/*
+ * These work around paging, however they dont guarentee you're on the
+ * right page.
+ */
+#define SIFREADB(reg) (inb(dev->base_addr + ((reg<0x8)?reg:reg-0x8)))
+#define SIFWRITEB(val, reg) (outb(val, dev->base_addr + ((reg<0x8)?reg:reg-0x8)))
+#define SIFREADW(reg) (inw(dev->base_addr + ((reg<0x8)?reg:reg-0x8)))
+#define SIFWRITEW(val, reg) (outw(val, dev->base_addr + ((reg<0x8)?reg:reg-0x8)))
+
+/*
+ * Read a byte-length value from the register.
+ */
+static unsigned short madgemc_sifreadb(struct net_device *dev, unsigned short reg)
+{
+	unsigned short ret;
+	if (reg<0x8)	
+		ret = SIFREADB(reg);
+	else {
+		madgemc_setregpage(dev, 1);	
+		ret = SIFREADB(reg);
+		madgemc_setregpage(dev, 0);
+	}
+	return ret;
+}
+
+/*
+ * Write a byte-length value to a register.
+ */
+static void madgemc_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+	if (reg<0x8)
+		SIFWRITEB(val, reg);
+	else {
+		madgemc_setregpage(dev, 1);
+		SIFWRITEB(val, reg);
+		madgemc_setregpage(dev, 0);
+	}
+	return;
+}
+
+/*
+ * Read a word-length value from a register
+ */
+static unsigned short madgemc_sifreadw(struct net_device *dev, unsigned short reg)
+{
+	unsigned short ret;
+	if (reg<0x8)	
+		ret = SIFREADW(reg);
+	else {
+		madgemc_setregpage(dev, 1);	
+		ret = SIFREADW(reg);
+		madgemc_setregpage(dev, 0);
+	}
+	return ret;
+}
+
+/*
+ * Write a word-length value to a register.
+ */
+static void madgemc_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+	if (reg<0x8)
+		SIFWRITEW(val, reg);
+	else {
+		madgemc_setregpage(dev, 1);
+		SIFWRITEW(val, reg);
+		madgemc_setregpage(dev, 0);
+	}
+	return;
+}
+
+
+
+int __init madgemc_probe(void)
+{	
+	static int versionprinted = 0;
+	struct net_device *dev;
+	struct net_local *tp;
+	struct madgemc_card *card;
+	int i,slot = 0;
+	__u8 posreg[4];
+
+	if (!MCA_bus)
+		return -1;	
+       
+	while (slot != MCA_NOTFOUND) {
+		/*
+		 * Currently we only support the MC16/32 (MCA ID 002d)
+		 */
+		slot = mca_find_unused_adapter(0x002d, slot);
+		if (slot == MCA_NOTFOUND)
+			break;
+
+		/*
+		 * If we get here, we have an adapter.
+		 */
+		if (versionprinted++ == 0)
+			printk("%s", version);
+
+		if ((dev = init_trdev(NULL, 0))==NULL) {
+			printk("madgemc: unable to allocate dev space\n");
+			return -1;
+		}
+		dev->dma = 0;
+
+		/*
+		 * Fetch MCA config registers
+		 */
+		for(i=0;i<4;i++)
+			posreg[i] = mca_read_stored_pos(slot, i+2);
+		
+		card = kmalloc(sizeof(struct madgemc_card), GFP_KERNEL);
+		if (card==NULL) {
+			printk("madgemc: unable to allocate card struct\n");
+			return -1;
+		}
+		card->dev = dev;
+
+		/*
+		 * Parse configuration information.  This all comes
+		 * directly from the publicly available @002d.ADF.
+		 * Get it from Madge or your local ADF library.
+		 */
+
+		/*
+		 * Base address 
+		 */
+		dev->base_addr = 0x0a20 + 
+			((posreg[2] & MC16_POS2_ADDR2)?0x0400:0) +
+			((posreg[0] & MC16_POS0_ADDR1)?0x1000:0) +
+			((posreg[3] & MC16_POS3_ADDR3)?0x2000:0);
+
+		/*
+		 * Interrupt line
+		 */
+		switch(posreg[0] >> 6) { /* upper two bits */
+		case 0x1: dev->irq = 3; break;
+		case 0x2: dev->irq = 9; break; /* IRQ 2 = IRQ 9 */
+		case 0x3: dev->irq = 10; break;
+		default: dev->irq = 0; break;
+		}
+
+		if (dev->irq == 0) {
+			printk("%s: invalid IRQ\n", dev->name);
+			goto getout;
+		}
+
+		request_region(dev->base_addr, MADGEMC_IO_EXTENT, "madgemc");
+#if 0
+		/* why is this not working? */
+		if (request_region(dev->base_addr, MADGEMC_IO_EXTENT, 
+				   "madgemc")) {
+			printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", slot, dev->base_addr);
+			dev->base_addr += MADGEMC_SIF_OFFSET;
+			goto getout;
+		}
+#endif
+		dev->base_addr += MADGEMC_SIF_OFFSET;
+		
+		/*
+		 * Arbitration Level
+		 */
+		card->arblevel = ((posreg[0] >> 1) & 0x7) + 8;
+
+		/*
+		 * Burst mode and Fairness
+		 */
+		card->burstmode = ((posreg[2] >> 6) & 0x3);
+		card->fairness = ((posreg[2] >> 4) & 0x1);
+
+		/*
+		 * Ring Speed
+		 */
+		if ((posreg[1] >> 2)&0x1)
+			card->ringspeed = 2; /* not selected */
+		else if ((posreg[2] >> 5) & 0x1)
+			card->ringspeed = 1; /* 16Mb */
+		else
+			card->ringspeed = 0; /* 4Mb */
+
+		/* 
+		 * Cable type
+		 */
+		if ((posreg[1] >> 6)&0x1)
+			card->cabletype = 1; /* STP/DB9 */
+		else
+			card->cabletype = 0; /* UTP/RJ-45 */
+
+
+		/* 
+		 * ROM Info. This requires us to actually twiddle
+		 * bits on the card, so we must ensure above that 
+		 * the base address is free of conflict (request_region above).
+		 */
+		madgemc_read_rom(card);
+		
+		if (card->manid != 0x4d) { /* something went wrong */
+			printk(KERN_INFO "%s: Madge MC ROM read failed (unknown manufacturer ID %02x)\n", dev->name, card->manid);
+			goto getout;
+		}
+		
+		if ((card->cardtype != 0x08) && (card->cardtype != 0x0d)) {
+			printk(KERN_INFO "%s: Madge MC ROM read failed (unknown card ID %02x)\n", dev->name, card->cardtype);
+			goto getout;
+		}
+	       
+		/* All cards except Rev 0 and 1 MC16's have 256kb of RAM */
+		if ((card->cardtype == 0x08) && (card->cardrev <= 0x01))
+			card->ramsize = 128;
+		else
+			card->ramsize = 256;
+
+		printk("%s: %s Rev %d at 0x%04lx IRQ %d\n", 
+		       dev->name, 
+		       (card->cardtype == 0x08)?MADGEMC16_CARDNAME:
+		       MADGEMC32_CARDNAME, card->cardrev, 
+		       dev->base_addr, dev->irq);
+
+		if (card->cardtype == 0x0d)
+			printk("%s:     Warning: MC32 support is experimental and highly untested\n", dev->name);
+		
+		if (card->ringspeed==2) { /* Unknown */
+			printk("%s:     Warning: Ring speed not set in POS -- Please run the reference disk and set it!\n", dev->name);
+			card->ringspeed = 1; /* default to 16mb */
+		}
+		
+		printk("%s:     RAM Size: %dKB\n", dev->name, card->ramsize);
+
+		printk("%s:     Ring Speed: %dMb/sec on %s\n", dev->name, 
+		       (card->ringspeed)?16:4, 
+		       card->cabletype?"STP/DB9":"UTP/RJ-45");
+		printk("%s:     Arbitration Level: %d\n", dev->name, 
+		       card->arblevel);
+
+		printk("%s:     Burst Mode: ", dev->name);
+		switch(card->burstmode) {
+		case 0: printk("Cycle steal"); break;
+		case 1: printk("Limited burst"); break;
+		case 2: printk("Delayed release"); break;
+		case 3: printk("Immediate release"); break;
+		}
+		printk(" (%s)\n", (card->fairness)?"Unfair":"Fair");
+
+
+		/* 
+		 * Enable SIF before we assign the interrupt handler,
+		 * just in case we get spurious interrupts that need
+		 * handling.
+		 */ 
+		outb(0, dev->base_addr + MC_CONTROL_REG0); /* sanity */
+		madgemc_setsifsel(dev, 1);
+		if(request_irq(dev->irq, madgemc_interrupt, SA_SHIRQ,
+			       "madgemc", dev)) 
+			goto getout;
+		
+		madgemc_chipset_init(dev); /* enables interrupts! */
+		madgemc_setcabletype(dev, card->cabletype);
+
+		/* Setup MCA structures */
+		mca_set_adapter_name(slot, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
+		mca_set_adapter_procfn(slot, madgemc_mcaproc, dev);
+		mca_mark_as_used(slot);
+
+		printk("%s:     Ring Station Address: ", dev->name);
+		printk("%2.2x", dev->dev_addr[0]);
+		for (i = 1; i < 6; i++)
+			printk(":%2.2x", dev->dev_addr[i]);
+		printk("\n");
+
+		if (tmsdev_init(dev)) {
+			printk("%s: unable to get memory for dev->priv.\n", 
+			       dev->name);
+			return -1;
+		}
+		tp = (struct net_local *)dev->priv;
+
+		/* 
+		 * The MC16 is physically a 32bit card.  However, Madge
+		 * insists on calling it 16bit, so I'll assume here that
+		 * they know what they're talking about.  Cut off DMA
+		 * at 16mb.
+		 */
+		tp->dmalimit = ISA_MAX_ADDRESS; /* XXX: ?? */
+		tp->setnselout = madgemc_setnselout_pins;
+		tp->sifwriteb = madgemc_sifwriteb;
+		tp->sifreadb = madgemc_sifreadb;
+		tp->sifwritew = madgemc_sifwritew;
+		tp->sifreadw = madgemc_sifreadw;
+		tp->DataRate = (card->ringspeed)?SPEED_16:SPEED_4;
+
+		memcpy(tp->ProductID, "Madge MCA 16/4    ", PROD_ID_SIZE + 1);
+
+		dev->open = madgemc_open;
+		dev->stop = madgemc_close;
+		
+		if (register_trdev(dev) == 0) {
+			/* Enlist in the card list */
+			card->next = madgemc_card_list;
+			madgemc_card_list = card;
+		} else {
+			printk("madgemc: register_trdev() returned non-zero.\n");
+			
+			kfree(card);
+			kfree(dev->priv);
+			kfree(dev);
+			return -1;
+		}
+
+		slot++;
+		continue; /* successful, try to find another */
+		
+	getout:
+		release_region(dev->base_addr-MADGEMC_SIF_OFFSET, 
+			       MADGEMC_IO_EXTENT); 
+		kfree(card);
+		kfree(dev); /* release_trdev? */
+		slot++;
+	}
+
+	if (madgemc_card_list)
+		return 0;
+	return -1;
+}
+
+/*
+ * Handle interrupts generated by the card
+ *
+ * The MicroChannel Madge cards need slightly more handling
+ * after an interrupt than other TMS380 cards do.
+ *
+ * First we must make sure it was this card that generated the
+ * interrupt (since interrupt sharing is allowed).  Then,
+ * because we're using level-triggered interrupts (as is
+ * standard on MCA), we must toggle the interrupt line
+ * on the card in order to claim and acknowledge the interrupt.
+ * Once that is done, the interrupt should be handlable in
+ * the normal tms380tr_interrupt() routine.
+ *
+ * There's two ways we can check to see if the interrupt is ours,
+ * both with their own disadvantages...
+ *
+ * 1)  	Read in the SIFSTS register from the TMS controller.  This
+ *	is guarenteed to be accurate, however, there's a fairly
+ *	large performance penalty for doing so: the Madge chips
+ *	must request the register from the Eagle, the Eagle must
+ *	read them from its internal bus, and then take the route
+ *	back out again, for a 16bit read.  
+ *
+ * 2)	Use the MC_CONTROL_REG0_SINTR bit from the Madge ASICs.
+ *	The major disadvantage here is that the accuracy of the
+ *	bit is in question.  However, it cuts out the extra read
+ *	cycles it takes to read the Eagle's SIF, as its only an
+ *	8bit read, and theoretically the Madge bit is directly
+ *	connected to the interrupt latch coming out of the Eagle
+ *	hardware (that statement is not verified).  
+ *
+ * I can't determine which of these methods has the best win.  For now,
+ * we make a compromise.  Use the Madge way for the first interrupt,
+ * which should be the fast-path, and then once we hit the first 
+ * interrupt, keep on trying using the SIF method until we've
+ * exhausted all contiguous interrupts.
+ *
+ */
+static void madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int pending,reg1;
+	struct net_device *dev;
+
+	if (!dev_id) {
+		printk("madgemc_interrupt: was not passed a dev_id!\n");
+		return;
+	}
+
+	dev = (struct net_device *)dev_id;
+
+	/* Make sure its really us. -- the Madge way */
+	pending = inb(dev->base_addr + MC_CONTROL_REG0);
+	if (!(pending & MC_CONTROL_REG0_SINTR))
+		return; /* not our interrupt */
+
+	/*
+	 * Since we're level-triggered, we may miss the rising edge
+	 * of the next interrupt while we're off handling this one,
+	 * so keep checking until the SIF verifies that it has nothing
+	 * left for us to do.
+	 */
+	pending = STS_SYSTEM_IRQ;
+	do {
+		if (pending & STS_SYSTEM_IRQ) {
+
+			/* Toggle the interrupt to reset the latch on card */
+			reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+			outb(reg1 ^ MC_CONTROL_REG1_SINTEN, 
+			     dev->base_addr + MC_CONTROL_REG1);
+			outb(reg1, dev->base_addr + MC_CONTROL_REG1);
+
+			/* Continue handling as normal */
+			tms380tr_interrupt(irq, dev_id, regs);
+
+			pending = SIFREADW(SIFSTS); /* restart - the SIF way */
+
+		} else
+			return; 
+	} while (1);
+
+	return; /* not reachable */
+}
+
+/*
+ * Set the card to the prefered ring speed.
+ *
+ * Unlike newer cards, the MC16/32 have their speed selection
+ * circuit connected to the Madge ASICs and not to the TMS380
+ * NSELOUT pins. Set the ASIC bits correctly here, and return 
+ * zero to leave the TMS NSELOUT bits unaffected.
+ *
+ */
+unsigned short madgemc_setnselout_pins(struct net_device *dev)
+{
+	unsigned char reg1;
+	struct net_local *tp = (struct net_local *)dev->priv;
+	
+	reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+
+	if(tp->DataRate == SPEED_16)
+		reg1 |= MC_CONTROL_REG1_SPEED_SEL; /* add for 16mb */
+	else if (reg1 & MC_CONTROL_REG1_SPEED_SEL)
+		reg1 ^= MC_CONTROL_REG1_SPEED_SEL; /* remove for 4mb */
+	outb(reg1, dev->base_addr + MC_CONTROL_REG1);
+
+	return 0; /* no change */
+}
+
+/*
+ * Set the register page.  This equates to the SRSX line
+ * on the TMS380Cx6.
+ *
+ * Register selection is normally done via three contiguous
+ * bits.  However, some boards (such as the MC16/32) use only
+ * two bits, plus a seperate bit in the glue chip.  This
+ * sets the SRSX bit (the top bit).  See page 4-17 in the
+ * Yellow Book for which registers are affected.
+ *
+ */
+static void madgemc_setregpage(struct net_device *dev, int page)
+{	
+	static int reg1 = 0;
+
+	reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+	if ((page == 0) && (reg1 & MC_CONTROL_REG1_SRSX)) {
+		outb(reg1 ^ MC_CONTROL_REG1_SRSX, 
+		     dev->base_addr + MC_CONTROL_REG1);
+	}
+	else if (page == 1) {
+		outb(reg1 | MC_CONTROL_REG1_SRSX, 
+		     dev->base_addr + MC_CONTROL_REG1);
+	}
+	reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+
+	return;
+}
+
+/*
+ * The SIF registers are not mapped into register space by default
+ * Set this to 1 to map them, 0 to map the BIA ROM.
+ *
+ */
+static void madgemc_setsifsel(struct net_device *dev, int val)
+{
+	unsigned int reg0;
+
+	reg0 = inb(dev->base_addr + MC_CONTROL_REG0);
+	if ((val == 0) && (reg0 & MC_CONTROL_REG0_SIFSEL)) {
+		outb(reg0 ^ MC_CONTROL_REG0_SIFSEL, 
+		     dev->base_addr + MC_CONTROL_REG0);
+	} else if (val == 1) {
+		outb(reg0 | MC_CONTROL_REG0_SIFSEL, 
+		     dev->base_addr + MC_CONTROL_REG0);
+	}	
+	reg0 = inb(dev->base_addr + MC_CONTROL_REG0);
+
+	return;
+}
+
+/*
+ * Enable SIF interrupts
+ *
+ * This does not enable interrupts in the SIF, but rather
+ * enables SIF interrupts to be passed onto the host.
+ *
+ */
+static void madgemc_setint(struct net_device *dev, int val)
+{
+	unsigned int reg1;
+
+	reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+	if ((val == 0) && (reg1 & MC_CONTROL_REG1_SINTEN)) {
+		outb(reg1 ^ MC_CONTROL_REG1_SINTEN, 
+		     dev->base_addr + MC_CONTROL_REG1);
+	} else if (val == 1) {
+		outb(reg1 | MC_CONTROL_REG1_SINTEN, 
+		     dev->base_addr + MC_CONTROL_REG1);
+	}
+
+	return;
+}
+
+/*
+ * Cable type is set via control register 7. Bit zero high
+ * for UTP, low for STP.
+ */
+static void madgemc_setcabletype(struct net_device *dev, int type)
+{
+	outb((type==0)?MC_CONTROL_REG7_CABLEUTP:MC_CONTROL_REG7_CABLESTP,
+	     dev->base_addr + MC_CONTROL_REG7);
+}
+
+/*
+ * Enable the functions of the Madge chipset needed for
+ * full working order. 
+ */
+static int madgemc_chipset_init(struct net_device *dev)
+{
+	outb(0, dev->base_addr + MC_CONTROL_REG1); /* pull SRESET low */
+	tms380tr_wait(100); /* wait for card to reset */
+
+	/* bring back into normal operating mode */
+	outb(MC_CONTROL_REG1_NSRESET, dev->base_addr + MC_CONTROL_REG1);
+
+	/* map SIF registers */
+	madgemc_setsifsel(dev, 1);
+
+	/* enable SIF interrupts */
+	madgemc_setint(dev, 1); 
+
+	return 0;
+}
+
+/*
+ * Disable the board, and put back into power-up state.
+ */
+void madgemc_chipset_close(struct net_device *dev)
+{
+	/* disable interrupts */
+	madgemc_setint(dev, 0);
+	/* unmap SIF registers */
+	madgemc_setsifsel(dev, 0);
+
+	return;
+}
+
+/*
+ * Read the card type (MC16 or MC32) from the card.
+ *
+ * The configuration registers are stored in two seperate
+ * pages.  Pages are flipped by clearing bit 3 of CONTROL_REG0 (PAGE)
+ * for page zero, or setting bit 3 for page one.
+ *
+ * Page zero contains the following data:
+ *	Byte 0: Manufacturer ID (0x4D -- ASCII "M")
+ *	Byte 1: Card type:
+ *			0x08 for MC16
+ *			0x0D for MC32
+ *	Byte 2: Card revision
+ *	Byte 3: Mirror of POS config register 0
+ *	Byte 4: Mirror of POS 1
+ *	Byte 5: Mirror of POS 2
+ *
+ * Page one contains the following data:
+ *	Byte 0: Unused
+ *	Byte 1-6: BIA, MSB to LSB.
+ *
+ * Note that to read the BIA, we must unmap the SIF registers
+ * by clearing bit 2 of CONTROL_REG0 (SIFSEL), as the data
+ * will reside in the same logical location.  For this reason,
+ * _never_ read the BIA while the Eagle processor is running!
+ * The SIF will be completely inaccessible until the BIA operation
+ * is complete.
+ *
+ */
+static void madgemc_read_rom(struct madgemc_card *card)
+{
+	unsigned long ioaddr;
+	unsigned char reg0, reg1, tmpreg0, i;
+
+	ioaddr = card->dev->base_addr;
+
+	reg0 = inb(ioaddr + MC_CONTROL_REG0);
+	reg1 = inb(ioaddr + MC_CONTROL_REG1);
+
+	/* Switch to page zero and unmap SIF */
+	tmpreg0 = reg0 & ~(MC_CONTROL_REG0_PAGE + MC_CONTROL_REG0_SIFSEL);
+	outb(tmpreg0, ioaddr + MC_CONTROL_REG0);
+	
+	card->manid = inb(ioaddr + MC_ROM_MANUFACTURERID);
+	card->cardtype = inb(ioaddr + MC_ROM_ADAPTERID);
+	card->cardrev = inb(ioaddr + MC_ROM_REVISION);
+
+	/* Switch to rom page one */
+	outb(tmpreg0 | MC_CONTROL_REG0_PAGE, ioaddr + MC_CONTROL_REG0);
+
+	/* Read BIA */
+	card->dev->addr_len = 6;
+	for (i = 0; i < 6; i++)
+		card->dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i);
+	
+	/* Restore original register values */
+	outb(reg0, ioaddr + MC_CONTROL_REG0);
+	outb(reg1, ioaddr + MC_CONTROL_REG1);
+	
+	return;
+}
+
+static int madgemc_open(struct net_device *dev)
+{  
+	/*
+	 * Go ahead and reinitialize the chipset again, just to 
+	 * make sure we didn't get left in a bad state.
+	 */
+	madgemc_chipset_init(dev);
+	tms380tr_open(dev);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int madgemc_close(struct net_device *dev)
+{
+	tms380tr_close(dev);
+	madgemc_chipset_close(dev);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/*
+ * Give some details available from /proc/mca/slotX
+ */
+static int madgemc_mcaproc(char *buf, int slot, void *d) 
+{	
+	struct net_device *dev = (struct net_device *)d;
+	struct madgemc_card *curcard = madgemc_card_list;
+	int len = 0;
+	
+	while (curcard) { /* search for card struct */
+		if (curcard->dev == dev)
+			break;
+		curcard = curcard->next;
+	}
+	len += sprintf(buf+len, "-------\n");
+	if (curcard) {
+		struct net_local *tp = (struct net_local *)dev->priv;
+		int i;
+		
+		len += sprintf(buf+len, "Card Revision: %d\n", curcard->cardrev);
+		len += sprintf(buf+len, "RAM Size: %dkb\n", curcard->ramsize);
+		len += sprintf(buf+len, "Cable type: %s\n", (curcard->cabletype)?"STP/DB9":"UTP/RJ-45");
+		len += sprintf(buf+len, "Configured ring speed: %dMb/sec\n", (curcard->ringspeed)?16:4);
+		len += sprintf(buf+len, "Running ring speed: %dMb/sec\n", (tp->DataRate==SPEED_16)?16:4);
+		len += sprintf(buf+len, "Device: %s\n", dev->name);
+		len += sprintf(buf+len, "IO Port: 0x%04lx\n", dev->base_addr);
+		len += sprintf(buf+len, "IRQ: %d\n", dev->irq);
+		len += sprintf(buf+len, "Arbitration Level: %d\n", curcard->arblevel);
+		len += sprintf(buf+len, "Burst Mode: ");
+		switch(curcard->burstmode) {
+		case 0: len += sprintf(buf+len, "Cycle steal"); break;
+		case 1: len += sprintf(buf+len, "Limited burst"); break;
+		case 2: len += sprintf(buf+len, "Delayed release"); break;
+		case 3: len += sprintf(buf+len, "Immediate release"); break;
+		}
+		len += sprintf(buf+len, " (%s)\n", (curcard->fairness)?"Unfair":"Fair");
+		
+		len += sprintf(buf+len, "Ring Station Address: ");
+		len += sprintf(buf+len, "%2.2x", dev->dev_addr[0]);
+		for (i = 1; i < 6; i++)
+			len += sprintf(buf+len, " %2.2x", dev->dev_addr[i]);
+		len += sprintf(buf+len, "\n");
+	} else 
+		len += sprintf(buf+len, "Card not configured\n");
+
+	return len;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+	/* Probe for cards. */
+	if (madgemc_probe()) {
+		printk(KERN_NOTICE "madgemc.c: No cards found.\n");
+	}
+	/* lock_tms380_module(); */
+	return (0);
+}
+
+void cleanup_module(void)
+{
+	struct net_device *dev;
+	struct madgemc_card *this_card;
+	
+	while (madgemc_card_list) {
+		dev = madgemc_card_list->dev;
+		unregister_trdev(dev);
+		release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);
+		free_irq(dev->irq, dev);
+		kfree(dev->priv);
+		kfree(dev);
+		this_card = madgemc_card_list;
+		madgemc_card_list = this_card->next;
+		kfree(this_card);
+	}
+	/* unlock_tms380_module(); */
+}
+#endif /* MODULE */
+
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c"
+ *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c"
+ *  c-set-style "K&R"
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -ru --new-file 2.3.40.clean/drivers/net/tokenring/madgemc.h 2.3.40/drivers/net/tokenring/madgemc.h
--- 2.3.40.clean/drivers/net/tokenring/madgemc.h	Thu Jan  1 00:00:00 1970
+++ 2.3.40/drivers/net/tokenring/madgemc.h	Sun Jan 23 05:23:36 2000
@@ -0,0 +1,70 @@
+/* 
+ * madgemc.h: Header for the madgemc tms380tr module
+ *
+ * Authors:
+ * - Adam Fritzler <mid@auk.cx>
+ */
+
+#ifndef __LINUX_MADGEMC_H
+#define __LINUX_MADGEMC_H
+
+#ifdef __KERNEL__
+
+#define MADGEMC16_CARDNAME "Madge Smart 16/4 MC16 Ringnode"
+#define MADGEMC32_CARDNAME "Madge Smart 16/4 MC32 Ringnode"
+
+/* 
+ * Bit definitions for the POS config registers
+ */
+#define MC16_POS0_ADDR1 0x20
+#define MC16_POS2_ADDR2 0x04
+#define MC16_POS3_ADDR3 0x20
+
+#define MC_CONTROL_REG0		((long)-8) /* 0x00 */
+#define MC_CONTROL_REG1		((long)-7) /* 0x01 */
+#define MC_ADAPTER_POS_REG0	((long)-6) /* 0x02 */
+#define MC_ADAPTER_POS_REG1	((long)-5) /* 0x03 */
+#define MC_ADAPTER_POS_REG2	((long)-4) /* 0x04 */
+#define MC_ADAPTER_REG5_UNUSED	((long)-3) /* 0x05 */
+#define MC_ADAPTER_REG6_UNUSED	((long)-2) /* 0x06 */
+#define MC_CONTROL_REG7		((long)-1) /* 0x07 */
+
+#define MC_CONTROL_REG0_UNKNOWN1	0x01
+#define MC_CONTROL_REG0_UNKNOWN2	0x02
+#define MC_CONTROL_REG0_SIFSEL		0x04
+#define MC_CONTROL_REG0_PAGE		0x08
+#define MC_CONTROL_REG0_TESTINTERRUPT	0x10
+#define MC_CONTROL_REG0_UNKNOWN20	0x20
+#define MC_CONTROL_REG0_SINTR		0x40
+#define MC_CONTROL_REG0_UNKNOWN80	0x80
+
+#define MC_CONTROL_REG1_SINTEN		0x01
+#define MC_CONTROL_REG1_BITOFDEATH	0x02
+#define MC_CONTROL_REG1_NSRESET		0x04
+#define MC_CONTROL_REG1_UNKNOWN8	0x08
+#define MC_CONTROL_REG1_UNKNOWN10	0x10
+#define MC_CONTROL_REG1_UNKNOWN20	0x20
+#define MC_CONTROL_REG1_SRSX		0x40
+#define MC_CONTROL_REG1_SPEED_SEL	0x80
+
+#define MC_CONTROL_REG7_CABLESTP	0x00
+#define MC_CONTROL_REG7_CABLEUTP	0x01
+
+/*
+ * ROM Page Zero
+ */
+#define MC_ROM_MANUFACTURERID		0x00
+#define MC_ROM_ADAPTERID		0x01
+#define MC_ROM_REVISION			0x02
+#define MC_ROM_CONFIG0			0x03
+#define MC_ROM_CONFIG1			0x04
+#define MC_ROM_CONFIG2			0x05
+
+/*
+ * ROM Page One
+ */
+#define MC_ROM_UNUSED_BYTE		0x00
+#define MC_ROM_BIA_START		0x01
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_MADGEMC_H */
diff -ru --new-file 2.3.40.clean/drivers/net/tokenring/tms380tr.c 2.3.40/drivers/net/tokenring/tms380tr.c
--- 2.3.40.clean/drivers/net/tokenring/tms380tr.c	Sun Jan 23 05:30:26 2000
+++ 2.3.40/drivers/net/tokenring/tms380tr.c	Sun Jan 23 04:40:04 2000
@@ -1,5 +1,5 @@
 /*
- *  tms380tr.c: A network driver for Texas Instruments TMS380-based
+ *  tms380tr.c: A network driver library for Texas Instruments TMS380-based
  *              Token Ring Adapters.
  *
  *  Originally sktr.c: Written 1997 by Christoph Goos
@@ -10,14 +10,16 @@
  *  This software may be used and distributed according to the terms
  *  of the GNU Public License, incorporated herein by reference.
  *
- *  This device driver works with the following TMS380 adapters:
+ *  The following modules are currently available for card support:
+ *	- tmspci (Generic PCI card support)
+ *	- abyss (Madge PCI support)
+ *  
+ *  The following cards are currently lacking support, even
+ *  though they were supported in previous versions, because
+ *  their code did not get migrated into a seperate module:
  *	- SysKonnect TR4/16(+) ISA	(SK-4190)
- *	- SysKonnect TR4/16(+) PCI	(SK-4590)
- *	- SysKonnect TR4/16 PCI		(SK-4591)
- *      - Compaq TR 4/16 PCI
- *      - Thomas-Conrad TC4048 4/16 PCI
- *      - 3Com 3C339 Token Link Velocity
- *      - Any ISA or PCI adapter using only the TMS380 chipset
+ *  They are no longer supported by this driver, at least until
+ *  a module gets written for them.
  *
  *  Sources:
  *  	- The hardware related parts of this driver are take from
@@ -27,14 +29,16 @@
  *  	- Also various other drivers in the linux source tree were taken
  *  	  as samples for some tasks.
  *      - TI TMS380 Second-Generation Token Ring User's Guide
- *      - TI datasheets for respective chips
- *	- David Hein at Texas Instruments 
+ *  	- TI datasheets for respective chips
+ *  	- David Hein at Texas Instruments 
+ *  	- Various Madge employees
  *
  *  Maintainer(s):
  *    JS	Jay Schulist		jschlst@turbolinux.com
  *    CG	Christoph Goos		cgoos@syskonnect.de
  *    AF	Adam Fritzler		mid@auk.cx
- *
+ *    MLP       Mike Phillips           phillim@amtrak.com
+ *     
  *  Modification History:
  *	29-Aug-97	CG	Created
  *	04-Apr-98	CG	Fixed problems caused by tok_timer_check
@@ -42,22 +46,33 @@
  *	27-May-98	JS	Formated to Linux Kernel Format
  *	31-May-98	JS	Hacked in PCI support
  *	16-Jun-98	JS	Modulized for multiple cards with one driver
- *         Sep-99	AF      Renamed to tms380tr (supports more than SK's)
+ *	   Sep-99	AF	Renamed to tms380tr (supports more than SK's)
  *      23-Sep-99	AF      Added Compaq and Thomas-Conrad PCI support
  *				Fixed a bug causing double copies on PCI
  *				Fixed for new multicast stuff (2.2/2.3)
  *	25-Sep-99	AF	Uped TPL_NUM from 3 to 9
  *				Removed extraneous 'No free TPL'
+ *	22-Dec-99	AF	Added Madge PCI Mk2 support and generalized
+ *				parts of the initilization procedure.
+ *	30-Dec-99	AF	Turned tms380tr into a library ala 8390.
+ *				Madge support is provided in the abyss module
+ *				Generic PCI support is in the tmspci module.
  *
  *  To do:
- *    1. Selectable 16 Mbps or 4Mbps
- *    2. Multi/Broadcast packet handling (this may have fixed itself)
- *
+ *    1. Multi/Broadcast packet handling (this may have fixed itself)
+ *    2. Write a sktrisa module that includes the old ISA support
+ *    3. Allow modules to load their own microcode
+ *    4. Speed up the BUD process -- freezing the kernel for 3+sec is
+ *         quite unacceptable.
+ *    5. Still a few remaining stalls when the cable is unplugged.
  */
 
-static const char *version = "tms380tr.c: v1.03 29/09/1999 by Christoph Goos, Adam Fritzler\n";
+#ifdef MODULE
+static const char *version = "tms380tr.c: v1.07 21/01/2000 by Christoph Goos, Adam Fritzler\n";
+#endif
 
 #ifdef MODULE
+#define EXPORT_SYMTAB
 #include <linux/module.h>
 #include <linux/version.h>
 #endif
@@ -78,6 +93,7 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -90,45 +106,6 @@
 #include "tms380tr.h"		/* Our Stuff */
 #include "tms380tr_microcode.h"	/* TI microcode for COMMprocessor */
 
-/* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int tms380tr_portlist[] __initdata = {
-	0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,
-	0
-};
-
-/* A zero-terminated list of IRQs to be probed. 
- * Used again after initial probe for tms380tr_chipset_init, called from tms380tr_open.
- */
-static unsigned short tms380tr_irqlist[] = {
-	3, 5, 9, 10, 11, 12, 15,
-	0
-};
-
-/* A zero-terminated list of DMAs to be probed. */
-static int tms380tr_dmalist[] __initdata = {
-	5, 6, 7,
-	0
-};
-
-/* 
- * Table used for card detection and type determination.
- */
-struct cardinfo_table  cardinfo[] = {
-  { 0, 0, 0, 
-    "Unknown TMS380 Token Ring Adapter"},
-  { TMS_ISA, 0, 0, 
-    "SK NET TR 4/16 ISA"},
-  { TMS_PCI, PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TOKENRING, 
-    "Compaq 4/16 TR PCI"},
-  { TMS_PCI, PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_TR, 
-    "SK NET TR 4/16 PCI"},
-  { TMS_PCI, PCI_VENDOR_ID_TCONRAD, PCI_DEVICE_ID_TCONRAD_TOKENRING,
-    "Thomas-Conrad TC4048 PCI 4/16"},
-  { TMS_PCI, PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C339,
-    "3Com Token Link Velocity"},
-  { 0, 0, 0, NULL}
-};
-
 /* Use 0 for production, 1 for verification, 2 for debug, and
  * 3 for very verbose debug.
  */
@@ -137,24 +114,24 @@
 #endif
 static unsigned int tms380tr_debug = TMS380TR_DEBUG;
 
-/* The number of low I/O ports used by the tokencard. */
-#define TMS380TR_IO_EXTENT 32
-
 /* Index to functions, as function prototypes.
  * Alphabetical by function name.
  */
 
+/* "A" */
 /* "B" */
 static int      tms380tr_bringup_diags(struct net_device *dev);
 /* "C" */
 static void	tms380tr_cancel_tx_queue(struct net_local* tp);
 static int 	tms380tr_chipset_init(struct net_device *dev);
 static void 	tms380tr_chk_irq(struct net_device *dev);
+#if 0
 static unsigned char tms380tr_chk_frame(struct net_device *dev, unsigned char *Addr);
+#endif
 static void 	tms380tr_chk_outstanding_cmds(struct net_device *dev);
 static void 	tms380tr_chk_src_addr(unsigned char *frame, unsigned char *hw_addr);
 static unsigned char tms380tr_chk_ssb(struct net_local *tp, unsigned short IrqType);
-static int 	tms380tr_close(struct net_device *dev);
+int	 	tms380tr_close(struct net_device *dev);
 static void 	tms380tr_cmd_status_irq(struct net_device *dev);
 /* "D" */
 static void 	tms380tr_disable_interrupts(struct net_device *dev);
@@ -176,20 +153,15 @@
 static int 	tms380tr_init_card(struct net_device *dev);
 static void 	tms380tr_init_ipb(struct net_local *tp);
 static void 	tms380tr_init_net_local(struct net_device *dev);
-static void 	tms380tr_init_opb(struct net_local *tp);
-static void 	tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int 	tms380tr_isa_chk_card(struct net_device *dev, int ioaddr, struct cardinfo_table **outcard);
-static int      tms380tr_isa_chk_ioaddr(int ioaddr);
+static void 	tms380tr_init_opb(struct net_device *dev);
+void	 	tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+/* "M" */
 /* "O" */
-static int 	tms380tr_open(struct net_device *dev);
+int		tms380tr_open(struct net_device *dev);
 static void	tms380tr_open_adapter(struct net_device *dev);
 /* "P" */
-static int 	tms380tr_pci_chk_card(struct net_device *dev, struct cardinfo_table **outcard);
-int 		tms380tr_probe(struct net_device *dev);
-static int 	tms380tr_probe1(struct net_device *dev, int ioaddr);
 /* "R" */
 static void 	tms380tr_rcv_status_irq(struct net_device *dev);
-static void 	tms380tr_read_addr(struct net_device *dev, unsigned char *Address);
 static int 	tms380tr_read_ptr(struct net_device *dev);
 static void 	tms380tr_read_ram(struct net_device *dev, unsigned char *Data,
 			unsigned short Address, int Length);
@@ -199,6 +171,7 @@
 /* "S" */
 static int 	tms380tr_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void 	tms380tr_set_multicast_list(struct net_device *dev);
+static int	tms380tr_set_mac_address(struct net_device *dev, void *addr);
 /* "T" */
 static void 	tms380tr_timer_chk(unsigned long data);
 static void 	tms380tr_timer_end_wait(unsigned long data);
@@ -207,269 +180,61 @@
 static void 	tms380tr_update_rcv_stats(struct net_local *tp,
 			unsigned char DataPtr[], unsigned int Length);
 /* "W" */
-static void 	tms380tr_wait(unsigned long time);
+void	 	tms380tr_wait(unsigned long time);
 static void 	tms380tr_write_rpl_status(RPL *rpl, unsigned int Status);
 static void 	tms380tr_write_tpl_status(TPL *tpl, unsigned int Status);
 
-/*
- * Check for a network adapter of this type, and return '0' if one exists.
- * If dev->base_addr == 0, probe all likely locations.
- * If dev->base_addr == 1, always return failure.
- */
-int __init tms380tr_probe(struct net_device *dev)
-{
-	int i;
-	int base_addr = dev ? dev->base_addr : 0;
-
-	if(base_addr > 0x1ff)    /* Check a single specified location. */
-		return (tms380tr_probe1(dev, base_addr));
-	else if(base_addr != 0)  /* Don't probe at all. */
-		return (-ENXIO);
-
-	/* 
-	 * Let's check for pci adapters first 
-	 */
-	if (tms380tr_probe1(dev,0) == 0)  /* Success */
-		return 0 ;
-
-	/*
-	 * No pci cards found, let's check for isa
-	 */
+#define SIFREADB(reg) (((struct net_local *)dev->priv)->sifreadb(dev, reg))
+#define SIFWRITEB(val, reg) (((struct net_local *)dev->priv)->sifwriteb(dev, val, reg))
+#define SIFREADW(reg) (((struct net_local *)dev->priv)->sifreadw(dev, reg))
+#define SIFWRITEW(val, reg) (((struct net_local *)dev->priv)->sifwritew(dev, val, reg))
 
-	for(i = 0; tms380tr_portlist[i]; i++)
-	{
-		int ioaddr = tms380tr_portlist[i];
-		if(check_region(ioaddr, TMS380TR_IO_EXTENT)) /* Region already used */
-			continue;
-		if(!tms380tr_probe1(dev, ioaddr))
-			return (0);
-	}
 
-	return (-ENODEV);
-}
 
-struct cardinfo_table * __init tms380tr_pci_getcardinfo(unsigned short vendor, 
-							unsigned short device)
+#if TMS380TR_DEBUG > 0
+static int madgemc_sifprobe(struct net_device *dev)
 {
-	int cur;
-	for (cur = 1; cardinfo[cur].name != NULL; cur++) {
-		if (cardinfo[cur].type == 2) /* PCI */
-		{
-			if ((cardinfo[cur].vendor_id == vendor) && (cardinfo[cur].device_id == device))
-				return &cardinfo[cur];
-		}
-	}
+        unsigned char old, chk1, chk2;
 	
-	return NULL;
-}
+	old = SIFREADB(SIFADR);  /* Get the old SIFADR value */
 
-/*
- * Detect and setup the PCI SysKonnect TR cards in slot order.
- */
-static int __init tms380tr_pci_chk_card(struct net_device *dev, 
-					struct cardinfo_table **outcard)
-{
-	struct pci_dev *pci_device = NULL ; 
-	struct cardinfo_table *card;
-	int i;
-
-	if(!pci_present())
-		return (-1);	/* No PCI present. */
- 
-	while ( (pci_device=pci_find_class(PCI_CLASS_NETWORK_TOKEN_RING<<8, pci_device))) { 
-
-		unsigned int pci_irq_line;
-		unsigned int pci_ioaddr;
-
-		/* Remove I/O space marker in bit 0. */
-		pci_irq_line = pci_device->irq ; 
-		pci_ioaddr = pci_device->resource[0].start ; 
-/*		pci_ioaddr &= ~3; */
-
-		/* Don't return from here, just continue on the card discovery loop - MLP */
-		if (!(card = tms380tr_pci_getcardinfo(pci_device->vendor, pci_device->device)))  
-			continue ; 
-
-		if(check_region(pci_ioaddr, TMS380TR_IO_EXTENT))
-			continue;
-
-		request_region(pci_ioaddr, TMS380TR_IO_EXTENT, card->name);
-		if(request_irq(pci_device->irq, tms380tr_interrupt, SA_SHIRQ,
-				card->name, dev)) { 
-			release_region(pci_ioaddr, TMS380TR_IO_EXTENT) ; 
-			return (-ENODEV); /* continue; ?? */
-		}
-		/* At this point we have found a valid tms380tr PCI TR card. */
-
-		pci_ioaddr &= ~3 ; 
-		dev->base_addr	= pci_ioaddr;
-		dev->irq 	= pci_irq_line;
-		dev->dma	= 0;
-
-		dev->addr_len = 6;
-		tms380tr_read_addr(dev, (unsigned char*)dev->dev_addr);
+        chk1 = 0;       /* Begin with check value 0 */
+        do {
+		madgemc_setregpage(dev, 0);
+                /* Write new SIFADR value */
+		SIFWRITEB(chk1, SIFADR);
+		chk2 = SIFREADB(SIFADR);
+		if (chk2 != chk1)
+			return -1;
 		
-		printk("%s: %s found at %#4x, IRQ %d, ring station ",
-		       dev->name, card->name, pci_ioaddr, dev->irq);
-		printk("%2.2x", dev->dev_addr[0]);
-		for (i = 1; i < 6; i++)
-			printk(":%2.2x", dev->dev_addr[i]);
-		printk(".\n");
-
-		if (outcard)
-			*outcard = card;
+		madgemc_setregpage(dev, 1);
+                /* Read, invert and write */
+		chk2 = SIFREADB(SIFADD);
+		if (chk2 != chk1)
+			return -1;
+
+		madgemc_setregpage(dev, 0);
+                chk2 ^= 0x0FE;
+		SIFWRITEB(chk2, SIFADR);
+
+                /* Read, invert and compare */
+		madgemc_setregpage(dev, 1);
+		chk2 = SIFREADB(SIFADD);
+		madgemc_setregpage(dev, 0);
+                chk2 ^= 0x0FE;
+
+                if(chk1 != chk2)
+                        return (-1);    /* No adapter */
+                chk1 -= 2;
+        } while(chk1 != 0);     /* Repeat 128 times (all byte values) */
+
+	madgemc_setregpage(dev, 0); /* sanity */
+        /* Restore the SIFADR value */
+	SIFWRITEB(old, SIFADR);
 
-		return 0 ; 
-	}
-
- 	return (-1); 
+        return (0);
 }
-
-/*
- * Detect and setup the ISA SysKonnect TR cards.
- */
-static int __init tms380tr_isa_chk_card(struct net_device *dev, int ioaddr,
-					struct cardinfo_table **outcard)
-{
-	int i, err;
-	unsigned long flags;
-	struct cardinfo_table *card = NULL;
-
-	err = tms380tr_isa_chk_ioaddr(ioaddr);
-	if(err < 0)
-		return (-ENODEV);
-
-	if(virt_to_bus((void*)((unsigned long)dev->priv+sizeof(struct net_local)))
-		> ISA_MAX_ADDRESS)
-	{
-		printk("%s: Memory not accessible for DMA\n", dev->name);
-		kfree(dev->priv);
-		return (-EAGAIN);
-	}
-
-	/* FIXME */
-	card = &cardinfo[1];
-
-	/* Grab the region so that no one else tries to probe our ioports. */
-	request_region(ioaddr, TMS380TR_IO_EXTENT, card->name);
-	dev->base_addr = ioaddr;
-
-	/* Autoselect IRQ and DMA if dev->irq == 0 */
-	if(dev->irq == 0)
-	{
-		for(i = 0; tms380tr_irqlist[i] != 0; i++)
-		{
-			dev->irq = tms380tr_irqlist[i];
-			err = request_irq(dev->irq, &tms380tr_interrupt, 0, card->name, dev);
-			if(!err)
-				break;
-		}
-
-		if(tms380tr_irqlist[i] == 0)
-		{
-			printk("%s: AutoSelect no IRQ available\n", dev->name);
-			return (-EAGAIN);
-		}
-	}
-	else
-	{
-		err = request_irq(dev->irq, &tms380tr_interrupt, 0, card->name, dev);
-		if(err)
-		{
-			printk("%s: Selected IRQ not available\n", dev->name);
-			return (-EAGAIN);
-		}
-	}
-
-	/* Always allocate the DMA channel after IRQ and clean up on failure */
-	if(dev->dma == 0)
-	{
-		for(i = 0; tms380tr_dmalist[i] != 0; i++)
-		{
-			dev->dma = tms380tr_dmalist[i];
-			err = request_dma(dev->dma, card->name);
-			if(!err)
-				break;
-		}
-
-		if(dev->dma == 0)
-		{
-			printk("%s: AutoSelect no DMA available\n", dev->name);
-			free_irq(dev->irq, NULL);
-			return (-EAGAIN);
-		}
-	}
-	else
-	{
-		err = request_dma(dev->dma, card->name);
-		if(err)
-		{
-			printk("%s: Selected DMA not available\n", dev->name);
-			free_irq(dev->irq, NULL);
-			return (-EAGAIN);
-		}
-	}
-
-	flags=claim_dma_lock();
-	disable_dma(dev->dma);
-	set_dma_mode(dev->dma, DMA_MODE_CASCADE);
-	enable_dma(dev->dma);
-	release_dma_lock(flags);
-
-	printk("%s: %s found at %#4x, using IRQ %d and DMA %d.\n",
-		dev->name, card->name, ioaddr, dev->irq, dev->dma);
-
-	if (outcard)
-		*outcard = card;
-
-	return (0);
-}
-
-/*
- * Passing an ioaddr of 0 tells us to do a pci card search
- */
-
-static int __init tms380tr_probe1(struct net_device *dev, int ioaddr)
-{
-	static unsigned version_printed = 0;
-	struct net_local *tp;
-	int err;
-	struct cardinfo_table *card = NULL;
-
-	if(tms380tr_debug && version_printed++ == 0)
-		printk(KERN_INFO "%s", version);
-
-#ifndef MODULE
-	dev = init_trdev(dev, 0);
-	if(dev == NULL)
-		return (-ENOMEM);
 #endif
-	if (ioaddr == 0) {
-		err = tms380tr_pci_chk_card(dev, &card);
-	} else {
-		err = tms380tr_isa_chk_card(dev, ioaddr, &card);
-	}
-	if(err < 0)
-		return (-ENODEV);
-
-	/* Setup this devices private information structure */
-	tp = (struct net_local *)kmalloc(sizeof(struct net_local), GFP_KERNEL | GFP_DMA);
-	if(tp == NULL)
-		return (-ENOMEM);
-	memset(tp, 0, sizeof(struct net_local));
-	init_waitqueue_head(&tp->wait_for_tok_int);
-	tp->CardType = card;
-	
-	dev->priv		= tp;
-	dev->init		= tms380tr_init_card;
-	dev->open		= tms380tr_open;
-	dev->stop		= tms380tr_close;
-	dev->do_ioctl		= NULL ; 
-	dev->hard_start_xmit    = tms380tr_send_packet;
-	dev->get_stats		= tms380tr_get_stats;
-	dev->set_multicast_list = &tms380tr_set_multicast_list;
-	return (0);
-}
 
 /* Dummy function */
 static int __init tms380tr_init_card(struct net_device *dev)
@@ -481,42 +246,6 @@
 }
 
 /*
- * This function tests if an adapter is really installed at the
- * given I/O address. Return negative if no adapter at IO addr.
- */
-static int __init tms380tr_isa_chk_ioaddr(int ioaddr)
-{
-	unsigned char old, chk1, chk2;
-
-	old = inb(ioaddr + SIFADR);	/* Get the old SIFADR value */
-
-	chk1 = 0;	/* Begin with check value 0 */
-	do {
-		/* Write new SIFADR value */
-		outb(chk1, ioaddr + SIFADR);
-
-		/* Read, invert and write */
-		chk2 = inb(ioaddr + SIFADD);
-		chk2 ^= 0x0FE;
-		outb(chk2, ioaddr + SIFADR);
-
-		/* Read, invert and compare */
-		chk2 = inb(ioaddr + SIFADD);
-		chk2 ^= 0x0FE;
-
-		if(chk1 != chk2)
-			return (-1);	/* No adapter */
-
-		chk1 -= 2;
-	} while(chk1 != 0);	/* Repeat 128 times (all byte values) */
-
-    	/* Restore the SIFADR value */
-	outb(old, ioaddr + SIFADR);
-
-	return (0);
-}
-
-/*
  * Open/initialize the board. This is called sometime after
  * booting when the 'ifconfig' program is run.
  *
@@ -524,14 +253,14 @@
  * registers that "should" only need to be set once at boot, so that
  * there is non-reboot way to recover if something goes wrong.
  */
-static int tms380tr_open(struct net_device *dev)
+int tms380tr_open(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	int err;
 	
 	/* Reset the hardware here. Don't forget to set the station address. */
 	err = tms380tr_chipset_init(dev);
-	if(err)
+  	if(err)
 	{
 		printk(KERN_INFO "%s: Chipset initialization error\n", 
 			dev->name);
@@ -548,7 +277,6 @@
 
 	printk(KERN_INFO "%s: Adapter RAM size: %dK\n", 
 	       dev->name, tms380tr_read_ptr(dev));
-
 	tms380tr_enable_interrupts(dev);
 	tms380tr_open_adapter(dev);
 
@@ -566,8 +294,8 @@
 	/* If AdapterVirtOpenFlag is 1, the adapter is now open for use */
 	if(tp->AdapterVirtOpenFlag == 0)
 	{
-	  tms380tr_disable_interrupts(dev);
-	  return (-1);
+		tms380tr_disable_interrupts(dev);
+		return (-1);
 	}
 
 	dev->start = 1;
@@ -579,10 +307,6 @@
 	tp->timer.function	= tms380tr_timer_chk;
 	tp->timer.data		= (unsigned long)dev;
 	add_timer(&tp->timer);
-	
-#ifdef MODULE
-	MOD_INC_USE_COUNT;
-#endif
 
 	return (0);
 }
@@ -610,47 +334,20 @@
 static int tms380tr_chipset_init(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
-	unsigned char PosReg, Tmp;
-	int i, err;
+	int err;
 
 	tms380tr_init_ipb(tp);
-	tms380tr_init_opb(tp);
+	tms380tr_init_opb(dev);
 	tms380tr_init_net_local(dev);
 
-	/* Set pos register: selects irq and dma channel.
-	 * Only for ISA bus adapters.
-	 */
-	if(dev->dma > 0)
-	{
-		PosReg = 0;
-		for(i = 0; tms380tr_irqlist[i] != 0; i++)
-		{
-			if(tms380tr_irqlist[i] == dev->irq)
-				break;
-		}
-
-		/* Choose default cycle time, 500 nsec   */
-		PosReg |= CYCLE_TIME << 2;
-		PosReg |= i << 4;
-		i = dev->dma - 5;
-		PosReg |= i;
-
-		if(tp->DataRate == SPEED_4)
-			PosReg |= LINE_SPEED_BIT;
-		else
-			PosReg &= ~LINE_SPEED_BIT;
-
-		outb(PosReg, dev->base_addr + POSREG);
-		Tmp = inb(dev->base_addr + POSREG);
-		if((Tmp & ~CYCLE_TIME) != (PosReg & ~CYCLE_TIME))
-			printk(KERN_INFO "%s: POSREG error\n", dev->name);
-	}
 	err = tms380tr_reset_adapter(dev);
 	if(err < 0)
 		return (-1);
+
 	err = tms380tr_bringup_diags(dev);
 	if(err < 0)
 		return (-1);
+
 	err = tms380tr_init_adapter(dev);
 	if(err < 0)
 		return (-1);
@@ -690,7 +387,7 @@
 
 	skb_queue_head_init(&tp->SendSkbQueue);
 	tp->QueueSkb = MAX_TX_QUEUE;
-
+	
 	/* Create circular chain of transmit lists */
 	for (i = 0; i < TPL_NUM; i++)
 	{
@@ -713,7 +410,7 @@
 		tp->Rpl[i].NextRPLAddr = htonl((unsigned long) virt_to_bus(&tp->Rpl[(i+1) % RPL_NUM]));
 		tp->Rpl[i].Status = (RX_VALID | RX_START_FRAME | RX_END_FRAME | RX_FRAME_IRQ);
 		tp->Rpl[i].FrameSize = 0;
-		tp->Rpl[i].FragList[0].DataCount = SWAPB(tp->MaxPacketSize);
+		tp->Rpl[i].FragList[0].DataCount = cpu_to_be16((unsigned short)tp->MaxPacketSize);
 
 		/* Alloc skb and point adapter to data area */
 		tp->Rpl[i].Skb = dev_alloc_skb(tp->MaxPacketSize);
@@ -731,7 +428,7 @@
 			skb_put(tp->Rpl[i].Skb, tp->MaxPacketSize);
 
 			/* data unreachable for DMA ? then use local buffer */
-			if(tp->CardType->type == TMS_ISA && virt_to_bus(tp->Rpl[i].Skb->data) + tp->MaxPacketSize > ISA_MAX_ADDRESS)
+			if(tp->dmalimit && virt_to_bus(tp->Rpl[i].Skb->data) + tp->MaxPacketSize > tp->dmalimit)
 			{
 				tp->Rpl[i].SkbStat = SKB_DATA_COPY;
 				tp->Rpl[i].FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[i]));
@@ -780,28 +477,37 @@
 /*
  * Initializes the open parameter block.
  */
-static void tms380tr_init_opb(struct net_local *tp)
+static void tms380tr_init_opb(struct net_device *dev)
 {
+	struct net_local *tp;
 	unsigned long Addr;
 	unsigned short RplSize    = RPL_SIZE;
 	unsigned short TplSize    = TPL_SIZE;
 	unsigned short BufferSize = BUFFER_SIZE;
+	int i;
+
+	tp = (struct net_local *)dev->priv;
 
 	tp->ocpl.OPENOptions 	 = 0;
 	tp->ocpl.OPENOptions 	|= ENABLE_FULL_DUPLEX_SELECTION;
 	tp->ocpl.FullDuplex 	 = 0;
 	tp->ocpl.FullDuplex 	|= OPEN_FULL_DUPLEX_OFF;
 
-	/* Fixme: If mac address setable:
-	 * for (i=0; i<LENGTH_OF_ADDRESS; i++)
-	 *	mac->Vam->ocpl.NodeAddr[i] = mac->CurrentAddress[i];
+        /* 
+	 * Set node address 
+	 *
+	 * We go ahead and put it in the OPB even though on
+	 * most of the generic adapters this isn't required.
+	 * Its simpler this way.  -- ASF
 	 */
+        for (i=0;i<6;i++)
+                tp->ocpl.NodeAddr[i] = ((unsigned char *)dev->dev_addr)[i];
 
 	tp->ocpl.GroupAddr	 = 0;
 	tp->ocpl.FunctAddr	 = 0;
-	tp->ocpl.RxListSize	 = SWAPB(RplSize);
-	tp->ocpl.TxListSize	 = SWAPB(TplSize);
-	tp->ocpl.BufSize	 = SWAPB(BufferSize);
+	tp->ocpl.RxListSize	 = cpu_to_be16((unsigned short)RplSize);
+	tp->ocpl.TxListSize	 = cpu_to_be16((unsigned short)TplSize);
+	tp->ocpl.BufSize	 = cpu_to_be16((unsigned short)BufferSize);
 	tp->ocpl.Reserved	 = 0;
 	tp->ocpl.TXBufMin	 = TX_BUF_MIN;
 	tp->ocpl.TXBufMax	 = TX_BUF_MAX;
@@ -836,7 +542,7 @@
  */
 static void tms380tr_disable_interrupts(struct net_device *dev)
 {
-	outb(0, dev->base_addr + SIFACL);
+	SIFWRITEB(0, SIFACL);
 
 	return;
 }
@@ -847,7 +553,7 @@
  */
 static void tms380tr_enable_interrupts(struct net_device *dev)
 {
-	outb(ACL_SINTEN, dev->base_addr + SIFACL);
+	SIFWRITEB(ACL_SINTEN, SIFACL);
 
 	return;
 }
@@ -948,8 +654,7 @@
 
 		tp->QueueSkb++;
 		/* Is buffer reachable for Busmaster-DMA? */
-		if(tp->CardType->type == TMS_ISA && virt_to_bus((void*)(((long) skb->data) + skb->len))
-			> ISA_MAX_ADDRESS)
+		if(tp->dmalimit && virt_to_bus((void*)(((long) skb->data) + skb->len)) > tp->dmalimit)
 		{
 			/* Copy frame to local buffer */
 			i 	= tp->TplFree->TPLIndex;
@@ -975,11 +680,11 @@
     
 		/* Save the skb for delayed return of skb to system */
 		tpl->Skb = skb;
-		tpl->FragList[0].DataCount = (unsigned short) SWAPB(length);
+		tpl->FragList[0].DataCount = cpu_to_be16((unsigned short)length);
 		tpl->FragList[0].DataAddr  = htonl(virt_to_bus(newbuf));
 
 		/* Write the data length in the transmit list. */
-		tpl->FrameSize 	= (unsigned short) SWAPB(length);
+		tpl->FrameSize 	= cpu_to_be16((unsigned short)length);
 		tpl->MData 	= newbuf;
 
 		/* Transmit the frame and set the status values. */
@@ -1057,48 +762,41 @@
 /*
  * The typical workload of the driver: Handle the network interface interrupts.
  */
-static void tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+void tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *tp;
-	int ioaddr;
 	unsigned short irq_type;
 
-	if(dev == NULL)
-	{
+	if(dev == NULL) {
 		printk("%s: irq %d for unknown device.\n", dev->name, irq);
 		return;
 	}
 
 	dev->interrupt = 1;
 
-	ioaddr = dev->base_addr;
 	tp = (struct net_local *)dev->priv;
 
-	irq_type = inw(ioaddr + SIFSTS);
+	irq_type = SIFREADW(SIFSTS);
 
-	while(irq_type & STS_SYSTEM_IRQ)
-	{
+	while(irq_type & STS_SYSTEM_IRQ) {
 		irq_type &= STS_IRQ_MASK;
 
-		if(!tms380tr_chk_ssb(tp, irq_type))
-		{
+		if(!tms380tr_chk_ssb(tp, irq_type)) {
 			printk(KERN_INFO "%s: DATA LATE occurred\n", dev->name);
 			break;
 		}
 
-		switch(irq_type)
-		{
-			case STS_IRQ_RECEIVE_STATUS:
-				tms380tr_reset_interrupt(dev);
-				tms380tr_rcv_status_irq(dev);
-				break;
+		switch(irq_type) {
+		case STS_IRQ_RECEIVE_STATUS:
+			tms380tr_reset_interrupt(dev);
+			tms380tr_rcv_status_irq(dev);
+			break;
 
-			case STS_IRQ_TRANSMIT_STATUS:
-				/* Check if TRANSMIT.HALT command is complete */
-				if(tp->ssb.Parm[0] & COMMAND_COMPLETE)
-				{
-					tp->TransmitCommandActive = 0;
+		case STS_IRQ_TRANSMIT_STATUS:
+			/* Check if TRANSMIT.HALT command is complete */
+			if(tp->ssb.Parm[0] & COMMAND_COMPLETE) {
+				tp->TransmitCommandActive = 0;
 					tp->TransmitHaltScheduled = 0;
 
 					/* Issue a new transmit command. */
@@ -1109,40 +807,51 @@
 				tms380tr_tx_status_irq(dev);
 				break;
 
-			case STS_IRQ_COMMAND_STATUS:
-				/* The SSB contains status of last command
-				 * other than receive/transmit.
-				 */
-				tms380tr_cmd_status_irq(dev);
-				break;
-
-			case STS_IRQ_SCB_CLEAR:
-				/* The SCB is free for another command. */
-				tp->ScbInUse = 0;
-				tms380tr_chk_outstanding_cmds(dev);
-				break;
-
-			case STS_IRQ_RING_STATUS:
-				tms380tr_ring_status_irq(dev);
-				break;
+		case STS_IRQ_COMMAND_STATUS:
+			/* The SSB contains status of last command
+			 * other than receive/transmit.
+			 */
+			tms380tr_cmd_status_irq(dev);
+			break;
+			
+		case STS_IRQ_SCB_CLEAR:
+			/* The SCB is free for another command. */
+			tp->ScbInUse = 0;
+			tms380tr_chk_outstanding_cmds(dev);
+			break;
+			
+		case STS_IRQ_RING_STATUS:
+			tms380tr_ring_status_irq(dev);
+			break;
 
-			case STS_IRQ_ADAPTER_CHECK:
-				tms380tr_chk_irq(dev);
-				break;
+		case STS_IRQ_ADAPTER_CHECK:
+			tms380tr_chk_irq(dev);
+			break;
 
-			default:
-				printk(KERN_INFO "Unknown Token Ring IRQ\n");
-				break;
+		case STS_IRQ_LLC_STATUS:
+			printk(KERN_DEBUG "tms380tr: unexpected LLC status IRQ\n");
+			break;
+			
+		case STS_IRQ_TIMER:
+			printk(KERN_DEBUG "tms380tr: unexpected Timer IRQ\n");
+			break;
+			
+		case STS_IRQ_RECEIVE_PENDING:
+			printk(KERN_DEBUG "tms380tr: unexpected Receive Pending IRQ\n");
+			break;
+			
+		default:
+			printk(KERN_INFO "Unknown Token Ring IRQ (0x%04x)\n", irq_type);
+			break;
 		}
 
 		/* Reset system interrupt if not already done. */
 		if(irq_type != STS_IRQ_TRANSMIT_STATUS
-			&& irq_type != STS_IRQ_RECEIVE_STATUS)
-		{
+			&& irq_type != STS_IRQ_RECEIVE_STATUS) {
 			tms380tr_reset_interrupt(dev);
 		}
 
-		irq_type = inw(ioaddr + SIFSTS);
+		irq_type = SIFREADW(SIFSTS);
 	}
 
 	dev->interrupt = 0;
@@ -1436,7 +1145,7 @@
 /*
  * The inverse routine to tms380tr_open().
  */
-static int tms380tr_close(struct net_device *dev)
+int tms380tr_close(struct net_device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	dev->tbusy = 1;
@@ -1469,13 +1178,9 @@
 		release_dma_lock(flags);
 	}
 	
-	outw(0xFF00, dev->base_addr + SIFCMD);
-	if(dev->dma > 0)
-		outb(0xff, dev->base_addr + POSREG);
-
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
-#endif
+	SIFWRITEW(0xFF00, SIFCMD);
+	if(dev->dma > 0) /* what the? */
+		SIFWRITEB(0xff, POSREG);
 
 	tms380tr_cancel_tx_queue(tp);
 
@@ -1549,7 +1254,7 @@
 /*
  * Wait for some time (microseconds)
  */
-static void tms380tr_wait(unsigned long time)
+void tms380tr_wait(unsigned long time)
 {
 #if 0
 	long tmp;
@@ -1570,7 +1275,6 @@
  */
 static void tms380tr_exec_sifcmd(struct net_device *dev, unsigned int WriteValue)
 {
-	int ioaddr = dev->base_addr;
 	unsigned short cmd;
 	unsigned short SifStsValue;
 	unsigned long loop_counter;
@@ -1579,9 +1283,9 @@
 	cmd = (unsigned short)WriteValue;
 	loop_counter = 0,5 * 800000;
 	do {
-		SifStsValue = inw(ioaddr + SIFSTS);
+		SifStsValue = SIFREADW(SIFSTS);
 	} while((SifStsValue & CMD_INTERRUPT_ADAPTER) && loop_counter--);
-	outw(cmd, ioaddr + SIFCMD);
+	SIFWRITEW(cmd, SIFCMD);
 
 	return;
 }
@@ -1595,22 +1299,19 @@
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned short *fw_ptr = (unsigned short *)&tms380tr_code;
 	unsigned short count, c;
-	int ioaddr = dev->base_addr;
 
 	/* Hardware adapter reset */
-	outw(ACL_ARESET, ioaddr + SIFACL);
+	SIFWRITEW(ACL_ARESET, SIFACL);
 	tms380tr_wait(40);
 	
-	c = inw(ioaddr + SIFACL);
+	c = SIFREADW(SIFACL);
 	tms380tr_wait(20);
 
 	if(dev->dma == 0)	/* For PCI adapters */
 	{
-		c &= ~(ACL_SPEED4 | ACL_SPEED16);	/* Clear bits */
-		if(tp->DataRate == SPEED_4)
-			c |= ACL_SPEED4;		/* Set 4Mbps */
-		else
-			c |= ACL_SPEED16;		/* Set 16Mbps */
+		c &= ~(ACL_NSELOUT0 | ACL_NSELOUT1);	/* Clear bits */
+		if(tp->setnselout)
+		  c |= (*tp->setnselout)(dev);
 	}
 
 	/* In case a command is pending - forget it */
@@ -1618,18 +1319,20 @@
 
 	c &= ~ACL_ARESET;		/* Clear adapter reset bit */
 	c |=  ACL_CPHALT;		/* Halt adapter CPU, allow download */
+	c |= ACL_BOOT;
+	c |= ACL_SINTEN;
 	c &= ~ACL_PSDMAEN;		/* Clear pseudo dma bit */
-	outw(c, ioaddr + SIFACL);
+	SIFWRITEW(c, SIFACL);
 	tms380tr_wait(40);
 
 	/* Download firmware via DIO interface: */
 	do {
 		/* Download first address part */
-		outw(*fw_ptr, ioaddr + SIFADX);
+		SIFWRITEW(*fw_ptr, SIFADX);
 		fw_ptr++;
 
 		/* Download second address part */
-		outw(*fw_ptr, ioaddr + SIFADD);
+		SIFWRITEW(*fw_ptr, SIFADD);
 		fw_ptr++;
 
 		if((count = *fw_ptr) != 0)	/* Load loop counter */
@@ -1637,17 +1340,17 @@
 			fw_ptr++;	/* Download block data */
 			for(; count > 0; count--)
 			{
-				outw(*fw_ptr, ioaddr + SIFINC);
+				SIFWRITEW(*fw_ptr, SIFINC);
 				fw_ptr++;
 			}
 		}
 		else	/* Stop, if last block downloaded */
 		{
-			c = inw(ioaddr + SIFACL);
+			c = SIFREADW(SIFACL);
 			c &= (~ACL_CPHALT | ACL_SINTEN);
 
 			/* Clear CPHALT and start BUD */
-			outw(c, ioaddr + SIFACL);
+			SIFWRITEW(c, SIFACL);
 			return (1);
 		}
 	} while(count == 0);
@@ -1663,7 +1366,6 @@
 {
 	int loop_cnt, retry_cnt;
 	unsigned short Status;
-	int ioaddr = dev->base_addr;
 
 	tms380tr_wait(HALF_SECOND);
 	tms380tr_exec_sifcmd(dev, EXEC_SOFT_RESET);
@@ -1679,7 +1381,7 @@
 		do {			/* Inspect BUD results */
 			loop_cnt--;
 			tms380tr_wait(HALF_SECOND);
-			Status = inw(ioaddr + SIFSTS);
+			Status = SIFREADW(SIFSTS);
 			Status &= STS_MASK;
 
 			if(tms380tr_debug > 3)
@@ -1701,11 +1403,16 @@
 		}
 	} while(retry_cnt > 0);
 
-	Status = inw(ioaddr + SIFSTS);
-	Status &= STS_ERROR_MASK;	/* Hardware error occurred! */
-
-	printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n",
-		dev->name, Status);
+	Status = SIFREADW(SIFSTS);
+	
+	/* Hardware error occurred! */
+	Status &= 0x001f;
+	if (Status & 0x0010)
+		printk(KERN_INFO "%s: BUD Error: Timeout\n", dev->name);
+	else if ((Status & 0x000f) > 6)
+		printk(KERN_INFO "%s: BUD Error: Illegal Failure\n", dev->name);
+	else
+		printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n", dev->name, Status & 0x000f);
 
 	return (-1);
 }
@@ -1727,7 +1434,6 @@
 	unsigned char *sb_ptr = (unsigned char *) &tp->ssb;
 	unsigned short Status;
 	int i, loop_cnt, retry_cnt;
-	int ioaddr = dev->base_addr;
 
 	/* Normalize: byte order low/high, word order high/low! (only IPB!) */
 	tp->ipb.SCB_Addr = SWAPW(virt_to_bus(&tp->scb));
@@ -1740,14 +1446,14 @@
 		retry_cnt--;
 
 		/* Transfer initialization block */
-		outw(0x0001, ioaddr + SIFADX);
+		SIFWRITEW(0x0001, SIFADX);
 
 		/* To address 0001:0A00 of adapter RAM */
-		outw(0x0A00, ioaddr + SIFADD);
+		SIFWRITEW(0x0A00, SIFADD);
 
 		/* Write 11 words to adapter RAM */
 		for(i = 0; i < 11; i++)
-			outw(ipb_ptr[i], ioaddr + SIFINC);
+			SIFWRITEW(ipb_ptr[i], SIFINC);
 
 		/* Execute SCB adapter command */
 		tms380tr_exec_sifcmd(dev, CMD_EXECUTE);
@@ -1761,7 +1467,7 @@
 			tms380tr_wait(HALF_SECOND);
 
 			/* Mask interesting status bits */
-			Status = inw(ioaddr + SIFSTS);
+			Status = SIFREADW(SIFSTS);
 			Status &= STS_MASK;
 		} while(((Status &(STS_INITIALIZE | STS_ERROR | STS_TEST)) != 0)
 			&& ((Status & STS_ERROR) == 0) && (loop_cnt != 0));
@@ -1792,7 +1498,7 @@
 			if((Status & STS_ERROR) != 0)
 			{
 				/* Initialization error occurred */
-				Status = inw(ioaddr + SIFSTS);
+				Status = SIFREADW(SIFSTS);
 				Status &= STS_ERROR_MASK;
 				/* ShowInitialisationErrorCode(Status); */
 				return (-1); /* Unrecoverable error */
@@ -1820,7 +1526,6 @@
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	unsigned long Addr = 0;
-	unsigned char i = 0;
 
 	if(tp->CMDqueue == 0)
 		return;		/* No command execution */
@@ -1839,14 +1544,6 @@
 			/* Execute OPEN command	*/
 			tp->CMDqueue ^= OC_OPEN;
 
-			/* Copy the 18 bytes of the product ID */
-			while((tp->CardType->name[i] != '\0') 
-			      && (i < PROD_ID_SIZE))
-			{
-				tp->ProductID[i] = tp->CardType->name[i];
-				i++;
-			}
-
 			Addr = htonl(virt_to_bus(&tp->ocpl));
 			tp->scb.Parm[0] = LOWORD(Addr);
 			tp->scb.Parm[1] = HIWORD(Addr);
@@ -2001,7 +1698,7 @@
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 
-	tp->CurrentRingStatus = SWAPB(tp->ssb.Parm[0]);
+	tp->CurrentRingStatus = be16_to_cpu((unsigned short)tp->ssb.Parm[0]);
 
 	/* First: fill up statistics */
 	if(tp->ssb.Parm[0] & SIGNAL_LOSS)
@@ -2071,19 +1768,18 @@
 {
 	int i;
 	unsigned short AdapterCheckBlock[4];
-	unsigned short ioaddr = dev->base_addr;
 	struct net_local *tp = (struct net_local *)dev->priv;
 
 	tp->AdapterOpenFlag = 0;	/* Adapter closed now */
 
 	/* Page number of adapter memory */
-	outw(0x0001, ioaddr + SIFADX);
+	SIFWRITEW(0x0001, SIFADX);
 	/* Address offset */
-	outw(CHECKADDR, ioaddr + SIFADR);
+	SIFWRITEW(CHECKADDR, SIFADR);
 
 	/* Reading 8 byte adapter check block. */
 	for(i = 0; i < 4; i++)
-		AdapterCheckBlock[i] = inw(ioaddr + SIFINC);
+		AdapterCheckBlock[i] = SIFREADW(SIFINC);
 
 	if(tms380tr_debug > 3)
 	{
@@ -2234,8 +1930,8 @@
 	tms380tr_read_ram(dev, (unsigned char *)&tp->intptrs.BurnedInAddrPtr,
 			ADAPTER_INT_PTRS, 16);
 	tms380tr_read_ram(dev, (unsigned char *)&adapterram,
-			(unsigned short)SWAPB(tp->intptrs.AdapterRAMPtr), 2);
-	return SWAPB(adapterram); 
+			cpu_to_be16((unsigned short)tp->intptrs.AdapterRAMPtr), 2);
+	return be16_to_cpu(adapterram); 
 }
 
 /*
@@ -2246,22 +1942,21 @@
 {
 	int i;
 	unsigned short old_sifadx, old_sifadr, InWord;
-	unsigned short ioaddr = dev->base_addr;
 
 	/* Save the current values */
-	old_sifadx = inw(ioaddr + SIFADX);
-	old_sifadr = inw(ioaddr + SIFADR);
+	old_sifadx = SIFREADW(SIFADX);
+	old_sifadr = SIFREADW(SIFADR);
 
 	/* Page number of adapter memory */
-	outw(0x0001, ioaddr + SIFADX);
+	SIFWRITEW(0x0001, SIFADX);
 	/* Address offset in adapter RAM */
-	outw(Address, ioaddr + SIFADR);
+        SIFWRITEW(Address, SIFADR);
 
 	/* Copy len byte from adapter memory to system data area. */
 	i = 0;
 	for(;;)
 	{
-		InWord = inw(ioaddr + SIFINC);
+		InWord = SIFREADW(SIFINC);
 
 		*(Data + i) = HIBYTE(InWord);	/* Write first byte */
 		if(++i == Length)		/* All is done break */
@@ -2273,30 +1968,8 @@
 	}
 
 	/* Restore original values */
-	outw(old_sifadx, ioaddr + SIFADX);
-	outw(old_sifadr, ioaddr + SIFADR);
-
-	return;
-}
-
-/*
- * Reads MAC address from adapter ROM.
- */
-static void tms380tr_read_addr(struct net_device *dev, unsigned char *Address)
-{
-	int i, In;
-	unsigned short ioaddr = dev->base_addr;
-
-	/* Address: 0000:0000 */
-	outw(0, ioaddr + SIFADX);
-	outw(0, ioaddr + SIFADR);
-
-	/* Read six byte MAC address data */
-	for(i = 0; i < 6; i++)
-	{
-		In = inw(ioaddr + SIFINC);
-		*(Address + i) = (unsigned char)(In >> 8);
-	}
+	SIFWRITEW(old_sifadx, SIFADX);
+	SIFWRITEW(old_sifadr, SIFADR);
 
 	return;
 }
@@ -2447,7 +2120,7 @@
 		/* Get the frame size (Byte swap for Intel).
 		 * Do this early (see workaround comment below)
 		 */
-		Length = (unsigned short)SWAPB(rpl->FrameSize);
+		Length = be16_to_cpu((unsigned short)rpl->FrameSize);
 
 		/* Check if the Frame_Start, Frame_End and
 		 * Frame_Complete bits are set.
@@ -2463,15 +2136,16 @@
 			 * Length2 is there because there have also been
 			 * cases where the FrameSize was partially written
 			 */
-			Length2 = (unsigned short)SWAPB(rpl->FrameSize);
+			Length2 = be16_to_cpu((unsigned short)rpl->FrameSize);
 
 			if(Length == 0 || Length != Length2)
 			{
 				tp->RplHead = SaveHead;
 				break;	/* Return to tms380tr_interrupt */
 			}
-#if 0	/* This might happen for multicast or broadcast packets.
-	   The upper layers are expected to handle this, not here */
+#if 0  		/* This might happen for multicast or broadcast packets.
+		   The upper layers are expected to handle this, not here */
+
 			/* Drop frames sent by myself */
 			if(tms380tr_chk_frame(dev, rpl->MData))
 			{
@@ -2552,8 +2226,7 @@
 			skb_put(rpl->Skb, tp->MaxPacketSize);
 
 			/* Data unreachable for DMA ? then use local buffer */
-			if(tp->CardType->type == TMS_ISA && virt_to_bus(rpl->Skb->data) + tp->MaxPacketSize
-			   > ISA_MAX_ADDRESS)
+			if(tp->dmalimit && virt_to_bus(rpl->Skb->data) + tp->MaxPacketSize > tp->dmalimit)
 			{
 				rpl->SkbStat = SKB_DATA_COPY;
 				rpl->FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[rpl->RPLIndex]));
@@ -2568,7 +2241,7 @@
 			}
 		}
 
-		rpl->FragList[0].DataCount = SWAPB(tp->MaxPacketSize);
+		rpl->FragList[0].DataCount = cpu_to_be16((unsigned short)tp->MaxPacketSize);
 		rpl->FrameSize = 0;
 
 		/* Pass the last RPL back to the adapter */
@@ -2619,6 +2292,7 @@
 	return;
 }
 
+#if 0
 /*
  * Check if it is a frame of myself. Compare source address with my current
  * address in reverse direction, and mask out the TR_RII.
@@ -2639,6 +2313,20 @@
 
 	return (1);  /* It is my frame. */
 }
+#endif
+
+static int tms380tr_set_mac_address(struct net_device *dev, void *addr)
+{
+	struct net_local *tp = (struct net_local *)dev->priv;
+	struct sockaddr *saddr = addr;
+	
+	if (tp->AdapterOpenFlag || tp->AdapterVirtOpenFlag) {
+		printk(KERN_WARNING "%s: Cannot set MAC/LAA address while card is open\n", dev->name);
+		return -EIO;
+	}
+	memcpy(dev->dev_addr, saddr->sa_data, dev->addr_len);
+	return 0;
+}
 
 #if TMS380TR_DEBUG > 0
 /*
@@ -2651,80 +2339,73 @@
 	for (i = 0, j = 0; i < length / 8; i++, j += 8)
 	{
 		printk(KERN_DEBUG "%02x %02x %02x %02x %02x %02x %02x %02x\n",
-			Data[j+0],Data[j+1],Data[j+2],Data[j+3],
-			Data[j+4],Data[j+5],Data[j+6],Data[j+7]);
+		       Data[j+0],Data[j+1],Data[j+2],Data[j+3],
+		       Data[j+4],Data[j+5],Data[j+6],Data[j+7]);
 	}
 
 	return;
 }
 #endif
 
-#ifdef MODULE
+int tmsdev_init(struct net_device *dev)
+{
+	if (dev->priv == NULL)
+	{
+		struct net_local *tms_local;
+		
+		dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL | GFP_DMA);
+		if (dev->priv == NULL)
+			return -ENOMEM;
+		memset(dev->priv, 0, sizeof(struct net_local));
+		tms_local = (struct net_local *)dev->priv;
+		init_waitqueue_head(&tms_local->wait_for_tok_int);
+	}
+	
+	/* These can be overridden by the card driver if needed */
+	dev->init		= tms380tr_init_card;
+	dev->open		= tms380tr_open;
+	dev->stop		= tms380tr_close;
+	dev->do_ioctl		= NULL; 
+	dev->hard_start_xmit	= tms380tr_send_packet;
+	dev->get_stats		= tms380tr_get_stats;
+	dev->set_multicast_list = &tms380tr_set_multicast_list;
+	dev->set_mac_address	= tms380tr_set_mac_address;
 
-static struct net_device* dev_tms380tr[TMS380TR_MAX_ADAPTERS];
-static int io[TMS380TR_MAX_ADAPTERS]	= { 0, 0 };
-static int irq[TMS380TR_MAX_ADAPTERS] 	= { 0, 0 };
-static int mem[TMS380TR_MAX_ADAPTERS] 	= { 0, 0 };
-
-MODULE_PARM(io,  "1-" __MODULE_STRING(TMS380TR_MAX_ADAPTERS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(TMS380TR_MAX_ADAPTERS) "i");
-MODULE_PARM(mem, "1-" __MODULE_STRING(TMS380TR_MAX_ADAPTERS) "i");
+	return 0;
+}
 
-int init_module(void)
-{
-	int i;
+#ifdef MODULE
 
-	for(i = 0; i < TMS380TR_MAX_ADAPTERS; i++)
-	{
-		irq[i] = 0;
-		mem[i] = 0;
-		dev_tms380tr[i] = NULL;
-		dev_tms380tr[i] = init_trdev(dev_tms380tr[i], 0);
-		if(dev_tms380tr[i] == NULL)
-			return (-ENOMEM);
-
-		dev_tms380tr[i]->base_addr = io[i];
-		dev_tms380tr[i]->irq       = irq[i];
-		dev_tms380tr[i]->mem_start = mem[i];
-		dev_tms380tr[i]->init      = &tms380tr_probe;
-
-		if(register_trdev(dev_tms380tr[i]) != 0)
-		{
-			kfree_s(dev_tms380tr[i], sizeof(struct net_device));
-			dev_tms380tr[i] = NULL;
-			if(i == 0)
-			{
-				printk("tms380tr: register_trdev() returned non-zero.\n");
-				return (-EIO);
-			}
-			else
-				return (0);
-		} 
+EXPORT_SYMBOL(tms380tr_open);
+EXPORT_SYMBOL(tms380tr_close);
+EXPORT_SYMBOL(tms380tr_interrupt);
+EXPORT_SYMBOL(tmsdev_init);
+EXPORT_SYMBOL(tms380tr_wait);
 
-	}
+struct module *TMS380_module = NULL;
 
-	return (0);
+int init_module(void)
+{
+	printk("%s", version);
+	
+	TMS380_module = &__this_module;
+	return 0;
 }
 
 void cleanup_module(void)
 {
-	int i;
-
-	for(i = 0; i < TMS380TR_MAX_ADAPTERS; i++)
-	{
-		if(dev_tms380tr[i])
-		{
-			unregister_trdev(dev_tms380tr[i]);
-			release_region(dev_tms380tr[i]->base_addr, TMS380TR_IO_EXTENT);
-			if(dev_tms380tr[i]->irq)
-				free_irq(dev_tms380tr[i]->irq, dev_tms380tr[i]);
-			if(dev_tms380tr[i]->dma > 0)
-				free_dma(dev_tms380tr[i]->dma);
-			if(dev_tms380tr[i]->priv)
-				kfree_s(dev_tms380tr[i]->priv, sizeof(struct net_local));
-			kfree_s(dev_tms380tr[i], sizeof(struct net_device));
-			dev_tms380tr[i] = NULL;
-		}
-	}
+	TMS380_module = NULL;
 }
-#endif /* MODULE */
+#endif
+
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tms380tr.c"
+ *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tms380tr.c"
+ *  c-set-style "K&R"
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -ru --new-file 2.3.40.clean/drivers/net/tokenring/tms380tr.h 2.3.40/drivers/net/tokenring/tms380tr.h
--- 2.3.40.clean/drivers/net/tokenring/tms380tr.h	Thu Oct 14 21:22:09 1999
+++ 2.3.40/drivers/net/tokenring/tms380tr.h	Sun Jan 23 01:07:11 2000
@@ -1,7 +1,9 @@
-/* tms380tr.h: TI TMS380 Token Ring driver for Linux
+/* 
+ * tms380tr.h: TI TMS380 Token Ring driver for Linux
  *
  * Authors:
  * - Christoph Goos <cgoos@syskonnect.de>
+ * - Adam Fritzler <mid@auk.cx>
  */
 
 #ifndef __LINUX_TMS380TR_H
@@ -9,6 +11,13 @@
 
 #ifdef __KERNEL__
 
+/* module prototypes */
+int tms380tr_open(struct net_device *dev);
+int tms380tr_close(struct net_device *dev);
+void tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+int tmsdev_init(struct net_device *dev);
+void tms380tr_wait(unsigned long time);
+
 #define TMS380TR_MAX_ADAPTERS 7
 
 #define SEND_TIMEOUT 10*HZ
@@ -30,9 +39,6 @@
 /*  --------------------------------------------------------------  */
 /*------------------------------------------------------------------*/
 
-/* Swap bytes of a word.                        */
-#define SWAPB(x) (((unsigned short)((x) << 8)) | ((unsigned short)((x) >> 8)))
-
 /* Swap words of a long.                        */
 #define SWAPW(x) (((x) << 16) | ((x) >> 16))
 
@@ -51,24 +57,34 @@
 
 
 /* Token ring adapter I/O addresses for normal mode. */
-#define SIFDAT      		0L	/* SIF/DMA data. */
-#define SIFINC      		2L  	/* IO Word data with auto increment. */
-#define SIFINH      		3L  	/* IO Byte data with auto increment. */
-#define SIFADR      		4L  	/* SIF/DMA Address. */
-#define SIFCMD      		6L  	/* SIF Command. */
-#define SIFSTS      		6L  	/* SIF Status. */
-#define SIFACL      		8L  	/* SIF Adapter Control Register. */
-#define SIFADD      		10L 	/* SIF/DMA Address. */
-#define SIFADX      		12L
-#define DMALEN      		14L 	/* SIF DMA length. */
-#define POSREG      		16L 	/* Adapter Program Option Select (POS)
+
+/*
+ * The SIF registers.  Common to all adapters.
+ */
+/* Basic SIF (SRSX = 0) */
+#define SIFDAT      		0x00	/* SIF/DMA data. */
+#define SIFINC      		0x02  	/* IO Word data with auto increment. */
+#define SIFINH      		0x03  	/* IO Byte data with auto increment. */
+#define SIFADR      		0x04  	/* SIF/DMA Address. */
+#define SIFCMD      		0x06  	/* SIF Command. */
+#define SIFSTS      		0x06  	/* SIF Status. */
+
+/* "Extended" SIF (SRSX = 1) */
+#define SIFACL      		0x08  	/* SIF Adapter Control Register. */
+#define SIFADD      		0x0a 	/* SIF/DMA Address. -- 0x0a */
+#define SIFADX      		0x0c     /* 0x0c */
+#define DMALEN      		0x0e 	/* SIF DMA length. -- 0x0e */
+
+/*
+ * POS Registers.  Only for ISA Adapters.
+ */
+#define POSREG      		0x10 	/* Adapter Program Option Select (POS)
 			 		 * Register: base IO address + 16 byte.
 			 		 */
 #define POSREG_2    		24L 	/* only for TR4/16+ adapter
-			 		 * base IO address + 24 byte.
+			 		 * base IO address + 24 byte. -- 0x18
 			 		 */
 
-
 /* SIFCMD command codes (high-low) */
 #define CMD_INTERRUPT_ADAPTER   0x8000  /* Cause internal adapter interrupt */
 #define CMD_ADAPTER_RESET   	0x4000  /* Hardware reset of adapter */
@@ -118,8 +134,13 @@
 					 * (1/0): can be written if ACL_ARESET
 					 * is zero.
 					 */
-#define ACL_SPEED4		0x0003
-#define ACL_SPEED16		0x0001
+#define ACL_PEN                 0x0004
+
+#define ACL_NSELOUT0            0x0002 
+#define ACL_NSELOUT1            0x0001	/* NSELOUTx have a card-specific
+					 * meaning for setting ring speed.
+					 */
+
 #define PS_DMA_MASK		(ACL_SWHRQ | ACL_PSDMAEN)
 
 
@@ -145,69 +166,72 @@
 
 
 /* Interrupt Codes (only MAC IRQs) */
-#define STS_IRQ_ADAPTER_CHECK   0x0000  /* unrecoverable hardware or
+#define STS_IRQ_ADAPTER_CHECK	0x0000	/* unrecoverable hardware or
 					 * software error.
 					 */ 
-#define STS_IRQ_RING_STATUS     0x0004  /* SSB is updated with ring status. */
-#define STS_IRQ_SCB_CLEAR       0x0006  /* SCB clear, following an
+#define STS_IRQ_RING_STATUS	0x0004  /* SSB is updated with ring status. */
+#define STS_IRQ_LLC_STATUS	0x0005	/* Not used in MAC-only microcode */
+#define STS_IRQ_SCB_CLEAR	0x0006	/* SCB clear, following an
 					 * SCB_REQUEST IRQ.
 					 */
-#define STS_IRQ_COMMAND_STATUS  0x0008  /* SSB is updated with command 
+#define STS_IRQ_TIMER		0x0007	/* Not normally used in MAC ucode */
+#define STS_IRQ_COMMAND_STATUS	0x0008	/* SSB is updated with command 
 					 * status.
 					 */ 
-#define STS_IRQ_RECEIVE_STATUS  0x000A  /* SSB is updated with receive
+#define STS_IRQ_RECEIVE_STATUS	0x000A	/* SSB is updated with receive
 					 * status.
 					 */
-#define STS_IRQ_TRANSMIT_STATUS 0x000C  /* SSB is updated with transmit
+#define STS_IRQ_TRANSMIT_STATUS	0x000C	/* SSB is updated with transmit
                                          * status
 					 */
-#define STS_IRQ_MASK            0x000F  /* = STS_ERROR_MASK. */
+#define STS_IRQ_RECEIVE_PENDING	0x000E	/* Not used in MAC-only microcode */
+#define STS_IRQ_MASK		0x000F	/* = STS_ERROR_MASK. */
 
 
 /* TRANSMIT_STATUS completion code: (SSB.Parm[0]) */
-#define COMMAND_COMPLETE        0x0080  /* TRANSMIT command completed
+#define COMMAND_COMPLETE	0x0080	/* TRANSMIT command completed
                                          * (avoid this!) issue another transmit
 					 * to send additional frames.
 					 */
-#define FRAME_COMPLETE          0x0040  /* Frame has been transmitted;
+#define FRAME_COMPLETE		0x0040	/* Frame has been transmitted;
 					 * INTERRUPT_FRAME bit was set in the
 					 * CSTAT request; indication of possibly
 					 * more than one frame transmissions!
 					 * SSB.Parm[0-1]: 32 bit pointer to
 					 * TPL of last frame.
 					 */
-#define LIST_ERROR              0x0020  /* Error in one of the TPLs that
+#define LIST_ERROR		0x0020	/* Error in one of the TPLs that
 					 * compose the frame; TRANSMIT
-					 * terminated; Parm[1-2]: 32 bit pointer
+					 * terminated; Parm[1-2]: 32bit pointer
 					 * to TPL which starts the error
 					 * frame; error details in bits 8-13.
 					 * (14?)
 					 */
-#define FRAME_SIZE_ERROR        0x8000  /* FRAME_SIZE does not equal the sum of
+#define FRAME_SIZE_ERROR	0x8000	/* FRAME_SIZE does not equal the sum of
 					 * the valid DATA_COUNT fields;
 					 * FRAME_SIZE less than header plus
 					 * information field. (15 bytes +
 					 * routing field) Or if FRAME_SIZE
 					 * was specified as zero in one list.
 					 */
-#define TX_THRESHOLD            0x4000  /* FRAME_SIZE greater than (BUFFER_SIZE
+#define TX_THRESHOLD		0x4000	/* FRAME_SIZE greater than (BUFFER_SIZE
 					 * - 9) * TX_BUF_MAX.
 					 */
-#define ODD_ADDRESS             0x2000  /* Odd forward pointer value is
+#define ODD_ADDRESS		0x2000	/* Odd forward pointer value is
 					 * read on a list without END_FRAME
 					 * indication.
 					 */
-#define FRAME_ERROR             0x1000  /* START_FRAME bit is (not) anticipated,
+#define FRAME_ERROR		0x1000	/* START_FRAME bit (not) anticipated,
 					 * but (not) set.
 					 */
-#define ACCESS_PRIORITY_ERROR   0x0800  /* Access priority requested has not
+#define ACCESS_PRIORITY_ERROR	0x0800	/* Access priority requested has not
 					 * been allowed.
 					 */
-#define UNENABLED_MAC_FRAME     0x0400  /* MAC frame has source class of zero
+#define UNENABLED_MAC_FRAME	0x0400	/* MAC frame has source class of zero
 					 * or MAC frame PCF ATTN field is
 					 * greater than one.
 					 */
-#define ILLEGAL_FRAME_FORMAT    0x0200  /* Bit 0 or FC field was set to one. */
+#define ILLEGAL_FRAME_FORMAT	0x0200	/* Bit 0 or FC field was set to one. */
 
 
 /*
@@ -222,98 +246,98 @@
  *
  * The following defines the command code bits and the command queue:
  */
-#define OC_OPEN                 0x0001	/* OPEN command */
-#define OC_TRANSMIT             0x0002  /* TRANSMIT command */
-#define OC_TRANSMIT_HALT        0x0004  /* TRANSMIT_HALT command */
-#define OC_RECEIVE              0x0008  /* RECEIVE command */
-#define OC_CLOSE                0x0010  /* CLOSE command */
-#define OC_SET_GROUP_ADDR       0x0020  /* SET_GROUP_ADDR command */
-#define OC_SET_FUNCT_ADDR       0x0040  /* SET_FUNCT_ADDR command */
-#define OC_READ_ERROR_LOG       0x0080  /* READ_ERROR_LOG command */
-#define OC_READ_ADAPTER         0x0100  /* READ_ADAPTER command */
-#define OC_MODIFY_OPEN_PARMS    0x0400  /* MODIFY_OPEN_PARMS command */
-#define OC_RESTORE_OPEN_PARMS   0x0800  /* RESTORE_OPEN_PARMS command */
-#define OC_SET_FIRST_16_GROUP   0x1000  /* SET_FIRST_16_GROUP command */
-#define OC_SET_BRIDGE_PARMS     0x2000  /* SET_BRIDGE_PARMS command */
-#define OC_CONFIG_BRIDGE_PARMS  0x4000  /* CONFIG_BRIDGE_PARMS command */
+#define OC_OPEN			0x0001	/* OPEN command */
+#define OC_TRANSMIT		0x0002	/* TRANSMIT command */
+#define OC_TRANSMIT_HALT	0x0004	/* TRANSMIT_HALT command */
+#define OC_RECEIVE		0x0008	/* RECEIVE command */
+#define OC_CLOSE		0x0010	/* CLOSE command */
+#define OC_SET_GROUP_ADDR	0x0020	/* SET_GROUP_ADDR command */
+#define OC_SET_FUNCT_ADDR	0x0040	/* SET_FUNCT_ADDR command */
+#define OC_READ_ERROR_LOG	0x0080	/* READ_ERROR_LOG command */
+#define OC_READ_ADAPTER		0x0100	/* READ_ADAPTER command */
+#define OC_MODIFY_OPEN_PARMS	0x0400	/* MODIFY_OPEN_PARMS command */
+#define OC_RESTORE_OPEN_PARMS	0x0800	/* RESTORE_OPEN_PARMS command */
+#define OC_SET_FIRST_16_GROUP	0x1000	/* SET_FIRST_16_GROUP command */
+#define OC_SET_BRIDGE_PARMS	0x2000	/* SET_BRIDGE_PARMS command */
+#define OC_CONFIG_BRIDGE_PARMS	0x4000	/* CONFIG_BRIDGE_PARMS command */
 
-#define OPEN			0x0300  /* C: open command. S: completion. */
-#define TRANSMIT		0x0400  /* C: transmit command. S: completion
+#define OPEN			0x0300	/* C: open command. S: completion. */
+#define TRANSMIT		0x0400	/* C: transmit command. S: completion
 					 * status. (reject: COMMAND_REJECT if
 					 * adapter not opened, TRANSMIT already
 					 * issued or address passed in the SCB
 					 * not word aligned)
 					 */
-#define TRANSMIT_HALT		0x0500  /* C: interrupt TX TPL chain; if no
+#define TRANSMIT_HALT		0x0500	/* C: interrupt TX TPL chain; if no
 					 * TRANSMIT command issued, the command
-					 * is ignored. (completion with TRANSMIT
+					 * is ignored (completion with TRANSMIT
 					 * status (0x0400)!)
 					 */
-#define RECEIVE			0x0600  /* C: receive command. S: completion
+#define RECEIVE			0x0600	/* C: receive command. S: completion
 					 * status. (reject: COMMAND_REJECT if
 					 * adapter not opened, RECEIVE already
 					 * issued or address passed in the SCB 
 					 * not word aligned)
 					 */
-#define CLOSE			0x0700  /* C: close adapter. S: completion.
+#define CLOSE			0x0700	/* C: close adapter. S: completion.
 					 * (COMMAND_REJECT if adapter not open)
 					 */
-#define SET_GROUP_ADDR		0x0800  /* C: alter adapter group address after
-					 * OPEN.  S: completion. (COMMAND_REJECT
+#define SET_GROUP_ADDR		0x0800	/* C: alter adapter group address after
+					 * OPEN. S: completion. (COMMAND_REJECT
 					 * if adapter not open)
 					 */
-#define SET_FUNCT_ADDR		0x0900  /* C: alter adapter functional address
+#define SET_FUNCT_ADDR		0x0900	/* C: alter adapter functional address
 					 * after OPEN. S: completion.
 					 * (COMMAND_REJECT if adapter not open)
 					 */
-#define READ_ERROR_LOG		0x0A00  /* C: read adapter error counters.
+#define READ_ERROR_LOG		0x0A00	/* C: read adapter error counters.
 					 * S: completion. (command ignored
 					 * if adapter not open!)
 					 */
-#define READ_ADAPTER		0x0B00  /* C: read data from adapter memory.
+#define READ_ADAPTER		0x0B00	/* C: read data from adapter memory.
 					 * (important: after init and before
 					 * open!) S: completion. (ADAPTER_CHECK
 					 * interrupt if undefined storage area
 					 * read)
 					 */
-#define MODIFY_OPEN_PARMS	0x0D00  /* C: modify some adapter operational
+#define MODIFY_OPEN_PARMS	0x0D00	/* C: modify some adapter operational
 					 * parameters. (bit correspondend to
 					 * WRAP_INTERFACE is ignored)
 					 * S: completion. (reject: 
 					 * COMMAND_REJECT)
 					 */
-#define RESTORE_OPEN_PARMS	0x0E00  /* C: modify some adapter operational
+#define RESTORE_OPEN_PARMS	0x0E00	/* C: modify some adapter operational
 					 * parameters. (bit correspondend
 					 * to WRAP_INTERFACE is ignored)
 					 * S: completion. (reject:
 					 * COMMAND_REJECT)
 					 */
-#define SET_FIRST_16_GROUP	0x0F00  /* C: alter the first two bytes in
+#define SET_FIRST_16_GROUP	0x0F00	/* C: alter the first two bytes in
 					 * adapter group address.
 					 * S: completion. (reject:
 					 * COMMAND_REJECT)
 					 */
-#define SET_BRIDGE_PARMS	0x1000  /* C: values and conditions for the
+#define SET_BRIDGE_PARMS	0x1000	/* C: values and conditions for the
 					 * adapter hardware to use when frames
 					 * are copied for forwarding.
 					 * S: completion. (reject:
 					 * COMMAND_REJECT)
 					 */
-#define CONFIG_BRIDGE_PARMS 0x1100	/* C: ..
+#define CONFIG_BRIDGE_PARMS	0x1100	/* C: ..
 					 * S: completion. (reject:
 					 * COMMAND_REJECT)
 					 */
 
-#define SPEED_4         4
-#define SPEED_16        16	/* Default transmission speed  */
+#define SPEED_4			4
+#define SPEED_16		16	/* Default transmission speed  */
 
 
 /* Initialization Parameter Block (IPB); word alignment necessary! */
-#define BURST_SIZE      0x0018  /* Default burst size */
-#define BURST_MODE      0x9F00  /* Burst mode enable */
-#define DMA_RETRIES     0x0505  /* Magic DMA retry number... */
+#define BURST_SIZE	0x0018	/* Default burst size */
+#define BURST_MODE	0x9F00	/* Burst mode enable */
+#define DMA_RETRIES	0x0505	/* Magic DMA retry number... */
 
-#define CYCLE_TIME      3	/* Default AT-bus cycle time: 500 ns
+#define CYCLE_TIME	3	/* Default AT-bus cycle time: 500 ns
 				 * (later adapter version: fix  cycle time!)
 				 */
 #define LINE_SPEED_BIT	0x80
@@ -327,7 +351,7 @@
 #define FOUR_SECONDS		(ONE_SECOND_TICKS * 4)
 #define FIVE_SECONDS		(ONE_SECOND_TICKS * 5)
 
-#define BUFFER_SIZE 2048	/* Buffers on Adapter */
+#define BUFFER_SIZE 		2048	/* Buffers on Adapter */
 
 #pragma pack(1)
 typedef struct {
@@ -337,18 +361,18 @@
 
 	/* Interrupt vectors the adapter places on attached system bus. */
 	unsigned char CMD_Status_IV;	/* Interrupt vector: command status. */
-	unsigned char TX_IV;     	/* Interrupt vector: transmit. */
-	unsigned char RX_IV;     	/* Interrupt vector: receive. */
+	unsigned char TX_IV;		/* Interrupt vector: transmit. */
+	unsigned char RX_IV;		/* Interrupt vector: receive. */
 	unsigned char Ring_Status_IV;	/* Interrupt vector: ring status. */
-	unsigned char SCB_Clear_IV;  	/* Interrupt vector: SCB clear. */
+	unsigned char SCB_Clear_IV;	/* Interrupt vector: SCB clear. */
 	unsigned char Adapter_CHK_IV;	/* Interrupt vector: adapter check. */
 
 	unsigned short RX_Burst_Size;	/* Max. number of transfer cycles. */
 	unsigned short TX_Burst_Size;	/* During DMA burst; even value! */
-	unsigned short DMA_Abort_Thrhld; /* Number of DMA retries. */
+	unsigned short DMA_Abort_Thrhld;/* Number of DMA retries. */
 
-	unsigned long SCB_Addr;	/* SCB address: even, word aligned, high-low. */
-	unsigned long SSB_Addr;	/* SSB address: even, word aligned, high-low. */
+	unsigned long SCB_Addr;	/* SCB address: even, word aligned, high-low */
+	unsigned long SSB_Addr;	/* SSB address: even, word aligned, high-low */
 } IPB, *IPB_Ptr;
 #pragma pack()
 
@@ -361,10 +385,10 @@
 #define RPL_SIZE	14		/* (with TI firmware v2.26 handling
 					 * up to nine fragments possible)
 					 */
-#define TX_BUF_MIN      20		/* ??? (Stephan: calculation with */
-#define TX_BUF_MAX      40		/* BUFFER_SIZE and MAX_FRAME_SIZE) ??? 
+#define TX_BUF_MIN	20		/* ??? (Stephan: calculation with */
+#define TX_BUF_MAX	40		/* BUFFER_SIZE and MAX_FRAME_SIZE) ??? 
 					 */
-#define DISABLE_EARLY_TOKEN_RELEASE 0x1000
+#define DISABLE_EARLY_TOKEN_RELEASE 	0x1000
 
 /* OPEN Options (high-low) */
 #define WRAP_INTERFACE		0x0080	/* Inserting omitted for test
@@ -372,51 +396,52 @@
 					 * as receive data. (usefull for
 					 * testing; change: CLOSE necessary)
 					 */
-#define DISABLE_HARD_ERROR	0x0040  /* On HARD_ERROR & TRANSMIT_BEACON
+#define DISABLE_HARD_ERROR	0x0040	/* On HARD_ERROR & TRANSMIT_BEACON
 					 * no RING.STATUS interrupt.
 					 */
-#define DISABLE_SOFT_ERROR	0x0020  /* On SOFT_ERROR, no RING.STATUS
+#define DISABLE_SOFT_ERROR	0x0020	/* On SOFT_ERROR, no RING.STATUS
 					 * interrupt.
 					 */
-#define PASS_ADAPTER_MAC_FRAMES 0x0010  /* Passing unsupported MAC frames
+#define PASS_ADAPTER_MAC_FRAMES	0x0010	/* Passing unsupported MAC frames
 					 * to system.
 					 */
-#define PASS_ATTENTION_FRAMES   0x0008  /* All changed attention MAC frames are
+#define PASS_ATTENTION_FRAMES	0x0008	/* All changed attention MAC frames are
 					 * passed to the system.
 					 */
-#define PAD_ROUTING_FIELD	0x0004  /* Routing field is padded to 18
+#define PAD_ROUTING_FIELD	0x0004	/* Routing field is padded to 18
 					 * bytes.
 					 */
-#define FRAME_HOLD		0x0002  /* Adapter waits for entire frame before
+#define FRAME_HOLD		0x0002	/*Adapter waits for entire frame before
 					 * initiating DMA transfer; otherwise:
 					 * DMA transfer initiation if internal
 					 * buffer filled.
 					 */
-#define CONTENDER		0x0001  /* Adapter participates in the monitor
+#define CONTENDER		0x0001	/* Adapter participates in the monitor
 					 * contention process.
 					 */
-#define PASS_BEACON_MAC_FRAMES  0x8000  /* Adapter passes beacon MAC frames
+#define PASS_BEACON_MAC_FRAMES	0x8000	/* Adapter passes beacon MAC frames
 					 * to the system.
 					 */
-#define EARLY_TOKEN_RELEASE 	0x1000  /* Only valid in 16 Mbps operation;
+#define EARLY_TOKEN_RELEASE 	0x1000	/* Only valid in 16 Mbps operation;
 					 * 0 = ETR. (no effect in 4 Mbps
 					 * operation)
 					 */
-#define COPY_ALL_MAC_FRAMES	0x0400  /* All MAC frames are copied to
+#define COPY_ALL_MAC_FRAMES	0x0400	/* All MAC frames are copied to
 					 * the system. (after OPEN: duplicate
 					 * address test (DAT) MAC frame is 
 					 * first received frame copied to the
 					 * system)
 					 */
-#define COPY_ALL_NON_MAC_FRAMES	0x0200  /* All non MAC frames are copied to
+#define COPY_ALL_NON_MAC_FRAMES	0x0200	/* All non MAC frames are copied to
 					 * the system.
 					 */
-#define PASS_FIRST_BUF_ONLY	0x0100  /* Passes only first internal buffer
+#define PASS_FIRST_BUF_ONLY	0x0100	/* Passes only first internal buffer
 					 * of each received frame; FrameSize
 					 * of RPLs must contain internal
 					 * BUFFER_SIZE bits for promiscous mode.
 					 */
-#define ENABLE_FULL_DUPLEX_SELECTION 0x2000 /* Enable the use of full-duplex
+#define ENABLE_FULL_DUPLEX_SELECTION	0x2000 
+ 					/* Enable the use of full-duplex
 					 * settings with bits in byte 22 in
 					 * ocpl. (new feature in firmware
 					 * version 3.09)
@@ -434,7 +459,7 @@
 				  * fragments following.
 				  */
 
-#define ISA_MAX_ADDRESS 0x00ffffff
+#define ISA_MAX_ADDRESS 	0x00ffffff
 
 #pragma pack(1)
 typedef struct {
@@ -1031,15 +1056,6 @@
 	int RPLIndex;
 };
 
-#define TMS_ISA 1
-#define TMS_PCI 2
-struct cardinfo_table {
-	int type; /* 1 = ISA, 2 = PCI */
-	int vendor_id;
-	int device_id;
-	char *name;
-};
-
 /* Information that need to be kept for each board. */
 typedef struct net_local {
 #pragma pack(1)
@@ -1094,7 +1110,7 @@
 
 	struct tr_statistics MacStat;	/* MAC statistics structure */
 
-	struct cardinfo_table *CardType;
+	unsigned long dmalimit; /* the max DMA address (ie, ISA) */
 
 	struct timer_list timer;
 
@@ -1103,6 +1119,13 @@
 	INTPTRS intptrs;	/* Internal adapter pointer. Must be read
 				 * before OPEN command.
 				 */
+	unsigned short (*setnselout)(struct net_device *);
+	unsigned short (*sifreadb)(struct net_device *, unsigned short);
+	void (*sifwriteb)(struct net_device *, unsigned short, unsigned short);
+	unsigned short (*sifreadw)(struct net_device *, unsigned short);
+	void (*sifwritew)(struct net_device *, unsigned short, unsigned short);
+
+	void *tmspriv;
 } NET_LOCAL;
 
 #endif	/* __KERNEL__ */
diff -ru --new-file 2.3.40.clean/drivers/net/tokenring/tmspci.c 2.3.40/drivers/net/tokenring/tmspci.c
--- 2.3.40.clean/drivers/net/tokenring/tmspci.c	Thu Jan  1 00:00:00 1970
+++ 2.3.40/drivers/net/tokenring/tmspci.c	Sun Jan 23 01:07:11 2000
@@ -0,0 +1,336 @@
+/*
+ *  tmspci.c: A generic network driver for TMS380-based PCI token ring cards.
+ *
+ *  Written 1999 by Adam Fritzler
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU Public License, incorporated herein by reference.
+ *
+ *  This driver module supports the following cards:
+ *	- SysKonnect TR4/16(+) PCI	(SK-4590)
+ *	- SysKonnect TR4/16 PCI		(SK-4591)
+ *      - Compaq TR 4/16 PCI
+ *      - Thomas-Conrad TC4048 4/16 PCI 
+ *      - 3Com 3C339 Token Link Velocity
+ *
+ *  Maintainer(s):
+ *    AF	Adam Fritzler		mid@auk.cx
+ *
+ *  Modification History:
+ *	30-Dec-99	AF	Split off from the tms380tr driver.
+ *	22-Jan-00	AF	Updated to use indirect read/writes
+ *
+ *  TODO:
+ *	1. See if we can use MMIO instead of port accesses
+ *
+ */
+static const char *version = "tmspci.c: v1.01 22/01/2000 by Adam Fritzler\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include "tms380tr.h"
+
+#define TMS_PCI_IO_EXTENT 32
+
+struct cardinfo_table {
+	int vendor_id; /* PCI info */
+	int device_id;
+	int registeroffset; /* SIF offset from dev->base_addr */
+	unsigned char nselout[2]; /* NSELOUT vals for 4mb([0]) and 16mb([1]) */
+	char *name;
+};
+
+struct cardinfo_table probelist[] = {
+	{ 0, 0,
+	  0x0000, {0x00, 0x00}, "Unknown TMS380 Token Ring Adapter"},
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TOKENRING, 
+	  0x0000, {0x03, 0x01}, "Compaq 4/16 TR PCI"},
+	{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_TR, 
+	  0x0000, {0x03, 0x01}, "SK NET TR 4/16 PCI"},
+	{ PCI_VENDOR_ID_TCONRAD, PCI_DEVICE_ID_TCONRAD_TOKENRING,
+	  0x0000, {0x03, 0x01}, "Thomas-Conrad TC4048 PCI 4/16"},
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C339,
+	  0x0000, {0x03, 0x01}, "3Com Token Link Velocity"},
+	{ 0, 0, 0, {0x00, 0x00}, NULL}
+};
+
+int tms_pci_probe(void);
+static int tms_pci_open(struct net_device *dev);
+static int tms_pci_close(struct net_device *dev);
+static void tms_pci_read_eeprom(struct net_device *dev);
+static unsigned short tms_pci_setnselout_pins(struct net_device *dev);
+
+static unsigned short tms_pci_sifreadb(struct net_device *dev, unsigned short reg)
+{
+	return inb(dev->base_addr + reg);
+}
+
+static unsigned short tms_pci_sifreadw(struct net_device *dev, unsigned short reg)
+{
+	return inw(dev->base_addr + reg);
+}
+
+static void tms_pci_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+	outb(val, dev->base_addr + reg);
+}
+
+static void tms_pci_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+	outw(val, dev->base_addr + reg);
+}
+
+struct tms_pci_card {
+	struct net_device *dev;
+	struct pci_dev *pci_dev;
+	struct cardinfo_table *cardinfo;
+	struct tms_pci_card *next;
+};
+static struct tms_pci_card *tms_pci_card_list = NULL;
+
+
+struct cardinfo_table * __init tms_pci_getcardinfo(unsigned short vendor, 
+						   unsigned short device)
+{
+	int cur;
+	for (cur = 1; probelist[cur].name != NULL; cur++) {
+		if ((probelist[cur].vendor_id == vendor) && 
+		    (probelist[cur].device_id == device))
+			return &probelist[cur];
+	}
+	
+	return NULL;
+}
+
+int __init tms_pci_probe(void)
+{	
+	static int versionprinted = 0;
+	struct pci_dev *pdev = NULL ; 
+	struct net_device *dev;
+	struct net_local *tp;
+	int i;
+
+	if (!pci_present())
+		return (-1);	/* No PCI present. */
+  
+	while ( (pdev=pci_find_class(PCI_CLASS_NETWORK_TOKEN_RING<<8, pdev))) { 
+		unsigned int pci_irq_line;
+		unsigned long pci_ioaddr;
+		struct tms_pci_card *card;
+		struct cardinfo_table *cardinfo;
+		
+		if ((cardinfo = 
+		     tms_pci_getcardinfo(pdev->vendor, pdev->device)) == NULL)
+			continue;	
+
+		if (versionprinted++ == 0)
+			printk("%s", version);
+
+		pci_enable_device(pdev);
+
+		/* Remove I/O space marker in bit 0. */
+		pci_irq_line = pdev->irq;
+		pci_ioaddr = pdev->resource[0].start ; 
+		
+		if(check_region(pci_ioaddr, TMS_PCI_IO_EXTENT))
+			continue;
+    
+		/* At this point we have found a valid card. */
+    
+		dev = init_trdev(NULL, 0);
+		
+		request_region(pci_ioaddr, TMS_PCI_IO_EXTENT, cardinfo->name);
+		if(request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,
+			       cardinfo->name, dev)) { 
+			release_region(pci_ioaddr, TMS_PCI_IO_EXTENT); 
+			continue; /*return (-ENODEV);*/ /* continue; ?? */
+		}
+
+		/*
+		  if (load_tms380_module("tmspci.c")) {
+		  return 0;
+		  }
+		*/
+
+		pci_ioaddr &= ~3 ; 
+		dev->base_addr	= pci_ioaddr;
+		dev->irq 		= pci_irq_line;
+		dev->dma		= 0;
+		
+		printk("%s: %s\n", dev->name, cardinfo->name);
+		printk("%s:    IO: %#4lx  IRQ: %d\n",
+		       dev->name, dev->base_addr, dev->irq);
+		/*
+		 * Some cards have their TMS SIF registers offset from
+		 * their given base address.  Account for that here. 
+		 */
+		dev->base_addr += cardinfo->registeroffset;
+		
+		tms_pci_read_eeprom(dev);
+
+		printk("%s:    Ring Station Address: ", dev->name);
+		printk("%2.2x", dev->dev_addr[0]);
+		for (i = 1; i < 6; i++)
+			printk(":%2.2x", dev->dev_addr[i]);
+		printk("\n");
+		
+		if (tmsdev_init(dev)) {
+			printk("%s: unable to get memory for dev->priv.\n", dev->name);
+			return 0;
+		}
+
+		tp = (struct net_local *)dev->priv;
+		tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */
+		tp->setnselout = tms_pci_setnselout_pins;
+		
+		tp->sifreadb = tms_pci_sifreadb;
+		tp->sifreadw = tms_pci_sifreadw;
+		tp->sifwriteb = tms_pci_sifwriteb;
+		tp->sifwritew = tms_pci_sifwritew;
+		
+		memcpy(tp->ProductID, cardinfo->name, PROD_ID_SIZE + 1);
+
+		tp->tmspriv = cardinfo;
+
+		dev->open = tms_pci_open;
+		dev->stop = tms_pci_close;
+
+		if (register_trdev(dev) == 0) {
+			/* Enlist in the card list */
+			card = kmalloc(sizeof(struct tms_pci_card), GFP_KERNEL);
+			card->next = tms_pci_card_list;
+			tms_pci_card_list = card;
+			card->dev = dev;
+			card->pci_dev = pdev;
+			card->cardinfo = cardinfo;
+		} else {
+			printk("%s: register_trdev() returned non-zero.\n", dev->name);
+			kfree(dev->priv);
+			kfree(dev);
+			return -1;
+		}
+	}
+	
+	if (tms_pci_card_list)
+		return 0;
+	return (-1);
+}
+
+/*
+ * Reads MAC address from adapter RAM, which should've read it from
+ * the onboard ROM.  
+ *
+ * Calling this on a board that does not support it can be a very
+ * dangerous thing.  The Madge board, for instance, will lock your
+ * machine hard when this is called.  Luckily, its supported in a
+ * seperate driver.  --ASF
+ */
+static void tms_pci_read_eeprom(struct net_device *dev)
+{
+	int i;
+	
+	/* Address: 0000:0000 */
+	tms_pci_sifwritew(dev, 0, SIFADX);
+	tms_pci_sifwritew(dev, 0, SIFADR);	
+	
+	/* Read six byte MAC address data */
+	dev->addr_len = 6;
+	for(i = 0; i < 6; i++)
+		dev->dev_addr[i] = tms_pci_sifreadw(dev, SIFINC) >> 8;
+}
+
+unsigned short tms_pci_setnselout_pins(struct net_device *dev)
+{
+	unsigned short val = 0;
+	struct net_local *tp = (struct net_local *)dev->priv;
+	struct cardinfo_table *cardinfo = (struct cardinfo_table *)tp->tmspriv;
+  
+	if(tp->DataRate == SPEED_4)
+		val |= cardinfo->nselout[0];	/* Set 4Mbps */
+	else
+		val |= cardinfo->nselout[1];	/* Set 16Mbps */
+	return val;
+}
+
+static int tms_pci_open(struct net_device *dev)
+{  
+	tms380tr_open(dev);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int tms_pci_close(struct net_device *dev)
+{
+	tms380tr_close(dev);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+	/* Probe for cards. */
+	if (tms_pci_probe()) {
+		printk(KERN_NOTICE "tmspci.c: No cards found.\n");
+	}
+	/* lock_tms380_module(); */
+	return (0);
+}
+
+void cleanup_module(void)
+{
+	struct net_device *dev;
+	struct tms_pci_card *this_card;
+
+	while (tms_pci_card_list) {
+		dev = tms_pci_card_list->dev;
+		
+		/*
+		 * If we used a register offset, revert here.
+		 */
+		if (dev->priv)
+		{	
+			struct net_local *tp;
+			struct cardinfo_table *cardinfo;
+
+			tp = (struct net_local *)dev->priv;
+			cardinfo = (struct cardinfo_table *)tp->tmspriv;
+			
+			dev->base_addr -= cardinfo->registeroffset;
+		}
+		unregister_netdev(dev);
+		release_region(dev->base_addr, TMS_PCI_IO_EXTENT);
+		free_irq(dev->irq, dev);
+		kfree(dev->priv);
+		kfree(dev);
+		this_card = tms_pci_card_list;
+		tms_pci_card_list = this_card->next;
+		kfree(this_card);
+	}
+	/* unlock_tms380_module(); */
+}
+#endif /* MODULE */
+
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmspci.c"
+ *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmspci.c"
+ *  c-set-style "K&R"
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -ru --new-file 2.3.40.clean/drivers/scsi/aha1542.c 2.3.40/drivers/scsi/aha1542.c
--- 2.3.40.clean/drivers/scsi/aha1542.c	Thu Dec 30 01:00:54 1999
+++ 2.3.40/drivers/scsi/aha1542.c	Sun Jan 23 01:07:11 2000
@@ -21,6 +21,8 @@
  *  Modified by Chris Faulhaber <jedgar@fxp.org>
  *        Added module command-line options
  *        19-Jul-99
+ *  Modified by Adam Fritzler <mid@auk.cx>
+ *        Added proper detection of the AHA-1640 (MCA version of AHA-1540)
  */
 
 #include <linux/module.h>
@@ -40,6 +42,9 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <linux/blk.h>
+#ifdef CONFIG_MCA
+#include <linux/mca.h>
+#endif
 #include "scsi.h"
 #include "hosts.h"
 
@@ -96,7 +101,7 @@
 #define MAXBOARDS 4		/* Increase this and the sizes of the
 				   arrays below, if you need more.. */
 
-/* Boards 3,4 slots are reserved for ISAPnP scans */
+/* Boards 3,4 slots are reserved for ISAPnP/MCA scans */
 
 static unsigned int bases[MAXBOARDS] = {0x330, 0x334, 0, 0};
 
@@ -1043,6 +1048,69 @@
 		setup_dmaspeed[0] = atbt;
 	}
 #endif
+
+	/*
+	 *	Find MicroChannel cards (AHA1640)
+	 */
+#ifdef CONFIG_MCA
+	if(MCA_bus) {
+		int slot = 0;
+		int pos = 0;
+
+		for (indx = 0; (slot !=  MCA_NOTFOUND) && 
+			     (indx < sizeof(bases)/sizeof(bases[0])); indx++) {
+
+			if (bases[indx])
+				continue;
+
+			/* Detect only AHA-1640 cards -- MCA ID 0F1F */
+			slot = mca_find_unused_adapter(0x0f1f, slot);
+			if (slot == MCA_NOTFOUND)
+				break;
+
+			
+			/* Found one */
+			pos = mca_read_stored_pos(slot, 3);
+			
+			/* Decode address */
+			if (pos & 0x80) {
+				if (pos & 0x02) {
+					if (pos & 0x01)
+						bases[indx] = 0x334;
+					else
+						bases[indx] = 0x234;
+				} else {
+					if (pos & 0x01)
+						bases[indx] = 0x134;
+				}
+			} else {
+				if (pos & 0x02) {
+					if (pos & 0x01)
+						bases[indx] = 0x330;
+					else
+						bases[indx] = 0x230;
+				} else {
+					if (pos & 0x01)
+						bases[indx] = 0x130;
+				}
+			}
+
+			/* No need to decode IRQ and Arb level -- those are
+			 * read off the card later.
+			 */
+			printk(KERN_INFO "Found an AHA-1640 in MCA slot %d, I/O 0x%04x\n", slot, bases[indx]);
+
+			mca_set_adapter_name(slot, "Adapter AHA-1640");
+			mca_set_adapter_procfn(slot, NULL, NULL);
+			mca_mark_as_used(slot);
+			
+			/* Go on */
+			slot++;
+		}
+		
+	}
+#endif
+
 	/*
 	 *	Hunt for ISA Plug'n'Pray Adaptecs (AHA1535)
 	 */
diff -ru --new-file 2.3.40.clean/net/ipv4/ipconfig.c 2.3.40/net/ipv4/ipconfig.c
--- 2.3.40.clean/net/ipv4/ipconfig.c	Sun Jan  9 05:36:20 2000
+++ 2.3.40/net/ipv4/ipconfig.c	Sun Jan 23 01:07:11 2000
@@ -534,7 +534,14 @@
 
 	/* Construct BOOTP header */
 	b->op = BOOTP_REQUEST;
-	b->htype = dev->type;
+	if (dev->type < 256) /* check for false types */
+		b->htype = dev->type;
+	else if (dev->type == ARPHRD_IEEE802_TR) /* fix for token ring */
+		b->htype = ARPHRD_IEEE802;
+	else {
+		printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name);
+		b->htype = dev->type; /* can cause undefined behavior */
+	}
 	b->hlen = dev->addr_len;
 	memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
 	b->secs = htons(jiffies / HZ);
