Parent repository is bk://gkernel.bkbits.net/netdev-2.6
======== ChangeSet 1.1573 ========
D 1.1573 04/02/11 22:29:23-08:00 akpm@mnm.(none) 36686 36678 0/0/1
P ChangeSet
C Merge mnm.(none):/usr/src/bk25 into mnm.(none):/usr/src/bk-netdev
------------------------------------------------

diff -Nru a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c
--- a/Documentation/networking/ifenslave.c	Wed Feb 11 22:30:56 2004
+++ b/Documentation/networking/ifenslave.c	Wed Feb 11 22:30:56 2004
@@ -89,13 +89,13 @@
  *	   while it is running. It was already set during enslave. To
  *	   simplify things, it is now handeled separately.
  *
- *    - 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ *    - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	 - Code cleanup and style changes
  *	   set version to 1.1.0
  */
 
 #define APP_VERSION	"1.1.0"
-#define APP_RELDATE	"Septemer 24, 2003"
+#define APP_RELDATE	"December 1, 2003"
 #define APP_NAME	"ifenslave"
 
 static char *version =
diff -Nru a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/networking/netconsole.txt	Wed Feb 11 22:30:58 2004
@@ -0,0 +1,57 @@
+
+started by Ingo Molnar <mingo@redhat.com>, 2001.09.17
+2.6 port and netpoll api by Matt Mackall <mpm@selenic.com>, Sep 9 2003
+
+Please send bug reports to Matt Mackall <mpm@selenic.com>
+
+This module logs kernel printk messages over UDP allowing debugging of
+problem where disk logging fails and serial consoles are impractical.
+
+It can be used either built-in or as a module. As a built-in,
+netconsole initializes immediately after NIC cards and will bring up
+the specified interface as soon as possible. While this doesn't allow
+capture of early kernel panics, it does capture most of the boot
+process.
+
+It takes a string configuration parameter "netconsole" in the
+following format:
+
+ netconsole=[src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr]
+
+   where
+        src-port      source for UDP packets (defaults to 6665)
+        src-ip        source IP to use (interface address)
+        dev           network interface (eth0)
+        tgt-port      port for logging agent (6666)
+        tgt-ip        IP address for logging agent
+        tgt-macaddr   ethernet MAC address for logging agent (broadcast)
+
+Examples:
+
+ linux netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc
+
+  or
+
+ insmod netconsole netconsole=@/,@10.0.0.2/
+
+Built-in netconsole starts immediately after the TCP stack is
+initialized and attempts to bring up the supplied dev at the supplied
+address.
+
+The remote host can run either 'netcat -u -l -p <port>' or syslogd.
+
+WARNING: the default target ethernet setting uses the broadcast
+ethernet address to send packets, which can cause increased load on
+other systems on the same ethernet segment.
+
+NOTE: the network device (eth1 in the above case) can run any kind
+of other network traffic, netconsole is not intrusive. Netconsole
+might cause slight delays in other traffic if the volume of kernel
+messages is high, but should have no other impact.
+
+Netconsole was designed to be as instantaneous as possible, to
+enable the logging of even the most critical kernel bugs. It works
+from IRQ contexts as well, and does not enable interrupts while
+sending packets. Due to these unique needs, configuration can not
+be more automatic, and some fundamental limitations will remain:
+only IP networks, UDP packets and ethernet devices are supported.
diff -Nru a/arch/cris/arch-v10/drivers/ethernet.c b/arch/cris/arch-v10/drivers/ethernet.c
--- a/arch/cris/arch-v10/drivers/ethernet.c	Wed Feb 11 22:30:57 2004
+++ b/arch/cris/arch-v10/drivers/ethernet.c	Wed Feb 11 22:30:57 2004
@@ -482,7 +482,7 @@
 	/* Register device */
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
diff -Nru a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
--- a/arch/ia64/hp/sim/simeth.c	Wed Feb 11 22:30:57 2004
+++ b/arch/ia64/hp/sim/simeth.c	Wed Feb 11 22:30:57 2004
@@ -224,7 +224,7 @@
 
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
diff -Nru a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
--- a/arch/ppc/8260_io/enet.c	Wed Feb 11 22:30:56 2004
+++ b/arch/ppc/8260_io/enet.c	Wed Feb 11 22:30:56 2004
@@ -851,7 +851,7 @@
 
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
diff -Nru a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
--- a/arch/ppc/8260_io/fcc_enet.c	Wed Feb 11 22:30:57 2004
+++ b/arch/ppc/8260_io/fcc_enet.c	Wed Feb 11 22:30:57 2004
@@ -1371,7 +1371,7 @@
 
 		err = register_netdev(dev);
 		if (err) {
-			kfree(dev);
+			free_netdev(dev);
 			return err;
 		}
 
diff -Nru a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
--- a/arch/ppc/8xx_io/enet.c	Wed Feb 11 22:30:57 2004
+++ b/arch/ppc/8xx_io/enet.c	Wed Feb 11 22:30:57 2004
@@ -949,7 +949,7 @@
 
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
diff -Nru a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
--- a/arch/ppc/8xx_io/fec.c	Wed Feb 11 22:30:57 2004
+++ b/arch/ppc/8xx_io/fec.c	Wed Feb 11 22:30:57 2004
@@ -1748,7 +1748,7 @@
 
 	err = register_netdev(dev);
 	if (err) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 
diff -Nru a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
--- a/arch/um/drivers/net_kern.c	Wed Feb 11 22:30:57 2004
+++ b/arch/um/drivers/net_kern.c	Wed Feb 11 22:30:57 2004
@@ -358,8 +358,12 @@
 	rtnl_lock();
 	err = register_netdevice(dev);
 	rtnl_unlock();
-	if (err)
+	if (err) {
+		device->dev = NULL;
+		/* XXX: should we call ->remove() here? */
+		free_netdev(dev);
 		return 1;
+	}
 	lp = dev->priv;
 
 	INIT_LIST_HEAD(&lp->list);
diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
--- a/drivers/isdn/i4l/isdn_ppp.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/isdn/i4l/isdn_ppp.c	Wed Feb 11 22:30:57 2004
@@ -1125,12 +1125,15 @@
 		return -EINVAL;
 
 	switch (cmd) {
+
+#define PPP_VERSION "2.3.7"
 	case SIOCGPPPVER:
 		r = (char *) ifr->ifr_ifru.ifru_data;
 		len = strlen(PPP_VERSION) + 1;
 		if (copy_to_user(r, PPP_VERSION, len))
 			error = -EFAULT;
 		break;
+
 	case SIOCGPPPSTATS:
 		error = isdn_ppp_dev_ioctl_stats(ifr, dev);
 		break;
diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
--- a/drivers/media/dvb/dvb-core/dvb_net.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/media/dvb/dvb-core/dvb_net.c	Wed Feb 11 22:30:56 2004
@@ -523,7 +523,8 @@
         net->base_addr = pid;
                 
 	if ((result = register_netdev(net)) < 0) {
-		kfree(net);
+		dvbnet->device[if_num] = NULL;
+		free_netdev(net);
 		return result;
 	}
 
@@ -545,6 +546,7 @@
 	flush_scheduled_work();
         unregister_netdev(net);
 	dvbnet->state[num]=0;
+	dvbnet->device[num] = NULL;
 	free_netdev(net);
 
 	return 0;
diff -Nru a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
--- a/drivers/message/fusion/mptlan.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/message/fusion/mptlan.c	Wed Feb 11 22:30:57 2004
@@ -1437,7 +1437,7 @@
 	SET_MODULE_OWNER(dev);
 
 	if (register_netdev(dev) != 0) {
-		kfree(dev);
+		free_netdev(dev);
 		dev = NULL;
 	}
 	return dev;
diff -Nru a/drivers/net/3c503.c b/drivers/net/3c503.c
--- a/drivers/net/3c503.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/3c503.c	Wed Feb 11 22:30:57 2004
@@ -337,6 +337,9 @@
     dev->open = &el2_open;
     dev->stop = &el2_close;
     dev->ethtool_ops = &netdev_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = ei_poll;
+#endif
 
     if (dev->mem_start)
 	printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c
--- a/drivers/net/3c509.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/3c509.c	Wed Feb 11 22:30:56 2004
@@ -678,6 +678,8 @@
 		err = el3_common_init(dev);
 
 		if (err) {
+			device->driver_data = NULL;
+			free_netdev(dev);
 			return -ENOMEM;
 		}
 
@@ -737,6 +739,8 @@
 	err = el3_common_init(dev);
 
 	if (err) {
+		eisa_set_drvdata (edev, NULL);
+		free_netdev(dev);
 		return err;
 	}
 
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/3c59x.c	Wed Feb 11 22:30:56 2004
@@ -920,6 +920,18 @@
 
 static int vortex_cards_found;
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void poll_vortex(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	unsigned long flags;
+	local_save_flags(flags);
+	local_irq_disable();
+	(vp->full_bus_master_rx ? boomerang_interrupt:vortex_interrupt)(dev->irq,dev,NULL);
+	local_irq_restore(flags);
+} 
+#endif
+
 #ifdef CONFIG_PM
 
 static int vortex_suspend (struct pci_dev *pdev, u32 state)
@@ -1450,6 +1462,9 @@
 	dev->set_multicast_list = set_rx_mode;
 	dev->tx_timeout = vortex_tx_timeout;
 	dev->watchdog_timeo = (watchdog * HZ) / 1000;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = poll_vortex; 
+#endif
 	if (pdev) {
 		vp->pm_state_valid = 1;
  		pci_save_state(VORTEX_PCI(vp), vp->power_state);
diff -Nru a/drivers/net/8390.c b/drivers/net/8390.c
--- a/drivers/net/8390.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/8390.c	Wed Feb 11 22:30:56 2004
@@ -516,6 +516,15 @@
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void ei_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	ei_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 /**
  * ei_tx_err - handle transmitter error
  * @dev: network device which threw the exception
@@ -1124,6 +1133,9 @@
 EXPORT_SYMBOL(ei_open);
 EXPORT_SYMBOL(ei_close);
 EXPORT_SYMBOL(ei_interrupt);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+EXPORT_SYMBOL(ei_poll);
+#endif
 EXPORT_SYMBOL(ei_tx_timeout);
 EXPORT_SYMBOL(NS8390_init);
 EXPORT_SYMBOL(__alloc_ei_netdev);
diff -Nru a/drivers/net/8390.h b/drivers/net/8390.h
--- a/drivers/net/8390.h	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/8390.h	Wed Feb 11 22:30:57 2004
@@ -39,6 +39,10 @@
 #define ei_debug 1
 #endif
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+extern void ei_poll(struct net_device *dev);
+#endif
+
 extern void NS8390_init(struct net_device *dev, int startp);
 extern int ei_open(struct net_device *dev);
 extern int ei_close(struct net_device *dev);
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/Kconfig	Wed Feb 11 22:30:57 2004
@@ -1354,8 +1354,9 @@
 	  say N.
 
 config E100
-	tristate "EtherExpressPro/100 support (e100, Alternate Intel driver)"
+	tristate "Intel(R) PRO/100+ support"
 	depends on NET_PCI && PCI
+	select MII
 	---help---
 	  This driver supports Intel(R) PRO/100 family of adapters, which 
 	  includes:
@@ -1428,6 +1429,10 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module
 	  will be called e100.
 
+config E100_NAPI
+	bool "Use Rx Polling (NAPI)"
+	depends on E100
+
 config LNE390
 	tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
 	depends on NET_PCI && EISA && EXPERIMENTAL
@@ -2475,6 +2480,13 @@
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called shaper.  If unsure, say N.
+
+config NETCONSOLE
+	tristate "Network console logging support (EXPERIMENTAL)"
+	depends on NETDEVICES && EXPERIMENTAL
+	---help---
+	If you want to log kernel messages over the network, enable this.
+	See Documentation/networking/netconsole.txt for details.
 
 source "drivers/net/wan/Kconfig"
 
diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/Makefile	Wed Feb 11 22:30:57 2004
@@ -8,7 +8,6 @@
   obj-$(CONFIG_ISDN) += slhc.o
 endif
 
-obj-$(CONFIG_E100) += e100/
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_IXGB) += ixgb/
 obj-$(CONFIG_BONDING) += bonding/
@@ -39,6 +38,7 @@
 obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
 obj-$(CONFIG_PCNET32) += pcnet32.o
 obj-$(CONFIG_EEPRO100) += eepro100.o
+obj-$(CONFIG_E100) += e100.o
 obj-$(CONFIG_TLAN) += tlan.o
 obj-$(CONFIG_EPIC100) += epic100.o
 obj-$(CONFIG_SIS190) += sis190.o
@@ -188,3 +188,4 @@
 obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/
 
+obj-$(CONFIG_NETCONSOLE) += netconsole.o
diff -Nru a/drivers/net/ac3200.c b/drivers/net/ac3200.c
--- a/drivers/net/ac3200.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/ac3200.c	Wed Feb 11 22:30:57 2004
@@ -276,6 +276,9 @@
 
 	dev->open = &ac_open;
 	dev->stop = &ac_close_card;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 out1:
diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c
--- a/drivers/net/acenic.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/acenic.c	Wed Feb 11 22:30:57 2004
@@ -731,12 +731,6 @@
 			break;
 		}
 
-		if (register_netdev(dev)) {
-			printk(KERN_ERR "acenic: device registration failed\n");
-			free_netdev(dev);
-			continue;
-		}
-
 		switch(pdev->vendor) {
 		case PCI_VENDOR_ID_ALTEON:
 			if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {
@@ -824,6 +818,13 @@
 			continue;
 		}
 
+		if (register_netdev(dev)) {
+			printk(KERN_ERR "acenic: device registration failed\n");
+			ace_init_cleanup(dev);
+			free_netdev(dev);
+			continue;
+		}
+
 		if (ap->pci_using_dac)
 			dev->features |= NETIF_F_HIGHDMA;
 
@@ -874,6 +875,7 @@
 	while (root_dev) {
 		ap = root_dev->priv;
 		next = ap->next;
+		unregister_netdev(root_dev);
 
 		regs = ap->regs;
 
@@ -1133,7 +1135,6 @@
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 
-	unregister_netdev(dev);
 	iounmap(ap->regs);
 }
 
diff -Nru a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
--- a/drivers/net/amd8111e.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/amd8111e.c	Wed Feb 11 22:30:57 2004
@@ -1153,6 +1153,17 @@
 	return IRQ_RETVAL(handled);
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void amd8111e_poll(struct net_device *dev)
+{ 
+	unsigned long flags;
+	local_save_flags(flags); 
+	local_irq_disable();
+	amd8111e_interrupt(0, dev, NULL);
+	local_irq_restore(flags); 
+} 
+#endif
+
 /*
 This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down.
 */
@@ -1884,6 +1895,9 @@
 	dev->irq =pdev->irq;
 	dev->tx_timeout = amd8111e_tx_timeout; 
 	dev->watchdog_timeo = AMD8111E_TX_TIMEOUT; 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = amd8111e_poll; 
+#endif
 
 #if AMD8111E_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
diff -Nru a/drivers/net/apne.c b/drivers/net/apne.c
--- a/drivers/net/apne.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/apne.c	Wed Feb 11 22:30:57 2004
@@ -333,6 +333,9 @@
     ei_status.get_8390_hdr = &apne_get_8390_hdr;
     dev->open = &apne_open;
     dev->stop = &apne_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = ei_poll;
+#endif
     NS8390_init(dev, 0);
 
     pcmcia_ack_int(pcmcia_get_intreq());		/* ack PCMCIA int req */
@@ -579,6 +582,8 @@
 	free_irq(IRQ_AMIGA_PORTS, apne_dev);
 
 	pcmcia_reset();
+
+	release_region(IOBASE, 0x20);
 
 	free_netdev(apne_dev);
 }
diff -Nru a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
--- a/drivers/net/appletalk/cops.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/appletalk/cops.c	Wed Feb 11 22:30:57 2004
@@ -262,7 +262,7 @@
 out1:
 	cleanup_card(dev);
 out:
-	kfree(dev);
+	free_netdev(dev);
 	return ERR_PTR(err);
 }
 
diff -Nru a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
--- a/drivers/net/arm/am79c961a.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/arm/am79c961a.c	Wed Feb 11 22:30:57 2004
@@ -672,6 +672,10 @@
 	dev->base_addr = 0x220;
 	dev->irq = IRQ_EBSA110_ETHERNET;
 
+    	ret = -ENODEV;
+	if (!request_region(dev->base_addr, 0x18, dev->name))
+		goto nodev;
+
 	/*
 	 * Reset the device.
 	 */
@@ -682,14 +686,10 @@
 	 * Check the manufacturer part of the
 	 * ether address.
 	 */
-    	ret = -ENODEV;
 	if (inb(dev->base_addr) != 0x08 ||
 	    inb(dev->base_addr + 2) != 0x00 ||
 	    inb(dev->base_addr + 4) != 0x2b)
-	    	goto nodev;
-
-	if (!request_region(dev->base_addr, 0x18, dev->name))
-		goto nodev;
+	    	goto release;
 
 	am79c961_banner();
 	printk(KERN_INFO "%s: ether address ", dev->name);
diff -Nru a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
--- a/drivers/net/bonding/bond_3ad.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/bonding/bond_3ad.c	Wed Feb 11 22:30:57 2004
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -48,7 +48,7 @@
  *	  problem on very high Tx traffic load where packets may get dropped
  *	  by the slave.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
  */
 
diff -Nru a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
--- a/drivers/net/bonding/bond_3ad.h	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/bonding/bond_3ad.h	Wed Feb 11 22:30:57 2004
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -29,7 +29,7 @@
  *	- Renamed bond_3ad_link_status_changed() to
  *	  bond_3ad_handle_link_change() for compatibility with TLB.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
  */
 
diff -Nru a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
--- a/drivers/net/bonding/bond_alb.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/bonding/bond_alb.c	Wed Feb 11 22:30:57 2004
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -29,8 +29,11 @@
  *	- Add support for setting bond's MAC address with special
  *	  handling required for ALB/TLB.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
+ *
+ * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
+ *	- Fixed: Cannot remove and re-enslave the original active slave.
  */
 
 //#define BONDING_DEBUG 1
@@ -992,6 +995,7 @@
 static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
 {
 	struct slave *tmp_slave1, *tmp_slave2, *free_mac_slave;
+	struct slave *has_bond_addr = bond->curr_active_slave;
 	int i, j, found = 0;
 
 	if (bond->slave_cnt == 0) {
@@ -1049,6 +1053,15 @@
 			free_mac_slave = tmp_slave1;
 			break;
 		}
+
+		if (!has_bond_addr) {
+			if (!memcmp(tmp_slave1->dev->dev_addr,
+				    bond->dev->dev_addr,
+				    ETH_ALEN)) {
+
+				has_bond_addr = tmp_slave1;
+			}
+		}
 	}
 
 	if (free_mac_slave) {
@@ -1059,7 +1072,8 @@
 		       ": Warning: the hw address of slave %s is in use by "
 		       "the bond; giving it the hw address of %s\n",
 		       slave->dev->name, free_mac_slave->dev->name);
-	} else {
+
+	} else if (has_bond_addr) {
 		printk(KERN_ERR DRV_NAME
 		       ": Error: the hw address of slave %s is in use by the "
 		       "bond; couldn't find a slave with a free hw address to "
@@ -1217,8 +1231,7 @@
 			break;
 		}
 
-		if (ipx_hdr(skb)->ipx_type !=
-		    __constant_htons(IPX_TYPE_NCP)) {
+		if (ipx_hdr(skb)->ipx_type != IPX_TYPE_NCP) {
 			/* The only protocol worth balancing in
 			 * this family since it has an "ARP" like
 			 * mechanism
diff -Nru a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
--- a/drivers/net/bonding/bond_alb.h	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/bonding/bond_alb.h	Wed Feb 11 22:30:57 2004
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -25,7 +25,7 @@
  *	- Add support for setting bond's MAC address with special
  *	  handling required for ALB/TLB.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
  */
 
diff -Nru a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
--- a/drivers/net/bonding/bond_main.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/bonding/bond_main.c	Wed Feb 11 22:30:57 2004
@@ -452,6 +452,15 @@
  *	  o Change struct member names and types.
  *	  o Chomp trailing spaces, remove empty lines, fix indentations.
  *	  o Re-organize code according to context.
+ *
+ * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
+ *	- Fixed: Cannot remove and re-enslave the original active slave.
+ *	- Fixed: Releasing the original active slave causes mac address duplication.
+ *	- Add support for slaves that use ethtool_ops.
+ *	  Set version to 2.5.3.
+ *
+ * 2004/01/05 - Amir Noam <amir.noam at intel dot com>
+ *	- Save bonding parameters per bond instead of using the global values.
  */
 
 //#define BONDING_DEBUG 1
@@ -503,7 +512,6 @@
 /* monitor all links that often (in milliseconds). <=0 disables monitoring */
 #define BOND_LINK_MON_INTERV	0
 #define BOND_LINK_ARP_INTERV	0
-#define MAX_ARP_IP_TARGETS	16
 
 static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
 static int miimon	= BOND_LINK_MON_INTERV;
@@ -514,7 +522,7 @@
 static char *primary	= NULL;
 static char *lacp_rate	= NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
-static char *arp_ip_target[MAX_ARP_IP_TARGETS] = { NULL, };
+static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
 
 MODULE_PARM(max_bonds, "i");
 MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -534,7 +542,7 @@
 MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
 MODULE_PARM(arp_interval, "i");
 MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
-MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(MAX_ARP_IP_TARGETS) "s");
+MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(BOND_MAX_ARP_TARGETS) "s");
 MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
 
 /*----------------------------- Global variables ----------------------------*/
@@ -548,7 +556,7 @@
 static struct proc_dir_entry *bond_proc_dir = NULL;
 #endif
 
-static u32 arp_target[MAX_ARP_IP_TARGETS] = { 0, } ;
+static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
 static int arp_ip_count	= 0;
 static u32 my_ip	= 0;
 static int bond_mode	= BOND_MODE_ROUNDROBIN;
@@ -584,11 +592,15 @@
 {	NULL,			-1},
 };
 
+/*-------------------------- Forward declarations ---------------------------*/
+
+static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode);
+
 /*---------------------------- General routines -----------------------------*/
 
-static const char *bond_mode_name(void)
+static const char *bond_mode_name(int mode)
 {
-	switch (bond_mode) {
+	switch (mode) {
 	case BOND_MODE_ROUNDROBIN :
 		return "load balancing (round-robin)";
 	case BOND_MODE_ACTIVEBACKUP :
@@ -623,44 +635,55 @@
 	struct ifreq ifr;
 	struct ethtool_cmd etool;
 
-	ioctl = slave_dev->do_ioctl;
-	if (ioctl) {
-		etool.cmd = ETHTOOL_GSET;
-		ifr.ifr_data = (char*)&etool;
-		if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) {
-			slave->speed = etool.speed;
-			slave->duplex = etool.duplex;
-		} else {
-			goto err_out;
+	/* Fake speed and duplex */
+	slave->speed = SPEED_100;
+	slave->duplex = DUPLEX_FULL;
+
+	if (slave_dev->ethtool_ops) {
+		u32 res;
+
+		if (!slave_dev->ethtool_ops->get_settings) {
+			return -1;
 		}
-	} else {
-		goto err_out;
+
+		res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
+		if (res < 0) {
+			return -1;
+		}
+
+		goto verify;
 	}
 
-	switch (slave->speed) {
+	ioctl = slave_dev->do_ioctl;
+	strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
+	etool.cmd = ETHTOOL_GSET;
+	ifr.ifr_data = (char*)&etool;
+	if (!ioctl || (IOCTL(slave_dev, &ifr, SIOCETHTOOL) < 0)) {
+		return -1;
+	}
+
+verify:
+	switch (etool.speed) {
 	case SPEED_10:
 	case SPEED_100:
 	case SPEED_1000:
 		break;
 	default:
-		goto err_out;
+		return -1;
 	}
 
-	switch (slave->duplex) {
+	switch (etool.duplex) {
 	case DUPLEX_FULL:
 	case DUPLEX_HALF:
 		break;
 	default:
-		goto err_out;
+		return -1;
 	}
 
-	return 0;
+	slave->speed = etool.speed;
+	slave->duplex = etool.duplex;
 
-err_out:
-	/* Fake speed and duplex */
-	slave->speed = SPEED_100;
-	slave->duplex = DUPLEX_FULL;
-	return -1;
+	return 0;
 }
 
 /*
@@ -679,14 +702,14 @@
  * It'd be nice if there was a good way to tell if a driver supports
  * netif_carrier, but there really isn't.
  */
-static int bond_check_dev_link(struct net_device *slave_dev, int reporting)
+static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting)
 {
 	static int (* ioctl)(struct net_device *, struct ifreq *, int);
 	struct ifreq ifr;
 	struct mii_ioctl_data *mii;
 	struct ethtool_value etool;
 
-	if (use_carrier) {
+	if (bond->params.use_carrier) {
 		return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
 	}
 
@@ -705,6 +728,7 @@
 		 */
 
 		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
+		strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
 		mii = (struct mii_ioctl_data *)&ifr.ifr_data;
 		if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
 			mii->reg_num = MII_BMSR;
@@ -712,10 +736,23 @@
 				return (mii->val_out & BMSR_LSTATUS);
 			}
 		}
+	}
+
+	/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
+	/* for a period of time so we attempt to get link status   */
+	/* from it last if the above MII ioctls fail...            */
+	if (slave_dev->ethtool_ops) {
+		if (slave_dev->ethtool_ops->get_link) {
+			u32 link;
+
+			link = slave_dev->ethtool_ops->get_link(slave_dev);
+
+			return link ? BMSR_LSTATUS : 0;
+		}
+	}
 
-		/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
-		/* for a period of time so we attempt to get link status   */
-		/* from it last if the above MII ioctls fail...            */
+	if (ioctl) {
+		strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
 		etool.cmd = ETHTOOL_GLINK;
 		ifr.ifr_data = (char*)&etool;
 		if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) {
@@ -769,7 +806,7 @@
  */
 static void bond_set_promiscuity(struct bonding *bond, int inc)
 {
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
 			dev_set_promiscuity(bond->curr_active_slave->dev, inc);
@@ -788,7 +825,7 @@
  */
 static void bond_set_allmulti(struct bonding *bond, int inc)
 {
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
 			dev_set_allmulti(bond->curr_active_slave->dev, inc);
@@ -808,7 +845,7 @@
  */
 static void bond_mc_add(struct bonding *bond, void *addr, int alen)
 {
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
 			dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0);
@@ -828,7 +865,7 @@
  */
 static void bond_mc_delete(struct bonding *bond, void *addr, int alen)
 {
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
 		if (bond->curr_active_slave) {
 			dev_mc_delete(bond->curr_active_slave->dev, addr, alen, 0);
@@ -888,13 +925,14 @@
  */
 static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev)
 {
+	struct bonding *bond = bond_dev->priv;
 	struct dev_mc_list *dmi;
 
 	for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
 		dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* del lacpdu mc addr from mc list */
 		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
 
@@ -913,7 +951,7 @@
 {
 	struct dev_mc_list *dmi;
 
-	if (!USES_PRIMARY(bond_mode)) {
+	if (!USES_PRIMARY(bond->params.mode)) {
 		/* nothing to do -  mc list is already up-to-date on
 		 * all slaves
 		 */
@@ -959,7 +997,7 @@
 {
 	struct slave *new_active, *old_active;
 	struct slave *bestslave = NULL;
-	int mintime;
+	int mintime = bond->params.updelay;
 	int i;
 
 	new_active = old_active = bond->curr_active_slave;
@@ -972,15 +1010,13 @@
 		}
 	}
 
-	mintime = updelay;
-
 	/* first try the primary link; if arping, a link must tx/rx traffic
 	 * before it can be considered the curr_active_slave - also, we would skip
 	 * slaves between the curr_active_slave and primary_slave that may be up
 	 * and able to arp
 	 */
 	if ((bond->primary_slave) &&
-	    (!arp_interval) &&
+	    (!bond->params.arp_interval) &&
 	    (IS_UP(bond->primary_slave->dev))) {
 		new_active = bond->primary_slave;
 	}
@@ -1030,28 +1066,28 @@
 
 	if (new_active) {
 		if (new_active->link == BOND_LINK_BACK) {
-			if (USES_PRIMARY(bond_mode)) {
+			if (USES_PRIMARY(bond->params.mode)) {
 				printk(KERN_INFO DRV_NAME
 				       ": %s: making interface %s the new "
 				       "active one %d ms earlier.\n",
 				       bond->dev->name, new_active->dev->name,
-				       (updelay - new_active->delay) * miimon);
+				       (bond->params.updelay - new_active->delay) * bond->params.miimon);
 			}
 
 			new_active->delay = 0;
 			new_active->link = BOND_LINK_UP;
 			new_active->jiffies = jiffies;
 
-			if (bond_mode == BOND_MODE_8023AD) {
+			if (bond->params.mode == BOND_MODE_8023AD) {
 				bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
 			}
 
-			if ((bond_mode == BOND_MODE_TLB) ||
-			    (bond_mode == BOND_MODE_ALB)) {
+			if ((bond->params.mode == BOND_MODE_TLB) ||
+			    (bond->params.mode == BOND_MODE_ALB)) {
 				bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
 			}
 		} else {
-			if (USES_PRIMARY(bond_mode)) {
+			if (USES_PRIMARY(bond->params.mode)) {
 				printk(KERN_INFO DRV_NAME
 				       ": %s: making interface %s the new "
 				       "active one.\n",
@@ -1060,7 +1096,7 @@
 		}
 	}
 
-	if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
 		if (old_active) {
 			bond_set_slave_inactive_flags(old_active);
 		}
@@ -1070,12 +1106,12 @@
 		}
 	}
 
-	if (USES_PRIMARY(bond_mode)) {
+	if (USES_PRIMARY(bond->params.mode)) {
 		bond_mc_swap(bond, new_active, old_active);
 	}
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		bond_alb_handle_active_change(bond, new_active);
 	} else {
 		bond->curr_active_slave = new_active;
@@ -1230,13 +1266,13 @@
 			return -EINVAL;
 		}
 
-		if ((bond_mode == BOND_MODE_8023AD) ||
-		    (bond_mode == BOND_MODE_TLB)    ||
-		    (bond_mode == BOND_MODE_ALB)) {
+		if ((bond->params.mode == BOND_MODE_8023AD) ||
+		    (bond->params.mode == BOND_MODE_TLB)    ||
+		    (bond->params.mode == BOND_MODE_ALB)) {
 			printk(KERN_ERR DRV_NAME
 			       ": Error: to use %s mode, you must upgrade "
 			       "ifenslave.\n",
-			       bond_mode_name());
+			       bond_mode_name(bond->params.mode));
 			return -EOPNOTSUPP;
 		}
 	}
@@ -1292,8 +1328,8 @@
 
 	new_slave->dev = slave_dev;
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		/* bond_alb_init_slave() must be called before all other stages since
 		 * it might fail and we do not want to have to undo everything
 		 */
@@ -1308,7 +1344,7 @@
 	 * curr_active_slave, and that is taken care of later when calling
 	 * bond_change_active()
 	 */
-	if (!USES_PRIMARY(bond_mode)) {
+	if (!USES_PRIMARY(bond->params.mode)) {
 		/* set promiscuity level to new slave */
 		if (bond_dev->flags & IFF_PROMISC) {
 			dev_set_promiscuity(slave_dev, 1);
@@ -1325,7 +1361,7 @@
 		}
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* add lacpdu mc addr to mc list */
 		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
 
@@ -1339,10 +1375,10 @@
 	new_slave->delay = 0;
 	new_slave->link_failure_count = 0;
 
-	if (miimon && !use_carrier) {
-		link_reporting = bond_check_dev_link(slave_dev, 1);
+	if (bond->params.miimon && !bond->params.use_carrier) {
+		link_reporting = bond_check_dev_link(bond, slave_dev, 1);
 
-		if ((link_reporting == -1) && !arp_interval) {
+		if ((link_reporting == -1) && !bond->params.arp_interval) {
 			/*
 			 * miimon is set but a bonded network driver
 			 * does not support ETHTOOL/MII and
@@ -1372,13 +1408,13 @@
 	}
 
 	/* check for initial state */
-	if (!miimon ||
-	    (bond_check_dev_link(slave_dev, 0) == BMSR_LSTATUS)) {
-		if (updelay) {
+	if (!bond->params.miimon ||
+	    (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS)) {
+		if (bond->params.updelay) {
 			dprintk("Initial state of slave_dev is "
 				"BOND_LINK_BACK\n");
 			new_slave->link  = BOND_LINK_BACK;
-			new_slave->delay = updelay;
+			new_slave->delay = bond->params.updelay;
 		} else {
 			dprintk("Initial state of slave_dev is "
 				"BOND_LINK_UP\n");
@@ -1398,7 +1434,7 @@
 		       "forced to 100Mbps, duplex forced to Full.\n",
 		       new_slave->dev->name);
 
-		if (bond_mode == BOND_MODE_8023AD) {
+		if (bond->params.mode == BOND_MODE_8023AD) {
 			printk(KERN_WARNING
 			       "Operation of 802.3ad mode requires ETHTOOL "
 			       "support in base driver for proper aggregator "
@@ -1406,14 +1442,14 @@
 		}
 	}
 
-	if (USES_PRIMARY(bond_mode) && primary) {
+	if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
 		/* if there is a primary slave, remember it */
-		if (strcmp(primary, new_slave->dev->name) == 0) {
+		if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
 			bond->primary_slave = new_slave;
 		}
 	}
 
-	switch (bond_mode) {
+	switch (bond->params.mode) {
 	case BOND_MODE_ACTIVEBACKUP:
 		/* if we're in active-backup mode, we need one and only one active
 		 * interface. The backup interfaces will have their NOARP flag set
@@ -1447,7 +1483,7 @@
 			 * can be called only after the mac address of the bond is set
 			 */
 			bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL,
-					    lacp_fast);
+					    bond->params.lacp_fast);
 		} else {
 			SLAVE_AD_INFO(new_slave).id =
 				SLAVE_AD_INFO(new_slave->prev).id + 1;
@@ -1557,7 +1593,7 @@
 static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 {
 	struct bonding *bond = bond_dev->priv;
-	struct slave *slave;
+	struct slave *slave, *oldcurrent;
 	struct sockaddr addr;
 	int mac_addr_differ;
 
@@ -1603,7 +1639,7 @@
 	}
 
 	/* Inform AD package of unbinding of slave. */
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* must be called before the slave is
 		 * detached from the list
 		 */
@@ -1617,6 +1653,8 @@
 	       ? "active" : "backup",
 	       slave_dev->name);
 
+	oldcurrent = bond->curr_active_slave;
+
 	bond->current_arp_slave = NULL;
 
 	/* release the slave from its bond */
@@ -1626,34 +1664,38 @@
 		bond->primary_slave = NULL;
 	}
 
-	if (bond->curr_active_slave == slave) {
+	if (oldcurrent == slave) {
 		bond_change_active_slave(bond, NULL);
-		bond_select_active_slave(bond);
 	}
 
-	if (!bond->curr_active_slave) {
-		printk(KERN_INFO DRV_NAME
-		       ": %s: now running without any active "
-		       "interface !\n",
-		       bond_dev->name);
-	}
-
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
-		/* must be called only after the slave has been
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
+		/* Must be called only after the slave has been
 		 * detached from the list and the curr_active_slave
-		 * has been replaced (if our_slave == old_current)
+		 * has been cleared (if our_slave == old_current),
+		 * but before a new active slave is selected.
 		 */
 		bond_alb_deinit_slave(bond, slave);
 	}
 
+	if (oldcurrent == slave) {
+		bond_select_active_slave(bond);
+
+		if (!bond->curr_active_slave) {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: now running without any active "
+			       "interface !\n",
+			       bond_dev->name);
+		}
+	}
+
 	write_unlock_bh(&bond->lock);
 
 	/* If the mode USES_PRIMARY, then we should only remove its
 	 * promisc and mc settings if it was the curr_active_slave, but that was
 	 * already taken care of above when we detached the slave
 	 */
-	if (!USES_PRIMARY(bond_mode)) {
+	if (!USES_PRIMARY(bond->params.mode)) {
 		/* unset promiscuity level from slave */
 		if (bond_dev->flags & IFF_PROMISC) {
 			dev_set_promiscuity(slave_dev, -1);
@@ -1725,15 +1767,15 @@
 		/* Inform AD package of unbinding of slave
 		 * before slave is detached from the list.
 		 */
-		if (bond_mode == BOND_MODE_8023AD) {
+		if (bond->params.mode == BOND_MODE_8023AD) {
 			bond_3ad_unbind_slave(slave);
 		}
 
 		slave_dev = slave->dev;
 		bond_detach_slave(bond, slave);
 
-		if ((bond_mode == BOND_MODE_TLB) ||
-		    (bond_mode == BOND_MODE_ALB)) {
+		if ((bond->params.mode == BOND_MODE_TLB) ||
+		    (bond->params.mode == BOND_MODE_ALB)) {
 			/* must be called only after the slave
 			 * has been detached from the list
 			 */
@@ -1750,7 +1792,7 @@
 		 * promisc and mc settings if it was the curr_active_slave, but that was
 		 * already taken care of above when we detached the slave
 		 */
-		if (!USES_PRIMARY(bond_mode)) {
+		if (!USES_PRIMARY(bond->params.mode)) {
 			/* unset promiscuity level from slave */
 			if (bond_dev->flags & IFF_PROMISC) {
 				dev_set_promiscuity(slave_dev, -1);
@@ -1824,6 +1866,10 @@
 	struct slave *new_active = NULL;
 	int res = 0;
 
+	if (!USES_PRIMARY(bond->params.mode)) {
+		return -EINVAL;
+	}
+
 	/* Verify that master_dev is indeed the master of slave_dev */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
 	    (slave_dev->master != bond_dev)) {
@@ -1912,8 +1958,8 @@
 {
 	struct bonding *bond = bond_dev->priv;
 
-	info->bond_mode = bond_mode;
-	info->miimon = miimon;
+	info->bond_mode = bond->params.mode;
+	info->miimon = bond->params.miimon;
 
 	read_lock_bh(&bond->lock);
 	info->num_slaves = bond->slave_cnt;
@@ -1963,11 +2009,13 @@
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave, *oldcurrent;
 	int do_failover = 0;
-	int delta_in_ticks = (miimon * HZ) / 1000;
+	int delta_in_ticks;
 	int i;
 
 	read_lock(&bond->lock);
 
+	delta_in_ticks = (bond->params.miimon * HZ) / 1000;
+
 	if (bond->kill_timers) {
 		goto out;
 	}
@@ -1992,7 +2040,7 @@
 		u16 old_speed = slave->speed;
 		u8 old_duplex = slave->duplex;
 
-		link_state = bond_check_dev_link(slave_dev, 0);
+		link_state = bond_check_dev_link(bond, slave_dev, 0);
 
 		switch (slave->link) {
 		case BOND_LINK_UP:	/* the link was up */
@@ -2001,26 +2049,26 @@
 				break;
 			} else { /* link going down */
 				slave->link  = BOND_LINK_FAIL;
-				slave->delay = downdelay;
+				slave->delay = bond->params.downdelay;
 
 				if (slave->link_failure_count < UINT_MAX) {
 					slave->link_failure_count++;
 				}
 
-				if (downdelay) {
+				if (bond->params.downdelay) {
 					printk(KERN_INFO DRV_NAME
 					       ": %s: link status down for %s "
 					       "interface %s, disabling it in "
 					       "%d ms.\n",
 					       bond_dev->name,
 					       IS_UP(slave_dev)
-					       ? ((bond_mode == BOND_MODE_ACTIVEBACKUP)
+					       ? ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
 						  ? ((slave == oldcurrent)
 						     ? "active " : "backup ")
 						  : "")
 					       : "idle ",
 					       slave_dev->name,
-					       downdelay * miimon);
+					       bond->params.downdelay * bond->params.miimon);
 				}
 			}
 			/* no break ! fall through the BOND_LINK_FAIL test to
@@ -2036,8 +2084,8 @@
 					/* in active/backup mode, we must
 					 * completely disable this interface
 					 */
-					if ((bond_mode == BOND_MODE_ACTIVEBACKUP) ||
-					    (bond_mode == BOND_MODE_8023AD)) {
+					if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) ||
+					    (bond->params.mode == BOND_MODE_8023AD)) {
 						bond_set_slave_inactive_flags(slave);
 					}
 
@@ -2049,12 +2097,12 @@
 					       slave_dev->name);
 
 					/* notify ad that the link status has changed */
-					if (bond_mode == BOND_MODE_8023AD) {
+					if (bond->params.mode == BOND_MODE_8023AD) {
 						bond_3ad_handle_link_change(slave, BOND_LINK_DOWN);
 					}
 
-					if ((bond_mode == BOND_MODE_TLB) ||
-					    (bond_mode == BOND_MODE_ALB)) {
+					if ((bond->params.mode == BOND_MODE_TLB) ||
+					    (bond->params.mode == BOND_MODE_ALB)) {
 						bond_alb_handle_link_change(bond, slave, BOND_LINK_DOWN);
 					}
 
@@ -2072,7 +2120,7 @@
 				       ": %s: link status up again after %d "
 				       "ms for interface %s.\n",
 				       bond_dev->name,
-				       (downdelay - slave->delay) * miimon,
+				       (bond->params.downdelay - slave->delay) * bond->params.miimon,
 				       slave_dev->name);
 			}
 			break;
@@ -2082,9 +2130,9 @@
 				break;
 			} else {	/* link going up */
 				slave->link  = BOND_LINK_BACK;
-				slave->delay = updelay;
+				slave->delay = bond->params.updelay;
 
-				if (updelay) {
+				if (bond->params.updelay) {
 					/* if updelay == 0, no need to
 					   advertise about a 0 ms delay */
 					printk(KERN_INFO DRV_NAME
@@ -2093,7 +2141,7 @@
 					       "in %d ms.\n",
 					       bond_dev->name,
 					       slave_dev->name,
-					       updelay * miimon);
+					       bond->params.updelay * bond->params.miimon);
 				}
 			}
 			/* no break ! fall through the BOND_LINK_BACK state in
@@ -2108,7 +2156,7 @@
 				       ": %s: link status down again after %d "
 				       "ms for interface %s.\n",
 				       bond_dev->name,
-				       (updelay - slave->delay) * miimon,
+				       (bond->params.updelay - slave->delay) * bond->params.miimon,
 				       slave_dev->name);
 			} else {
 				/* link stays up */
@@ -2117,10 +2165,10 @@
 					slave->link = BOND_LINK_UP;
 					slave->jiffies = jiffies;
 
-					if (bond_mode == BOND_MODE_8023AD) {
+					if (bond->params.mode == BOND_MODE_8023AD) {
 						/* prevent it from being the active one */
 						slave->state = BOND_STATE_BACKUP;
-					} else if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
+					} else if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
 						/* make it immediately active */
 						slave->state = BOND_STATE_ACTIVE;
 					} else if (slave != bond->primary_slave) {
@@ -2135,12 +2183,12 @@
 					       slave_dev->name);
 
 					/* notify ad that the link status has changed */
-					if (bond_mode == BOND_MODE_8023AD) {
+					if (bond->params.mode == BOND_MODE_8023AD) {
 						bond_3ad_handle_link_change(slave, BOND_LINK_UP);
 					}
 
-					if ((bond_mode == BOND_MODE_TLB) ||
-					    (bond_mode == BOND_MODE_ALB)) {
+					if ((bond->params.mode == BOND_MODE_TLB) ||
+					    (bond->params.mode == BOND_MODE_ALB)) {
 						bond_alb_handle_link_change(bond, slave, BOND_LINK_UP);
 					}
 
@@ -2162,7 +2210,7 @@
 
 		bond_update_speed_duplex(slave);
 
-		if (bond_mode == BOND_MODE_8023AD) {
+		if (bond->params.mode == BOND_MODE_8023AD) {
 			if (old_speed != slave->speed) {
 				bond_3ad_adapter_speed_changed(slave);
 			}
@@ -2190,17 +2238,20 @@
 	}
 
 re_arm:
-	mod_timer(&bond->mii_timer, jiffies + delta_in_ticks);
+	if (bond->params.miimon) {
+		mod_timer(&bond->mii_timer, jiffies + delta_in_ticks);
+	}
 out:
 	read_unlock(&bond->lock);
 }
 
-static void bond_arp_send_all(struct slave *slave)
+static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 {
 	int i;
+	u32 *targets = bond->params.arp_targets;
 
-	for (i = 0; (i<MAX_ARP_IP_TARGETS) && arp_target[i]; i++) {
-		arp_send(ARPOP_REQUEST, ETH_P_ARP, arp_target[i], slave->dev,
+	for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
+		arp_send(ARPOP_REQUEST, ETH_P_ARP, targets[i], slave->dev,
 			 my_ip, NULL, slave->dev->dev_addr,
 			 NULL);
 	}
@@ -2218,11 +2269,13 @@
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave, *oldcurrent;
 	int do_failover = 0;
-	int delta_in_ticks = (arp_interval * HZ) / 1000;
+	int delta_in_ticks;
 	int i;
 
 	read_lock(&bond->lock);
 
+	delta_in_ticks = (bond->params.arp_interval * HZ) / 1000;
+
 	if (bond->kill_timers) {
 		goto out;
 	}
@@ -2307,7 +2360,7 @@
 		 * to be unstable during low/no traffic periods
 		 */
 		if (IS_UP(slave->dev)) {
-			bond_arp_send_all(slave);
+			bond_arp_send_all(bond, slave);
 		}
 	}
 
@@ -2327,7 +2380,9 @@
 	}
 
 re_arm:
-	mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	if (bond->params.arp_interval) {
+		mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	}
 out:
 	read_unlock(&bond->lock);
 }
@@ -2351,11 +2406,13 @@
 {
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave;
-	int delta_in_ticks = (arp_interval * HZ) / 1000;
+	int delta_in_ticks;
 	int i;
 
 	read_lock(&bond->lock);
 
+	delta_in_ticks = (bond->params.arp_interval * HZ) / 1000;
+
 	if (bond->kill_timers) {
 		goto out;
 	}
@@ -2514,7 +2571,7 @@
 		 * rx traffic
 		 */
 		if (slave && my_ip) {
-			bond_arp_send_all(slave);
+			bond_arp_send_all(bond, slave);
 		}
 	}
 
@@ -2535,7 +2592,7 @@
 				if (IS_UP(slave->dev)) {
 					slave->link = BOND_LINK_BACK;
 					bond_set_slave_active_flags(slave);
-					bond_arp_send_all(slave);
+					bond_arp_send_all(bond, slave);
 					slave->jiffies = jiffies;
 					bond->current_arp_slave = slave;
 					break;
@@ -2567,7 +2624,9 @@
 	}
 
 re_arm:
-	mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	if (bond->params.arp_interval) {
+		mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+	}
 out:
 	read_unlock(&bond->lock);
 }
@@ -2625,33 +2684,40 @@
 	read_unlock(&dev_base_lock);
 }
 
-static void bond_info_show_master(struct seq_file *seq, struct bonding *bond)
+static void bond_info_show_master(struct seq_file *seq)
 {
+	struct bonding *bond = seq->private;
 	struct slave *curr;
 
 	read_lock(&bond->curr_slave_lock);
 	curr = bond->curr_active_slave;
 	read_unlock(&bond->curr_slave_lock);
 
-	seq_printf(seq, "Bonding Mode: %s\n", bond_mode_name());
+	seq_printf(seq, "Bonding Mode: %s\n",
+		   bond_mode_name(bond->params.mode));
 
-	if (USES_PRIMARY(bond_mode)) {
-		if (curr) {
-			seq_printf(seq,
-				   "Currently Active Slave: %s\n",
-				   curr->dev->name);
-		}
+	if (USES_PRIMARY(bond->params.mode)) {
+		seq_printf(seq, "Primary Slave: %s\n",
+			   (bond->params.primary[0]) ?
+			   	bond->params.primary : "None");
+
+		seq_printf(seq, "Currently Active Slave: %s\n",
+			   (curr) ? curr->dev->name : "None");
 	}
 
 	seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down");
-	seq_printf(seq, "MII Polling Interval (ms): %d\n", miimon);
-	seq_printf(seq, "Up Delay (ms): %d\n", updelay * miimon);
-	seq_printf(seq, "Down Delay (ms): %d\n", downdelay * miimon);
+	seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
+	seq_printf(seq, "Up Delay (ms): %d\n",
+		   bond->params.updelay * bond->params.miimon);
+	seq_printf(seq, "Down Delay (ms): %d\n",
+		   bond->params.downdelay * bond->params.miimon);
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
 
 		seq_puts(seq, "\n802.3ad info\n");
+		seq_printf(seq, "LACP rate: %s\n",
+			   (bond->params.lacp_fast) ? "fast" : "slow");
 
 		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 			seq_printf(seq, "bond %s has no active aggregator\n",
@@ -2680,6 +2746,8 @@
 
 static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave)
 {
+	struct bonding *bond = seq->private;
+
 	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
 	seq_printf(seq, "MII Status: %s\n",
 		   (slave->link == BOND_LINK_UP) ?  "up" : "down");
@@ -2697,7 +2765,7 @@
 			   slave->perm_hwaddr[5]);
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		const struct aggregator *agg
 			= SLAVE_AD_INFO(slave).port.aggregator;
 
@@ -2714,7 +2782,7 @@
 {
 	if (v == SEQ_START_TOKEN) {
 		seq_printf(seq, "%s\n", version);
-		bond_info_show_master(seq, seq->private);
+		bond_info_show_master(seq);
 	} else {
 		bond_info_show_slave(seq, v);
 	}
@@ -2989,14 +3057,14 @@
 
 	bond->kill_timers = 0;
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer);
 
 		/* bond_alb_initialize must be called before the timer
 		 * is started.
 		 */
-		if (bond_alb_initialize(bond, (bond_mode == BOND_MODE_ALB))) {
+		if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) {
 			/* something went wrong - fail the open operation */
 			return -1;
 		}
@@ -3008,7 +3076,7 @@
 		add_timer(alb_timer);
 	}
 
-	if (miimon) {  /* link check interval, in milliseconds. */
+	if (bond->params.miimon) {  /* link check interval, in milliseconds. */
 		init_timer(mii_timer);
 		mii_timer->expires  = jiffies + 1;
 		mii_timer->data     = (unsigned long)bond_dev;
@@ -3016,11 +3084,11 @@
 		add_timer(mii_timer);
 	}
 
-	if (arp_interval) {  /* arp interval, in milliseconds. */
+	if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
 		init_timer(arp_timer);
 		arp_timer->expires  = jiffies + 1;
 		arp_timer->data     = (unsigned long)bond_dev;
-		if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+		if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
 			arp_timer->function = (void *)&bond_activebackup_arp_mon;
 		} else {
 			arp_timer->function = (void *)&bond_loadbalance_arp_mon;
@@ -3028,7 +3096,7 @@
 		add_timer(arp_timer);
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct timer_list *ad_timer = &(BOND_AD_INFO(bond).ad_timer);
 		init_timer(ad_timer);
 		ad_timer->expires  = jiffies + 1;
@@ -3051,7 +3119,7 @@
 
 	bond_mc_list_destroy(bond);
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* Unregister the receive of LACPDUs */
 		bond_unregister_lacpdu(bond);
 	}
@@ -3065,15 +3133,15 @@
 	 * because a running timer might be trying to hold it too
 	 */
 
-	if (miimon) {  /* link check interval, in milliseconds. */
+	if (bond->params.miimon) {  /* link check interval, in milliseconds. */
 		del_timer_sync(&bond->mii_timer);
 	}
 
-	if (arp_interval) {  /* arp interval, in milliseconds. */
+	if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
 		del_timer_sync(&bond->arp_timer);
 	}
 
-	switch (bond_mode) {
+	switch (bond->params.mode) {
 	case BOND_MODE_8023AD:
 		del_timer_sync(&(BOND_AD_INFO(bond).ad_timer));
 		break;
@@ -3088,8 +3156,8 @@
 	/* Release the bonded slaves */
 	bond_release_all(bond_dev);
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		/* Must be called only after all
 		 * slaves have been released
 		 */
@@ -3269,11 +3337,7 @@
 			break;
 		case BOND_CHANGE_ACTIVE_OLD:
 		case SIOCBONDCHANGEACTIVE:
-			if (USES_PRIMARY(bond_mode)) {
-				res = bond_ioctl_change_active(bond_dev, slave_dev);
-			} else {
-				res = -EINVAL;
-			}
+			res = bond_ioctl_change_active(bond_dev, slave_dev);
 			break;
 		default:
 			res = -EOPNOTSUPP;
@@ -3556,7 +3620,7 @@
 
 	/* if we are sending arp packets, try to at least
 	   identify our own ip address */
-	if (arp_interval && !my_ip &&
+	if (bond->params.arp_interval && !my_ip &&
 		(skb->protocol == __constant_htons(ETH_P_ARP))) {
 		char *the_ip = (char *)skb->data +
 				sizeof(struct ethhdr) +
@@ -3717,13 +3781,47 @@
 /*------------------------- Device initialization ---------------------------*/
 
 /*
+ * set bond mode specific net device operations
+ */
+static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode)
+{
+	switch (mode) {
+	case BOND_MODE_ROUNDROBIN:
+		bond_dev->hard_start_xmit = bond_xmit_roundrobin;
+		break;
+	case BOND_MODE_ACTIVEBACKUP:
+		bond_dev->hard_start_xmit = bond_xmit_activebackup;
+		break;
+	case BOND_MODE_XOR:
+		bond_dev->hard_start_xmit = bond_xmit_xor;
+		break;
+	case BOND_MODE_BROADCAST:
+		bond_dev->hard_start_xmit = bond_xmit_broadcast;
+		break;
+	case BOND_MODE_8023AD:
+		bond_dev->hard_start_xmit = bond_3ad_xmit_xor;
+		break;
+	case BOND_MODE_TLB:
+	case BOND_MODE_ALB:
+		bond_dev->hard_start_xmit = bond_alb_xmit;
+		bond_dev->set_mac_address = bond_alb_set_mac_address;
+		break;
+	default:
+		/* Should never happen, mode already checked */
+		printk(KERN_ERR DRV_NAME
+		       ": Error: Unknown bonding mode %d\n",
+		       mode);
+		break;
+	}
+}
+
+/*
  * Does not allocate but creates a /proc entry.
  * Allowed to fail.
  */
-static int __init bond_init(struct net_device *bond_dev)
+static int __init bond_init(struct net_device *bond_dev, struct bond_params *params)
 {
 	struct bonding *bond = bond_dev->priv;
-	int count;
 
 	dprintk("Begin bond_init for %s\n", bond_dev->name);
 
@@ -3731,6 +3829,8 @@
 	rwlock_init(&bond->lock);
 	rwlock_init(&bond->curr_slave_lock);
 
+	bond->params = *params; /* copy params struct */
+
 	/* Initialize pointers */
 	bond->first_slave = NULL;
 	bond->curr_active_slave = NULL;
@@ -3747,33 +3847,7 @@
 	bond_dev->change_mtu = bond_change_mtu;
 	bond_dev->set_mac_address = bond_set_mac_address;
 
-	switch (bond_mode) {
-	case BOND_MODE_ROUNDROBIN:
-		bond_dev->hard_start_xmit = bond_xmit_roundrobin;
-		break;
-	case BOND_MODE_ACTIVEBACKUP:
-		bond_dev->hard_start_xmit = bond_xmit_activebackup;
-		break;
-	case BOND_MODE_XOR:
-		bond_dev->hard_start_xmit = bond_xmit_xor;
-		break;
-	case BOND_MODE_BROADCAST:
-		bond_dev->hard_start_xmit = bond_xmit_broadcast;
-		break;
-	case BOND_MODE_8023AD:
-		bond_dev->hard_start_xmit = bond_3ad_xmit_xor; /* extern */
-		break;
-	case BOND_MODE_TLB:
-	case BOND_MODE_ALB:
-		bond_dev->hard_start_xmit = bond_alb_xmit; /* extern */
-		bond_dev->set_mac_address = bond_alb_set_mac_address; /* extern */
-		break;
-	default:
-		printk(KERN_ERR DRV_NAME
-		       ": Error: Unknown bonding mode %d\n",
-		       bond_mode);
-		return -EINVAL;
-	}
+	bond_set_mode_ops(bond_dev, bond->params.mode);
 
 	bond_dev->destructor = free_netdev;
 #ifdef CONFIG_NET_FASTROUTE
@@ -3784,27 +3858,6 @@
 	bond_dev->tx_queue_len = 0;
 	bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
 
-	printk(KERN_INFO DRV_NAME ": %s registered with", bond_dev->name);
-	if (miimon) {
-		printk(" MII link monitoring set to %d ms", miimon);
-		updelay /= miimon;
-		downdelay /= miimon;
-	} else {
-		printk("out MII link monitoring");
-	}
-	printk(", in %s mode.\n", bond_mode_name());
-
-	printk(KERN_INFO DRV_NAME ": %s registered with", bond_dev->name);
-	if (arp_interval > 0) {
-		printk(" ARP monitoring set to %d ms with %d target(s):",
-		       arp_interval, arp_ip_count);
-		for (count=0 ; count<arp_ip_count ; count++) {
-			printk(" %s", arp_ip_target[count]);
-		}
-		printk("\n");
-	} else {
-		printk("out ARP monitoring\n");
-	}
 
 #ifdef CONFIG_PROC_FS
 	bond_create_proc_entry(bond);
@@ -3870,7 +3923,7 @@
 	return -1;
 }
 
-static int bond_check_params(void)
+static int bond_check_params(struct bond_params *params)
 {
 	/*
 	 * Convert string parameters.
@@ -3889,7 +3942,7 @@
 		if (bond_mode != BOND_MODE_8023AD) {
 			printk(KERN_INFO DRV_NAME
 			       ": lacp_rate param is irrelevant in mode %s\n",
-			       bond_mode_name());
+			       bond_mode_name(bond_mode));
 		} else {
 			lacp_fast = bond_parse_parm(lacp_rate, bond_lacp_tbl);
 			if (lacp_fast == -1) {
@@ -3933,17 +3986,17 @@
 		downdelay = 0;
 	}
 
+	if ((use_carrier != 0) && (use_carrier != 1)) {
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: use_carrier module parameter (%d), "
+		       "not of valid value (0/1), so it was set to 1\n",
+		       use_carrier);
+		use_carrier = 1;
+	}
+
 	/* reset values for 802.3ad */
 	if (bond_mode == BOND_MODE_8023AD) {
-		if (arp_interval) {
-			printk(KERN_WARNING DRV_NAME
-			       ": Warning: ARP monitoring can't be used "
-			       "simultaneously with 802.3ad, disabling ARP "
-			       "monitoring\n");
-			arp_interval = 0;
-		}
-
-		if (miimon) {
+		if (!miimon) {
 			printk(KERN_WARNING DRV_NAME
 			       ": Warning: miimon must be specified, "
 			       "otherwise bonding will not detect link "
@@ -4002,25 +4055,23 @@
 		}
 
 		if ((updelay % miimon) != 0) {
-			/* updelay will be rounded in bond_init() when it
-			 * is divided by miimon, we just inform user here
-			 */
 			printk(KERN_WARNING DRV_NAME
 			       ": Warning: updelay (%d) is not a multiple "
 			       "of miimon (%d), updelay rounded to %d ms\n",
 			       updelay, miimon, (updelay / miimon) * miimon);
 		}
 
+		updelay /= miimon;
+
 		if ((downdelay % miimon) != 0) {
-			/* downdelay will be rounded in bond_init() when it
-			 * is divided by miimon, we just inform user here
-			 */
 			printk(KERN_WARNING DRV_NAME
 			       ": Warning: downdelay (%d) is not a multiple "
 			       "of miimon (%d), downdelay rounded to %d ms\n",
 			       downdelay, miimon,
 			       (downdelay / miimon) * miimon);
 		}
+
+		downdelay /= miimon;
 	}
 
 	if (arp_interval < 0) {
@@ -4032,7 +4083,7 @@
 	}
 
 	for (arp_ip_count = 0;
-	     (arp_ip_count < MAX_ARP_IP_TARGETS) && arp_ip_target[arp_ip_count];
+	     (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[arp_ip_count];
 	     arp_ip_count++) {
 		/* not complete check, but should be good enough to
 		   catch mistakes */
@@ -4058,7 +4109,23 @@
 		arp_interval = 0;
 	}
 
-	if (!miimon && !arp_interval) {
+	if (miimon) {
+		printk(KERN_INFO DRV_NAME
+		       ": MII link monitoring set to %d ms\n",
+		       miimon);
+	} else if (arp_interval) {
+		int i;
+
+		printk(KERN_INFO DRV_NAME
+		       ": ARP monitoring set to %d ms with %d target(s):",
+		       arp_interval, arp_ip_count);
+
+		for (i = 0; i < arp_ip_count; i++)
+			printk (" %s", arp_ip_target[i]);
+
+		printk("\n");
+
+	} else {
 		/* miimon and arp_interval not set, we need one so things
 		 * work as expected, see bonding.txt for details
 		 */
@@ -4076,21 +4143,39 @@
 		printk(KERN_WARNING DRV_NAME
 		       ": Warning: %s primary device specified but has no "
 		       "effect in %s mode\n",
-		       primary, bond_mode_name());
+		       primary, bond_mode_name(bond_mode));
 		primary = NULL;
 	}
 
+	/* fill params struct with the proper values */
+	params->mode = bond_mode;
+	params->miimon = miimon;
+	params->arp_interval = arp_interval;
+	params->updelay = updelay;
+	params->downdelay = downdelay;
+	params->use_carrier = use_carrier;
+	params->lacp_fast = lacp_fast;
+	params->primary[0] = 0;
+
+	if (primary) {
+		strncpy(params->primary, primary, IFNAMSIZ);
+		params->primary[IFNAMSIZ - 1] = 0;
+	}
+
+	memcpy(params->arp_targets, arp_target, sizeof(arp_target));
+
 	return 0;
 }
 
 static int __init bonding_init(void)
 {
+	struct bond_params params;
 	int i;
 	int res;
 
 	printk(KERN_INFO "%s", version);
 
-	res = bond_check_params();
+	res = bond_check_params(&params);
 	if (res) {
 		return res;
 	}
@@ -4120,7 +4205,7 @@
 		 * /proc files), but before register_netdevice(), because we
 		 * need to set function pointers.
 		 */
-		res = bond_init(bond_dev);
+		res = bond_init(bond_dev, &params);
 		if (res < 0) {
 			free_netdev(bond_dev);
 			goto out_err;
diff -Nru a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
--- a/drivers/net/bonding/bonding.h	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/bonding/bonding.h	Wed Feb 11 22:30:57 2004
@@ -23,7 +23,7 @@
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Added support for Transmit load balancing mode.
  *
- * 2003/09/24 - Shmulik Hen <shmulik.hen at intel dot com>
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
  */
 
@@ -36,11 +36,13 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"2.5.0"
-#define DRV_RELDATE	"December 1, 2003"
+#define DRV_VERSION	"2.5.4"
+#define DRV_RELDATE	"December 30, 2003"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
+#define BOND_MAX_ARP_TARGETS	16
+
 #ifdef BONDING_DEBUG
 #define dprintk(fmt, args...) \
 	printk(KERN_DEBUG     \
@@ -133,6 +135,18 @@
 		bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave)
 
 
+struct bond_params {
+	int mode;
+	int miimon;
+	int arp_interval;
+	int use_carrier;
+	int updelay;
+	int downdelay;
+	int lacp_fast;
+	char primary[IFNAMSIZ];
+	u32 arp_targets[BOND_MAX_ARP_TARGETS];
+};
+
 struct slave {
 	struct net_device *dev; /* first - usefull for panic debug */
 	struct slave *next;
@@ -181,6 +195,7 @@
 	u16      flags;
 	struct   ad_bond_info ad_info;
 	struct   alb_bond_info alb_info;
+	struct   bond_params params;
 };
 
 /**
diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c
--- a/drivers/net/dgrs.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/dgrs.c	Wed Feb 11 22:30:56 2004
@@ -121,11 +121,22 @@
 #include "dgrs_asstruct.h"
 #include "dgrs_bcomm.h"
 
+#ifdef CONFIG_PCI
 static struct pci_device_id dgrs_pci_tbl[] = {
 	{ SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
 	{ }			/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, dgrs_pci_tbl);
+#endif
+
+#ifdef CONFIG_EISA
+static struct eisa_device_id dgrs_eisa_tbl[] = {
+	{ "DBI0A01" },
+	{ }
+};
+MODULE_DEVICE_TABLE(eisa, dgrs_eisa_tbl);
+#endif
+
 MODULE_LICENSE("GPL");
 
 
@@ -179,11 +190,6 @@
 static int	dgrs_nicmode;
 
 /*
- *	Chain of device structures
- */
-static struct net_device *dgrs_root_dev;
-
-/*
  *	Private per-board data structure (dev->priv)
  */
 typedef struct
@@ -191,7 +197,6 @@
 	/*
 	 *	Stuff for generic ethercard I/F
 	 */
-	struct net_device		*next_dev;
 	struct net_device_stats	stats;
 
 	/*
@@ -1187,7 +1192,7 @@
 	priv->intrcnt = 0;
 	for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); )
 	{
-		barrier();		/* gcc 2.95 needs this */
+		cpu_relax();
 		if (priv->intrcnt >= 2)
 			break;
 	}
@@ -1200,16 +1205,6 @@
 	}
 
 	/*
-	 *	Register the /proc/ioports information...
-	 */
-	if (!request_region(dev->base_addr, 256, "RightSwitch")) {
-		printk(KERN_ERR "%s: io 0x%3lX, which is busy.\n", dev->name,
-				dev->base_addr);
-		rc = -EBUSY;
-		goto err_free_irq;
-	}
-	
-	/*
 	 *	Entry points...
 	 */
 	dev->open = &dgrs_open;
@@ -1242,22 +1237,23 @@
 	return (0);
 }
 
-static int __init 
+static struct net_device * __init 
 dgrs_found_device(
 	int		io,
 	ulong		mem,
 	int		irq,
 	ulong		plxreg,
-	ulong		plxdma
+	ulong		plxdma,
+	struct device   *pdev
 )
 {
-	DGRS_PRIV	*priv;
-	struct net_device *dev, *aux;
-	int i, ret;
+	DGRS_PRIV *priv;
+	struct net_device *dev;
+	int i, ret = -ENOMEM;
 
 	dev = alloc_etherdev(sizeof(DGRS_PRIV));
 	if (!dev)
-		return -ENOMEM;
+		goto err0;
 
 	priv = (DGRS_PRIV *)dev->priv;
 
@@ -1272,19 +1268,19 @@
 	priv->chan = 1;
 	priv->devtbl[0] = dev;
 
-	dev->init = dgrs_probe1;
 	SET_MODULE_OWNER(dev);
-
-	if (register_netdev(dev) != 0) {
-		free_netdev(dev);
-		return -EIO;
-	}
-
-	priv->next_dev = dgrs_root_dev;
-	dgrs_root_dev = dev;
+	SET_NETDEV_DEV(dev, pdev);
+	
+	ret = dgrs_probe1(dev);
+	if (ret) 
+		goto err1;
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto err2;
 
 	if ( !dgrs_nicmode )
-		return (0);	/* Switch mode, we are done */
+		return dev;	/* Switch mode, we are done */
 
 	/*
 	 * Operating card as N separate NICs
@@ -1302,8 +1298,7 @@
 		if (!devN) 
 			goto fail;
 
-		/* Make it an exact copy of dev[0]... */
-		*devN = *dev;
+		/* Don't copy the network device structure! */
 
 		/* copy the priv structure of dev[0] */
 		privN = (DGRS_PRIV *)devN->priv;
@@ -1316,123 +1311,212 @@
 		devN->irq = 0;
 			/* ... and base MAC address off address of 1st port */
 		devN->dev_addr[5] += i;
-			/* ... choose a new name */
-		strncpy(devN->name, "eth%d", IFNAMSIZ);
-		devN->init = dgrs_initclone;
+
+		ret = dgrs_initclone(devN);
+		if (ret)
+			goto fail;
+
 		SET_MODULE_OWNER(devN);
+		SET_NETDEV_DEV(dev, pdev);
 
-		ret = -EIO;
-		if (register_netdev(devN)) {
+		ret = register_netdev(devN);
+		if (ret) {
 			free_netdev(devN);
 			goto fail;
 		}
 		privN->chan = i+1;
 		priv->devtbl[i] = devN;
-		privN->next_dev = dgrs_root_dev;
-		dgrs_root_dev = devN;
 	}
-	return 0;
-fail:	aux = priv->next_dev;
-	while (dgrs_root_dev != aux) {
-		struct net_device *d = dgrs_root_dev;
-		
-		dgrs_root_dev = ((DGRS_PRIV *)d->priv)->next_dev;
+	return dev;
+
+ fail:	
+	while (i >= 0) {
+		struct net_device *d = priv->devtbl[i--];
 		unregister_netdev(d);
 		free_netdev(d);
 	}
-	return ret;
+
+ err2:
+	free_irq(dev->irq, dev);
+ err1:
+	free_netdev(dev);
+ err0:
+	return ERR_PTR(ret);
 }
 
-/*
- *	Scan for all boards
- */
-static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
+static void __devexit dgrs_remove(struct net_device *dev)
+{
+	DGRS_PRIV *priv = dev->priv;
+	int i;
+
+	unregister_netdev(dev);
+
+	for (i = 1; i < priv->nports; ++i) {
+		struct net_device *d = priv->devtbl[i];
+		if (d) {
+			unregister_netdev(d);
+			free_netdev(d);
+		}
+	}
+
+	proc_reset(priv->devtbl[0], 1);
 
-static int __init  dgrs_scan(void)
+	if (priv->vmem)
+		iounmap(priv->vmem);
+	if (priv->vplxdma)
+		iounmap((uchar *) priv->vplxdma);
+
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+
+	for (i = 1; i < priv->nports; ++i) {
+		if (priv->devtbl[i])
+			unregister_netdev(priv->devtbl[i]);
+	}
+}
+
+#ifdef CONFIG_PCI
+static int __init dgrs_pci_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
 {
-	int	cards_found = 0;
+	struct net_device *dev;
+	int err;
 	uint	io;
 	uint	mem;
 	uint	irq;
 	uint	plxreg;
 	uint	plxdma;
-	struct pci_dev *pdev = NULL;
 
 	/*
-	 *	First, check for PCI boards
-	 */
-	while ((pdev = pci_find_device(SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, pdev)) != NULL)
-	{
-		/*
-		 * Get and check the bus-master and latency values.
-		 * Some PCI BIOSes fail to set the master-enable bit,
-		 * and the latency timer must be set to the maximum
-		 * value to avoid data corruption that occurs when the
-		 * timer expires during a transfer.  Yes, it's a bug.
-		 */
-		if (pci_enable_device(pdev))
-			continue;
-		pci_set_master(pdev);
-
-		plxreg = pci_resource_start (pdev, 0);
-		io = pci_resource_start (pdev, 1);
-		mem = pci_resource_start (pdev, 2);
-		pci_read_config_dword(pdev, 0x30, &plxdma);
-		irq = pdev->irq;
-		plxdma &= ~15;
+	 * Get and check the bus-master and latency values.
+	 * Some PCI BIOSes fail to set the master-enable bit,
+	 * and the latency timer must be set to the maximum
+	 * value to avoid data corruption that occurs when the
+	 * timer expires during a transfer.  Yes, it's a bug.
+	 */
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+	err = pci_request_regions(pdev, "RightSwitch");
+	if (err)
+		return err;
+
+	pci_set_master(pdev);
+
+	plxreg = pci_resource_start (pdev, 0);
+	io = pci_resource_start (pdev, 1);
+	mem = pci_resource_start (pdev, 2);
+	pci_read_config_dword(pdev, 0x30, &plxdma);
+	irq = pdev->irq;
+	plxdma &= ~15;
+
+	/*
+	 * On some BIOSES, the PLX "expansion rom" (used for DMA)
+	 * address comes up as "0".  This is probably because
+	 * the BIOS doesn't see a valid 55 AA ROM signature at
+	 * the "ROM" start and zeroes the address.  To get
+	 * around this problem the SE-6 is configured to ask
+	 * for 4 MB of space for the dual port memory.  We then
+	 * must set its range back to 2 MB, and use the upper
+	 * half for DMA register access
+	 */
+	OUTL(io + PLX_SPACE0_RANGE, 0xFFE00000L);
+	if (plxdma == 0)
+		plxdma = mem + (2048L * 1024L);
+	pci_write_config_dword(pdev, 0x30, plxdma + 1);
+	pci_read_config_dword(pdev, 0x30, &plxdma);
+	plxdma &= ~15;
+
+	dev = dgrs_found_device(io, mem, irq, plxreg, plxdma, &pdev->dev);
+	if (IS_ERR(dev)) {
+		pci_release_regions(pdev);
+		return PTR_ERR(dev);
+	}
 
-		/*
-		 * On some BIOSES, the PLX "expansion rom" (used for DMA)
-		 * address comes up as "0".  This is probably because
-		 * the BIOS doesn't see a valid 55 AA ROM signature at
-		 * the "ROM" start and zeroes the address.  To get
-		 * around this problem the SE-6 is configured to ask
-		 * for 4 MB of space for the dual port memory.  We then
-		 * must set its range back to 2 MB, and use the upper
-		 * half for DMA register access
-		 */
-		OUTL(io + PLX_SPACE0_RANGE, 0xFFE00000L);
-		if (plxdma == 0)
-			plxdma = mem + (2048L * 1024L);
-		pci_write_config_dword(pdev, 0x30, plxdma + 1);
-		pci_read_config_dword(pdev, 0x30, &plxdma);
-		plxdma &= ~15;
+	pci_set_drvdata(pdev, dev);
+	return 0;
+}
 
-		dgrs_found_device(io, mem, irq, plxreg, plxdma);
+static void __devexit dgrs_pci_remove(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
 
-		cards_found++;
-	}
+	dgrs_remove(dev);
+	pci_release_regions(pdev);
+	free_netdev(dev);
+}
 
-	/*
-	 *	Second, check for EISA boards
-	 */
-	if (EISA_bus)
-	{
-		for (io = 0x1000; io < 0x9000; io += 0x1000)
-		{
-			if (inb(io+ES4H_MANUFmsb) != 0x10
-				|| inb(io+ES4H_MANUFlsb) != 0x49
-				|| inb(io+ES4H_PRODUCT) != ES4H_PRODUCT_CODE)
-				continue;
+static struct pci_driver dgrs_pci_driver = {
+	.name = "dgrs",
+	.id_table = dgrs_pci_tbl,
+	.probe = dgrs_pci_probe,
+	.remove = __devexit_p(dgrs_pci_remove),
+};
+#endif
+
+
+#ifdef CONFIG_EISA
+static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
 
-			if ( ! (inb(io+ES4H_EC) & ES4H_EC_ENABLE) )
-				continue; /* Not EISA configured */
+static int __init dgrs_eisa_probe (struct device *gendev)
+{
+	struct net_device *dev;
+	struct eisa_device *edev = to_eisa_device(gendev);
+	uint	io = edev->base_addr;
+	uint	mem;
+	uint	irq;
+	int 	rc = -ENODEV; /* Not EISA configured */
+
+	if (!request_region(io, 256, "RightSwitch")) {
+		printk(KERN_ERR "%s: io 0x%3lX, which is busy.\n", dev->name,
+				dev->base_addr);
+		return -EBUSY;
+	}
 
-			mem = (inb(io+ES4H_AS_31_24) << 24)
-				+ (inb(io+ES4H_AS_23_16) << 16);
+	if ( ! (inb(io+ES4H_EC) & ES4H_EC_ENABLE) ) 
+		goto err_out;
 
-			irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ];
+	mem = (inb(io+ES4H_AS_31_24) << 24)
+		+ (inb(io+ES4H_AS_23_16) << 16);
 
-			dgrs_found_device(io, mem, irq, 0L, 0L);
+	irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ];
 
-			++cards_found;
-		}
+	dev = dgrs_found_device(io, mem, irq, 0L, 0L, gendev);
+	if (IS_ERR(dev)) {
+		rc = PTR_ERR(dev);
+		goto err_out;
 	}
 
-	return cards_found;
+	gendev->driver_data = dev;
+	return 0;
+ err_out:
+	release_region(io, 256);
+	return rc;
+}
+
+static int __devexit dgrs_eisa_remove(struct device *gendev)
+{
+	struct net_device *dev = gendev->driver_data;
+	
+	dgrs_remove(dev);
+
+	release_region(dev->base_addr, 256);
+		
+	free_netdev(dev);
+	return 0;
 }
 
 
+static struct eisa_driver dgrs_eisa_driver = {
+	.id_table = dgrs_eisa_tbl,
+	.driver = {
+		.name = "dgrs",
+		.probe = dgrs_eisa_probe,
+		.remove = __devexit_p(dgrs_eisa_remove),
+	}
+};
+#endif
+
 /*
  *	Variables that can be overriden from module command line
  */
@@ -1459,8 +1543,8 @@
 
 static int __init dgrs_init_module (void)
 {
-	int	cards_found;
 	int	i;
+	int eisacount = 0, pcicount = 0;
 
 	/*
 	 *	Command line variable overrides
@@ -1501,38 +1585,27 @@
 	/*
 	 *	Find and configure all the cards
 	 */
-	dgrs_root_dev = NULL;
-	cards_found = dgrs_scan();
-
-	return cards_found ? 0 : -ENODEV;
+#ifdef CONFIG_EISA
+	eisacount = eisa_driver_register(&dgrs_eisa_driver);
+	if (eisacount < 0)
+		return eisacount;
+#endif
+#ifdef CONFIG_PCI
+	pcicount = pci_register_driver(&dgrs_pci_driver);
+	if (pcicount < 0)
+		return pcicount;
+#endif
+	return (eisacount + pcicount) == 0 ? -ENODEV : 0;
 }
 
 static void __exit dgrs_cleanup_module (void)
 {
-        while (dgrs_root_dev)
-	{
-		struct net_device	*next_dev;
-		DGRS_PRIV	*priv;
-
-		priv = (DGRS_PRIV *) dgrs_root_dev->priv;
-                next_dev = priv->next_dev;
-                unregister_netdev(dgrs_root_dev);
-
-		proc_reset(priv->devtbl[0], 1);
-
-		if (priv->vmem)
-			iounmap(priv->vmem);
-		if (priv->vplxdma)
-			iounmap((uchar *) priv->vplxdma);
-
-		release_region(dgrs_root_dev->base_addr, 256);
-
-		if (dgrs_root_dev->irq)
-			free_irq(dgrs_root_dev->irq, dgrs_root_dev);
-
-                free_netdev(dgrs_root_dev);
-                dgrs_root_dev = next_dev;
-        }
+#ifdef CONFIG_EISA
+	eisa_driver_unregister (&dgrs_eisa_driver);
+#endif
+#ifdef CONFIG_PCI
+	pci_unregister_driver (&dgrs_pci_driver);
+#endif
 }
 
 module_init(dgrs_init_module);
diff -Nru a/drivers/net/e100/LICENSE b/drivers/net/e100/LICENSE
--- a/drivers/net/e100/LICENSE	Wed Feb 11 22:30:57 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,339 +0,0 @@
-
-"This software program is licensed subject to the GNU General Public License 
-(GPL). Version 2, June 1991, available at 
-<http://www.fsf.org/copyleft/gpl.html>"
-
-GNU General Public License 
-
-Version 2, June 1991
-
-Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
-59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
-
-Everyone is permitted to copy and distribute verbatim copies of this license
-document, but changing it is not allowed.
-
-Preamble
-
-The licenses for most software are designed to take away your freedom to 
-share and change it. By contrast, the GNU General Public License is intended
-to guarantee your freedom to share and change free software--to make sure 
-the software is free for all its users. This General Public License applies 
-to most of the Free Software Foundation's software and to any other program 
-whose authors commit to using it. (Some other Free Software Foundation 
-software is covered by the GNU Library General Public License instead.) You 
-can apply it to your programs, too.
-
-When we speak of free software, we are referring to freedom, not price. Our
-General Public Licenses are designed to make sure that you have the freedom 
-to distribute copies of free software (and charge for this service if you 
-wish), that you receive source code or can get it if you want it, that you 
-can change the software or use pieces of it in new free programs; and that 
-you know you can do these things.
-
-To protect your rights, we need to make restrictions that forbid anyone to 
-deny you these rights or to ask you to surrender the rights. These 
-restrictions translate to certain responsibilities for you if you distribute
-copies of the software, or if you modify it.
-
-For example, if you distribute copies of such a program, whether gratis or 
-for a fee, you must give the recipients all the rights that you have. You 
-must make sure that they, too, receive or can get the source code. And you 
-must show them these terms so they know their rights.
- 
-We protect your rights with two steps: (1) copyright the software, and (2) 
-offer you this license which gives you legal permission to copy, distribute 
-and/or modify the software. 
-
-Also, for each author's protection and ours, we want to make certain that 
-everyone understands that there is no warranty for this free software. If 
-the software is modified by someone else and passed on, we want its 
-recipients to know that what they have is not the original, so that any 
-problems introduced by others will not reflect on the original authors' 
-reputations. 
-
-Finally, any free program is threatened constantly by software patents. We 
-wish to avoid the danger that redistributors of a free program will 
-individually obtain patent licenses, in effect making the program 
-proprietary. To prevent this, we have made it clear that any patent must be 
-licensed for everyone's free use or not licensed at all. 
-
-The precise terms and conditions for copying, distribution and modification 
-follow. 
-
-TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-0. This License applies to any program or other work which contains a notice
-   placed by the copyright holder saying it may be distributed under the 
-   terms of this General Public License. The "Program", below, refers to any
-   such program or work, and a "work based on the Program" means either the 
-   Program or any derivative work under copyright law: that is to say, a 
-   work containing the Program or a portion of it, either verbatim or with 
-   modifications and/or translated into another language. (Hereinafter, 
-   translation is included without limitation in the term "modification".) 
-   Each licensee is addressed as "you". 
-
-   Activities other than copying, distribution and modification are not 
-   covered by this License; they are outside its scope. The act of running 
-   the Program is not restricted, and the output from the Program is covered 
-   only if its contents constitute a work based on the Program (independent 
-   of having been made by running the Program). Whether that is true depends
-   on what the Program does. 
-
-1. You may copy and distribute verbatim copies of the Program's source code 
-   as you receive it, in any medium, provided that you conspicuously and 
-   appropriately publish on each copy an appropriate copyright notice and 
-   disclaimer of warranty; keep intact all the notices that refer to this 
-   License and to the absence of any warranty; and give any other recipients 
-   of the Program a copy of this License along with the Program. 
-
-   You may charge a fee for the physical act of transferring a copy, and you 
-   may at your option offer warranty protection in exchange for a fee. 
-
-2. You may modify your copy or copies of the Program or any portion of it, 
-   thus forming a work based on the Program, and copy and distribute such 
-   modifications or work under the terms of Section 1 above, provided that 
-   you also meet all of these conditions: 
-
-   * a) You must cause the modified files to carry prominent notices stating 
-        that you changed the files and the date of any change. 
-
-   * b) You must cause any work that you distribute or publish, that in 
-        whole or in part contains or is derived from the Program or any part 
-        thereof, to be licensed as a whole at no charge to all third parties
-        under the terms of this License. 
-
-   * c) If the modified program normally reads commands interactively when 
-        run, you must cause it, when started running for such interactive 
-        use in the most ordinary way, to print or display an announcement 
-        including an appropriate copyright notice and a notice that there is
-        no warranty (or else, saying that you provide a warranty) and that 
-        users may redistribute the program under these conditions, and 
-        telling the user how to view a copy of this License. (Exception: if 
-        the Program itself is interactive but does not normally print such 
-        an announcement, your work based on the Program is not required to 
-        print an announcement.) 
-
-   These requirements apply to the modified work as a whole. If identifiable 
-   sections of that work are not derived from the Program, and can be 
-   reasonably considered independent and separate works in themselves, then 
-   this License, and its terms, do not apply to those sections when you 
-   distribute them as separate works. But when you distribute the same 
-   sections as part of a whole which is a work based on the Program, the 
-   distribution of the whole must be on the terms of this License, whose 
-   permissions for other licensees extend to the entire whole, and thus to 
-   each and every part regardless of who wrote it. 
-
-   Thus, it is not the intent of this section to claim rights or contest 
-   your rights to work written entirely by you; rather, the intent is to 
-   exercise the right to control the distribution of derivative or 
-   collective works based on the Program. 
-
-   In addition, mere aggregation of another work not based on the Program 
-   with the Program (or with a work based on the Program) on a volume of a 
-   storage or distribution medium does not bring the other work under the 
-   scope of this License. 
-
-3. You may copy and distribute the Program (or a work based on it, under 
-   Section 2) in object code or executable form under the terms of Sections 
-   1 and 2 above provided that you also do one of the following: 
-
-   * a) Accompany it with the complete corresponding machine-readable source 
-        code, which must be distributed under the terms of Sections 1 and 2 
-        above on a medium customarily used for software interchange; or, 
-
-   * b) Accompany it with a written offer, valid for at least three years, 
-        to give any third party, for a charge no more than your cost of 
-        physically performing source distribution, a complete machine-
-        readable copy of the corresponding source code, to be distributed 
-        under the terms of Sections 1 and 2 above on a medium customarily 
-        used for software interchange; or, 
-
-   * c) Accompany it with the information you received as to the offer to 
-        distribute corresponding source code. (This alternative is allowed 
-        only for noncommercial distribution and only if you received the 
-        program in object code or executable form with such an offer, in 
-        accord with Subsection b above.) 
-
-   The source code for a work means the preferred form of the work for 
-   making modifications to it. For an executable work, complete source code 
-   means all the source code for all modules it contains, plus any 
-   associated interface definition files, plus the scripts used to control 
-   compilation and installation of the executable. However, as a special 
-   exception, the source code distributed need not include anything that is 
-   normally distributed (in either source or binary form) with the major 
-   components (compiler, kernel, and so on) of the operating system on which
-   the executable runs, unless that component itself accompanies the 
-   executable. 
-
-   If distribution of executable or object code is made by offering access 
-   to copy from a designated place, then offering equivalent access to copy 
-   the source code from the same place counts as distribution of the source 
-   code, even though third parties are not compelled to copy the source 
-   along with the object code. 
-
-4. You may not copy, modify, sublicense, or distribute the Program except as
-   expressly provided under this License. Any attempt otherwise to copy, 
-   modify, sublicense or distribute the Program is void, and will 
-   automatically terminate your rights under this License. However, parties 
-   who have received copies, or rights, from you under this License will not
-   have their licenses terminated so long as such parties remain in full 
-   compliance. 
-
-5. You are not required to accept this License, since you have not signed 
-   it. However, nothing else grants you permission to modify or distribute 
-   the Program or its derivative works. These actions are prohibited by law 
-   if you do not accept this License. Therefore, by modifying or 
-   distributing the Program (or any work based on the Program), you 
-   indicate your acceptance of this License to do so, and all its terms and
-   conditions for copying, distributing or modifying the Program or works 
-   based on it. 
-
-6. Each time you redistribute the Program (or any work based on the 
-   Program), the recipient automatically receives a license from the 
-   original licensor to copy, distribute or modify the Program subject to 
-   these terms and conditions. You may not impose any further restrictions 
-   on the recipients' exercise of the rights granted herein. You are not 
-   responsible for enforcing compliance by third parties to this License. 
-
-7. If, as a consequence of a court judgment or allegation of patent 
-   infringement or for any other reason (not limited to patent issues), 
-   conditions are imposed on you (whether by court order, agreement or 
-   otherwise) that contradict the conditions of this License, they do not 
-   excuse you from the conditions of this License. If you cannot distribute 
-   so as to satisfy simultaneously your obligations under this License and 
-   any other pertinent obligations, then as a consequence you may not 
-   distribute the Program at all. For example, if a patent license would 
-   not permit royalty-free redistribution of the Program by all those who 
-   receive copies directly or indirectly through you, then the only way you 
-   could satisfy both it and this License would be to refrain entirely from 
-   distribution of the Program. 
-
-   If any portion of this section is held invalid or unenforceable under any
-   particular circumstance, the balance of the section is intended to apply
-   and the section as a whole is intended to apply in other circumstances. 
-
-   It is not the purpose of this section to induce you to infringe any 
-   patents or other property right claims or to contest validity of any 
-   such claims; this section has the sole purpose of protecting the 
-   integrity of the free software distribution system, which is implemented 
-   by public license practices. Many people have made generous contributions
-   to the wide range of software distributed through that system in 
-   reliance on consistent application of that system; it is up to the 
-   author/donor to decide if he or she is willing to distribute software 
-   through any other system and a licensee cannot impose that choice. 
-
-   This section is intended to make thoroughly clear what is believed to be 
-   a consequence of the rest of this License. 
-
-8. If the distribution and/or use of the Program is restricted in certain 
-   countries either by patents or by copyrighted interfaces, the original 
-   copyright holder who places the Program under this License may add an 
-   explicit geographical distribution limitation excluding those countries, 
-   so that distribution is permitted only in or among countries not thus 
-   excluded. In such case, this License incorporates the limitation as if 
-   written in the body of this License. 
-
-9. The Free Software Foundation may publish revised and/or new versions of 
-   the General Public License from time to time. Such new versions will be 
-   similar in spirit to the present version, but may differ in detail to 
-   address new problems or concerns. 
-
-   Each version is given a distinguishing version number. If the Program 
-   specifies a version number of this License which applies to it and "any 
-   later version", you have the option of following the terms and 
-   conditions either of that version or of any later version published by 
-   the Free Software Foundation. If the Program does not specify a version 
-   number of this License, you may choose any version ever published by the 
-   Free Software Foundation. 
-
-10. If you wish to incorporate parts of the Program into other free programs
-    whose distribution conditions are different, write to the author to ask 
-    for permission. For software which is copyrighted by the Free Software 
-    Foundation, write to the Free Software Foundation; we sometimes make 
-    exceptions for this. Our decision will be guided by the two goals of 
-    preserving the free status of all derivatives of our free software and 
-    of promoting the sharing and reuse of software generally. 
-
-   NO WARRANTY
-
-11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 
-    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 
-    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 
-    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 
-    EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
-    ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH 
-    YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
-    NECESSARY SERVICING, REPAIR OR CORRECTION. 
-
-12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
-    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
-    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
-    DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
-    DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM 
-    (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 
-    INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF 
-    THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR 
-    OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
-
-END OF TERMS AND CONDITIONS
-
-How to Apply These Terms to Your New Programs
-
-If you develop a new program, and you want it to be of the greatest 
-possible use to the public, the best way to achieve this is to make it free 
-software which everyone can redistribute and change under these terms. 
-
-To do so, attach the following notices to the program. It is safest to 
-attach them to the start of each source file to most effectively convey the
-exclusion of warranty; and each file should have at least the "copyright" 
-line and a pointer to where the full notice is found. 
-
-one line to give the program's name and an idea of what it does.
-Copyright (C) yyyy  name of author
-
-This program is free software; you can redistribute it and/or modify it 
-under the terms of the GNU General Public License as published by the Free 
-Software Foundation; either version 2 of the License, or (at your option) 
-any later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT 
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 
-Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-Also add information on how to contact you by electronic and paper mail. 
-
-If the program is interactive, make it output a short notice like this when 
-it starts in an interactive mode: 
-
-Gnomovision version 69, Copyright (C) year name of author Gnomovision comes 
-with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free 
-software, and you are welcome to redistribute it under certain conditions; 
-type 'show c' for details.
-
-The hypothetical commands 'show w' and 'show c' should show the appropriate 
-parts of the General Public License. Of course, the commands you use may be 
-called something other than 'show w' and 'show c'; they could even be 
-mouse-clicks or menu items--whatever suits your program. 
-
-You should also get your employer (if you work as a programmer) or your 
-school, if any, to sign a "copyright disclaimer" for the program, if 
-necessary. Here is a sample; alter the names: 
-
-Yoyodyne, Inc., hereby disclaims all copyright interest in the program 
-'Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-signature of Ty Coon, 1 April 1989
-Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into 
-proprietary programs. If your program is a subroutine library, you may 
-consider it more useful to permit linking proprietary applications with the 
-library. If this is what you want to do, use the GNU Library General Public 
-License instead of this License.
diff -Nru a/drivers/net/e100/Makefile b/drivers/net/e100/Makefile
--- a/drivers/net/e100/Makefile	Wed Feb 11 22:30:57 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,8 +0,0 @@
-#
-# Makefile for the Intel's E100 ethernet driver
-#
-
-obj-$(CONFIG_E100) += e100.o
-
-e100-objs := e100_main.o e100_config.o e100_phy.o \
-	     e100_eeprom.o e100_test.o
diff -Nru a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h
--- a/drivers/net/e100/e100.h	Wed Feb 11 22:30:57 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,999 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#ifndef _E100_INC_
-#define _E100_INC_
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <linux/reboot.h>
-#include <asm/io.h>
-#include <asm/unaligned.h>
-#include <asm/processor.h>
-#include <linux/ethtool.h>
-#include <linux/inetdevice.h>
-#include <linux/bitops.h>
-
-#include <linux/if.h>
-#include <asm/uaccess.h>
-#include <linux/ip.h>
-#include <linux/if_vlan.h>
-#include <linux/mii.h>
-
-#define E100_CABLE_UNKNOWN	0
-#define E100_CABLE_OK		1		
-#define E100_CABLE_OPEN_NEAR	2	/* Open Circuit Near End  */
-#define E100_CABLE_OPEN_FAR	3	/* Open Circuit Far End   */
-#define E100_CABLE_SHORT_NEAR	4	/* Short Circuit Near End */
-#define E100_CABLE_SHORT_FAR	5	/* Short Circuit Far End  */
-
-#define E100_REGS_LEN 2
-/*
- *  Configure parameters for buffers per controller.
- *  If the machine this is being used on is a faster machine (i.e. > 150MHz)
- *  and running on a 10MBS network then more queueing of data occurs. This
- *  may indicate the some of the numbers below should be adjusted.  Here are
- *  some typical numbers:
- *                             MAX_TCB 64
- *                             MAX_RFD 64
- *  The default numbers give work well on most systems tests so no real
- *  adjustments really need to take place.  Also, if the machine is connected
- *  to a 100MBS network the numbers described above can be lowered from the
- *  defaults as considerably less data will be queued.
- */
-
-#define TX_FRAME_CNT   8	/* consecutive transmit frames per interrupt */
-/* TX_FRAME_CNT must be less than MAX_TCB    */
-
-#define E100_DEFAULT_TCB   64
-#define E100_MIN_TCB       2*TX_FRAME_CNT + 3	/* make room for at least 2 interrupts */
-#define E100_MAX_TCB       1024
-
-#define E100_DEFAULT_RFD   64
-#define E100_MIN_RFD       8
-#define E100_MAX_RFD       1024
-
-#define E100_DEFAULT_XSUM         true
-#define E100_DEFAULT_BER          ZLOCK_MAX_ERRORS
-#define E100_DEFAULT_SPEED_DUPLEX 0
-#define E100_DEFAULT_FC           0
-#define E100_DEFAULT_IFS          true
-#define E100_DEFAULT_UCODE        true
-
-#define TX_THRSHLD     8
-
-/* IFS parameters */
-#define MIN_NUMBER_OF_TRANSMITS_100 1000
-#define MIN_NUMBER_OF_TRANSMITS_10  100
-
-#define E100_MAX_NIC 16
-
-#define E100_MAX_SCB_WAIT	100	/* Max udelays in wait_scb */
-#define E100_MAX_CU_IDLE_WAIT	50	/* Max udelays in wait_cus_idle */
-
-/* HWI feature related constant */
-#define HWI_REGISTER_GRANULARITY        80	/* register granularity = 80 Cm */
-#define HWI_NEAR_END_BOUNDARY           1000	/* Near end is defined as < 10 meters */
-
-/* CPUSAVER_BUNDLE_MAX: Sets the maximum number of frames that will be bundled.
- * In some situations, such as the TCP windowing algorithm, it may be
- * better to limit the growth of the bundle size than let it go as
- * high as it can, because that could cause too much added latency.
- * The default is six, because this is the number of packets in the
- * default TCP window size.  A value of 1 would make CPUSaver indicate
- * an interrupt for every frame received.  If you do not want to put
- * a limit on the bundle size, set this value to xFFFF.
- */
-#define E100_DEFAULT_CPUSAVER_BUNDLE_MAX	6
-#define E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY	0x600
-#define E100_DEFAULT_BUNDLE_SMALL_FR		false
-
-/* end of configurables */
-
-/* ====================================================================== */
-/*                                hw                                      */
-/* ====================================================================== */
-
-/* timeout for command completion */
-#define E100_CMD_WAIT   100	/* iterations */
-
-struct driver_stats {
-	struct net_device_stats net_stats;
-
-	unsigned long tx_late_col;
-	unsigned long tx_ok_defrd;
-	unsigned long tx_one_retry;
-	unsigned long tx_mt_one_retry;
-	unsigned long rcv_cdt_frames;
-	unsigned long xmt_fc_pkts;
-	unsigned long rcv_fc_pkts;
-	unsigned long rcv_fc_unsupported;
-	unsigned long xmt_tco_pkts;
-	unsigned long rcv_tco_pkts;
-	unsigned long rx_intr_pkts;
-};
-
-/* TODO: kill me when we can do C99 */
-#define false		(0)
-#define true		(1)
-
-/* Changed for 82558 and 82559 enhancements */
-/* defines for 82558/9 flow control CSR values */
-#define DFLT_FC_THLD       0x00	/* Rx FIFO threshold of 0.5KB free  */
-#define DFLT_FC_CMD        0x00	/* FC Command in CSR */
-
-/* ====================================================================== */
-/*                              equates                                   */
-/* ====================================================================== */
-
-/*
- * These are general purpose defines 
- */
-
-/* Bit Mask definitions */
-#define BIT_0       0x0001
-#define BIT_1       0x0002
-#define BIT_2       0x0004
-#define BIT_3       0x0008
-#define BIT_4       0x0010
-#define BIT_5       0x0020
-#define BIT_6       0x0040
-#define BIT_7       0x0080
-#define BIT_8       0x0100
-#define BIT_9       0x0200
-#define BIT_10      0x0400
-#define BIT_11      0x0800
-#define BIT_12      0x1000
-#define BIT_13      0x2000
-#define BIT_14      0x4000
-#define BIT_15      0x8000
-#define BIT_28      0x10000000
-
-#define BIT_0_2     0x0007
-#define BIT_0_3     0x000F
-#define BIT_0_4     0x001F
-#define BIT_0_5     0x003F
-#define BIT_0_6     0x007F
-#define BIT_0_7     0x00FF
-#define BIT_0_8     0x01FF
-#define BIT_0_13    0x3FFF
-#define BIT_0_15    0xFFFF
-#define BIT_1_2     0x0006
-#define BIT_1_3     0x000E
-#define BIT_2_5     0x003C
-#define BIT_3_4     0x0018
-#define BIT_4_5     0x0030
-#define BIT_4_6     0x0070
-#define BIT_4_7     0x00F0
-#define BIT_5_7     0x00E0
-#define BIT_5_12    0x1FE0
-#define BIT_5_15    0xFFE0
-#define BIT_6_7     0x00c0
-#define BIT_7_11    0x0F80
-#define BIT_8_10    0x0700
-#define BIT_9_13    0x3E00
-#define BIT_12_15   0xF000
-#define BIT_8_15    0xFF00
-
-#define BIT_16_20   0x001F0000
-#define BIT_21_25   0x03E00000
-#define BIT_26_27   0x0C000000
-
-/* Transmit Threshold related constants */
-#define DEFAULT_TX_PER_UNDERRUN         20000
-
-#define MAX_MULTICAST_ADDRS             64
-#define MAX_FILTER                      16
-
-#define FULL_DUPLEX      2
-#define HALF_DUPLEX      1
-
-/*
- * These defines are specific to the 82557 
- */
-
-/* E100 PORT functions -- lower 4 bits */
-#define PORT_SOFTWARE_RESET         0
-#define PORT_SELFTEST               1
-#define PORT_SELECTIVE_RESET        2
-#define PORT_DUMP                   3
-
-/* SCB Status Word bit definitions */
-/* Interrupt status/ack fields */
-/* ER and FCP interrupts for 82558 masks  */
-#define SCB_STATUS_ACK_MASK        BIT_8_15	/* Status Mask */
-#define SCB_STATUS_ACK_CX          BIT_15	/* CU Completed Action Cmd */
-#define SCB_STATUS_ACK_FR          BIT_14	/* RU Received A Frame */
-#define SCB_STATUS_ACK_CNA         BIT_13	/* CU Became Inactive (IDLE) */
-#define SCB_STATUS_ACK_RNR         BIT_12	/* RU Became Not Ready */
-#define SCB_STATUS_ACK_MDI         BIT_11	/* MDI read or write done */
-#define SCB_STATUS_ACK_SWI         BIT_10	/* S/W generated interrupt */
-#define SCB_STATUS_ACK_ER          BIT_9	/* Early Receive */
-#define SCB_STATUS_ACK_FCP         BIT_8	/* Flow Control Pause */
-
-/*- CUS Fields */
-#define SCB_CUS_MASK            (BIT_6 | BIT_7)	/* CUS 2-bit Mask */
-#define SCB_CUS_IDLE            0	/* CU Idle */
-#define SCB_CUS_SUSPEND         BIT_6	/* CU Suspended */
-#define SCB_CUS_ACTIVE          BIT_7	/* CU Active */
-
-/*- RUS Fields */
-#define SCB_RUS_IDLE            0	/* RU Idle */
-#define SCB_RUS_MASK            BIT_2_5	/* RUS 3-bit Mask */
-#define SCB_RUS_SUSPEND         BIT_2	/* RU Suspended */
-#define SCB_RUS_NO_RESOURCES    BIT_3	/* RU Out Of Resources */
-#define SCB_RUS_READY           BIT_4	/* RU Ready */
-#define SCB_RUS_SUSP_NO_RBDS    (BIT_2 | BIT_5)	/* RU No More RBDs */
-#define SCB_RUS_NO_RBDS         (BIT_3 | BIT_5)	/* RU No More RBDs */
-#define SCB_RUS_READY_NO_RBDS   (BIT_4 | BIT_5)	/* RU Ready, No RBDs */
-
-/* SCB Command Word bit definitions */
-/*- CUC fields */
-/* Changing mask to 4 bits */
-#define SCB_CUC_MASK            BIT_4_7	/* CUC 4-bit Mask */
-#define SCB_CUC_NOOP            0
-#define SCB_CUC_START           BIT_4	/* CU Start */
-#define SCB_CUC_RESUME          BIT_5	/* CU Resume */
-#define SCB_CUC_UNKNOWN         BIT_7	/* CU unknown command */
-/* Changed for 82558 enhancements */
-#define SCB_CUC_STATIC_RESUME   (BIT_5 | BIT_7)	/* 82558/9 Static Resume */
-#define SCB_CUC_DUMP_ADDR       BIT_6	/* CU Dump Counters Address */
-#define SCB_CUC_DUMP_STAT       (BIT_4 | BIT_6)	/* CU Dump stat. counters */
-#define SCB_CUC_LOAD_BASE       (BIT_5 | BIT_6)	/* Load the CU base */
-/* Below was defined as BIT_4_7 */
-#define SCB_CUC_DUMP_RST_STAT   BIT_4_6	/* CU Dump & reset statistics cntrs */
-
-/*- RUC fields */
-#define SCB_RUC_MASK            BIT_0_2	/* RUC 3-bit Mask */
-#define SCB_RUC_START           BIT_0	/* RU Start */
-#define SCB_RUC_RESUME          BIT_1	/* RU Resume */
-#define SCB_RUC_ABORT           BIT_2	/* RU Abort */
-#define SCB_RUC_LOAD_HDS        (BIT_0 | BIT_2)	/* Load RFD Header Data Size */
-#define SCB_RUC_LOAD_BASE       (BIT_1 | BIT_2)	/* Load the RU base */
-#define SCB_RUC_RBD_RESUME      BIT_0_2	/* RBD resume */
-
-/* Interrupt fields (assuming byte addressing) */
-#define SCB_INT_MASK            BIT_0	/* Mask interrupts */
-#define SCB_SOFT_INT            BIT_1	/* Generate a S/W interrupt */
-/*  Specific Interrupt Mask Bits (upper byte of SCB Command word) */
-#define SCB_FCP_INT_MASK        BIT_2	/* Flow Control Pause */
-#define SCB_ER_INT_MASK         BIT_3	/* Early Receive */
-#define SCB_RNR_INT_MASK        BIT_4	/* RU Not Ready */
-#define SCB_CNA_INT_MASK        BIT_5	/* CU Not Active */
-#define SCB_FR_INT_MASK         BIT_6	/* Frame Received */
-#define SCB_CX_INT_MASK         BIT_7	/* CU eXecution w/ I-bit done */
-#define SCB_BACHELOR_INT_MASK   BIT_2_7	/* 82558 interrupt mask bits */
-
-#define SCB_GCR2_EEPROM_ACCESS_SEMAPHORE BIT_7
-
-/* EEPROM bit definitions */
-/*- EEPROM control register bits */
-#define EEPROM_FLAG_ASF  0x8000
-#define EEPROM_FLAG_GCL  0x4000
-
-#define EN_TRNF          0x10	/* Enable turnoff */
-#define EEDO             0x08	/* EEPROM data out */
-#define EEDI             0x04	/* EEPROM data in (set for writing data) */
-#define EECS             0x02	/* EEPROM chip select (1=hi, 0=lo) */
-#define EESK             0x01	/* EEPROM shift clock (1=hi, 0=lo) */
-
-/*- EEPROM opcodes */
-#define EEPROM_READ_OPCODE          06
-#define EEPROM_WRITE_OPCODE         05
-#define EEPROM_ERASE_OPCODE         07
-#define EEPROM_EWEN_OPCODE          19	/* Erase/write enable */
-#define EEPROM_EWDS_OPCODE          16	/* Erase/write disable */
-
-/*- EEPROM data locations */
-#define EEPROM_NODE_ADDRESS_BYTE_0      0
-#define EEPROM_COMPATIBILITY_WORD       3
-#define EEPROM_PWA_NO                   8
-#define EEPROM_ID_WORD			0x0A
-#define EEPROM_CONFIG_ASF		0x0D
-#define EEPROM_SMBUS_ADDR		0x90
-
-#define EEPROM_SUM                      0xbaba
-
-// Zero Locking Algorithm definitions:
-#define ZLOCK_ZERO_MASK		0x00F0
-#define ZLOCK_MAX_READS		50	
-#define ZLOCK_SET_ZERO		0x2010
-#define ZLOCK_MAX_SLEEP		300 * HZ	
-#define ZLOCK_MAX_ERRORS	300
-
-/* E100 Action Commands */
-#define CB_IA_ADDRESS           1
-#define CB_CONFIGURE            2
-#define CB_MULTICAST            3
-#define CB_TRANSMIT             4
-#define CB_LOAD_MICROCODE       5
-#define CB_LOAD_FILTER		8
-#define CB_MAX_NONTX_CMD        9
-#define CB_IPCB_TRANSMIT        9
-
-/* Pre-defined Filter Bits */
-#define CB_FILTER_EL            0x80000000
-#define CB_FILTER_FIX           0x40000000
-#define CB_FILTER_ARP           0x08000000
-#define CB_FILTER_IA_MATCH      0x02000000
-
-/* Command Block (CB) Field Definitions */
-/*- CB Command Word */
-#define CB_EL_BIT           BIT_15	/* CB EL Bit */
-#define CB_S_BIT            BIT_14	/* CB Suspend Bit */
-#define CB_I_BIT            BIT_13	/* CB Interrupt Bit */
-#define CB_TX_SF_BIT        BIT_3	/* TX CB Flexible Mode */
-#define CB_CMD_MASK         BIT_0_3	/* CB 4-bit CMD Mask */
-#define CB_CID_DEFAULT      (0x1f << 8)	/* CB 5-bit CID (max value) */
-
-/*- CB Status Word */
-#define CB_STATUS_MASK          BIT_12_15	/* CB Status Mask (4-bits) */
-#define CB_STATUS_COMPLETE      BIT_15	/* CB Complete Bit */
-#define CB_STATUS_OK            BIT_13	/* CB OK Bit */
-#define CB_STATUS_VLAN          BIT_12 /* CB Valn detected Bit */
-#define CB_STATUS_FAIL          BIT_11	/* CB Fail (F) Bit */
-
-/*misc command bits */
-#define CB_TX_EOF_BIT           BIT_15	/* TX CB/TBD EOF Bit */
-
-/* Config params */
-#define CB_CFIG_BYTE_COUNT          22	/* 22 config bytes */
-#define CB_CFIG_D102_BYTE_COUNT    10
-
-/* Receive Frame Descriptor Fields */
-
-/*- RFD Status Bits */
-#define RFD_RECEIVE_COLLISION   BIT_0	/* Collision detected on Receive */
-#define RFD_IA_MATCH            BIT_1	/* Indv Address Match Bit */
-#define RFD_RX_ERR              BIT_4	/* RX_ERR pin on Phy was set */
-#define RFD_FRAME_TOO_SHORT     BIT_7	/* Receive Frame Short */
-#define RFD_DMA_OVERRUN         BIT_8	/* Receive DMA Overrun */
-#define RFD_NO_RESOURCES        BIT_9	/* No Buffer Space */
-#define RFD_ALIGNMENT_ERROR     BIT_10	/* Alignment Error */
-#define RFD_CRC_ERROR           BIT_11	/* CRC Error */
-#define RFD_STATUS_OK           BIT_13	/* RFD OK Bit */
-#define RFD_STATUS_COMPLETE     BIT_15	/* RFD Complete Bit */
-
-/*- RFD Command Bits*/
-#define RFD_EL_BIT      BIT_15	/* RFD EL Bit */
-#define RFD_S_BIT       BIT_14	/* RFD Suspend Bit */
-#define RFD_H_BIT       BIT_4	/* Header RFD Bit */
-#define RFD_SF_BIT      BIT_3	/* RFD Flexible Mode */
-
-/*- RFD misc bits*/
-#define RFD_EOF_BIT         BIT_15	/* RFD End-Of-Frame Bit */
-#define RFD_F_BIT           BIT_14	/* RFD Buffer Fetch Bit */
-#define RFD_ACT_COUNT_MASK  BIT_0_13	/* RFD Actual Count Mask */
-
-/* Receive Buffer Descriptor Fields*/
-#define RBD_EOF_BIT             BIT_15	/* RBD End-Of-Frame Bit */
-#define RBD_F_BIT               BIT_14	/* RBD Buffer Fetch Bit */
-#define RBD_ACT_COUNT_MASK      BIT_0_13	/* RBD Actual Count Mask */
-
-#define SIZE_FIELD_MASK     BIT_0_13	/* Size of the associated buffer */
-#define RBD_EL_BIT          BIT_15	/* RBD EL Bit */
-
-/* Self Test Results*/
-#define CB_SELFTEST_FAIL_BIT        BIT_12
-#define CB_SELFTEST_DIAG_BIT        BIT_5
-#define CB_SELFTEST_REGISTER_BIT    BIT_3
-#define CB_SELFTEST_ROM_BIT         BIT_2
-
-#define CB_SELFTEST_ERROR_MASK ( \
-                CB_SELFTEST_FAIL_BIT | CB_SELFTEST_DIAG_BIT | \
-                CB_SELFTEST_REGISTER_BIT | CB_SELFTEST_ROM_BIT)
-
-/* adapter vendor & device ids */
-#define PCI_OHIO_BOARD   0x10f0	/* subdevice ID, Ohio dual port nic */
-
-/* Values for PCI_REV_ID_REGISTER values */
-#define D101A4_REV_ID      4	/* 82558 A4 stepping */
-#define D101B0_REV_ID      5	/* 82558 B0 stepping */
-#define D101MA_REV_ID      8	/* 82559 A0 stepping */
-#define D101S_REV_ID      9	/* 82559S A-step */
-#define D102_REV_ID      12
-#define D102C_REV_ID     13	/* 82550 step C */
-#define D102E_REV_ID     15
-
-/* ############Start of 82555 specific defines################## */
-
-#define PHY_82555_LED_SWITCH_CONTROL    	0x1b	/* 82555 led switch control register */
-
-/* 82555 led switch control reg. opcodes */
-#define PHY_82555_LED_NORMAL_CONTROL    0	// control back to the 8255X
-#define PHY_82555_LED_DRIVER_CONTROL    BIT_2	// the driver is in control
-#define PHY_82555_LED_OFF               BIT_2	// activity LED is off
-#define PHY_82555_LED_ON_559           (BIT_0 | BIT_2)	// activity LED is on for 559 and later
-#define PHY_82555_LED_ON_PRE_559       (BIT_0 | BIT_1 | BIT_2)	// activity LED is on for 558 and before
-
-// Describe the state of the phy led.
-// needed for the function : 'e100_blink_timer'
-enum led_state_e {
-	LED_OFF = 0,
-	LED_ON,
-};
-
-/* ############End of 82555 specific defines##################### */
-
-#define RFD_PARSE_BIT			BIT_3
-#define RFD_TCP_PACKET			0x00
-#define RFD_UDP_PACKET			0x01
-#define TCPUDP_CHECKSUM_BIT_VALID	BIT_4
-#define TCPUDP_CHECKSUM_VALID		BIT_5
-#define CHECKSUM_PROTOCOL_MASK		0x03
-
-#define VLAN_SIZE   4
-#define CHKSUM_SIZE 2
-#define RFD_DATA_SIZE (ETH_FRAME_LEN + CHKSUM_SIZE + VLAN_SIZE)
-
-/* Bits for bdp->flags */
-#define DF_LINK_FC_CAP     0x00000001	/* Link is flow control capable */
-#define DF_CSUM_OFFLOAD    0x00000002
-#define DF_UCODE_LOADED    0x00000004
-#define USE_IPCB           0x00000008	/* set if using ipcb for transmits */
-#define IS_BACHELOR        0x00000010	/* set if 82558 or newer board */
-#define IS_ICH             0x00000020
-#define DF_SPEED_FORCED    0x00000040	/* set if speed is forced */
-#define LED_IS_ON	   0x00000080	/* LED is turned ON by the driver */
-#define DF_LINK_FC_TX_ONLY 0x00000100	/* Received PAUSE frames are honored*/
-
-typedef struct net_device_stats net_dev_stats_t;
-
-/* needed macros */
-/* These macros use the bdp pointer. If you use them it better be defined */
-#define PREV_TCB_USED(X)  ((X).tail ? (X).tail - 1 : bdp->params.TxDescriptors - 1)
-#define NEXT_TCB_TOUSE(X) ((((X) + 1) >= bdp->params.TxDescriptors) ? 0 : (X) + 1)
-#define TCB_TO_USE(X)     ((X).tail)
-#define TCBS_AVAIL(X)     (NEXT_TCB_TOUSE( NEXT_TCB_TOUSE((X).tail)) != (X).head)
-
-#define RFD_POINTER(skb,bdp)      ((rfd_t *) (((unsigned char *)((skb)->data))-((bdp)->rfd_size)))
-#define SKB_RFD_STATUS(skb,bdp)   ((RFD_POINTER((skb),(bdp)))->rfd_header.cb_status)
-
-/* ====================================================================== */
-/*                              82557                                     */
-/* ====================================================================== */
-
-/* Changed for 82558 enhancement */
-typedef struct _d101_scb_ext_t {
-	u32 scb_rx_dma_cnt;	/* Rx DMA byte count */
-	u8 scb_early_rx_int;	/* Early Rx DMA byte count */
-	u8 scb_fc_thld;	/* Flow Control threshold */
-	u8 scb_fc_xon_xoff;	/* Flow Control XON/XOFF values */
-	u8 scb_pmdr;	/* Power Mgmt. Driver Reg */
-} d101_scb_ext __attribute__ ((__packed__));
-
-/* Changed for 82559 enhancement */
-typedef struct _d101m_scb_ext_t {
-	u32 scb_rx_dma_cnt;	/* Rx DMA byte count */
-	u8 scb_early_rx_int;	/* Early Rx DMA byte count */
-	u8 scb_fc_thld;	/* Flow Control threshold */
-	u8 scb_fc_xon_xoff;	/* Flow Control XON/XOFF values */
-	u8 scb_pmdr;	/* Power Mgmt. Driver Reg */
-	u8 scb_gen_ctrl;	/* General Control */
-	u8 scb_gen_stat;	/* General Status */
-	u16 scb_reserved;	/* Reserved */
-	u32 scb_function_event;	/* Cardbus Function Event */
-	u32 scb_function_event_mask;	/* Cardbus Function Mask */
-	u32 scb_function_present_state;	/* Cardbus Function state */
-	u32 scb_force_event;	/* Cardbus Force Event */
-} d101m_scb_ext __attribute__ ((__packed__));
-
-/* Changed for 82550 enhancement */
-typedef struct _d102_scb_ext_t {
-	u32 scb_rx_dma_cnt;	/* Rx DMA byte count */
-	u8 scb_early_rx_int;	/* Early Rx DMA byte count */
-	u8 scb_fc_thld;	/* Flow Control threshold */
-	u8 scb_fc_xon_xoff;	/* Flow Control XON/XOFF values */
-	u8 scb_pmdr;	/* Power Mgmt. Driver Reg */
-	u8 scb_gen_ctrl;	/* General Control */
-	u8 scb_gen_stat;	/* General Status */
-	u8 scb_gen_ctrl2;
-	u8 scb_reserved;	/* Reserved */
-	u32 scb_scheduling_reg;
-	u32 scb_reserved2;
-	u32 scb_function_event;	/* Cardbus Function Event */
-	u32 scb_function_event_mask;	/* Cardbus Function Mask */
-	u32 scb_function_present_state;	/* Cardbus Function state */
-	u32 scb_force_event;	/* Cardbus Force Event */
-} d102_scb_ext __attribute__ ((__packed__));
-
-/*
- * 82557 status control block. this will be memory mapped & will hang of the
- * the bdp, which hangs of the bdp. This is the brain of it.
- */
-typedef struct _scb_t {
-	u16 scb_status;	/* SCB Status register */
-	u8 scb_cmd_low;	/* SCB Command register (low byte) */
-	u8 scb_cmd_hi;	/* SCB Command register (high byte) */
-	u32 scb_gen_ptr;	/* SCB General pointer */
-	u32 scb_port;	/* PORT register */
-	u16 scb_flsh_cntrl;	/* Flash Control register */
-	u16 scb_eprm_cntrl;	/* EEPROM control register */
-	u32 scb_mdi_cntrl;	/* MDI Control Register */
-	/* Changed for 82558 enhancement */
-	union {
-		u32 scb_rx_dma_cnt;	/* Rx DMA byte count */
-		d101_scb_ext d101_scb;	/* 82558/9 specific fields */
-		d101m_scb_ext d101m_scb;	/* 82559 specific fields */
-		d102_scb_ext d102_scb;
-	} scb_ext;
-} scb_t __attribute__ ((__packed__));
-
-/* Self test
- * This is used to dump results of the self test 
- */
-typedef struct _self_test_t {
-	u32 st_sign;	/* Self Test Signature */
-	u32 st_result;	/* Self Test Results */
-} self_test_t __attribute__ ((__packed__));
-
-/* 
- *  Statistical Counters 
- */
-/* 82557 counters */
-typedef struct _basic_cntr_t {
-	u32 xmt_gd_frames;	/* Good frames transmitted */
-	u32 xmt_max_coll;	/* Fatal frames -- had max collisions */
-	u32 xmt_late_coll;	/* Fatal frames -- had a late coll. */
-	u32 xmt_uruns;	/* Xmit underruns (fatal or re-transmit) */
-	u32 xmt_lost_crs;	/* Frames transmitted without CRS */
-	u32 xmt_deferred;	/* Deferred transmits */
-	u32 xmt_sngl_coll;	/* Transmits that had 1 and only 1 coll. */
-	u32 xmt_mlt_coll;	/* Transmits that had multiple coll. */
-	u32 xmt_ttl_coll;	/* Transmits that had 1+ collisions. */
-	u32 rcv_gd_frames;	/* Good frames received */
-	u32 rcv_crc_errs;	/* Aligned frames that had a CRC error */
-	u32 rcv_algn_errs;	/* Receives that had alignment errors */
-	u32 rcv_rsrc_err;	/* Good frame dropped cuz no resources */
-	u32 rcv_oruns;	/* Overrun errors - bus was busy */
-	u32 rcv_err_coll;	/* Received frms. that encountered coll. */
-	u32 rcv_shrt_frames;	/* Received frames that were to short */
-} basic_cntr_t;
-
-/* 82558 extended statistic counters */
-typedef struct _ext_cntr_t {
-	u32 xmt_fc_frames;
-	u32 rcv_fc_frames;
-	u32 rcv_fc_unsupported;
-} ext_cntr_t;
-
-/* 82559 TCO statistic counters */
-typedef struct _tco_cntr_t {
-	u16 xmt_tco_frames;
-	u16 rcv_tco_frames;
-} tco_cntr_t;
-
-/* Structures to access thet physical dump area */
-/* Use one of these types, according to the statisitcal counters mode,
-   to cast the pointer to the physical dump area and access the cmd_complete
-   DWORD. */
-
-/* 557-mode : only basic counters + cmd_complete */
-typedef struct _err_cntr_557_t {
-	basic_cntr_t basic_stats;
-	u32 cmd_complete;
-} err_cntr_557_t;
-
-/* 558-mode : basic + extended counters + cmd_complete */
-typedef struct _err_cntr_558_t {
-	basic_cntr_t basic_stats;
-	ext_cntr_t extended_stats;
-	u32 cmd_complete;
-} err_cntr_558_t;
-
-/* 559-mode : basic + extended + TCO counters + cmd_complete */
-typedef struct _err_cntr_559_t {
-	basic_cntr_t basic_stats;
-	ext_cntr_t extended_stats;
-	tco_cntr_t tco_stats;
-	u32 cmd_complete;
-} err_cntr_559_t;
-
-/* This typedef defines the struct needed to hold the largest number of counters */
-typedef err_cntr_559_t max_counters_t;
-
-/* Different statistical-counters mode the controller may be in */
-typedef enum _stat_mode_t {
-	E100_BASIC_STATS = 0,	/* 82557 stats : 16 counters / 16 dw */
-	E100_EXTENDED_STATS,	/* 82558 stats : 19 counters / 19 dw */
-	E100_TCO_STATS		/* 82559 stats : 21 counters / 20 dw */
-} stat_mode_t;
-
-/* dump statistical counters complete codes */
-#define DUMP_STAT_COMPLETED	0xA005
-#define DUMP_RST_STAT_COMPLETED	0xA007
-
-/* Command Block (CB) Generic Header Structure*/
-typedef struct _cb_header_t {
-	u16 cb_status;	/* Command Block Status */
-	u16 cb_cmd;	/* Command Block Command */
-	u32 cb_lnk_ptr;	/* Link To Next CB */
-} cb_header_t __attribute__ ((__packed__));
-
-//* Individual Address Command Block (IA_CB)*/
-typedef struct _ia_cb_t {
-	cb_header_t ia_cb_hdr;
-	u8 ia_addr[ETH_ALEN];
-} ia_cb_t __attribute__ ((__packed__));
-
-/* Configure Command Block (CONFIG_CB)*/
-typedef struct _config_cb_t {
-	cb_header_t cfg_cbhdr;
-	u8 cfg_byte[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT];
-} config_cb_t __attribute__ ((__packed__));
-
-/* MultiCast Command Block (MULTICAST_CB)*/
-typedef struct _multicast_cb_t {
-	cb_header_t mc_cbhdr;
-	u16 mc_count;	/* Number of multicast addresses */
-	u8 mc_addr[(ETH_ALEN * MAX_MULTICAST_ADDRS)];
-} mltcst_cb_t __attribute__ ((__packed__));
-
-#define UCODE_MAX_DWORDS	134
-/* Load Microcode Command Block (LOAD_UCODE_CB)*/
-typedef struct _load_ucode_cb_t {
-	cb_header_t load_ucode_cbhdr;
-	u32 ucode_dword[UCODE_MAX_DWORDS];
-} load_ucode_cb_t __attribute__ ((__packed__));
-
-/* Load Programmable Filter Data*/
-typedef struct _filter_cb_t {
-	cb_header_t filter_cb_hdr;
-	u32 filter_data[MAX_FILTER];
-} filter_cb_t __attribute__ ((__packed__));
-
-/* NON_TRANSMIT_CB -- Generic Non-Transmit Command Block 
- */
-typedef struct _nxmit_cb_t {
-	union {
-		config_cb_t config;
-		ia_cb_t setup;
-		load_ucode_cb_t load_ucode;
-		mltcst_cb_t multicast;
-		filter_cb_t filter;
-	} ntcb;
-} nxmit_cb_t __attribute__ ((__packed__));
-
-/*Block for queuing for postponed execution of the non-transmit commands*/
-typedef struct _nxmit_cb_entry_t {
-	struct list_head list_elem;
-	nxmit_cb_t *non_tx_cmd;
-	dma_addr_t dma_addr;
-	unsigned long expiration_time;
-} nxmit_cb_entry_t;
-
-/* States for postponed non tx commands execution */
-typedef enum _non_tx_cmd_state_t {
-	E100_NON_TX_IDLE = 0,	/* No queued NON-TX commands */
-	E100_WAIT_TX_FINISH,	/* Wait for completion of the TX activities */
-	E100_WAIT_NON_TX_FINISH	/* Wait for completion of the non TX command */
-} non_tx_cmd_state_t;
-
-/* some defines for the ipcb */
-#define IPCB_IP_CHECKSUM_ENABLE 	BIT_4
-#define IPCB_TCPUDP_CHECKSUM_ENABLE	BIT_5
-#define IPCB_TCP_PACKET 		BIT_6
-#define IPCB_LARGESEND_ENABLE 		BIT_7
-#define IPCB_HARDWAREPARSING_ENABLE	BIT_0
-#define IPCB_INSERTVLAN_ENABLE 		BIT_1
-#define IPCB_IP_ACTIVATION_DEFAULT      IPCB_HARDWAREPARSING_ENABLE
-
-/* Transmit Buffer Descriptor (TBD)*/
-typedef struct _tbd_t {
-	u32 tbd_buf_addr;	/* Physical Transmit Buffer Address */
-	u16 tbd_buf_cnt;	/* Actual Count Of Bytes */
-	u16 padd;
-} tbd_t __attribute__ ((__packed__));
-
-/* d102 specific fields */
-typedef struct _tcb_ipcb_t {
-	u16 schedule_low;
-	u8 ip_schedule;
-	u8 ip_activation_high;
-	u16 vlan;
-	u8 ip_header_offset;
-	u8 tcp_header_offset;
-	union {
-		u32 sec_rec_phys_addr;
-		u32 tbd_zero_address;
-	} tbd_sec_addr;
-	union {
-		u16 sec_rec_size;
-		u16 tbd_zero_size;
-	} tbd_sec_size;
-	u16 total_tcp_payload;
-} tcb_ipcb_t __attribute__ ((__packed__));
-
-#define E100_TBD_ARRAY_SIZE (2+MAX_SKB_FRAGS)
-
-/* Transmit Command Block (TCB)*/
-struct _tcb_t {
-	cb_header_t tcb_hdr;
-	u32 tcb_tbd_ptr;	/* TBD address */
-	u16 tcb_cnt;	/* Data Bytes In TCB past header */
-	u8 tcb_thrshld;	/* TX Threshold for FIFO Extender */
-	u8 tcb_tbd_num;
-
-	union {
-		tcb_ipcb_t ipcb;	/* d102 ipcb fields */
-		tbd_t tbd_array[E100_TBD_ARRAY_SIZE];
-	} tcbu;
-
-	/* From here onward we can dump anything we want as long as the
-	 * size of the total structure is a multiple of a paragraph
-	 * boundary ( i.e. -16 bit aligned ).
-	 */
-	tbd_t *tbd_ptr;
-
-	u32 tcb_tbd_dflt_ptr;	/* TBD address for non-segmented packet */
-	u32 tcb_tbd_expand_ptr;	/* TBD address for segmented packet */
-
-	struct sk_buff *tcb_skb;	/* the associated socket buffer */
-	dma_addr_t tcb_phys;	/* phys addr of the TCB */
-} __attribute__ ((__packed__));
-
-#define _TCB_T_
-typedef struct _tcb_t tcb_t;
-
-/* Receive Frame Descriptor (RFD) - will be using the simple model*/
-struct _rfd_t {
-	/* 8255x */
-	cb_header_t rfd_header;
-	u32 rfd_rbd_ptr;	/* Receive Buffer Descriptor Addr */
-	u16 rfd_act_cnt;	/* Number Of Bytes Received */
-	u16 rfd_sz;	/* Number Of Bytes In RFD */
-	/* D102 aka Gamla */
-	u16 vlanid;
-	u8 rcvparserstatus;
-	u8 reserved;
-	u16 securitystatus;
-	u8 checksumstatus;
-	u8 zerocopystatus;
-	u8 pad[8];	/* data should be 16 byte aligned */
-	u8 data[RFD_DATA_SIZE];
-
-} __attribute__ ((__packed__));
-
-#define _RFD_T_
-typedef struct _rfd_t rfd_t;
-
-/* Receive Buffer Descriptor (RBD)*/
-typedef struct _rbd_t {
-	u16 rbd_act_cnt;	/* Number Of Bytes Received */
-	u16 rbd_filler;
-	u32 rbd_lnk_addr;	/* Link To Next RBD */
-	u32 rbd_rcb_addr;	/* Receive Buffer Address */
-	u16 rbd_sz;	/* Receive Buffer Size */
-	u16 rbd_filler1;
-} rbd_t __attribute__ ((__packed__));
-
-/*
- * This structure is used to maintain a FIFO access to a resource that is 
- * maintained as a circular queue. The resource to be maintained is pointed
- * to by the "data" field in the structure below. In this driver the TCBs', 
- * TBDs' & RFDs' are maintained  as a circular queue & are managed thru this
- * structure.
- */
-typedef struct _buf_pool_t {
-	unsigned int head;	/* index to first used resource */
-	unsigned int tail;	/* index to last used resource */
-	void *data;		/* points to resource pool */
-} buf_pool_t;
-
-/*Rx skb holding structure*/
-struct rx_list_elem {
-	struct list_head list_elem;
-	dma_addr_t dma_addr;
-	struct sk_buff *skb;
-};
-
-enum next_cu_cmd_e { RESUME_NO_WAIT = 0, RESUME_WAIT, START_WAIT };
-enum zlock_state_e { ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING };
-enum tx_queue_stop_type { LONG_STOP = 0, SHORT_STOP };
-
-/* 64 bit aligned size */
-#define E100_SIZE_64A(X) ((sizeof(X) + 7) & ~0x7)
-
-typedef struct _bd_dma_able_t {
-	char selftest[E100_SIZE_64A(self_test_t)];
-	char stats_counters[E100_SIZE_64A(max_counters_t)];
-} bd_dma_able_t;
-
-/* bit masks for bool parameters */
-#define PRM_XSUMRX       0x00000001
-#define PRM_UCODE        0x00000002
-#define PRM_FC           0x00000004
-#define PRM_IFS          0x00000008
-#define PRM_BUNDLE_SMALL 0x00000010
-
-struct cfg_params {
-	int e100_speed_duplex;
-	int RxDescriptors;
-	int TxDescriptors;
-	int IntDelay;
-	int BundleMax;
-	int ber;
-	u32 b_params;
-};
-struct ethtool_lpbk_data{
-        dma_addr_t dma_handle;
-        tcb_t *tcb;
-        rfd_t *rfd;
-
-};
-
-struct e100_private {
-	struct vlan_group *vlgrp;
-	u32 flags;		/* board management flags */
-	u32 tx_per_underrun;	/* number of good tx frames per underrun */
-	unsigned int tx_count;	/* count of tx frames, so we can request an interrupt */
-	u8 tx_thld;		/* stores transmit threshold */
-	u16 eeprom_size;
-	u32 pwa_no;		/* PWA: xxxxxx-0xx */
-	u8 perm_node_address[ETH_ALEN];
-	struct list_head active_rx_list;	/* list of rx buffers */
-	struct list_head rx_struct_pool;	/* pool of rx buffer struct headers */
-	u16 rfd_size;			/* size of the adapter's RFD struct */
-	int skb_req;			/* number of skbs neede by the adapter */
-	u8 intr_mask;			/* mask for interrupt status */
-
-	void *dma_able;			/* dma allocated structs */
-	dma_addr_t dma_able_phys;
-	self_test_t *selftest;		/* pointer to self test area */
-	dma_addr_t selftest_phys;	/* phys addr of selftest */
-	max_counters_t *stats_counters;	/* pointer to stats table */
-	dma_addr_t stat_cnt_phys;	/* phys addr of stat counter area */
-
-	stat_mode_t stat_mode;	/* statistics mode: extended, TCO, basic */
-	scb_t *scb;		/* memory mapped ptr to 82557 scb */
-
-	tcb_t *last_tcb;	/* pointer to last tcb sent */
-	buf_pool_t tcb_pool;	/* adapter's TCB array */
-	dma_addr_t tcb_phys;	/* phys addr of start of TCBs */
-
-	u16 cur_line_speed;
-	u16 cur_dplx_mode;
-
-	struct net_device *device;
-	struct pci_dev *pdev;
-	struct driver_stats drv_stats;
-
-	u8 rev_id;		/* adapter PCI revision ID */
-
-	unsigned int phy_addr;	/* address of PHY component */
-	unsigned int PhyId;	/* ID of PHY component */
-	unsigned int PhyState;	/* state for the fix squelch algorithm */
-	unsigned int PhyDelay;	/* delay for the fix squelch algorithm */
-
-	/* Lock defintions for the driver */
-	spinlock_t bd_lock;		/* board lock */
-	spinlock_t bd_non_tx_lock;	/* Non transmit command lock  */
-	spinlock_t config_lock;		/* config block lock */
-	spinlock_t mdi_access_lock;	/* mdi lock */
-
-	struct timer_list watchdog_timer;	/* watchdog timer id */
-
-	/* non-tx commands parameters */
-	struct timer_list nontx_timer_id;	/* non-tx timer id */
-	struct list_head non_tx_cmd_list;
-	non_tx_cmd_state_t non_tx_command_state;
-	nxmit_cb_entry_t *same_cmd_entry[CB_MAX_NONTX_CMD];
-
-	enum next_cu_cmd_e next_cu_cmd;
-
-	/* Zero Locking Algorithm data members */
-	enum zlock_state_e zlock_state;
-	u8 zlock_read_data[16];	/* number of times each value 0-15 was read */
-	u16 zlock_read_cnt;	/* counts number of reads */
-	ulong zlock_sleep_cnt;	/* keeps track of "sleep" time */
-
-	u8 config[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT];
-
-	/* IFS params */
-	u8 ifs_state;
-	u8 ifs_value;
-
-	struct cfg_params params;	/* adapter's command line parameters */
-
-	u32 speed_duplex_caps;	/* adapter's speed/duplex capabilities */
-
-	/* WOL params for ethtool */
-	u32 wolsupported;
-	u32 wolopts;
-	u16 ip_lbytes;
-	struct ethtool_lpbk_data loopback;
-	struct timer_list blink_timer;	/* led blink timer id */
-
-#ifdef CONFIG_PM
-	u32 pci_state[16];
-#endif
-#ifdef E100_CU_DEBUG	
-	u8 last_cmd;
-	u8 last_sub_cmd;
-#endif	
-};
-
-#define E100_AUTONEG        0
-#define E100_SPEED_10_HALF  1
-#define E100_SPEED_10_FULL  2
-#define E100_SPEED_100_HALF 3
-#define E100_SPEED_100_FULL 4
-
-/********* function prototypes *************/
-extern int e100_open(struct net_device *);
-extern int e100_close(struct net_device *);
-extern void e100_isolate_driver(struct e100_private *bdp);
-extern unsigned char e100_hw_init(struct e100_private *);
-extern void e100_sw_reset(struct e100_private *bdp, u32 reset_cmd);
-extern u8 e100_start_cu(struct e100_private *bdp, tcb_t *tcb);
-extern void e100_free_non_tx_cmd(struct e100_private *bdp,
-				 nxmit_cb_entry_t *non_tx_cmd);
-extern nxmit_cb_entry_t *e100_alloc_non_tx_cmd(struct e100_private *bdp);
-extern unsigned char e100_exec_non_cu_cmd(struct e100_private *bdp,
-					  nxmit_cb_entry_t *cmd);
-extern unsigned char e100_selftest(struct e100_private *bdp, u32 *st_timeout,
-				   u32 *st_result);
-extern unsigned char e100_get_link_state(struct e100_private *bdp);
-extern unsigned char e100_wait_scb(struct e100_private *bdp);
-
-extern void e100_deisolate_driver(struct e100_private *bdp, u8 full_reset);
-extern unsigned char e100_configure_device(struct e100_private *bdp);
-#ifdef E100_CU_DEBUG
-extern unsigned char e100_cu_unknown_state(struct e100_private *bdp);
-#endif
-
-#define ROM_TEST_FAIL		0x01
-#define REGISTER_TEST_FAIL	0x02
-#define SELF_TEST_FAIL		0x04
-#define TEST_TIMEOUT		0x08
-
-enum test_offsets {
-	test_link,
-	test_eeprom,
-	test_self_test,
-	test_loopback_mac,
-	test_loopback_phy,
-	cable_diag,
-	max_test_res,  /* must be last */
-};
-
-#endif
diff -Nru a/drivers/net/e100/e100_config.c b/drivers/net/e100/e100_config.c
--- a/drivers/net/e100/e100_config.c	Wed Feb 11 22:30:57 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,639 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-/**********************************************************************
-*                                                                     *
-* INTEL CORPORATION                                                   *
-*                                                                     *
-* This software is supplied under the terms of the license included   *
-* above.  All use of this driver must be in accordance with the terms *
-* of that license.                                                    *
-*                                                                     *
-* Module Name:  e100_config.c                                         *
-*                                                                     *
-* Abstract:     Functions for configuring the network adapter.        *
-*                                                                     *
-* Environment:  This file is intended to be specific to the Linux     *
-*               operating system.                                     *
-*                                                                     *
-**********************************************************************/
-#include "e100_config.h"
-
-static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable);
-
-static const u8 def_config[] = {
-	CB_CFIG_BYTE_COUNT,
-	0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x07, 0x01,
-	0x00, 0x2e, 0x00, 0x60, 0x00, 0xf2, 0xc8, 0x00,
-	0x40, 0xf2, 0x80, 0x3f, 0x05
-};
-
-/**
- * e100_config_init_82557 - config the 82557 adapter
- * @bdp: atapter's private data struct
- *
- * This routine will initialize the 82557 configure block.
- * All other init functions will only set values that are
- * different from the 82557 default.
- */
-void
-e100_config_init_82557(struct e100_private *bdp)
-{
-	/* initialize config block */
-	memcpy(bdp->config, def_config, sizeof (def_config));
-	bdp->config[0] = CB_CFIG_BYTE_COUNT;	/* just in case */
-
-	e100_config_ifs(bdp);
-
-	/*
-	 * Enable extended statistical counters (82558 and up) and TCO counters
-	 * (82559 and up) and set the statistical counters' mode in bdp 
-	 *  
-	 *  stat. mode      |    TCO stat. bit (2)  |  Extended stat. bit (5)
-	 * ------------------------------------------------------------------
-	 *  Basic (557)     |       0               |         1
-	 * ------------------------------------------------------------------
-	 *  Extended (558)  |       0               |         0
-	 * ------------------------------------------------------------------
-	 *  TCO (559)       |       1               |         1
-	 * ------------------------------------------------------------------
-	 *  Reserved        |       1               |         0
-	 * ------------------------------------------------------------------
-	 */
-	bdp->config[6] &= ~CB_CFIG_TCO_STAT;
-	bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
-	bdp->stat_mode = E100_BASIC_STATS;
-
-	/* Setup for MII or 503 operation.  The CRS+CDT bit should only be set */
-	/* when operating in 503 mode. */
-	if (bdp->phy_addr == 32) {
-		bdp->config[8] &= ~CB_CFIG_503_MII;
-		bdp->config[15] |= CB_CFIG_CRS_OR_CDT;
-	} else {
-		bdp->config[8] |= CB_CFIG_503_MII;
-		bdp->config[15] &= ~CB_CFIG_CRS_OR_CDT;
-	}
-
-	e100_config_fc(bdp);
-	e100_config_force_dplx(bdp);
-	e100_config_promisc(bdp, false);
-	e100_config_mulcast_enbl(bdp, false);
-}
-
-static void
-e100_config_init_82558(struct e100_private *bdp)
-{
-	/* MWI enable. This should be turned on only if the adapter is a 82558/9
-	 * and if the PCI command reg. has enabled the MWI bit. */
-	bdp->config[3] |= CB_CFIG_MWI_EN;
-
-	bdp->config[6] &= ~CB_CFIG_EXT_TCB_DIS;
-
-	if (bdp->rev_id >= D101MA_REV_ID) {
-		/* this is 82559 and up - enable TCO counters */
-		bdp->config[6] |= CB_CFIG_TCO_STAT;
-		bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
-		bdp->stat_mode = E100_TCO_STATS;
-
-		if ((bdp->rev_id < D102_REV_ID) &&
-		    (bdp->params.b_params & PRM_XSUMRX) &&
-		    (bdp->pdev->device != 0x1209)) {
-
-			bdp->flags |= DF_CSUM_OFFLOAD;
-			bdp->config[9] |= 1;
-		}
-	} else {
-		/* this is 82558 */
-		bdp->config[6] &= ~CB_CFIG_TCO_STAT;
-		bdp->config[6] &= ~CB_CFIG_EXT_STAT_DIS;
-		bdp->stat_mode = E100_EXTENDED_STATS;
-	}
-
-	e100_config_long_rx(bdp, true);
-}
-
-static void
-e100_config_init_82550(struct e100_private *bdp)
-{
-	/* The D102 chip allows for 32 config bytes.  This value is
-	 * supposed to be in Byte 0.  Just add the extra bytes to
-	 * what was already setup in the block. */
-	bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
-
-	/* now we need to enable the extended RFD.  When this is
-	 * enabled, the immediated receive data buffer starts at offset
-	 * 32 from the RFD base address, instead of at offset 16. */
-	bdp->config[7] |= CB_CFIG_EXTENDED_RFD;
-
-	/* put the chip into D102 receive mode.  This is necessary
-	 * for any parsing and offloading features. */
-	bdp->config[22] = CB_CFIG_RECEIVE_GAMLA_MODE;
-
-	/* set the flag if checksum offloading was enabled */
-	if (bdp->params.b_params & PRM_XSUMRX) {
-		bdp->flags |= DF_CSUM_OFFLOAD;
-	}
-}
-
-/* Initialize the adapter's configure block */
-void
-e100_config_init(struct e100_private *bdp)
-{
-	e100_config_init_82557(bdp);
-
-	if (bdp->flags & IS_BACHELOR)
-		e100_config_init_82558(bdp);
-
-	if (bdp->rev_id >= D102_REV_ID)
-		e100_config_init_82550(bdp);
-}
-
-/**
- * e100_force_config - force a configure command
- * @bdp: atapter's private data struct
- *
- * This routine will force a configure command to the adapter.
- * The command will be executed in polled mode as interrupts
- * are _disabled_ at this time.
- *
- * Returns:
- *      true: if the configure command was successfully issued and completed
- *      false: otherwise
- */
-unsigned char
-e100_force_config(struct e100_private *bdp)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	bdp->config[0] = CB_CFIG_BYTE_COUNT;
-	if (bdp->rev_id >= D102_REV_ID) {
-		/* The D102 chip allows for 32 config bytes.  This value is
-		   supposed to be in Byte 0.  Just add the extra bytes to
-		   what was already setup in the block. */
-		bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-
-	// although we call config outside the lock, there is no
-	// race condition because config byte count has maximum value
-	return e100_config(bdp);
-}
-
-/**
- * e100_config - issue a configure command
- * @bdp: atapter's private data struct
- *
- * This routine will issue a configure command to the 82557.
- * This command will be executed in polled mode as interrupts
- * are _disabled_ at this time.
- *
- * Returns:
- *      true: if the configure command was successfully issued and completed
- *      false: otherwise
- */
-unsigned char
-e100_config(struct e100_private *bdp)
-{
-	cb_header_t *pntcb_hdr;
-	unsigned char res = true;
-	nxmit_cb_entry_t *cmd;
-
-	if (bdp->config[0] == 0) {
-		goto exit;
-	}
-
-	if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) {
-		res = false;
-		goto exit;
-	}
-
-	pntcb_hdr = (cb_header_t *) cmd->non_tx_cmd;
-	pntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_CONFIGURE);
-
-	spin_lock_bh(&bdp->config_lock);
-
-	if (bdp->config[0] < CB_CFIG_MIN_PARAMS) {
-		bdp->config[0] = CB_CFIG_MIN_PARAMS;
-	}
-
-	/* Copy the device's config block to the device's memory */
-	memcpy(cmd->non_tx_cmd->ntcb.config.cfg_byte, bdp->config,
-	       bdp->config[0]);
-	/* reset number of bytes to config next time */
-	bdp->config[0] = 0;
-
-	spin_unlock_bh(&bdp->config_lock);
-
-	res = e100_exec_non_cu_cmd(bdp, cmd);
-
-exit:
-	if (netif_running(bdp->device))
-		netif_wake_queue(bdp->device);
-	return res;
-}
-
-/**
- * e100_config_fc - config flow-control state
- * @bdp: adapter's private data struct
- *
- * This routine will enable or disable flow control support in the adapter's
- * config block. Flow control will be enable only if requested using the command
- * line option, and if the link is flow-contorl capable (both us and the link
- * partner). But, if link partner is capable of autoneg, but not capable of
- * flow control, received PAUSE	frames are still honored.
- */
-void
-e100_config_fc(struct e100_private *bdp)
-{
-	unsigned char enable = false;
-	/* 82557 doesn't support fc. Don't touch this option */
-	if (!(bdp->flags & IS_BACHELOR))
-		return;
-
-	/* Enable fc if requested and if the link supports it */
-	if ((bdp->params.b_params & PRM_FC) && (bdp->flags & 
-		(DF_LINK_FC_CAP | DF_LINK_FC_TX_ONLY))) {
-		enable = true;
-	}
-
-	spin_lock_bh(&(bdp->config_lock));
-
-	if (enable) {
-		if (bdp->flags & DF_LINK_FC_TX_ONLY) {
-			/* If link partner is capable of autoneg, but  */
-			/* not capable of flow control, Received PAUSE */
-			/* frames are still honored, i.e.,             */
-			/* transmitted frames would be paused by       */
-			/* incoming PAUSE frames                       */
-			bdp->config[16] = DFLT_NO_FC_DELAY_LSB;
-			bdp->config[17] = DFLT_NO_FC_DELAY_MSB;
-			bdp->config[19] &= ~(CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART);
-			bdp->config[19] |= CB_CFIG_FC_REJECT;
-			bdp->config[19] &= ~CB_CFIG_TX_FC_DIS;
-		} else {
-			bdp->config[16] = DFLT_FC_DELAY_LSB;
-			bdp->config[17] = DFLT_FC_DELAY_MSB;
-			bdp->config[19] |= CB_CFIG_FC_OPTS;
-			bdp->config[19] &= ~CB_CFIG_TX_FC_DIS;
-		}
-	} else {
-		bdp->config[16] = DFLT_NO_FC_DELAY_LSB;
-		bdp->config[17] = DFLT_NO_FC_DELAY_MSB;
-		bdp->config[19] &= ~CB_CFIG_FC_OPTS;
-		bdp->config[19] |= CB_CFIG_TX_FC_DIS;
-	}
-	E100_CONFIG(bdp, 19);
-	spin_unlock_bh(&(bdp->config_lock));
-
-	return;
-}
-
-/**
- * e100_config_promisc - configure promiscuous mode
- * @bdp: atapter's private data struct
- * @enable: should we enable this option or not
- *
- * This routine will enable or disable promiscuous mode
- * in the adapter's config block.
- */
-void
-e100_config_promisc(struct e100_private *bdp, unsigned char enable)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	/* if in promiscuous mode, save bad frames */
-	if (enable) {
-
-		if (!(bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES)) {
-			bdp->config[6] |= CB_CFIG_SAVE_BAD_FRAMES;
-			E100_CONFIG(bdp, 6);
-		}
-
-		if (bdp->config[7] & (u8) BIT_0) {
-			bdp->config[7] &= (u8) (~BIT_0);
-			E100_CONFIG(bdp, 7);
-		}
-
-		if (!(bdp->config[15] & CB_CFIG_PROMISCUOUS)) {
-			bdp->config[15] |= CB_CFIG_PROMISCUOUS;
-			E100_CONFIG(bdp, 15);
-		}
-
-	} else {		/* not in promiscuous mode */
-
-		if (bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES) {
-			bdp->config[6] &= ~CB_CFIG_SAVE_BAD_FRAMES;
-			E100_CONFIG(bdp, 6);
-		}
-
-		if (!(bdp->config[7] & (u8) BIT_0)) {
-			bdp->config[7] |= (u8) (BIT_0);
-			E100_CONFIG(bdp, 7);
-		}
-
-		if (bdp->config[15] & CB_CFIG_PROMISCUOUS) {
-			bdp->config[15] &= ~CB_CFIG_PROMISCUOUS;
-			E100_CONFIG(bdp, 15);
-		}
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_mulcast_enbl - configure allmulti mode
- * @bdp: atapter's private data struct
- * @enable: should we enable this option or not
- *
- * This routine will enable or disable reception of all multicast packets
- * in the adapter's config block.
- */
-void
-e100_config_mulcast_enbl(struct e100_private *bdp, unsigned char enable)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	/* this flag is used to enable receiving all multicast packet */
-	if (enable) {
-		if (!(bdp->config[21] & CB_CFIG_MULTICAST_ALL)) {
-			bdp->config[21] |= CB_CFIG_MULTICAST_ALL;
-			E100_CONFIG(bdp, 21);
-		}
-
-	} else {
-		if (bdp->config[21] & CB_CFIG_MULTICAST_ALL) {
-			bdp->config[21] &= ~CB_CFIG_MULTICAST_ALL;
-			E100_CONFIG(bdp, 21);
-		}
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_ifs - configure the IFS parameter
- * @bdp: atapter's private data struct
- *
- * This routine will configure the adaptive IFS value
- * in the adapter's config block. IFS values are only
- * relevant in half duplex, so set to 0 in full duplex.
- */
-void
-e100_config_ifs(struct e100_private *bdp)
-{
-	u8 value = 0;
-
-	spin_lock_bh(&(bdp->config_lock));
-
-	/* IFS value is only needed to be specified at half-duplex mode */
-	if (bdp->cur_dplx_mode == HALF_DUPLEX) {
-		value = (u8) bdp->ifs_value;
-	}
-
-	if (bdp->config[2] != value) {
-		bdp->config[2] = value;
-		E100_CONFIG(bdp, 2);
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_force_dplx - configure the forced full duplex mode
- * @bdp: atapter's private data struct
- *
- * This routine will enable or disable force full duplex
- * in the adapter's config block. If the PHY is 503, and
- * the duplex is full, consider the adapter forced.
- */
-void
-e100_config_force_dplx(struct e100_private *bdp)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	/* We must force full duplex on if we are using PHY 0, and we are */
-	/* supposed to run in FDX mode. We do this because the e100 has only */
-	/* one FDX# input pin, and that pin will be connected to PHY 1. */
-	/* Changed the 'if' condition below to fix performance problem * at 10
-	 * full. The Phy was getting forced to full duplex while the MAC * was
-	 * not, because the cur_dplx_mode was not being set to 2 by SetupPhy. *
-	 * This is how the condition was, initially. * This has been changed so
-	 * that the MAC gets forced to full duplex * simply if the user has
-	 * forced full duplex. * * if (( bdp->phy_addr == 0 ) && (
-	 * bdp->cur_dplx_mode == 2 )) */
-	/* The rest of the fix is in the PhyDetect code. */
-	if ((bdp->params.e100_speed_duplex == E100_SPEED_10_FULL) ||
-	    (bdp->params.e100_speed_duplex == E100_SPEED_100_FULL) ||
-	    ((bdp->phy_addr == 32) && (bdp->cur_dplx_mode == FULL_DUPLEX))) {
-		if (!(bdp->config[19] & (u8) CB_CFIG_FORCE_FDX)) {
-			bdp->config[19] |= (u8) CB_CFIG_FORCE_FDX;
-			E100_CONFIG(bdp, 19);
-		}
-
-	} else {
-		if (bdp->config[19] & (u8) CB_CFIG_FORCE_FDX) {
-			bdp->config[19] &= (u8) (~CB_CFIG_FORCE_FDX);
-			E100_CONFIG(bdp, 19);
-		}
-	}
-
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_long_rx
- * @bdp: atapter's private data struct
- * @enable: should we enable this option or not
- *
- * This routine will enable or disable reception of larger packets.
- * This is needed by VLAN implementations.
- */
-static void
-e100_config_long_rx(struct e100_private *bdp, unsigned char enable)
-{
-	if (enable) {
-		if (!(bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
-			bdp->config[18] |= CB_CFIG_LONG_RX_OK;
-			E100_CONFIG(bdp, 18);
-		}
-
-	} else {
-		if ((bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
-			bdp->config[18] &= ~CB_CFIG_LONG_RX_OK;
-			E100_CONFIG(bdp, 18);
-		}
-	}
-}
-
-/**
- * e100_config_wol
- * @bdp: atapter's private data struct
- *
- * This sets configuration options for PHY and Magic Packet WoL 
- */
-void
-e100_config_wol(struct e100_private *bdp)
-{
-	spin_lock_bh(&(bdp->config_lock));
-
-	if (bdp->wolopts & WAKE_PHY) {
-		bdp->config[9] |= CB_LINK_STATUS_WOL;
-	}
-	else {
-		/* Disable PHY WoL */
-		bdp->config[9] &= ~CB_LINK_STATUS_WOL;
-	}
-
-	if (bdp->wolopts & WAKE_MAGIC) {
-		bdp->config[19] &= ~CB_DISABLE_MAGPAK_WAKE;
-	}
-	else {
-		/* Disable Magic Packet WoL */
-		bdp->config[19] |= CB_DISABLE_MAGPAK_WAKE;
-	}
-
-	E100_CONFIG(bdp, 19);
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-void
-e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable)
-{
-	spin_lock_bh(&(bdp->config_lock));
-	if (enable) {
-		if (!(bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) {
-			bdp->config[22] |= CB_CFIG_VLAN_DROP_ENABLE;
-			E100_CONFIG(bdp, 22);
-		}
-
-	} else {
-		if ((bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) {
-			bdp->config[22] &= ~CB_CFIG_VLAN_DROP_ENABLE;
-			E100_CONFIG(bdp, 22);
-		}
-	}
-	spin_unlock_bh(&(bdp->config_lock));
-}
-
-/**
- * e100_config_loopback_mode
- * @bdp: atapter's private data struct
- * @mode: loopback mode(phy/mac/none)
- *
- */
-unsigned char
-e100_config_loopback_mode(struct e100_private *bdp, u8 mode)
-{
-	unsigned char bc_changed = false;
-	u8 config_byte;
-
-	spin_lock_bh(&(bdp->config_lock));
-
-	switch (mode) {
-	case NO_LOOPBACK:
-		config_byte = CB_CFIG_LOOPBACK_NORMAL;
-		break;
-	case MAC_LOOPBACK:
-		config_byte = CB_CFIG_LOOPBACK_INTERNAL;
-		break;
-	case PHY_LOOPBACK:
-		config_byte = CB_CFIG_LOOPBACK_EXTERNAL;
-		break;
-	default:
-		printk(KERN_NOTICE "e100: e100_config_loopback_mode: "
-		       "Invalid argument 'mode': %d\n", mode);
-		goto exit;
-	}
-
-	if ((bdp->config[10] & CB_CFIG_LOOPBACK_MODE) != config_byte) {
-
-		bdp->config[10] &= (~CB_CFIG_LOOPBACK_MODE);
-		bdp->config[10] |= config_byte;
-		E100_CONFIG(bdp, 10);
-		bc_changed = true;
-	}
-
-exit:
-	spin_unlock_bh(&(bdp->config_lock));
-	return bc_changed;
-}
-unsigned char
-e100_config_tcb_ext_enable(struct e100_private *bdp, unsigned char enable)
-{
-        unsigned char bc_changed = false;
- 
-        spin_lock_bh(&(bdp->config_lock));
- 
-        if (enable) {
-                if (bdp->config[6] & CB_CFIG_EXT_TCB_DIS) {
- 
-                        bdp->config[6] &= (~CB_CFIG_EXT_TCB_DIS);
-                        E100_CONFIG(bdp, 6);
-                        bc_changed = true;
-                }
- 
-        } else {
-                if (!(bdp->config[6] & CB_CFIG_EXT_TCB_DIS)) {
- 
-                        bdp->config[6] |= CB_CFIG_EXT_TCB_DIS;
-                        E100_CONFIG(bdp, 6);
-                        bc_changed = true;
-                }
-        }
-        spin_unlock_bh(&(bdp->config_lock));
- 
-        return bc_changed;
-}
-unsigned char
-e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable)
-{
-        unsigned char bc_changed = false;
- 
-        spin_lock_bh(&(bdp->config_lock));
- 
-        if (enable) {
-                if (!(bdp->config[7] & CB_CFIG_DYNTBD_EN)) {
- 
-                        bdp->config[7] |= CB_CFIG_DYNTBD_EN;
-                        E100_CONFIG(bdp, 7);
-                        bc_changed = true;
-                }
- 
-        } else {
-                if (bdp->config[7] & CB_CFIG_DYNTBD_EN) {
- 
-                        bdp->config[7] &= (~CB_CFIG_DYNTBD_EN);
-                        E100_CONFIG(bdp, 7);
-                        bc_changed = true;
-                }
-        }
-        spin_unlock_bh(&(bdp->config_lock));
- 
-        return bc_changed;
-}
-
diff -Nru a/drivers/net/e100/e100_config.h b/drivers/net/e100/e100_config.h
--- a/drivers/net/e100/e100_config.h	Wed Feb 11 22:30:56 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,168 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#ifndef _E100_CONFIG_INC_
-#define _E100_CONFIG_INC_
-
-#include "e100.h"
-
-#define E100_CONFIG(bdp, X) ((bdp)->config[0] = max_t(u8, (bdp)->config[0], (X)+1))
-
-#define CB_CFIG_MIN_PARAMS         8
-
-/* byte 0 bit definitions*/
-#define CB_CFIG_BYTE_COUNT_MASK     BIT_0_5	/* Byte count occupies bit 5-0 */
-
-/* byte 1 bit definitions*/
-#define CB_CFIG_RXFIFO_LIMIT_MASK   BIT_0_4	/* RxFifo limit mask */
-#define CB_CFIG_TXFIFO_LIMIT_MASK   BIT_4_7	/* TxFifo limit mask */
-
-/* byte 2 bit definitions -- ADAPTIVE_IFS*/
-
-/* word 3 bit definitions -- RESERVED*/
-/* Changed for 82558 enhancements */
-/* byte 3 bit definitions */
-#define CB_CFIG_MWI_EN      BIT_0	/* Enable MWI on PCI bus */
-#define CB_CFIG_TYPE_EN     BIT_1	/* Type Enable */
-#define CB_CFIG_READAL_EN   BIT_2	/* Enable Read Align */
-#define CB_CFIG_TERMCL_EN   BIT_3	/* Cache line write  */
-
-/* byte 4 bit definitions*/
-#define CB_CFIG_RX_MIN_DMA_MASK     BIT_0_6	/* Rx minimum DMA count mask */
-
-/* byte 5 bit definitions*/
-#define CB_CFIG_TX_MIN_DMA_MASK BIT_0_6	/* Tx minimum DMA count mask */
-#define CB_CFIG_DMBC_EN         BIT_7	/* Enable Tx/Rx min. DMA counts */
-
-/* Changed for 82558 enhancements */
-/* byte 6 bit definitions*/
-#define CB_CFIG_LATE_SCB           BIT_0	/* Update SCB After New Tx Start */
-#define CB_CFIG_DIRECT_DMA_DIS     BIT_1	/* Direct DMA mode */
-#define CB_CFIG_TNO_INT            BIT_2	/* Tx Not OK Interrupt */
-#define CB_CFIG_TCO_STAT           BIT_2	/* TCO statistics in 559 and above */
-#define CB_CFIG_CI_INT             BIT_3	/* Command Complete Interrupt */
-#define CB_CFIG_EXT_TCB_DIS        BIT_4	/* Extended TCB */
-#define CB_CFIG_EXT_STAT_DIS       BIT_5	/* Extended Stats */
-#define CB_CFIG_SAVE_BAD_FRAMES    BIT_7	/* Save Bad Frames Enabled */
-
-/* byte 7 bit definitions*/
-#define CB_CFIG_DISC_SHORT_FRAMES   BIT_0	/* Discard Short Frames */
-#define CB_CFIG_DYNTBD_EN           BIT_7	/* Enable dynamic TBD */
-/* Enable extended RFD's on D102 */
-#define CB_CFIG_EXTENDED_RFD        BIT_5
-
-/* byte 8 bit definitions*/
-#define CB_CFIG_503_MII             BIT_0	/* 503 vs. MII mode */
-
-/* byte 9 bit definitions -- pre-defined all zeros*/
-#define CB_LINK_STATUS_WOL	BIT_5
-
-/* byte 10 bit definitions*/
-#define CB_CFIG_NO_SRCADR       BIT_3	/* No Source Address Insertion */
-#define CB_CFIG_PREAMBLE_LEN    BIT_4_5	/* Preamble Length */
-#define CB_CFIG_LOOPBACK_MODE   BIT_6_7	/* Loopback Mode */
-#define CB_CFIG_LOOPBACK_NORMAL 0
-#define CB_CFIG_LOOPBACK_INTERNAL BIT_6
-#define CB_CFIG_LOOPBACK_EXTERNAL BIT_6_7
-
-/* byte 11 bit definitions*/
-#define CB_CFIG_LINEAR_PRIORITY     BIT_0_2	/* Linear Priority */
-
-/* byte 12 bit definitions*/
-#define CB_CFIG_LINEAR_PRI_MODE     BIT_0	/* Linear Priority mode */
-#define CB_CFIG_IFS_MASK            BIT_4_7	/* Interframe Spacing mask */
-
-/* byte 13 bit definitions -- pre-defined all zeros*/
-
-/* byte 14 bit definitions -- pre-defined 0xf2*/
-
-/* byte 15 bit definitions*/
-#define CB_CFIG_PROMISCUOUS         BIT_0	/* Promiscuous Mode Enable */
-#define CB_CFIG_BROADCAST_DIS       BIT_1	/* Broadcast Mode Disable */
-#define CB_CFIG_CRS_OR_CDT          BIT_7	/* CRS Or CDT */
-
-/* byte 16 bit definitions -- pre-defined all zeros*/
-#define DFLT_FC_DELAY_LSB  0x1f	/* Delay for outgoing Pause frames */
-#define DFLT_NO_FC_DELAY_LSB  0x00	/* no flow control default value */
-
-/* byte 17 bit definitions -- pre-defined 0x40*/
-#define DFLT_FC_DELAY_MSB  0x01	/* Delay for outgoing Pause frames */
-#define DFLT_NO_FC_DELAY_MSB  0x40	/* no flow control default value */
-
-/* byte 18 bit definitions*/
-#define CB_CFIG_STRIPPING           BIT_0	/* Padding Disabled */
-#define CB_CFIG_PADDING             BIT_1	/* Padding Disabled */
-#define CB_CFIG_CRC_IN_MEM          BIT_2	/* Transfer CRC To Memory */
-
-/* byte 19 bit definitions*/
-#define CB_CFIG_TX_ADDR_WAKE        BIT_0	/* Address Wakeup */
-#define CB_DISABLE_MAGPAK_WAKE      BIT_1	/* Magic Packet Wakeup disable */
-/* Changed TX_FC_EN to TX_FC_DIS because 0 enables, 1 disables. Jul 8, 1999 */
-#define CB_CFIG_TX_FC_DIS           BIT_2	/* Tx Flow Control Disable */
-#define CB_CFIG_FC_RESTOP           BIT_3	/* Rx Flow Control Restop */
-#define CB_CFIG_FC_RESTART          BIT_4	/* Rx Flow Control Restart */
-#define CB_CFIG_FC_REJECT           BIT_5	/* Rx Flow Control Restart */
-#define CB_CFIG_FC_OPTS (CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART | CB_CFIG_FC_REJECT)
-
-/* end 82558/9 specifics */
-
-#define CB_CFIG_FORCE_FDX           BIT_6	/* Force Full Duplex */
-#define CB_CFIG_FDX_ENABLE          BIT_7	/* Full Duplex Enabled */
-
-/* byte 20 bit definitions*/
-#define CB_CFIG_MULTI_IA            BIT_6	/* Multiple IA Addr */
-
-/* byte 21 bit definitions*/
-#define CB_CFIG_MULTICAST_ALL       BIT_3	/* Multicast All */
-
-/* byte 22 bit defines */
-#define CB_CFIG_RECEIVE_GAMLA_MODE  BIT_0	/* D102 receive mode */
-#define CB_CFIG_VLAN_DROP_ENABLE    BIT_1	/* vlan stripping */
-
-#define CB_CFIG_LONG_RX_OK	    BIT_3
-
-#define NO_LOOPBACK	0	
-#define MAC_LOOPBACK	0x01
-#define PHY_LOOPBACK	0x02
-
-/* function prototypes */
-extern void e100_config_init(struct e100_private *bdp);
-extern void e100_config_init_82557(struct e100_private *bdp);
-extern unsigned char e100_force_config(struct e100_private *bdp);
-extern unsigned char e100_config(struct e100_private *bdp);
-extern void e100_config_fc(struct e100_private *bdp);
-extern void e100_config_promisc(struct e100_private *bdp, unsigned char enable);
-extern void e100_config_brdcast_dsbl(struct e100_private *bdp);
-extern void e100_config_mulcast_enbl(struct e100_private *bdp,
-				     unsigned char enable);
-extern void e100_config_ifs(struct e100_private *bdp);
-extern void e100_config_force_dplx(struct e100_private *bdp);
-extern u8 e100_config_loopback_mode(struct e100_private *bdp, u8 mode);
-extern u8 e100_config_dynamic_tbd(struct e100_private *bdp, u8 enable);
-extern u8 e100_config_tcb_ext_enable(struct e100_private *bdp, u8 enable);
-extern void e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable);
-#endif /* _E100_CONFIG_INC_ */
diff -Nru a/drivers/net/e100/e100_eeprom.c b/drivers/net/e100/e100_eeprom.c
--- a/drivers/net/e100/e100_eeprom.c	Wed Feb 11 22:30:57 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,565 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-/**********************************************************************
-*                                                                     *
-* INTEL CORPORATION                                                   *
-*                                                                     *
-* This software is supplied under the terms of the license included   *
-* above.  All use of this driver must be in accordance with the terms *
-* of that license.                                                    *
-*                                                                     *
-* Module Name:  e100_eeprom.c                                         *
-*                                                                     *
-* Abstract:     This module contains routines to read and write to a  *
-*               serial EEPROM                                         *
-*                                                                     *
-* Environment:  This file is intended to be specific to the Linux     *
-*               operating system.                                     *
-*                                                                     *
-**********************************************************************/
-#include "e100.h"
-
-#define CSR_EEPROM_CONTROL_FIELD(bdp) ((bdp)->scb->scb_eprm_cntrl)
-
-#define CSR_GENERAL_CONTROL2_FIELD(bdp) \
-	           ((bdp)->scb->scb_ext.d102_scb.scb_gen_ctrl2)
-
-#define EEPROM_STALL_TIME	4
-#define EEPROM_CHECKSUM		((u16) 0xBABA)
-#define EEPROM_MAX_WORD_SIZE	256
-
-void e100_eeprom_cleanup(struct e100_private *adapter);
-u16 e100_eeprom_calculate_chksum(struct e100_private *adapter);
-static void e100_eeprom_write_word(struct e100_private *adapter, u16 reg,
-				   u16 data);
-void e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data,
-			     u16 size);
-u16 e100_eeprom_size(struct e100_private *adapter);
-u16 e100_eeprom_read(struct e100_private *adapter, u16 reg);
-
-static void shift_out_bits(struct e100_private *adapter, u16 data, u16 count);
-static u16 shift_in_bits(struct e100_private *adapter);
-static void raise_clock(struct e100_private *adapter, u16 *x);
-static void lower_clock(struct e100_private *adapter, u16 *x);
-static u16 eeprom_wait_cmd_done(struct e100_private *adapter);
-static void eeprom_stand_by(struct e100_private *adapter);
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_set_semaphore
-//
-// Description: This function set (write 1) Gamla EEPROM semaphore bit (bit 23 word 0x1C in the CSR).
-//
-// Arguments:
-//      Adapter                 - Adapter context
-//
-// Returns:  true if success
-//           else return false 
-//
-//----------------------------------------------------------------------------------------
-
-inline u8
-eeprom_set_semaphore(struct e100_private *adapter)
-{
-	u16 data = 0;
-	unsigned long expiration_time = jiffies + HZ / 100 + 1;
-
-	do {
-		// Get current value of General Control 2
-		data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
-
-		// Set bit 23 word 0x1C in the CSR.
-		data |= SCB_GCR2_EEPROM_ACCESS_SEMAPHORE;
-		writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter));
-
-		// Check to see if this bit set or not.
-		data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
-
-		if (data & SCB_GCR2_EEPROM_ACCESS_SEMAPHORE) {
-			return true;
-		}
-
-		if (time_before(jiffies, expiration_time))
-			yield();
-		else
-			return false;
-
-	} while (true);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_reset_semaphore
-//
-// Description: This function reset (write 0) Gamla EEPROM semaphore bit 
-//              (bit 23 word 0x1C in the CSR).
-//
-// Arguments:  struct e100_private * adapter - Adapter context
-//----------------------------------------------------------------------------------------
-
-inline void
-eeprom_reset_semaphore(struct e100_private *adapter)
-{
-	u16 data = 0;
-
-	data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
-	data &= ~(SCB_GCR2_EEPROM_ACCESS_SEMAPHORE);
-	writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter));
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_size
-//
-// Description: This routine determines the size of the EEPROM.  This value should be
-//              checked for validity - ie. is it too big or too small.  The size returned
-//              is then passed to the read/write functions.
-//
-// Returns:
-//      Size of the eeprom, or zero if an error occurred
-//----------------------------------------------------------------------------------------
-u16
-e100_eeprom_size(struct e100_private *adapter)
-{
-	u16 x, size = 1;	// must be one to accumulate a product
-
-	// if we've already stored this data, read from memory
-	if (adapter->eeprom_size) {
-		return adapter->eeprom_size;
-	}
-	// otherwise, read from the eeprom
-	// Set EEPROM semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		if (!eeprom_set_semaphore(adapter))
-			return 0;
-	}
-	// enable the eeprom by setting EECS.
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EEDI | EEDO | EESK);
-	x |= EECS;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	// write the read opcode
-	shift_out_bits(adapter, EEPROM_READ_OPCODE, 3);
-
-	// experiment to discover the size of the eeprom.  request register zero
-	// and wait for the eeprom to tell us it has accepted the entire address.
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	do {
-		size *= 2;	// each bit of address doubles eeprom size
-		x |= EEDO;	// set bit to detect "dummy zero"
-		x &= ~EEDI;	// address consists of all zeros
-
-		writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-		readw(&(adapter->scb->scb_status));
-		udelay(EEPROM_STALL_TIME);
-		raise_clock(adapter, &x);
-		lower_clock(adapter, &x);
-
-		// check for "dummy zero"
-		x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-		if (size > EEPROM_MAX_WORD_SIZE) {
-			size = 0;
-			break;
-		}
-	} while (x & EEDO);
-
-	// read in the value requested
-	(void) shift_in_bits(adapter);
-	e100_eeprom_cleanup(adapter);
-
-	// Clear EEPROM Semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		eeprom_reset_semaphore(adapter);
-	}
-
-	return size;
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_address_size
-//
-// Description: determines the number of bits in an address for the eeprom acceptable
-//              values are 64, 128, and 256
-// Arguments: size of the eeprom
-// Returns: bits in an address for that size eeprom
-//----------------------------------------------------------------------------------------
-
-static inline int
-eeprom_address_size(u16 size)
-{
-	int isize = size;
-	
-	return (ffs(isize) - 1);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_read
-//
-// Description: This routine serially reads one word out of the EEPROM.
-//
-// Arguments:
-//      adapter - our adapter context
-//      reg - EEPROM word to read.
-//
-// Returns:
-//      Contents of EEPROM word (reg).
-//----------------------------------------------------------------------------------------
-
-u16
-e100_eeprom_read(struct e100_private *adapter, u16 reg)
-{
-	u16 x, data, bits;
-
-	// Set EEPROM semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		if (!eeprom_set_semaphore(adapter))
-			return 0;
-	}
-	// eeprom size is initialized to zero
-	if (!adapter->eeprom_size)
-		adapter->eeprom_size = e100_eeprom_size(adapter);
-
-	bits = eeprom_address_size(adapter->eeprom_size);
-
-	// select EEPROM, reset bits, set EECS
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	x &= ~(EEDI | EEDO | EESK);
-	x |= EECS;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	// write the read opcode and register number in that order
-	// The opcode is 3bits in length, reg is 'bits' bits long
-	shift_out_bits(adapter, EEPROM_READ_OPCODE, 3);
-	shift_out_bits(adapter, reg, bits);
-
-	// Now read the data (16 bits) in from the selected EEPROM word
-	data = shift_in_bits(adapter);
-
-	e100_eeprom_cleanup(adapter);
-
-	// Clear EEPROM Semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		eeprom_reset_semaphore(adapter);
-	}
-
-	return data;
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   shift_out_bits
-//
-// Description: This routine shifts data bits out to the EEPROM.
-//
-// Arguments:
-//      data - data to send to the EEPROM.
-//      count - number of data bits to shift out.
-//
-// Returns: (none)
-//----------------------------------------------------------------------------------------
-
-static void
-shift_out_bits(struct e100_private *adapter, u16 data, u16 count)
-{
-	u16 x, mask;
-
-	mask = 1 << (count - 1);
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EEDO | EEDI);
-
-	do {
-		x &= ~EEDI;
-		if (data & mask)
-			x |= EEDI;
-
-		writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-		readw(&(adapter->scb->scb_status)); /* flush command to card */
-		udelay(EEPROM_STALL_TIME);
-		raise_clock(adapter, &x);
-		lower_clock(adapter, &x);
-		mask = mask >> 1;
-	} while (mask);
-
-	x &= ~EEDI;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   raise_clock
-//
-// Description: This routine raises the EEPROM's clock input (EESK)
-//
-// Arguments:
-//      x - Ptr to the EEPROM control register's current value
-//
-// Returns: (none)
-//----------------------------------------------------------------------------------------
-
-void
-raise_clock(struct e100_private *adapter, u16 *x)
-{
-	*x = *x | EESK;
-	writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   lower_clock
-//
-// Description: This routine lower's the EEPROM's clock input (EESK)
-//
-// Arguments:
-//      x - Ptr to the EEPROM control register's current value
-//
-// Returns: (none)
-//----------------------------------------------------------------------------------------
-
-void
-lower_clock(struct e100_private *adapter, u16 *x)
-{
-	*x = *x & ~EESK;
-	writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   shift_in_bits
-//
-// Description: This routine shifts data bits in from the EEPROM.
-//
-// Arguments:
-//
-// Returns:
-//      The contents of that particular EEPROM word
-//----------------------------------------------------------------------------------------
-
-static u16
-shift_in_bits(struct e100_private *adapter)
-{
-	u16 x, d, i;
-
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EEDO | EEDI);
-	d = 0;
-
-	for (i = 0; i < 16; i++) {
-		d <<= 1;
-		raise_clock(adapter, &x);
-
-		x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-
-		x &= ~EEDI;
-		if (x & EEDO)
-			d |= 1;
-
-		lower_clock(adapter, &x);
-	}
-
-	return d;
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_cleanup
-//
-// Description: This routine returns the EEPROM to an idle state
-//----------------------------------------------------------------------------------------
-
-void
-e100_eeprom_cleanup(struct e100_private *adapter)
-{
-	u16 x;
-
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	x &= ~(EECS | EEDI);
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	raise_clock(adapter, &x);
-	lower_clock(adapter, &x);
-}
-
-//**********************************************************************************
-// Procedure:   e100_eeprom_update_chksum
-//
-// Description: Calculates the checksum and writes it to the EEProm. 
-//              It calculates the checksum accroding to the formula: 
-//                              Checksum = 0xBABA - (sum of first 63 words).
-//
-//-----------------------------------------------------------------------------------
-u16
-e100_eeprom_calculate_chksum(struct e100_private *adapter)
-{
-	u16 idx, xsum_index, checksum = 0;
-
-	// eeprom size is initialized to zero
-	if (!adapter->eeprom_size)
-		adapter->eeprom_size = e100_eeprom_size(adapter);
-
-	xsum_index = adapter->eeprom_size - 1;
-	for (idx = 0; idx < xsum_index; idx++)
-		checksum += e100_eeprom_read(adapter, idx);
-
-	checksum = EEPROM_CHECKSUM - checksum;
-	return checksum;
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_write_word
-//
-// Description: This routine writes a word to a specific EEPROM location without.
-//              taking EEPROM semaphore and updating checksum. 
-//              Use e100_eeprom_write_block for the EEPROM update
-// Arguments: reg - The EEPROM word that we are going to write to.
-//            data - The data (word) that we are going to write to the EEPROM.
-//----------------------------------------------------------------------------------------
-static void
-e100_eeprom_write_word(struct e100_private *adapter, u16 reg, u16 data)
-{
-	u16 x;
-	u16 bits;
-
-	bits = eeprom_address_size(adapter->eeprom_size);
-
-	/* select EEPROM, mask off ASIC and reset bits, set EECS */
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EEDI | EEDO | EESK);
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-	x |= EECS;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-
-	shift_out_bits(adapter, EEPROM_EWEN_OPCODE, 5);
-	shift_out_bits(adapter, reg, (u16) (bits - 2));
-	if (!eeprom_wait_cmd_done(adapter))
-		return;
-
-	/* write the new word to the EEPROM & send the write opcode the EEPORM */
-	shift_out_bits(adapter, EEPROM_WRITE_OPCODE, 3);
-
-	/* select which word in the EEPROM that we are writing to */
-	shift_out_bits(adapter, reg, bits);
-
-	/* write the data to the selected EEPROM word */
-	shift_out_bits(adapter, data, 16);
-	if (!eeprom_wait_cmd_done(adapter))
-		return;
-
-	shift_out_bits(adapter, EEPROM_EWDS_OPCODE, 5);
-	shift_out_bits(adapter, reg, (u16) (bits - 2));
-	if (!eeprom_wait_cmd_done(adapter))
-		return;
-
-	e100_eeprom_cleanup(adapter);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   e100_eeprom_write_block
-//
-// Description: This routine writes a block of words starting from specified EEPROM 
-//              location and updates checksum
-// Arguments: reg - The EEPROM word that we are going to write to.
-//            data - The data (word) that we are going to write to the EEPROM.
-//----------------------------------------------------------------------------------------
-void
-e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data,
-			u16 size)
-{
-	u16 checksum;
-	u16 i;
-
-	if (!adapter->eeprom_size)
-		adapter->eeprom_size = e100_eeprom_size(adapter);
-
-	// Set EEPROM semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		if (!eeprom_set_semaphore(adapter))
-			return;
-	}
-
-	for (i = 0; i < size; i++) {
-		e100_eeprom_write_word(adapter, start + i, data[i]);
-	}
-	//Update checksum
-	checksum = e100_eeprom_calculate_chksum(adapter);
-	e100_eeprom_write_word(adapter, (adapter->eeprom_size - 1), checksum);
-
-	// Clear EEPROM Semaphore.
-	if (adapter->rev_id >= D102_REV_ID) {
-		eeprom_reset_semaphore(adapter);
-	}
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_wait_cmd_done
-//
-// Description: This routine waits for the the EEPROM to finish its command.  
-//                              Specifically, it waits for EEDO (data out) to go high.
-// Returns:     true - If the command finished
-//              false - If the command never finished (EEDO stayed low)
-//----------------------------------------------------------------------------------------
-static u16
-eeprom_wait_cmd_done(struct e100_private *adapter)
-{
-	u16 x;
-	unsigned long expiration_time = jiffies + HZ / 100 + 1;
-
-	eeprom_stand_by(adapter);
-
-	do {
-		rmb();
-		x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-		if (x & EEDO)
-			return true;
-		if (time_before(jiffies, expiration_time))
-			yield();
-		else
-			return false;
-	} while (true);
-}
-
-//----------------------------------------------------------------------------------------
-// Procedure:   eeprom_stand_by
-//
-// Description: This routine lowers the EEPROM chip select (EECS) for a few microseconds.
-//----------------------------------------------------------------------------------------
-static void
-eeprom_stand_by(struct e100_private *adapter)
-{
-	u16 x;
-
-	x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
-	x &= ~(EECS | EESK);
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-	x |= EECS;
-	writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
-	readw(&(adapter->scb->scb_status)); /* flush command to card */
-	udelay(EEPROM_STALL_TIME);
-}
diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
--- a/drivers/net/e100/e100_main.c	Wed Feb 11 22:30:57 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,4341 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-/**********************************************************************
-*                                                                     *
-* INTEL CORPORATION                                                   *
-*                                                                     *
-* This software is supplied under the terms of the license included   *
-* above.  All use of this driver must be in accordance with the terms *
-* of that license.                                                    *
-*                                                                     *
-* Module Name:  e100_main.c                                           *
-*                                                                     *
-* Abstract:     Functions for the driver entry points like load,      *
-*               unload, open and close. All board specific calls made *
-*               by the network interface section of the driver.       *
-*                                                                     *
-* Environment:  This file is intended to be specific to the Linux     *
-*               operating system.                                     *
-*                                                                     *
-**********************************************************************/
-
-/* Change Log
- * 
- * 2.3.36       11/13/03
- * o Moved to 2.6 APIs: pci_name() and free_netdev().
- * o Removed some __devinit from some functions that shouldn't be marked
- *   as such (Anton Blanchard [anton@samba.org]).
- * 
- * 2.3.33       10/21/03
- * o Bug fix (Bugzilla 97908): Loading e100 was causing crash on Itanium2
- *   with HP chipset
- * o Bug fix (Bugzilla 101583): e100 can't pass traffic with ipv6
- * o Bug fix (Bugzilla 101360): PRO/10+ can't pass traffic
- * 
- * 2.3.27       08/08/03
- */
- 
-#include <linux/config.h>
-#include <net/checksum.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include "e100.h"
-#include "e100_ucode.h"
-#include "e100_config.h"
-#include "e100_phy.h"
-
-extern void e100_force_speed_duplex_to_phy(struct e100_private *bdp);
-
-static char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
-	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
-	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
-	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
-	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
-	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
-	"tx_heartbeat_errors", "tx_window_errors",
-};
-#define E100_STATS_LEN	sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN
-
-static int e100_do_ethtool_ioctl(struct net_device *, struct ifreq *);
-static void e100_get_speed_duplex_caps(struct e100_private *);
-static int e100_ethtool_get_settings(struct net_device *, struct ifreq *);
-static int e100_ethtool_set_settings(struct net_device *, struct ifreq *);
-
-static int e100_ethtool_get_drvinfo(struct net_device *, struct ifreq *);
-static int e100_ethtool_eeprom(struct net_device *, struct ifreq *);
-
-#define E100_EEPROM_MAGIC 0x1234
-static int e100_ethtool_glink(struct net_device *, struct ifreq *);
-static int e100_ethtool_gregs(struct net_device *, struct ifreq *);
-static int e100_ethtool_nway_rst(struct net_device *, struct ifreq *);
-static int e100_ethtool_wol(struct net_device *, struct ifreq *);
-#ifdef CONFIG_PM
-static unsigned char e100_setup_filter(struct e100_private *bdp);
-static void e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp);
-#endif
-static u16 e100_get_ip_lbytes(struct net_device *dev);
-extern void e100_config_wol(struct e100_private *bdp);
-extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags);
-static int e100_ethtool_test(struct net_device *, struct ifreq *);
-static int e100_ethtool_gstrings(struct net_device *, struct ifreq *);
-static char test_strings[][ETH_GSTRING_LEN] = {
-	"Link test     (on/offline)",
-	"Eeprom test   (on/offline)",
-	"Self test        (offline)",
-	"Mac loopback     (offline)",
-	"Phy loopback     (offline)",
-	"Cable diagnostic (offline)"
-};
-
-static int e100_ethtool_led_blink(struct net_device *, struct ifreq *);
-
-static int e100_mii_ioctl(struct net_device *, struct ifreq *, int);
-
-static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *,
-						  nxmit_cb_entry_t *);
-static void e100_free_nontx_list(struct e100_private *);
-static void e100_non_tx_background(unsigned long);
-static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
-/* Global Data structures and variables */
-char e100_copyright[] = "Copyright (c) 2003 Intel Corporation";
-char e100_driver_version[]="2.3.36-k1";
-const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
-char e100_short_driver_name[] = "e100";
-static int e100nics = 0;
-static void e100_vlan_rx_register(struct net_device *netdev, struct vlan_group
-		*grp);
-static void e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
-static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
-
-#ifdef CONFIG_PM
-static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
-static int e100_suspend(struct pci_dev *pcid, u32 state);
-static int e100_resume(struct pci_dev *pcid);
-static unsigned char e100_asf_enabled(struct e100_private *bdp);
-struct notifier_block e100_notifier_reboot = {
-        .notifier_call  = e100_notify_reboot,
-        .next           = NULL,
-        .priority       = 0
-};
-#endif
-
-/*********************************************************************/
-/*! This is a GCC extension to ANSI C.
- *  See the item "Labeled Elements in Initializers" in the section
- *  "Extensions to the C Language Family" of the GCC documentation.
- *********************************************************************/
-#define E100_PARAM_INIT { [0 ... E100_MAX_NIC] = -1 }
-
-/* All parameters are treated the same, as an integer array of values.
- * This macro just reduces the need to repeat the same declaration code
- * over and over (plus this helps to avoid typo bugs).
- */
-#define E100_PARAM(X, S)                                        \
-        static const int X[E100_MAX_NIC + 1] = E100_PARAM_INIT; \
-        MODULE_PARM(X, "1-" __MODULE_STRING(E100_MAX_NIC) "i"); \
-        MODULE_PARM_DESC(X, S);
-
-/* ====================================================================== */
-static u8 e100_D101M_checksum(struct e100_private *, struct sk_buff *);
-static u8 e100_D102_check_checksum(rfd_t *);
-static int e100_ioctl(struct net_device *, struct ifreq *, int);
-static int e100_change_mtu(struct net_device *, int);
-static int e100_xmit_frame(struct sk_buff *, struct net_device *);
-static unsigned char e100_init(struct e100_private *);
-static int e100_set_mac(struct net_device *, void *);
-struct net_device_stats *e100_get_stats(struct net_device *);
-
-static irqreturn_t e100intr(int, void *, struct pt_regs *);
-static void e100_print_brd_conf(struct e100_private *);
-static void e100_set_multi(struct net_device *);
-
-static u8 e100_pci_setup(struct pci_dev *, struct e100_private *);
-static u8 e100_sw_init(struct e100_private *);
-static void e100_tco_workaround(struct e100_private *);
-static unsigned char e100_alloc_space(struct e100_private *);
-static void e100_dealloc_space(struct e100_private *);
-static int e100_alloc_tcb_pool(struct e100_private *);
-static void e100_setup_tcb_pool(tcb_t *, unsigned int, struct e100_private *);
-static void e100_free_tcb_pool(struct e100_private *);
-static int e100_alloc_rfd_pool(struct e100_private *);
-static void e100_free_rfd_pool(struct e100_private *);
-
-static void e100_rd_eaddr(struct e100_private *);
-static void e100_rd_pwa_no(struct e100_private *);
-extern u16 e100_eeprom_read(struct e100_private *, u16);
-extern void e100_eeprom_write_block(struct e100_private *, u16, u16 *, u16);
-extern u16 e100_eeprom_size(struct e100_private *);
-u16 e100_eeprom_calculate_chksum(struct e100_private *adapter);
-
-static unsigned char e100_clr_cntrs(struct e100_private *);
-static unsigned char e100_load_microcode(struct e100_private *);
-static unsigned char e100_setup_iaaddr(struct e100_private *, u8 *);
-static unsigned char e100_update_stats(struct e100_private *bdp);
-
-static void e100_start_ru(struct e100_private *);
-static void e100_dump_stats_cntrs(struct e100_private *);
-
-static void e100_check_options(int board, struct e100_private *bdp);
-static void e100_set_int_option(int *, int, int, int, int, char *);
-static void e100_set_bool_option(struct e100_private *bdp, int, u32, int,
-				 char *);
-unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8);
-void e100_exec_cmplx(struct e100_private *, u32, u8);
-
-/**
- * e100_get_rx_struct - retrieve cell to hold skb buff from the pool
- * @bdp: atapter's private data struct
- *
- * Returns the new cell to hold sk_buff or %NULL.
- */
-static inline struct rx_list_elem *
-e100_get_rx_struct(struct e100_private *bdp)
-{
-	struct rx_list_elem *rx_struct = NULL;
-
-	if (!list_empty(&(bdp->rx_struct_pool))) {
-		rx_struct = list_entry(bdp->rx_struct_pool.next,
-				       struct rx_list_elem, list_elem);
-		list_del(&(rx_struct->list_elem));
-	}
-
-	return rx_struct;
-}
-
-/**
- * e100_alloc_skb - allocate an skb for the adapter
- * @bdp: atapter's private data struct
- *
- * Allocates skb with enough room for rfd, and data, and reserve non-data space.
- * Returns the new cell with sk_buff or %NULL.
- */
-static inline struct rx_list_elem *
-e100_alloc_skb(struct e100_private *bdp)
-{
-	struct sk_buff *new_skb;
-	u32 skb_size = sizeof (rfd_t);
-	struct rx_list_elem *rx_struct;
-
-	new_skb = (struct sk_buff *) dev_alloc_skb(skb_size);
-	if (new_skb) {
-		/* The IP data should be 
-		   DWORD aligned. since the ethernet header is 14 bytes long, 
-		   we need to reserve 2 extra bytes so that the TCP/IP headers
-		   will be DWORD aligned. */
-		skb_reserve(new_skb, 2);
-		if ((rx_struct = e100_get_rx_struct(bdp)) == NULL)
-			goto err;
-		rx_struct->skb = new_skb;
-		rx_struct->dma_addr = pci_map_single(bdp->pdev, new_skb->data,
-						     sizeof (rfd_t),
-						     PCI_DMA_FROMDEVICE);
-		if (!rx_struct->dma_addr)
-			goto err;
-		skb_reserve(new_skb, bdp->rfd_size);
-		return rx_struct;
-	} else {
-		return NULL;
-	}
-
-err:
-	dev_kfree_skb_irq(new_skb);
-	return NULL;
-}
-
-/**
- * e100_add_skb_to_end - add an skb to the end of our rfd list
- * @bdp: atapter's private data struct
- * @rx_struct: rx_list_elem with the new skb
- *
- * Adds a newly allocated skb to the end of our rfd list.
- */
-inline void
-e100_add_skb_to_end(struct e100_private *bdp, struct rx_list_elem *rx_struct)
-{
-	rfd_t *rfdn;		/* The new rfd */
-	rfd_t *rfd;		/* The old rfd */
-	struct rx_list_elem *rx_struct_last;
-
-	(rx_struct->skb)->dev = bdp->device;
-	rfdn = RFD_POINTER(rx_struct->skb, bdp);
-	rfdn->rfd_header.cb_status = 0;
-	rfdn->rfd_header.cb_cmd = __constant_cpu_to_le16(RFD_EL_BIT);
-	rfdn->rfd_act_cnt = 0;
-	rfdn->rfd_sz = __constant_cpu_to_le16(RFD_DATA_SIZE);
-
-	pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, bdp->rfd_size,
-			    PCI_DMA_TODEVICE);
-
-	if (!list_empty(&(bdp->active_rx_list))) {
-		rx_struct_last = list_entry(bdp->active_rx_list.prev,
-					    struct rx_list_elem, list_elem);
-		rfd = RFD_POINTER(rx_struct_last->skb, bdp);
-		pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr,
-				    4, PCI_DMA_FROMDEVICE);
-		put_unaligned(cpu_to_le32(rx_struct->dma_addr),
-			      ((u32 *) (&(rfd->rfd_header.cb_lnk_ptr))));
-
-		pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr,
-				    8, PCI_DMA_TODEVICE);
-		rfd->rfd_header.cb_cmd &=
-			__constant_cpu_to_le16((u16) ~RFD_EL_BIT);
-
-		pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr,
-				    4, PCI_DMA_TODEVICE);
-	}
-
-	list_add_tail(&(rx_struct->list_elem), &(bdp->active_rx_list));
-}
-
-static inline void
-e100_alloc_skbs(struct e100_private *bdp)
-{
-	for (; bdp->skb_req > 0; bdp->skb_req--) {
-		struct rx_list_elem *rx_struct;
-
-		if ((rx_struct = e100_alloc_skb(bdp)) == NULL)
-			return;
-
-		e100_add_skb_to_end(bdp, rx_struct);
-	}
-}
-
-void e100_tx_srv(struct e100_private *);
-u32 e100_rx_srv(struct e100_private *);
-
-void e100_watchdog(struct net_device *);
-void e100_refresh_txthld(struct e100_private *);
-void e100_manage_adaptive_ifs(struct e100_private *);
-void e100_clear_pools(struct e100_private *);
-static void e100_clear_structs(struct net_device *);
-static inline tcb_t *e100_prepare_xmit_buff(struct e100_private *,
-					    struct sk_buff *);
-static void e100_set_multi_exec(struct net_device *dev);
-
-MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
-MODULE_DESCRIPTION("Intel(R) PRO/100 Network Driver");
-MODULE_LICENSE("GPL");
-
-E100_PARAM(TxDescriptors, "Number of transmit descriptors");
-E100_PARAM(RxDescriptors, "Number of receive descriptors");
-E100_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
-E100_PARAM(e100_speed_duplex, "Speed and Duplex settings");
-E100_PARAM(ucode, "Disable or enable microcode loading");
-E100_PARAM(ber, "Value for the BER correction algorithm");
-E100_PARAM(flow_control, "Disable or enable Ethernet PAUSE frames processing");
-E100_PARAM(IntDelay, "Value for CPU saver's interrupt delay");
-E100_PARAM(BundleSmallFr, "Disable or enable interrupt bundling of small frames");
-E100_PARAM(BundleMax, "Maximum number for CPU saver's packet bundling");
-E100_PARAM(IFS, "Disable or enable the adaptive IFS algorithm");
-
-/**
- * e100_exec_cmd - issue a comand
- * @bdp: atapter's private data struct
- * @scb_cmd_low: the command that is to be issued
- *
- * This general routine will issue a command to the e100.
- */
-static inline void
-e100_exec_cmd(struct e100_private *bdp, u8 cmd_low)
-{
-	writeb(cmd_low, &(bdp->scb->scb_cmd_low));
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-}
-
-/**
- * e100_wait_scb - wait for SCB to clear
- * @bdp: atapter's private data struct
- *
- * This routine checks to see if the e100 has accepted a command.
- * It does so by checking the command field in the SCB, which will
- * be zeroed by the e100 upon accepting a command.  The loop waits
- * for up to 1 millisecond for command acceptance.
- *
- * Returns:
- *      true if the SCB cleared within 1 millisecond.
- *      false if it didn't clear within 1 millisecond
- */
-unsigned char
-e100_wait_scb(struct e100_private *bdp)
-{
-	int i;
-
-	/* loop on the scb for a few times */
-	for (i = 0; i < 100; i++) {
-		if (!readb(&bdp->scb->scb_cmd_low))
-			return true;
-		cpu_relax();
-	}
-
-	/* it didn't work. do it the slow way using udelay()s */
-	for (i = 0; i < E100_MAX_SCB_WAIT; i++) {
-		if (!readb(&bdp->scb->scb_cmd_low))
-			return true;
-		cpu_relax();
-		udelay(1);
-	}
-
-	return false;
-}
-
-/**
- * e100_wait_exec_simple - issue a command
- * @bdp: atapter's private data struct
- * @scb_cmd_low: the command that is to be issued
- *
- * This general routine will issue a command to the e100 after waiting for
- * the previous command to finish.
- *
- * Returns:
- *      true if the command was issued to the chip successfully
- *      false if the command was not issued to the chip
- */
-inline unsigned char
-e100_wait_exec_simple(struct e100_private *bdp, u8 scb_cmd_low)
-{
-	if (!e100_wait_scb(bdp)) {
-		printk(KERN_DEBUG "e100: %s: e100_wait_exec_simple: failed\n",
-		       bdp->device->name);
-#ifdef E100_CU_DEBUG		
-		printk(KERN_ERR "e100: %s: Last command (%x/%x) "
-			"timeout\n", bdp->device->name, 
-			bdp->last_cmd, bdp->last_sub_cmd);
-		printk(KERN_ERR "e100: %s: Current simple command (%x) "
-			"can't be executed\n", 
-			bdp->device->name, scb_cmd_low);
-#endif		
-		return false;
-	}
-	e100_exec_cmd(bdp, scb_cmd_low);
-#ifdef E100_CU_DEBUG	
-	bdp->last_cmd = scb_cmd_low;
-	bdp->last_sub_cmd = 0;
-#endif	
-	return true;
-}
-
-void
-e100_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd)
-{
-	writel(phys_addr, &(bdp->scb->scb_gen_ptr));
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-	e100_exec_cmd(bdp, cmd);
-}
-
-unsigned char
-e100_wait_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd, u8 sub_cmd)
-{
-	if (!e100_wait_scb(bdp)) {
-#ifdef E100_CU_DEBUG		
-		printk(KERN_ERR "e100: %s: Last command (%x/%x) "
-			"timeout\n", bdp->device->name, 
-			bdp->last_cmd, bdp->last_sub_cmd);
-		printk(KERN_ERR "e100: %s: Current complex command "
-			"(%x/%x) can't be executed\n", 
-			bdp->device->name, cmd, sub_cmd);
-#endif		
-		return false;
-	}
-	e100_exec_cmplx(bdp, phys_addr, cmd);
-#ifdef E100_CU_DEBUG	
-	bdp->last_cmd = cmd;
-	bdp->last_sub_cmd = sub_cmd;
-#endif	
-	return true;
-}
-
-inline u8
-e100_wait_cus_idle(struct e100_private *bdp)
-{
-	int i;
-
-	/* loop on the scb for a few times */
-	for (i = 0; i < 100; i++) {
-		if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) !=
-		     SCB_CUS_ACTIVE)) {
-			return true;
-		}
-		cpu_relax();
-	}
-
-	for (i = 0; i < E100_MAX_CU_IDLE_WAIT; i++) {
-		if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) !=
-		     SCB_CUS_ACTIVE)) {
-			return true;
-		}
-		cpu_relax();
-		udelay(1);
-	}
-
-	return false;
-}
-
-/**
- * e100_disable_clear_intr - disable and clear/ack interrupts
- * @bdp: atapter's private data struct
- *
- * This routine disables interrupts at the hardware, by setting
- * the M (mask) bit in the adapter's CSR SCB command word.
- * It also clear/ack interrupts.
- */
-static inline void
-e100_disable_clear_intr(struct e100_private *bdp)
-{
-	u16 intr_status;
-	/* Disable interrupts on our PCI board by setting the mask bit */
-	writeb(SCB_INT_MASK, &bdp->scb->scb_cmd_hi);
-	intr_status = readw(&bdp->scb->scb_status);
-	/* ack and clear intrs */
-	writew(intr_status, &bdp->scb->scb_status);
-	readw(&bdp->scb->scb_status);
-}
-
-/**
- * e100_set_intr_mask - set interrupts
- * @bdp: atapter's private data struct
- *
- * This routine sets interrupts at the hardware, by resetting
- * the M (mask) bit in the adapter's CSR SCB command word
- */
-static inline void
-e100_set_intr_mask(struct e100_private *bdp)
-{
-	writeb(bdp->intr_mask, &bdp->scb->scb_cmd_hi);
-	readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */
-}
-
-static inline void
-e100_trigger_SWI(struct e100_private *bdp)
-{
-	/* Trigger interrupt on our PCI board by asserting SWI bit */
-	writeb(SCB_SOFT_INT, &bdp->scb->scb_cmd_hi);
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-}
-
-static int
-e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
-{
-	static int first_time = true;
-	struct net_device *dev = NULL;
-	struct e100_private *bdp = NULL;
-	int rc = 0;
-	u16 cal_checksum, read_checksum;
-
-	dev = alloc_etherdev(sizeof (struct e100_private));
-	if (dev == NULL) {
-		printk(KERN_ERR "e100: Not able to alloc etherdev struct\n");
-		rc = -ENODEV;
-		goto out;
-	}
-
-	SET_MODULE_OWNER(dev);
-
-	if (first_time) {
-		first_time = false;
-        	printk(KERN_NOTICE "%s - version %s\n",
-	               e100_full_driver_name, e100_driver_version);
-		printk(KERN_NOTICE "%s\n", e100_copyright);
-		printk(KERN_NOTICE "\n");
-	}
-
-	bdp = dev->priv;
-	bdp->pdev = pcid;
-	bdp->device = dev;
-
-	pci_set_drvdata(pcid, dev);
-	SET_NETDEV_DEV(dev, &pcid->dev);
-
-	bdp->flags = 0;
-	bdp->ifs_state = 0;
-	bdp->ifs_value = 0;
-	bdp->scb = 0;
-
-	init_timer(&bdp->nontx_timer_id);
-	bdp->nontx_timer_id.data = (unsigned long) bdp;
-	bdp->nontx_timer_id.function = (void *) &e100_non_tx_background;
-	INIT_LIST_HEAD(&(bdp->non_tx_cmd_list));
-	bdp->non_tx_command_state = E100_NON_TX_IDLE;
-
-	init_timer(&bdp->watchdog_timer);
-	bdp->watchdog_timer.data = (unsigned long) dev;
-	bdp->watchdog_timer.function = (void *) &e100_watchdog;
-
-	if ((rc = e100_pci_setup(pcid, bdp)) != 0) {
-		goto err_dev;
-	}
-
-	if ((rc = e100_alloc_space(bdp)) != 0) {
-		goto err_pci;
-	}
-
-	if (((bdp->pdev->device > 0x1030)
-	       && (bdp->pdev->device < 0x103F))
-	    || ((bdp->pdev->device >= 0x1050)
-	       && (bdp->pdev->device <= 0x1057))
-	    || (bdp->pdev->device == 0x2449)
-	    || (bdp->pdev->device == 0x2459)
-	    || (bdp->pdev->device == 0x245D)) {
-		bdp->rev_id = D101MA_REV_ID;	/* workaround for ICH3 */
-		bdp->flags |= IS_ICH;
-	}
-
-	if (bdp->rev_id == 0xff)
-		bdp->rev_id = 1;
-
-	if ((u8) bdp->rev_id >= D101A4_REV_ID)
-		bdp->flags |= IS_BACHELOR;
-
-	if ((u8) bdp->rev_id >= D102_REV_ID) {
-		bdp->flags |= USE_IPCB;
-		bdp->rfd_size = 32;
-	} else {
-		bdp->rfd_size = 16;
-	}
-
-	dev->vlan_rx_register = e100_vlan_rx_register;
-	dev->vlan_rx_add_vid = e100_vlan_rx_add_vid;
-	dev->vlan_rx_kill_vid = e100_vlan_rx_kill_vid;
-	dev->irq = pcid->irq;
-	dev->open = &e100_open;
-	dev->hard_start_xmit = &e100_xmit_frame;
-	dev->stop = &e100_close;
-	dev->change_mtu = &e100_change_mtu;
-	dev->get_stats = &e100_get_stats;
-	dev->set_multicast_list = &e100_set_multi;
-	dev->set_mac_address = &e100_set_mac;
-	dev->do_ioctl = &e100_ioctl;
-
-	if (bdp->flags & USE_IPCB)
-	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-		
-	if ((rc = register_netdev(dev)) != 0) {
-		goto err_dealloc;
-	}
-
-	e100_check_options(e100nics, bdp);
-
-	if (!e100_init(bdp)) {
-		printk(KERN_ERR "e100: Failed to initialize, instance #%d\n",
-		       e100nics);
-		rc = -ENODEV;
-		goto err_unregister_netdev;
-	}
-
-	/* Check if checksum is valid */
-	cal_checksum = e100_eeprom_calculate_chksum(bdp);
-	read_checksum = e100_eeprom_read(bdp, (bdp->eeprom_size - 1));
-	if (cal_checksum != read_checksum) {
-                printk(KERN_ERR "e100: Corrupted EEPROM on instance #%d\n",
-		       e100nics);
-                rc = -ENODEV;
-                goto err_unregister_netdev;
-	}
-	
-	e100nics++;
-
-	e100_get_speed_duplex_caps(bdp);
-
-	printk(KERN_NOTICE
-	       "e100: %s: %s\n", 
-	       bdp->device->name, "Intel(R) PRO/100 Network Connection");
-	e100_print_brd_conf(bdp);
-
-	bdp->wolsupported = 0;
-	bdp->wolopts = 0;
-	if (bdp->rev_id >= D101A4_REV_ID)
-		bdp->wolsupported = WAKE_PHY | WAKE_MAGIC;
-	if (bdp->rev_id >= D101MA_REV_ID)
-		bdp->wolsupported |= WAKE_UCAST | WAKE_ARP;
-	
-	/* Check if WoL is enabled on EEPROM */
-	if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) {
-		/* Magic Packet WoL is enabled on device by default */
-		/* if EEPROM WoL bit is TRUE                        */
-		bdp->wolopts = WAKE_MAGIC;
-	}
-
-	printk(KERN_NOTICE "\n");
-
-	goto out;
-
-err_unregister_netdev:
-	unregister_netdev(dev);
-err_dealloc:
-	e100_dealloc_space(bdp);
-err_pci:
-	iounmap(bdp->scb);
-	pci_release_regions(pcid);
-	pci_disable_device(pcid);
-err_dev:
-	pci_set_drvdata(pcid, NULL);
-	free_netdev(dev);
-out:
-	return rc;
-}
-
-/**
- * e100_clear_structs - free resources
- * @dev: adapter's net_device struct
- *
- * Free all device specific structs, unmap i/o address, etc.
- */
-static void __devexit
-e100_clear_structs(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-
-	iounmap(bdp->scb);
-	pci_release_regions(bdp->pdev);
-	pci_disable_device(bdp->pdev);
-
-	e100_dealloc_space(bdp);
-	pci_set_drvdata(bdp->pdev, NULL);
-	free_netdev(dev);
-}
-
-static void __devexit
-e100_remove1(struct pci_dev *pcid)
-{
-	struct net_device *dev;
-	struct e100_private *bdp;
-
-	if (!(dev = (struct net_device *) pci_get_drvdata(pcid)))
-		return;
-
-	bdp = dev->priv;
-
-	unregister_netdev(dev);
-
-	e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
-
-	if (bdp->non_tx_command_state != E100_NON_TX_IDLE) {
-		del_timer_sync(&bdp->nontx_timer_id);
-		e100_free_nontx_list(bdp);
-		bdp->non_tx_command_state = E100_NON_TX_IDLE;
-	}
-
-	e100_clear_structs(dev);
-
-	--e100nics;
-}
-
-static struct pci_device_id e100_id_table[] = {
-	{0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-  	{0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },	
-	{0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 
-	{0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 
-	{0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 
-	{0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0,} /* This has to be the last entry*/
-};
-MODULE_DEVICE_TABLE(pci, e100_id_table);
-
-static struct pci_driver e100_driver = {
-	.name         = "e100",
-	.id_table     = e100_id_table,
-	.probe        = e100_found1,
-	.remove       = __devexit_p(e100_remove1),
-#ifdef CONFIG_PM
-	.suspend      = e100_suspend,
-	.resume       = e100_resume,
-#endif
-};
-
-static int __init
-e100_init_module(void)
-{
-	int ret;
-        ret = pci_module_init(&e100_driver);
-
-	if(ret >= 0) {
-#ifdef CONFIG_PM
-		register_reboot_notifier(&e100_notifier_reboot);
-#endif 
-	}
-
-	return ret;
-}
-
-static void __exit
-e100_cleanup_module(void)
-{
-#ifdef CONFIG_PM	
-	unregister_reboot_notifier(&e100_notifier_reboot);
-#endif 
-
-	pci_unregister_driver(&e100_driver);
-}
-
-module_init(e100_init_module);
-module_exit(e100_cleanup_module);
-
-/**
- * e100_check_options - check command line options
- * @board: board number
- * @bdp: atapter's private data struct
- *
- * This routine does range checking on command-line options
- */
-void
-e100_check_options(int board, struct e100_private *bdp)
-{
-	if (board >= E100_MAX_NIC) {
-		printk(KERN_NOTICE 
-		       "e100: No configuration available for board #%d\n",
-		       board);
-		printk(KERN_NOTICE "e100: Using defaults for all values\n");
-		board = E100_MAX_NIC;
-	}
-
-	e100_set_int_option(&(bdp->params.TxDescriptors), TxDescriptors[board],
-			    E100_MIN_TCB, E100_MAX_TCB, E100_DEFAULT_TCB,
-			    "TxDescriptor count");
-
-	e100_set_int_option(&(bdp->params.RxDescriptors), RxDescriptors[board],
-			    E100_MIN_RFD, E100_MAX_RFD, E100_DEFAULT_RFD,
-			    "RxDescriptor count");
-
-	e100_set_int_option(&(bdp->params.e100_speed_duplex),
-			    e100_speed_duplex[board], 0, 4,
-			    E100_DEFAULT_SPEED_DUPLEX, "speed/duplex mode");
-
-	e100_set_int_option(&(bdp->params.ber), ber[board], 0, ZLOCK_MAX_ERRORS,
-			    E100_DEFAULT_BER, "Bit Error Rate count");
-
-	e100_set_bool_option(bdp, XsumRX[board], PRM_XSUMRX, E100_DEFAULT_XSUM,
-			     "XsumRX value");
-
-	/* Default ucode value depended on controller revision */
-	if (bdp->rev_id >= D101MA_REV_ID) {
-		e100_set_bool_option(bdp, ucode[board], PRM_UCODE,
-				     E100_DEFAULT_UCODE, "ucode value");
-	} else {
-		e100_set_bool_option(bdp, ucode[board], PRM_UCODE, false,
-				     "ucode value");
-	}
-
-	e100_set_bool_option(bdp, flow_control[board], PRM_FC, E100_DEFAULT_FC,
-			     "flow control value");
-
-	e100_set_bool_option(bdp, IFS[board], PRM_IFS, E100_DEFAULT_IFS,
-			     "IFS value");
-
-	e100_set_bool_option(bdp, BundleSmallFr[board], PRM_BUNDLE_SMALL,
-			     E100_DEFAULT_BUNDLE_SMALL_FR,
-			     "CPU saver bundle small frames value");
-
-	e100_set_int_option(&(bdp->params.IntDelay), IntDelay[board], 0x0,
-			    0xFFFF, E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY,
-			    "CPU saver interrupt delay value");
-
-	e100_set_int_option(&(bdp->params.BundleMax), BundleMax[board], 0x1,
-			    0xFFFF, E100_DEFAULT_CPUSAVER_BUNDLE_MAX,
-			    "CPU saver bundle max value");
-
-}
-
-/**
- * e100_set_int_option - check and set an integer option
- * @option: a pointer to the relevant option field
- * @val: the value specified
- * @min: the minimum valid value
- * @max: the maximum valid value
- * @default_val: the default value
- * @name: the name of the option
- *
- * This routine does range checking on a command-line option.
- * If the option's value is '-1' use the specified default.
- * Otherwise, if the value is invalid, change it to the default.
- */
-void
-e100_set_int_option(int *option, int val, int min, int max, int default_val,
-		    char *name)
-{
-	if (val == -1) {	/* no value specified. use default */
-		*option = default_val;
-
-	} else if ((val < min) || (val > max)) {
-		printk(KERN_NOTICE
-		       "e100: Invalid %s specified (%i). "
-		       "Valid range is %i-%i\n",
-		       name, val, min, max);
-		printk(KERN_NOTICE "e100: Using default %s of %i\n", name,
-		       default_val);
-		*option = default_val;
-	} else {
-		printk(KERN_INFO "e100: Using specified %s of %i\n", name, val);
-		*option = val;
-	}
-}
-
-/**
- * e100_set_bool_option - check and set a boolean option
- * @bdp: atapter's private data struct
- * @val: the value specified
- * @mask: the mask for the relevant option
- * @default_val: the default value
- * @name: the name of the option
- *
- * This routine checks a boolean command-line option.
- * If the option's value is '-1' use the specified default.
- * Otherwise, if the value is invalid (not 0 or 1), 
- * change it to the default.
- */
-void
-e100_set_bool_option(struct e100_private *bdp, int val, u32 mask,
-		     int default_val, char *name)
-{
-	if (val == -1) {
-		if (default_val)
-			bdp->params.b_params |= mask;
-
-	} else if ((val != true) && (val != false)) {
-		printk(KERN_NOTICE
-		       "e100: Invalid %s specified (%i). "
-		       "Valid values are %i/%i\n",
-		       name, val, false, true);
-		printk(KERN_NOTICE "e100: Using default %s of %i\n", name,
-		       default_val);
-
-		if (default_val)
-			bdp->params.b_params |= mask;
-	} else {
-		printk(KERN_INFO "e100: Using specified %s of %i\n", name, val);
-		if (val)
-			bdp->params.b_params |= mask;
-	}
-}
-
-int
-e100_open(struct net_device *dev)
-{
-	struct e100_private *bdp;
-	int rc = 0;
-
-	bdp = dev->priv;
-
-	/* setup the tcb pool */
-	if (!e100_alloc_tcb_pool(bdp)) {
-		rc = -ENOMEM;
-		goto err_exit;
-	}
-	bdp->last_tcb = NULL;
-
-	bdp->tcb_pool.head = 0;
-	bdp->tcb_pool.tail = 1;	
-
-	e100_setup_tcb_pool((tcb_t *) bdp->tcb_pool.data,
-			    bdp->params.TxDescriptors, bdp);
-
-	if (!e100_alloc_rfd_pool(bdp)) {
-		rc = -ENOMEM;
-		goto err_exit;
-	}
-
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) {
-		rc = -EAGAIN;
-		goto err_exit;
-	}
-
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) {
-		rc = -EAGAIN;
-		goto err_exit;
-	}
-
-	mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));
-
-	if (dev->flags & IFF_UP)
-		/* Otherwise process may sleep forever */
-		netif_wake_queue(dev);
-	else
-		netif_start_queue(dev);
-
-	e100_start_ru(bdp);
-	if ((rc = request_irq(dev->irq, &e100intr, SA_SHIRQ,
-			      dev->name, dev)) != 0) {
-		del_timer_sync(&bdp->watchdog_timer);
-		goto err_exit;
-	}
-	bdp->intr_mask = 0;
-	e100_set_intr_mask(bdp);
-
-	e100_force_config(bdp);
-
-	goto exit;
-
-err_exit:
-	e100_clear_pools(bdp);
-exit:
-	return rc;
-}
-
-int
-e100_close(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-
-	e100_disable_clear_intr(bdp);
-	free_irq(dev->irq, dev);
-	bdp->intr_mask = SCB_INT_MASK;
-	e100_isolate_driver(bdp);
-
-	netif_carrier_off(bdp->device);
-	bdp->cur_line_speed = 0;
-	bdp->cur_dplx_mode = 0;
-	e100_clear_pools(bdp);
-
-	return 0;
-}
-
-static int
-e100_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if ((new_mtu < 68) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE)))
-		return -EINVAL;
-
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-static int
-e100_xmit_frame(struct sk_buff *skb, struct net_device *dev)
-{
-	int rc = 0;
-	int notify_stop = false;
-	struct e100_private *bdp = dev->priv;
-
-	if (!spin_trylock(&bdp->bd_non_tx_lock)) {
-		notify_stop = true;
-		rc = 1;
-		goto exit2;
-	}
-
-	/* tcb list may be empty temporarily during releasing resources */
-	if (!TCBS_AVAIL(bdp->tcb_pool) || (bdp->tcb_phys == 0) ||
-	    (bdp->non_tx_command_state != E100_NON_TX_IDLE)) {
-		notify_stop = true;
-		rc = 1;
-		goto exit1;
-	}
-
-	bdp->drv_stats.net_stats.tx_bytes += skb->len;
-
-	e100_prepare_xmit_buff(bdp, skb);
-
-	dev->trans_start = jiffies;
-
-exit1:
-	spin_unlock(&bdp->bd_non_tx_lock);
-exit2:
-	if (notify_stop) {
-		netif_stop_queue(dev);
-	}
-
-	return rc;
-}
-
-/**
- * e100_get_stats - get driver statistics
- * @dev: adapter's net_device struct
- *
- * This routine is called when the OS wants the adapter's stats returned.
- * It returns the address of the net_device_stats stucture for the device.
- * If the statistics are currently being updated, then they might be incorrect
- * for a short while. However, since this cannot actually cause damage, no
- * locking is used.
- */
-struct net_device_stats *
-e100_get_stats(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-
-	bdp->drv_stats.net_stats.tx_errors =
-		bdp->drv_stats.net_stats.tx_carrier_errors +
-		bdp->drv_stats.net_stats.tx_aborted_errors;
-
-	bdp->drv_stats.net_stats.rx_errors =
-		bdp->drv_stats.net_stats.rx_crc_errors +
-		bdp->drv_stats.net_stats.rx_frame_errors +
-		bdp->drv_stats.net_stats.rx_length_errors +
-		bdp->drv_stats.rcv_cdt_frames;
-
-	return &(bdp->drv_stats.net_stats);
-}
-
-/**
- * e100_set_mac - set the MAC address
- * @dev: adapter's net_device struct
- * @addr: the new address
- *
- * This routine sets the ethernet address of the board
- * Returns:
- * 0  - if successful
- * -1 - otherwise
- */
-static int
-e100_set_mac(struct net_device *dev, void *addr)
-{
-	struct e100_private *bdp;
-	int rc = -1;
-	struct sockaddr *p_sockaddr = (struct sockaddr *) addr;
-
-	if (!is_valid_ether_addr(p_sockaddr->sa_data))
-		return -EADDRNOTAVAIL;
-	bdp = dev->priv;
-
-	if (e100_setup_iaaddr(bdp, (u8 *) (p_sockaddr->sa_data))) {
-		memcpy(&(dev->dev_addr[0]), p_sockaddr->sa_data, ETH_ALEN);
-		rc = 0;
-	}
-
-	return rc;
-}
-
-static void
-e100_set_multi_exec(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-	mltcst_cb_t *mcast_buff;
-	cb_header_t *cb_hdr;
-	struct dev_mc_list *mc_list;
-	unsigned int i;
-	nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(bdp);
-
-	if (cmd != NULL) {
-		mcast_buff = &((cmd->non_tx_cmd)->ntcb.multicast);
-		cb_hdr = &((cmd->non_tx_cmd)->ntcb.multicast.mc_cbhdr);
-	} else {
-		return;
-	}
-
-	/* initialize the multi cast command */
-	cb_hdr->cb_cmd = __constant_cpu_to_le16(CB_MULTICAST);
-
-	/* now fill in the rest of the multicast command */
-	*(u16 *) (&(mcast_buff->mc_count)) = cpu_to_le16(dev->mc_count * 6);
-	for (i = 0, mc_list = dev->mc_list;
-	     (i < dev->mc_count) && (i < MAX_MULTICAST_ADDRS);
-	     i++, mc_list = mc_list->next) {
-		/* copy into the command */
-		memcpy(&(mcast_buff->mc_addr[i * ETH_ALEN]),
-		       (u8 *) &(mc_list->dmi_addr), ETH_ALEN);
-	}
-
-	if (!e100_exec_non_cu_cmd(bdp, cmd)) {
-		printk(KERN_WARNING "e100: %s: Multicast setup failed\n", 
-		       dev->name);
-	}
-}
-
-/**
- * e100_set_multi - set multicast status
- * @dev: adapter's net_device struct
- *
- * This routine is called to add or remove multicast addresses, and/or to
- * change the adapter's promiscuous state.
- */
-static void
-e100_set_multi(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-	unsigned char promisc_enbl;
-	unsigned char mulcast_enbl;
-
-	promisc_enbl = ((dev->flags & IFF_PROMISC) == IFF_PROMISC);
-	mulcast_enbl = ((dev->flags & IFF_ALLMULTI) ||
-			(dev->mc_count > MAX_MULTICAST_ADDRS));
-
-	e100_config_promisc(bdp, promisc_enbl);
-	e100_config_mulcast_enbl(bdp, mulcast_enbl);
-
-	/* reconfigure the chip if something has changed in its config space */
-	e100_config(bdp);
-
-	if (promisc_enbl || mulcast_enbl) {
-		return;	/* no need for Multicast Cmd */
-	}
-
-	/* get the multicast CB */
-	e100_set_multi_exec(dev);
-}
-
-static int
-e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-
-	switch (cmd) {
-
-	case SIOCETHTOOL:
-		return e100_do_ethtool_ioctl(dev, ifr);
-		break;
-
-	case SIOCGMIIPHY:	/* Get address of MII PHY in use. */
-	case SIOCGMIIREG:	/* Read MII PHY register. */
-	case SIOCSMIIREG:	/* Write to MII PHY register. */
-		return e100_mii_ioctl(dev, ifr, cmd);
-		break;
-
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-
-}
-
-/**
- * e100init - initialize the adapter
- * @bdp: atapter's private data struct
- *
- * This routine is called when this driver is loaded. This is the initialization
- * routine which allocates memory, configures the adapter and determines the
- * system resources.
- *
- * Returns:
- *      true: if successful
- *      false: otherwise
- */
-static unsigned char
-e100_init(struct e100_private *bdp)
-{
-	u32 st_timeout = 0;
-	u32 st_result = 0;
-	e100_sw_init(bdp);
-
-	if (!e100_selftest(bdp, &st_timeout, &st_result)) {
-        	if (st_timeout) {
-			printk(KERN_ERR "e100: selftest timeout\n");
-		} else {
-			printk(KERN_ERR "e100: selftest failed. Results: %x\n",
-					st_result);
-		}
-		return false;
-	}
-	else
-		printk(KERN_DEBUG "e100: selftest OK.\n");
-
-	/* read the MAC address from the eprom */
-	e100_rd_eaddr(bdp);
-	if (!is_valid_ether_addr(bdp->device->dev_addr)) {
-		printk(KERN_ERR "e100: Invalid Ethernet address\n");
-		return false;
-	}
-	/* read NIC's part number */
-	e100_rd_pwa_no(bdp);
-
-	if (!e100_hw_init(bdp))
-		return false;
-	/* Interrupts are enabled after device reset */
-	e100_disable_clear_intr(bdp);
-
-	return true;
-}
-
-/**
- * e100_sw_init - initialize software structs
- * @bdp: atapter's private data struct
- * 
- * This routine initializes all software structures. Sets up the
- * circular structures for the RFD's & TCB's. Allocates the per board
- * structure for storing adapter information. The CSR is also memory 
- * mapped in this routine.
- *
- * Returns :
- *      true: if S/W was successfully initialized
- *      false: otherwise
- */
-static unsigned char
-e100_sw_init(struct e100_private *bdp)
-{
-	bdp->next_cu_cmd = START_WAIT;	// init the next cu state
-
-	/* 
-	 * Set the value for # of good xmits per underrun. the value assigned
-	 * here is an intelligent  suggested default. Nothing magical about it.
-	 */
-	bdp->tx_per_underrun = DEFAULT_TX_PER_UNDERRUN;
-
-	/* get the default transmit threshold value */
-	bdp->tx_thld = TX_THRSHLD;
-
-	/* get the EPROM size */
-	bdp->eeprom_size = e100_eeprom_size(bdp);
-
-	/* Initialize our spinlocks */
-	spin_lock_init(&(bdp->bd_lock));
-	spin_lock_init(&(bdp->bd_non_tx_lock));
-	spin_lock_init(&(bdp->config_lock));
-	spin_lock_init(&(bdp->mdi_access_lock));
-	/* Initialize configuration data */
-	e100_config_init(bdp);
-
-	return 1;
-}
-
-static void
-e100_tco_workaround(struct e100_private *bdp)
-{
-	int i;
-
-	/* Do software reset */
-	e100_sw_reset(bdp, PORT_SOFTWARE_RESET);
-
-	/* Do a dummy LOAD CU BASE command. */
-	/* This gets us out of pre-driver to post-driver. */
-	e100_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE);
-
-	/* Wait 20 msec for reset to take effect */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 50 + 1);
-
-	/* disable interrupts since they are enabled */
-	/* after device reset                        */
-	e100_disable_clear_intr(bdp);
-
-	/* Wait for command to be cleared up to 1 sec */
-	for (i=0; i<100; i++) {
-		if (!readb(&bdp->scb->scb_cmd_low))
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 100 + 1);
-	}
-
-	/* Wait for TCO request bit in PMDR register to be clear */
-	for (i=0; i<50; i++) {
-		if (!(readb(&bdp->scb->scb_ext.d101m_scb.scb_pmdr) & BIT_1))
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 100 + 1);
-	}
-}
-
-/**
- * e100_hw_init - initialized tthe hardware
- * @bdp: atapter's private data struct
- *
- * This routine performs a reset on the adapter, and configures the adapter.
- * This includes configuring the 82557 LAN controller, validating and setting
- * the node address, detecting and configuring the Phy chip on the adapter,
- * and initializing all of the on chip counters.
- *
- * Returns:
- *      true - If the adapter was initialized
- *      false - If the adapter failed initialization
- */
-unsigned char
-e100_hw_init(struct e100_private *bdp)
-{
-	if (!e100_phy_init(bdp))
-		goto err;
-
-	e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
-
-	/* Only 82559 or above needs TCO workaround */
-	if (bdp->rev_id >= D101MA_REV_ID)
-		e100_tco_workaround(bdp);
-
-	/* Load the CU BASE (set to 0, because we use linear mode) */
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0))
-		goto err;
-
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0))
-		goto err;
-
-	/* Load interrupt microcode  */
-	if (e100_load_microcode(bdp)) {
-		bdp->flags |= DF_UCODE_LOADED;
-	}
-
-	if ((u8) bdp->rev_id < D101A4_REV_ID)
-		e100_config_init_82557(bdp);
-		
-	if (!e100_config(bdp))
-		goto err;
-
-	if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr))
-		goto err;
-
-	/* Clear the internal counters */
-	if (!e100_clr_cntrs(bdp))
-		goto err;
-
-	/* Change for 82558 enhancement */
-	/* If 82558/9 and if the user has enabled flow control, set up the
-	 * Flow Control Reg. in the CSR */
-	if ((bdp->flags & IS_BACHELOR)
-	    && (bdp->params.b_params & PRM_FC)) {
-		writeb(DFLT_FC_THLD, &bdp->scb->scb_ext.d101_scb.scb_fc_thld);
-		writeb(DFLT_FC_CMD,
-		       &bdp->scb->scb_ext.d101_scb.scb_fc_xon_xoff);
-	}
-
-	return true;
-err:
-	printk(KERN_ERR "e100: hw init failed\n");
-	return false;
-}
-
-/**
- * e100_setup_tcb_pool - setup TCB circular list
- * @head: Pointer to head of the allocated TCBs
- * @qlen: Number of elements in the queue
- * @bdp: atapter's private data struct
- * 
- * This routine arranges the contigiously allocated TCB's in a circular list.
- * Also does the one time initialization of the TCBs.
- */
-static void
-e100_setup_tcb_pool(tcb_t *head, unsigned int qlen, struct e100_private *bdp)
-{
-	int ele_no;
-	tcb_t *pcurr_tcb;	/* point to current tcb */
-	u32 next_phys;		/* the next phys addr */
-	u16 txcommand = CB_S_BIT | CB_TX_SF_BIT;
-
-	bdp->tx_count = 0;
-	if (bdp->flags & USE_IPCB) {
-		txcommand |= CB_IPCB_TRANSMIT | CB_CID_DEFAULT;
-	} else if (bdp->flags & IS_BACHELOR) {
-		txcommand |= CB_TRANSMIT | CB_CID_DEFAULT;
-	} else {
-		txcommand |= CB_TRANSMIT;
-	}
-
-	for (ele_no = 0, next_phys = bdp->tcb_phys, pcurr_tcb = head;
-	     ele_no < qlen; ele_no++, pcurr_tcb++) {
-
-		/* set the phys addr for this TCB, next_phys has not incr. yet */
-		pcurr_tcb->tcb_phys = next_phys;
-		next_phys += sizeof (tcb_t);
-
-		/* set the link to next tcb */
-		if (ele_no == (qlen - 1))
-			pcurr_tcb->tcb_hdr.cb_lnk_ptr =
-				cpu_to_le32(bdp->tcb_phys);
-		else
-			pcurr_tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(next_phys);
-
-		pcurr_tcb->tcb_hdr.cb_status = 0;
-		pcurr_tcb->tcb_hdr.cb_cmd = cpu_to_le16(txcommand);
-		pcurr_tcb->tcb_cnt = 0;	
-		pcurr_tcb->tcb_thrshld = bdp->tx_thld;	
-		if (ele_no < 2) {
-			pcurr_tcb->tcb_hdr.cb_status =
-				cpu_to_le16(CB_STATUS_COMPLETE);
-		}
-		pcurr_tcb->tcb_tbd_num = 1;
-
-		if (bdp->flags & IS_BACHELOR) {
-			pcurr_tcb->tcb_tbd_ptr =
-				__constant_cpu_to_le32(0xFFFFFFFF);
-		} else {
-			pcurr_tcb->tcb_tbd_ptr =
-				cpu_to_le32(pcurr_tcb->tcb_phys + 0x10);
-		}
-
-		if (bdp->flags & IS_BACHELOR) {
-			pcurr_tcb->tcb_tbd_expand_ptr =
-				cpu_to_le32(pcurr_tcb->tcb_phys + 0x20);
-		} else {
-			pcurr_tcb->tcb_tbd_expand_ptr =
-				cpu_to_le32(pcurr_tcb->tcb_phys + 0x10);
-		}
-		pcurr_tcb->tcb_tbd_dflt_ptr = pcurr_tcb->tcb_tbd_ptr;
-
-		if (bdp->flags & USE_IPCB) {
-			pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[1]);
-			pcurr_tcb->tcbu.ipcb.ip_activation_high =
-				IPCB_IP_ACTIVATION_DEFAULT;
-			pcurr_tcb->tcbu.ipcb.vlan = 0;
-		} else {
-			pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[0]);
-		}
-
-		pcurr_tcb->tcb_skb = NULL;
-	}
-
-	wmb();
-}
-
-/***************************************************************************/
-/***************************************************************************/
-/*       Memory Management Routines                                        */
-/***************************************************************************/
-
-/**
- * e100_alloc_space - allocate private driver data
- * @bdp: atapter's private data struct
- *
- * This routine allocates memory for the driver. Memory allocated is for the
- * selftest and statistics structures.
- *
- * Returns:
- *      0: if the operation was successful
- *      %-ENOMEM: if memory allocation failed
- */
-unsigned char
-e100_alloc_space(struct e100_private *bdp)
-{
-	unsigned long off;
-
-	/* allocate all the dma-able structures in one call:
-	 * selftest results, adapter stats, and non-tx cb commands */
-	if (!(bdp->dma_able =
-	      pci_alloc_consistent(bdp->pdev, sizeof (bd_dma_able_t),
-				   &(bdp->dma_able_phys)))) {
-		goto err;
-	}
-
-	/* now assign the various pointers into the struct we've just allocated */
-	off = offsetof(bd_dma_able_t, selftest);
-
-	bdp->selftest = (self_test_t *) (bdp->dma_able + off);
-	bdp->selftest_phys = bdp->dma_able_phys + off;
-
-	off = offsetof(bd_dma_able_t, stats_counters);
-
-	bdp->stats_counters = (max_counters_t *) (bdp->dma_able + off);
-	bdp->stat_cnt_phys = bdp->dma_able_phys + off;
-
-	return 0;
-
-err:
-	printk(KERN_ERR
-	       "e100: Failed to allocate memory\n");
-	return -ENOMEM;
-}
-
-/**
- * e100_alloc_tcb_pool - allocate TCB circular list
- * @bdp: atapter's private data struct
- *
- * This routine allocates memory for the circular list of transmit descriptors.
- *
- * Returns:
- *       0: if allocation has failed.
- *       1: Otherwise. 
- */
-int
-e100_alloc_tcb_pool(struct e100_private *bdp)
-{
-	int stcb = sizeof (tcb_t) * bdp->params.TxDescriptors;
-
-	/* allocate space for the TCBs */
-	if (!(bdp->tcb_pool.data =
-	      pci_alloc_consistent(bdp->pdev, stcb, &bdp->tcb_phys)))
-		return 0;
-
-	memset(bdp->tcb_pool.data, 0x00, stcb);
-
-	return 1;
-}
-
-void
-e100_free_tcb_pool(struct e100_private *bdp)
-{
-	tcb_t *tcb;
-	int i;
-	/* Return tx skbs */ 
-	for (i = 0; i < bdp->params.TxDescriptors; i++) {
-	  	tcb = bdp->tcb_pool.data;
-		tcb += bdp->tcb_pool.head;
-  		e100_tx_skb_free(bdp, tcb);
-		if (NEXT_TCB_TOUSE(bdp->tcb_pool.head) == bdp->tcb_pool.tail)
-		  	break;
-		bdp->tcb_pool.head = NEXT_TCB_TOUSE(bdp->tcb_pool.head);
-	}
-	pci_free_consistent(bdp->pdev,
-			    sizeof (tcb_t) * bdp->params.TxDescriptors,
-			    bdp->tcb_pool.data, bdp->tcb_phys);
-	bdp->tcb_pool.head = 0;
-	bdp->tcb_pool.tail = 1;	
-	bdp->tcb_phys = 0;
-}
-
-static void
-e100_dealloc_space(struct e100_private *bdp)
-{
-	if (bdp->dma_able) {
-		pci_free_consistent(bdp->pdev, sizeof (bd_dma_able_t),
-				    bdp->dma_able, bdp->dma_able_phys);
-	}
-
-	bdp->selftest_phys = 0;
-	bdp->stat_cnt_phys = 0;
-	bdp->dma_able_phys = 0;
-	bdp->dma_able = 0;
-}
-
-static void
-e100_free_rfd_pool(struct e100_private *bdp)
-{
-	struct rx_list_elem *rx_struct;
-
-	while (!list_empty(&(bdp->active_rx_list))) {
-
-		rx_struct = list_entry(bdp->active_rx_list.next,
-				       struct rx_list_elem, list_elem);
-		list_del(&(rx_struct->list_elem));
-		pci_unmap_single(bdp->pdev, rx_struct->dma_addr,
-				 sizeof (rfd_t), PCI_DMA_TODEVICE);
-		dev_kfree_skb(rx_struct->skb);
-		kfree(rx_struct);
-	}
-
-	while (!list_empty(&(bdp->rx_struct_pool))) {
-		rx_struct = list_entry(bdp->rx_struct_pool.next,
-				       struct rx_list_elem, list_elem);
-		list_del(&(rx_struct->list_elem));
-		kfree(rx_struct);
-	}
-}
-
-/**
- * e100_alloc_rfd_pool - allocate RFDs
- * @bdp: atapter's private data struct
- *
- * Allocates initial pool of skb which holds both rfd and data,
- * and return a pointer to the head of the list
- */
-static int
-e100_alloc_rfd_pool(struct e100_private *bdp)
-{
-	struct rx_list_elem *rx_struct;
-	int i;
-
-	INIT_LIST_HEAD(&(bdp->active_rx_list));
-	INIT_LIST_HEAD(&(bdp->rx_struct_pool));
-	bdp->skb_req = bdp->params.RxDescriptors;
-	for (i = 0; i < bdp->skb_req; i++) {
-		rx_struct = kmalloc(sizeof (struct rx_list_elem), GFP_ATOMIC);
-		list_add(&(rx_struct->list_elem), &(bdp->rx_struct_pool));
-	}
-	e100_alloc_skbs(bdp);
-	return !list_empty(&(bdp->active_rx_list));
-
-}
-
-void
-e100_clear_pools(struct e100_private *bdp)
-{
-	bdp->last_tcb = NULL;
-	e100_free_rfd_pool(bdp);
-	e100_free_tcb_pool(bdp);
-}
-
-/*****************************************************************************/
-/*****************************************************************************/
-/*      Run Time Functions                                                   */
-/*****************************************************************************/
-
-/**
- * e100_watchdog
- * @dev: adapter's net_device struct
- *
- * This routine runs every 2 seconds and updates our statitics and link state,
- * and refreshs txthld value.
- */
-void
-e100_watchdog(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-
-#ifdef E100_CU_DEBUG
-	if (e100_cu_unknown_state(bdp)) {
-		printk(KERN_ERR "e100: %s: CU unknown state in e100_watchdog\n",
-			dev->name);
-	}
-#endif	
-	if (!netif_running(dev)) {
-		return;
-	}
-
-	/* check if link state has changed */
-	if (e100_phy_check(bdp)) {
-		if (netif_carrier_ok(dev)) {
-			printk(KERN_ERR
-			       "e100: %s NIC Link is Up %d Mbps %s duplex\n",
-			       bdp->device->name, bdp->cur_line_speed,
-			       (bdp->cur_dplx_mode == HALF_DUPLEX) ?
-			       "Half" : "Full");
-
-			e100_config_fc(bdp);
-			e100_config(bdp);  
-
-		} else {
-			printk(KERN_ERR "e100: %s NIC Link is Down\n",
-			       bdp->device->name);
-		}
-	}
-
-	// toggle the tx queue according to link status
-	// this also resolves a race condition between tx & non-cu cmd flows
-	if (netif_carrier_ok(dev)) {
-		if (netif_running(dev))
-			netif_wake_queue(dev);
-	} else {
-		if (netif_running(dev))
-			netif_stop_queue(dev);
-		/* When changing to non-autoneg, device may lose  */
-		/* link with some switches. e100 will try to      */
-		/* revover link by sending command to PHY layer   */
-		if (bdp->params.e100_speed_duplex != E100_AUTONEG)
-			e100_force_speed_duplex_to_phy(bdp);
-	}
-
-	rmb();
-
-	if (e100_update_stats(bdp)) {
-
-		/* Check if a change in the IFS parameter is needed,
-		   and configure the device accordingly */
-		if (bdp->params.b_params & PRM_IFS)
-			e100_manage_adaptive_ifs(bdp);
-
-		/* Now adjust our dynamic tx threshold value */
-		e100_refresh_txthld(bdp);
-
-		/* Now if we are on a 557 and we havn't received any frames then we
-		 * should issue a multicast command to reset the RU */
-		if (bdp->rev_id < D101A4_REV_ID) {
-			if (!(bdp->stats_counters->basic_stats.rcv_gd_frames)) {
-				e100_set_multi(dev);
-			}
-		}
-	}
-	/* Issue command to dump statistics from device.        */
-	/* Check for command completion on next watchdog timer. */
-	e100_dump_stats_cntrs(bdp);
-
-	wmb();
-
-	/* relaunch watchdog timer in 2 sec */
-	mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));
-
-	if (list_empty(&bdp->active_rx_list))
-		e100_trigger_SWI(bdp);
-}
-
-/**
- * e100_manage_adaptive_ifs
- * @bdp: atapter's private data struct
- *
- * This routine manages the adaptive Inter-Frame Spacing algorithm
- * using a state machine.
- */
-void
-e100_manage_adaptive_ifs(struct e100_private *bdp)
-{
-	static u16 state_table[9][4] = {	// rows are states
-		{2, 0, 0, 0},	// state0   // column0: next state if increasing
-		{2, 0, 5, 30},	// state1   // column1: next state if decreasing
-		{5, 1, 5, 30},	// state2   // column2: IFS value for 100 mbit
-		{5, 3, 0, 0},	// state3   // column3: IFS value for 10 mbit
-		{5, 3, 10, 60},	// state4
-		{8, 4, 10, 60},	// state5
-		{8, 6, 0, 0},	// state6
-		{8, 6, 20, 60},	// state7
-		{8, 7, 20, 60}	// state8
-	};
-
-	u32 transmits =
-		le32_to_cpu(bdp->stats_counters->basic_stats.xmt_gd_frames);
-	u32 collisions =
-		le32_to_cpu(bdp->stats_counters->basic_stats.xmt_ttl_coll);
-	u32 state = bdp->ifs_state;
-	u32 old_value = bdp->ifs_value;
-	int next_col;
-	u32 min_transmits;
-
-	if (bdp->cur_dplx_mode == FULL_DUPLEX) {
-		bdp->ifs_state = 0;
-		bdp->ifs_value = 0;
-
-	} else {		/* Half Duplex */
-		/* Set speed specific parameters */
-		if (bdp->cur_line_speed == 100) {
-			next_col = 2;
-			min_transmits = MIN_NUMBER_OF_TRANSMITS_100;
-
-		} else {	/* 10 Mbps */
-			next_col = 3;
-			min_transmits = MIN_NUMBER_OF_TRANSMITS_10;
-		}
-
-		if ((transmits / 32 < collisions)
-		    && (transmits > min_transmits)) {
-			state = state_table[state][0];	/* increment */
-
-		} else if (transmits < min_transmits) {
-			state = state_table[state][1];	/* decrement */
-		}
-
-		bdp->ifs_value = state_table[state][next_col];
-		bdp->ifs_state = state;
-	}
-
-	/* If the IFS value has changed, configure the device */
-	if (bdp->ifs_value != old_value) {
-		e100_config_ifs(bdp);
-		e100_config(bdp);
-	}
-}
-
-/**
- * e100intr - interrupt handler
- * @irq: the IRQ number
- * @dev_inst: the net_device struct
- * @regs: registers (unused)
- *
- * This routine is the ISR for the e100 board. It services
- * the RX & TX queues & starts the RU if it has stopped due
- * to no resources.
- */
-irqreturn_t
-e100intr(int irq, void *dev_inst, struct pt_regs *regs)
-{
-	struct net_device *dev;
-	struct e100_private *bdp;
-	u16 intr_status;
-
-	dev = dev_inst;
-	bdp = dev->priv;
-
-	intr_status = readw(&bdp->scb->scb_status);
-	/* If not my interrupt, just return */
-	if (!(intr_status & SCB_STATUS_ACK_MASK) || (intr_status == 0xffff)) {
-		return IRQ_NONE;
-	}
-
-	/* disable and ack intr */
-	e100_disable_clear_intr(bdp);
-
-	/* the device is closed, don't continue or else bad things may happen. */
-	if (!netif_running(dev)) {
-		e100_set_intr_mask(bdp);
-		return IRQ_NONE;
-	}
-
-	/* SWI intr (triggered by watchdog) is signal to allocate new skb buffers */
-	if (intr_status & SCB_STATUS_ACK_SWI) {
-		e100_alloc_skbs(bdp);
-	}
-
-	/* do recv work if any */
-	if (intr_status &
-	    (SCB_STATUS_ACK_FR | SCB_STATUS_ACK_RNR | SCB_STATUS_ACK_SWI)) 
-		bdp->drv_stats.rx_intr_pkts += e100_rx_srv(bdp);
-
-	/* clean up after tx'ed packets */
-	if (intr_status & (SCB_STATUS_ACK_CNA | SCB_STATUS_ACK_CX))
-		e100_tx_srv(bdp);
-
-	e100_set_intr_mask(bdp);
-	return IRQ_HANDLED;
-}
-
-/**
- * e100_tx_skb_free - free TX skbs resources
- * @bdp: atapter's private data struct
- * @tcb: associated tcb of the freed skb
- *
- * This routine frees resources of TX skbs.
- */
-static inline void
-e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb)
-{
-	if (tcb->tcb_skb) {
-		int i;
-		tbd_t *tbd_arr = tcb->tbd_ptr;
-		int frags = skb_shinfo(tcb->tcb_skb)->nr_frags;
-
-		for (i = 0; i <= frags; i++, tbd_arr++) {
-			pci_unmap_single(bdp->pdev,
-					 le32_to_cpu(tbd_arr->tbd_buf_addr),
-					 le16_to_cpu(tbd_arr->tbd_buf_cnt),
-					 PCI_DMA_TODEVICE);
-		}
-		dev_kfree_skb_irq(tcb->tcb_skb);
-		tcb->tcb_skb = NULL;
-	}
-}
-
-/**
- * e100_tx_srv - service TX queues
- * @bdp: atapter's private data struct
- *
- * This routine services the TX queues. It reclaims the TCB's & TBD's & other
- * resources used during the transmit of this buffer. It is called from the ISR.
- * We don't need a tx_lock since we always access buffers which were already
- * prepared.
- */
-void
-e100_tx_srv(struct e100_private *bdp)
-{
-	tcb_t *tcb;
-	int i;
-
-	/* go over at most TxDescriptors buffers */
-	for (i = 0; i < bdp->params.TxDescriptors; i++) {
-		tcb = bdp->tcb_pool.data;
-		tcb += bdp->tcb_pool.head;
-
-		rmb();
-
-		/* if the buffer at 'head' is not complete, break */
-		if (!(tcb->tcb_hdr.cb_status &
-		      __constant_cpu_to_le16(CB_STATUS_COMPLETE)))
-			break;
-
-		/* service next buffer, clear the out of resource condition */
-		e100_tx_skb_free(bdp, tcb);
-
-		if (netif_running(bdp->device))
-			netif_wake_queue(bdp->device);
-
-		/* if we've caught up with 'tail', break */
-		if (NEXT_TCB_TOUSE(bdp->tcb_pool.head) == bdp->tcb_pool.tail) {
-			break;
-		}
-
-		bdp->tcb_pool.head = NEXT_TCB_TOUSE(bdp->tcb_pool.head);
-	}
-}
-
-/**
- * e100_rx_srv - service RX queue
- * @bdp: atapter's private data struct
- * @max_number_of_rfds: max number of RFDs to process
- * @rx_congestion: flag pointer, to inform the calling function of congestion.
- *
- * This routine processes the RX interrupt & services the RX queues.
- * For each successful RFD, it allocates a new msg block, links that
- * into the RFD list, and sends the old msg upstream.
- * The new RFD is then put at the end of the free list of RFD's.
- * It returns the number of serviced RFDs.
- */
-u32
-e100_rx_srv(struct e100_private *bdp)
-{
-	rfd_t *rfd;		/* new rfd, received rfd */
-	int i;
-	u16 rfd_status;
-	struct sk_buff *skb;
-	struct net_device *dev;
-	unsigned int data_sz;
-	struct rx_list_elem *rx_struct;
-	u32 rfd_cnt = 0;
-
-	dev = bdp->device;
-
-	/* current design of rx is as following:
-	 * 1. socket buffer (skb) used to pass network packet to upper layer
-	 * 2. all HW host memory structures (like RFDs, RBDs and data buffers)
-	 *    are placed in a skb's data room
-	 * 3. when rx process is complete, we change skb internal pointers to exclude
-	 *    from data area all unrelated things (RFD, RDB) and to leave
-	 *    just rx'ed packet netto
-	 * 4. for each skb passed to upper layer, new one is allocated instead.
-	 * 5. if no skb left, in 2 sec another atempt to allocate skbs will be made
-	 *    (watchdog trigger SWI intr and isr should allocate new skbs)
-	 */
-	for (i = 0; i < bdp->params.RxDescriptors; i++) {
-		if (list_empty(&(bdp->active_rx_list))) {
-			break;
-		}
-
-		rx_struct = list_entry(bdp->active_rx_list.next,
-				       struct rx_list_elem, list_elem);
-		skb = rx_struct->skb;
-
-		rfd = RFD_POINTER(skb, bdp);	/* locate RFD within skb */
-
-		// sync only the RFD header
-		pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr,
-				    bdp->rfd_size, PCI_DMA_FROMDEVICE);
-		rfd_status = le16_to_cpu(rfd->rfd_header.cb_status);	/* get RFD's status */
-		if (!(rfd_status & RFD_STATUS_COMPLETE))	/* does not contains data yet - exit */
-			break;
-
-		/* to allow manipulation with current skb we need to unlink it */
-		list_del(&(rx_struct->list_elem));
-
-		/* do not free & unmap badly received packet.
-		 * move it to the end of skb list for reuse */
-		if (!(rfd_status & RFD_STATUS_OK)) {
-			e100_add_skb_to_end(bdp, rx_struct);
-			continue;
-		}
-
-		data_sz = min_t(u16, (le16_to_cpu(rfd->rfd_act_cnt) & 0x3fff),
-				(sizeof (rfd_t) - bdp->rfd_size));
-
-		/* now sync all the data */
-		pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr,
-				    (data_sz + bdp->rfd_size),
-				    PCI_DMA_FROMDEVICE);
-
-		pci_unmap_single(bdp->pdev, rx_struct->dma_addr,
-				 sizeof (rfd_t), PCI_DMA_FROMDEVICE);
-
-		list_add(&(rx_struct->list_elem), &(bdp->rx_struct_pool));
-
-		/* end of dma access to rfd */
-		bdp->skb_req++;	/* incr number of requested skbs */
-		e100_alloc_skbs(bdp);	/* and get them */
-
-		/* set packet size, excluding checksum (2 last bytes) if it is present */
-		if ((bdp->flags & DF_CSUM_OFFLOAD)
-		    && (bdp->rev_id < D102_REV_ID))
-			skb_put(skb, (int) data_sz - 2);
-		else
-			skb_put(skb, (int) data_sz);
-
-		/* set the protocol */
-		skb->protocol = eth_type_trans(skb, dev);
-
-		/* set the checksum info */
-		if (bdp->flags & DF_CSUM_OFFLOAD) {
-			if (bdp->rev_id >= D102_REV_ID) {
-				skb->ip_summed = e100_D102_check_checksum(rfd);
-			} else {
-				skb->ip_summed = e100_D101M_checksum(bdp, skb);
-			}
-		} else {
-			skb->ip_summed = CHECKSUM_NONE;
-		}
-
-		bdp->drv_stats.net_stats.rx_bytes += skb->len;
-
-		if(bdp->vlgrp && (rfd_status & CB_STATUS_VLAN)) {
-			vlan_hwaccel_rx(skb, bdp->vlgrp, be16_to_cpu(rfd->vlanid));
-		} else {
-			netif_rx(skb);
-		}
-		dev->last_rx = jiffies;
-		
-		rfd_cnt++;
-	}			/* end of rfd loop */
-
-	/* restart the RU if it has stopped */
-	if ((readw(&bdp->scb->scb_status) & SCB_RUS_MASK) != SCB_RUS_READY) {
-		e100_start_ru(bdp);
-	}
-
-	return rfd_cnt;
-}
-
-void
-e100_refresh_txthld(struct e100_private *bdp)
-{
-	basic_cntr_t *pstat = &(bdp->stats_counters->basic_stats);
-
-	/* as long as tx_per_underrun is not 0, we can go about dynamically *
-	 * adjusting the xmit threshold. we stop doing that & resort to defaults
-	 * * once the adjustments become meaningless. the value is adjusted by *
-	 * dumping the error counters & checking the # of xmit underrun errors *
-	 * we've had. */
-	if (bdp->tx_per_underrun) {
-		/* We are going to last values dumped from the dump statistics
-		 * command */
-		if (le32_to_cpu(pstat->xmt_gd_frames)) {
-			if (le32_to_cpu(pstat->xmt_uruns)) {
-				/* 
-				 * if we have had more than one underrun per "DEFAULT #
-				 * OF XMITS ALLOWED PER UNDERRUN" good xmits, raise the
-				 * THRESHOLD.
-				 */
-				if ((le32_to_cpu(pstat->xmt_gd_frames) /
-				     le32_to_cpu(pstat->xmt_uruns)) <
-				    bdp->tx_per_underrun) {
-					bdp->tx_thld += 3;
-				}
-			}
-
-			/* 
-			 * if we've had less than one underrun per the DEFAULT number of
-			 * of good xmits allowed, lower the THOLD but not less than 0 
-			 */
-			if (le32_to_cpu(pstat->xmt_gd_frames) >
-			    bdp->tx_per_underrun) {
-				bdp->tx_thld--;
-
-				if (bdp->tx_thld < 6)
-					bdp->tx_thld = 6;
-
-			}
-		}
-
-		/* end good xmits */
-		/* 
-		 * * if our adjustments are becoming unresonable, stop adjusting &
-		 * resort * to defaults & pray. A THOLD value > 190 means that the
-		 * adapter will * wait for 190*8=1520 bytes in TX FIFO before it
-		 * starts xmit. Since * MTU is 1514, it doesn't make any sense for
-		 * further increase. */
-		if (bdp->tx_thld >= 190) {
-			bdp->tx_per_underrun = 0;
-			bdp->tx_thld = 189;
-		}
-	}			/* end underrun check */
-}
-
-/**
- * e100_prepare_xmit_buff - prepare a buffer for transmission
- * @bdp: atapter's private data struct
- * @skb: skb to send
- *
- * This routine prepare a buffer for transmission. It checks
- * the message length for the appropiate size. It picks up a
- * free tcb from the TCB pool and sets up the corresponding
- * TBD's. If the number of fragments are more than the number
- * of TBD/TCB it copies all the fragments in a coalesce buffer.
- * It returns a pointer to the prepared TCB.
- */
-static inline tcb_t *
-e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb)
-{
-	tcb_t *tcb, *prev_tcb;
-
-	tcb = bdp->tcb_pool.data;
-	tcb += TCB_TO_USE(bdp->tcb_pool);
-
-	if (bdp->flags & USE_IPCB) {
-		tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT;
-		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCP_PACKET;
-		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE;
-	}
-
-	if(bdp->vlgrp && vlan_tx_tag_present(skb)) {
-		(tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE;
-		(tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb));
-	}
-	
-	tcb->tcb_hdr.cb_status = 0;
-	tcb->tcb_thrshld = bdp->tx_thld;
-	tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT);
-
-	/* Set I (Interrupt) bit on every (TX_FRAME_CNT)th packet */
-	if (!(++bdp->tx_count % TX_FRAME_CNT))
-		tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_I_BIT);
-	else
-		/* Clear I bit on other packets */
-		tcb->tcb_hdr.cb_cmd &= ~__constant_cpu_to_le16(CB_I_BIT);
-
-	tcb->tcb_skb = skb;
-
-	if (skb->ip_summed == CHECKSUM_HW) {
-		const struct iphdr *ip = skb->nh.iph;
-
-		if ((ip->protocol == IPPROTO_TCP) ||
-		    (ip->protocol == IPPROTO_UDP)) {
-
-			tcb->tcbu.ipcb.ip_activation_high |=
-				IPCB_HARDWAREPARSING_ENABLE;
-			tcb->tcbu.ipcb.ip_schedule |=
-				IPCB_TCPUDP_CHECKSUM_ENABLE;
-
-			if (ip->protocol == IPPROTO_TCP)
-				tcb->tcbu.ipcb.ip_schedule |= IPCB_TCP_PACKET;
-		}
-	}
-
-	if (!skb_shinfo(skb)->nr_frags) {
-		(tcb->tbd_ptr)->tbd_buf_addr =
-			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,
-						   skb->len, PCI_DMA_TODEVICE));
-		(tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len);
-		tcb->tcb_tbd_num = 1;
-		tcb->tcb_tbd_ptr = tcb->tcb_tbd_dflt_ptr;
-	} else {
-		int i;
-		void *addr;
-		tbd_t *tbd_arr_ptr = &(tcb->tbd_ptr[1]);
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[0];
-
-		(tcb->tbd_ptr)->tbd_buf_addr =
-			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,
-						   skb_headlen(skb),
-						   PCI_DMA_TODEVICE));
-		(tcb->tbd_ptr)->tbd_buf_cnt =
-			cpu_to_le16(skb_headlen(skb));
-
-		for (i = 0; i < skb_shinfo(skb)->nr_frags;
-		     i++, tbd_arr_ptr++, frag++) {
-
-			addr = ((void *) page_address(frag->page) +
-				frag->page_offset);
-
-			tbd_arr_ptr->tbd_buf_addr =
-				cpu_to_le32(pci_map_single(bdp->pdev,
-							   addr, frag->size,
-							   PCI_DMA_TODEVICE));
-			tbd_arr_ptr->tbd_buf_cnt = cpu_to_le16(frag->size);
-		}
-		tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1;
-		tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr;
-	}
-
-	/* clear the S-BIT on the previous tcb */
-	prev_tcb = bdp->tcb_pool.data;
-	prev_tcb += PREV_TCB_USED(bdp->tcb_pool);
-	prev_tcb->tcb_hdr.cb_cmd &= __constant_cpu_to_le16((u16) ~CB_S_BIT);
-
-	bdp->tcb_pool.tail = NEXT_TCB_TOUSE(bdp->tcb_pool.tail);
-
-	wmb();
-
-	e100_start_cu(bdp, tcb);
-
-	return tcb;
-}
-
-/* Changed for 82558 enhancement */
-/**
- * e100_start_cu - start the adapter's CU
- * @bdp: atapter's private data struct
- * @tcb: TCB to be transmitted
- *
- * This routine issues a CU Start or CU Resume command to the 82558/9.
- * This routine was added because the prepare_ext_xmit_buff takes advantage
- * of the 82558/9's Dynamic TBD chaining feature and has to start the CU as
- * soon as the first TBD is ready. 
- *
- * e100_start_cu must be called while holding the tx_lock ! 
- */
-u8
-e100_start_cu(struct e100_private *bdp, tcb_t *tcb)
-{
-	unsigned long lock_flag;
-	u8 ret = true;
-
-	spin_lock_irqsave(&(bdp->bd_lock), lock_flag);
-	switch (bdp->next_cu_cmd) {
-	case RESUME_NO_WAIT:
-		/*last cu command was a CU_RESMUE if this is a 558 or newer we don't need to
-		 * wait for command word to clear, we reach here only if we are bachlor
-		 */
-		e100_exec_cmd(bdp, SCB_CUC_RESUME);
-		break;
-
-	case RESUME_WAIT:
-		if ((bdp->flags & IS_ICH) &&
-		    (bdp->cur_line_speed == 10) &&
-		    (bdp->cur_dplx_mode == HALF_DUPLEX)) {
-			e100_wait_exec_simple(bdp, SCB_CUC_NOOP);
-			udelay(1);
-		}
-		if ((e100_wait_exec_simple(bdp, SCB_CUC_RESUME)) &&
-		    (bdp->flags & IS_BACHELOR) && (!(bdp->flags & IS_ICH))) {
-			bdp->next_cu_cmd = RESUME_NO_WAIT;
-		}
-		break;
-
-	case START_WAIT:
-		// The last command was a non_tx CU command
-		if (!e100_wait_cus_idle(bdp))
-			printk(KERN_DEBUG
-			       "e100: %s: cu_start: timeout waiting for cu\n",
-			       bdp->device->name);
-		if (!e100_wait_exec_cmplx(bdp, (u32) (tcb->tcb_phys),
-					  SCB_CUC_START, CB_TRANSMIT)) {
-			printk(KERN_DEBUG
-			       "e100: %s: cu_start: timeout waiting for scb\n",
-			       bdp->device->name);
-			e100_exec_cmplx(bdp, (u32) (tcb->tcb_phys),
-					SCB_CUC_START);
-			ret = false;
-		}
-
-		bdp->next_cu_cmd = RESUME_WAIT;
-
-		break;
-	}
-
-	/* save the last tcb */
-	bdp->last_tcb = tcb;
-
-	spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag);
-	return ret;
-}
-
-/* ====================================================================== */
-/* hw                                                                     */
-/* ====================================================================== */
-
-/**
- * e100_selftest - perform H/W self test
- * @bdp: atapter's private data struct
- * @st_timeout: address to return timeout value, if fails
- * @st_result: address to return selftest result, if fails
- *
- * This routine will issue PORT Self-test command to test the e100.
- * The self-test will fail if the adapter's master-enable bit is not
- * set in the PCI Command Register, or if the adapter is not seated
- * in a PCI master-enabled slot. we also disable interrupts when the
- * command is completed.
- *
- * Returns:
- *      true: if adapter passes self_test
- *      false: otherwise
- */
-unsigned char
-e100_selftest(struct e100_private *bdp, u32 *st_timeout, u32 *st_result)
-{
-	u32 selftest_cmd;
-
-	/* initialize the nic state before running test */
-	e100_sw_reset(bdp, PORT_SOFTWARE_RESET);
-	/* Setup the address of the self_test area */
-	selftest_cmd = bdp->selftest_phys;
-
-	/* Setup SELF TEST Command Code in D3 - D0 */
-	selftest_cmd |= PORT_SELFTEST;
-
-	/* Initialize the self-test signature and results DWORDS */
-	bdp->selftest->st_sign = 0;
-	bdp->selftest->st_result = 0xffffffff;
-
-	/* Do the port command */
-	writel(selftest_cmd, &bdp->scb->scb_port);
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-
-	/* Wait at least 10 milliseconds for the self-test to complete */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 100 + 1);
-
-	/* disable interrupts since they are enabled */
-	/* after device reset during selftest        */
-	e100_disable_clear_intr(bdp);
-
-	/* if The First Self Test DWORD Still Zero, We've timed out. If the
-	 * second DWORD is not zero then we have an error. */
-	if ((bdp->selftest->st_sign == 0) || (bdp->selftest->st_result != 0)) {
-
-		if (st_timeout)
-			*st_timeout = !(le32_to_cpu(bdp->selftest->st_sign));
-
-		if (st_result)
-			*st_result = le32_to_cpu(bdp->selftest->st_result);
-
-		return false;
-	}
-
-	return true;
-}
-
-/**
- * e100_setup_iaaddr - issue IA setup sommand
- * @bdp: atapter's private data struct
- * @eaddr: new ethernet address
- *
- * This routine will issue the IA setup command. This command
- * will notify the 82557 (e100) of what its individual (node)
- * address is. This command will be executed in polled mode.
- *
- * Returns:
- *      true: if the IA setup command was successfully issued and completed
- *      false: otherwise
- */
-unsigned char
-e100_setup_iaaddr(struct e100_private *bdp, u8 *eaddr)
-{
-	unsigned int i;
-	cb_header_t *ntcb_hdr;
-	unsigned char res;
-	nxmit_cb_entry_t *cmd;
-
-	if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) {
-		res = false;
-		goto exit;
-	}
-
-	ntcb_hdr = (cb_header_t *) cmd->non_tx_cmd;
-	ntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_IA_ADDRESS);
-
-	for (i = 0; i < ETH_ALEN; i++) {
-		(cmd->non_tx_cmd)->ntcb.setup.ia_addr[i] = eaddr[i];
-	}
-
-	res = e100_exec_non_cu_cmd(bdp, cmd);
-	if (!res)
-		printk(KERN_WARNING "e100: %s: IA setup failed\n", 
-		       bdp->device->name);
-
-exit:
-	return res;
-}
-
-/**
- * e100_start_ru - start the RU if needed
- * @bdp: atapter's private data struct
- *
- * This routine checks the status of the 82557's receive unit(RU),
- * and starts the RU if it was not already active.  However,
- * before restarting the RU, the driver gives the RU the buffers
- * it freed up during the servicing of the ISR. If there are
- * no free buffers to give to the RU, (i.e. we have reached a
- * no resource condition) the RU will not be started till the
- * next ISR.
- */
-void
-e100_start_ru(struct e100_private *bdp)
-{
-	struct rx_list_elem *rx_struct = NULL;
-	int buffer_found = 0;
-	struct list_head *entry_ptr;
-
-	list_for_each(entry_ptr, &(bdp->active_rx_list)) {
-		rx_struct =
-			list_entry(entry_ptr, struct rx_list_elem, list_elem);
-		pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr,
-				    bdp->rfd_size, PCI_DMA_FROMDEVICE);
-		if (!((SKB_RFD_STATUS(rx_struct->skb, bdp) &
-		       __constant_cpu_to_le16(RFD_STATUS_COMPLETE)))) {
-			buffer_found = 1;
-			break;
-		}
-	}
-
-	/* No available buffers */
-	if (!buffer_found) {
-		return;
-	}
-
-	spin_lock(&bdp->bd_lock);
-
-	if (!e100_wait_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START, 0)) {
-		printk(KERN_DEBUG
-		       "e100: %s: start_ru: wait_scb failed\n", 
-		       bdp->device->name);
-		e100_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START);
-	}
-	if (bdp->next_cu_cmd == RESUME_NO_WAIT) {
-		bdp->next_cu_cmd = RESUME_WAIT;
-	}
-	spin_unlock(&bdp->bd_lock);
-}
-
-/**
- * e100_cmd_complete_location
- * @bdp: atapter's private data struct
- *
- * This routine returns a pointer to the location of the command-complete
- * DWord in the dump statistical counters area, according to the statistical
- * counters mode (557 - basic, 558 - extended, or 559 - TCO mode).
- * See e100_config_init() for the setting of the statistical counters mode.
- */
-static u32 *
-e100_cmd_complete_location(struct e100_private *bdp)
-{
-	u32 *cmd_complete;
-	max_counters_t *stats = bdp->stats_counters;
-
-	switch (bdp->stat_mode) {
-	case E100_EXTENDED_STATS:
-		cmd_complete =
-			(u32 *) &(((err_cntr_558_t *) (stats))->cmd_complete);
-		break;
-
-	case E100_TCO_STATS:
-		cmd_complete =
-			(u32 *) &(((err_cntr_559_t *) (stats))->cmd_complete);
-		break;
-
-	case E100_BASIC_STATS:
-	default:		
-		cmd_complete =
-			(u32 *) &(((err_cntr_557_t *) (stats))->cmd_complete);
-		break;
-	}
-
-	return cmd_complete;
-}
-
-/**
- * e100_clr_cntrs - clear statistics counters
- * @bdp: atapter's private data struct
- *
- * This routine will clear the adapter error statistic counters.
- *
- * Returns:
- *      true: if successfully cleared stat counters
- *      false: otherwise
- */
-static unsigned char
-e100_clr_cntrs(struct e100_private *bdp)
-{
-	volatile u32 *pcmd_complete;
-
-	/* clear the dump counter complete word */
-	pcmd_complete = e100_cmd_complete_location(bdp);
-	*pcmd_complete = 0;
-	wmb();
-
-	if (!e100_wait_exec_cmplx(bdp, bdp->stat_cnt_phys, SCB_CUC_DUMP_ADDR, 0))
-		return false;
-
-	/* wait 10 microseconds for the command to complete */
-	udelay(10);
-
-	if (!e100_wait_exec_simple(bdp, SCB_CUC_DUMP_RST_STAT))
-		return false;
-
-	if (bdp->next_cu_cmd == RESUME_NO_WAIT) {
-		bdp->next_cu_cmd = RESUME_WAIT;
-	}
-
-	return true;
-}
-
-static unsigned char
-e100_update_stats(struct e100_private *bdp)
-{
-	u32 *pcmd_complete;
-	basic_cntr_t *pstat = &(bdp->stats_counters->basic_stats);
-
-	// check if last dump command completed
-	pcmd_complete = e100_cmd_complete_location(bdp);
-	if (*pcmd_complete != le32_to_cpu(DUMP_RST_STAT_COMPLETED) &&
-	    *pcmd_complete != le32_to_cpu(DUMP_STAT_COMPLETED)) {
-		*pcmd_complete = 0;
-		return false;
-	}
-
-	/* increment the statistics */
-	bdp->drv_stats.net_stats.rx_packets +=
-		le32_to_cpu(pstat->rcv_gd_frames);
-	bdp->drv_stats.net_stats.tx_packets +=
-		le32_to_cpu(pstat->xmt_gd_frames);
-	bdp->drv_stats.net_stats.rx_dropped += le32_to_cpu(pstat->rcv_rsrc_err);
-	bdp->drv_stats.net_stats.collisions += le32_to_cpu(pstat->xmt_ttl_coll);
-	bdp->drv_stats.net_stats.rx_length_errors +=
-		le32_to_cpu(pstat->rcv_shrt_frames);
-	bdp->drv_stats.net_stats.rx_over_errors +=
-		le32_to_cpu(pstat->rcv_rsrc_err);
-	bdp->drv_stats.net_stats.rx_crc_errors +=
-		le32_to_cpu(pstat->rcv_crc_errs);
-	bdp->drv_stats.net_stats.rx_frame_errors +=
-		le32_to_cpu(pstat->rcv_algn_errs);
-	bdp->drv_stats.net_stats.rx_fifo_errors +=
-		le32_to_cpu(pstat->rcv_oruns);
-	bdp->drv_stats.net_stats.tx_aborted_errors +=
-		le32_to_cpu(pstat->xmt_max_coll);
-	bdp->drv_stats.net_stats.tx_carrier_errors +=
-		le32_to_cpu(pstat->xmt_lost_crs);
-	bdp->drv_stats.net_stats.tx_fifo_errors +=
-		le32_to_cpu(pstat->xmt_uruns);
-
-	bdp->drv_stats.tx_late_col += le32_to_cpu(pstat->xmt_late_coll);
-	bdp->drv_stats.tx_ok_defrd += le32_to_cpu(pstat->xmt_deferred);
-	bdp->drv_stats.tx_one_retry += le32_to_cpu(pstat->xmt_sngl_coll);
-	bdp->drv_stats.tx_mt_one_retry += le32_to_cpu(pstat->xmt_mlt_coll);
-	bdp->drv_stats.rcv_cdt_frames += le32_to_cpu(pstat->rcv_err_coll);
-
-	if (bdp->stat_mode != E100_BASIC_STATS) {
-		ext_cntr_t *pex_stat = &bdp->stats_counters->extended_stats;
-
-		bdp->drv_stats.xmt_fc_pkts +=
-			le32_to_cpu(pex_stat->xmt_fc_frames);
-		bdp->drv_stats.rcv_fc_pkts +=
-			le32_to_cpu(pex_stat->rcv_fc_frames);
-		bdp->drv_stats.rcv_fc_unsupported +=
-			le32_to_cpu(pex_stat->rcv_fc_unsupported);
-	}
-
-	if (bdp->stat_mode == E100_TCO_STATS) {
-		tco_cntr_t *ptco_stat = &bdp->stats_counters->tco_stats;
-
-		bdp->drv_stats.xmt_tco_pkts +=
-			le16_to_cpu(ptco_stat->xmt_tco_frames);
-		bdp->drv_stats.rcv_tco_pkts +=
-			le16_to_cpu(ptco_stat->rcv_tco_frames);
-	}
-
-	*pcmd_complete = 0;
-	return true;
-}
-
-/**
- * e100_dump_stat_cntrs
- * @bdp: atapter's private data struct
- *
- * This routine will dump the board statistical counters without waiting
- * for stat_dump to complete. Any access to this stats should verify the completion
- * of the command
- */
-void
-e100_dump_stats_cntrs(struct e100_private *bdp)
-{
-	unsigned long lock_flag_bd;
-
-	spin_lock_irqsave(&(bdp->bd_lock), lock_flag_bd);
-
-	/* dump h/w stats counters */
-	if (e100_wait_exec_simple(bdp, SCB_CUC_DUMP_RST_STAT)) {
-		if (bdp->next_cu_cmd == RESUME_NO_WAIT) {
-			bdp->next_cu_cmd = RESUME_WAIT;
-		}
-	}
-
-	spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag_bd);
-}
-
-/**
- * e100_exec_non_cu_cmd
- * @bdp: atapter's private data struct
- * @command: the non-cu command to execute
- *
- * This routine will submit a command block to be executed,
- */
-unsigned char
-e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command)
-{
-	cb_header_t *ntcb_hdr;
-	unsigned long lock_flag;
-	unsigned long expiration_time;
-	unsigned char rc = true;
-	u8 sub_cmd;
-
-	ntcb_hdr = (cb_header_t *) command->non_tx_cmd;	/* get hdr of non tcb cmd */
-	sub_cmd = cpu_to_le16(ntcb_hdr->cb_cmd);
-
-	/* Set the Command Block to be the last command block */
-	ntcb_hdr->cb_cmd |= __constant_cpu_to_le16(CB_EL_BIT);
-	ntcb_hdr->cb_status = 0;
-	ntcb_hdr->cb_lnk_ptr = 0;
-
-	wmb();
-	if (in_interrupt())
-		return e100_delayed_exec_non_cu_cmd(bdp, command);
-
-	if (netif_running(bdp->device) && netif_carrier_ok(bdp->device))
-		return e100_delayed_exec_non_cu_cmd(bdp, command);
-
-	spin_lock_bh(&(bdp->bd_non_tx_lock));
-
-	if (bdp->non_tx_command_state != E100_NON_TX_IDLE) {
-		goto delayed_exec;
-	}
-
-	if (bdp->last_tcb) {
-		rmb();
-		if ((bdp->last_tcb->tcb_hdr.cb_status &
-		     __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0)
-			goto delayed_exec;
-	}
-
-	if ((readw(&bdp->scb->scb_status) & SCB_CUS_MASK) == SCB_CUS_ACTIVE) {
-		goto delayed_exec;
-	}
-
-	spin_lock_irqsave(&bdp->bd_lock, lock_flag);
-
-	if (!e100_wait_exec_cmplx(bdp, command->dma_addr, SCB_CUC_START, sub_cmd)) {
-		spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag);
-		rc = false;
-		goto exit;
-	}
-
-	bdp->next_cu_cmd = START_WAIT;
-	spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag);
-
-	/* now wait for completion of non-cu CB up to 20 msec */
-	expiration_time = jiffies + HZ / 50 + 1;
-	rmb();
-	while (!(ntcb_hdr->cb_status &
-		     __constant_cpu_to_le16(CB_STATUS_COMPLETE))) {
-
-		if (time_before(jiffies, expiration_time)) {
-			spin_unlock_bh(&(bdp->bd_non_tx_lock));
-			yield();
-			spin_lock_bh(&(bdp->bd_non_tx_lock));
-		} else {
-#ifdef E100_CU_DEBUG			
-			printk(KERN_ERR "e100: %s: non-TX command (%x) "
-				"timeout\n", bdp->device->name, sub_cmd);
-#endif			
-			rc = false;
-			goto exit;
-		}
-		rmb();
-	}
-
-exit:
-	e100_free_non_tx_cmd(bdp, command);
-
-	if (netif_running(bdp->device))
-		netif_wake_queue(bdp->device);
-
-	spin_unlock_bh(&(bdp->bd_non_tx_lock));
-	return rc;
-
-delayed_exec:
-	spin_unlock_bh(&(bdp->bd_non_tx_lock));
-	return e100_delayed_exec_non_cu_cmd(bdp, command);
-}
-
-/**
- * e100_sw_reset
- * @bdp: atapter's private data struct
- * @reset_cmd: s/w reset or selective reset
- *
- * This routine will issue a software reset to the adapter. It 
- * will also disable interrupts, as the are enabled after reset.
- */
-void
-e100_sw_reset(struct e100_private *bdp, u32 reset_cmd)
-{
-	/* Do  a selective reset first to avoid a potential PCI hang */
-	writel(PORT_SELECTIVE_RESET, &bdp->scb->scb_port);
-	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
-
-	/* wait for the reset to take effect */
-	udelay(20);
-	if (reset_cmd == PORT_SOFTWARE_RESET) {
-		writel(PORT_SOFTWARE_RESET, &bdp->scb->scb_port);
-
-		/* wait 20 micro seconds for the reset to take effect */
-		udelay(20);
-	}
-
-	/* Mask off our interrupt line -- it is unmasked after reset */
-	e100_disable_clear_intr(bdp);
-#ifdef E100_CU_DEBUG	
-	bdp->last_cmd = 0;
-	bdp->last_sub_cmd = 0;
-#endif	
-}
-
-/**
- * e100_load_microcode - Download microsocde to controller.
- * @bdp: atapter's private data struct
- *
- * This routine downloads microcode on to the controller. This
- * microcode is available for the 82558/9, 82550. Currently the
- * microcode handles interrupt bundling and TCO workaround.
- *
- * Returns:
- *      true: if successfull
- *      false: otherwise
- */
-static unsigned char
-e100_load_microcode(struct e100_private *bdp)
-{
-	static struct {
-		u8 rev_id;
-		u32 ucode[UCODE_MAX_DWORDS + 1];
-		int timer_dword;
-		int bundle_dword;
-		int min_size_dword;
-	} ucode_opts[] = {
-		{ D101A4_REV_ID,
-		  D101_A_RCVBUNDLE_UCODE,
-		  D101_CPUSAVER_TIMER_DWORD,
-		  D101_CPUSAVER_BUNDLE_DWORD,
-		  D101_CPUSAVER_MIN_SIZE_DWORD },
-		{ D101B0_REV_ID,
-		  D101_B0_RCVBUNDLE_UCODE,
-		  D101_CPUSAVER_TIMER_DWORD,
-		  D101_CPUSAVER_BUNDLE_DWORD,
-		  D101_CPUSAVER_MIN_SIZE_DWORD },
-		{ D101MA_REV_ID,
-		  D101M_B_RCVBUNDLE_UCODE,
-		  D101M_CPUSAVER_TIMER_DWORD,
-		  D101M_CPUSAVER_BUNDLE_DWORD,
-		  D101M_CPUSAVER_MIN_SIZE_DWORD },
-		{ D101S_REV_ID,
-		  D101S_RCVBUNDLE_UCODE,
-		  D101S_CPUSAVER_TIMER_DWORD,
-		  D101S_CPUSAVER_BUNDLE_DWORD,
-		  D101S_CPUSAVER_MIN_SIZE_DWORD },
-		{ D102_REV_ID,
-		  D102_B_RCVBUNDLE_UCODE,
-		  D102_B_CPUSAVER_TIMER_DWORD,
-		  D102_B_CPUSAVER_BUNDLE_DWORD,
-		  D102_B_CPUSAVER_MIN_SIZE_DWORD },
-		{ D102C_REV_ID,
-		  D102_C_RCVBUNDLE_UCODE,
-		  D102_C_CPUSAVER_TIMER_DWORD,
-		  D102_C_CPUSAVER_BUNDLE_DWORD,
-		  D102_C_CPUSAVER_MIN_SIZE_DWORD },
-		{ D102E_REV_ID,
-		  D102_E_RCVBUNDLE_UCODE,
-		  D102_E_CPUSAVER_TIMER_DWORD,
-		  D102_E_CPUSAVER_BUNDLE_DWORD,
-		  D102_E_CPUSAVER_MIN_SIZE_DWORD },
-		{ 0, {0}, 0, 0, 0}
-	}, *opts;
-
-	opts = ucode_opts;
-
-	/* User turned ucode loading off */
-	if (!(bdp->params.b_params & PRM_UCODE))
-		return false;
-
-	/* These controllers do not need ucode */
-	if (bdp->flags & IS_ICH)
-		return false;
-
-	/* Search for ucode match against h/w rev_id */
-	while (opts->rev_id) {
-		if (bdp->rev_id == opts->rev_id) {
-			int i;
-			u32 *ucode_dword;
-			load_ucode_cb_t *ucode_cmd_ptr;
-			nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(bdp);
-
-			if (cmd != NULL) {
-				ucode_cmd_ptr =
-					(load_ucode_cb_t *) cmd->non_tx_cmd;
-				ucode_dword = ucode_cmd_ptr->ucode_dword;
-			} else {
-				return false;
-			}
-
-			memcpy(ucode_dword, opts->ucode, sizeof (opts->ucode));
-
-			/* Insert user-tunable settings */
-			ucode_dword[opts->timer_dword] &= 0xFFFF0000;
-			ucode_dword[opts->timer_dword] |=
-				(u16) bdp->params.IntDelay;
-			ucode_dword[opts->bundle_dword] &= 0xFFFF0000;
-			ucode_dword[opts->bundle_dword] |=
-				(u16) bdp->params.BundleMax;
-			ucode_dword[opts->min_size_dword] &= 0xFFFF0000;
-			ucode_dword[opts->min_size_dword] |=
-				(bdp->params.b_params & PRM_BUNDLE_SMALL) ?
-				0xFFFF : 0xFF80;
-
-			for (i = 0; i < UCODE_MAX_DWORDS; i++)
-				cpu_to_le32s(&(ucode_dword[i]));
-
-			ucode_cmd_ptr->load_ucode_cbhdr.cb_cmd =
-				__constant_cpu_to_le16(CB_LOAD_MICROCODE);
-
-			return e100_exec_non_cu_cmd(bdp, cmd);
-		}
-		opts++;
-	}
-
-	return false;
-}
-
-/***************************************************************************/
-/***************************************************************************/
-/*       EEPROM  Functions                                                 */
-/***************************************************************************/
-
-/* Read PWA (printed wired assembly) number */
-void
-e100_rd_pwa_no(struct e100_private *bdp)
-{
-	bdp->pwa_no = e100_eeprom_read(bdp, EEPROM_PWA_NO);
-	bdp->pwa_no <<= 16;
-	bdp->pwa_no |= e100_eeprom_read(bdp, EEPROM_PWA_NO + 1);
-}
-
-/* Read the permanent ethernet address from the eprom. */
-void
-e100_rd_eaddr(struct e100_private *bdp)
-{
-	int i;
-	u16 eeprom_word;
-
-	for (i = 0; i < 6; i += 2) {
-		eeprom_word =
-			e100_eeprom_read(bdp,
-					 EEPROM_NODE_ADDRESS_BYTE_0 + (i / 2));
-
-		bdp->device->dev_addr[i] =
-			bdp->perm_node_address[i] = (u8) eeprom_word;
-		bdp->device->dev_addr[i + 1] =
-			bdp->perm_node_address[i + 1] = (u8) (eeprom_word >> 8);
-	}
-}
-
-/* Check the D102 RFD flags to see if the checksum passed */
-static unsigned char
-e100_D102_check_checksum(rfd_t *rfd)
-{
-	if (((le16_to_cpu(rfd->rfd_header.cb_status)) & RFD_PARSE_BIT)
-	    && (((rfd->rcvparserstatus & CHECKSUM_PROTOCOL_MASK) ==
-		 RFD_TCP_PACKET)
-		|| ((rfd->rcvparserstatus & CHECKSUM_PROTOCOL_MASK) ==
-		    RFD_UDP_PACKET))
-	    && (rfd->checksumstatus & TCPUDP_CHECKSUM_BIT_VALID)
-	    && (rfd->checksumstatus & TCPUDP_CHECKSUM_VALID)) {
-		return CHECKSUM_UNNECESSARY;
-	}
-	return CHECKSUM_NONE;
-}
-
-/**
- * e100_D101M_checksum
- * @bdp: atapter's private data struct
- * @skb: skb received
- *
- * Sets the skb->csum value from D101 csum found at the end of the Rx frame. The
- * D101M sums all words in frame excluding the ethernet II header (14 bytes) so
- * in case the packet is ethernet II and the protocol is IP, all is need is to
- * assign this value to skb->csum.
- */
-static unsigned char
-e100_D101M_checksum(struct e100_private *bdp, struct sk_buff *skb)
-{
-	unsigned short proto = (skb->protocol);
-
-	if (proto == __constant_htons(ETH_P_IP)) {
-
-		skb->csum = get_unaligned((u16 *) (skb->tail));
-		return CHECKSUM_HW;
-	}
-	return CHECKSUM_NONE;
-}
-
-/***************************************************************************/
-/***************************************************************************/
-/***************************************************************************/
-/***************************************************************************/
-/*       Auxilary Functions                                                */
-/***************************************************************************/
-
-/* Print the board's configuration */
-void
-e100_print_brd_conf(struct e100_private *bdp)
-{
-	/* Print the string if checksum Offloading was enabled */
-	if (bdp->flags & DF_CSUM_OFFLOAD)
-		printk(KERN_NOTICE "  Hardware receive checksums enabled\n");
-	else {
-		if (bdp->rev_id >= D101MA_REV_ID) 
-			printk(KERN_NOTICE "  Hardware receive checksums disabled\n");
-	}
-
-	if ((bdp->flags & DF_UCODE_LOADED))
-		printk(KERN_NOTICE "  cpu cycle saver enabled\n");
-}
-
-/**
- * e100_pci_setup - setup the adapter's PCI information
- * @pcid: adapter's pci_dev struct
- * @bdp: atapter's private data struct
- *
- * This routine sets up all PCI information for the adapter. It enables the bus
- * master bit (some BIOS don't do this), requests memory ans I/O regions, and
- * calls ioremap() on the adapter's memory region.
- *
- * Returns:
- *      true: if successfull
- *      false: otherwise
- */
-static unsigned char
-e100_pci_setup(struct pci_dev *pcid, struct e100_private *bdp)
-{
-	struct net_device *dev = bdp->device;
-	int rc = 0;
-
-	if ((rc = pci_enable_device(pcid)) != 0) {
-		goto err;
-	}
-
-	/* dev and ven ID have already been checked so it is our device */
-	pci_read_config_byte(pcid, PCI_REVISION_ID, (u8 *) &(bdp->rev_id));
-
-	/* address #0 is a memory region */
-	dev->mem_start = pci_resource_start(pcid, 0);
-	dev->mem_end = dev->mem_start + sizeof (scb_t);
-
-	/* address #1 is a IO region */
-	dev->base_addr = pci_resource_start(pcid, 1);
-
-	if ((rc = pci_request_regions(pcid, e100_short_driver_name)) != 0) {
-		goto err_disable;
-	}
-
-	pci_enable_wake(pcid, 0, 0);
-
-	/* if Bus Mastering is off, turn it on! */
-	pci_set_master(pcid);
-
-	/* address #0 is a memory mapping */
-	bdp->scb = (scb_t *) ioremap_nocache(dev->mem_start, sizeof (scb_t));
-
-	if (!bdp->scb) {
-		printk(KERN_ERR "e100: %s: Failed to map PCI address 0x%lX\n",
-		       dev->name, pci_resource_start(pcid, 0));
-		rc = -ENOMEM;
-		goto err_region;
-	}
-
-	return 0;
-
-err_region:
-	pci_release_regions(pcid);
-err_disable:
-	pci_disable_device(pcid);
-err:
-	return rc;
-}
-
-void
-e100_isolate_driver(struct e100_private *bdp)
-{
-
-	/* Check if interface is up                              */
-	/* NOTE: Can't use netif_running(bdp->device) because    */
-	/* dev_close clears __LINK_STATE_START before calling    */
-	/* e100_close (aka dev->stop)                            */
-	if (bdp->device->flags & IFF_UP) {
-		e100_disable_clear_intr(bdp);
-		del_timer_sync(&bdp->watchdog_timer);
-		netif_carrier_off(bdp->device);
-		netif_stop_queue(bdp->device); 
-		bdp->last_tcb = NULL;
-	} 
-	e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
-}
-
-static void
-e100_tcb_add_C_bit(struct e100_private *bdp)
-{
-	tcb_t *tcb = (tcb_t *) bdp->tcb_pool.data;
-	int i;
-
-	for (i = 0; i < bdp->params.TxDescriptors; i++, tcb++) {
-		tcb->tcb_hdr.cb_status |= cpu_to_le16(CB_STATUS_COMPLETE);
-	}
-}
-
-/* 
- * Procedure:   e100_configure_device
- *
- * Description: This routine will configure device
- *
- * Arguments:
- *      bdp - Ptr to this card's e100_bdconfig structure
- *
- * Returns:
- *        true upon success
- *        false upon failure
- */
-unsigned char
-e100_configure_device(struct e100_private *bdp)
-{
-	/*load CU & RU base */
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0))
-		return false;
-
-	if (e100_load_microcode(bdp))
-		bdp->flags |= DF_UCODE_LOADED;
-
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0))
-		return false;
-
-	/* Issue the load dump counters address command */
-	if (!e100_wait_exec_cmplx(bdp, bdp->stat_cnt_phys, SCB_CUC_DUMP_ADDR, 0))
-		return false;
-
-	if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr)) {
-		printk(KERN_ERR "e100: e100_configure_device: "
-			"setup iaaddr failed\n");
-		return false;
-	}
-
-	e100_set_multi_exec(bdp->device);
-
-	/* Change for 82558 enhancement                                */
-	/* If 82558/9 and if the user has enabled flow control, set up */
-	/* flow Control Reg. in the CSR                                */
-	if ((bdp->flags & IS_BACHELOR)
-	    && (bdp->params.b_params & PRM_FC)) {
-		writeb(DFLT_FC_THLD,
-			&bdp->scb->scb_ext.d101_scb.scb_fc_thld);
-		writeb(DFLT_FC_CMD,
-			&bdp->scb->scb_ext.d101_scb.scb_fc_xon_xoff);
-	}
-
-	e100_force_config(bdp);
-
-	return true;
-}
-
-void
-e100_deisolate_driver(struct e100_private *bdp, u8 full_reset)
-{
-	u32 cmd = full_reset ? PORT_SOFTWARE_RESET : PORT_SELECTIVE_RESET;
-	e100_sw_reset(bdp, cmd);
-	if (cmd == PORT_SOFTWARE_RESET) {
-		if (!e100_configure_device(bdp))
-			printk(KERN_ERR "e100: e100_deisolate_driver:" 
-		       		" device configuration failed\n");
-	} 
-
-	if (netif_running(bdp->device)) {
-
-		bdp->next_cu_cmd = START_WAIT;
-		bdp->last_tcb = NULL;
-
-		e100_start_ru(bdp);
-
-		/* relaunch watchdog timer in 2 sec */
-		mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));
-
-		// we must clear tcbs since we may have lost Tx intrrupt
-		// or have unsent frames on the tcb chain
-		e100_tcb_add_C_bit(bdp);
-		e100_tx_srv(bdp);
-		netif_wake_queue(bdp->device);
-		e100_set_intr_mask(bdp);
-	}
-}
-
-static int
-e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
-{
-	struct ethtool_cmd ecmd;
-	int rc = -EOPNOTSUPP;
-
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd.cmd)))
-		return -EFAULT;
-
-	switch (ecmd.cmd) {
-	case ETHTOOL_GSET:
-		rc = e100_ethtool_get_settings(dev, ifr);
-		break;
-	case ETHTOOL_SSET:
-		rc = e100_ethtool_set_settings(dev, ifr);
-		break;
-	case ETHTOOL_GDRVINFO:
-		rc = e100_ethtool_get_drvinfo(dev, ifr);
-		break;
-	case ETHTOOL_GREGS:
-		rc = e100_ethtool_gregs(dev, ifr);
-		break;
-	case ETHTOOL_NWAY_RST:
-		rc = e100_ethtool_nway_rst(dev, ifr);
-		break;
-	case ETHTOOL_GLINK:
-		rc = e100_ethtool_glink(dev, ifr);
-		break;
-	case ETHTOOL_GEEPROM:
-	case ETHTOOL_SEEPROM:
-		rc = e100_ethtool_eeprom(dev, ifr);
-		break;
-	case ETHTOOL_GSTATS: {
-		struct {
-			struct ethtool_stats cmd;
-			uint64_t data[E100_STATS_LEN];
-		} stats = { {ETHTOOL_GSTATS, E100_STATS_LEN} };
-		struct e100_private *bdp = dev->priv;
-		void *addr = ifr->ifr_data;
-		int i;
-
-		for(i = 0; i < E100_STATS_LEN; i++)
-			stats.data[i] =
-				((unsigned long *)&bdp->drv_stats.net_stats)[i];
-		if(copy_to_user(addr, &stats, sizeof(stats)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GWOL:
-	case ETHTOOL_SWOL:
-		rc = e100_ethtool_wol(dev, ifr);
-		break;
-	case ETHTOOL_TEST:
-		rc = e100_ethtool_test(dev, ifr);
-		break;
-	case ETHTOOL_GSTRINGS:
-		rc = e100_ethtool_gstrings(dev,ifr);
-		break;
-	case ETHTOOL_PHYS_ID:
-		rc = e100_ethtool_led_blink(dev,ifr);
-		break;
-#ifdef	ETHTOOL_GRINGPARAM
-	case ETHTOOL_GRINGPARAM: {
-		struct ethtool_ringparam ering;
-		struct e100_private *bdp = dev->priv;
-		memset((void *) &ering, 0, sizeof(ering));
-		ering.rx_max_pending = E100_MAX_RFD;
-		ering.tx_max_pending = E100_MAX_TCB;
-		ering.rx_pending = bdp->params.RxDescriptors;
-		ering.tx_pending = bdp->params.TxDescriptors;
-		rc = copy_to_user(ifr->ifr_data, &ering, sizeof(ering))
-			? -EFAULT : 0;
-		return rc;
-	}
-#endif
-#ifdef	ETHTOOL_SRINGPARAM
-	case ETHTOOL_SRINGPARAM: {
-		struct ethtool_ringparam ering;
-		struct e100_private *bdp = dev->priv;
-		if (copy_from_user(&ering, ifr->ifr_data, sizeof(ering)))
-			return -EFAULT;
-		if (ering.rx_pending > E100_MAX_RFD 
-		    || ering.rx_pending < E100_MIN_RFD)
-			return -EINVAL;
-		if (ering.tx_pending > E100_MAX_TCB 
-		    || ering.tx_pending < E100_MIN_TCB)
-			return -EINVAL;
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			/* Use new values to open interface */
-			bdp->params.RxDescriptors = ering.rx_pending;
-			bdp->params.TxDescriptors = ering.tx_pending;
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-		else {
-			bdp->params.RxDescriptors = ering.rx_pending;
-			bdp->params.TxDescriptors = ering.tx_pending;
-		}
-		return 0;
-	}
-#endif
-#ifdef	ETHTOOL_GPAUSEPARAM
-	case ETHTOOL_GPAUSEPARAM: {
-		struct ethtool_pauseparam epause;
-		struct e100_private *bdp = dev->priv;
-		memset((void *) &epause, 0, sizeof(epause));
-		if ((bdp->flags & IS_BACHELOR)
-		    && (bdp->params.b_params & PRM_FC)) {
-			epause.autoneg = 1;
-			if (bdp->flags && DF_LINK_FC_CAP) {
-				epause.rx_pause = 1;
-				epause.tx_pause = 1;
-			}
-			if (bdp->flags && DF_LINK_FC_TX_ONLY)
-				epause.tx_pause = 1;
-		}
-		rc = copy_to_user(ifr->ifr_data, &epause, sizeof(epause))
-			? -EFAULT : 0;
-		return rc;
-	}
-#endif
-#ifdef	ETHTOOL_SPAUSEPARAM
-	case ETHTOOL_SPAUSEPARAM: {
-		struct ethtool_pauseparam epause;
-		struct e100_private *bdp = dev->priv;
-		if (!(bdp->flags & IS_BACHELOR))
-			return -EINVAL;
-		if (copy_from_user(&epause, ifr->ifr_data, sizeof(epause)))
-			return -EFAULT;
-		if (epause.autoneg == 1)
-			bdp->params.b_params |= PRM_FC;
-		else
-			bdp->params.b_params &= ~PRM_FC;
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-		return 0;
-	}
-#endif
-#ifdef	ETHTOOL_GRXCSUM
-	case ETHTOOL_GRXCSUM:
-	case ETHTOOL_GTXCSUM:
-	case ETHTOOL_GSG:
-	{	struct ethtool_value eval;
-		struct e100_private *bdp = dev->priv;
-		memset((void *) &eval, 0, sizeof(eval));
-		if ((ecmd.cmd == ETHTOOL_GRXCSUM) 
-		    && (bdp->params.b_params & PRM_XSUMRX))
-			eval.data = 1;
-		else
-			eval.data = 0;
-		rc = copy_to_user(ifr->ifr_data, &eval, sizeof(eval))
-			? -EFAULT : 0;
-		return rc;
-	}
-#endif
-#ifdef	ETHTOOL_SRXCSUM
-	case ETHTOOL_SRXCSUM:
-	case ETHTOOL_STXCSUM:
-	case ETHTOOL_SSG:
-	{	struct ethtool_value eval;
-		struct e100_private *bdp = dev->priv;
-		if (copy_from_user(&eval, ifr->ifr_data, sizeof(eval)))
-			return -EFAULT;
-		if (ecmd.cmd == ETHTOOL_SRXCSUM) {
-			if (eval.data == 1) { 
-				if (bdp->rev_id >= D101MA_REV_ID)
-					bdp->params.b_params |= PRM_XSUMRX;
-				else
-					return -EINVAL;
-			} else {
-				if (bdp->rev_id >= D101MA_REV_ID)
-					bdp->params.b_params &= ~PRM_XSUMRX;
-				else
-					return 0;
-			}
-		} else {
-			if (eval.data == 1)
-				return -EINVAL;
-			else
-				return 0;
-		}
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-		return 0;
-	}
-#endif
-	default:
-		break;
-	}			//switch
-	return rc;
-}
-
-static int
-e100_ethtool_get_settings(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_cmd ecmd;
-	u16 advert = 0;
-
-	memset((void *) &ecmd, 0, sizeof (ecmd));
-
-	bdp = dev->priv;
-
-	ecmd.supported = bdp->speed_duplex_caps;
-
-	ecmd.port =
-		(bdp->speed_duplex_caps & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
-	ecmd.transceiver = XCVR_INTERNAL;
-	ecmd.phy_address = bdp->phy_addr;
-
-	if (netif_carrier_ok(bdp->device)) {
-		ecmd.speed = bdp->cur_line_speed;
-		ecmd.duplex =
-			(bdp->cur_dplx_mode == HALF_DUPLEX) ? DUPLEX_HALF : DUPLEX_FULL;
-	}
-	else {
-		ecmd.speed = -1;
-		ecmd.duplex = -1;
-	}
-
-	ecmd.advertising = ADVERTISED_TP;
-
-	if (bdp->params.e100_speed_duplex == E100_AUTONEG) {
-		ecmd.autoneg = AUTONEG_ENABLE;
-		ecmd.advertising |= ADVERTISED_Autoneg;
-	} else {
-		ecmd.autoneg = AUTONEG_DISABLE;
-	}
-
-	if (bdp->speed_duplex_caps & SUPPORTED_MII) {
-		e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &advert);
-
-		if (advert & ADVERTISE_10HALF)
-			ecmd.advertising |= ADVERTISED_10baseT_Half;
-		if (advert & ADVERTISE_10FULL)
-			ecmd.advertising |= ADVERTISED_10baseT_Full;
-		if (advert & ADVERTISE_100HALF)
-			ecmd.advertising |= ADVERTISED_100baseT_Half;
-		if (advert & ADVERTISE_100FULL)
-			ecmd.advertising |= ADVERTISED_100baseT_Full;
-	} else {
-		ecmd.autoneg = AUTONEG_DISABLE;
-		ecmd.advertising &= ~ADVERTISED_Autoneg;
-	}
-
-	if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int
-e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	int e100_new_speed_duplex;
-	int ethtool_new_speed_duplex;
-	struct ethtool_cmd ecmd;
-
-	bdp = dev->priv;
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) {
-		return -EFAULT;
-	}
-
-	if ((ecmd.autoneg == AUTONEG_ENABLE)
-	    && (bdp->speed_duplex_caps & SUPPORTED_Autoneg)) {
-		bdp->params.e100_speed_duplex = E100_AUTONEG;
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-	} else {
-		if (ecmd.speed == SPEED_10) {
-			if (ecmd.duplex == DUPLEX_HALF) {
-				e100_new_speed_duplex =
-					E100_SPEED_10_HALF;
-				ethtool_new_speed_duplex =
-					SUPPORTED_10baseT_Half;
-			} else { 
-				e100_new_speed_duplex =
-					E100_SPEED_10_FULL;
-				ethtool_new_speed_duplex =
-					SUPPORTED_10baseT_Full;
-			} 
-		} else { 
-			if (ecmd.duplex == DUPLEX_HALF) {
-				e100_new_speed_duplex =
-					E100_SPEED_100_HALF;
-				ethtool_new_speed_duplex =
-					SUPPORTED_100baseT_Half;
-			} else { 
-				e100_new_speed_duplex =
-					E100_SPEED_100_FULL;
-				ethtool_new_speed_duplex =
-					SUPPORTED_100baseT_Full;
-			} 
-		}
-
-		if (bdp->speed_duplex_caps & ethtool_new_speed_duplex) {
-			bdp->params.e100_speed_duplex =
-				e100_new_speed_duplex;
-			if (netif_running(dev)) {
-				spin_lock_bh(&dev->xmit_lock);
-				e100_close(dev);
-				spin_unlock_bh(&dev->xmit_lock);
-				e100_hw_init(bdp);
-				e100_open(dev);
-			}
-		} else {
-			return -EOPNOTSUPP;
-		} 
-	}
-
-	return 0;
-}
-
-static int
-e100_ethtool_glink(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_value info;
-
-	memset((void *) &info, 0, sizeof (info));
-
-	bdp = dev->priv;
-	info.cmd = ETHTOOL_GLINK;
-
-	/* Consider both PHY link and netif_running */
-	info.data = e100_update_link_state(bdp);
-
-	if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int
-e100_ethtool_test(struct net_device *dev, struct ifreq *ifr)
-{
-	struct ethtool_test *info;
-	int rc = -EFAULT;
-
-	info = kmalloc(sizeof(*info) + max_test_res * sizeof(u64),
-		       GFP_ATOMIC);
-
-	if (!info)
-		return -ENOMEM;
-
-	memset((void *) info, 0, sizeof(*info) +
-				 max_test_res * sizeof(u64));
-
-	if (copy_from_user(info, ifr->ifr_data, sizeof(*info)))
-		goto exit;
-
-	info->flags = e100_run_diag(dev, info->data, info->flags);
-
-	if (!copy_to_user(ifr->ifr_data, info,
-			 sizeof(*info) + max_test_res * sizeof(u64)))
-		rc = 0;
-exit:
-	kfree(info);
-	return rc;
-}
-
-static int
-e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	u32 regs_buff[E100_REGS_LEN];
-	struct ethtool_regs regs = {ETHTOOL_GREGS};
-	void *addr = ifr->ifr_data;
-	u16 mdi_reg;
-
-	bdp = dev->priv;
-
-	if(copy_from_user(&regs, addr, sizeof(regs)))
-		return -EFAULT;
-
-	regs.version = (1 << 24) | bdp->rev_id;
-	regs_buff[0] = readb(&(bdp->scb->scb_cmd_hi)) << 24 |
-		readb(&(bdp->scb->scb_cmd_low)) << 16 |
-		readw(&(bdp->scb->scb_status));
-	e100_mdi_read(bdp, MII_NCONFIG, bdp->phy_addr, &mdi_reg);
-	regs_buff[1] = mdi_reg;
-
-	if(copy_to_user(addr, &regs, sizeof(regs)))
-		return -EFAULT;
-
-	addr += offsetof(struct ethtool_regs, data);
-	if(copy_to_user(addr, regs_buff, regs.len))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int
-e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-
-	bdp = dev->priv;
-
-	if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) &&
-	    (bdp->params.e100_speed_duplex == E100_AUTONEG)) {
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-			e100_hw_init(bdp);
-			e100_open(dev);
-		}
-	} else {
-		return -EFAULT;
-	}
-	return 0;
-}
-
-static int
-e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_drvinfo info;
-
-	memset((void *) &info, 0, sizeof (info));
-
-	bdp = dev->priv;
-
-	strncpy(info.driver, e100_short_driver_name, sizeof (info.driver) - 1);
-	strncpy(info.version, e100_driver_version, sizeof (info.version) - 1);
-	strncpy(info.fw_version, "N/A",
-		sizeof (info.fw_version) - 1);
-	strncpy(info.bus_info, pci_name(bdp->pdev),
-		sizeof (info.bus_info) - 1);
-	info.n_stats = E100_STATS_LEN;
-	info.regdump_len  = E100_REGS_LEN * sizeof(u32);
-	info.eedump_len = (bdp->eeprom_size << 1);	
-	info.testinfo_len = max_test_res;
-	if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int
-e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_eeprom ecmd;
-	u16 eeprom_data[256];
-	u16 *usr_eeprom_ptr;
-	u16 first_word, last_word;
-	int i, max_len;
-	void *ptr;
-	u8 *eeprom_data_bytes = (u8 *)eeprom_data;
-
-	bdp = dev->priv;
-
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
-		return -EFAULT;
-
-	usr_eeprom_ptr =
-		(u16 *) (ifr->ifr_data + offsetof(struct ethtool_eeprom, data));
-
-        max_len = bdp->eeprom_size * 2;
-        
-        if (ecmd.offset > ecmd.offset + ecmd.len)
-        	return -EINVAL;
-        	
-	if ((ecmd.offset + ecmd.len) > max_len)
-		ecmd.len = (max_len - ecmd.offset);
-
-	first_word = ecmd.offset >> 1;
-	last_word = (ecmd.offset + ecmd.len - 1) >> 1;
-		
-	if (first_word >= bdp->eeprom_size)
-		return -EFAULT;
-
-	if (ecmd.cmd == ETHTOOL_GEEPROM) {
-        	for(i = 0; i <= (last_word - first_word); i++)
-			eeprom_data[i] = e100_eeprom_read(bdp, first_word + i);
-
-		ecmd.magic = E100_EEPROM_MAGIC;
-
-		if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd)))
-			return -EFAULT;
-
-		if(ecmd.offset & 1)
-			eeprom_data_bytes++;
-		if (copy_to_user(usr_eeprom_ptr, eeprom_data_bytes, ecmd.len))
-			return -EFAULT;
-	} else {
-		if (ecmd.magic != E100_EEPROM_MAGIC)
-			return -EFAULT;
-
-		ptr = (void *)eeprom_data;
-        	if(ecmd.offset & 1) {
-                	/* need modification of first changed EEPROM word */
-                	/* only the second byte of the word is being modified */
-			eeprom_data[0] = e100_eeprom_read(bdp, first_word);
-                	ptr++;
-        	}
-        	if((ecmd.offset + ecmd.len) & 1) {
-	                /* need modification of last changed EEPROM word */
-	                /* only the first byte of the word is being modified */
-			eeprom_data[last_word - first_word] = 
-				e100_eeprom_read(bdp, last_word);
-		}
-        	if(copy_from_user(ptr, usr_eeprom_ptr, ecmd.len))
-	                return -EFAULT;
-
-		e100_eeprom_write_block(bdp, first_word, eeprom_data,
-					last_word - first_word + 1);
-
-		if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd)))
-			return -EFAULT;
-	}
-	return 0;
-}
-
-#define E100_BLINK_INTERVAL	(HZ/4)
-/**
- * e100_led_control
- * @bdp: atapter's private data struct
- * @led_mdi_op: led operation
- *
- * Software control over adapter's led. The possible operations are:
- * TURN LED OFF, TURN LED ON and RETURN LED CONTROL TO HARDWARE.
- */
-static void
-e100_led_control(struct e100_private *bdp, u16 led_mdi_op)
-{
-	e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL,
-		       bdp->phy_addr, led_mdi_op);
-
-}
-/**
- * e100_led_blink_callback
- * @data: pointer to atapter's private data struct
- *
- * Blink timer callback function. Toggles ON/OFF led status bit and calls
- * led hardware access function. 
- */
-static void
-e100_led_blink_callback(unsigned long data)
-{
-	struct e100_private *bdp = (struct e100_private *) data;
-
-	if(bdp->flags & LED_IS_ON) {
-		bdp->flags &= ~LED_IS_ON;
-		e100_led_control(bdp, PHY_82555_LED_OFF);
-	} else {
-		bdp->flags |= LED_IS_ON;
-		if (bdp->rev_id >= D101MA_REV_ID)
-			e100_led_control(bdp, PHY_82555_LED_ON_559);
-		else
-			e100_led_control(bdp, PHY_82555_LED_ON_PRE_559);
-	}
-
-	mod_timer(&bdp->blink_timer, jiffies + E100_BLINK_INTERVAL);
-}
-/**
- * e100_ethtool_led_blink
- * @dev: pointer to atapter's net_device struct
- * @ifr: pointer to ioctl request structure
- *
- * Blink led ioctl handler. Initialtes blink timer and sleeps until
- * blink period expires. Than it kills timer and returns. The led control
- * is returned back to hardware when blink timer is killed.
- */
-static int
-e100_ethtool_led_blink(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_value ecmd;
-
-	bdp = dev->priv;
-
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
-		return -EFAULT;
-
-	if(!bdp->blink_timer.function) {
-		init_timer(&bdp->blink_timer);
-		bdp->blink_timer.function = e100_led_blink_callback;
-		bdp->blink_timer.data = (unsigned long) bdp;
-	}
-
-	mod_timer(&bdp->blink_timer, jiffies);
-
-	set_current_state(TASK_INTERRUPTIBLE);
-
-	if ((!ecmd.data) || (ecmd.data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)))
-		ecmd.data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
-
-	schedule_timeout(ecmd.data * HZ);
-
-	del_timer_sync(&bdp->blink_timer);
-
-	e100_led_control(bdp, PHY_82555_LED_NORMAL_CONTROL);
-
-	return 0;
-}
-
-static inline int
-e100_10BaseT_adapter(struct e100_private *bdp)
-{
-	return ((bdp->pdev->device == 0x1229) &&
-		(bdp->pdev->subsystem_vendor == 0x8086) &&
-		(bdp->pdev->subsystem_device == 0x0003));
-}
-
-static void
-e100_get_speed_duplex_caps(struct e100_private *bdp)
-{
-	u16 status;
-
-	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status);
-
-	bdp->speed_duplex_caps = 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_ANEGCAPABLE) ? SUPPORTED_Autoneg : 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_10HALF) ? SUPPORTED_10baseT_Half : 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_10FULL) ? SUPPORTED_10baseT_Full : 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_100HALF) ? SUPPORTED_100baseT_Half : 0;
-
-	bdp->speed_duplex_caps |=
-		(status & BMSR_100FULL) ? SUPPORTED_100baseT_Full : 0;
-
-	if (IS_NC3133(bdp))
-		bdp->speed_duplex_caps =
-			(SUPPORTED_FIBRE | SUPPORTED_100baseT_Full);
-	else
-		bdp->speed_duplex_caps |= SUPPORTED_TP;
-
-	if ((status == 0xFFFF) && e100_10BaseT_adapter(bdp)) {
-		bdp->speed_duplex_caps =
-			(SUPPORTED_10baseT_Half | SUPPORTED_TP);
-	} else {
-		bdp->speed_duplex_caps |= SUPPORTED_MII;
-	}
-
-}
-
-#ifdef CONFIG_PM
-static unsigned char
-e100_setup_filter(struct e100_private *bdp)
-{
-	cb_header_t *ntcb_hdr;
-	unsigned char res = false;
-	nxmit_cb_entry_t *cmd;
-
-	if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) {
-		goto exit;
-	}
-
-	ntcb_hdr = (cb_header_t *) cmd->non_tx_cmd;
-	ntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_LOAD_FILTER);
-
-	/* Set EL and FIX bit */
-	(cmd->non_tx_cmd)->ntcb.filter.filter_data[0] =
-		__constant_cpu_to_le32(CB_FILTER_EL | CB_FILTER_FIX);
-
-	if (bdp->wolopts & WAKE_UCAST) {
-		(cmd->non_tx_cmd)->ntcb.filter.filter_data[0] |=
-			__constant_cpu_to_le32(CB_FILTER_IA_MATCH);
-	}
-
-	if (bdp->wolopts & WAKE_ARP) {
-		/* Setup ARP bit and lower IP parts */
-		/* bdp->ip_lbytes contains 2 lower bytes of IP address in network byte order */
-		(cmd->non_tx_cmd)->ntcb.filter.filter_data[0] |=
-			cpu_to_le32(CB_FILTER_ARP | bdp->ip_lbytes);
-	}
-
-	res = e100_exec_non_cu_cmd(bdp, cmd);
-	if (!res)
-		printk(KERN_WARNING "e100: %s: Filter setup failed\n",
-		       bdp->device->name);
-
-exit:
-	return res;
-
-}
-
-static void
-e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp)
-{
-	e100_config_wol(bdp);
-
-	if (e100_config(bdp)) {
-		if (bdp->wolopts & (WAKE_UCAST | WAKE_ARP))
-			if (!e100_setup_filter(bdp))
-				printk(KERN_ERR
-				       "e100: WOL options failed\n");
-	} else {
-		printk(KERN_ERR "e100: config WOL failed\n");
-	}
-}
-#endif
-
-static u16
-e100_get_ip_lbytes(struct net_device *dev)
-{
-	struct in_ifaddr *ifa;
-	struct in_device *in_dev;
-	u32 res = 0;
-
-	in_dev = (struct in_device *) dev->ip_ptr;
-	/* Check if any in_device bound to interface */
-	if (in_dev) {
-		/* Check if any IP address is bound to interface */
-		if ((ifa = in_dev->ifa_list) != NULL) {
-			res = __constant_ntohl(ifa->ifa_address);
-			res = __constant_htons(res & 0x0000ffff);
-		}
-	}
-	return res;
-}
-
-static int
-e100_ethtool_wol(struct net_device *dev, struct ifreq *ifr)
-{
-	struct e100_private *bdp;
-	struct ethtool_wolinfo wolinfo;
-	int res = 0;
-
-	bdp = dev->priv;
-
-	if (copy_from_user(&wolinfo, ifr->ifr_data, sizeof (wolinfo))) {
-		return -EFAULT;
-	}
-
-	switch (wolinfo.cmd) {
-	case ETHTOOL_GWOL:
-		wolinfo.supported = bdp->wolsupported;
-		wolinfo.wolopts = bdp->wolopts;
-		if (copy_to_user(ifr->ifr_data, &wolinfo, sizeof (wolinfo)))
-			res = -EFAULT;
-		break;
-	case ETHTOOL_SWOL:
-		/* If ALL requests are supported or request is DISABLE wol */
-		if (((wolinfo.wolopts & bdp->wolsupported) == wolinfo.wolopts)
-		    || (wolinfo.wolopts == 0)) {
-			bdp->wolopts = wolinfo.wolopts;
-		} else {
-			res = -EOPNOTSUPP;
-		}
-		if (wolinfo.wolopts & WAKE_ARP)
-			bdp->ip_lbytes = e100_get_ip_lbytes(dev);
-		break;
-	default:
-		break;
-	}
-	return res;
-}
-
-static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr)
-{
-	struct ethtool_gstrings info;
-	char *strings = NULL;
-	char *usr_strings;
-	int i;
-
-	memset((void *) &info, 0, sizeof(info));
-
-	usr_strings = (u8 *) (ifr->ifr_data + 
-			      offsetof(struct ethtool_gstrings, data));
-
-	if (copy_from_user(&info, ifr->ifr_data, sizeof (info)))
-		return -EFAULT;
-
-	switch (info.string_set) {
-	case ETH_SS_TEST: {
-		int ret = 0;
-		if (info.len > max_test_res)
-			info.len = max_test_res;
-		strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC);
-		if (!strings)
-			return -ENOMEM;
-		memset(strings, 0, info.len * ETH_GSTRING_LEN);
-
-		for (i = 0; i < info.len; i++) {
-			sprintf(strings + i * ETH_GSTRING_LEN, "%s",
-				test_strings[i]);
-		}
-		if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
-			ret = -EFAULT;
-		if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN))
-			ret = -EFAULT;
-		kfree(strings);
-		return ret;
-	}
-	case ETH_SS_STATS: {
-		char *strings = NULL;
-		void *addr = ifr->ifr_data;
-		info.len = E100_STATS_LEN;
-		strings = *e100_gstrings_stats;
-		if(copy_to_user(ifr->ifr_data, &info, sizeof(info)))
-			return -EFAULT;
-		addr += offsetof(struct ethtool_gstrings, data);
-		if(copy_to_user(addr, strings,
-		   info.len * ETH_GSTRING_LEN))
-			return -EFAULT;
-		return 0;
-	}
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static int
-e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	struct e100_private *bdp;
-	struct mii_ioctl_data *data_ptr =
-		(struct mii_ioctl_data *) &(ifr->ifr_data);
-
-	bdp = dev->priv;
-
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		data_ptr->phy_id = bdp->phy_addr & 0x1f;
-		break;
-
-	case SIOCGMIIREG:
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		e100_mdi_read(bdp, data_ptr->reg_num & 0x1f, bdp->phy_addr,
-			      &(data_ptr->val_out));
-		break;
-
-	case SIOCSMIIREG:
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		/* If reg = 0 && change speed/duplex */
-		if (data_ptr->reg_num == 0 && 
-			(data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART) /* restart cmd */
-			|| data_ptr->val_in == (BMCR_RESET) /* reset cmd */ 
-			|| data_ptr->val_in & (BMCR_SPEED100 | BMCR_FULLDPLX) 
-			|| data_ptr->val_in == 0)) {
-				if (data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART)
-					|| data_ptr->val_in == (BMCR_RESET))
-					bdp->params.e100_speed_duplex = E100_AUTONEG;
-				else if (data_ptr->val_in == (BMCR_SPEED100 | BMCR_FULLDPLX))
-					bdp->params.e100_speed_duplex = E100_SPEED_100_FULL;
-				else if (data_ptr->val_in == (BMCR_SPEED100))
-					bdp->params.e100_speed_duplex = E100_SPEED_100_HALF;
-				else if (data_ptr->val_in == (BMCR_FULLDPLX))
-					bdp->params.e100_speed_duplex = E100_SPEED_10_FULL;
-				else
-					bdp->params.e100_speed_duplex = E100_SPEED_10_HALF;
-				if (netif_running(dev)) {
-					spin_lock_bh(&dev->xmit_lock);
-					e100_close(dev);
-					spin_unlock_bh(&dev->xmit_lock);
-					e100_hw_init(bdp);
-					e100_open(dev);
-				}
-		}
-		else 
-			/* Only allows changing speed/duplex */
-			return -EINVAL;
-		
-		break;
-
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-nxmit_cb_entry_t *
-e100_alloc_non_tx_cmd(struct e100_private *bdp)
-{
-	nxmit_cb_entry_t *non_tx_cmd_elem;
-
-	if (!(non_tx_cmd_elem = (nxmit_cb_entry_t *)
-	      kmalloc(sizeof (nxmit_cb_entry_t), GFP_ATOMIC))) {
-		return NULL;
-	}
-	non_tx_cmd_elem->non_tx_cmd =
-		pci_alloc_consistent(bdp->pdev, sizeof (nxmit_cb_t),
-				     &(non_tx_cmd_elem->dma_addr));
-	if (non_tx_cmd_elem->non_tx_cmd == NULL) {
-		kfree(non_tx_cmd_elem);
-		return NULL;
-	}
-	return non_tx_cmd_elem;
-}
-
-void
-e100_free_non_tx_cmd(struct e100_private *bdp,
-		     nxmit_cb_entry_t *non_tx_cmd_elem)
-{
-	pci_free_consistent(bdp->pdev, sizeof (nxmit_cb_t),
-			    non_tx_cmd_elem->non_tx_cmd,
-			    non_tx_cmd_elem->dma_addr);
-	kfree(non_tx_cmd_elem);
-}
-
-static void
-e100_free_nontx_list(struct e100_private *bdp)
-{
-	nxmit_cb_entry_t *command;
-	int i;
-
-	while (!list_empty(&bdp->non_tx_cmd_list)) {
-		command = list_entry(bdp->non_tx_cmd_list.next,
-				     nxmit_cb_entry_t, list_elem);
-		list_del(&(command->list_elem));
-		e100_free_non_tx_cmd(bdp, command);
-	}
-
-	for (i = 0; i < CB_MAX_NONTX_CMD; i++) {
-		bdp->same_cmd_entry[i] = NULL;
-	}
-}
-
-static unsigned char
-e100_delayed_exec_non_cu_cmd(struct e100_private *bdp,
-			     nxmit_cb_entry_t *command)
-{
-	nxmit_cb_entry_t *same_command;
-	cb_header_t *ntcb_hdr;
-	u16 cmd;
-
-	ntcb_hdr = (cb_header_t *) command->non_tx_cmd;
-
-	cmd = CB_CMD_MASK & le16_to_cpu(ntcb_hdr->cb_cmd);
-
-	spin_lock_bh(&(bdp->bd_non_tx_lock));
-
-	same_command = bdp->same_cmd_entry[cmd];
-
-	if (same_command != NULL) {
-		memcpy((void *) (same_command->non_tx_cmd),
-		       (void *) (command->non_tx_cmd), sizeof (nxmit_cb_t));
-		e100_free_non_tx_cmd(bdp, command);
-	} else {
-		list_add_tail(&(command->list_elem), &(bdp->non_tx_cmd_list));
-		bdp->same_cmd_entry[cmd] = command;
-	}
-
-	if (bdp->non_tx_command_state == E100_NON_TX_IDLE) {
-		bdp->non_tx_command_state = E100_WAIT_TX_FINISH;
-		mod_timer(&(bdp->nontx_timer_id), jiffies + 1);
-	}
-
-	spin_unlock_bh(&(bdp->bd_non_tx_lock));
-	return true;
-}
-
-static void
-e100_non_tx_background(unsigned long ptr)
-{
-	struct e100_private *bdp = (struct e100_private *) ptr;
-	nxmit_cb_entry_t *active_command;
-	int restart = true;
-	cb_header_t *non_tx_cmd;
-	u8 sub_cmd;
-
-	spin_lock_bh(&(bdp->bd_non_tx_lock));
-
-	switch (bdp->non_tx_command_state) {
-	case E100_WAIT_TX_FINISH:
-		if (bdp->last_tcb != NULL) {
-			rmb();
-			if ((bdp->last_tcb->tcb_hdr.cb_status &
-			     __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0)
-				goto exit;
-		}
-		if ((readw(&bdp->scb->scb_status) & SCB_CUS_MASK) ==
-		    SCB_CUS_ACTIVE) {
-			goto exit;
-		}
-		break;
-
-	case E100_WAIT_NON_TX_FINISH:
-		active_command = list_entry(bdp->non_tx_cmd_list.next,
-					    nxmit_cb_entry_t, list_elem);
-		rmb();
-
-		if (((((cb_header_t *) (active_command->non_tx_cmd))->cb_status
-		      & __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0)
-		    && time_before(jiffies, active_command->expiration_time)) {
-			goto exit;
-		} else {
-			non_tx_cmd = (cb_header_t *) active_command->non_tx_cmd;
-			sub_cmd = CB_CMD_MASK & le16_to_cpu(non_tx_cmd->cb_cmd);
-#ifdef E100_CU_DEBUG			
-			if (!(non_tx_cmd->cb_status 
-			    & __constant_cpu_to_le16(CB_STATUS_COMPLETE)))
-				printk(KERN_ERR "e100: %s: Queued "
-					"command (%x) timeout\n", 
-					bdp->device->name, sub_cmd);
-#endif			
-			list_del(&(active_command->list_elem));
-			e100_free_non_tx_cmd(bdp, active_command);
-		}
-		break;
-
-	default:
-		break;
-	}			//switch
-
-	if (list_empty(&bdp->non_tx_cmd_list)) {
-		bdp->non_tx_command_state = E100_NON_TX_IDLE;
-		spin_lock_irq(&(bdp->bd_lock));
-		bdp->next_cu_cmd = START_WAIT;
-		spin_unlock_irq(&(bdp->bd_lock));
-		restart = false;
-		goto exit;
-	} else {
-		u16 cmd_type;
-
-		bdp->non_tx_command_state = E100_WAIT_NON_TX_FINISH;
-		active_command = list_entry(bdp->non_tx_cmd_list.next,
-					    nxmit_cb_entry_t, list_elem);
-		sub_cmd = ((cb_header_t *) active_command->non_tx_cmd)->cb_cmd;
-		spin_lock_irq(&(bdp->bd_lock));
-		e100_wait_exec_cmplx(bdp, active_command->dma_addr,
-				     SCB_CUC_START, sub_cmd);
-		spin_unlock_irq(&(bdp->bd_lock));
-		active_command->expiration_time = jiffies + HZ;
-		cmd_type = CB_CMD_MASK &
-			le16_to_cpu(((cb_header_t *)
-				     (active_command->non_tx_cmd))->cb_cmd);
-		bdp->same_cmd_entry[cmd_type] = NULL;
-	}
-
-exit:
-	if (restart) {
-		mod_timer(&(bdp->nontx_timer_id), jiffies + 1);
-	} else {
-		if (netif_running(bdp->device))
-			netif_wake_queue(bdp->device);
-	}
-	spin_unlock_bh(&(bdp->bd_non_tx_lock));
-}
-
-static void
-e100_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
-	struct e100_private *bdp = netdev->priv;
-
-	e100_disable_clear_intr(bdp);
-	bdp->vlgrp = grp;
-
-	if(grp) {
-		/* enable VLAN tag insert/strip */
-		e100_config_vlan_drop(bdp, true);
-
-	} else {
-		/* disable VLAN tag insert/strip */
-		e100_config_vlan_drop(bdp, false);
-	}
-
-	e100_config(bdp);
-	e100_set_intr_mask(bdp);
-}
-
-static void
-e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
-	/* We don't do Vlan filtering */
-	return;
-}
-
-static void
-e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
-	struct e100_private *bdp = netdev->priv;
-
-	if(bdp->vlgrp)
-		bdp->vlgrp->vlan_devices[vid] = NULL;
-	/* We don't do Vlan filtering */
-	return;
-}
-
-#ifdef CONFIG_PM
-static int
-e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
-{
-        struct pci_dev *pdev = NULL;
-	
-        switch(event) {
-        case SYS_DOWN:
-        case SYS_HALT:
-        case SYS_POWER_OFF:
-		while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
-                        if(pci_dev_driver(pdev) == &e100_driver) {
-				/* If net_device struct is allocated? */
-                                if (pci_get_drvdata(pdev))
-					e100_suspend(pdev, 3);
-
-			}
-		}
-        }
-        return NOTIFY_DONE;
-}
-
-static int
-e100_suspend(struct pci_dev *pcid, u32 state)
-{
-	struct net_device *netdev = pci_get_drvdata(pcid);
-	struct e100_private *bdp = netdev->priv;
-
-	e100_isolate_driver(bdp);
-	pci_save_state(pcid, bdp->pci_state);
-
-	/* Enable or disable WoL */
-	e100_do_wol(pcid, bdp);
-	
-	/* If wol is enabled */
-	if (bdp->wolopts || e100_asf_enabled(bdp)) {
-		pci_enable_wake(pcid, 3, 1);	/* Enable PME for power state D3 */
-		pci_set_power_state(pcid, 3);	/* Set power state to D3.        */
-	} else {
-		/* Disable bus mastering */
-		pci_disable_device(pcid);
-		pci_set_power_state(pcid, state);
-	}
-	return 0;
-}
-
-static int
-e100_resume(struct pci_dev *pcid)
-{
-	struct net_device *netdev = pci_get_drvdata(pcid);
-	struct e100_private *bdp = netdev->priv;
-
-	pci_set_power_state(pcid, 0);
-	pci_enable_wake(pcid, 0, 0);	/* Clear PME status and disable PME */
-	pci_restore_state(pcid, bdp->pci_state);
-
-	/* Also do device full reset because device was in D3 state */
-	e100_deisolate_driver(bdp, true);
-
-	return 0;
-}
-
-/**
- * e100_asf_enabled - checks if ASF is configured on the current adaper
- *                    by reading registers 0xD and 0x90 in the EEPROM 
- * @bdp: atapter's private data struct
- *
- * Returns: true if ASF is enabled
- */
-static unsigned char
-e100_asf_enabled(struct e100_private *bdp)
-{
-	u16 asf_reg;
-	u16 smbus_addr_reg;
-	if ((bdp->pdev->device >= 0x1050) && (bdp->pdev->device <= 0x1055)) {
-		asf_reg = e100_eeprom_read(bdp, EEPROM_CONFIG_ASF);
-		if ((asf_reg & EEPROM_FLAG_ASF)
-		    && !(asf_reg & EEPROM_FLAG_GCL)) {
-			smbus_addr_reg = 
-				e100_eeprom_read(bdp, EEPROM_SMBUS_ADDR);
-			if ((smbus_addr_reg & 0xFF) != 0xFE) 
-				return true;
-		}
-	}
-	return false;
-}
-#endif /* CONFIG_PM */
-
-#ifdef E100_CU_DEBUG
-unsigned char
-e100_cu_unknown_state(struct e100_private *bdp)
-{
-	u8 scb_cmd_low;
-	u16 scb_status;
-	scb_cmd_low = bdp->scb->scb_cmd_low;
-	scb_status = le16_to_cpu(bdp->scb->scb_status);
-	/* If CU is active and executing unknown cmd */
-	if (scb_status & SCB_CUS_ACTIVE && scb_cmd_low & SCB_CUC_UNKNOWN)
-		return true;
-	else
-		return false;
-}
-#endif
-
diff -Nru a/drivers/net/e100/e100_phy.c b/drivers/net/e100/e100_phy.c
--- a/drivers/net/e100/e100_phy.c	Wed Feb 11 22:30:58 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1163 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#include "e100_phy.h"
-
-void e100_handle_zlock(struct e100_private *bdp);
-
-/* 
- * Procedure:	e100_mdi_write
- *
- * Description: This routine will write a value to the specified MII register
- *		of an external MDI compliant device (e.g. PHY 100).  The
- *		command will execute in polled mode.
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *	reg_addr - The MII register that we are writing to
- *	phy_addr - The MDI address of the Phy component.
- *	data - The value that we are writing to the MII register.
- *
- * Returns:
- *	NOTHING
- */
-int
-e100_mdi_write(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 data)
-{
-	int e100_retry;
-	u32 temp_val;
-	unsigned int mdi_cntrl;
-
-	spin_lock_bh(&bdp->mdi_access_lock);
-	temp_val = (((u32) data) | (reg_addr << 16) |
-		    (phy_addr << 21) | (MDI_WRITE << 26));
-	writel(temp_val, &bdp->scb->scb_mdi_cntrl);
-	readw(&bdp->scb->scb_status);
-
-	/* wait 20usec before checking status */
-	udelay(20);
-
-	/* poll for the mdi write to complete */
-	e100_retry = E100_CMD_WAIT;
-	while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) {
-
-		udelay(20);
-		e100_retry--;
-	}
-	spin_unlock_bh(&bdp->mdi_access_lock);
-	if (mdi_cntrl & MDI_PHY_READY) 
-		return 0;
-	else {
-		printk(KERN_ERR "e100: MDI write timeout\n");
-		return 1;
-	}
-}
-
-/* 
- * Procedure:	e100_mdi_read
- *
- * Description: This routine will read a value from the specified MII register
- *		of an external MDI compliant device (e.g. PHY 100), and return
- *		it to the calling routine.  The command will execute in polled
- *		mode.
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *	reg_addr - The MII register that we are reading from
- *	phy_addr - The MDI address of the Phy component.
- *
- * Results:
- *	data - The value that we read from the MII register.
- *
- * Returns:
- *	NOTHING
- */
-int
-e100_mdi_read(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 *data)
-{
-	int e100_retry;
-	u32 temp_val;
-	unsigned int mdi_cntrl;
-
-	spin_lock_bh(&bdp->mdi_access_lock);
-	/* Issue the read command to the MDI control register. */
-	temp_val = ((reg_addr << 16) | (phy_addr << 21) | (MDI_READ << 26));
-	writel(temp_val, &bdp->scb->scb_mdi_cntrl);
-	readw(&bdp->scb->scb_status);
-
-	/* wait 20usec before checking status */
-	udelay(20);
-
-	/* poll for the mdi read to complete */
-	e100_retry = E100_CMD_WAIT;
-	while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) {
-
-		udelay(20);
-		e100_retry--;
-	}
-
-	spin_unlock_bh(&bdp->mdi_access_lock);
-	if (mdi_cntrl & MDI_PHY_READY) {
-		/* return the lower word */
-		*data = (u16) mdi_cntrl;
-		return 0;
-	}
-	else {
-		printk(KERN_ERR "e100: MDI read timeout\n");
-		return 1;
-	}
-}
-
-static unsigned char
-e100_phy_valid(struct e100_private *bdp, unsigned int phy_address)
-{
-	u16 ctrl_reg, stat_reg;
-
-	/* Read the MDI control register */
-	e100_mdi_read(bdp, MII_BMCR, phy_address, &ctrl_reg);
-
-	/* Read the status register twice, bacause of sticky bits */
-	e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg);
-	e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg);
-
-	if ((ctrl_reg == 0xffff) || ((stat_reg == 0) && (ctrl_reg == 0)))
-		return false;
-
-	return true;
-}
-
-static void
-e100_phy_address_detect(struct e100_private *bdp)
-{
-	unsigned int addr;
-	unsigned char valid_phy_found = false;
-
-	if (IS_NC3133(bdp)) {
-		bdp->phy_addr = 0;
-		return;
-	}
-
-	if (e100_phy_valid(bdp, PHY_DEFAULT_ADDRESS)) {
-		bdp->phy_addr = PHY_DEFAULT_ADDRESS;
-		valid_phy_found = true;
-
-	} else {
-		for (addr = MIN_PHY_ADDR; addr <= MAX_PHY_ADDR; addr++) {
-			if (e100_phy_valid(bdp, addr)) {
-				bdp->phy_addr = addr;
-				valid_phy_found = true;
-				break;
-			}
-		}
-	}
-
-	if (!valid_phy_found) {
-		bdp->phy_addr = PHY_ADDRESS_503;
-	}
-}
-
-static void
-e100_phy_id_detect(struct e100_private *bdp)
-{
-	u16 low_id_reg, high_id_reg;
-
-	if (bdp->phy_addr == PHY_ADDRESS_503) {
-		bdp->PhyId = PHY_503;
-		return;
-	}
-	if (!(bdp->flags & IS_ICH)) {
-		if (bdp->rev_id >= D102_REV_ID) {
-			bdp->PhyId = PHY_82562ET;
-			return;
-		}
-	}
-
-	/* Read phy id from the MII register */
-	e100_mdi_read(bdp, MII_PHYSID1, bdp->phy_addr, &low_id_reg);
-	e100_mdi_read(bdp, MII_PHYSID2, bdp->phy_addr, &high_id_reg);
-
-	bdp->PhyId = ((unsigned int) low_id_reg |
-		      ((unsigned int) high_id_reg << 16));
-}
-
-static void
-e100_phy_isolate(struct e100_private *bdp)
-{
-	unsigned int phy_address;
-	u16 ctrl_reg;
-
-	/* Go over all phy addresses. Deisolate the selected one, and isolate
-	 * all the rest */
-	for (phy_address = 0; phy_address <= MAX_PHY_ADDR; phy_address++) {
-		if (phy_address != bdp->phy_addr) {
-			e100_mdi_write(bdp, MII_BMCR, phy_address,
-				       BMCR_ISOLATE);
-
-		} else {
-			e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &ctrl_reg);
-			ctrl_reg &= ~BMCR_ISOLATE;
-			e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
-		}
-
-		udelay(100);
-	}
-}
-
-static unsigned char
-e100_phy_specific_setup(struct e100_private *bdp)
-{
-	u16 misc_reg;
-
-	if (bdp->phy_addr == PHY_ADDRESS_503) {
-		switch (bdp->params.e100_speed_duplex) {
-		case E100_AUTONEG:
-			/* The adapter can't autoneg. so set to 10/HALF */
-			printk(KERN_INFO
-			       "e100: 503 serial component detected which "
-			       "cannot autonegotiate\n");
-			printk(KERN_INFO
-			       "e100: speed/duplex forced to "
-			       "10Mbps / Half duplex\n");
-			bdp->params.e100_speed_duplex = E100_SPEED_10_HALF;
-			break;
-
-		case E100_SPEED_100_HALF:
-		case E100_SPEED_100_FULL:
-			printk(KERN_ERR
-			       "e100: 503 serial component detected "
-			       "which does not support 100Mbps\n");
-			printk(KERN_ERR
-			       "e100: Change the forced speed/duplex "
-			       "to a supported setting\n");
-			return false;
-		}
-
-		return true;
-	}
-
-	if (IS_NC3133(bdp)) {
-		u16 int_reg;
-
-		/* enable 100BASE fiber interface */
-		e100_mdi_write(bdp, MDI_NC3133_CONFIG_REG, bdp->phy_addr,
-			       MDI_NC3133_100FX_ENABLE);
-
-		if ((bdp->params.e100_speed_duplex != E100_AUTONEG) &&
-		    (bdp->params.e100_speed_duplex != E100_SPEED_100_FULL)) {
-			/* just inform user about 100 full */
-			printk(KERN_ERR "e100: NC3133 NIC can only run "
-			       "at 100Mbps full duplex\n");
-		}
-
-		bdp->params.e100_speed_duplex = E100_SPEED_100_FULL;
-
-		/* enable interrupts */
-		e100_mdi_read(bdp, MDI_NC3133_INT_ENABLE_REG,
-			      bdp->phy_addr, &int_reg);
-		int_reg |= MDI_NC3133_INT_ENABLE;
-		e100_mdi_write(bdp, MDI_NC3133_INT_ENABLE_REG,
-			       bdp->phy_addr, int_reg);
-	}
-
-	/* Handle the National TX */
-	if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_NSC_TX) {
-		e100_mdi_read(bdp, NSC_CONG_CONTROL_REG,
-			      bdp->phy_addr, &misc_reg);
-
-		misc_reg |= NSC_TX_CONG_TXREADY;
-
-		/* disable the congestion control bit in the National Phy */
-		misc_reg &= ~NSC_TX_CONG_ENABLE;
-
-		e100_mdi_write(bdp, NSC_CONG_CONTROL_REG,
-			       bdp->phy_addr, misc_reg);
-	}
-
-	return true;
-}
-
-/* 
- * Procedure:	e100_phy_fix_squelch
- *
- * Description:
- *	Help find link on certain rare scenarios.
- *	NOTE: This routine must be called once per watchdog,
- *	      and *after* setting the current link state.
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *
- * Returns:
- *	NOTHING
- */
-static void
-e100_phy_fix_squelch(struct e100_private *bdp)
-{
-	if ((bdp->PhyId != PHY_82555_TX) || (bdp->flags & DF_SPEED_FORCED))
-		return;
-
-	if (netif_carrier_ok(bdp->device)) {
-		switch (bdp->PhyState) {
-		case 0:
-			break;
-		case 1:
-			e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-				       bdp->phy_addr, 0x0000);
-			break;
-		case 2:
-			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-				       bdp->phy_addr, 0x3000);
-			break;
-		}
-		bdp->PhyState = 0;
-		bdp->PhyDelay = 0;
-
-	} else if (!bdp->PhyDelay--) {
-		switch (bdp->PhyState) {
-		case 0:
-			e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-				       bdp->phy_addr, EXTENDED_SQUELCH_BIT);
-			bdp->PhyState = 1;
-			break;
-		case 1:
-			e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-				       bdp->phy_addr, 0x0000);
-			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-				       bdp->phy_addr, 0x2010);
-			bdp->PhyState = 2;
-			break;
-		case 2:
-			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-				       bdp->phy_addr, 0x3000);
-			bdp->PhyState = 0;
-			break;
-		}
-
-		e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
-			       BMCR_ANENABLE | BMCR_ANRESTART);
-		bdp->PhyDelay = 3;
-	}
-}
-
-/* 
- * Procedure:	e100_fix_polarity
- *
- * Description:
- *	Fix for 82555 auto-polarity toggle problem. With a short cable 
- *	connecting an 82555 with an 840A link partner, if the medium is noisy,
- *	the 82555 sometime thinks that the polarity might be wrong and so 
- *	toggles polarity. This happens repeatedly and results in a high bit 
- *	error rate.
- *	NOTE: This happens only at 10 Mbps
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *
- * Returns:
- *	NOTHING
- */
-static void
-e100_fix_polarity(struct e100_private *bdp)
-{
-	u16 status;
-	u16 errors;
-	u16 misc_reg;
-	int speed;
-
-	if ((bdp->PhyId != PHY_82555_TX) && (bdp->PhyId != PHY_82562ET) &&
-	    (bdp->PhyId != PHY_82562EM))
-		return;
-
-	/* If the user wants auto-polarity disabled, do only that and nothing *
-	 * else. * e100_autopolarity == 0 means disable --- we do just the
-	 * disabling * e100_autopolarity == 1 means enable  --- we do nothing at
-	 * all * e100_autopolarity >= 2 means we do the workaround code. */
-	/* Change for 82558 enhancement */
-	switch (E100_AUTOPOLARITY) {
-	case 0:
-		e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,
-			      bdp->phy_addr, &misc_reg);
-		e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr,
-			       (u16) (misc_reg | DISABLE_AUTO_POLARITY));
-		break;
-
-	case 1:
-		e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,
-			      bdp->phy_addr, &misc_reg);
-		e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr,
-			       (u16) (misc_reg & ~DISABLE_AUTO_POLARITY));
-		break;
-
-	case 2:
-		/* we do this only if link is up */
-		if (!netif_carrier_ok(bdp->device)) {
-			break;
-		}
-
-		e100_mdi_read(bdp, PHY_82555_CSR, bdp->phy_addr, &status);
-		speed = (status & PHY_82555_SPEED_BIT) ? 100 : 10;
-
-		/* we need to do this only if speed is 10 */
-		if (speed != 10) {
-			break;
-		}
-
-		/* see if we have any end of frame errors */
-		e100_mdi_read(bdp, PHY_82555_EOF_COUNTER,
-			      bdp->phy_addr, &errors);
-
-		/* if non-zero, wait for 100 ms before reading again */
-		if (errors) {
-			udelay(200);
-			e100_mdi_read(bdp, PHY_82555_EOF_COUNTER,
-				      bdp->phy_addr, &errors);
-
-			/* if non-zero again, we disable polarity */
-			if (errors) {
-				e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,
-					      bdp->phy_addr, &misc_reg);
-				e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-					       bdp->phy_addr,
-					       (u16) (misc_reg |
-						      DISABLE_AUTO_POLARITY));
-			}
-		}
-
-		if (!errors) {
-			/* it is safe to read the polarity now */
-			e100_mdi_read(bdp, PHY_82555_CSR,
-				      bdp->phy_addr, &status);
-
-			/* if polarity is normal, disable polarity */
-			if (!(status & PHY_82555_POLARITY_BIT)) {
-				e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,
-					      bdp->phy_addr, &misc_reg);
-				e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,
-					       bdp->phy_addr,
-					       (u16) (misc_reg |
-						      DISABLE_AUTO_POLARITY));
-			}
-		}
-		break;
-
-	default:
-		break;
-	}
-}
-
-/* 
- * Procedure:	e100_find_speed_duplex
- *
- * Description: This routine will figure out what line speed and duplex mode
- *		the PHY is currently using.
- *
- * Arguments:
- *	bdp - Ptr to this card's e100_bdconfig structure
- *
- * Returns:
- *	NOTHING
- */
-static void
-e100_find_speed_duplex(struct e100_private *bdp)
-{
-	unsigned int PhyId;
-	u16 stat_reg, misc_reg;
-	u16 ad_reg, lp_ad_reg;
-
-	PhyId = bdp->PhyId & PHY_MODEL_REV_ID_MASK;
-
-	/* First we should check to see if we have link */
-	/* If we don't have a link no reason to print a speed and duplex */
-	if (!e100_update_link_state(bdp)) {
-		bdp->cur_line_speed = 0;
-		bdp->cur_dplx_mode = 0;
-		return;
-	}
-
-	/* On the 82559 and later controllers, speed/duplex is part of the *
-	 * SCB. So, we save an mdi_read and get these from the SCB. * */
-	if (bdp->rev_id >= D101MA_REV_ID) {
-		/* Read speed */
-		if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_1)
-			bdp->cur_line_speed = 100;
-		else
-			bdp->cur_line_speed = 10;
-
-		/* Read duplex */
-		if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_2)
-			bdp->cur_dplx_mode = FULL_DUPLEX;
-		else
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-
-		return;
-	}
-
-	/* If this is a Phy 100, then read bits 1 and 0 of extended register 0,
-	 * to get the current speed and duplex settings. */
-	if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) ||
-	    (PhyId == PHY_82555_TX)) {
-
-		/* Read Phy 100 extended register 0 */
-		e100_mdi_read(bdp, EXTENDED_REG_0, bdp->phy_addr, &misc_reg);
-
-		/* Get current speed setting */
-		if (misc_reg & PHY_100_ER0_SPEED_INDIC)
-			bdp->cur_line_speed = 100;
-		else
-			bdp->cur_line_speed = 10;
-
-		/* Get current duplex setting -- FDX enabled if bit is set */
-		if (misc_reg & PHY_100_ER0_FDX_INDIC)
-			bdp->cur_dplx_mode = FULL_DUPLEX;
-		else
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-
-		return;
-	}
-
-	/* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */
-	e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &misc_reg);
-
-	/* See if Auto-Negotiation was complete (bit 5, reg 1) */
-	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-
-	/* If a True NWAY connection was made, then we can detect speed/dplx
-	 * by ANDing our adapter's advertised abilities with our link partner's
-	 * advertised ablilities, and then assuming that the highest common
-	 * denominator was chosed by NWAY. */
-	if ((misc_reg & EXPANSION_NWAY) && (stat_reg & BMSR_ANEGCOMPLETE)) {
-
-		/* Read our advertisement register */
-		e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg);
-
-		/* Read our link partner's advertisement register */
-		e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg);
-
-		/* AND the two advertisement registers together, and get rid
-		 * of any extraneous bits. */
-		ad_reg &= (lp_ad_reg & NWAY_LP_ABILITY);
-
-		/* Get speed setting */
-		if (ad_reg &
-		    (ADVERTISE_100HALF | ADVERTISE_100FULL |
-		     ADVERTISE_100BASE4))
-
-			bdp->cur_line_speed = 100;
-		else
-			bdp->cur_line_speed = 10;
-
-		/* Get duplex setting -- use priority resolution algorithm */
-		if (ad_reg & ADVERTISE_100BASE4) {
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-		} else if (ad_reg & ADVERTISE_100FULL) {
-			bdp->cur_dplx_mode = FULL_DUPLEX;
-		} else if (ad_reg & ADVERTISE_100HALF) {
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-		} else if (ad_reg & ADVERTISE_10FULL) {
-			bdp->cur_dplx_mode = FULL_DUPLEX;
-		} else {
-			bdp->cur_dplx_mode = HALF_DUPLEX;
-		}
-
-		return;
-	}
-
-	/* If we are connected to a dumb (non-NWAY) repeater or hub, and the
-	 * line speed was determined automatically by parallel detection, then
-	 * we have no way of knowing exactly what speed the PHY is set to
-	 * unless that PHY has a propietary register which indicates speed in
-	 * this situation. The NSC TX PHY does have such a register. Also,
-	 * since NWAY didn't establish the connection, the duplex setting
-	 * should HALF duplex. */
-	bdp->cur_dplx_mode = HALF_DUPLEX;
-
-	if (PhyId == PHY_NSC_TX) {
-		/* Read register 25 to get the SPEED_10 bit */
-		e100_mdi_read(bdp, NSC_SPEED_IND_REG, bdp->phy_addr, &misc_reg);
-
-		/* If bit 6 was set then we're at 10Mbps */
-		if (misc_reg & NSC_TX_SPD_INDC_SPEED)
-			bdp->cur_line_speed = 10;
-		else
-			bdp->cur_line_speed = 100;
-
-	} else {
-		/* If we don't know the line speed, default to 10Mbps */
-		bdp->cur_line_speed = 10;
-	}
-}
-
-/* 
- * Procedure: e100_force_speed_duplex
- *
- * Description: This routine forces line speed and duplex mode of the
- * adapter based on the values the user has set in e100.c.
- *
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *
- * Returns: void
- *
- */
-void
-e100_force_speed_duplex(struct e100_private *bdp)
-{
-	u16 control;
-	unsigned long expires;
-
-	bdp->flags |= DF_SPEED_FORCED;
-
-	e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);
-	control &= ~BMCR_ANENABLE;
-	control &= ~BMCR_LOOPBACK;
-
-	switch (bdp->params.e100_speed_duplex) {
-	case E100_SPEED_10_HALF:
-		control &= ~BMCR_SPEED100;
-		control &= ~BMCR_FULLDPLX;
-		bdp->cur_line_speed = 10;
-		bdp->cur_dplx_mode = HALF_DUPLEX;
-		break;
-
-	case E100_SPEED_10_FULL:
-		control &= ~BMCR_SPEED100;
-		control |= BMCR_FULLDPLX;
-		bdp->cur_line_speed = 10;
-		bdp->cur_dplx_mode = FULL_DUPLEX;
-		break;
-
-	case E100_SPEED_100_HALF:
-		control |= BMCR_SPEED100;
-		control &= ~BMCR_FULLDPLX;
-		bdp->cur_line_speed = 100;
-		bdp->cur_dplx_mode = HALF_DUPLEX;
-		break;
-
-	case E100_SPEED_100_FULL:
-		control |= BMCR_SPEED100;
-		control |= BMCR_FULLDPLX;
-		bdp->cur_line_speed = 100;
-		bdp->cur_dplx_mode = FULL_DUPLEX;
-		break;
-	}
-
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);
-
-	/* loop must run at least once */
-	expires = jiffies + 2 * HZ;
-	do {
-		if (e100_update_link_state(bdp) || 
-		    time_after(jiffies, expires)) {
-			break;
-		} else {
-			yield();
-		}
-
-	} while (true);
-}
-
-void
-e100_force_speed_duplex_to_phy(struct e100_private *bdp)
-{
-	u16 control;
-
-	e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);
-	control &= ~BMCR_ANENABLE;
-	control &= ~BMCR_LOOPBACK;
-
-	switch (bdp->params.e100_speed_duplex) {
-	case E100_SPEED_10_HALF:
-		control &= ~BMCR_SPEED100;
-		control &= ~BMCR_FULLDPLX;
-		break;
-
-	case E100_SPEED_10_FULL:
-		control &= ~BMCR_SPEED100;
-		control |= BMCR_FULLDPLX;
-		break;
-
-	case E100_SPEED_100_HALF:
-		control |= BMCR_SPEED100;
-		control &= ~BMCR_FULLDPLX;
-		break;
-
-	case E100_SPEED_100_FULL:
-		control |= BMCR_SPEED100;
-		control |= BMCR_FULLDPLX;
-		break;
-	}
-
-	/* Send speed/duplex command to PHY layer. */
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);
-}
-
-/* 
- * Procedure: e100_set_fc
- *
- * Description: Checks the link's capability for flow control.
- * 
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *		    
- * Returns: void
- *
- */
-static void
-e100_set_fc(struct e100_private *bdp)
-{
-	u16 ad_reg;
-	u16 lp_ad_reg;
-	u16 exp_reg;
-
-	/* no flow control for 82557, forced links or half duplex */
-	if (!netif_carrier_ok(bdp->device) || (bdp->flags & DF_SPEED_FORCED) ||
-	    (bdp->cur_dplx_mode == HALF_DUPLEX) ||
-	    !(bdp->flags & IS_BACHELOR)) {
-
-		bdp->flags &= ~DF_LINK_FC_CAP;
-		return;
-	}
-
-	/* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */
-	e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &exp_reg);
-
-	if (exp_reg & EXPANSION_NWAY) {
-		/* Read our advertisement register */
-		e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg);
-
-		/* Read our link partner's advertisement register */
-		e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg);
-
-		ad_reg &= lp_ad_reg;	/* AND the 2 ad registers */
-
-		if (ad_reg & NWAY_AD_FC_SUPPORTED)
-			bdp->flags |= DF_LINK_FC_CAP;
-		else
-			/* If link partner is capable of autoneg, but  */
-			/* not capable of flow control, Received PAUSE */
-			/* frames are still honored, i.e.,             */
-		        /* transmitted frames would be paused */
-			/* by incoming PAUSE frames           */
-			bdp->flags |= DF_LINK_FC_TX_ONLY;
-
-	} else {
-		bdp->flags &= ~DF_LINK_FC_CAP;
-	}
-}
-
-/* 
- * Procedure: e100_phy_check
- * 
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *
- * Returns: true if link state was changed
- *	   false otherwise
- *
- */
-unsigned char
-e100_phy_check(struct e100_private *bdp)
-{
-	unsigned char old_link;
-	unsigned char changed = false;
-
-	old_link = netif_carrier_ok(bdp->device) ? 1 : 0;
-	e100_find_speed_duplex(bdp);
-
-	if (!old_link && netif_carrier_ok(bdp->device)) {
-		e100_set_fc(bdp);
-		changed = true;
-	}
-
-	if (old_link && !netif_carrier_ok(bdp->device)) {
-		/* reset the zero lock state */
-		bdp->zlock_state = ZLOCK_INITIAL;
-
-		// set auto lock for phy auto-negotiation on link up
-		if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_82555_TX)
-			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-				       bdp->phy_addr, 0);
-		changed = true;
-	}
-
-	e100_phy_fix_squelch(bdp);
-	e100_handle_zlock(bdp);
-
-	return changed;
-}
-
-/* 
- * Procedure:	e100_auto_neg
- *
- * Description: This routine will start autonegotiation and wait
- *		     for it to complete
- *
- * Arguments:
- *	bdp		- pointer to this card's e100_bdconfig structure
- *	force_restart	- defines if autoneg should be restarted even if it
- *			has been completed before
- * Returns:
- *	NOTHING
- */
-static void
-e100_auto_neg(struct e100_private *bdp, unsigned char force_restart)
-{
-	u16 stat_reg;
-	unsigned long expires;
-
-	bdp->flags &= ~DF_SPEED_FORCED;
-
-	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-
-	/* if we are capable of performing autoneg then we restart if needed */
-	if ((stat_reg != 0xFFFF) && (stat_reg & BMSR_ANEGCAPABLE)) {
-
-		if ((!force_restart) &&
-		    (stat_reg & BMSR_ANEGCOMPLETE)) {
-			goto exit;
-		}
-
-		e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
-			       BMCR_ANENABLE | BMCR_ANRESTART);
-
-		/* wait for autoneg to complete (up to 3 seconds) */
-		expires = jiffies + HZ * 3;
-		do {
-			/* now re-read the value. Sticky so read twice */
-			e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-			e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
-
-			if ((stat_reg & BMSR_ANEGCOMPLETE) ||
-			    time_after(jiffies, expires) ) {
-				goto exit;
-			} else {
-				yield();
-			}
-		} while (true);
-	}
-
-exit:
-	e100_find_speed_duplex(bdp);
-}
-
-void
-e100_phy_set_speed_duplex(struct e100_private *bdp, unsigned char force_restart)
-{
-	if (bdp->params.e100_speed_duplex == E100_AUTONEG) {
-        	if (bdp->rev_id >= D102_REV_ID) 
-			/* Enable MDI/MDI-X auto switching */
-                	e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,
-		                       MDI_MDIX_AUTO_SWITCH_ENABLE);
-		e100_auto_neg(bdp, force_restart);
-
-	} else {
-        	if (bdp->rev_id >= D102_REV_ID) 
-			/* Disable MDI/MDI-X auto switching */
-                	e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,
-		                       MDI_MDIX_RESET_ALL_MASK);
-		e100_force_speed_duplex(bdp);
-	}
-
-	e100_set_fc(bdp);
-}
-
-void
-e100_phy_autoneg(struct e100_private *bdp)
-{
-	u16 ctrl_reg;
-
-	ctrl_reg = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET;
-
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
-
-	udelay(100);
-}
-
-void
-e100_phy_set_loopback(struct e100_private *bdp)
-{
-	u16 ctrl_reg;
-	ctrl_reg = BMCR_LOOPBACK;
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
-		udelay(100);
-}
-	
-void
-e100_phy_reset(struct e100_private *bdp)
-{
-	u16 ctrl_reg;
-	ctrl_reg = BMCR_RESET;
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
-	/* ieee 802.3 : The reset process shall be completed       */
-	/* within 0.5 seconds from the settting of PHY reset bit.  */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 2);
-}
-
-unsigned char
-e100_phy_init(struct e100_private *bdp)
-{
-	e100_phy_reset(bdp);
-	e100_phy_address_detect(bdp);
-	e100_phy_isolate(bdp);
-	e100_phy_id_detect(bdp);
-
-	if (!e100_phy_specific_setup(bdp))
-		return false;
-
-	bdp->PhyState = 0;
-	bdp->PhyDelay = 0;
-	bdp->zlock_state = ZLOCK_INITIAL;
-
-	e100_phy_set_speed_duplex(bdp, false);
-	e100_fix_polarity(bdp);
-
-	return true;
-}
-
-/* 
- * Procedure: e100_get_link_state
- * 
- * Description: This routine checks the link status of the adapter
- *
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *		    
- *
- * Returns: true - If a link is found
- *		false - If there is no link
- *
- */
-unsigned char
-e100_get_link_state(struct e100_private *bdp)
-{
-	unsigned char link = false;
-	u16 status;
-
-	/* Check link status */
-	/* If the controller is a 82559 or later one, link status is available
-	 * from the CSR. This avoids the mdi_read. */
-	if (bdp->rev_id >= D101MA_REV_ID) {
-		if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_0) {
-			link = true;
-		} else {
-			link = false;
-		}
-
-	} else {
-		/* Read the status register twice because of sticky bits */
-		e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status);
-		e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status);
-
-		if (status & BMSR_LSTATUS) {
-			link = true;
-		} else {
-			link = false;
-		}
-	}
-
-	return link;
-}
-
-/* 
- * Procedure: e100_update_link_state
- * 
- * Description: This routine updates the link status of the adapter,
- * 		also considering netif_running
- *
- * Arguments:  bdp - Pointer to the e100_private structure for the board
- *		    
- *
- * Returns: true - If a link is found
- *		false - If there is no link
- *
- */
-unsigned char
-e100_update_link_state(struct e100_private *bdp)
-{
-	unsigned char link;
-
-	/* Logical AND PHY link & netif_running */
-	link = e100_get_link_state(bdp) && netif_running(bdp->device);
-
-	if (link) {
-		if (!netif_carrier_ok(bdp->device))
-			netif_carrier_on(bdp->device);
-	} else {
-		if (netif_carrier_ok(bdp->device))
-			netif_carrier_off(bdp->device);
-	}
-
-	return link;
-}
-
-/**************************************************************************\
- **
- ** PROC NAME:     e100_handle_zlock
- **    This function manages a state machine that controls
- **    the driver's zero locking algorithm.
- **    This function is called by e100_watchdog() every ~2 second.
- ** States:
- **    The current link handling state is stored in 
- **    bdp->zlock_state, and is one of:
- **    ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING
- **    Detailed description of the states and the transitions
- **    between states is found below.
- **    Note that any time the link is down / there is a reset
- **    state will be changed outside this function to ZLOCK_INITIAL
- ** Algorithm:
- **    1. If link is up & 100 Mbps continue else stay in #1:
- **    2. Set 'auto lock'
- **    3. Read & Store 100 times 'Zero' locked in 1 sec interval
- **    4. If max zero read >= 0xB continue else goto 1
- **    5. Set most popular 'Zero' read in #3
- **    6. Sleep 5 minutes
- **    7. Read number of errors, if it is > 300 goto 2 else goto 6
- ** Data Structures (in DRIVER_DATA):
- **    zlock_state           - current state of the algorithm
- **    zlock_read_cnt        - counts number of reads (up to 100)
- **    zlock_read_data[i]    - counts number of times 'Zero' read was i, 0 <= i <= 15
- **    zlock_sleep_cnt       - keeps track of "sleep" time (up to 300 secs = 5 minutes)
- **                                
- ** Parameters:    DRIVER_DATA    *bdp
- **
- **                bdp  - Pointer to HSM's adapter data space
- **
- ** Return Value:  NONE
- **
- ** See Also:      e100_watchdog()
- **
- \**************************************************************************/
-void
-e100_handle_zlock(struct e100_private *bdp)
-{
-	u16 pos;
-	u16 eq_reg;
-	u16 err_cnt;
-	u8 mpz;			/* Most Popular Zero */
-
-	switch (bdp->zlock_state) {
-	case ZLOCK_INITIAL:
-
-		if (((u8) bdp->rev_id <= D102_REV_ID) ||
-		    !(bdp->cur_line_speed == 100) ||
-		    !netif_carrier_ok(bdp->device)) {
-			break;
-		}
-
-		/* initialize hw and sw and start reading */
-		e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-			       bdp->phy_addr, 0);
-		/* reset read counters: */
-		bdp->zlock_read_cnt = 0;
-		for (pos = 0; pos < 16; pos++)
-			bdp->zlock_read_data[pos] = 0;
-		/* start reading in the next call back: */
-		bdp->zlock_state = ZLOCK_READING;
-
-		/* FALL THROUGH !! */
-
-	case ZLOCK_READING:
-		/* state: reading (100 times) zero locked in 1 sec interval
-		 * prev states: ZLOCK_INITIAL
-		 * next states: ZLOCK_INITIAL, ZLOCK_SLEEPING */
-
-		e100_mdi_read(bdp, PHY_82555_MDI_EQUALIZER_CSR,
-			      bdp->phy_addr, &eq_reg);
-		pos = (eq_reg & ZLOCK_ZERO_MASK) >> 4;
-		bdp->zlock_read_data[pos]++;
-		bdp->zlock_read_cnt++;
-
-		if (bdp->zlock_read_cnt == ZLOCK_MAX_READS) {
-			/* check if we read a 'Zero' value of 0xB or greater */
-			if ((bdp->zlock_read_data[0xB]) ||
-			    (bdp->zlock_read_data[0xC]) ||
-			    (bdp->zlock_read_data[0xD]) ||
-			    (bdp->zlock_read_data[0xE]) ||
-			    (bdp->zlock_read_data[0xF])) {
-
-				/* we've read 'Zero' value of 0xB or greater,
-				 * find most popular 'Zero' value and lock it */
-				mpz = 0;
-				/* this loop finds the most popular 'Zero': */
-				for (pos = 1; pos < 16; pos++) {
-					if (bdp->zlock_read_data[pos] >
-					    bdp->zlock_read_data[mpz])
-
-						mpz = pos;
-				}
-				/* now lock the most popular 'Zero': */
-				eq_reg = (ZLOCK_SET_ZERO | mpz);
-				e100_mdi_write(bdp,
-					       PHY_82555_MDI_EQUALIZER_CSR,
-					       bdp->phy_addr, eq_reg);
-
-				/* sleep for 5 minutes: */
-				bdp->zlock_sleep_cnt = jiffies;
-				bdp->zlock_state = ZLOCK_SLEEPING;
-				/* we will be reading the # of errors after 5
-				 * minutes, so we need to reset the error
-				 * counters - these registers are self clearing
-				 * on read, so read them */
-				e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR,
-					      bdp->phy_addr, &err_cnt);
-
-			} else {
-				/* we did not read a 'Zero' value of 0xB or
-				 * above. go back to the start */
-				bdp->zlock_state = ZLOCK_INITIAL;
-			}
-
-		}
-		break;
-
-	case ZLOCK_SLEEPING:
-		/* state: sleeping for 5 minutes
-		 * prev states: ZLOCK_READING
-		 * next states: ZLOCK_READING, ZLOCK_SLEEPING */
-
-		/* if 5 minutes have passed: */
-		if ((jiffies - bdp->zlock_sleep_cnt) >= ZLOCK_MAX_SLEEP) {
-			/* read and sum up the number of errors:  */
-			e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR,
-				      bdp->phy_addr, &err_cnt);
-			/* if we've more than 300 errors (this number was
-			 * calculated according to the spec max allowed errors
-			 * (80 errors per 1 million frames) for 5 minutes in
-			 * 100 Mbps (or the user specified max BER number) */
-			if (err_cnt > bdp->params.ber) {
-				/* start again in the next callback: */
-				bdp->zlock_state = ZLOCK_INITIAL;
-			} else {
-				/* we don't have more errors than allowed,
-				 * sleep for 5 minutes */
-				bdp->zlock_sleep_cnt = jiffies;
-			}
-		}
-		break;
-
-	default:
-		break;
-	}
-}
diff -Nru a/drivers/net/e100/e100_phy.h b/drivers/net/e100/e100_phy.h
--- a/drivers/net/e100/e100_phy.h	Wed Feb 11 22:30:56 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,158 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#ifndef _E100_PHY_INC_
-#define _E100_PHY_INC_
-
-#include "e100.h"
-
-/*
- * Auto-polarity enable/disable
- * e100_autopolarity = 0 => disable auto-polarity
- * e100_autopolarity = 1 => enable auto-polarity
- * e100_autopolarity = 2 => let software determine
- */
-#define E100_AUTOPOLARITY 2
-
-#define IS_NC3133(bdp) (((bdp)->pdev->subsystem_vendor == 0x0E11) && \
-                        ((bdp)->pdev->subsystem_device == 0xB0E1))
-
-#define PHY_503                 0
-#define PHY_100_A               0x000003E0
-#define PHY_100_C               0x035002A8
-#define PHY_NSC_TX              0x5c002000
-#define PHY_82562ET             0x033002A8
-#define PHY_82562EM             0x032002A8
-#define PHY_82562EH             0x017002A8
-#define PHY_82555_TX            0x015002a8	/* added this for 82555 */
-#define PHY_OTHER               0xFFFF
-#define MAX_PHY_ADDR            31
-#define MIN_PHY_ADDR            0
-
-#define PHY_MODEL_REV_ID_MASK   0xFFF0FFFF
-
-#define PHY_DEFAULT_ADDRESS 1
-#define PHY_ADDRESS_503 32
-
-/* MDI Control register bit definitions */
-#define MDI_PHY_READY	    BIT_28	/* PHY is ready for next MDI cycle */
-
-#define MDI_NC3133_CONFIG_REG           0x19
-#define MDI_NC3133_100FX_ENABLE         BIT_2
-#define MDI_NC3133_INT_ENABLE_REG       0x17
-#define MDI_NC3133_INT_ENABLE           BIT_1
-
-/* MDI Control register opcode definitions */
-#define MDI_WRITE 1		/* Phy Write */
-#define MDI_READ  2		/* Phy read */
-
-/* MDI register set*/
-#define AUTO_NEG_NEXT_PAGE_REG	    0x07	/* Auto-negotiation next page xmit */
-#define EXTENDED_REG_0		    0x10	/* Extended reg 0 (Phy 100 modes) */
-#define EXTENDED_REG_1		    0x14	/* Extended reg 1 (Phy 100 error indications) */
-#define NSC_CONG_CONTROL_REG	    0x17	/* National (TX) congestion control */
-#define NSC_SPEED_IND_REG	    0x19	/* National (TX) speed indication */
-
-#define HWI_CONTROL_REG             0x1D	/* HWI Control register */
-/* MDI/MDI-X Control Register bit definitions */
-#define MDI_MDIX_RES_TIMER          BIT_0_3	/* minimum slot time for resolution timer */
-#define MDI_MDIX_CONFIG_IS_OK       BIT_4	/* 1 = resolution algorithm completes OK */
-#define MDI_MDIX_STATUS             BIT_5	/* 1 = MDIX (croos over), 0 = MDI (straight through) */
-#define MDI_MDIX_SWITCH             BIT_6	/* 1 = Forces to MDIX, 0 = Forces to MDI */
-#define MDI_MDIX_AUTO_SWITCH_ENABLE BIT_7	/* 1 = MDI/MDI-X feature enabled */
-#define MDI_MDIX_CONCT_CONFIG       BIT_8	/* Sets the MDI/MDI-X connectivity configuration (test prupose only) */
-#define MDI_MDIX_CONCT_TEST_ENABLE  BIT_9	/* 1 = Enables connectivity testing */
-#define MDI_MDIX_RESET_ALL_MASK     0x0000
-
-/* HWI Control Register bit definitions */
-#define HWI_TEST_DISTANCE           BIT_0_8	/* distance to cable problem */
-#define HWI_TEST_HIGHZ_PROBLEM      BIT_9	/* 1 = Open Circuit */
-#define HWI_TEST_LOWZ_PROBLEM       BIT_10	/* 1 = Short Circuit */
-#define HWI_TEST_RESERVED           (BIT_11 | BIT_12)	/* reserved */
-#define HWI_TEST_EXECUTE            BIT_13	/* 1 = Execute the HWI test on the PHY */
-#define HWI_TEST_ABILITY            BIT_14	/* 1 = test passed */
-#define HWI_TEST_ENABLE             BIT_15	/* 1 = Enables the HWI feature */
-#define HWI_RESET_ALL_MASK          0x0000
-
-/* ############Start of 82555 specific defines################## */
-
-/* Intel 82555 specific registers */
-#define PHY_82555_CSR		    0x10	/* 82555 CSR */
-#define PHY_82555_SPECIAL_CONTROL   0x11	/* 82555 special control register */
-
-#define PHY_82555_RCV_ERR	    0x15	/* 82555 100BaseTx Receive Error
-						 * Frame Counter */
-#define PHY_82555_SYMBOL_ERR	    0x16	/* 82555 RCV Symbol Error Counter */
-#define PHY_82555_PREM_EOF_ERR	    0x17	/* 82555 100BaseTx RCV Premature End
-						 * of Frame Error Counter */
-#define PHY_82555_EOF_COUNTER	    0x18	/* 82555 end of frame error counter */
-#define PHY_82555_MDI_EQUALIZER_CSR 0x1a	/* 82555 specific equalizer reg. */
-
-/* 82555 CSR bits */
-#define PHY_82555_SPEED_BIT    BIT_1
-#define PHY_82555_POLARITY_BIT BIT_8
-
-/* 82555 equalizer reg. opcodes */
-#define ENABLE_ZERO_FORCING  0x2010	/* write to ASD conf. reg. 0 */
-#define DISABLE_ZERO_FORCING 0x2000	/* write to ASD conf. reg. 0 */
-
-/* 82555 special control reg. opcodes */
-#define DISABLE_AUTO_POLARITY 0x0010
-#define EXTENDED_SQUELCH_BIT  BIT_2
-
-/* ############End of 82555 specific defines##################### */
-
-/* Auto-Negotiation advertisement register bit definitions*/
-#define NWAY_AD_FC_SUPPORTED    0x0400	/* Flow Control supported */
-
-/* Auto-Negotiation link partner ability register bit definitions*/
-#define NWAY_LP_ABILITY	        0x07e0	/* technologies supported */
-
-/* PHY 100 Extended Register 0 bit definitions*/
-#define PHY_100_ER0_FDX_INDIC	BIT_0	/* 1 = FDX, 0 = half duplex */
-#define PHY_100_ER0_SPEED_INDIC BIT_1	/* 1 = 100Mbps, 0= 10Mbps */
-
-/* National Semiconductor TX phy congestion control register bit definitions*/
-#define NSC_TX_CONG_TXREADY  BIT_10	/* Makes TxReady an input */
-#define NSC_TX_CONG_ENABLE   BIT_8	/* Enables congestion control */
-
-/* National Semiconductor TX phy speed indication register bit definitions*/
-#define NSC_TX_SPD_INDC_SPEED BIT_6	/* 0 = 100Mbps, 1=10Mbps */
-
-/************* function prototypes ************/
-extern unsigned char e100_phy_init(struct e100_private *bdp);
-extern unsigned char e100_update_link_state(struct e100_private *bdp);
-extern unsigned char e100_phy_check(struct e100_private *bdp);
-extern void e100_phy_set_speed_duplex(struct e100_private *bdp,
-				      unsigned char force_restart);
-extern void e100_phy_autoneg(struct e100_private *bdp);
-extern void e100_phy_reset(struct e100_private *bdp);
-extern void e100_phy_set_loopback(struct e100_private *bdp);
-extern int e100_mdi_write(struct e100_private *, u32, u32, u16);
-extern int e100_mdi_read(struct e100_private *, u32, u32, u16 *);
-
-#endif
diff -Nru a/drivers/net/e100/e100_test.c b/drivers/net/e100/e100_test.c
--- a/drivers/net/e100/e100_test.c	Wed Feb 11 22:30:57 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,500 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#include "e100_phy.h"
-#include "e100_config.h"
-
-extern u16 e100_eeprom_read(struct e100_private *, u16);
-extern int e100_wait_exec_cmplx(struct e100_private *, u32,u8, u8);
-extern void e100_phy_reset(struct e100_private *bdp);
-extern void e100_phy_autoneg(struct e100_private *bdp);
-extern void e100_phy_set_loopback(struct e100_private *bdp);
-extern void e100_force_speed_duplex(struct e100_private *bdp);
-
-static u8 e100_diag_selftest(struct net_device *);
-static u8 e100_diag_eeprom(struct net_device *);
-static u8 e100_diag_loopback(struct net_device *);
-
-static u8 e100_diag_one_loopback (struct net_device *, u8);
-static u8 e100_diag_rcv_loopback_pkt(struct e100_private *);
-static void e100_diag_config_loopback(struct e100_private *, u8, u8, u8 *,u8 *);
-static u8 e100_diag_loopback_alloc(struct e100_private *);
-static void e100_diag_loopback_cu_ru_exec(struct e100_private *);
-static u8 e100_diag_check_pkt(u8 *);
-static void e100_diag_loopback_free(struct e100_private *);
-static int e100_cable_diag(struct e100_private *bdp);
-
-#define LB_PACKET_SIZE 1500
-
-/**
- * e100_run_diag - main test execution handler - checks mask of requests and calls the diag routines  
- * @dev: atapter's net device data struct
- * @test_info: array with test request mask also used to store test results
- *
- * RETURNS: updated flags field of struct ethtool_test
- */
-u32
-e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
-{
-	struct e100_private* bdp = dev->priv;
-	u8 test_result = 0;
-
-	if (!e100_get_link_state(bdp)) {
-		test_result = ETH_TEST_FL_FAILED;
-		test_info[test_link] = true;
-	}
-	if (!e100_diag_eeprom(dev)) {
-		test_result = ETH_TEST_FL_FAILED;
-		test_info[test_eeprom] = true;
-	}
-	if (flags & ETH_TEST_FL_OFFLINE) {
-		u8 fail_mask;
-		if (netif_running(dev)) {
-			spin_lock_bh(&dev->xmit_lock);
-			e100_close(dev);
-			spin_unlock_bh(&dev->xmit_lock);
-		}
-		if (e100_diag_selftest(dev)) {
-			test_result = ETH_TEST_FL_FAILED;
-			test_info[test_self_test] = true;
-		}
-
-		fail_mask = e100_diag_loopback(dev);
-		if (fail_mask) {
-			test_result = ETH_TEST_FL_FAILED;
-			if (fail_mask & PHY_LOOPBACK)
-				test_info[test_loopback_phy] = true;
-			if (fail_mask & MAC_LOOPBACK)
-				test_info[test_loopback_mac] = true;
-		}
-
-		test_info[cable_diag] = e100_cable_diag(bdp);
-		/* Need hw init regardless of netif_running */
-		e100_hw_init(bdp);
-		if (netif_running(dev)) {
-			e100_open(dev);
-		}
-	}
-	else {
-		test_info[test_self_test] = false;
-		test_info[test_loopback_phy] = false;
-		test_info[test_loopback_mac] = false;
-		test_info[cable_diag] = false;
-	}
-
-	return flags | test_result;
-}
-
-/**
- * e100_diag_selftest - run hardware selftest 
- * @dev: atapter's net device data struct
- */
-static u8
-e100_diag_selftest(struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-	u32 st_timeout, st_result;
-	u8 retval = 0;
-
-	if (!e100_selftest(bdp, &st_timeout, &st_result)) {
-		if (!st_timeout) {
-			if (st_result & CB_SELFTEST_REGISTER_BIT)
-				retval |= REGISTER_TEST_FAIL;
-			if (st_result & CB_SELFTEST_DIAG_BIT)
-				retval |= SELF_TEST_FAIL;
-			if (st_result & CB_SELFTEST_ROM_BIT)
-				retval |= ROM_TEST_FAIL;
-		} else {
-            		retval = TEST_TIMEOUT;
-		}
-	}
-
-	return retval;
-}
-
-/**
- * e100_diag_eeprom - validate eeprom checksum correctness
- * @dev: atapter's net device data struct
- *
- */
-static u8
-e100_diag_eeprom (struct net_device *dev)
-{
-	struct e100_private *bdp = dev->priv;
-	u16 i, eeprom_sum, eeprom_actual_csm;
-
-	for (i = 0, eeprom_sum = 0; i < (bdp->eeprom_size - 1); i++) {
-		eeprom_sum += e100_eeprom_read(bdp, i);
-	}
-
-	eeprom_actual_csm = e100_eeprom_read(bdp, bdp->eeprom_size - 1);
-
-	if (eeprom_actual_csm == (u16)(EEPROM_SUM - eeprom_sum)) {
-		return true;
-	}
-
-	return false;
-}
-
-/**
- * e100_diag_loopback - performs loopback test  
- * @dev: atapter's net device data struct
- */
-static u8
-e100_diag_loopback (struct net_device *dev)
-{
-	u8 rc = 0;
-
-	printk(KERN_DEBUG "%s: PHY loopback test starts\n", dev->name);
-	e100_hw_init(dev->priv);
-	if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) {
-		rc |= PHY_LOOPBACK;
-	}
-	printk(KERN_DEBUG "%s: PHY loopback test ends\n", dev->name);
-
-	printk(KERN_DEBUG "%s: MAC loopback test starts\n", dev->name);
-	e100_hw_init(dev->priv);
-	if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) {
-		rc |= MAC_LOOPBACK;
-	}
-	printk(KERN_DEBUG "%s: MAC loopback test ends\n", dev->name);
-
-	return rc;
-}
-
-/**
- * e100_diag_loopback - performs loopback test  
- * @dev: atapter's net device data struct
- * @mode: lopback test type
- */
-static u8
-e100_diag_one_loopback (struct net_device *dev, u8 mode)
-{
-        struct e100_private *bdp = dev->priv;
-        u8 res = false;
-   	u8 saved_dynamic_tbd = false;
-   	u8 saved_extended_tcb = false;
-
-	if (!e100_diag_loopback_alloc(bdp))
-		return false;
-
-	/* change the config block to standard tcb and the correct loopback */
-        e100_diag_config_loopback(bdp, true, mode,
-				  &saved_extended_tcb, &saved_dynamic_tbd);
-
-	e100_diag_loopback_cu_ru_exec(bdp);
-
-        if (e100_diag_rcv_loopback_pkt(bdp)) {
-		res = true;
-	}
-
-        e100_diag_loopback_free(bdp);
-
-        /* change the config block to previous tcb mode and the no loopback */
-        e100_diag_config_loopback(bdp, false, mode,
-				  &saved_extended_tcb, &saved_dynamic_tbd);
-	return res;
-}
-
-/**
- * e100_diag_config_loopback - setup/clear loopback before/after lpbk test
- * @bdp: atapter's private data struct
- * @set_loopback: true if the function is called to set lb
- * @loopback_mode: the loopback mode(MAC or PHY)
- * @tcb_extended: true if need to set extended tcb mode after clean loopback
- * @dynamic_tbd: true if needed to set dynamic tbd mode after clean loopback
- *
- */
-void
-e100_diag_config_loopback(struct e100_private* bdp,
-			  u8 set_loopback,
-			  u8 loopback_mode,
-			  u8* tcb_extended,
-			  u8* dynamic_tbd)
-{
-	/* if set_loopback == true - we want to clear tcb_extended/dynamic_tbd.
-	 * the previous values are saved in the params tcb_extended/dynamic_tbd
-	 * if set_loopback == false - we want to restore previous value.
-	 */
-	if (set_loopback || (*tcb_extended))
-		  *tcb_extended = e100_config_tcb_ext_enable(bdp,*tcb_extended);
-
-	if (set_loopback || (*dynamic_tbd))
-		 *dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd);
-
-	if (set_loopback) {
-		/* ICH PHY loopback is broken */
-		if (bdp->flags & IS_ICH && loopback_mode == PHY_LOOPBACK)
-			loopback_mode = MAC_LOOPBACK;
-		/* Configure loopback on MAC */
-		e100_config_loopback_mode(bdp,loopback_mode);
-	} else {
-		e100_config_loopback_mode(bdp,NO_LOOPBACK);
-	}
-
-	e100_config(bdp);
-
-	if (loopback_mode == PHY_LOOPBACK) {
-		if (set_loopback)
-                        /* Set PHY loopback mode */
-                        e100_phy_set_loopback(bdp);
-		else
-			/* Reset PHY loopback mode */
-			e100_phy_reset(bdp);	
-		/* Wait for PHY state change */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-                schedule_timeout(HZ);
-	} else { /* For MAC loopback wait 500 msec to take effect */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 2);
-	}
-}
-  
-/**
- * e100_diag_loopback_alloc - alloc & initate tcb and rfd for the loopback
- * @bdp: atapter's private data struct
- *
- */
-static u8
-e100_diag_loopback_alloc(struct e100_private *bdp)
-{
-	dma_addr_t dma_handle;
-	tcb_t *tcb;
-	rfd_t *rfd;
-	tbd_t *tbd;
-
-	/* tcb, tbd and transmit buffer are allocated */
-	tcb = pci_alloc_consistent(bdp->pdev,
-				   (sizeof (tcb_t) + sizeof (tbd_t) +
-				    LB_PACKET_SIZE),
-				   &dma_handle);
-        if (tcb == NULL)
-		return false;
-
-	memset(tcb, 0x00, sizeof (tcb_t) + sizeof (tbd_t) + LB_PACKET_SIZE);
-	tcb->tcb_phys = dma_handle;
-	tcb->tcb_hdr.cb_status = 0;
-	tcb->tcb_hdr.cb_cmd =
-		cpu_to_le16(CB_EL_BIT | CB_TRANSMIT | CB_TX_SF_BIT);
-	/* Next command is null */
-	tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(0xffffffff);
-	tcb->tcb_cnt = 0;
-	tcb->tcb_thrshld = bdp->tx_thld;
-	tcb->tcb_tbd_num = 1;
-	/* Set up tcb tbd pointer */
-	tcb->tcb_tbd_ptr = cpu_to_le32(tcb->tcb_phys + sizeof (tcb_t));
-	tbd = (tbd_t *) ((u8 *) tcb + sizeof (tcb_t));
-	/* Set up tbd transmit buffer */
-	tbd->tbd_buf_addr =
-		cpu_to_le32(le32_to_cpu(tcb->tcb_tbd_ptr) + sizeof (tbd_t));
-	tbd->tbd_buf_cnt = __constant_cpu_to_le16(1024);
-	/* The value of first 512 bytes is FF */
-	memset((void *) ((u8 *) tbd + sizeof (tbd_t)), 0xFF, 512);
-	/* The value of second 512 bytes is BA */
-	memset((void *) ((u8 *) tbd + sizeof (tbd_t) + 512), 0xBA, 512);
-	wmb();
-	rfd = pci_alloc_consistent(bdp->pdev, sizeof (rfd_t), &dma_handle);
-
-	if (rfd == NULL) {
-		pci_free_consistent(bdp->pdev,
-				    sizeof (tcb_t) + sizeof (tbd_t) +
-				    LB_PACKET_SIZE, tcb, tcb->tcb_phys);
-		return false;
-	}
-
-	memset(rfd, 0x00, sizeof (rfd_t));
-
-	/* init all fields in rfd */
-	rfd->rfd_header.cb_cmd = cpu_to_le16(RFD_EL_BIT);
-	rfd->rfd_sz = cpu_to_le16(ETH_FRAME_LEN + CHKSUM_SIZE);
-	/* dma_handle is physical address of rfd */
-	bdp->loopback.dma_handle = dma_handle;
-	bdp->loopback.tcb = tcb;
-	bdp->loopback.rfd = rfd;
-	wmb();
-	return true;
-}
-
-/**
- * e100_diag_loopback_cu_ru_exec - activates cu and ru to send & receive the pkt
- * @bdp: atapter's private data struct
- *
- */
-static void
-e100_diag_loopback_cu_ru_exec(struct e100_private *bdp)
-{
-	/*load CU & RU base */ 
-	if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START, 0))
-		printk(KERN_ERR "e100: SCB_RUC_START failed!\n");
-
-	bdp->next_cu_cmd = START_WAIT;
-	e100_start_cu(bdp, bdp->loopback.tcb);
-	bdp->last_tcb = NULL;
-	rmb();
-}
-/**
- * e100_diag_check_pkt - checks if a given packet is a loopback packet
- * @bdp: atapter's private data struct
- *
- * Returns true if OK false otherwise.
- */
-static u8
-e100_diag_check_pkt(u8 *datap)
-{
-	int i;
-	for (i = 0; i<512; i++) {
-		if( !((*datap)==0xFF && (*(datap + 512) == 0xBA)) ) {
-			printk (KERN_ERR "e100: check loopback packet failed at: %x\n", i);
-			return false;
-			}
-	}
-	printk (KERN_DEBUG "e100: Check received loopback packet OK\n");
-	return true;
-}
-
-/**
- * e100_diag_rcv_loopback_pkt - waits for receive and checks lpbk packet
- * @bdp: atapter's private data struct
- *
- * Returns true if OK false otherwise.
- */
-static u8
-e100_diag_rcv_loopback_pkt(struct e100_private* bdp) 
-{    
-	rfd_t *rfdp;
-	u16 rfd_status;
-	unsigned long expires = jiffies + HZ * 2;
-
-        rfdp =bdp->loopback.rfd;
-
-        rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
-
-        while (!(rfd_status & RFD_STATUS_COMPLETE)) { 
-		if (time_before(jiffies, expires)) {
-			yield();
-			rmb();
-			rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
-		} else {
-			break;
-		}
-        }
-
-        if (rfd_status & RFD_STATUS_COMPLETE) {
-		printk(KERN_DEBUG "e100: Loopback packet received\n");
-                return e100_diag_check_pkt(((u8 *)rfdp+bdp->rfd_size));
-	}
-	else {
-		printk(KERN_ERR "e100: Loopback packet not received\n");
-		return false;
-	}
-}
-
-/**
- * e100_diag_loopback_free - free data allocated for loopback pkt send/receive
- * @bdp: atapter's private data struct
- *
- */
-static void
-e100_diag_loopback_free (struct e100_private *bdp)
-{
-        pci_free_consistent(bdp->pdev,
-			    sizeof(tcb_t) + sizeof(tbd_t) + LB_PACKET_SIZE,
-			    bdp->loopback.tcb, bdp->loopback.tcb->tcb_phys);
-
-        pci_free_consistent(bdp->pdev, sizeof(rfd_t), bdp->loopback.rfd,
-			    bdp->loopback.dma_handle);
-}
-
-static int
-e100_cable_diag(struct e100_private *bdp)
-{	
-	int saved_open_circut = 0xffff;
-	int saved_short_circut = 0xffff;
-	int saved_distance = 0xffff;
-	int saved_same = 0;
-	int cable_status = E100_CABLE_UNKNOWN;
-	int i;
-	
-	/* If we have link, */	
-	if (e100_get_link_state(bdp))
-		return E100_CABLE_OK;
-	
-	if (bdp->rev_id < D102_REV_ID)
-		return E100_CABLE_UNKNOWN;
-
-	/* Disable MDI/MDI-X auto switching */
-        e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,
-		MDI_MDIX_RESET_ALL_MASK);
-	/* Set to 100 Full as required by cable test */
-	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
-		BMCR_SPEED100 | BMCR_FULLDPLX);
-
-	/* Test up to 100 times */
-	for (i = 0; i < 100; i++) {
-		u16 ctrl_reg;
-		int distance, open_circut, short_circut, near_end;
-
-		/* Enable and execute cable test */
-		e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,
-			(HWI_TEST_ENABLE | HWI_TEST_EXECUTE));
-		/* Wait for cable test finished */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/100 + 1);
-		/* Read results */
-		e100_mdi_read(bdp, HWI_CONTROL_REG, bdp->phy_addr, &ctrl_reg);
-		distance = ctrl_reg & HWI_TEST_DISTANCE;
-		open_circut = ctrl_reg & HWI_TEST_HIGHZ_PROBLEM;
-		short_circut = ctrl_reg & HWI_TEST_LOWZ_PROBLEM;
-
-		if ((distance == saved_distance) &&
-	    	    (open_circut == saved_open_circut) &&
-	    	    (short_circut == saved_short_circut)) 
-			saved_same++;
-		else {
-			saved_same = 0;
-			saved_distance = distance;
-			saved_open_circut = open_circut;
-			saved_short_circut = short_circut;
-		}
-		/* If results are the same 3 times */
-		if (saved_same == 3) {
-			near_end = ((distance * HWI_REGISTER_GRANULARITY) <
-			       HWI_NEAR_END_BOUNDARY);
-			if (open_circut)
-				cable_status = (near_end) ? 
-					E100_CABLE_OPEN_NEAR : E100_CABLE_OPEN_FAR;
-			if (short_circut)
-				cable_status = (near_end) ?
-					E100_CABLE_SHORT_NEAR : E100_CABLE_SHORT_FAR;
-			break;
-		}
-	}
-	/* Reset cable test */
-        e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,					       HWI_RESET_ALL_MASK);
-	return cable_status;
-}
-
diff -Nru a/drivers/net/e100/e100_ucode.h b/drivers/net/e100/e100_ucode.h
--- a/drivers/net/e100/e100_ucode.h	Wed Feb 11 22:30:57 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,365 +0,0 @@
-/*******************************************************************************
-
-  
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
-  
-  This program is free software; you can redistribute it and/or modify it 
-  under the terms of the GNU General Public License as published by the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
-  more details.
-  
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
-
-#ifndef _E100_UCODE_H_
-#define _E100_UCODE_H_
-
-/*
-e100_ucode.h
-
-This file contains the loadable micro code arrays to implement receive 
-bundling on the D101 A-step, D101 B-step, D101M (B-step only), D101S, 
-D102 B-step, D102 B-step with TCO work around and D102 C-step.
-
-Each controller has its own specific micro code array.  The array for one 
-controller is totally incompatible with any other controller, and if used 
-will most likely cause the controller to lock up and stop responding to 
-the driver.  Each micro code array has its own parameter offsets (described 
-below), and they each have their own version number.
-*/
-
-/*************************************************************************
-*  CPUSaver parameters
-*
-*  All CPUSaver parameters are 16-bit literals that are part of a
-*  "move immediate value" instruction.  By changing the value of
-*  the literal in the instruction before the code is loaded, the
-*  driver can change algorithm.
-*
-*  CPUSAVER_DWORD - This is the location of the instruction that loads
-*    the dead-man timer with its inital value.  By writing a 16-bit
-*    value to the low word of this instruction, the driver can change
-*    the timer value.  The current default is either x600 or x800;
-*    experiments show that the value probably should stay within the
-*    range of x200 - x1000.
-*
-*  CPUSAVER_BUNDLE_MAX_DWORD - This is the location of the instruction
-*    that sets the maximum number of frames that will be bundled.  In
-*    some situations, such as the TCP windowing algorithm, it may be
-*    better to limit the growth of the bundle size than let it go as
-*    high as it can, because that could cause too much added latency.
-*    The default is six, because this is the number of packets in the
-*    default TCP window size.  A value of 1 would make CPUSaver indicate
-*    an interrupt for every frame received.  If you do not want to put
-*    a limit on the bundle size, set this value to xFFFF.
-*
-*  CPUSAVER_MIN_SIZE_DWORD - This is the location of the instruction
-*    that contains a bit-mask describing the minimum size frame that
-*    will be bundled.  The default masks the lower 7 bits, which means
-*    that any frame less than 128 bytes in length will not be bundled,
-*    but will instead immediately generate an interrupt.  This does
-*    not affect the current bundle in any way.  Any frame that is 128
-*    bytes or large will be bundled normally.  This feature is meant
-*    to provide immediate indication of ACK frames in a TCP environment.
-*    Customers were seeing poor performance when a machine with CPUSaver
-*    enabled was sending but not receiving.  The delay introduced when
-*    the ACKs were received was enough to reduce total throughput, because
-*    the sender would sit idle until the ACK was finally seen.
-*
-*    The current default is 0xFF80, which masks out the lower 7 bits.
-*    This means that any frame which is x7F (127) bytes or smaller
-*    will cause an immediate interrupt.  Because this value must be a 
-*    bit mask, there are only a few valid values that can be used.  To
-*    turn this feature off, the driver can write the value xFFFF to the
-*    lower word of this instruction (in the same way that the other
-*    parameters are used).  Likewise, a value of 0xF800 (2047) would
-*    cause an interrupt to be generated for every frame, because all
-*    standard Ethernet frames are <= 2047 bytes in length.
-*************************************************************************/
-
-#ifndef UCODE_MAX_DWORDS
-#define UCODE_MAX_DWORDS	134
-#endif
-
-/********************************************************/
-/*  CPUSaver micro code for the D101A                   */
-/********************************************************/
-
-/*  Version 2.0  */
-
-/*  This value is the same for both A and B step of 558.  */
-
-#define D101_CPUSAVER_TIMER_DWORD		72
-#define D101_CPUSAVER_BUNDLE_DWORD		UCODE_MAX_DWORDS
-#define D101_CPUSAVER_MIN_SIZE_DWORD		UCODE_MAX_DWORDS
-
-#define     D101_A_RCVBUNDLE_UCODE \
-{\
-0x03B301BB, 0x0046FFFF, 0xFFFFFFFF, 0x051DFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
-0x000C0001, 0x00101212, 0x000C0008, 0x003801BC, \
-0x00000000, 0x00124818, 0x000C1000, 0x00220809, \
-0x00010200, 0x00124818, 0x000CFFFC, 0x003803B5, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x0024B81D, 0x00130836, 0x000C0001, \
-0x0026081C, 0x0020C81B, 0x00130824, 0x00222819, \
-0x00101213, 0x00041000, 0x003A03B3, 0x00010200, \
-0x00101B13, 0x00238081, 0x00213049, 0x0038003B, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x0024B83E, 0x00130826, 0x000C0001, \
-0x0026083B, 0x00010200, 0x00134824, 0x000C0001, \
-0x00101213, 0x00041000, 0x0038051E, 0x00101313, \
-0x00010400, 0x00380521, 0x00050600, 0x00100824, \
-0x00101310, 0x00041000, 0x00080600, 0x00101B10, \
-0x0038051E, 0x00000000, 0x00000000, 0x00000000  \
-}
-
-/********************************************************/
-/*  CPUSaver micro code for the D101B                   */
-/********************************************************/
-
-/*  Version 2.0  */
-
-#define     D101_B0_RCVBUNDLE_UCODE \
-{\
-0x03B401BC, 0x0047FFFF, 0xFFFFFFFF, 0x051EFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
-0x000C0001, 0x00101B92, 0x000C0008, 0x003801BD, \
-0x00000000, 0x00124818, 0x000C1000, 0x00220809, \
-0x00010200, 0x00124818, 0x000CFFFC, 0x003803B6, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x0024B81D, 0x0013082F, 0x000C0001, \
-0x0026081C, 0x0020C81B, 0x00130837, 0x00222819, \
-0x00101B93, 0x00041000, 0x003A03B4, 0x00010200, \
-0x00101793, 0x00238082, 0x0021304A, 0x0038003C, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x0024B83E, 0x00130826, 0x000C0001, \
-0x0026083B, 0x00010200, 0x00134837, 0x000C0001, \
-0x00101B93, 0x00041000, 0x0038051F, 0x00101313, \
-0x00010400, 0x00380522, 0x00050600, 0x00100837, \
-0x00101310, 0x00041000, 0x00080600, 0x00101790, \
-0x0038051F, 0x00000000, 0x00000000, 0x00000000  \
-}
-
-/********************************************************/
-/*  CPUSaver micro code for the D101M (B-step only)     */
-/********************************************************/
-
-/*  Version 2.10.1  */
-
-/*  Parameter values for the D101M B-step  */
-#define D101M_CPUSAVER_TIMER_DWORD		78
-#define D101M_CPUSAVER_BUNDLE_DWORD		65
-#define D101M_CPUSAVER_MIN_SIZE_DWORD		126
-
-#define D101M_B_RCVBUNDLE_UCODE \
-{\
-0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \
-0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \
-0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \
-0x00380438, 0x00000000, 0x00140000, 0x00380555, \
-0x00308000, 0x00100662, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \
-0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \
-0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \
-0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \
-0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \
-0x00041000, 0x00010004, 0x00130826, 0x000C0006, \
-0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380C34, 0x00000000, 0x00000000, \
-0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \
-0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \
-0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \
-0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \
-0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \
-0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \
-0x00130826, 0x000C0001, 0x00220559, 0x00101313, \
-0x00380559, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00130831, 0x0010090B, 0x00124813, \
-0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \
-0x003806A8, 0x00000000, 0x00000000, 0x00000000, \
-}
-
-/********************************************************/
-/*  CPUSaver micro code for the D101S                   */
-/********************************************************/
-
-/*  Version 1.20.1  */
-
-/*  Parameter values for the D101S  */
-#define D101S_CPUSAVER_TIMER_DWORD		78
-#define D101S_CPUSAVER_BUNDLE_DWORD		67
-#define D101S_CPUSAVER_MIN_SIZE_DWORD		128
-
-#define D101S_RCVBUNDLE_UCODE \
-{\
-0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \
-0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \
-0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \
-0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \
-0x00308000, 0x00100610, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \
-0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \
-0x003A047E, 0x00044010, 0x00380819, 0x00000000, \
-0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \
-0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \
-0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \
-0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \
-0x00101313, 0x00380700, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \
-0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \
-0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \
-0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \
-0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \
-0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \
-0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \
-0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \
-0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00130831, \
-0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \
-0x00041000, 0x00010004, 0x00380700  \
-}
-
-/********************************************************/
-/*  CPUSaver micro code for the D102 B-step             */
-/********************************************************/
-
-/*  Version 2.0  */
-/*  Parameter values for the D102 B-step  */
-#define D102_B_CPUSAVER_TIMER_DWORD		82
-#define D102_B_CPUSAVER_BUNDLE_DWORD		106
-#define D102_B_CPUSAVER_MIN_SIZE_DWORD		70
-
-#define     D102_B_RCVBUNDLE_UCODE \
-{\
-0x006F0276, 0x0EF71FFF, 0x0ED30F86, 0x0D250ED9, 0x1FFF1FFF, 0x1FFF04D2, \
-0x00300001, 0x0140D871, 0x00300008, 0x00E00277, \
-0x01406C57, 0x00816073, 0x008700FA, 0x00E00070, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x01406CBA, 0x00807F9A, 0x00901F9A, 0x0024FFFF, \
-0x014B6F6F, 0x0030FFFE, 0x01407172, 0x01496FBA, \
-0x014B6F72, 0x00308000, 0x01406C52, 0x00912EFC, \
-0x00E00EF8, 0x00000000, 0x00000000, 0x00000000, \
-0x00906F8C, 0x00900F8C, 0x00E00F87, 0x00000000, \
-0x00906ED8, 0x01406C55, 0x00E00ED4, 0x00000000, \
-0x01406C51, 0x0080DFC2, 0x01406C52, 0x00815FC2, \
-0x01406C57, 0x00917FCC, 0x00E01FDD, 0x00000000, \
-0x00822D30, 0x01406C51, 0x0080CD26, 0x01406C52, \
-0x00814D26, 0x01406C57, 0x00916D26, 0x014C6FD7, \
-0x00300000, 0x00841FD2, 0x00300001, 0x0140D772, \
-0x00E012B3, 0x014C6F91, 0x0150710B, 0x01496F72, \
-0x0030FF80, 0x00940EDD, 0x00102000, 0x00038400, \
-0x00E00EDA, 0x00000000, 0x00000000, 0x00000000, \
-0x01406C57, 0x00917FE9, 0x00001000, 0x00E01FE9, \
-0x00200600, 0x0140D76F, 0x00138400, 0x01406FD8, \
-0x0140D96F, 0x00E01FDD, 0x00038400, 0x00102000, \
-0x00971FD7, 0x00101000, 0x00050200, 0x00E804D2, \
-0x014C6FD8, 0x00300001, 0x00840D26, 0x0140D872, \
-0x00E00D26, 0x014C6FD9, 0x00300001, 0x0140D972, \
-0x00941FBD, 0x00102000, 0x00038400, 0x014C6FD8, \
-0x00300006, 0x00840EDA, 0x014F71D8, 0x0140D872, \
-0x00E00EDA, 0x01496F50, 0x00E004D3, 0x00000000, \
-}
-
-/********************************************************/
-/*  Micro code for the D102 C-step                      */
-/********************************************************/
-
-/*  Parameter values for the D102 C-step  */
-#define D102_C_CPUSAVER_TIMER_DWORD		46
-#define D102_C_CPUSAVER_BUNDLE_DWORD		74
-#define D102_C_CPUSAVER_MIN_SIZE_DWORD		54
-
-#define     D102_C_RCVBUNDLE_UCODE \
-{ \
-0x00700279, 0x0E6604E2, 0x02BF0CAE, 0x1508150C, 0x15190E5B, 0x0E840F13, \
-0x00E014D8, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014DC, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014F4, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014E0, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014E7, 0x00000000, 0x00000000, 0x00000000, \
-0x00141000, 0x015D6F0D, 0x00E002C0, 0x00000000, \
-0x00200600, 0x00E0150D, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0030FF80, 0x00940E6A, 0x00038200, 0x00102000, \
-0x00E00E67, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00906E65, 0x00800E60, 0x00E00E5D, 0x00000000, \
-0x00300006, 0x00E0151A, 0x00000000, 0x00000000, \
-0x00906F19, 0x00900F19, 0x00E00F14, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x01406CBA, 0x00807FDA, 0x00901FDA, 0x0024FFFF, \
-0x014B6F6F, 0x0030FFFE, 0x01407172, 0x01496FBA, \
-0x014B6F72, 0x00308000, 0x01406C52, 0x00912E89, \
-0x00E00E85, 0x00000000, 0x00000000, 0x00000000  \
-}
-
-/********************************************************/
-/*  Micro code for the D102 E-step                      */
-/********************************************************/
-
-/*  Parameter values for the D102 E-step  */
-#define D102_E_CPUSAVER_TIMER_DWORD		42
-#define D102_E_CPUSAVER_BUNDLE_DWORD		54
-#define D102_E_CPUSAVER_MIN_SIZE_DWORD		46
-
-#define     D102_E_RCVBUNDLE_UCODE \
-{\
-0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x1FFF1FFF, 0x1FFF1FFF, \
-0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \
-0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \
-0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \
-0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \
-0x00300006, 0x00E014FB, 0x00000000, 0x00000000  \
-}
-
-#endif /* _E100_UCODE_H_ */
diff -Nru a/drivers/net/e100.c b/drivers/net/e100.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e100.c	Wed Feb 11 22:30:58 2004
@@ -0,0 +1,2297 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+/*
+ *	e100.c: Intel(R) PRO/100 ethernet driver
+ *
+ *	(Re)written 2003 by scott.feldman@intel.com.  Based loosely on
+ *	original e100 driver, but better described as a munging of
+ *	e100, e1000, eepro100, tg3, 8139cp, and other drivers.
+ *
+ *	References:
+ *		Intel 8255x 10/100 Mbps Ethernet Controller Family,
+ *		Open Source Software Developers Manual,
+ *		http://sourceforge.net/projects/e1000
+ *
+ *
+ *	                      Theory of Operation
+ *
+ *	I.   General
+ *
+ *	The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet
+ *	controller family, which includes the 82557, 82558, 82559, 82550,
+ *	82551, and 82562 devices.  82558 and greater controllers
+ *	integrate the Intel 82555 PHY.  The controllers are used in
+ *	server and client network interface cards, as well as in
+ *	LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx
+ *	configurations.  8255x supports a 32-bit linear addressing
+ *	mode and operates at 33Mhz PCI clock rate.
+ *
+ *	II.  Driver Operation
+ *
+ *	Memory-mapped mode is used exclusively to access the device's
+ *	shared-memory structure, the Control/Status Registers (CSR). All
+ *	setup, configuration, and control of the device, including queuing
+ *	of Tx, Rx, and configuration commands is through the CSR.
+ *	cmd_lock serializes accesses to the CSR command register.  cb_lock
+ *	protects the shared Command Block List (CBL).
+ *
+ *	8255x is highly MII-compliant and all access to the PHY go
+ *	through the Management Data Interface (MDI).  Consequently, the
+ *	driver leverages the mii.c library shared with other MII-compliant
+ *	devices.
+ *
+ *	Big- and Little-Endian byte order as well as 32- and 64-bit
+ *	archs are supported.  Weak-ordered memory and non-cache-coherent
+ *	archs are supported.
+ *
+ *	III. Transmit
+ *
+ *	A Tx skb is mapped and hangs off of a TCB.  TCBs are linked
+ *	together in a fixed-size ring (CBL) thus forming the flexible mode
+ *	memory structure.  A TCB marked with the suspend-bit indicates
+ *	the end of the ring.  The last TCB processed suspends the
+ *	controller, and the controller can be restarted by issue a CU
+ *	resume command to continue from the suspend point, or a CU start
+ *	command to start at a given position in the ring.
+ *
+ *	Non-Tx commands (config, multicast setup, etc) are linked
+ *	into the CBL ring along with Tx commands.  The common structure
+ *	used for both Tx and non-Tx commands is the Command Block (CB).
+ *
+ *	cb_to_use is the next CB to use for queuing a command; cb_to_clean
+ *	is the next CB to check for completion; cb_to_send is the first
+ *	CB to start on in case of a previous failure to resume.  CB clean
+ *	up happens in interrupt context in response to a CU interrupt, or
+ *	in dev->poll in the case where NAPI is enabled.  cbs_avail keeps
+ *	track of number of free CB resources available.
+ *
+ * 	Hardware padding of short packets to minimum packet size is
+ * 	enabled.  82557 pads with 7Eh, while the later controllers pad
+ * 	with 00h.
+ *
+ *	IV.  Recieve
+ *
+ *	The Receive Frame Area (RFA) comprises a ring of Receive Frame
+ *	Descriptors (RFD) + data buffer, thus forming the simplified mode
+ *	memory structure.  Rx skbs are allocated to contain both the RFD
+ *	and the data buffer, but the RFD is pulled off before the skb is
+ *	indicated.  The data buffer is aligned such that encapsulated
+ *	protocol headers are u32-aligned.  Since the RFD is part of the
+ *	mapped shared memory, and completion status is contained within
+ *	the RFD, the RFD must be dma_sync'ed to maintain a consistent
+ *	view from software and hardware.
+ *
+ *	Under typical operation, the  receive unit (RU) is start once,
+ *	and the controller happily fills RFDs as frames arrive.  If
+ *	replacement RFDs cannot be allocated, or the RU goes non-active,
+ *	the RU must be restarted.  Frame arrival generates an interrupt,
+ *	and Rx indication and re-allocation happen in the same context,
+ *	therefore no locking is required.  If NAPI is enabled, this work
+ *	happens in dev->poll.  A software-generated interrupt is gen-
+ *	erated from the watchdog to recover from a failed allocation
+ *	senario where all Rx resources have been indicated and none re-
+ *	placed.
+ *
+ *	V.   Miscellaneous
+ *
+ * 	VLAN offloading of tagging, stripping and filtering is not
+ * 	supported, but driver will accommodate the extra 4-byte VLAN tag
+ * 	for processing by upper layers.  Tx/Rx Checksum offloading is not
+ * 	supported.  Tx Scatter/Gather is not supported.  Jumbo Frames is
+ * 	not supported (hardware limitation).
+ *
+ * 	NAPI support is enabled with CONFIG_E100_NAPI.
+ *
+ * 	MagicPacket(tm) WoL support is enabled/disabled via ethtool.
+ *
+ * 	Thanks to JC (jchapman@katalix.com) for helping with
+ * 	testing/troubleshooting the development driver.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/string.h>
+#include <asm/unaligned.h>
+
+
+#define DRV_NAME		"e100"
+#define DRV_VERSION		"3.0.13_dev"
+#define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
+#define DRV_COPYRIGHT		"Copyright(c) 1999-2004 Intel Corporation"
+#define PFX			DRV_NAME ": "
+
+#define E100_WATCHDOG_PERIOD	2 * HZ
+#define E100_NAPI_WEIGHT	16
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+static int debug = 3;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+	(void)((NETIF_MSG_##nlevel & nic->msg_enable) && \
+	printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \
+		__FUNCTION__ , ## args))
+
+#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\
+	PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \
+	PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich }
+static struct pci_device_id e100_id_table[] = {
+	INTEL_8255X_ETHERNET_DEVICE(0x1029, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x1030, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x1031, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1032, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1033, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1034, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1038, 3),
+	INTEL_8255X_ETHERNET_DEVICE(0x1039, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103A, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103B, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103C, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103D, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x103E, 4),
+	INTEL_8255X_ETHERNET_DEVICE(0x1050, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1051, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1052, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1053, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1054, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1055, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1064, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1065, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1066, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1067, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1068, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1069, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x106A, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x106B, 6),
+	INTEL_8255X_ETHERNET_DEVICE(0x1059, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
+	INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
+	INTEL_8255X_ETHERNET_DEVICE(0x2459, 2),
+	INTEL_8255X_ETHERNET_DEVICE(0x245D, 2),
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, e100_id_table);
+
+enum mac {
+	mac_82557_D100_A  = 0,
+	mac_82557_D100_B  = 1,
+	mac_82557_D100_C  = 2,
+	mac_82558_D101_A4 = 4,
+	mac_82558_D101_B0 = 5,
+	mac_82559_D101M   = 8,
+	mac_82559_D101S   = 9,
+	mac_82550_D102    = 12,
+	mac_82550_D102_C  = 13,
+	mac_82551_E       = 14,
+	mac_82551_F       = 15,
+	mac_82551_10      = 16,
+	mac_unknown       = 0xFF,
+};
+
+enum phy {
+	phy_100a     = 0x000003E0,
+	phy_100c     = 0x035002A8,
+	phy_82555_tx = 0x015002A8,
+	phy_nsc_tx   = 0x5C002000,
+	phy_82562_et = 0x033002A8,
+	phy_82562_em = 0x032002A8,
+	phy_82562_eh = 0x017002A8,
+	phy_unknown  = 0xFFFFFFFF,
+};
+
+/* CSR (Control/Status Registers) */
+struct csr {
+	struct {
+		u8 status;
+		u8 stat_ack;
+		u8 cmd_lo;
+		u8 cmd_hi;
+		u32 gen_ptr;
+	} scb;
+	u32 port;
+	u16 flash_ctrl;
+	u8 eeprom_ctrl_lo;
+	u8 eeprom_ctrl_hi;
+	u32 mdi_ctrl;
+	u32 rx_dma_count;
+};
+
+enum scb_status {
+	rus_ready        = 0x10,
+	rus_mask         = 0x3C,
+};
+
+enum scb_stat_ack {
+	stat_ack_not_ours    = 0x00,
+	stat_ack_sw_gen      = 0x04,
+	stat_ack_rnr         = 0x10,
+	stat_ack_cu_idle     = 0x20,
+	stat_ack_frame_rx    = 0x40,
+	stat_ack_cu_cmd_done = 0x80,
+	stat_ack_not_present = 0xFF,
+	stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx),
+	stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),
+};
+
+enum scb_cmd_hi {
+	irq_mask_none = 0x00,
+	irq_mask_all  = 0x01,
+	irq_sw_gen    = 0x02,
+};
+
+enum scb_cmd_lo {
+	ruc_start      = 0x01,
+	ruc_load_base  = 0x06,
+	cuc_start      = 0x10,
+	cuc_resume     = 0x20,
+	cuc_dump_addr  = 0x40,
+	cuc_dump_stats = 0x50,
+	cuc_load_base  = 0x60,
+	cuc_dump_reset = 0x70,
+};
+
+enum port {
+	software_reset  = 0x0000,
+	selftest        = 0x0001,
+	selective_reset = 0x0002,
+};
+
+enum eeprom_ctrl_lo {
+	eesk = 0x01,
+	eecs = 0x02,
+	eedi = 0x04,
+	eedo = 0x08,
+};
+
+enum mdi_ctrl {
+	mdi_write = 0x04000000,
+	mdi_read  = 0x08000000,
+	mdi_ready = 0x10000000,
+};
+
+enum eeprom_op {
+	op_write = 0x05,
+	op_read  = 0x06,
+	op_ewds  = 0x10,
+	op_ewen  = 0x13,
+};
+
+enum eeprom_offsets {
+	eeprom_id         = 0x0A,
+	eeprom_config_asf = 0x0D,
+	eeprom_smbus_addr = 0x90,
+};
+
+enum eeprom_id {
+	eeprom_id_wol = 0x0020,
+};
+
+enum eeprom_config_asf {
+	eeprom_asf = 0x8000,
+	eeprom_gcl = 0x4000,
+};
+
+enum cb_status {
+	cb_complete = 0x8000,
+	cb_ok       = 0x2000,
+};
+
+enum cb_command {
+	cb_iaaddr = 0x0001,
+	cb_config = 0x0002,
+	cb_multi  = 0x0003,
+	cb_tx     = 0x0004,
+	cb_dump   = 0x0006,
+	cb_tx_sf  = 0x0008,
+	cb_cid    = 0x1f00,
+	cb_i      = 0x2000,
+	cb_s      = 0x4000,
+	cb_el     = 0x8000,
+};
+
+struct rfd {
+	u16 status;
+	u16 command;
+	u32 link;
+	u32 rbd;
+	u16 actual_size;
+	u16 size;
+};
+
+struct rx {
+	struct rx *next, *prev;
+	struct sk_buff *skb;
+	dma_addr_t dma_addr;
+};
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+#define X(a,b)	b,a
+#else
+#define X(a,b)	a,b
+#endif
+struct config {
+/*0*/	u8 X(byte_count:6, pad0:2);
+/*1*/	u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1);
+/*2*/	u8 adaptive_ifs;
+/*3*/	u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1),
+	   term_write_cache_line:1), pad3:4);
+/*4*/	u8 X(rx_dma_max_count:7, pad4:1);
+/*5*/	u8 X(tx_dma_max_count:7, dma_max_count_enable:1);
+/*6*/	u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1),
+	   tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1),
+	   rx_discard_overruns:1), rx_save_bad_frames:1);
+/*7*/	u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2),
+	   pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1),
+	   tx_dynamic_tbd:1);
+/*8*/	u8 X(X(mii_mode:1, pad8:6), csma_disabled:1);
+/*9*/	u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1),
+	   link_status_wake:1), arp_wake:1), mcmatch_wake:1);
+/*10*/	u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2),
+	   loopback:2);
+/*11*/	u8 X(linear_priority:3, pad11:5);
+/*12*/	u8 X(X(linear_priority_mode:1, pad12:3), ifs:4);
+/*13*/	u8 ip_addr_lo;
+/*14*/	u8 ip_addr_hi;
+/*15*/	u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1),
+	   wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1),
+	   pad15_2:1), crs_or_cdt:1);
+/*16*/	u8 fc_delay_lo;
+/*17*/	u8 fc_delay_hi;
+/*18*/	u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1),
+	   rx_long_ok:1), fc_priority_threshold:3), pad18:1);
+/*19*/	u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1),
+	   fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1),
+	   full_duplex_force:1), full_duplex_pin:1);
+/*20*/	u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1);
+/*21*/	u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4);
+/*22*/	u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6);
+	u8 pad_d102[9];
+};
+
+#define E100_MAX_MULTICAST_ADDRS	64
+struct multi {
+	u16 count;
+	u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/];
+};
+
+/* Important: keep total struct u32-aligned */
+struct cb {
+	u16 status;
+	u16 command;
+	u32 link;
+	union {
+		u8 iaaddr[ETH_ALEN];
+		struct config config;
+		struct multi multi;
+		struct {
+			u32 tbd_array;
+			u16 tcb_byte_count;
+			u8 threshold;
+			u8 tbd_count;
+			struct {
+				u32 buf_addr;
+				u16 size;
+				u16 eol;
+			} tbd;
+		} tcb;
+		u32 dump_buffer_addr;
+	} u;
+	struct cb *next, *prev;
+	dma_addr_t dma_addr;
+	struct sk_buff *skb;
+};
+
+enum loopback {
+	lb_none = 0, lb_mac = 1, lb_phy = 3,
+};
+
+struct stats {
+	u32 tx_good_frames, tx_max_collisions, tx_late_collisions,
+		tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
+		tx_multiple_collisions, tx_total_collisions;
+	u32 rx_good_frames, rx_crc_errors, rx_alignment_errors,
+		rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
+		rx_short_frame_errors;
+	u32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
+	u16 xmt_tco_frames, rcv_tco_frames;
+	u32 complete;
+};
+
+struct mem {
+	struct {
+		u32 signature;
+		u32 result;
+	} selftest;
+	struct stats stats;
+	u8 dump_buf[596];
+};
+
+struct param_range {
+	u32 min;
+	u32 max;
+	u32 count;
+};
+
+struct params {
+	struct param_range rfds;
+	struct param_range cbs;
+};
+
+struct nic {
+	/* Begin: frequently used values: keep adjacent for cache effect */
+	u32 msg_enable				____cacheline_aligned;
+	struct net_device *netdev;
+	struct pci_dev *pdev;
+
+	struct rx *rxs				____cacheline_aligned;
+	struct rx *rx_to_use;
+	struct rx *rx_to_clean;
+	struct rfd blank_rfd;
+	int ru_running;
+
+	spinlock_t cb_lock			____cacheline_aligned;
+	spinlock_t cmd_lock;
+	struct csr *csr;
+	enum scb_cmd_lo cuc_cmd;
+	unsigned int cbs_avail;
+	struct cb *cbs;
+	struct cb *cb_to_use;
+	struct cb *cb_to_send;
+	struct cb *cb_to_clean;
+	u16 tx_command;
+	/* End: frequently used values: keep adjacent for cache effect */
+
+	enum {
+		ich           = (1 << 0),
+		promiscuous   = (1 << 1),
+		multicast_all = (1 << 2),
+		wol_magic     = (1 << 3),
+	} flags					____cacheline_aligned;
+
+	enum mac mac;
+	enum phy phy;
+	struct params params;
+	struct net_device_stats net_stats;
+	struct timer_list watchdog;
+	struct timer_list blink_timer;
+	struct mii_if_info mii;
+	enum loopback loopback;
+
+	struct mem *mem;
+	dma_addr_t dma_addr;
+
+	dma_addr_t cbs_dma_addr;
+	u8 adaptive_ifs;
+	u8 tx_threshold;
+	u32 tx_frames;
+	u32 tx_collisions;
+	u32 tx_deferred;
+	u32 tx_single_collisions;
+	u32 tx_multiple_collisions;
+	u32 tx_fc_pause;
+	u32 tx_tco_frames;
+
+	u32 rx_fc_pause;
+	u32 rx_fc_unsupported;
+	u32 rx_tco_frames;
+
+	u8 rev_id;
+	u16 leds;
+	u16 eeprom_wc;
+	u16 eeprom[256];
+	u32 pm_state[16];
+};
+
+static inline void e100_write_flush(struct nic *nic)
+{
+	/* Flush previous PCI writes through intermediate bridges
+	 * by doing a benign read */
+	(void)readb(&nic->csr->scb.status);
+}
+
+static inline void e100_enable_irq(struct nic *nic)
+{
+	writeb(irq_mask_none, &nic->csr->scb.cmd_hi);
+	e100_write_flush(nic);
+}
+
+static inline void e100_disable_irq(struct nic *nic)
+{
+	writeb(irq_mask_all, &nic->csr->scb.cmd_hi);
+	e100_write_flush(nic);
+}
+
+static void e100_hw_reset(struct nic *nic)
+{
+	/* Put CU and RU into idle with a selective reset to get
+	 * device off of PCI bus */
+	writel(selective_reset, &nic->csr->port);
+	e100_write_flush(nic); udelay(20);
+
+	/* Now fully reset device */
+	writel(software_reset, &nic->csr->port);
+	e100_write_flush(nic); udelay(20);
+
+	/* TCO workaround - 82559 and greater */
+	if(nic->mac >= mac_82559_D101M) {
+		/* Issue a redundant CU load base without setting
+		 * general pointer, and without waiting for scb to
+		 * clear.  This gets us into post-driver.  Finally,
+		 * wait 20 msec for reset to take effect. */
+		writeb(cuc_load_base, &nic->csr->scb.cmd_lo);
+		mdelay(20);
+	}
+
+	/* Mask off our interrupt line - it's unmasked after reset */
+	e100_disable_irq(nic);
+}
+
+static int e100_self_test(struct nic *nic)
+{
+	u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest);
+
+	/* Passing the self-test is a pretty good indication
+	 * that the device can DMA to/from host memory */
+
+	nic->mem->selftest.signature = 0;
+	nic->mem->selftest.result = 0xFFFFFFFF;
+
+	writel(selftest | dma_addr, &nic->csr->port);
+	e100_write_flush(nic);
+	/* Wait 10 msec for self-test to complete */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ / 100 + 1);
+
+	/* Interrupts are enabled after self-test */
+	e100_disable_irq(nic);
+
+	/* Check results of self-test */
+	if(nic->mem->selftest.result != 0) {
+		DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n",
+			nic->mem->selftest.result);
+		return -ETIMEDOUT;
+	}
+	if(nic->mem->selftest.signature == 0) {
+		DPRINTK(HW, ERR, "Self-test failed: timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data)
+{
+	u32 cmd_addr_data[3];
+	u8 ctrl;
+	int i, j;
+
+	/* Three cmds: write/erase enable, write data, write/erase disable */
+	cmd_addr_data[0] = op_ewen << (addr_len - 2);
+	cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | data;
+	cmd_addr_data[2] = op_ewds << (addr_len - 2);
+
+	/* Bit-bang cmds to write word to eeprom */
+	for(j = 0; j < 3; j++) {
+
+		/* Chip select */
+		writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
+		e100_write_flush(nic); udelay(4);
+
+		for(i = 31; i >= 0; i--) {
+			ctrl = (cmd_addr_data[j] & (1 << i)) ?
+				eecs | eedi : eecs;
+			writeb(ctrl, &nic->csr->eeprom_ctrl_lo);
+			e100_write_flush(nic); udelay(4);
+			writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
+			e100_write_flush(nic); udelay(4);
+		}
+		/* Wait 10 msec for cmd to complete */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ / 100 + 1);
+
+		/* Chip deselect */
+		writeb(0, &nic->csr->eeprom_ctrl_lo);
+		e100_write_flush(nic); udelay(4);
+	}
+
+};
+
+/* General technique stolen from the eepro100 driver - very clever */
+static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
+{
+	u32 cmd_addr_data;
+	u16 data = 0;
+	u8 ctrl;
+	int i;
+
+	cmd_addr_data = ((op_read << *addr_len) | addr) << 16;
+
+	/* Chip select */
+	writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
+	e100_write_flush(nic); udelay(4);
+
+	/* Bit-bang to read word from eeprom */
+	for(i = 31; i >= 0; i--) {
+		ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
+		writeb(ctrl, &nic->csr->eeprom_ctrl_lo);
+		e100_write_flush(nic); udelay(4);
+		writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
+		e100_write_flush(nic); udelay(4);
+		/* Eeprom drives a dummy zero to EEDO after receiving
+		 * complete address.  Use this to adjust addr_len. */
+		ctrl = readb(&nic->csr->eeprom_ctrl_lo);
+		if(!(ctrl & eedo) && i > 16) {
+			*addr_len -= (i - 16);
+			i = 17;
+		}
+		data = (data << 1) | (ctrl & eedo ? 1 : 0);
+	}
+
+	/* Chip deselect */
+	writeb(0, &nic->csr->eeprom_ctrl_lo);
+	e100_write_flush(nic); udelay(4);
+
+	return data;
+};
+
+/* Load entire EEPROM image into driver cache and validate checksum */
+static int e100_eeprom_load(struct nic *nic)
+{
+	u16 addr, addr_len = 8, checksum = 0;
+
+	/* Try reading with an 8-bit addr len to discover actual addr len */
+	e100_eeprom_read(nic, &addr_len, 0);
+	nic->eeprom_wc = 1 << addr_len;
+
+	for(addr = 0; addr < nic->eeprom_wc; addr++) {
+		nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
+		if(addr < nic->eeprom_wc - 1)
+			checksum += nic->eeprom[addr];
+	}
+
+	/* The checksum, stored in the last word, is calculated such that
+	 * the sum of words should be 0xBABA */
+	checksum = 0xBABA - checksum;
+	if(checksum != nic->eeprom[nic->eeprom_wc - 1]) {
+		DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+/* Save (portion of) driver EEPROM cache to device and update checksum */
+static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
+{
+	u16 addr, addr_len = 8, checksum = 0;
+
+	/* Try reading with an 8-bit addr len to discover actual addr len */
+	e100_eeprom_read(nic, &addr_len, 0);
+	nic->eeprom_wc = 1 << addr_len;
+
+	if(start + count >= nic->eeprom_wc)
+		return -EINVAL;
+
+	for(addr = start; addr < start + count; addr++)
+		e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]);
+
+	/* The checksum, stored in the last word, is calculated such that
+	 * the sum of words should be 0xBABA */
+	for(addr = 0; addr < nic->eeprom_wc - 1; addr++)
+		checksum += nic->eeprom[addr];
+	nic->eeprom[nic->eeprom_wc - 1] = 0xBABA - checksum;
+	e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, 0xBABA - checksum);
+
+	return 0;
+}
+
+#define E100_WAIT_SCB_TIMEOUT 40
+static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
+{
+	unsigned long flags;
+	unsigned int i;
+	int err = 0;
+
+	spin_lock_irqsave(&nic->cmd_lock, flags);
+
+	/* Previous command is accepted when SCB clears */
+	for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) {
+		if(likely(!readb(&nic->csr->scb.cmd_lo)))
+			break;
+		cpu_relax();
+		if(unlikely(i > (E100_WAIT_SCB_TIMEOUT >> 1)))
+			udelay(5);
+	}
+	if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
+		err = -EAGAIN;
+		goto err_unlock;
+	}
+
+	if(unlikely(cmd != cuc_resume))
+		writel(dma_addr, &nic->csr->scb.gen_ptr);
+	writeb(cmd, &nic->csr->scb.cmd_lo);
+
+err_unlock:
+	spin_unlock_irqrestore(&nic->cmd_lock, flags);
+
+	return err;
+}
+
+static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
+	void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
+{
+	struct cb *cb;
+	unsigned long flags;
+	int err = 0;
+
+	spin_lock_irqsave(&nic->cb_lock, flags);
+
+	if(unlikely(!nic->cbs_avail)) {
+		err = -ENOMEM;
+		goto err_unlock;
+	}
+
+	cb = nic->cb_to_use;
+	nic->cb_to_use = cb->next;
+	nic->cbs_avail--;
+	cb->skb = skb;
+
+	if(unlikely(!nic->cbs_avail))
+		err = -ENOSPC;
+
+	cb_prepare(nic, cb, skb);
+
+	/* Order is important otherwise we'll be in a race with h/w:
+	 * set S-bit in current first, then clear S-bit in previous. */
+	cb->command |= cpu_to_le16(cb_s);
+	cb->prev->command &= cpu_to_le16(~cb_s);
+
+	while(nic->cb_to_send != nic->cb_to_use) {
+		if(unlikely((err = e100_exec_cmd(nic, nic->cuc_cmd,
+			nic->cb_to_send->dma_addr)))) {
+			/* Ok, here's where things get sticky.  It's
+			 * possible that we can't schedule the command
+			 * because the controller is too busy, so
+			 * let's just queue the command and try again
+			 * when another command is scheduled. */
+			break;
+		} else {
+			nic->cuc_cmd = cuc_resume;
+			nic->cb_to_send = nic->cb_to_send->next;
+		}
+	}
+
+err_unlock:
+	spin_unlock_irqrestore(&nic->cb_lock, flags);
+
+	return err;
+}
+
+static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
+{
+	u32 data_out = 0;
+	unsigned int i;
+
+	writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl);
+
+	for(i = 0; i < 100; i++) {
+		udelay(20);
+		if((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready)
+			break;
+	}
+
+	DPRINTK(HW, DEBUG,
+		"%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n",
+		dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out);
+	return (u16)data_out;
+}
+
+static int mdio_read(struct net_device *netdev, int addr, int reg)
+{
+	return mdio_ctrl(netdev->priv, addr, mdi_read, reg, 0);
+}
+
+static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
+{
+	mdio_ctrl(netdev->priv, addr, mdi_write, reg, data);
+}
+
+static void e100_get_defaults(struct nic *nic)
+{
+	struct param_range rfds = { .min = 64, .max = 256, .count = 64 };
+	struct param_range cbs  = { .min = 64, .max = 256, .count = 64 };
+
+	pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
+	/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
+	nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id;
+	if(nic->mac == mac_unknown)
+		nic->mac = mac_82557_D100_A;
+
+	nic->params.rfds = rfds;
+	nic->params.cbs = cbs;
+
+	/* Quadwords to DMA into FIFO before starting frame transmit */
+	nic->tx_threshold = 0xE0;
+
+	nic->tx_command = cpu_to_le16(cb_tx | cb_i | cb_tx_sf |
+		((nic->mac >= mac_82558_D101_A4) ? cb_cid : 0));
+
+	/* Template for a freshly allocated RFD */
+	nic->blank_rfd.command = cpu_to_le16(cb_el);
+	nic->blank_rfd.rbd = 0xFFFFFFFF;
+	nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
+
+	/* MII setup */
+	nic->mii.phy_id_mask = 0x1F;
+	nic->mii.reg_num_mask = 0x1F;
+	nic->mii.dev = nic->netdev;
+	nic->mii.mdio_read = mdio_read;
+	nic->mii.mdio_write = mdio_write;
+}
+
+static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+{
+	struct config *config = &cb->u.config;
+	u8 *c = (u8 *)config;
+
+	cb->command = cpu_to_le16(cb_config);
+
+	memset(config, 0, sizeof(struct config));
+
+	config->byte_count = 0x16;		/* bytes in this struct */
+	config->rx_fifo_limit = 0x8;		/* bytes in FIFO before DMA */
+	config->direct_rx_dma = 0x1;		/* reserved */
+	config->standard_tcb = 0x1;		/* 1=standard, 0=extended */
+	config->standard_stat_counter = 0x1;	/* 1=standard, 0=extended */
+	config->rx_discard_short_frames = 0x1;	/* 1=discard, 0=pass */
+	config->tx_underrun_retry = 0x3;	/* # of underrun retries */
+	config->mii_mode = 0x1;			/* 1=MII mode, 0=503 mode */
+	config->pad10 = 0x6;
+	config->no_source_addr_insertion = 0x1;	/* 1=no, 0=yes */
+	config->preamble_length = 0x2;		/* 0=1, 1=3, 2=7, 3=15 bytes */
+	config->ifs = 0x6;			/* x16 = inter frame spacing */
+	config->ip_addr_hi = 0xF2;		/* ARP IP filter - not used */
+	config->pad15_1 = 0x1;
+	config->pad15_2 = 0x1;
+	config->crs_or_cdt = 0x0;		/* 0=CRS only, 1=CRS or CDT */
+	config->fc_delay_hi = 0x40;		/* time delay for fc frame */
+	config->tx_padding = 0x1;		/* 1=pad short frames */
+	config->fc_priority_threshold = 0x7;	/* 7=priority fc disabled */
+	config->pad18 = 0x1;
+	config->full_duplex_pin = 0x1;		/* 1=examine FDX# pin */
+	config->pad20_1 = 0x1F;
+	config->fc_priority_location = 0x1;	/* 1=byte#31, 0=byte#19 */
+	config->pad21_1 = 0x5;
+
+	config->adaptive_ifs = nic->adaptive_ifs;
+	config->loopback = nic->loopback;
+
+	if(nic->mii.force_media && nic->mii.full_duplex)
+		config->full_duplex_force = 0x1;	/* 1=force, 0=auto */
+
+	if(nic->flags & promiscuous || nic->loopback) {
+		config->rx_save_bad_frames = 0x1;	/* 1=save, 0=discard */
+		config->rx_discard_short_frames = 0x0;	/* 1=discard, 0=save */
+		config->promiscuous_mode = 0x1;		/* 1=on, 0=off */
+	}
+
+	if(nic->flags & multicast_all)
+		config->multicast_all = 0x1;		/* 1=accept, 0=no */
+
+	if(!(nic->flags & wol_magic))
+		config->magic_packet_disable = 0x1;	/* 1=off, 0=on */
+
+	if(nic->mac >= mac_82558_D101_A4) {
+		config->fc_disable = 0x1;	/* 1=Tx fc off, 0=Tx fc on */
+		config->mwi_enable = 0x1;	/* 1=enable, 0=disable */
+		config->standard_tcb = 0x0;	/* 1=standard, 0=extended */
+		config->rx_long_ok = 0x1;	/* 1=VLANs ok, 0=standard */
+		if(nic->mac >= mac_82559_D101M)
+			config->tno_intr = 0x1;		/* TCO stats enable */
+		else
+			config->standard_stat_counter = 0x0;
+	}
+
+	DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+		c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
+	DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+		c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]);
+	DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+		c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
+}
+
+static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
+	struct sk_buff *skb)
+{
+	cb->command = cpu_to_le16(cb_iaaddr);
+	memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN);
+}
+
+static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+{
+	cb->command = cpu_to_le16(cb_dump);
+	cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr +
+		offsetof(struct mem, dump_buf));
+}
+
+#define NCONFIG_AUTO_SWITCH	0x0080
+#define MII_NSC_CONG		MII_RESV1
+#define NSC_CONG_ENABLE		0x0100
+#define NSC_CONG_TXREADY	0x0400
+#define ADVERTISE_FC_SUPPORTED	0x0400
+static int e100_phy_init(struct nic *nic)
+{
+	struct net_device *netdev = nic->netdev;
+	u32 addr;
+	u16 bmcr, stat, id_lo, id_hi, cong;
+
+	/* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
+	for(addr = 0; addr < 32; addr++) {
+		nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
+		bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
+		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
+		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
+		if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
+			break;
+	}
+	DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
+	if(addr == 32)
+		return -EAGAIN;
+
+	/* Selected the phy and isolate the rest */
+	for(addr = 0; addr < 32; addr++) {
+		if(addr != nic->mii.phy_id) {
+			mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
+		} else {
+			bmcr = mdio_read(netdev, addr, MII_BMCR);
+			mdio_write(netdev, addr, MII_BMCR,
+				bmcr & ~BMCR_ISOLATE);
+		}
+	}
+
+	/* Get phy ID */
+	id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
+	id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
+	nic->phy = (u32)id_hi << 16 | (u32)id_lo;
+	DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy);
+
+	/* Handle National tx phy */
+	if(nic->phy == phy_nsc_tx) {
+		/* Disable congestion control */
+		cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG);
+		cong |= NSC_CONG_TXREADY;
+		cong &= ~NSC_CONG_ENABLE;
+		mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
+	}
+
+	if(nic->mac >= mac_82550_D102)
+		/* enable/disable MDI/MDI-X auto-switching */
+		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
+			nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
+
+	return 0;
+}
+
+static int e100_hw_init(struct nic *nic)
+{
+	int err;
+
+	e100_hw_reset(nic);
+
+	DPRINTK(HW, ERR, "e100_hw_init\n");
+	if(!in_interrupt() && (err = e100_self_test(nic)))
+		return err;
+
+	if((err = e100_phy_init(nic)))
+		return err;
+	if((err = e100_exec_cmd(nic, cuc_load_base, 0)))
+		return err;
+	if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
+		return err;
+	if((err = e100_exec_cb(nic, NULL, e100_configure)))
+		return err;
+	if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
+		return err;
+	if((err = e100_exec_cmd(nic, cuc_dump_addr,
+		nic->dma_addr + offsetof(struct mem, stats))))
+		return err;
+	if((err = e100_exec_cmd(nic, cuc_dump_reset, 0)))
+		return err;
+
+	e100_disable_irq(nic);
+
+	return 0;
+}
+
+static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+{
+	struct net_device *netdev = nic->netdev;
+	struct dev_mc_list *list = netdev->mc_list;
+	u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS);
+
+	cb->command = cpu_to_le16(cb_multi);
+	cb->u.multi.count = cpu_to_le16(count * ETH_ALEN);
+	for(i = 0; list && i < count; i++, list = list->next)
+		memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr,
+			ETH_ALEN);
+}
+
+static void e100_set_multicast_list(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+
+	DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n",
+		netdev->mc_count, netdev->flags);
+
+	if(netdev->flags & IFF_PROMISC)
+		nic->flags |= promiscuous;
+	else
+		nic->flags &= ~promiscuous;
+
+	if(netdev->flags & IFF_ALLMULTI ||
+		netdev->mc_count > E100_MAX_MULTICAST_ADDRS)
+		nic->flags |= multicast_all;
+	else
+		nic->flags &= ~multicast_all;
+
+	e100_exec_cb(nic, NULL, e100_configure);
+	e100_exec_cb(nic, NULL, e100_multi);
+}
+
+static void e100_update_stats(struct nic *nic)
+{
+	struct net_device_stats *ns = &nic->net_stats;
+	struct stats *s = &nic->mem->stats;
+	u32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause :
+		(nic->mac < mac_82559_D101M) ? (u32 *)&s->xmt_tco_frames :
+		&s->complete;
+
+	/* Device's stats reporting may take several microseconds to
+	 * complete, so where always waiting for results of the
+	 * previous command. */
+
+	if(*complete == le32_to_cpu(0x0000A007)) {
+		*complete = 0;
+		nic->tx_frames = le32_to_cpu(s->tx_good_frames);
+		nic->tx_collisions = le32_to_cpu(s->tx_total_collisions);
+		ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions);
+		ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions);
+		ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs);
+		ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns);
+		ns->collisions += nic->tx_collisions;
+		ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
+			le32_to_cpu(s->tx_lost_crs);
+		ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
+		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors);
+		ns->rx_over_errors += le32_to_cpu(s->rx_resource_errors);
+		ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
+		ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
+		ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
+		ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
+			le32_to_cpu(s->rx_alignment_errors) +
+			le32_to_cpu(s->rx_short_frame_errors) +
+			le32_to_cpu(s->rx_cdt_errors);
+		nic->tx_deferred += le32_to_cpu(s->tx_deferred);
+		nic->tx_single_collisions +=
+			le32_to_cpu(s->tx_single_collisions);
+		nic->tx_multiple_collisions +=
+			le32_to_cpu(s->tx_multiple_collisions);
+		if(nic->mac >= mac_82558_D101_A4) {
+			nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause);
+			nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause);
+			nic->rx_fc_unsupported +=
+				le32_to_cpu(s->fc_rcv_unsupported);
+			if(nic->mac >= mac_82559_D101M) {
+				nic->tx_tco_frames +=
+					le16_to_cpu(s->xmt_tco_frames);
+				nic->rx_tco_frames +=
+					le16_to_cpu(s->rcv_tco_frames);
+			}
+		}
+	}
+
+	e100_exec_cmd(nic, cuc_dump_reset, 0);
+}
+
+static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
+{
+	/* Adjust inter-frame-spacing (IFS) between two transmits if
+	 * we're getting collisions on a half-duplex connection. */
+
+	if(duplex == DUPLEX_HALF) {
+		u32 prev = nic->adaptive_ifs;
+		u32 min_frames = (speed == SPEED_100) ? 1000 : 100;
+
+		if((nic->tx_frames / 32 < nic->tx_collisions) &&
+		   (nic->tx_frames > min_frames)) {
+			if(nic->adaptive_ifs < 60)
+				nic->adaptive_ifs += 5;
+		} else if (nic->tx_frames < min_frames) {
+			if(nic->adaptive_ifs >= 5)
+				nic->adaptive_ifs -= 5;
+		}
+		if(nic->adaptive_ifs != prev)
+			e100_exec_cb(nic, NULL, e100_configure);
+	}
+}
+
+static void e100_watchdog(unsigned long data)
+{
+	struct nic *nic = (struct nic *)data;
+	struct ethtool_cmd cmd;
+
+	DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies);
+
+	/* mii library handles link maintenance tasks */
+
+	mii_ethtool_gset(&nic->mii, &cmd);
+
+	if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
+		DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n",
+			cmd.speed == SPEED_100 ? "100" : "10",
+			cmd.duplex == DUPLEX_FULL ? "full" : "half");
+	} else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
+		DPRINTK(LINK, INFO, "link down\n");
+	}
+
+	mii_check_link(&nic->mii);
+
+	/* Software generated interrupt to recover from (rare) Rx
+	 * allocation failure */
+	writeb(irq_sw_gen, &nic->csr->scb.cmd_hi);
+	e100_write_flush(nic);
+
+	e100_update_stats(nic);
+	e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex);
+
+	if(nic->mac <= mac_82557_D100_C)
+		/* Issue a multicast command to workaround a 557 lock up */
+		e100_set_multicast_list(nic->netdev);
+
+	mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD);
+}
+
+static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb,
+	struct sk_buff *skb)
+{
+	cb->command = nic->tx_command;
+	cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
+	cb->u.tcb.tcb_byte_count = 0;
+	cb->u.tcb.threshold = nic->tx_threshold;
+	cb->u.tcb.tbd_count = 1;
+	cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
+		skb->data, skb->len, PCI_DMA_TODEVICE));
+	cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
+}
+
+static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	int err = e100_exec_cb(nic, skb, e100_xmit_prepare);
+
+	switch(err) {
+	case -ENOSPC:
+		/* We queued the skb, but now we're out of space. */
+		netif_stop_queue(netdev);
+		break;
+	case -ENOMEM:
+		/* This is a hard error - log it. */
+		DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n");
+		netif_stop_queue(netdev);
+		return 1;
+	}
+
+	netdev->trans_start = jiffies;
+	return 0;
+}
+
+static inline int e100_tx_clean(struct nic *nic)
+{
+	struct cb *cb;
+	int tx_cleaned = 0;
+
+	spin_lock(&nic->cb_lock);
+
+	DPRINTK(TX_DONE, DEBUG, "cb->status = 0x%04X\n",
+		nic->cb_to_clean->status);
+
+	/* Clean CBs marked complete */
+	for(cb = nic->cb_to_clean;
+	    cb->status & cpu_to_le16(cb_complete);
+	    cb = nic->cb_to_clean = cb->next) {
+		if(likely(cb->skb)) {
+			nic->net_stats.tx_packets++;
+			nic->net_stats.tx_bytes += cb->skb->len;
+
+			pci_unmap_single(nic->pdev,
+				le32_to_cpu(cb->u.tcb.tbd.buf_addr),
+				le16_to_cpu(cb->u.tcb.tbd.size),
+				PCI_DMA_TODEVICE);
+			dev_kfree_skb_any(cb->skb);
+			tx_cleaned = 1;
+		}
+		cb->status = 0;
+		nic->cbs_avail++;
+	}
+
+	spin_unlock(&nic->cb_lock);
+
+	/* Recover from running out of Tx resources in xmit_frame */
+	if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
+		netif_wake_queue(nic->netdev);
+
+	return tx_cleaned;
+}
+
+static void e100_clean_cbs(struct nic *nic)
+{
+	if(nic->cbs) {
+		while(nic->cb_to_clean != nic->cb_to_use) {
+			struct cb *cb = nic->cb_to_clean;
+			if(cb->skb) {
+				pci_unmap_single(nic->pdev,
+					le32_to_cpu(cb->u.tcb.tbd.buf_addr),
+					le16_to_cpu(cb->u.tcb.tbd.size),
+					PCI_DMA_TODEVICE);
+				dev_kfree_skb(cb->skb);
+			}
+			nic->cb_to_clean = nic->cb_to_clean->next;
+		}
+		nic->cbs_avail = nic->params.cbs.count;
+		pci_free_consistent(nic->pdev,
+			sizeof(struct cb) * nic->params.cbs.count,
+			nic->cbs, nic->cbs_dma_addr);
+		nic->cbs = NULL;
+		nic->cbs_avail = 0;
+	}
+	nic->cuc_cmd = cuc_start;
+	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean =
+		nic->cbs;
+}
+
+static int e100_alloc_cbs(struct nic *nic)
+{
+	struct cb *cb;
+	unsigned int i, count = nic->params.cbs.count;
+
+	nic->cuc_cmd = cuc_start;
+	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL;
+	nic->cbs_avail = 0;
+
+	nic->cbs = pci_alloc_consistent(nic->pdev,
+		sizeof(struct cb) * count, &nic->cbs_dma_addr);
+	if(!nic->cbs)
+		return -ENOMEM;
+
+	for(cb = nic->cbs, i = 0; i < count; cb++, i++) {
+		cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
+		cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1;
+
+		cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb);
+		cb->link = cpu_to_le32(nic->cbs_dma_addr +
+			((i+1) % count) * sizeof(struct cb));
+	}
+
+	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs;
+	nic->cbs_avail = count;
+
+	return 0;
+}
+
+static inline void e100_start_receiver(struct nic *nic)
+{
+	/* (Re)start RU if suspended or idle and RFA is non-NULL */
+	if(!nic->ru_running && nic->rx_to_clean->skb) {
+		e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr);
+		nic->ru_running = 1;
+	}
+}
+
+#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
+static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
+{
+	unsigned int rx_offset = 2; /* u32 align protocol headers */
+
+	if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + rx_offset)))
+		return -ENOMEM;
+
+	/* Align, init, and map the RFA. */
+	rx->skb->dev = nic->netdev;
+	skb_reserve(rx->skb, rx_offset);
+	memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd));
+	rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
+		RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+
+	/* Link the RFD to end of RFA by linking previous RFD to
+	 * this one, and clearing EL bit of previous.  */
+	if(rx->prev->skb) {
+		struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
+		put_unaligned(cpu_to_le32(rx->dma_addr),
+			(u32 *)&prev_rfd->link);
+		prev_rfd->command &= ~cpu_to_le16(cb_el);
+		pci_dma_sync_single(nic->pdev, rx->prev->dma_addr,
+			sizeof(struct rfd), PCI_DMA_TODEVICE);
+	}
+
+	return 0;
+}
+
+static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
+	unsigned int *work_done, unsigned int work_to_do)
+{
+	struct sk_buff *skb = rx->skb;
+	struct rfd *rfd = (struct rfd *)skb->data;
+	u16 rfd_status, actual_size;
+
+	if(unlikely(work_done && *work_done >= work_to_do))
+		return -EAGAIN;
+
+	/* Need to sync before taking a peek at cb_complete bit */
+	pci_dma_sync_single(nic->pdev, rx->dma_addr,
+		sizeof(struct rfd), PCI_DMA_FROMDEVICE);
+	rfd_status = le16_to_cpu(rfd->status);
+
+	DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status);
+
+	/* If data isn't ready, nothing to indicate */
+	if(unlikely(!(rfd_status & cb_complete)))
+       		return -EAGAIN;
+
+	/* Get actual data size */
+	actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
+	if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
+		actual_size = RFD_BUF_LEN - sizeof(struct rfd);
+
+	/* Get data */
+	pci_dma_sync_single(nic->pdev, rx->dma_addr,
+		sizeof(struct rfd) + actual_size,
+		PCI_DMA_FROMDEVICE);
+	pci_unmap_single(nic->pdev, rx->dma_addr,
+		RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+
+	/* Pull off the RFD and put the actual data (minus eth hdr) */
+	skb_reserve(skb, sizeof(struct rfd));
+	skb_put(skb, actual_size);
+	skb->protocol = eth_type_trans(skb, nic->netdev);
+
+	if(unlikely(!(rfd_status & cb_ok)) ||
+	   actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) {
+		/* Don't indicate if errors */
+		dev_kfree_skb_any(skb);
+	} else {
+		nic->net_stats.rx_packets++;
+		nic->net_stats.rx_bytes += actual_size;
+		nic->netdev->last_rx = jiffies;
+#ifdef CONFIG_E100_NAPI
+		netif_receive_skb(skb);
+#else
+		netif_rx(skb);
+#endif
+		if(work_done)
+			(*work_done)++;
+	}
+
+	rx->skb = NULL;
+
+	return 0;
+}
+
+static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done,
+	unsigned int work_to_do)
+{
+	struct rx *rx;
+
+	/* Indicate newly arrived packets */
+	for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
+		if(e100_rx_indicate(nic, rx, work_done, work_to_do))
+			break; /* No more to clean */
+	}
+
+	/* Alloc new skbs to refill list */
+	for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
+		if(unlikely(e100_rx_alloc_skb(nic, rx)))
+			break; /* Better luck next time (see watchdog) */
+	}
+
+	e100_start_receiver(nic);
+}
+
+static void e100_rx_clean_list(struct nic *nic)
+{
+	struct rx *rx;
+	unsigned int i, count = nic->params.rfds.count;
+
+	if(nic->rxs) {
+		for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
+			if(rx->skb) {
+				pci_unmap_single(nic->pdev, rx->dma_addr,
+					RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+				dev_kfree_skb(rx->skb);
+			}
+		}
+		kfree(nic->rxs);
+		nic->rxs = NULL;
+	}
+
+	nic->rx_to_use = nic->rx_to_clean = NULL;
+	nic->ru_running = 0;
+}
+
+static int e100_rx_alloc_list(struct nic *nic)
+{
+	struct rx *rx;
+	unsigned int i, count = nic->params.rfds.count;
+
+	nic->rx_to_use = nic->rx_to_clean = NULL;
+
+	if(!(nic->rxs = kmalloc(sizeof(struct rx) * count, GFP_ATOMIC)))
+		return -ENOMEM;
+	memset(nic->rxs, 0, sizeof(struct rx) * count);
+
+	for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
+		rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;
+		rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1;
+		if(e100_rx_alloc_skb(nic, rx)) {
+			e100_rx_clean_list(nic);
+			return -ENOMEM;
+		}
+	}
+
+	nic->rx_to_use = nic->rx_to_clean = nic->rxs;
+
+	return 0;
+}
+
+static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *netdev = dev_id;
+	struct nic *nic = netdev->priv;
+	u8 stat_ack = readb(&nic->csr->scb.stat_ack);
+
+	DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack);
+
+	if(stat_ack == stat_ack_not_ours ||	/* Not our interrupt */
+	   stat_ack == stat_ack_not_present)	/* Hardware is ejected */
+		return IRQ_NONE;
+
+	/* Ack interrupt(s) */
+	writeb(stat_ack, &nic->csr->scb.stat_ack);
+
+	/* We hit Receive No Resource (RNR); restart RU after cleaning */
+	if(stat_ack & stat_ack_rnr)
+		nic->ru_running = 0;
+
+#ifdef CONFIG_E100_NAPI
+	e100_disable_irq(nic);
+	netif_rx_schedule(netdev);
+#else
+	if(stat_ack & stat_ack_rx)
+		e100_rx_clean(nic, NULL, 0);
+	if(stat_ack & stat_ack_tx)
+		e100_tx_clean(nic);
+#endif
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_E100_NAPI
+static int e100_poll(struct net_device *netdev, int *budget)
+{
+	struct nic *nic = netdev->priv;
+	unsigned int work_to_do = min(netdev->quota, *budget);
+	unsigned int work_done = 0;
+	int tx_cleaned;
+
+	e100_rx_clean(nic, &work_done, work_to_do);
+	tx_cleaned = e100_tx_clean(nic);
+
+	/* If no Rx and Tx cleanup work was done, exit polling mode. */
+	if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
+		netif_rx_complete(netdev);
+		e100_enable_irq(nic);
+		return 0;
+	}
+
+	*budget -= work_done;
+	netdev->quota -= work_done;
+
+	return 1;
+}
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void e100_netpoll(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	e100_disable_irq(nic);
+	e100_intr(nic->pdev->irq, netdev, NULL);
+	e100_enable_irq(nic);
+}
+#endif
+
+static struct net_device_stats *e100_get_stats(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return &nic->net_stats;
+}
+
+static int e100_set_mac_address(struct net_device *netdev, void *p)
+{
+	struct nic *nic = netdev->priv;
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	e100_exec_cb(nic, NULL, e100_setup_iaaddr);
+
+	return 0;
+}
+
+static int e100_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
+		return -EINVAL;
+	netdev->mtu = new_mtu;
+	return 0;
+}
+
+static int e100_asf(struct nic *nic)
+{
+	/* ASF can be enabled from eeprom */
+	return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1055) &&
+	   (nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
+	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
+	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
+}
+
+static int e100_up(struct nic *nic)
+{
+	int err;
+
+	if((err = e100_rx_alloc_list(nic)))
+		return err;
+	if((err = e100_alloc_cbs(nic)))
+		goto err_rx_clean_list;
+	if((err = e100_hw_init(nic)))
+		goto err_clean_cbs;
+	e100_set_multicast_list(nic->netdev);
+	e100_start_receiver(nic);
+	netif_start_queue(nic->netdev);
+	mod_timer(&nic->watchdog, jiffies);
+	if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ,
+		nic->netdev->name, nic->netdev)))
+		goto err_no_irq;
+	e100_enable_irq(nic);
+	return 0;
+
+err_no_irq:
+	del_timer_sync(&nic->watchdog);
+	netif_stop_queue(nic->netdev);
+err_clean_cbs:
+	e100_clean_cbs(nic);
+err_rx_clean_list:
+	e100_rx_clean_list(nic);
+	return err;
+}
+
+static void e100_down(struct nic *nic)
+{
+	e100_hw_reset(nic);
+	free_irq(nic->pdev->irq, nic->netdev);
+	del_timer_sync(&nic->watchdog);
+	netif_carrier_off(nic->netdev);
+	netif_stop_queue(nic->netdev);
+	e100_clean_cbs(nic);
+	e100_rx_clean_list(nic);
+}
+
+static void e100_tx_timeout(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+
+	DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n",
+		readb(&nic->csr->scb.status));
+	e100_down(netdev->priv);
+	e100_up(netdev->priv);
+}
+
+static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
+{
+	int err;
+	struct sk_buff *skb;
+
+	/* Use driver resources to perform internal MAC or PHY
+	 * loopback test.  A single packet is prepared and transmitted
+	 * in loopback mode, and the test passes if the received
+	 * packet compares byte-for-byte to the transmitted packet. */
+
+	if((err = e100_rx_alloc_list(nic)))
+		return err;
+	if((err = e100_alloc_cbs(nic)))
+		goto err_clean_rx;
+
+	/* ICH PHY loopback is broken so do MAC loopback instead */
+	if(nic->flags & ich && loopback_mode == lb_phy)
+		loopback_mode = lb_mac;
+
+	nic->loopback = loopback_mode;
+	if((err = e100_hw_init(nic)))
+		goto err_loopback_none;
+
+	if(loopback_mode == lb_phy)
+		mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
+			BMCR_LOOPBACK);
+
+	e100_start_receiver(nic);
+
+	if(!(skb = dev_alloc_skb(ETH_DATA_LEN))) {
+		err = -ENOMEM;
+		goto err_loopback_none;
+	}
+	skb_put(skb, ETH_DATA_LEN);
+	memset(skb->data, 0xFF, ETH_DATA_LEN);
+	e100_xmit_frame(skb, nic->netdev);
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ / 100 + 1);
+
+	if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
+	   skb->data, ETH_DATA_LEN))
+       		err = -EAGAIN;
+
+err_loopback_none:
+	mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
+	nic->loopback = lb_none;
+	e100_hw_init(nic);
+	e100_clean_cbs(nic);
+err_clean_rx:
+	e100_rx_clean_list(nic);
+	return err;
+}
+
+#define MII_LED_CONTROL	0x1B
+static void e100_blink_led(unsigned long data)
+{
+	struct nic *nic = (struct nic *)data;
+	enum led_state {
+		led_on     = 0x01,
+		led_off    = 0x04,
+		led_on_559 = 0x05,
+		led_on_557 = 0x07,
+	};
+
+	nic->leds = (nic->leds & led_on) ? led_off :
+		(nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559;
+	mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds);
+	mod_timer(&nic->blink_timer, jiffies + HZ / 4);
+}
+
+static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct nic *nic = netdev->priv;
+	return mii_ethtool_gset(&nic->mii, cmd);
+}
+
+static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct nic *nic = netdev->priv;
+	int err;
+
+	mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET);
+	err = mii_ethtool_sset(&nic->mii, cmd);
+	e100_exec_cb(nic, NULL, e100_configure);
+
+	return err;
+}
+
+static void e100_get_drvinfo(struct net_device *netdev,
+	struct ethtool_drvinfo *info)
+{
+	struct nic *nic = netdev->priv;
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->fw_version, "N/A");
+	strcpy(info->bus_info, pci_name(nic->pdev));
+}
+
+static int e100_get_regs_len(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+#define E100_PHY_REGS		0x1C
+#define E100_REGS_LEN		1 + E100_PHY_REGS + \
+	sizeof(nic->mem->dump_buf) / sizeof(u32)
+	return E100_REGS_LEN * sizeof(u32);
+}
+
+static void e100_get_regs(struct net_device *netdev,
+	struct ethtool_regs *regs, void *p)
+{
+	struct nic *nic = netdev->priv;
+	u32 *buff = p;
+	int i;
+
+	regs->version = (1 << 24) | nic->rev_id;
+	buff[0] = readb(&nic->csr->scb.cmd_hi) << 24 |
+		readb(&nic->csr->scb.cmd_lo) << 16 |
+		readw(&nic->csr->scb.status);
+	for(i = E100_PHY_REGS; i >= 0; i--)
+		buff[1 + E100_PHY_REGS - i] =
+			mdio_read(netdev, nic->mii.phy_id, i);
+	memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
+	e100_exec_cb(nic, NULL, e100_dump);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ / 100 + 1);
+	memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf,
+		sizeof(nic->mem->dump_buf));
+}
+
+static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct nic *nic = netdev->priv;
+	wol->supported = (nic->mac >= mac_82558_D101_A4) ?  WAKE_MAGIC : 0;
+	wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0;
+}
+
+static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct nic *nic = netdev->priv;
+
+	if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
+		return -EOPNOTSUPP;
+
+	if(wol->wolopts)
+		nic->flags |= wol_magic;
+	else
+		nic->flags &= ~wol_magic;
+
+	pci_enable_wake(nic->pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+	e100_exec_cb(nic, NULL, e100_configure);
+
+	return 0;
+}
+
+static u32 e100_get_msglevel(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return nic->msg_enable;
+}
+
+static void e100_set_msglevel(struct net_device *netdev, u32 value)
+{
+	struct nic *nic = netdev->priv;
+	nic->msg_enable = value;
+}
+
+static int e100_nway_reset(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return mii_nway_restart(&nic->mii);
+}
+
+static u32 e100_get_link(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return mii_link_ok(&nic->mii);
+}
+
+static int e100_get_eeprom_len(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	return nic->eeprom_wc << 1;
+}
+
+#define E100_EEPROM_MAGIC	0x1234
+static int e100_get_eeprom(struct net_device *netdev,
+	struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct nic *nic = netdev->priv;
+
+	eeprom->magic = E100_EEPROM_MAGIC;
+	memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len);
+
+	return 0;
+}
+
+static int e100_set_eeprom(struct net_device *netdev,
+	struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct nic *nic = netdev->priv;
+
+	if(eeprom->magic != E100_EEPROM_MAGIC)
+		return -EINVAL;
+	memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len);
+
+	return e100_eeprom_save(nic, eeprom->offset >> 1,
+		(eeprom->len >> 1) + 1);
+}
+
+static void e100_get_ringparam(struct net_device *netdev,
+	struct ethtool_ringparam *ring)
+{
+	struct nic *nic = netdev->priv;
+	struct param_range *rfds = &nic->params.rfds;
+	struct param_range *cbs = &nic->params.cbs;
+
+	ring->rx_max_pending = rfds->max;
+	ring->tx_max_pending = cbs->max;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = rfds->count;
+	ring->tx_pending = cbs->count;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+static int e100_set_ringparam(struct net_device *netdev,
+	struct ethtool_ringparam *ring)
+{
+	struct nic *nic = netdev->priv;
+	struct param_range *rfds = &nic->params.rfds;
+	struct param_range *cbs = &nic->params.cbs;
+
+	if(netif_running(netdev))
+		e100_down(nic);
+	rfds->count = max(ring->rx_pending, rfds->min);
+	rfds->count = min(rfds->count, rfds->max);
+	cbs->count = max(ring->tx_pending, cbs->min);
+	cbs->count = min(cbs->count, cbs->max);
+	if(netif_running(netdev))
+		e100_up(nic);
+
+	return 0;
+}
+
+static const char e100_gstrings_test[][ETH_GSTRING_LEN] = {
+	"Link test     (on/offline)",
+	"Eeprom test   (on/offline)",
+	"Self test        (offline)",
+	"Mac loopback     (offline)",
+	"Phy loopback     (offline)",
+};
+#define E100_TEST_LEN	sizeof(e100_gstrings_test) / ETH_GSTRING_LEN
+
+static int e100_diag_test_count(struct net_device *netdev)
+{
+	return E100_TEST_LEN;
+}
+
+static void e100_diag_test(struct net_device *netdev,
+	struct ethtool_test *test, u64 *data)
+{
+	struct nic *nic = netdev->priv;
+	int i;
+
+	memset(data, 0, E100_TEST_LEN * sizeof(u64));
+	data[0] = !mii_link_ok(&nic->mii);
+	data[1] = e100_eeprom_load(nic);
+	if(test->flags & ETH_TEST_FL_OFFLINE) {
+		if(netif_running(netdev))
+			e100_down(nic);
+		data[2] = e100_self_test(nic);
+		data[3] = e100_loopback_test(nic, lb_mac);
+		data[4] = e100_loopback_test(nic, lb_phy);
+		if(netif_running(netdev))
+			e100_up(nic);
+	}
+	for(i = 0; i < E100_TEST_LEN; i++)
+		test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0;
+}
+
+static int e100_phys_id(struct net_device *netdev, u32 data)
+{
+	struct nic *nic = netdev->priv;
+
+	if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+	mod_timer(&nic->blink_timer, jiffies);
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(data * HZ);
+	del_timer_sync(&nic->blink_timer);
+	mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0);
+
+	return 0;
+}
+
+static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
+	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
+	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
+	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
+	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
+	"tx_heartbeat_errors", "tx_window_errors",
+	/* device-specific stats */
+	"tx_deferred", "tx_single_collisions", "tx_multi_collisions",
+	"tx_flow_control_pause", "rx_flow_control_pause",
+	"rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets",
+};
+#define E100_NET_STATS_LEN	21
+#define E100_STATS_LEN	sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN
+
+static int e100_get_stats_count(struct net_device *netdev)
+{
+	return E100_STATS_LEN;
+}
+
+static void e100_get_ethtool_stats(struct net_device *netdev,
+	struct ethtool_stats *stats, u64 *data)
+{
+	struct nic *nic = netdev->priv;
+	int i;
+
+	for(i = 0; i < E100_NET_STATS_LEN; i++)
+		data[i] = ((unsigned long *)&nic->net_stats)[i];
+
+	data[i++] = nic->tx_deferred;
+	data[i++] = nic->tx_single_collisions;
+	data[i++] = nic->tx_multiple_collisions;
+	data[i++] = nic->tx_fc_pause;
+	data[i++] = nic->rx_fc_pause;
+	data[i++] = nic->rx_fc_unsupported;
+	data[i++] = nic->tx_tco_frames;
+	data[i++] = nic->rx_tco_frames;
+}
+
+static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+{
+	switch(stringset) {
+	case ETH_SS_TEST:
+		memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test));
+		break;
+	case ETH_SS_STATS:
+		memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats));
+		break;
+	}
+}
+
+static struct ethtool_ops e100_ethtool_ops = {
+	.get_settings		= e100_get_settings,
+	.set_settings		= e100_set_settings,
+	.get_drvinfo		= e100_get_drvinfo,
+	.get_regs_len		= e100_get_regs_len,
+	.get_regs		= e100_get_regs,
+	.get_wol		= e100_get_wol,
+	.set_wol		= e100_set_wol,
+	.get_msglevel		= e100_get_msglevel,
+	.set_msglevel		= e100_set_msglevel,
+	.nway_reset		= e100_nway_reset,
+	.get_link		= e100_get_link,
+	.get_eeprom_len		= e100_get_eeprom_len,
+	.get_eeprom		= e100_get_eeprom,
+	.set_eeprom		= e100_set_eeprom,
+	.get_ringparam		= e100_get_ringparam,
+	.set_ringparam		= e100_set_ringparam,
+	.self_test_count	= e100_diag_test_count,
+	.self_test		= e100_diag_test,
+	.get_strings		= e100_get_strings,
+	.phys_id		= e100_phys_id,
+	.get_stats_count	= e100_get_stats_count,
+	.get_ethtool_stats	= e100_get_ethtool_stats,
+};
+
+static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct nic *nic = netdev->priv;
+	struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr->ifr_data;
+
+	return generic_mii_ioctl(&nic->mii, mii, cmd, NULL);
+}
+
+static int e100_alloc(struct nic *nic)
+{
+	nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem),
+		&nic->dma_addr);
+	return nic->mem ? 0 : -ENOMEM;
+}
+
+static void e100_free(struct nic *nic)
+{
+	if(nic->mem) {
+		pci_free_consistent(nic->pdev, sizeof(struct mem),
+			nic->mem, nic->dma_addr);
+		nic->mem = NULL;
+	}
+}
+
+static int e100_open(struct net_device *netdev)
+{
+	struct nic *nic = netdev->priv;
+	int err = 0;
+
+	netif_carrier_off(netdev);
+	if((err = e100_up(nic)))
+		DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n");
+	return err;
+}
+
+static int e100_close(struct net_device *netdev)
+{
+	e100_down(netdev->priv);
+	return 0;
+}
+
+static int __devinit e100_probe(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	struct net_device *netdev;
+	struct nic *nic;
+	int err;
+
+	if(!(netdev = alloc_etherdev(sizeof(struct nic)))) {
+		if(((1 << debug) - 1) & NETIF_MSG_PROBE)
+			printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n");
+		return -ENOMEM;
+	}
+
+	netdev->open = e100_open;
+	netdev->stop = e100_close;
+	netdev->hard_start_xmit = e100_xmit_frame;
+	netdev->get_stats = e100_get_stats;
+	netdev->set_multicast_list = e100_set_multicast_list;
+	netdev->set_mac_address = e100_set_mac_address;
+	netdev->change_mtu = e100_change_mtu;
+	netdev->do_ioctl = e100_do_ioctl;
+	SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
+	netdev->tx_timeout = e100_tx_timeout;
+	netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
+#ifdef CONFIG_E100_NAPI
+	netdev->poll = e100_poll;
+	netdev->weight = E100_NAPI_WEIGHT;
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	netdev->poll_controller = e100_netpoll;
+#endif
+
+	nic = netdev->priv;
+	nic->netdev = netdev;
+	nic->pdev = pdev;
+	nic->msg_enable = (1 << debug) - 1;
+	pci_set_drvdata(pdev, netdev);
+
+	if((err = pci_enable_device(pdev))) {
+		DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n");
+		goto err_out_free_dev;
+	}
+
+	if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+		DPRINTK(PROBE, ERR, "Cannot find proper PCI device "
+			"base address, aborting.\n");
+		err = -ENODEV;
+		goto err_out_disable_pdev;
+	}
+
+	if((err = pci_request_regions(pdev, DRV_NAME))) {
+		DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n");
+		goto err_out_disable_pdev;
+	}
+
+	pci_set_master(pdev);
+
+	if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) {
+		DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n");
+		goto err_out_free_res;
+	}
+
+	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
+	nic->csr = ioremap(pci_resource_start(pdev, 0), sizeof(struct csr));
+	if(!nic->csr) {
+		DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n");
+		err = -ENOMEM;
+		goto err_out_free_res;
+	}
+
+	if(ent->driver_data)
+		nic->flags |= ich;
+	else
+		nic->flags &= ~ich;
+
+	spin_lock_init(&nic->cb_lock);
+	spin_lock_init(&nic->cmd_lock);
+
+	init_timer(&nic->watchdog);
+	nic->watchdog.function = e100_watchdog;
+	nic->watchdog.data = (unsigned long)nic;
+	init_timer(&nic->blink_timer);
+	nic->blink_timer.function = e100_blink_led;
+	nic->blink_timer.data = (unsigned long)nic;
+
+	if((err = e100_alloc(nic))) {
+		DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n");
+		goto err_out_iounmap;
+	}
+
+	e100_get_defaults(nic);
+	e100_hw_reset(nic);
+	e100_phy_init(nic);
+
+	if((err = e100_eeprom_load(nic)))
+		goto err_out_free;
+	((u16 *)netdev->dev_addr)[0] = le16_to_cpu(nic->eeprom[0]);
+	((u16 *)netdev->dev_addr)[1] = le16_to_cpu(nic->eeprom[1]);
+	((u16 *)netdev->dev_addr)[2] = le16_to_cpu(nic->eeprom[2]);
+	if(!is_valid_ether_addr(netdev->dev_addr)) {
+		DPRINTK(PROBE, ERR, "Invalid MAC address from "
+			"EEPROM, aborting.\n");
+		err = -EAGAIN;
+		goto err_out_free;
+	}
+
+	/* Wol magic packet can be enabled from eeprom */
+	if((nic->mac >= mac_82558_D101_A4) &&
+	   (nic->eeprom[eeprom_id] & eeprom_id_wol))
+		nic->flags |= wol_magic;
+
+	pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+
+	if((err = register_netdev(netdev))) {
+		DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");
+		goto err_out_free;
+	}
+
+	DPRINTK(PROBE, INFO, "addr 0x%lx, irq %d, "
+		"MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n",
+		pci_resource_start(pdev, 0), pdev->irq,
+		netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
+		netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+
+	return 0;
+
+err_out_free:
+	e100_free(nic);
+err_out_iounmap:
+	iounmap(nic->csr);
+err_out_free_res:
+	pci_release_regions(pdev);
+err_out_disable_pdev:
+	pci_disable_device(pdev);
+err_out_free_dev:
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(netdev);
+	return err;
+}
+
+static void __devexit e100_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+
+	if(netdev) {
+		struct nic *nic = netdev->priv;
+		unregister_netdev(netdev);
+		e100_free(nic);
+		iounmap(nic->csr);
+		free_netdev(netdev);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		pci_set_drvdata(pdev, NULL);
+	}
+}
+
+#ifdef CONFIG_PM
+static int e100_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct nic *nic = netdev->priv;
+
+	if(netif_running(netdev))
+		e100_down(nic);
+	e100_hw_reset(nic);
+	netif_device_detach(netdev);
+
+	pci_save_state(pdev, nic->pm_state);
+	pci_enable_wake(pdev, state, nic->flags & (wol_magic | e100_asf(nic)));
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, state);
+
+	return 0;
+}
+
+static int e100_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct nic *nic = netdev->priv;
+
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev, nic->pm_state);
+	e100_hw_init(nic);
+
+	netif_device_attach(netdev);
+	if(netif_running(netdev))
+		e100_up(nic);
+
+	return 0;
+}
+#endif
+
+static struct pci_driver e100_driver = {
+	.name =         DRV_NAME,
+	.id_table =     e100_id_table,
+	.probe =        e100_probe,
+	.remove =       __devexit_p(e100_remove),
+#ifdef CONFIG_PM
+	.suspend =      e100_suspend,
+	.resume =       e100_resume,
+#endif
+};
+
+static int __init e100_init_module(void)
+{
+	if(((1 << debug) - 1) & NETIF_MSG_DRV) {
+		printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
+		printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
+	}
+        return pci_module_init(&e100_driver);
+}
+
+static void __exit e100_cleanup_module(void)
+{
+	pci_unregister_driver(&e100_driver);
+}
+
+module_init(e100_init_module);
+module_exit(e100_cleanup_module);
diff -Nru a/drivers/net/e2100.c b/drivers/net/e2100.c
--- a/drivers/net/e2100.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/e2100.c	Wed Feb 11 22:30:57 2004
@@ -269,6 +269,9 @@
 	ei_status.get_8390_hdr = &e21_get_8390_hdr;
 	dev->open = &e21_open;
 	dev->stop = &e21_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 	return 0;
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/eepro100.c	Wed Feb 11 22:30:57 2004
@@ -542,6 +542,7 @@
 static void speedo_refill_rx_buffers(struct net_device *dev, int force);
 static int speedo_rx(struct net_device *dev);
 static void speedo_tx_buffer_gc(struct net_device *dev);
+static void poll_speedo (struct net_device *dev);
 static irqreturn_t speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static int speedo_close(struct net_device *dev);
 static struct net_device_stats *speedo_get_stats(struct net_device *dev);
@@ -885,6 +886,9 @@
 	dev->get_stats = &speedo_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &speedo_ioctl;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &poll_speedo;
+#endif
 
 	if (register_netdevice(dev))
 		goto err_free_unlock;
@@ -1674,6 +1678,23 @@
 	clear_bit(0, (void*)&sp->in_interrupt);
 	return IRQ_RETVAL(handled);
 }
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+static void poll_speedo (struct net_device *dev)
+{
+	/* disable_irq is not very nice, but with the funny lockless design
+	   we have no other choice. */
+	disable_irq(dev->irq);
+	speedo_interrupt (dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 
 static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
 {
diff -Nru a/drivers/net/es3210.c b/drivers/net/es3210.c
--- a/drivers/net/es3210.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/es3210.c	Wed Feb 11 22:30:57 2004
@@ -298,6 +298,9 @@
 
 	dev->open = &es_open;
 	dev->stop = &es_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 out1:
diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c
--- a/drivers/net/fc/iph5526.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/fc/iph5526.c	Wed Feb 11 22:30:57 2004
@@ -4501,7 +4501,7 @@
 		iph5526_probe_pci(dev);
 		err = register_netdev(dev);
 		if (err < 0) {
-			kfree(dev);
+			free_netdev(dev);
 			printk("iph5526.c: init_fcdev failed for card #%d\n", i+1);
 			break;
 		}
diff -Nru a/drivers/net/fec.c b/drivers/net/fec.c
--- a/drivers/net/fec.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/fec.c	Wed Feb 11 22:30:56 2004
@@ -1638,9 +1638,12 @@
 
 /* Initialize the FEC Ethernet on 860T (or ColdFire 5272).
  */
+ /*
+  * XXX:  We need to clean up on failure exits here.
+  */
 int __init fec_enet_init(struct net_device *dev)
 {
-	struct fec_enet_private *fep;
+	struct fec_enet_private *fep = dev->priv;
 	unsigned long	mem_addr;
 	volatile cbd_t	*bdp;
 	cbd_t		*cbd_base;
@@ -1651,13 +1654,6 @@
 	if (found)
 		return(-ENXIO);
 
-	/* Allocate some private information.
-	*/
-	fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL);
-	if (!fep)
-		return -ENOMEM;
-	memset(fep, 0, sizeof(*fep));
-
 	/* Create an Ethernet device instance.
 	*/
 	fecp = fec_hwp;
@@ -1694,6 +1690,7 @@
 	}
 	mem_addr = __get_free_page(GFP_KERNEL);
 	cbd_base = (cbd_t *)mem_addr;
+	/* XXX: missing check for allocation failure */
 
 	fec_uncache(mem_addr);
 
@@ -1715,6 +1712,7 @@
 		/* Allocate a page.
 		*/
 		mem_addr = __get_free_page(GFP_KERNEL);
+		/* XXX: missing check for allocation failure */
 
 		fec_uncache(mem_addr);
 
@@ -1761,9 +1759,6 @@
 	fec_request_intrs(dev, fecp);
 
 	dev->base_addr = (unsigned long)fecp;
-	dev->priv = fep;
-
-	ether_setup(dev);
 
 	/* The FEC Ethernet specific entries in the device structure. */
 	dev->open = fec_enet_open;
@@ -1949,14 +1944,28 @@
 	fecp->fec_mii_speed = fep->phy_speed;
 }
 
-static struct net_device fec_dev = {
-	.init = fec_enet_init,
-};
+static struct net_device *fec_dev;
 
 static int __init fec_enet_module_init(void)
 {
-	if (register_netdev(&fec_dev) != 0)
+	struct net_device *dev;
+	int err;
+
+	dev = alloc_etherdev(sizeof(struct fec_enet_private));
+	if (!dev)
+		return -ENOMEM;
+	err = fec_enet_init(dev);
+	if (err) {
+		free_netdev(dev);
+		return err;
+	}
+
+	if (register_netdev(dev) != 0) {
+		/* XXX: missing cleanup here */
+		free_netdev(dev);
 		return -EIO;
+	}
+	fec_dev = dev;
 	return(0);
 }
 
diff -Nru a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
--- a/drivers/net/hp-plus.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/hp-plus.c	Wed Feb 11 22:30:56 2004
@@ -236,6 +236,9 @@
 
 	dev->open = &hpp_open;
 	dev->stop = &hpp_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	ei_status.name = name;
 	ei_status.word16 = 0;		/* Agggghhhhh! Debug time: 2 days! */
diff -Nru a/drivers/net/hp.c b/drivers/net/hp.c
--- a/drivers/net/hp.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/hp.c	Wed Feb 11 22:30:57 2004
@@ -207,6 +207,9 @@
 	dev->base_addr = ioaddr + NIC_OFFSET;
 	dev->open = &hp_open;
 	dev->stop = &hp_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	ei_status.name = name;
 	ei_status.word16 = wordmode;
diff -Nru a/drivers/net/hydra.c b/drivers/net/hydra.c
--- a/drivers/net/hydra.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/hydra.c	Wed Feb 11 22:30:57 2004
@@ -138,6 +138,9 @@
     ei_status.reg_offset = hydra_offsets;
     dev->open = &hydra_open;
     dev->stop = &hydra_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = ei_poll;
+#endif
 #ifdef MODULE
     ei_status.priv = (unsigned long)root_hydra_dev;
     root_hydra_dev = dev;
diff -Nru a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c
--- a/drivers/net/isa-skeleton.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/isa-skeleton.c	Wed Feb 11 22:30:57 2004
@@ -104,8 +104,6 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int netcard_probe(struct net_device *dev);
-
 static int	netcard_probe1(struct net_device *dev, int ioaddr);
 static int	net_open(struct net_device *dev);
 static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
@@ -129,11 +127,11 @@
  * If dev->base_addr == 2, allocate space for the device and return success
  * (detachable devices only).
  */
-int __init 
-netcard_probe(struct net_device *dev)
+static int __init do_netcard_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev->base_addr;
+	int irq = dev->irq;
 
 	SET_MODULE_OWNER(dev);
 
@@ -144,14 +142,49 @@
 
 	for (i = 0; netcard_portlist[i]; i++) {
 		int ioaddr = netcard_portlist[i];
-		if (check_region(ioaddr, NETCARD_IO_EXTENT))
-			continue;
 		if (netcard_probe1(dev, ioaddr) == 0)
 			return 0;
+		dev->irq = irq;
 	}
 
 	return -ENODEV;
 }
+ 
+static void cleanup_card(struct net_device *dev)
+{
+#ifdef jumpered_dma
+	free_dma(dev->dma);
+#endif
+#ifdef jumpered_interrupts
+	free_irq(dev->irq, dev);
+#endif
+	release_region(dev->base_addr, NETCARD_IO_EXTENT);
+}
+
+struct net_device * __init netcard_probe(int unit)
+{
+	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_netcard_probe(dev);
+	if (err)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	cleanup_card(dev);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
 
 /*
  * This is the real probe routine. Linux has a history of friendly device
@@ -163,6 +196,11 @@
 	struct net_local *np;
 	static unsigned version_printed;
 	int i;
+	int err = -ENODEV;
+
+	/* Grab the region so that no one else tries to probe our ioports. */
+	if (!request_region(ioaddr, NETCARD_IO_EXTENT, cardname))
+		return -EBUSY;
 
 	/*
 	 * For ethernet adaptors the first three octets of the station address 
@@ -171,9 +209,8 @@
 	 */ 
 	if (inb(ioaddr + 0) != SA_ADDR0
 		||	 inb(ioaddr + 1) != SA_ADDR1
-		||	 inb(ioaddr + 2) != SA_ADDR2) {
-		return -ENODEV;
-	}
+		||	 inb(ioaddr + 2) != SA_ADDR2)
+		goto out;
 
 	if (net_debug  &&  version_printed++ == 0)
 		printk(KERN_DEBUG "%s", version);
@@ -187,6 +224,7 @@
 	for (i = 0; i < 6; i++)
 		printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
 
+	err = -EAGAIN;
 #ifdef jumpered_interrupts
 	/*
 	 * If this board has jumpered interrupts, allocate the interrupt
@@ -217,7 +255,7 @@
 		if (irqval) {
 			printk("%s: unable to get IRQ %d (irqval=%d).\n",
 				   dev->name, dev->irq, irqval);
-			return -EAGAIN;
+			goto out;
 		}
 	}
 #endif	/* jumpered interrupt */
@@ -229,7 +267,7 @@
 	if (dev->dma == 0) {
 		if (request_dma(dev->dma, cardname)) {
 			printk("DMA %d allocation failed.\n", dev->dma);
-			return -EAGAIN;
+			goto out1;
 		} else
 			printk(", assigned DMA %d.\n", dev->dma);
 	} else {
@@ -256,30 +294,18 @@
 			}
 		if (i <= 0) {
 			printk("DMA probe failed.\n");
-			return -EAGAIN;
+			goto out1;
 		} 
 		if (request_dma(dev->dma, cardname)) {
 			printk("probed DMA %d allocation failed.\n", dev->dma);
-			return -EAGAIN;
+			goto out1;
 		}
 	}
 #endif	/* jumpered DMA */
 
-	/* Initialize the device structure. */
-	if (dev->priv == NULL) {
-		dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
-		if (dev->priv == NULL)
-			return -ENOMEM;
-	}
-
-	memset(dev->priv, 0, sizeof(struct net_local));
-
 	np = (struct net_local *)dev->priv;
 	spin_lock_init(&np->lock);
 
-	/* Grab the region so that no one else tries to probe our ioports. */
-	request_region(ioaddr, NETCARD_IO_EXTENT, cardname);
-
 	dev->open		= net_open;
 	dev->stop		= net_close;
 	dev->hard_start_xmit	= net_send_packet;
@@ -288,11 +314,14 @@
 
         dev->tx_timeout		= &net_tx_timeout;
         dev->watchdog_timeo	= MY_TX_TIMEOUT; 
-
-	/* Fill in the fields of the device structure with ethernet values. */
-	ether_setup(dev);
-
 	return 0;
+out1:
+#ifdef jumpered_interrupts
+	free_irq(dev->irq, dev);
+#endif
+out:
+	release_region(base_addr, NETCARD_IO_EXTENT);
+	return err;
 }
 
 static void net_tx_timeout(struct net_device *dev)
@@ -635,7 +664,7 @@
 
 #ifdef MODULE
 
-static struct net_device this_device;
+static struct net_device *this_device;
 static int io = 0x300;
 static int irq;
 static int dma;
@@ -644,42 +673,38 @@
 
 int init_module(void)
 {
+	struct net_device *dev;
 	int result;
 
 	if (io == 0)
 		printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n",
 			   cardname);
+	dev = alloc_etherdev(sizeof(struct net_local));
+	if (!dev)
+		return -ENOMEM;
 
 	/* Copy the parameters from insmod into the device structure. */
-	this_device.base_addr = io;
-	this_device.irq       = irq;
-	this_device.dma       = dma;
-	this_device.mem_start = mem;
-	this_device.init      = netcard_probe;
-
-	if ((result = register_netdev(&this_device)) != 0)
-		return result;
-
-	return 0;
+	dev->base_addr = io;
+	dev->irq       = irq;
+	dev->dma       = dma;
+	dev->mem_start = mem;
+	if (do_netcard_probe(dev) == 0) {
+		if (register_netdev(dev) == 0)
+			this_device = dev;
+			return 0;
+		}
+		cleanup_card(dev);
+	}
+	free_netdev(dev);
+	return -ENXIO;
 }
 
 void
 cleanup_module(void)
 {
-	unregister_netdev(&this_device);
-	/*
-	 * If we don't do this, we can't re-insmod it later.
-	 * Release irq/dma here, when you have jumpered versions and
-	 * allocate them in net_probe1().
-	 */
-	/*
-	   free_irq(this_device.irq, dev);
-	   free_dma(this_device.dma);
-	*/
-	release_region(this_device.base_addr, NETCARD_IO_EXTENT);
-
-	if (this_device.priv)
-		kfree(this_device.priv);
+	unregister_netdev(this_device);
+	cleanup_card(this_device);
+	free_netdev(this_device);
 }
 
 #endif /* MODULE */
diff -Nru a/drivers/net/lne390.c b/drivers/net/lne390.c
--- a/drivers/net/lne390.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/lne390.c	Wed Feb 11 22:30:57 2004
@@ -299,6 +299,9 @@
 
 	dev->open = &lne390_open;
 	dev->stop = &lne390_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 cleanup:
diff -Nru a/drivers/net/mac8390.c b/drivers/net/mac8390.c
--- a/drivers/net/mac8390.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/mac8390.c	Wed Feb 11 22:30:57 2004
@@ -442,6 +442,9 @@
 	/* Now fill in our stuff */
 	dev->open = &mac8390_open;
 	dev->stop = &mac8390_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	/* GAR, ei_status is actually a macro even though it looks global */
 	ei_status.name = cardname[type];
diff -Nru a/drivers/net/mace.c b/drivers/net/mace.c
--- a/drivers/net/mace.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/mace.c	Wed Feb 11 22:30:57 2004
@@ -20,9 +20,10 @@
 #include <asm/dbdma.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <asm/macio.h>
+
 #include "mace.h"
 
-static struct net_device *mace_devs;
 static int port_aaui = -1;
 
 #define N_RX_RING	8
@@ -61,8 +62,7 @@
     int timeout_active;
     int port_aaui;
     int chipid;
-    struct device_node* of_node;
-    struct net_device *next_mace;
+    struct macio_dev *mdev;
     spinlock_t lock;
 };
 
@@ -76,8 +76,6 @@
 	+ (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd))
 
 static int bitrev(int);
-static int mace_probe(void);
-static void mace_probe1(struct device_node *mace);
 static int mace_open(struct net_device *dev);
 static int mace_close(struct net_device *dev);
 static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
@@ -110,26 +108,19 @@
     return d;
 }
 
-static int __init mace_probe(void)
-{
-	struct device_node *mace;
-
-	for (mace = find_devices("mace"); mace != NULL; mace = mace->next)
-		mace_probe1(mace);
-	return mace_devs? 0: -ENODEV;
-}
 
-static void __init mace_probe1(struct device_node *mace)
+static int __devinit mace_probe(struct macio_dev *mdev, const struct of_match *match)
 {
-	int j, rev;
+	struct device_node *mace = macio_get_of_node(mdev);
 	struct net_device *dev;
 	struct mace_data *mp;
 	unsigned char *addr;
+	int j, rev, rc = -EBUSY;
 
-	if (mace->n_addrs != 3 || mace->n_intrs != 3) {
+	if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
 		printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n",
 		       mace->full_name);
-		return;
+		return -ENODEV;
 	}
 
 	addr = get_property(mace, "mac-address", NULL);
@@ -138,48 +129,48 @@
 		if (addr == NULL) {
 			printk(KERN_ERR "Can't get mac-address for MACE %s\n",
 			       mace->full_name);
-			return;
+			return -ENODEV;
 		}
 	}
 
 	/*
-	 * lazy allocation - it's a driver-wide thing and it will live until
-	 * the unload, but we don't allocate it until it's needed
+	 * lazy allocate the driver-wide dummy buffer. (Note that we
+	 * never have more than one MACE in the system anyway)
 	 */
 	if (dummy_buf == NULL) {
 		dummy_buf = kmalloc(RX_BUFLEN+2, GFP_KERNEL);
 		if (dummy_buf == NULL) {
 			printk(KERN_ERR "MACE: couldn't allocate dummy buffer\n");
-			return;
+			return -ENOMEM;
 		}
 	}
 
+	if (macio_request_resources(mdev, "mace")) {
+		printk(KERN_ERR "MACE: can't request IO resources !\n");
+		return -EBUSY;
+	}
+
 	dev = alloc_etherdev(PRIV_BYTES);
-	if (!dev)
-		return;
+	if (!dev) {
+		printk(KERN_ERR "MACE: can't allocate ethernet device !\n");
+		rc = -ENOMEM;
+		goto err_release;
+	}
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
 
 	mp = dev->priv;
-	mp->of_node = mace;
-	
-	if (!request_OF_resource(mace, 0, " (mace)")) {
-		printk(KERN_ERR "MACE: can't request IO resource !\n");
-		goto out1;
-	}
-	if (!request_OF_resource(mace, 1, " (mace tx dma)")) {
-		printk(KERN_ERR "MACE: can't request TX DMA resource !\n");
-		goto out2;
-	}
-
-	if (!request_OF_resource(mace, 2, " (mace tx dma)")) {
-		printk(KERN_ERR "MACE: can't request RX DMA resource !\n");
-		goto out3;
-	}
-
-	dev->base_addr = mace->addrs[0].address;
-	mp->mace = (volatile struct mace *)
-		ioremap(mace->addrs[0].address, 0x1000);
-	dev->irq = mace->intrs[0].line;
+	mp->mdev = mdev;
+	macio_set_drvdata(mdev, dev);
+
+	dev->base_addr = macio_resource_start(mdev, 0);
+	mp->mace = (volatile struct mace *)ioremap(dev->base_addr, 0x1000);
+	if (mp->mace == NULL) {
+		printk(KERN_ERR "MACE: can't map IO resources !\n");
+		rc = -ENOMEM;
+		goto err_free;
+	}
+	dev->irq = macio_irq(mdev, 0);
 
 	printk(KERN_INFO "%s: MACE at", dev->name);
 	rev = addr[0] == 0 && addr[1] == 0xA0;
@@ -194,12 +185,24 @@
 
 	mp = (struct mace_data *) dev->priv;
 	mp->maccc = ENXMT | ENRCV;
+
 	mp->tx_dma = (volatile struct dbdma_regs *)
-		ioremap(mace->addrs[1].address, 0x1000);
-	mp->tx_dma_intr = mace->intrs[1].line;
+		ioremap(macio_resource_start(mdev, 1), 0x1000);
+	if (mp->tx_dma == NULL) {
+		printk(KERN_ERR "MACE: can't map TX DMA resources !\n");
+		rc = -ENOMEM;
+		goto err_unmap_io;
+	}
+	mp->tx_dma_intr = macio_irq(mdev, 1);
+
 	mp->rx_dma = (volatile struct dbdma_regs *)
-		ioremap(mace->addrs[2].address, 0x1000);
-	mp->rx_dma_intr = mace->intrs[2].line;
+		ioremap(macio_resource_start(mdev, 2), 0x1000);
+	if (mp->rx_dma == NULL) {
+		printk(KERN_ERR "MACE: can't map RX DMA resources !\n");
+		rc = -ENOMEM;
+		goto err_unmap_tx_dma;
+	}
+	mp->rx_dma_intr = macio_irq(mdev, 2);;
 
 	mp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(mp + 1);
 	mp->rx_cmds = mp->tx_cmds + NCMDS_TX * N_TX_RING + 1;
@@ -233,43 +236,81 @@
 	dev->set_multicast_list = mace_set_multicast;
 	dev->set_mac_address = mace_set_address;
 
+	/*
+	 * Most of what is below could be moved to mace_open()
+	 */
 	mace_reset(dev);
 
-	if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) {
+	rc = request_irq(dev->irq, mace_interrupt, 0, "MACE", dev);
+	if (rc) {
 		printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
-		goto out4;
+		goto err_unmap_rx_dma;
 	}
-	if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma",
-			dev)) {
+	rc = request_irq(mp->tx_dma_intr, mace_txdma_intr, 0, "MACE-txdma", dev);
+	if (rc) {
 		printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line);
-		goto out5;
+		goto err_free_irq;
 	}
-	if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma",
-			dev)) {
+	rc = request_irq(mp->rx_dma_intr, mace_rxdma_intr, 0, "MACE-rxdma", dev);
+	if (rc) {
 		printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line);
-		goto out6;
+		goto err_free_tx_irq;
 	}
-	if (register_netdev(dev) != 0)
-		goto out7;
 
-	mp->next_mace = mace_devs;
-	mace_devs = dev;
-	return;
-	
-out7:
-	free_irq(mp->rx_dma_intr, dev);
-out6:
-	free_irq(mp->tx_dma_intr, dev);
-out5:
+	rc = register_netdev(dev);
+	if (rc) {
+		printk(KERN_ERR "Cannot register net device, aborting.\n");
+		goto err_free_rx_irq;
+	}
+
+	return 0;
+ 
+ err_free_rx_irq:
+	free_irq(macio_irq(mdev, 2), dev);
+ err_free_tx_irq:
+	free_irq(macio_irq(mdev, 1), dev);
+ err_free_irq:
+	free_irq(macio_irq(mdev, 0), dev);
+ err_unmap_rx_dma:
+	iounmap((void*)mp->rx_dma);
+ err_unmap_tx_dma:
+	iounmap((void*)mp->tx_dma);
+ err_unmap_io:
+	iounmap((void*)mp->mace);
+ err_free:
+	free_netdev(dev);
+ err_release:
+	macio_release_resources(mdev);
+
+	return rc;
+}
+
+static int __devexit mace_remove(struct macio_dev *mdev)
+{
+	struct net_device *dev = macio_get_drvdata(mdev);
+	struct mace_data *mp;
+
+	BUG_ON(dev == NULL);
+
+	macio_set_drvdata(mdev, NULL);
+
+	mp = dev->priv;
+
+	unregister_netdev(dev);
+
 	free_irq(dev->irq, dev);
-out4:
-	release_OF_resource(mp->of_node, 2);
-out3:
-	release_OF_resource(mp->of_node, 1);
-out2:
-	release_OF_resource(mp->of_node, 0);
-out1:
+	free_irq(mp->tx_dma_intr, dev);
+	free_irq(mp->rx_dma_intr, dev);
+
+	iounmap((void*)mp->rx_dma);
+	iounmap((void*)mp->tx_dma);
+	iounmap((void*)mp->mace);
+
 	free_netdev(dev);
+
+	macio_release_resources(mdev);
+
+	return 0;
 }
 
 static void dbdma_reset(volatile struct dbdma_regs *dma)
@@ -967,37 +1008,45 @@
     return IRQ_HANDLED;
 }
 
-MODULE_AUTHOR("Paul Mackerras");
-MODULE_DESCRIPTION("PowerMac MACE driver.");
-MODULE_PARM(port_aaui, "i");
-MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
-MODULE_LICENSE("GPL");
+static struct of_match mace_match[] = 
+{
+	{
+	.name 		= "mace",
+	.type		= OF_ANY_MATCH,
+	.compatible	= OF_ANY_MATCH
+	},
+	{},
+};
 
-static void __exit mace_cleanup (void)
+static struct macio_driver mace_driver = 
 {
-    struct net_device *dev;
-    struct mace_data *mp;
+	.name 		= "mace",
+	.match_table	= mace_match,
+	.probe		= mace_probe,
+	.remove		= mace_remove,
+};
 
-    while ((dev = mace_devs) != 0) {
-		mp = (struct mace_data *) mace_devs->priv;
-		mace_devs = mp->next_mace;
 
-		unregister_netdev(dev);
-		free_irq(dev->irq, dev);
-		free_irq(mp->tx_dma_intr, dev);
-		free_irq(mp->rx_dma_intr, dev);
+static int __init mace_init(void)
+{
+	return macio_register_driver(&mace_driver);
+}
 
-		release_OF_resource(mp->of_node, 0);
-		release_OF_resource(mp->of_node, 1);
-		release_OF_resource(mp->of_node, 2);
+static void __exit mace_cleanup(void)
+{
+	macio_unregister_driver(&mace_driver);
 
-		free_netdev(dev);
-    }
-    if (dummy_buf != NULL) {
+	if (dummy_buf) {
 		kfree(dummy_buf);
 		dummy_buf = NULL;
-    }
+	}
 }
 
-module_init(mace_probe);
+MODULE_AUTHOR("Paul Mackerras");
+MODULE_DESCRIPTION("PowerMac MACE driver.");
+MODULE_PARM(port_aaui, "i");
+MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
+MODULE_LICENSE("GPL");
+
+module_init(mace_init);
 module_exit(mace_cleanup);
diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c
--- a/drivers/net/ne.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/ne.c	Wed Feb 11 22:30:57 2004
@@ -496,6 +496,9 @@
 	ei_status.priv = 0;
 	dev->open = &ne_open;
 	dev->stop = &ne_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 
diff -Nru a/drivers/net/ne2.c b/drivers/net/ne2.c
--- a/drivers/net/ne2.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/ne2.c	Wed Feb 11 22:30:57 2004
@@ -509,6 +509,9 @@
 	
 	dev->open = &ne_open;
 	dev->stop = &ne_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 out:
diff -Nru a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
--- a/drivers/net/ne2k-pci.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/ne2k-pci.c	Wed Feb 11 22:30:56 2004
@@ -359,6 +359,9 @@
 	dev->open = &ne2k_pci_open;
 	dev->stop = &ne2k_pci_close;
 	dev->ethtool_ops = &ne2k_pci_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 	i = register_netdev(dev);
diff -Nru a/drivers/net/ne2k_cbus.c b/drivers/net/ne2k_cbus.c
--- a/drivers/net/ne2k_cbus.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/ne2k_cbus.c	Wed Feb 11 22:30:57 2004
@@ -534,6 +534,9 @@
 	ei_status.priv = 0;
 	dev->open = &ne_open;
 	dev->stop = &ne_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 	return 0;
 
diff -Nru a/drivers/net/ne3210.c b/drivers/net/ne3210.c
--- a/drivers/net/ne3210.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/ne3210.c	Wed Feb 11 22:30:57 2004
@@ -205,6 +205,9 @@
 
 	dev->open = &ne3210_open;
 	dev->stop = &ne3210_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	dev->if_port = ifmap_val[port_index];
 
 	if ((retval = register_netdev (dev)))
diff -Nru a/drivers/net/netconsole.c b/drivers/net/netconsole.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/netconsole.c	Wed Feb 11 22:30:58 2004
@@ -0,0 +1,127 @@
+/*
+ *  linux/drivers/net/netconsole.c
+ *
+ *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
+ *
+ *  This file contains the implementation of an IRQ-safe, crash-safe
+ *  kernel console implementation that outputs kernel messages to the
+ *  network.
+ *
+ * Modification history:
+ *
+ * 2001-09-17    started by Ingo Molnar.
+ * 2003-08-11    2.6 port by Matt Mackall
+ *               simplified options
+ *               generic card hooks
+ *               works non-modular
+ * 2003-09-07    rewritten with netpoll api
+ */
+
+/****************************************************************
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2, or (at your option)
+ *      any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/tty_driver.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/sysrq.h>
+#include <linux/smp.h>
+#include <linux/netpoll.h>
+
+MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>");
+MODULE_DESCRIPTION("Console driver for network interfaces");
+MODULE_LICENSE("GPL");
+
+static char config[256];
+module_param_string(netconsole, config, 256, 0);
+MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]\n");
+
+static struct netpoll np = {
+	.name = "netconsole",
+	.dev_name = "eth0",
+	.local_port = 6665,
+	.remote_port = 6666,
+	.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+};
+static int configured = 0;
+
+#define MAX_PRINT_CHUNK 1000
+
+static void write_msg(struct console *con, const char *msg, unsigned int len)
+{
+	int frag, left;
+	unsigned long flags;
+
+	if (!np.dev)
+		return;
+
+	local_irq_save(flags);
+
+	for(left = len; left; ) {
+		frag = min(left, MAX_PRINT_CHUNK);
+		netpoll_send_udp(&np, msg, frag);
+		msg += frag;
+		left -= frag;
+	}
+
+	local_irq_restore(flags);
+}
+
+static struct console netconsole = {
+	.flags = CON_ENABLED | CON_PRINTBUFFER,
+	.write = write_msg
+};
+
+static int option_setup(char *opt)
+{
+	configured = !netpoll_parse_options(&np, opt);
+	return 0;
+}
+
+__setup("netconsole=", option_setup);
+
+static int init_netconsole(void)
+{
+	if(strlen(config))
+		option_setup(config);
+
+	if(!configured) {
+		printk("netconsole: not configured, aborting\n");
+		return -EINVAL;
+	}
+
+	if(netpoll_setup(&np))
+		return -EINVAL;
+
+	register_console(&netconsole);
+	printk(KERN_INFO "netconsole: network logging started\n");
+	return 0;
+}
+
+static void cleanup_netconsole(void)
+{
+	unregister_console(&netconsole);
+	netpoll_cleanup(&np);
+}
+
+module_init(init_netconsole);
+module_exit(cleanup_netconsole);
diff -Nru a/drivers/net/oaknet.c b/drivers/net/oaknet.c
--- a/drivers/net/oaknet.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/oaknet.c	Wed Feb 11 22:30:57 2004
@@ -192,6 +192,9 @@
 
 	dev->open = oaknet_open;
 	dev->stop = oaknet_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	NS8390_init(dev, FALSE);
 	ret = register_netdev(dev);
diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
--- a/drivers/net/pcnet32.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/pcnet32.c	Wed Feb 11 22:30:57 2004
@@ -456,6 +456,14 @@
     .reset	= pcnet32_dwio_reset
 };
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void pcnet32_poll_controller(struct net_device *dev)
+{ 
+	disable_irq(dev->irq);
+	pcnet32_interrupt(0, dev, NULL);
+	enable_irq(dev->irq);
+} 
+#endif
 
 
 /* only probes for non-PCI devices, the rest are handled by 
@@ -805,6 +813,10 @@
     dev->do_ioctl = &pcnet32_ioctl;
     dev->tx_timeout = pcnet32_tx_timeout;
     dev->watchdog_timeo = (5*HZ);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = pcnet32_poll_controller;
+#endif    
 
     /* Fill in the generic fields of the device structure. */
     if (register_netdev(dev))
diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c
--- a/drivers/net/pppoe.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/pppoe.c	Wed Feb 11 22:30:57 2004
@@ -67,7 +67,6 @@
 #include <linux/ppp_channel.h>
 #include <linux/ppp_defs.h>
 #include <linux/if_ppp.h>
-#include <linux/if_pppvar.h>
 #include <linux/notifier.h>
 #include <linux/file.h>
 #include <linux/proc_fs.h>
diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c
--- a/drivers/net/r8169.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/r8169.c	Wed Feb 11 22:30:57 2004
@@ -56,9 +56,11 @@
 	        printk( "Assertion failed! %s,%s,%s,line=%d\n",	\
         	#expr,__FILE__,__FUNCTION__,__LINE__);		\
         }
+#define dprintk(fmt, args...)	do { printk(PFX fmt, ## args) } while (0)
 #else
 #define assert(expr) do {} while (0)
-#endif
+#define dprintk(fmt, args...)	do {} while (0)
+#endif /* RTL8169_DEBUG */
 
 /* media options */
 #define MAX_UNITS 8
@@ -89,9 +91,12 @@
 #define NUM_TX_DESC	64	/* Number of Tx descriptor registers */
 #define NUM_RX_DESC	64	/* Number of Rx descriptor registers */
 #define RX_BUF_SIZE	1536	/* Rx Buffer size */
+#define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
+#define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
 
 #define RTL_MIN_IO_SIZE 0x80
-#define TX_TIMEOUT  (6*HZ)
+#define RTL8169_TX_TIMEOUT	(6*HZ)
+#define RTL8169_PHY_TIMEOUT	(HZ) 
 
 /* write/read MMIO register */
 #define RTL_W8(reg, val8)	writeb ((val8), ioaddr + (reg))
@@ -101,11 +106,35 @@
 #define RTL_R16(reg)		readw (ioaddr + (reg))
 #define RTL_R32(reg)		((unsigned long) readl (ioaddr + (reg)))
 
-static struct {
+enum mac_version {
+	RTL_GIGA_MAC_VER_B = 0x00,
+	/* RTL_GIGA_MAC_VER_C = 0x03, */
+	RTL_GIGA_MAC_VER_D = 0x01,
+	RTL_GIGA_MAC_VER_E = 0x02
+};
+
+enum phy_version {
+	RTL_GIGA_PHY_VER_C = 0x03, /* PHY Reg 0x03 bit0-3 == 0x0000 */
+	RTL_GIGA_PHY_VER_D = 0x04, /* PHY Reg 0x03 bit0-3 == 0x0000 */
+	RTL_GIGA_PHY_VER_E = 0x05, /* PHY Reg 0x03 bit0-3 == 0x0000 */
+	RTL_GIGA_PHY_VER_F = 0x06, /* PHY Reg 0x03 bit0-3 == 0x0001 */
+	RTL_GIGA_PHY_VER_G = 0x07, /* PHY Reg 0x03 bit0-3 == 0x0002 */
+};
+
+
+#define _R(NAME,MAC,MASK) \
+	{ .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
+
+const static struct {
 	const char *name;
-} board_info[] __devinitdata = {
-	{
-"RealTek RTL8169 Gigabit Ethernet"},};
+	u8 mac_version;
+	u32 RxConfigMask;	/* Clears the bits supported by this chip */
+} rtl_chip_info[] = {
+	_R("RTL8169",		RTL_GIGA_MAC_VER_B, 0xff7e1880),
+	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_D, 0xff7e1880),
+	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_E, 0xff7e1880)
+};
+#undef _R
 
 static struct pci_device_id rtl8169_pci_tbl[] = {
 	{0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -114,6 +143,8 @@
 
 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
+static int rx_copybreak = 200;
+
 enum RTL8169_registers {
 	MAC0 = 0,		/* Ethernet hardware address. */
 	MAR0 = 8,		/* Multicast filter. */
@@ -242,14 +273,6 @@
 	TBILinkOK = 0x02000000,
 };
 
-const static struct {
-	const char *name;
-	u8 version;		/* depend on RTL8169 docs */
-	u32 RxConfigMask;	/* should clear the bits supported by this chip */
-} rtl_chip_info[] = {
-	{
-"RTL-8169", 0x00, 0xff7e1880,},};
-
 enum _DescStatusBit {
 	OWNbit = 0x80000000,
 	EORbit = 0x40000000,
@@ -257,6 +280,8 @@
 	LSbit = 0x10000000,
 };
 
+#define RsvdMask	0x3fffc000
+
 struct TxDesc {
 	u32 status;
 	u32 vlan_tag;
@@ -277,28 +302,33 @@
 	struct net_device_stats stats;	/* statistics of net device */
 	spinlock_t lock;	/* spin lock flag */
 	int chipset;
-	unsigned long cur_rx;	/* Index into the Rx descriptor buffer of next Rx pkt. */
-	unsigned long cur_tx;	/* Index into the Tx descriptor buffer of next Rx pkt. */
-	unsigned long dirty_tx;
-	unsigned char *TxDescArrays;	/* Index of Tx Descriptor buffer */
-	unsigned char *RxDescArrays;	/* Index of Rx Descriptor buffer */
+	int mac_version;
+	int phy_version;
+	u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
+	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
+	u32 dirty_rx;
+	u32 dirty_tx;
 	struct TxDesc *TxDescArray;	/* Index of 256-alignment Tx Descriptor buffer */
 	struct RxDesc *RxDescArray;	/* Index of 256-alignment Rx Descriptor buffer */
-	unsigned char *RxBufferRings;	/* Index of Rx Buffer  */
-	unsigned char *RxBufferRing[NUM_RX_DESC];	/* Index of Rx Buffer array */
+	dma_addr_t TxPhyAddr;
+	dma_addr_t RxPhyAddr;
+	struct sk_buff *Rx_skbuff[NUM_RX_DESC];	/* Rx data buffers */
 	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Index of Transmit data buffer */
+	struct timer_list timer;
+	unsigned long phy_link_down_cnt;
 };
 
 MODULE_AUTHOR("Realtek");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
 MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_copybreak, "i");
 MODULE_LICENSE("GPL");
 
 static int rtl8169_open(struct net_device *dev);
 static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance,
 			      struct pt_regs *regs);
-static void rtl8169_init_ring(struct net_device *dev);
+static int rtl8169_init_ring(struct net_device *dev);
 static void rtl8169_hw_start(struct net_device *dev);
 static int rtl8169_close(struct net_device *dev);
 static void rtl8169_set_rx_mode(struct net_device *dev);
@@ -306,11 +336,15 @@
 static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
 
 static const u16 rtl8169_intr_mask =
-    SYSErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK |
-    RxErr | RxOK;
+    RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
 static const unsigned int rtl8169_rx_config =
     (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
+#define PHY_Cap_10_Half_Or_Less PHY_Cap_10_Half
+#define PHY_Cap_10_Full_Or_Less PHY_Cap_10_Full | PHY_Cap_10_Half_Or_Less
+#define PHY_Cap_100_Half_Or_Less PHY_Cap_100_Half | PHY_Cap_10_Full_Or_Less
+#define PHY_Cap_100_Full_Or_Less PHY_Cap_100_Full | PHY_Cap_100_Half_Or_Less
+
 void
 mdio_write(void *ioaddr, int RegAddr, int value)
 {
@@ -342,13 +376,258 @@
 		if (RTL_R32(PHYAR) & 0x80000000) {
 			value = (int) (RTL_R32(PHYAR) & 0xFFFF);
 			break;
-		} else {
-			udelay(100);
 		}
+		udelay(100);
 	}
 	return value;
 }
 
+static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum,
+				       int bitval)
+{
+	int val;
+
+	val = mdio_read(ioaddr, reg);
+	val = (bitval == 1) ?
+		val | (bitval << bitnum) :  val & ~(0x0001 << bitnum);
+	mdio_write(ioaddr, reg, val & 0xffff); 
+}
+
+static void rtl8169_get_mac_version(struct rtl8169_private *tp, void *ioaddr)
+{
+	const struct {
+		u32 mask;
+		int mac_version;
+	} mac_info[] = {
+		{ 0x1 << 26,	RTL_GIGA_MAC_VER_E },
+		{ 0x1 << 23,	RTL_GIGA_MAC_VER_D }, 
+		{ 0x00000000,	RTL_GIGA_MAC_VER_B } /* Catch-all */
+	}, *p = mac_info;
+	u32 reg;
+
+	reg = RTL_R32(TxConfig) & 0x7c800000;
+	while ((reg & p->mask) != p->mask)
+		p++;
+	tp->mac_version = p->mac_version;
+}
+
+static void rtl8169_print_mac_version(struct rtl8169_private *tp)
+{
+	struct {
+		int version;
+		char *msg;
+	} mac_print[] = {
+		{ RTL_GIGA_MAC_VER_E, "RTL_GIGA_MAC_VER_E" },
+		{ RTL_GIGA_MAC_VER_D, "RTL_GIGA_MAC_VER_D" },
+		{ RTL_GIGA_MAC_VER_B, "RTL_GIGA_MAC_VER_B" },
+		{ 0, NULL }
+	}, *p;
+
+	for (p = mac_print; p->msg; p++) {
+		if (tp->mac_version == p->version) {
+			dprintk("mac_version == %s (%04d)\n", p->msg,
+				  p->version);
+			return;
+		}
+	}
+	dprintk("mac_version == Unknown\n");
+}
+
+static void rtl8169_get_phy_version(struct rtl8169_private *tp, void *ioaddr)
+{
+	const struct {
+		u16 mask;
+		u16 set;
+		int phy_version;
+	} phy_info[] = {
+		{ 0x000f, 0x0002, RTL_GIGA_PHY_VER_G },
+		{ 0x000f, 0x0001, RTL_GIGA_PHY_VER_F },
+		{ 0x000f, 0x0000, RTL_GIGA_PHY_VER_E },
+		{ 0x0000, 0x0000, RTL_GIGA_PHY_VER_D } /* Catch-all */
+	}, *p = phy_info;
+	u16 reg;
+
+	reg = mdio_read(ioaddr, 3) & 0xffff;
+	while ((reg & p->mask) != p->set)
+		p++;
+	tp->phy_version = p->phy_version;
+}
+
+static void rtl8169_print_phy_version(struct rtl8169_private *tp)
+{
+	struct {
+		int version;
+		char *msg;
+		u32 reg;
+	} phy_print[] = {
+		{ RTL_GIGA_PHY_VER_G, "RTL_GIGA_PHY_VER_G", 0x0002 },
+		{ RTL_GIGA_PHY_VER_F, "RTL_GIGA_PHY_VER_F", 0x0001 },
+		{ RTL_GIGA_PHY_VER_E, "RTL_GIGA_PHY_VER_E", 0x0000 },
+		{ RTL_GIGA_PHY_VER_D, "RTL_GIGA_PHY_VER_D", 0x0000 },
+		{ 0, NULL, 0x0000 }
+	}, *p;
+
+	for (p = phy_print; p->msg; p++) {
+		if (tp->phy_version == p->version) {
+			dprintk("phy_version == %s (%04x)\n", p->msg, p->reg);
+			return;
+		}
+	}
+	dprintk("phy_version == Unknown\n");
+}
+
+static void rtl8169_hw_phy_config(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	struct {
+		u16 regs[5]; /* Beware of bit-sign propagation */
+	} phy_magic[5] = { {
+		{ 0x0000,	//w 4 15 12 0
+		  0x00a1,	//w 3 15 0 00a1
+		  0x0008,	//w 2 15 0 0008
+		  0x1020,	//w 1 15 0 1020
+		  0x1000 } },{	//w 0 15 0 1000
+		{ 0x7000,	//w 4 15 12 7
+		  0xff41,	//w 3 15 0 ff41
+		  0xde60,	//w 2 15 0 de60
+		  0x0140,	//w 1 15 0 0140
+		  0x0077 } },{	//w 0 15 0 0077
+		{ 0xa000,	//w 4 15 12 a
+		  0xdf01,	//w 3 15 0 df01
+		  0xdf20,	//w 2 15 0 df20
+		  0xff95,	//w 1 15 0 ff95
+		  0xfa00 } },{	//w 0 15 0 fa00
+		{ 0xb000,	//w 4 15 12 b
+		  0xff41,	//w 3 15 0 ff41
+		  0xde20,	//w 2 15 0 de20
+		  0x0140,	//w 1 15 0 0140
+		  0x00bb } },{	//w 0 15 0 00bb
+		{ 0xf000,	//w 4 15 12 f
+		  0xdf01,	//w 3 15 0 df01
+		  0xdf20,	//w 2 15 0 df20
+		  0xff95,	//w 1 15 0 ff95
+		  0xbf00 }	//w 0 15 0 bf00
+		}
+	}, *p = phy_magic;
+	int i;
+
+	rtl8169_print_mac_version(tp);
+	rtl8169_print_phy_version(tp);
+
+	if (tp->mac_version <= RTL_GIGA_MAC_VER_B)
+		return;
+	if (tp->phy_version >= RTL_GIGA_PHY_VER_F) 
+		return;
+
+	dprintk("MAC version != 0 && PHY version == 0 or 1\n");
+	dprintk("Do final_reg2.cfg\n");
+
+	/* Shazam ! */
+
+	// phy config for RTL8169s mac_version C chip
+	mdio_write(ioaddr, 31, 0x0001);			//w 31 2 0 1
+	mdio_write(ioaddr, 21, 0x1000);			//w 21 15 0 1000
+	mdio_write(ioaddr, 24, 0x65c7);			//w 24 15 0 65c7
+	rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0);	//w 4 11 11 0
+
+	for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) {
+		int val, pos = 4;
+
+		val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff);
+		mdio_write(ioaddr, pos, val);
+		while (--pos >= 0)
+			mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff);
+		rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1
+		rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
+	}
+	mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0
+}
+
+static void rtl8169_hw_phy_reset(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	int i, val;
+
+	printk(KERN_WARNING PFX "%s: Reset RTL8169s PHY\n", dev->name);
+
+	val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff;
+	mdio_write(ioaddr, 0, val);
+
+	for (i = 50; i >= 0; i--) {
+		if (!(mdio_read(ioaddr, 0) & 0x8000))
+			break;
+		udelay(100); /* Gross */
+	}
+
+	if (i < 0) {
+		printk(KERN_WARNING PFX "%s: no PHY Reset ack. Giving up.\n",
+		       dev->name);
+	}
+}
+
+static void rtl8169_phy_timer(unsigned long __opaque)
+{
+	struct net_device *dev = (struct net_device *)__opaque;
+	struct rtl8169_private *tp = dev->priv;
+	struct timer_list *timer = &tp->timer;
+	void *ioaddr = tp->mmio_addr;
+
+	assert(tp->mac_version > RTL_GIGA_MAC_VER_B);
+	assert(tp->phy_version < RTL_GIGA_PHY_VER_G);
+
+	if (RTL_R8(PHYstatus) & LinkStatus)
+		tp->phy_link_down_cnt = 0;
+	else {
+		tp->phy_link_down_cnt++;
+		if (tp->phy_link_down_cnt >= 12) {
+			int reg;
+
+			// If link on 1000, perform phy reset.
+			reg = mdio_read(ioaddr, PHY_1000_CTRL_REG);
+			if (reg & PHY_Cap_1000_Full) 
+				rtl8169_hw_phy_reset(dev);
+
+			tp->phy_link_down_cnt = 0;
+		}
+	}
+
+	mod_timer(timer, RTL8169_PHY_TIMEOUT);
+}
+
+static inline void rtl8169_delete_timer(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+	struct timer_list *timer = &tp->timer;
+
+	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
+	    (tp->phy_version >= RTL_GIGA_PHY_VER_G))
+		return;
+
+	del_timer_sync(timer);
+
+	tp->phy_link_down_cnt = 0;
+}
+
+static inline void rtl8169_request_timer(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+	struct timer_list *timer = &tp->timer;
+
+	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
+	    (tp->phy_version >= RTL_GIGA_PHY_VER_G))
+		return;
+
+	tp->phy_link_down_cnt = 0;
+
+	init_timer(timer);
+	timer->expires = jiffies + RTL8169_PHY_TIMEOUT;
+	timer->data = (unsigned long)(dev);
+	timer->function = rtl8169_phy_timer;
+	add_timer(timer);
+}
+
 static int __devinit
 rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
 		   void **ioaddr_out)
@@ -356,9 +635,9 @@
 	void *ioaddr = NULL;
 	struct net_device *dev;
 	struct rtl8169_private *tp;
-	int rc, i;
 	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
-	u32 tmp;
+	int rc, i, acpi_idle_state = 0, pm_cap;
+
 
 	assert(pdev != NULL);
 	assert(ioaddr_out != NULL);
@@ -379,8 +658,22 @@
 
 	// enable device (incl. PCI PM wakeup and hotplug setup)
 	rc = pci_enable_device(pdev);
-	if (rc)
+	if (rc) {
+		printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name);
 		goto err_out;
+	}
+
+	/* save power state before pci_enable_device overwrites it */
+	pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+	if (pm_cap) {
+		u16 pwr_command;
+
+		pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
+		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
+	} else {
+		printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n");
+		goto err_out_free_res;
+	}
 
 	mmio_start = pci_resource_start(pdev, 1);
 	mmio_end = pci_resource_end(pdev, 1);
@@ -402,8 +695,10 @@
 	}
 
 	rc = pci_request_regions(pdev, dev->name);
-	if (rc)
+	if (rc) {
+		printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name);
 		goto err_out_disable;
+	}
 
 	// enable PCI bus-mastering
 	pci_set_master(pdev);
@@ -420,30 +715,32 @@
 	RTL_W8(ChipCmd, CmdReset);
 
 	// Check that the chip has finished the reset.
-	for (i = 1000; i > 0; i--)
+	for (i = 1000; i > 0; i--) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
-		else
-			udelay(10);
+		udelay(10);
+	}
 
-	// identify chip attached to board
-	tmp = RTL_R32(TxConfig);
-	tmp = ((tmp & 0x7c000000) + ((tmp & 0x00800000) << 2)) >> 24;
-
-	for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--)
-		if (tmp == rtl_chip_info[i].version) {
-			tp->chipset = i;
-			goto match;
-		}
-	//if unknown chip, assume array element #0, original RTL-8169 in this case
-	printk(KERN_DEBUG PFX
-	       "PCI device %s: unknown chip version, assuming RTL-8169\n",
-	       pci_name(pdev));
-	printk(KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n",
-	       pci_name(pdev), (unsigned long) RTL_R32(TxConfig));
-	tp->chipset = 0;
+	// Identify chip attached to board
+	rtl8169_get_mac_version(tp, ioaddr);
+	rtl8169_get_phy_version(tp, ioaddr);
+
+	rtl8169_print_mac_version(tp);
+	rtl8169_print_phy_version(tp);
+
+	for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) {
+		if (tp->mac_version == rtl_chip_info[i].mac_version)
+			break;
+	}
+	if (i < 0) {
+		/* Unknown chip: assume array element #0, original RTL-8169 */
+		printk(KERN_DEBUG PFX
+		       "PCI device %s: unknown chip version, assuming %s\n",
+		       pci_name(pdev), rtl_chip_info[0].name);
+		i++;
+	}
+	tp->chipset = i;
 
-match:
 	*ioaddr_out = ioaddr;
 	*dev_out = dev;
 	return 0;
@@ -499,7 +796,7 @@
 	dev->stop = rtl8169_close;
 	dev->tx_timeout = rtl8169_tx_timeout;
 	dev->set_multicast_list = rtl8169_set_rx_mode;
-	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 	dev->irq = pdev->irq;
 	dev->base_addr = (unsigned long) ioaddr;
 //      dev->do_ioctl           = mii_ioctl;
@@ -528,12 +825,29 @@
 	       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
 	       "IRQ %d\n",
 	       dev->name,
-	       board_info[ent->driver_data].name,
+	       rtl_chip_info[ent->driver_data].name,
 	       dev->base_addr,
 	       dev->dev_addr[0], dev->dev_addr[1],
 	       dev->dev_addr[2], dev->dev_addr[3],
 	       dev->dev_addr[4], dev->dev_addr[5], dev->irq);
 
+	rtl8169_hw_phy_config(dev);
+
+	dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+	RTL_W8(0x82, 0x01);
+
+	if (tp->mac_version < RTL_GIGA_MAC_VER_E) {
+		dprintk("Set PCI Latency=0x40\n");
+		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+	}
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
+		dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+		RTL_W8(0x82, 0x01);
+		dprintk("Set PHY Reg 0x0bh = 0x00h\n");
+		mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
+	}
+
 	// if TBI is not endbled
 	if (!(RTL_R8(PHYstatus) & TBI_Enable)) {
 		int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);
@@ -546,23 +860,23 @@
 			Cap10_100 = 0, Cap1000 = 0;
 			switch (option) {
 			case _10_Half:
-				Cap10_100 = PHY_Cap_10_Half;
+				Cap10_100 = PHY_Cap_10_Half_Or_Less;
 				Cap1000 = PHY_Cap_Null;
 				break;
 			case _10_Full:
-				Cap10_100 = PHY_Cap_10_Full;
+				Cap10_100 = PHY_Cap_10_Full_Or_Less;
 				Cap1000 = PHY_Cap_Null;
 				break;
 			case _100_Half:
-				Cap10_100 = PHY_Cap_100_Half;
+				Cap10_100 = PHY_Cap_100_Half_Or_Less;
 				Cap1000 = PHY_Cap_Null;
 				break;
 			case _100_Full:
-				Cap10_100 = PHY_Cap_100_Full;
+				Cap10_100 = PHY_Cap_100_Full_Or_Less;
 				Cap1000 = PHY_Cap_Null;
 				break;
 			case _1000_Full:
-				Cap10_100 = PHY_Cap_Null;
+				Cap10_100 = PHY_Cap_100_Full_Or_Less;
 				Cap1000 = PHY_Cap_1000_Full;
 				break;
 			default:
@@ -576,9 +890,7 @@
 
 			// enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
 			mdio_write(ioaddr, PHY_AUTO_NEGO_REG,
-				   PHY_Cap_10_Half | PHY_Cap_10_Full |
-				   PHY_Cap_100_Half | PHY_Cap_100_Full | (val &
-									  0x1F));
+				   PHY_Cap_100_Full_Or_Less | (val & 0x1f));
 
 			// enable 1000 Full Mode
 			mdio_write(ioaddr, PHY_1000_CTRL_REG,
@@ -647,56 +959,96 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
+#ifdef CONFIG_PM
+
+static int rtl8169_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rtl8169_private *tp = dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	unsigned long flags;
+
+	if (!netif_running(dev))
+		return 0;
+	
+	netif_device_detach(dev);
+	netif_stop_queue(dev);
+	spin_lock_irqsave(&tp->lock, flags);
+
+	/* Disable interrupts, stop Rx and Tx */
+	RTL_W16(IntrMask, 0);
+	RTL_W8(ChipCmd, 0);
+		
+	/* Update the error counts. */
+	tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+	RTL_W32(RxMissed, 0);
+	spin_unlock_irqrestore(&tp->lock, flags);
+	
+	return 0;
+}
+
+static int rtl8169_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	if (!netif_running(dev))
+	    return 0;
+
+	netif_device_attach(dev);
+	rtl8169_hw_start(dev);
+
+	return 0;
+}
+                                                                                
+#endif /* CONFIG_PM */
+
 static int
 rtl8169_open(struct net_device *dev)
 {
 	struct rtl8169_private *tp = dev->priv;
+	struct pci_dev *pdev = tp->pci_dev;
 	int retval;
-	u8 diff;
-	u32 TxPhyAddr, RxPhyAddr;
 
 	retval =
 	    request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev);
-	if (retval) {
-		return retval;
-	}
+	if (retval < 0)
+		goto out;
 
-	tp->TxDescArrays =
-	    kmalloc(NUM_TX_DESC * sizeof (struct TxDesc) + 256, GFP_KERNEL);
-	// Tx Desscriptor needs 256 bytes alignment;
-	TxPhyAddr = virt_to_bus(tp->TxDescArrays);
-	diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8));
-	TxPhyAddr += diff;
-	tp->TxDescArray = (struct TxDesc *) (tp->TxDescArrays + diff);
-
-	tp->RxDescArrays =
-	    kmalloc(NUM_RX_DESC * sizeof (struct RxDesc) + 256, GFP_KERNEL);
-	// Rx Desscriptor needs 256 bytes alignment;
-	RxPhyAddr = virt_to_bus(tp->RxDescArrays);
-	diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8));
-	RxPhyAddr += diff;
-	tp->RxDescArray = (struct RxDesc *) (tp->RxDescArrays + diff);
+	retval = -ENOMEM;
 
-	if (tp->TxDescArrays == NULL || tp->RxDescArrays == NULL) {
-		printk(KERN_INFO
-		       "Allocate RxDescArray or TxDescArray failed\n");
-		free_irq(dev->irq, dev);
-		if (tp->TxDescArrays)
-			kfree(tp->TxDescArrays);
-		if (tp->RxDescArrays)
-			kfree(tp->RxDescArrays);
-		return -ENOMEM;
-	}
-	tp->RxBufferRings = kmalloc(RX_BUF_SIZE * NUM_RX_DESC, GFP_KERNEL);
-	if (tp->RxBufferRings == NULL) {
-		printk(KERN_INFO "Allocate RxBufferRing failed\n");
-	}
+	/*
+	 * Rx and Tx desscriptors needs 256 bytes alignment.
+	 * pci_alloc_consistent provides more.
+	 */
+	tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
+					       &tp->TxPhyAddr);
+	if (!tp->TxDescArray)
+		goto err_free_irq;
+
+	tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
+					       &tp->RxPhyAddr);
+	if (!tp->RxDescArray)
+		goto err_free_tx;
+
+	retval = rtl8169_init_ring(dev);
+	if (retval < 0)
+		goto err_free_rx;
 
-	rtl8169_init_ring(dev);
 	rtl8169_hw_start(dev);
 
-	return 0;
-
+	rtl8169_request_timer(dev);
+out:
+	return retval;
+
+err_free_rx:
+	pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
+			    tp->RxPhyAddr);
+err_free_tx:
+	pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
+			    tp->TxPhyAddr);
+err_free_irq:
+	free_irq(dev->irq, dev);
+	goto out;
 }
 
 static void
@@ -733,11 +1085,17 @@
 	RTL_W32(TxConfig,
 		(TX_DMA_BURST << TxDMAShift) | (InterFrameGap <<
 						TxInterFrameGapShift));
+	RTL_W16(CPlusCmd, RTL_R16(CPlusCmd));
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
+		dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n");
+		RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | (1 << 14) | (1 << 3));
+	}
 
 	tp->cur_rx = 0;
 
-	RTL_W32(TxDescStartAddr, virt_to_bus(tp->TxDescArray));
-	RTL_W32(RxDescStartAddr, virt_to_bus(tp->RxDescArray));
+	RTL_W32(TxDescStartAddr, tp->TxPhyAddr);
+	RTL_W32(RxDescStartAddr, tp->RxPhyAddr);
 	RTL_W8(Cfg9346, Cfg9346_Lock);
 	udelay(10);
 
@@ -755,31 +1113,131 @@
 
 }
 
-static void
-rtl8169_init_ring(struct net_device *dev)
+static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
+{
+	desc->buf_addr = 0xdeadbeef;
+	desc->status &= ~cpu_to_le32(OWNbit | RsvdMask);
+}
+
+static void rtl8169_free_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+				struct RxDesc *desc)
+{
+	pci_unmap_single(pdev, le32_to_cpu(desc->buf_addr), RX_BUF_SIZE,
+			 PCI_DMA_FROMDEVICE);
+	dev_kfree_skb(*sk_buff);
+	*sk_buff = NULL;
+	rtl8169_make_unusable_by_asic(desc);
+}
+
+static inline void rtl8169_return_to_asic(struct RxDesc *desc)
+{
+	desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE);
+}
+
+static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping)
+{
+	desc->buf_addr = cpu_to_le32(mapping);
+	desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE);
+}
+
+static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev,
+				struct sk_buff **sk_buff, struct RxDesc *desc)
+{
+	struct sk_buff *skb;
+	dma_addr_t mapping;
+	int ret = 0;
+
+	skb = dev_alloc_skb(RX_BUF_SIZE);
+	if (!skb)
+		goto err_out;
+
+	skb->dev = dev;
+	skb_reserve(skb, 2);
+	*sk_buff = skb;
+
+	mapping = pci_map_single(pdev, skb->tail, RX_BUF_SIZE,
+				 PCI_DMA_FROMDEVICE);
+
+	rtl8169_give_to_asic(desc, mapping);
+
+out:
+	return ret;
+
+err_out:
+	ret = -ENOMEM;
+	rtl8169_make_unusable_by_asic(desc);
+	goto out;
+}
+
+static void rtl8169_rx_clear(struct rtl8169_private *tp)
 {
-	struct rtl8169_private *tp = dev->priv;
 	int i;
 
-	tp->cur_rx = 0;
-	tp->cur_tx = 0;
-	tp->dirty_tx = 0;
+	for (i = 0; i < NUM_RX_DESC; i++) {
+		if (tp->Rx_skbuff[i]) {
+			rtl8169_free_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
+					    tp->RxDescArray + i);
+		}
+	}
+}
+
+static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
+			   u32 start, u32 end)
+{
+	u32 cur;
+	
+	for (cur = start; end - cur > 0; cur++) {
+		int ret, i = cur % NUM_RX_DESC;
+
+		if (tp->Rx_skbuff[i])
+			continue;
+			
+		ret = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->Rx_skbuff + i,
+					   tp->RxDescArray + i);
+		if (ret < 0)
+			break;
+	}
+	return cur - start;
+}
+
+static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
+{
+	desc->status |= cpu_to_le32(EORbit);
+}
+
+static int rtl8169_init_ring(struct net_device *dev)
+{
+	struct rtl8169_private *tp = dev->priv;
+
+	tp->cur_rx = tp->dirty_rx = 0;
+	tp->cur_tx = tp->dirty_tx = 0;
 	memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof (struct TxDesc));
 	memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc));
 
-	for (i = 0; i < NUM_TX_DESC; i++) {
-		tp->Tx_skbuff[i] = NULL;
-	}
-	for (i = 0; i < NUM_RX_DESC; i++) {
-		if (i == (NUM_RX_DESC - 1))
-			tp->RxDescArray[i].status =
-			    (OWNbit | EORbit) + RX_BUF_SIZE;
-		else
-			tp->RxDescArray[i].status = OWNbit + RX_BUF_SIZE;
+	memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
+	memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
 
-		tp->RxBufferRing[i] = &(tp->RxBufferRings[i * RX_BUF_SIZE]);
-		tp->RxDescArray[i].buf_addr = virt_to_bus(tp->RxBufferRing[i]);
-	}
+	if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
+		goto err_out;
+
+	rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
+
+	return 0;
+
+err_out:
+	rtl8169_rx_clear(tp);
+	return -ENOMEM;
+}
+
+static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+				 struct TxDesc *desc)
+{
+	u32 len = sk_buff[0]->len;
+
+	pci_unmap_single(pdev, le32_to_cpu(desc->buf_addr),
+			 len < ETH_ZLEN ? ETH_ZLEN : len, PCI_DMA_TODEVICE);
+	desc->buf_addr = 0x00;
+	*sk_buff = NULL;
 }
 
 static void
@@ -789,9 +1247,12 @@
 
 	tp->cur_tx = 0;
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		if (tp->Tx_skbuff[i] != NULL) {
-			dev_kfree_skb(tp->Tx_skbuff[i]);
-			tp->Tx_skbuff[i] = NULL;
+		struct sk_buff *skb = tp->Tx_skbuff[i];
+
+		if (skb) {
+			rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + i,
+					     tp->TxDescArray + i);
+			dev_kfree_skb(skb);
 			tp->stats.tx_dropped++;
 		}
 	}
@@ -829,49 +1290,58 @@
 	struct rtl8169_private *tp = dev->priv;
 	void *ioaddr = tp->mmio_addr;
 	int entry = tp->cur_tx % NUM_TX_DESC;
+	u32 len = skb->len;
 
-	if (skb->len < ETH_ZLEN) {
+	if (unlikely(skb->len < ETH_ZLEN)) {
 		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
+		if (!skb)
+			goto err_update_stats;
+		len = ETH_ZLEN;
 	}
 	
 	spin_lock_irq(&tp->lock);
 
-	if ((tp->TxDescArray[entry].status & OWNbit) == 0) {
+	if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) {
+		dma_addr_t mapping;
+
+		mapping = pci_map_single(tp->pci_dev, skb->data, len,
+					 PCI_DMA_TODEVICE);
+
 		tp->Tx_skbuff[entry] = skb;
-		tp->TxDescArray[entry].buf_addr = virt_to_bus(skb->data);
-		if (entry != (NUM_TX_DESC - 1))
-			tp->TxDescArray[entry].status =
-			    (OWNbit | FSbit | LSbit) | ((skb->len > ETH_ZLEN) ?
-							skb->len : ETH_ZLEN);
-		else
-			tp->TxDescArray[entry].status =
-			    (OWNbit | EORbit | FSbit | LSbit) |
-			    ((skb->len > ETH_ZLEN) ? skb->len : ETH_ZLEN);
+		tp->TxDescArray[entry].buf_addr = cpu_to_le32(mapping);
 
+		tp->TxDescArray[entry].status = cpu_to_le32(OWNbit | FSbit |
+			LSbit | len | (EORbit * !((entry + 1) % NUM_TX_DESC)));
+			
 		RTL_W8(TxPoll, 0x40);	//set polling bit
 
 		dev->trans_start = jiffies;
 
 		tp->cur_tx++;
-	}
+	} else
+		goto err_drop;
 
-	spin_unlock_irq(&tp->lock);
 
 	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) {
 		netif_stop_queue(dev);
 	}
+out:
+	spin_unlock_irq(&tp->lock);
 
 	return 0;
+
+err_drop:
+	dev_kfree_skb(skb);
+err_update_stats:
+	tp->stats.tx_dropped++;
+	goto out;
 }
 
 static void
 rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	unsigned long dirty_tx, tx_left = 0;
-	int entry = tp->cur_tx % NUM_TX_DESC;
+	unsigned long dirty_tx, tx_left;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -881,14 +1351,21 @@
 	tx_left = tp->cur_tx - dirty_tx;
 
 	while (tx_left > 0) {
-		if ((tp->TxDescArray[entry].status & OWNbit) == 0) {
-			dev_kfree_skb_irq(tp->
-					  Tx_skbuff[dirty_tx % NUM_TX_DESC]);
-			tp->Tx_skbuff[dirty_tx % NUM_TX_DESC] = NULL;
+		int entry = dirty_tx % NUM_TX_DESC;
+
+		if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) {
+			struct sk_buff *skb = tp->Tx_skbuff[entry];
+
+			/* FIXME: is it really accurate for TxErr ? */
+			tp->stats.tx_bytes += skb->len >= ETH_ZLEN ?
+					      skb->len : ETH_ZLEN;
 			tp->stats.tx_packets++;
+			rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + entry,
+					     tp->TxDescArray + entry);
+			dev_kfree_skb_irq(skb);
+			tp->Tx_skbuff[entry] = NULL;
 			dirty_tx++;
 			tx_left--;
-			entry++;
 		}
 	}
 
@@ -899,70 +1376,95 @@
 	}
 }
 
+static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
+				      struct RxDesc *desc,
+				      struct net_device *dev)
+{
+	int ret = -1;
+
+	if (pkt_size < rx_copybreak) {
+		struct sk_buff *skb;
+
+		skb = dev_alloc_skb(pkt_size + 2);
+		if (skb) {
+			skb->dev = dev;
+			skb_reserve(skb, 2);
+			eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0);
+			*sk_buff = skb;
+			rtl8169_return_to_asic(desc);
+			ret = 0;
+		}
+	}
+	return ret;
+}
+
 static void
 rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	int cur_rx;
-	struct sk_buff *skb;
-	int pkt_size = 0;
+	int cur_rx, delta;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
 	assert(ioaddr != NULL);
 
-	cur_rx = tp->cur_rx;
+	cur_rx = tp->cur_rx % NUM_RX_DESC;
 
-	while ((tp->RxDescArray[cur_rx].status & OWNbit) == 0) {
+	while (!(le32_to_cpu(tp->RxDescArray[cur_rx].status) & OWNbit)) {
+		u32 status = le32_to_cpu(tp->RxDescArray[cur_rx].status);
 
-		if (tp->RxDescArray[cur_rx].status & RxRES) {
+		if (status & RxRES) {
 			printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name);
 			tp->stats.rx_errors++;
-			if (tp->RxDescArray[cur_rx].status & (RxRWT | RxRUNT))
+			if (status & (RxRWT | RxRUNT))
 				tp->stats.rx_length_errors++;
-			if (tp->RxDescArray[cur_rx].status & RxCRC)
+			if (status & RxCRC)
 				tp->stats.rx_crc_errors++;
 		} else {
-			pkt_size =
-			    (int) (tp->RxDescArray[cur_rx].
-				   status & 0x00001FFF) - 4;
-			skb = dev_alloc_skb(pkt_size + 2);
-			if (skb != NULL) {
-				skb->dev = dev;
-				skb_reserve(skb, 2);	// 16 byte align the IP fields. //
-				eth_copy_and_sum(skb, tp->RxBufferRing[cur_rx],
-						 pkt_size, 0);
-				skb_put(skb, pkt_size);
-				skb->protocol = eth_type_trans(skb, dev);
-				netif_rx(skb);
-
-				if (cur_rx == (NUM_RX_DESC - 1))
-					tp->RxDescArray[cur_rx].status =
-					    (OWNbit | EORbit) + RX_BUF_SIZE;
-				else
-					tp->RxDescArray[cur_rx].status =
-					    OWNbit + RX_BUF_SIZE;
-
-				tp->RxDescArray[cur_rx].buf_addr =
-				    virt_to_bus(tp->RxBufferRing[cur_rx]);
-				dev->last_rx = jiffies;
-				tp->stats.rx_bytes += pkt_size;
-				tp->stats.rx_packets++;
-			} else {
-				printk(KERN_WARNING
-				       "%s: Memory squeeze, deferring packet.\n",
-				       dev->name);
-				/* We should check that some rx space is free.
-				   If not, free one and mark stats->rx_dropped++. */
-				tp->stats.rx_dropped++;
+			struct RxDesc *desc = tp->RxDescArray + cur_rx;
+			struct sk_buff *skb = tp->Rx_skbuff[cur_rx];
+			int pkt_size = (status & 0x00001FFF) - 4;
+
+			pci_dma_sync_single(tp->pci_dev,
+					    le32_to_cpu(desc->buf_addr),
+					    RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+
+			if (rtl8169_try_rx_copy(&skb, pkt_size, desc, dev)) {
+				pci_unmap_single(tp->pci_dev,
+						 le32_to_cpu(desc->buf_addr),
+						 RX_BUF_SIZE,
+						 PCI_DMA_FROMDEVICE);
+				tp->Rx_skbuff[cur_rx] = NULL;
 			}
-		}
-
-		cur_rx = (cur_rx + 1) % NUM_RX_DESC;
-
-	}
 
-	tp->cur_rx = cur_rx;
+			skb_put(skb, pkt_size);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+
+			dev->last_rx = jiffies;
+			tp->stats.rx_bytes += pkt_size;
+			tp->stats.rx_packets++;
+		}
+		
+		tp->cur_rx++; 
+		cur_rx = tp->cur_rx % NUM_RX_DESC;
+	}
+
+	delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
+	if (delta > 0)
+		tp->dirty_rx += delta;
+	else if (delta < 0)
+		printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
+
+	/*
+	 * FIXME: until there is periodic timer to try and refill the ring,
+	 * a temporary shortage may definitely kill the Rx process.
+	 * - disable the asic to try and avoid an overflow and kick it again
+	 *   after refill ?
+	 * - how do others driver handle this condition (Uh oh...).
+	 */
+	if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
+		printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
@@ -991,9 +1493,7 @@
 		RTL_W16(IntrStatus,
 			(status & RxFIFOOver) ? (status | RxOverflow) : status);
 
-		if ((status &
-		     (SYSErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
-		      | TxErr | TxOK | RxErr | RxOK)) == 0)
+		if (!(status & rtl8169_intr_mask))
 			break;
 
 		// Rx interrupt 
@@ -1023,11 +1523,13 @@
 rtl8169_close(struct net_device *dev)
 {
 	struct rtl8169_private *tp = dev->priv;
+	struct pci_dev *pdev = tp->pci_dev;
 	void *ioaddr = tp->mmio_addr;
-	int i;
 
 	netif_stop_queue(dev);
 
+	rtl8169_delete_timer(dev);
+
 	spin_lock_irq(&tp->lock);
 
 	/* Stop the chip's Tx and Rx DMA processes. */
@@ -1046,16 +1548,15 @@
 	free_irq(dev->irq, dev);
 
 	rtl8169_tx_clear(tp);
-	kfree(tp->TxDescArrays);
-	kfree(tp->RxDescArrays);
-	tp->TxDescArrays = NULL;
-	tp->RxDescArrays = NULL;
+
+	rtl8169_rx_clear(tp);
+
+	pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
+			    tp->RxPhyAddr);
+	pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
+			    tp->TxPhyAddr);
 	tp->TxDescArray = NULL;
 	tp->RxDescArray = NULL;
-	kfree(tp->RxBufferRings);
-	for (i = 0; i < NUM_RX_DESC; i++) {
-		tp->RxBufferRing[i] = NULL;
-	}
 
 	return 0;
 }
@@ -1109,11 +1610,26 @@
 	spin_unlock_irqrestore(&tp->lock, flags);
 }
 
+/**
+ *  rtl8169_get_stats - Get rtl8169 read/write statistics
+ *  @dev: The Ethernet Device to get statistics for
+ *
+ *  Get TX/RX statistics for rtl8169
+ */
 struct net_device_stats *
 rtl8169_get_stats(struct net_device *dev)
 {
 	struct rtl8169_private *tp = dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	unsigned long flags;
 
+	if (netif_running(dev)) {
+		spin_lock_irqsave(&tp->lock, flags);
+		tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+		RTL_W32(RxMissed, 0);
+		spin_unlock_irqrestore(&tp->lock, flags);
+	}
+		
 	return &tp->stats;
 }
 
@@ -1122,8 +1638,10 @@
 	.id_table	= rtl8169_pci_tbl,
 	.probe		= rtl8169_init_one,
 	.remove		= __devexit_p(rtl8169_remove_one),
-	.suspend	= NULL,
-	.resume		= NULL,
+#ifdef CONFIG_PM
+	.suspend	= rtl8169_suspend,
+	.resume		= rtl8169_resume,
+#endif
 };
 
 static int __init
diff -Nru a/drivers/net/saa9730.c b/drivers/net/saa9730.c
--- a/drivers/net/saa9730.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/saa9730.c	Wed Feb 11 22:30:57 2004
@@ -1028,6 +1028,9 @@
 	 * Make certain the data structures used by the controller are aligned 
 	 * and DMAble. 
 	 */
+	/*
+	 *  XXX: that is obviously broken - kfree() won't be happy with us.
+	 */
 	lp = (struct lan_saa9730_private *) (((unsigned long)
 					      kmalloc(sizeof(*lp) + 7,
 						      GFP_DMA | GFP_KERNEL)
@@ -1095,7 +1098,6 @@
  out:
 	if (dev->priv)
 		kfree(dev->priv);
-	free_netdev(dev);
 	return ret;
 }
 
diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c
--- a/drivers/net/shaper.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/shaper.c	Wed Feb 11 22:30:57 2004
@@ -642,7 +642,6 @@
 
 	dev->open		= shaper_open;
 	dev->stop		= shaper_close;
-	dev->destructor 	= free_netdev;
 	dev->hard_start_xmit 	= shaper_start_xmit;
 	dev->get_stats 		= shaper_get_stats;
 	dev->set_multicast_list = NULL;
diff -Nru a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
--- a/drivers/net/smc-mca.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/smc-mca.c	Wed Feb 11 22:30:56 2004
@@ -324,6 +324,9 @@
 
 	dev->open = &ultramca_open;
 	dev->stop = &ultramca_close_card;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 
 	NS8390_init(dev, 0);
 
diff -Nru a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
--- a/drivers/net/smc-ultra.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/smc-ultra.c	Wed Feb 11 22:30:56 2004
@@ -121,6 +121,14 @@
 #define ULTRA_IO_EXTENT 32
 #define EN0_ERWCNT		0x08	/* Early receive warning count. */
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void ultra_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	ei_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 /*	Probe for the Ultra.  This looks like a 8013 with the station
 	address PROM at I/O ports <base>+8 to <base>+13, with a checksum
 	following.
@@ -134,6 +142,9 @@
 
 	SET_MODULE_OWNER(dev);
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &ultra_poll;
+#endif
 	if (base_addr > 0x1ff)		/* Check a single specified location. */
 		return ultra_probe1(dev, base_addr);
 	else if (base_addr != 0)	/* Don't probe at all. */
@@ -301,6 +312,9 @@
 	ei_status.reset_8390 = &ultra_reset_8390;
 	dev->open = &ultra_open;
 	dev->stop = &ultra_close_card;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 	return 0;
diff -Nru a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
--- a/drivers/net/smc-ultra32.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/smc-ultra32.c	Wed Feb 11 22:30:57 2004
@@ -268,6 +268,9 @@
 	ei_status.reset_8390 = &ultra32_reset_8390;
 	dev->open = &ultra32_open;
 	dev->stop = &ultra32_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 	return 0;
diff -Nru a/drivers/net/stnic.c b/drivers/net/stnic.c
--- a/drivers/net/stnic.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/stnic.c	Wed Feb 11 22:30:57 2004
@@ -124,6 +124,9 @@
   dev->irq = IRQ_STNIC;
   dev->open = &stnic_open;
   dev->stop = &stnic_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+  dev->poll_controller = ei_poll;
+#endif
 
   /* Snarf the interrupt now.  There's no point in waiting since we cannot
      share and the board will usually be enabled. */
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/tg3.c	Wed Feb 11 22:30:57 2004
@@ -2479,6 +2479,13 @@
 static int tg3_init_hw(struct tg3 *);
 static int tg3_halt(struct tg3 *);
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void tg3_poll_controller(struct net_device *dev)
+{
+	tg3_interrupt(dev->irq, dev, NULL);
+}
+#endif
+
 static void tg3_reset_task(void *_data)
 {
 	struct tg3 *tp = _data;
@@ -7696,6 +7703,9 @@
 	dev->watchdog_timeo = TG3_TX_TIMEOUT;
 	dev->change_mtu = tg3_change_mtu;
 	dev->irq = pdev->irq;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = tg3_poll_controller;
+#endif
 
 	err = tg3_get_invariants(tp);
 	if (err) {
diff -Nru a/drivers/net/tlan.c b/drivers/net/tlan.c
--- a/drivers/net/tlan.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/tlan.c	Wed Feb 11 22:30:56 2004
@@ -814,6 +814,14 @@
 
 } /* TLan_EisaProbe */
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void TLan_Poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	TLan_HandleInterrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 
 	
 
@@ -893,6 +901,9 @@
 	dev->get_stats = &TLan_GetStats;
 	dev->set_multicast_list = &TLan_SetMulticastList;
 	dev->do_ioctl = &TLan_ioctl;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &TLan_Poll;
+#endif
 	dev->tx_timeout = &TLan_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
diff -Nru a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
--- a/drivers/net/tokenring/3c359.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/tokenring/3c359.c	Wed Feb 11 22:30:57 2004
@@ -1129,7 +1129,7 @@
 				xl_freemem(dev) ; 
 				free_irq(dev->irq,dev); 
 				unregister_netdev(dev) ; 
-				kfree(dev) ;  
+				free_netdev(dev) ;  
 				xl_reset(dev) ; 
 				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
 				spin_unlock(&xl_priv->xl_lock) ; 
diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
--- a/drivers/net/tulip/tulip_core.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/tulip/tulip_core.c	Wed Feb 11 22:30:57 2004
@@ -253,7 +253,7 @@
 static struct net_device_stats *tulip_get_stats(struct net_device *dev);
 static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
-
+static void poll_tulip(struct net_device *dev);
 
 
 static void tulip_set_power_state (struct tulip_private *tp,
@@ -1618,6 +1618,9 @@
 	dev->get_stats = tulip_get_stats;
 	dev->do_ioctl = private_ioctl;
 	dev->set_multicast_list = set_rx_mode;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &poll_tulip;
+#endif
 
 	if (register_netdev(dev))
 		goto err_out_free_ring;
@@ -1774,6 +1777,22 @@
 	/* pci_power_off (pdev, -1); */
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+static void poll_tulip (struct net_device *dev)
+{
+	/* disable_irq here is not very nice, but with the lockless
+	   interrupt handler we have no other choice. */
+	disable_irq(dev->irq);
+	tulip_interrupt (dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 
 static struct pci_driver tulip_driver = {
 	.name		= DRV_NAME,
diff -Nru a/drivers/net/tun.c b/drivers/net/tun.c
--- a/drivers/net/tun.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/tun.c	Wed Feb 11 22:30:57 2004
@@ -118,12 +118,10 @@
 }
 
 /* Initialize net device. */
-int tun_net_init(struct net_device *dev)
+static void tun_net_init(struct net_device *dev)
 {
 	struct tun_struct *tun = (struct tun_struct *)dev->priv;
    
-	DBG(KERN_INFO "%s: tun_net_init\n", tun->dev->name);
-
 	switch (tun->flags & TUN_TYPE_MASK) {
 	case TUN_TUN_DEV:
 		/* Point-to-Point TUN Device */
@@ -147,9 +145,7 @@
 
 		ether_setup(dev);
 		break;
-	};
-
-	return 0;
+	}
 }
 
 /* Character device part */
@@ -351,7 +347,6 @@
 	init_waitqueue_head(&tun->read_wait);
 
 	tun->owner = -1;
-	dev->init = tun_net_init;
 
 	SET_MODULE_OWNER(dev);
 	dev->open = tun_net_open;
@@ -421,6 +416,8 @@
 		tun = dev->priv;
 		tun->dev = dev;
 		tun->flags = flags;
+
+		tun_net_init(dev);
 
 		if (strchr(dev->name, '%')) {
 			err = dev_alloc_name(dev, dev->name);
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/via-rhine.c	Wed Feb 11 22:30:57 2004
@@ -615,6 +615,15 @@
 			break;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void via_rhine_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	via_rhine_interrupt(dev->irq, (void *)dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 static int __devinit via_rhine_init_one (struct pci_dev *pdev,
 					 const struct pci_device_id *ent)
 {
@@ -784,6 +793,9 @@
 	dev->ethtool_ops = &netdev_ethtool_ops;
 	dev->tx_timeout = via_rhine_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = via_rhine_poll;
+#endif
 	if (np->drv_flags & ReqTxAlign)
 		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
diff -Nru a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
--- a/drivers/net/wan/c101.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/c101.c	Wed Feb 11 22:30:57 2004
@@ -54,7 +54,7 @@
 
 
 typedef struct card_s {
-	hdlc_device hdlc;	/* HDLC device struct - must be first */
+	struct net_device *dev;
 	spinlock_t lock;	/* TX lock */
 	u8 *win0base;		/* ISA window base address */
 	u32 phy_winbase;	/* ISA physical base address */
@@ -121,6 +121,7 @@
 
 static void sca_msci_intr(port_t *port)
 {
+	struct net_device *dev = port_to_dev(port);
 	card_t* card = port_to_card(port);
 	u8 stat = sca_in(MSCI1_OFFSET + ST1, card); /* read MSCI ST1 status */
 
@@ -128,8 +129,9 @@
 	sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, card);
 
 	if (stat & ST1_UDRN) {
-		port->hdlc.stats.tx_errors++; /* TX Underrun error detected */
-		port->hdlc.stats.tx_fifo_errors++;
+		struct net_device_stats *stats = hdlc_stats(dev);
+		stats->tx_errors++; /* TX Underrun error detected */
+		stats->tx_fifo_errors++;
 	}
 
 	/* Reset MSCI CDCD status bit - uses ch#2 DCD input */
@@ -137,7 +139,7 @@
 
 	if (stat & ST1_CDCD)
 		hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD),
-				 &port->hdlc);
+				 dev);
 }
 
 
@@ -177,22 +179,21 @@
 
 static int c101_open(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	int result;
 
-	result = hdlc_open(hdlc);
+	result = hdlc_open(dev);
 	if (result)
 		return result;
 
 	writeb(1, port->win0base + C101_DTR);
 	sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */
-	sca_open(hdlc);
+	sca_open(dev);
 	/* DCD is connected to port 2 !@#$%^& - disable MSCI0 CDCD interrupt */
 	sca_out(IE1_UDRN, MSCI0_OFFSET + IE1, port);
 	sca_out(IE0_TXINT, MSCI0_OFFSET + IE0, port);
 
-	hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD), hdlc);
+	hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD), dev);
 	printk(KERN_DEBUG "0x%X\n", sca_in(MSCI1_OFFSET + ST3, port));
 
 	/* enable MSCI1 CDCD interrupt */
@@ -206,13 +207,12 @@
 
 static int c101_close(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
-	sca_close(hdlc);
+	sca_close(dev);
 	writeb(0, port->win0base + C101_DTR);
 	sca_out(CTL_NORTS, MSCI1_OFFSET + CTL, port);
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	return 0;
 }
 
@@ -221,12 +221,11 @@
 {
 	const size_t size = sizeof(sync_serial_settings);
 	sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 #ifdef DEBUG_RINGS
 	if (cmd == SIOCDEVPRIVATE) {
-		sca_dump_rings(hdlc);
+		sca_dump_rings(dev);
 		printk(KERN_DEBUG "MSCI1: ST: %02x %02x %02x %02x\n",
 		       sca_in(MSCI1_OFFSET + ST0, port),
 		       sca_in(MSCI1_OFFSET + ST1, port),
@@ -288,6 +287,8 @@
 		release_mem_region(card->phy_winbase, C101_MAPPED_RAM_SIZE);
 	}
 
+	free_netdev(card->dev);
+
 	kfree(card);
 }
 
@@ -296,6 +297,7 @@
 static int __init c101_run(unsigned long irq, unsigned long winbase)
 {
 	struct net_device *dev;
+	hdlc_device *hdlc;
 	card_t *card;
 	int result;
 
@@ -316,6 +318,13 @@
 	}
 	memset(card, 0, sizeof(card_t));
 
+	card->dev = alloc_hdlcdev(card);
+	if (!card->dev) {
+		printk(KERN_ERR "c101: unable to allocate memory\n");
+		kfree(card);
+		return -ENOBUFS;
+	}
+
 	if (request_irq(irq, sca_intr, 0, devname, card)) {
 		printk(KERN_ERR "c101: could not allocate IRQ\n");
 		c101_destroy_card(card);
@@ -347,7 +356,8 @@
 
 	sca_init(card, 0);
 
-	dev = hdlc_to_dev(&card->hdlc);
+	dev = port_to_dev(card);
+	hdlc = dev_to_hdlc(dev);
 
 	spin_lock_init(&card->lock);
 	SET_MODULE_OWNER(dev);
@@ -358,24 +368,25 @@
 	dev->do_ioctl = c101_ioctl;
 	dev->open = c101_open;
 	dev->stop = c101_close;
-	card->hdlc.attach = sca_attach;
-	card->hdlc.xmit = sca_xmit;
+	hdlc->attach = sca_attach;
+	hdlc->xmit = sca_xmit;
 	card->settings.clock_type = CLOCK_EXT;
 
-	result = register_hdlc_device(&card->hdlc);
+	result = register_hdlc_device(dev);
 	if (result) {
 		printk(KERN_WARNING "c101: unable to register hdlc device\n");
 		c101_destroy_card(card);
 		return result;
 	}
 
+	/* XXX: are we OK with having that done when card is already up? */
+
 	sca_init_sync_port(card); /* Set up C101 memory */
-	hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD),
-			 &card->hdlc);
+	hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD), dev);
 
 	printk(KERN_INFO "%s: Moxa C101 on IRQ%u,"
 	       " using %u TX + %u RX packets rings\n",
-	       hdlc_to_name(&card->hdlc), card->irq,
+	       dev->name, card->irq,
 	       card->tx_ring_buffers, card->rx_ring_buffers);
 
 	*new_card = card;
@@ -424,7 +435,7 @@
 	while (card) {
 		card_t *ptr = card;
 		card = card->next_card;
-		unregister_hdlc_device(&ptr->hdlc);
+		unregister_hdlc_device(port_to_dev(ptr));
 		c101_destroy_card(ptr);
 	}
 }
diff -Nru a/drivers/net/wan/comx-proto-lapb.c b/drivers/net/wan/comx-proto-lapb.c
--- a/drivers/net/wan/comx-proto-lapb.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/wan/comx-proto-lapb.c	Wed Feb 11 22:30:56 2004
@@ -44,7 +44,7 @@
 	if (!dev || !dev->priv) {
 		dev_kfree_skb(skb);
 	} else {
-		lapb_data_received(dev->priv, skb);
+		lapb_data_received(dev, skb);
 	}
 }
 
@@ -82,7 +82,7 @@
 		return -ENODEV;
 	}
 
-	err = lapb_connect_request(ch);
+	err = lapb_connect_request(dev);
 
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
 		comx_debug(dev, "%s: lapb opened, error code: %d\n", 
@@ -108,7 +108,7 @@
 		comx_debug(dev, "%s: lapb closed\n", dev->name);
 	}
 
-	lapb_disconnect_request(ch);
+	lapb_disconnect_request(dev);
 
 	ch->init_status &= ~LINE_OPEN;
 	ch->line_status &= ~PROTO_UP;
@@ -130,11 +130,11 @@
 			case 0x00:	
 				break;	// transmit
 			case 0x01:	
-				lapb_connect_request(ch);
+				lapb_connect_request(dev);
 				kfree_skb(skb);
 				return 0;
 			case 0x02:	
-				lapb_disconnect_request(ch);
+				lapb_disconnect_request(dev);
 			default:
 				kfree_skb(skb);
 				return 0;
@@ -145,7 +145,7 @@
 	netif_stop_queue(dev);
 	
 	if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
-		lapb_data_request(ch, skb2);
+		lapb_data_request(dev, skb2);
 	}
 
 	return FRAME_ACCEPTED;
@@ -157,7 +157,7 @@
 	int len = 0;
 
 	len += sprintf(page + len, "Line status: ");
-	if (lapb_getparms(dev->priv, &parms) != LAPB_OK) {
+	if (lapb_getparms(dev, &parms) != LAPB_OK) {
 		len += sprintf(page + len, "not initialized\n");
 		return len;
 	}
@@ -178,7 +178,7 @@
 	struct lapb_parms_struct parms;
 	int len = 0;
 
-	if (lapb_getparms(dev->priv, &parms)) {
+	if (lapb_getparms(dev, &parms)) {
 		return -ENODEV;
 	}
 
@@ -223,7 +223,7 @@
 	unsigned long parm;
 	char *page;
 
-	if (lapb_getparms(dev->priv, &parms)) {
+	if (lapb_getparms(dev, &parms)) {
 		return -ENODEV;
 	}
 
@@ -243,23 +243,23 @@
 		parm=simple_strtoul(page,NULL,10);
 		if (parm > 0 && parm < 100) {
 			parms.t1=parm;
-			lapb_setparms(dev->priv, &parms);
+			lapb_setparms(dev, &parms);
 		}
 	} else if (strcmp(entry->name, FILENAME_T2) == 0) {
 		parm=simple_strtoul(page, NULL, 10);
 		if (parm > 0 && parm < 100) {
 			parms.t2=parm;
-			lapb_setparms(dev->priv, &parms);
+			lapb_setparms(dev, &parms);
 		}
 	} else if (strcmp(entry->name, FILENAME_N2) == 0) {
 		parm=simple_strtoul(page, NULL, 10);
 		if (parm > 0 && parm < 100) {
 			parms.n2=parm;
-			lapb_setparms(dev->priv, &parms);
+			lapb_setparms(dev, &parms);
 		}
 	} else if (strcmp(entry->name, FILENAME_WINDOW) == 0) {
 		parms.window = simple_strtoul(page, NULL, 10);
-		lapb_setparms(dev->priv, &parms);
+		lapb_setparms(dev, &parms);
 	} else if (strcmp(entry->name, FILENAME_MODE) == 0) {
 		if (comx_strcasecmp(page, "dte") == 0) {
 			parms.mode &= ~(LAPB_DCE | LAPB_DTE); 
@@ -276,7 +276,7 @@
 			parms.mode &= ~LAPB_STANDARD; 
 			parms.mode |= LAPB_EXTENDED;
 		}
-		lapb_setparms(dev->priv, &parms);
+		lapb_setparms(dev, &parms);
 	} else {
 		printk(KERN_ERR "comxlapb_write_proc: internal error, filename %s\n", 
 			entry->name);
@@ -287,9 +287,9 @@
 	return count;
 }
 
-static void comxlapb_connected(void *token, int reason)
+static void comxlapb_connected(struct net_device *dev, int reason)
 {
-	struct comx_channel *ch = token; 
+	struct comx_channel *ch = dev->priv; 
 	struct proc_dir_entry *comxdir = ch->procdir->subdir;
 
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
@@ -327,9 +327,9 @@
 	comx_status(ch->dev, ch->line_status);
 }
 
-static void comxlapb_disconnected(void *token, int reason)
+static void comxlapb_disconnected(struct net_device *dev, int reason)
 {
-	struct comx_channel *ch = token; 
+	struct comx_channel *ch = dev->priv; 
 	struct proc_dir_entry *comxdir = ch->procdir->subdir;
 
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
@@ -366,9 +366,9 @@
 	comx_status(ch->dev, ch->line_status);
 }
 
-static int comxlapb_data_indication(void *token, struct sk_buff *skb)
+static int comxlapb_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
-	struct comx_channel *ch = token; 
+	struct comx_channel *ch = dev->priv; 
 
 	if (ch->dev->type == ARPHRD_X25) {
 		skb_push(skb, 1);
@@ -387,9 +387,9 @@
 	return comx_rx(ch->dev, skb);
 }
 
-static void comxlapb_data_transmit(void *token, struct sk_buff *skb)
+static void comxlapb_data_transmit(struct net_device *dev, struct sk_buff *skb)
 {
-	struct comx_channel *ch = token; 
+	struct comx_channel *ch = dev->priv; 
 
 	if (ch->HW_send_packet) {
 		ch->HW_send_packet(ch->dev, skb);
@@ -417,7 +417,7 @@
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
 		comx_debug(dev, "%s: unregistering lapb\n", dev->name);
 	}
-	lapb_unregister(dev->priv);
+	lapb_unregister(dev);
 
 	remove_proc_entry(FILENAME_T1, ch->procdir);
 	remove_proc_entry(FILENAME_T2, ch->procdir);
@@ -453,7 +453,7 @@
 	lapbreg.disconnect_indication = comxlapb_disconnected;
 	lapbreg.data_indication = comxlapb_data_indication;
 	lapbreg.data_transmit = comxlapb_data_transmit;
-	if (lapb_register(dev->priv, &lapbreg)) {
+	if (lapb_register(dev, &lapbreg)) {
 		return -ENOMEM;
 	}
 	if (ch->debug_flags & DEBUG_COMX_LAPB) {
diff -Nru a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
--- a/drivers/net/wan/dlci.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/dlci.c	Wed Feb 11 22:30:57 2004
@@ -414,7 +414,7 @@
 
  err2:
 	rtnl_unlock();
-	kfree(master);
+	free_netdev(master);
  err1:
 	dev_put(slave);
 	return(err);
diff -Nru a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
--- a/drivers/net/wan/dscc4.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/dscc4.c	Wed Feb 11 22:30:57 2004
@@ -228,7 +228,7 @@
 
 	unsigned short encoding;
 	unsigned short parity;
-	hdlc_device hdlc;
+	struct net_device *dev;
 	sync_serial_settings settings;
 	u32 __pad __attribute__ ((aligned (4)));
 };
@@ -364,7 +364,7 @@
 static void dscc4_timer(unsigned long);
 static void dscc4_tx_timeout(struct net_device *);
 static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs);
-static int dscc4_hdlc_attach(hdlc_device *, unsigned short, unsigned short);
+static int dscc4_hdlc_attach(struct net_device *, unsigned short, unsigned short);
 static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *);
 static inline int dscc4_set_quartz(struct dscc4_dev_priv *, int);
 #ifdef DSCC4_POLLING
@@ -373,7 +373,12 @@
 
 static inline struct dscc4_dev_priv *dscc4_priv(struct net_device *dev)
 {
-	return list_entry(dev, struct dscc4_dev_priv, hdlc.netdev);
+	return dev_to_hdlc(dev)->priv;
+}
+
+static inline struct net_device *dscc4_to_dev(struct dscc4_dev_priv *p)
+{
+	return p->dev;
 }
 
 static void scc_patchl(u32 mask, u32 value, struct dscc4_dev_priv *dpriv,
@@ -636,7 +641,7 @@
 				struct net_device *dev)
 {
 	struct RxFD *rx_fd = dpriv->rx_fd + dpriv->rx_current%RX_RING_SIZE;
-	struct net_device_stats *stats = &dpriv->hdlc.stats;
+	struct net_device_stats *stats = hdlc_stats(dev);
 	struct pci_dev *pdev = dpriv->pci_priv->pdev;
 	struct sk_buff *skb;
 	int pkt_len;
@@ -689,10 +694,12 @@
 	root = ppriv->root;
 
 	for (i = 0; i < dev_per_card; i++)
-		unregister_hdlc_device(&root[i].hdlc);
+		unregister_hdlc_device(dscc4_to_dev(&root[i]));
 
 	pci_set_drvdata(pdev, NULL);
 
+	for (i = 0; i < dev_per_card; i++)
+		free_netdev(root[i].dev);
 	kfree(root);
 	kfree(ppriv);
 }
@@ -874,17 +881,31 @@
 	}
 	memset(root, 0, dev_per_card*sizeof(*root));
 
+	for (i = 0; i < dev_per_card; i++) {
+		root[i].dev = alloc_hdlcdev(root + i);
+		if (!root[i].dev) {
+			while (i--)
+				free_netdev(root[i].dev);
+			goto err_free_dev;
+		}
+	}
+
 	ppriv = (struct dscc4_pci_priv *) kmalloc(sizeof(*ppriv), GFP_KERNEL);
 	if (!ppriv) {
 		printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME);
-		goto err_free_dev;
+		goto err_free_dev2;
 	}
 	memset(ppriv, 0, sizeof(struct dscc4_pci_priv));
+	ret = dscc4_set_quartz(root, quartz);
+	if (ret < 0)
+		goto err_free_priv;
+	ppriv->root = root;
+	spin_lock_init(&ppriv->lock);
 
 	for (i = 0; i < dev_per_card; i++) {
 		struct dscc4_dev_priv *dpriv = root + i;
-		hdlc_device *hdlc = &dpriv->hdlc;
-		struct net_device *d = hdlc_to_dev(hdlc);
+		struct net_device *d = dscc4_to_dev(dpriv);
+		hdlc_device *hdlc = dev_to_hdlc(d);
 
 	        d->base_addr = ioaddr;
 		d->init = NULL;
@@ -905,36 +926,34 @@
 		hdlc->xmit = dscc4_start_xmit;
 		hdlc->attach = dscc4_hdlc_attach;
 
-		ret = register_hdlc_device(hdlc);
-		if (ret < 0) {
-			printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
-			goto err_unregister;
-	        }
-
 		dscc4_init_registers(dpriv, d);
 		dpriv->parity = PARITY_CRC16_PR0_CCITT;
 		dpriv->encoding = ENCODING_NRZ;
-
+	
 		ret = dscc4_init_ring(d);
+		if (ret < 0)
+			goto err_unregister;
+
+		ret = register_hdlc_device(d);
 		if (ret < 0) {
-			unregister_hdlc_device(hdlc);
+			printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
+			dscc4_release_ring(dpriv);
 			goto err_unregister;
-		}
+	        }
 	}
-	ret = dscc4_set_quartz(root, quartz);
-	if (ret < 0)
-		goto err_unregister;
-	ppriv->root = root;
-	spin_lock_init(&ppriv->lock);
 	pci_set_drvdata(pdev, ppriv);
 	return ret;
 
 err_unregister:
 	while (--i >= 0) {
 		dscc4_release_ring(root + i);
-		unregister_hdlc_device(&root[i].hdlc);
+		unregister_hdlc_device(dscc4_to_dev(&root[i]));
 	}
+err_free_priv:
 	kfree(ppriv);
+err_free_dev2:
+	for (i = 0; i < dev_per_card; i++)
+		free_netdev(root[i].dev);
 err_free_dev:
 	kfree(root);
 err_out:
@@ -964,7 +983,7 @@
 	sync_serial_settings *settings = &dpriv->settings;
 
 	if (settings->loopback && (settings->clock_type != CLOCK_INT)) {
-		struct net_device *dev = hdlc_to_dev(&dpriv->hdlc);
+		struct net_device *dev = dscc4_to_dev(dpriv);
 
 		printk(KERN_INFO "%s: loopback requires clock\n", dev->name);
 		return -1;
@@ -1015,14 +1034,13 @@
 static int dscc4_open(struct net_device *dev)
 {
 	struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
-	hdlc_device *hdlc = &dpriv->hdlc;
 	struct dscc4_pci_priv *ppriv;
 	int ret = -EAGAIN;
 
 	if ((dscc4_loopback_check(dpriv) < 0) || !dev->hard_start_xmit)
 		goto err;
 
-	if ((ret = hdlc_open(hdlc)))
+	if ((ret = hdlc_open(dev)))
 		goto err;
 
 	ppriv = dpriv->pci_priv;
@@ -1103,7 +1121,7 @@
 	scc_writel(0xffffffff, dpriv, dev, IMR);
 	scc_patchl(PowerUp | Vis, 0, dpriv, dev, CCR0);
 err_out:
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 err:
 	return ret;
 }
@@ -1155,7 +1173,6 @@
 static int dscc4_close(struct net_device *dev)
 {
 	struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
-	hdlc_device *hdlc = dev_to_hdlc(dev);
 
 	del_timer_sync(&dpriv->timer);
 	netif_stop_queue(dev);
@@ -1166,7 +1183,7 @@
 
 	dpriv->flags |= FakeReset;
 
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 
 	return 0;
 }
@@ -1467,7 +1484,7 @@
 	int i, handled = 1;
 
 	priv = root->pci_priv;
-	dev = hdlc_to_dev(&root->hdlc);
+	dev = dscc4_to_dev(root);
 
 	spin_lock_irqsave(&priv->lock, flags);
 
@@ -1518,7 +1535,7 @@
 static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
 				struct dscc4_dev_priv *dpriv)
 {
-	struct net_device *dev = hdlc_to_dev(&dpriv->hdlc);
+	struct net_device *dev = dscc4_to_dev(dpriv);
 	u32 state;
 	int cur, loop = 0;
 
@@ -1549,7 +1566,7 @@
 
 	if (state & SccEvt) {
 		if (state & Alls) {
-			struct net_device_stats *stats = &dpriv->hdlc.stats;
+			struct net_device_stats *stats = hdlc_stats(dev);
 			struct sk_buff *skb;
 			struct TxFD *tx_fd;
 
@@ -1677,7 +1694,7 @@
 		}
 		if (state & Err) {
 			printk(KERN_INFO "%s: Tx ERR\n", dev->name);
-			dev_to_hdlc(dev)->stats.tx_errors++;
+			hdlc_stats(dev)->tx_errors++;
 			state &= ~Err;
 		}
 	}
@@ -1687,7 +1704,7 @@
 static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv,
 				    struct dscc4_dev_priv *dpriv)
 {
-	struct net_device *dev = hdlc_to_dev(&dpriv->hdlc);
+	struct net_device *dev = dscc4_to_dev(dpriv);
 	u32 state;
 	int cur;
 
@@ -1813,7 +1830,7 @@
 				if (!(rx_fd->state2 & DataComplete))
 					break;
 				if (rx_fd->state2 & FrameAborted) {
-					dev_to_hdlc(dev)->stats.rx_over_errors++;
+					hdlc_stats(dev)->rx_over_errors++;
 					rx_fd->state1 |= Hold;
 					rx_fd->state2 = 0x00000000;
 					rx_fd->end = 0xbabeface;
@@ -1961,7 +1978,7 @@
 	ppriv = pci_get_drvdata(pdev);
 	root = ppriv->root;
 
-	ioaddr = hdlc_to_dev(&root->hdlc)->base_addr;
+	ioaddr = dscc4_to_dev(root)->base_addr;
 
 	dscc4_pci_reset(pdev, ioaddr);
 
@@ -1988,10 +2005,9 @@
 			   pci_resource_len(pdev, 0));
 }
 
-static int dscc4_hdlc_attach(hdlc_device *hdlc, unsigned short encoding,
+static int dscc4_hdlc_attach(struct net_device *dev, unsigned short encoding,
 	unsigned short parity)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
 	struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
 
 	if (encoding != ENCODING_NRZ &&
diff -Nru a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
--- a/drivers/net/wan/farsync.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/farsync.c	Wed Feb 11 22:30:57 2004
@@ -328,7 +328,7 @@
 /*      Per port (line or channel) information
  */
 struct fst_port_info {
-        hdlc_device             hdlc;   /* HDLC device struct - must be first */
+        struct net_device      *dev;
         struct fst_card_info   *card;   /* Card we're associated with */
         int                     index;  /* Port index on the card */
         int                     hwif;   /* Line hardware (lineInterface copy) */
@@ -357,9 +357,8 @@
 };
 
 /* Convert an HDLC device pointer into a port info pointer and similar */
-#define hdlc_to_port(H) ((struct fst_port_info *)(H))
-#define dev_to_port(D)  hdlc_to_port(dev_to_hdlc(D))
-#define port_to_dev(P)  hdlc_to_dev(&(P)->hdlc)
+#define dev_to_port(D)  (dev_to_hdlc(D)->priv)
+#define port_to_dev(P)  ((P)->dev)
 
 
 /*
@@ -651,6 +650,8 @@
         int rxp;
         unsigned short len;
         struct sk_buff *skb;
+	struct net_device *dev = port_to_dev(port);
+	struct net_device_stats *stats = hdlc_stats(dev);
         int i;
 
 
@@ -678,24 +679,24 @@
                                         len );
         if ( dmabits != ( RX_STP | RX_ENP ) || len > LEN_RX_BUFFER - 2 )
         {
-                port->hdlc.stats.rx_errors++;
+                stats->rx_errors++;
 
                 /* Update error stats and discard buffer */
                 if ( dmabits & RX_OFLO )
                 {
-                        port->hdlc.stats.rx_fifo_errors++;
+                        stats->rx_fifo_errors++;
                 }
                 if ( dmabits & RX_CRC )
                 {
-                        port->hdlc.stats.rx_crc_errors++;
+                        stats->rx_crc_errors++;
                 }
                 if ( dmabits & RX_FRAM )
                 {
-                        port->hdlc.stats.rx_frame_errors++;
+                        stats->rx_frame_errors++;
                 }
                 if ( dmabits == ( RX_STP | RX_ENP ))
                 {
-                        port->hdlc.stats.rx_length_errors++;
+                        stats->rx_length_errors++;
                 }
 
                 /* Discard buffer descriptors until we see the end of packet
@@ -732,7 +733,7 @@
         {
                 dbg ( DBG_RX,"intr_rx: can't allocate buffer\n");
 
-                port->hdlc.stats.rx_dropped++;
+                stats->rx_dropped++;
 
                 /* Return descriptor to card */
                 FST_WRB ( card, rxDescrRing[pi][rxp].bits, DMA_OWN );
@@ -756,16 +757,16 @@
                 port->rxpos = rxp;
 
         /* Update stats */
-        port->hdlc.stats.rx_packets++;
-        port->hdlc.stats.rx_bytes += len;
+        stats->rx_packets++;
+        stats->rx_bytes += len;
 
         /* Push upstream */
         skb->mac.raw = skb->data;
-        skb->dev = hdlc_to_dev ( &port->hdlc );
+        skb->dev = dev;
         skb->protocol = hdlc_type_trans(skb, skb->dev);
         netif_rx ( skb );
 
-        port_to_dev ( port )->last_rx = jiffies;
+        dev->last_rx = jiffies;
 }
 
 
@@ -835,8 +836,8 @@
                          * always load up the entire packet for DMA.
                          */
                         dbg ( DBG_TX,"Tx underflow port %d\n", event & 0x03 );
-                        port->hdlc.stats.tx_errors++;
-                        port->hdlc.stats.tx_fifo_errors++;
+                        hdlc_stats(port_to_dev(port))->tx_errors++;
+                        hdlc_stats(port_to_dev(port))->tx_fifo_errors++;
                         break;
 
                 case INIT_CPLT:
@@ -1309,7 +1310,7 @@
 {
         int err;
 
-        err = hdlc_open ( dev_to_hdlc ( dev ));
+        err = hdlc_open (dev);
         if ( err )
                 return err;
 
@@ -1323,12 +1324,12 @@
 {
         netif_stop_queue ( dev );
         fst_closeport ( dev_to_port ( dev ));
-        hdlc_close ( dev_to_hdlc  ( dev ));
+        hdlc_close ( dev );
         return 0;
 }
 
 static int
-fst_attach ( hdlc_device *hdlc, unsigned short encoding, unsigned short parity )
+fst_attach ( struct net_device *dev, unsigned short encoding, unsigned short parity )
 {
         /* Setting currently fixed in FarSync card so we check and forget */
         if ( encoding != ENCODING_NRZ || parity != PARITY_CRC16_PR1_CCITT )
@@ -1341,13 +1342,14 @@
 fst_tx_timeout ( struct net_device *dev )
 {
         struct fst_port_info *port;
+	struct net_device_stats *stats = hdlc_stats(dev);
 
         dbg ( DBG_INTR | DBG_TX,"tx_timeout\n");
 
         port = dev_to_port ( dev );
 
-        port->hdlc.stats.tx_errors++;
-        port->hdlc.stats.tx_aborted_errors++;
+        stats->tx_errors++;
+        stats->tx_aborted_errors++;
 
         if ( port->txcnt > 0 )
                 fst_issue_cmd ( port, ABORTTX );
@@ -1360,6 +1362,7 @@
 static int
 fst_start_xmit ( struct sk_buff *skb, struct net_device *dev )
 {
+	struct net_device_stats *stats = hdlc_stats(dev);
         struct fst_card_info *card;
         struct fst_port_info *port;
         unsigned char dmabits;
@@ -1374,8 +1377,8 @@
         if ( ! netif_carrier_ok ( dev ))
         {
                 dev_kfree_skb ( skb );
-                port->hdlc.stats.tx_errors++;
-                port->hdlc.stats.tx_carrier_errors++;
+                stats->tx_errors++;
+                stats->tx_carrier_errors++;
                 return 0;
         }
 
@@ -1385,7 +1388,7 @@
                 dbg ( DBG_TX,"Packet too large %d vs %d\n", skb->len,
                                                 LEN_TX_BUFFER );
                 dev_kfree_skb ( skb );
-                port->hdlc.stats.tx_errors++;
+                stats->tx_errors++;
                 return 0;
         }
 
@@ -1399,7 +1402,7 @@
                 spin_unlock_irqrestore ( &card->card_lock, flags );
                 dbg ( DBG_TX,"Out of Tx buffers\n");
                 dev_kfree_skb ( skb );
-                port->hdlc.stats.tx_errors++;
+                stats->tx_errors++;
                 return 0;
         }
         if ( ++port->txpos >= NUM_TX_BUFFER )
@@ -1419,8 +1422,8 @@
         FST_WRW ( card, txDescrRing[pi][txp].bcnt, cnv_bcnt ( skb->len ));
         FST_WRB ( card, txDescrRing[pi][txp].bits, DMA_OWN | TX_STP | TX_ENP );
 
-        port->hdlc.stats.tx_packets++;
-        port->hdlc.stats.tx_bytes += skb->len;
+        stats->tx_packets++;
+        stats->tx_bytes += skb->len;
 
         dev_kfree_skb ( skb );
 
@@ -1447,55 +1450,29 @@
 {
         int i;
         int err;
-        struct net_device *dev;
 
         /* We're working on a number of ports based on the card ID. If the
          * firmware detects something different later (should never happen)
          * we'll have to revise it in some way then.
          */
-        for ( i = 0 ; i < card->nports ; i++ )
-        {
-                card->ports[i].card   = card;
-                card->ports[i].index  = i;
-                card->ports[i].run    = 0;
-
-                dev = hdlc_to_dev ( &card->ports[i].hdlc );
-
-                /* Fill in the net device info */
-                                /* Since this is a PCI setup this is purely
-                                 * informational. Give them the buffer addresses
-                                 * and basic card I/O.
-                                 */
-                dev->mem_start   = card->phys_mem
-                                 + BUF_OFFSET ( txBuffer[i][0][0]);
-                dev->mem_end     = card->phys_mem
-                                 + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]);
-                dev->base_addr   = card->pci_conf;
-                dev->irq         = card->irq;
-
-                dev->tx_queue_len          = FST_TX_QUEUE_LEN;
-                dev->open                  = fst_open;
-                dev->stop                  = fst_close;
-                dev->do_ioctl              = fst_ioctl;
-                dev->watchdog_timeo        = FST_TX_TIMEOUT;
-                dev->tx_timeout            = fst_tx_timeout;
-                card->ports[i].hdlc.attach = fst_attach;
-                card->ports[i].hdlc.xmit   = fst_start_xmit;
-
-                if (( err = register_hdlc_device ( &card->ports[i].hdlc )) < 0 )
-                {
+        for ( i = 0 ; i < card->nports ; i++ ) {
+                err = register_hdlc_device(card->ports[i].dev);
+                if (err < 0) {
+			int j;
                         printk_err ("Cannot register HDLC device for port %d"
                                     " (errno %d)\n", i, -err );
+			for (j = i; j < card->nports; j++) {
+				free_netdev(card->ports[j].dev);
+				card->ports[j].dev = NULL;
+			}
                         card->nports = i;
                         break;
                 }
         }
 
-        spin_lock_init ( &card->card_lock );
-
         printk ( KERN_INFO "%s-%s: %s IRQ%d, %d ports\n",
-                        hdlc_to_dev(&card->ports[0].hdlc)->name,
-                        hdlc_to_dev(&card->ports[card->nports-1].hdlc)->name,
+                        port_to_dev(&card->ports[0])->name,
+                        port_to_dev(&card->ports[card->nports-1])->name,
                         type_strings[card->type], card->irq, card->nports );
 }
 
@@ -1510,6 +1487,7 @@
         static int firsttime_done = 0;
         struct fst_card_info *card;
         int err = 0;
+	int i;
 
         if ( ! firsttime_done )
         {
@@ -1546,6 +1524,46 @@
 
         card->state       = FST_UNINIT;
 
+        spin_lock_init ( &card->card_lock );
+
+        for ( i = 0 ; i < card->nports ; i++ ) {
+		struct net_device *dev = alloc_hdlcdev(&card->ports[i]);
+		hdlc_device *hdlc;
+		if (!dev) {
+			while (i--)
+				free_netdev(card->ports[i].dev);
+			printk_err ("FarSync: out of memory\n");
+			goto error_free_card;
+		}
+		card->ports[i].dev    = dev;
+                card->ports[i].card   = card;
+                card->ports[i].index  = i;
+                card->ports[i].run    = 0;
+
+		hdlc = dev_to_hdlc(dev);
+
+                /* Fill in the net device info */
+		/* Since this is a PCI setup this is purely
+		 * informational. Give them the buffer addresses
+		 * and basic card I/O.
+		 */
+                dev->mem_start   = card->phys_mem
+                                 + BUF_OFFSET ( txBuffer[i][0][0]);
+                dev->mem_end     = card->phys_mem
+                                 + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]);
+                dev->base_addr   = card->pci_conf;
+                dev->irq         = card->irq;
+
+                dev->tx_queue_len          = FST_TX_QUEUE_LEN;
+                dev->open                  = fst_open;
+                dev->stop                  = fst_close;
+                dev->do_ioctl              = fst_ioctl;
+                dev->watchdog_timeo        = FST_TX_TIMEOUT;
+                dev->tx_timeout            = fst_tx_timeout;
+                hdlc->attach = fst_attach;
+                hdlc->xmit   = fst_start_xmit;
+	}
+
         dbg ( DBG_PCI,"type %d nports %d irq %d\n", card->type,
                         card->nports, card->irq );
         dbg ( DBG_PCI,"conf %04x mem %08x ctlmem %08x\n",
@@ -1557,7 +1575,7 @@
                 printk_err ("Unable to get config I/O @ 0x%04X\n",
                                                 card->pci_conf );
                 err = -ENODEV;
-                goto error_free_card;
+                goto error_free_ports;
         }
         if ( ! request_mem_region ( card->phys_mem, FST_MEMSIZE,"Shared RAM"))
         {
@@ -1628,6 +1646,9 @@
 error_release_io:
         release_region ( card->pci_conf, 0x80 );
 
+error_free_ports:
+	for (i = 0; i < card->nports; i++)
+		free_netdev(card->ports[i].dev);
 error_free_card:
         kfree ( card );
         return err;
@@ -1647,7 +1668,8 @@
 
         for ( i = 0 ; i < card->nports ; i++ )
         {
-                unregister_hdlc_device ( &card->ports[i].hdlc );
+		struct net_device *dev = port_to_dev(&card->ports[i]);
+                unregister_hdlc_device(dev);
         }
 
         fst_disable_intr ( card );
@@ -1659,6 +1681,9 @@
         release_mem_region ( card->phys_ctlmem, 0x10 );
         release_mem_region ( card->phys_mem, FST_MEMSIZE );
         release_region ( card->pci_conf, 0x80 );
+
+	for (i = 0; i < card->nports; i++)
+		free_netdev(card->ports[i].dev);
 
         kfree ( card );
 }
diff -Nru a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
--- a/drivers/net/wan/hd6457x.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/wan/hd6457x.c	Wed Feb 11 22:30:56 2004
@@ -73,6 +73,11 @@
 #define writea(value, ptr)		writel(value, ptr)
 #endif
 
+static inline struct net_device *port_to_dev(port_t *port)
+{
+	return port->dev;
+}
+
 static inline int sca_intr_status(card_t *card)
 {
 	u8 result = 0;
@@ -110,22 +115,11 @@
 	return result;
 }
 
-
-
-static inline port_t* hdlc_to_port(hdlc_device *hdlc)
-{
-	return (port_t*)hdlc;
-}
-
-
-
 static inline port_t* dev_to_port(struct net_device *dev)
 {
-	return hdlc_to_port(dev_to_hdlc(dev));
+	return dev_to_hdlc(dev)->priv;
 }
 
-
-
 static inline u16 next_desc(port_t *port, u16 desc, int transmit)
 {
 	return (desc + 1) % (transmit ? port_to_card(port)->tx_ring_buffers
@@ -245,7 +239,7 @@
 	}
 
 	hdlc_set_carrier(!(sca_in(get_msci(port) + ST3, card) & ST3_DCD),
-			 &port->hdlc);
+			 port_to_dev(port));
 }
 
 
@@ -262,13 +256,14 @@
 	sca_out(stat & (ST1_UDRN | ST1_CDCD), msci + ST1, card);
 
 	if (stat & ST1_UDRN) {
-		port->hdlc.stats.tx_errors++; /* TX Underrun error detected */
-		port->hdlc.stats.tx_fifo_errors++;
+		struct net_device_stats *stats = hdlc_stats(port_to_dev(port));
+		stats->tx_errors++; /* TX Underrun error detected */
+		stats->tx_fifo_errors++;
 	}
 
 	if (stat & ST1_CDCD)
 		hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD),
-				 &port->hdlc);
+				 port_to_dev(port));
 }
 #endif
 
@@ -276,6 +271,8 @@
 
 static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u16 rxin)
 {
+	struct net_device *dev = port_to_dev(port);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	struct sk_buff *skb;
 	u16 len;
 	u32 buff;
@@ -287,7 +284,7 @@
 	len = readw(&desc->len);
 	skb = dev_alloc_skb(len);
 	if (!skb) {
-		port->hdlc.stats.rx_dropped++;
+		stats->rx_dropped++;
 		return;
 	}
 
@@ -313,15 +310,15 @@
 #endif
 	skb_put(skb, len);
 #ifdef DEBUG_PKT
-	printk(KERN_DEBUG "%s RX(%i):", hdlc_to_name(&port->hdlc), skb->len);
+	printk(KERN_DEBUG "%s RX(%i):", dev->name, skb->len);
 	debug_frame(skb);
 #endif
-	port->hdlc.stats.rx_packets++;
-	port->hdlc.stats.rx_bytes += skb->len;
+	stats->rx_packets++;
+	stats->rx_bytes += skb->len;
 	skb->mac.raw = skb->data;
-	skb->dev = hdlc_to_dev(&port->hdlc);
+	skb->dev = dev;
 	skb->dev->last_rx = jiffies;
-	skb->protocol = hdlc_type_trans(skb, hdlc_to_dev(&port->hdlc));
+	skb->protocol = hdlc_type_trans(skb, dev);
 	netif_rx(skb);
 }
 
@@ -333,7 +330,7 @@
 	u16 dmac = get_dmac_rx(port);
 	card_t *card = port_to_card(port);
 	u8 stat = sca_in(DSR_RX(phy_node(port)), card); /* read DMA Status */
-	struct net_device_stats *stats = &port->hdlc.stats;
+	struct net_device_stats *stats = hdlc_stats(port_to_dev(port));
 
 	/* Reset DSR status bits */
 	sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE,
@@ -380,6 +377,8 @@
 /* Transmit DMA interrupt service */
 static inline void sca_tx_intr(port_t *port)
 {
+	struct net_device *dev = port_to_dev(port);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	u16 dmac = get_dmac_tx(port);
 	card_t* card = port_to_card(port);
 	u8 stat;
@@ -401,13 +400,13 @@
 			break;	/* Transmitter is/will_be sending this frame */
 
 		desc = desc_address(port, port->txlast, 1);
-		port->hdlc.stats.tx_packets++;
-		port->hdlc.stats.tx_bytes += readw(&desc->len);
+		stats->tx_packets++;
+		stats->tx_bytes += readw(&desc->len);
 		writeb(0, &desc->stat);	/* Free descriptor */
 		port->txlast = next_desc(port, port->txlast, 1);
 	}
 
-	netif_wake_queue(hdlc_to_dev(&port->hdlc));
+	netif_wake_queue(dev);
 	spin_unlock(&port->lock);
 }
 
@@ -508,9 +507,9 @@
 
 
 
-static void sca_open(hdlc_device *hdlc)
+static void sca_open(struct net_device *dev)
 {
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	card_t* card = port_to_card(port);
 	u16 msci = get_msci(port);
 	u8 md0, md2;
@@ -569,7 +568,7 @@
    - all DMA interrupts
 */
 
-	hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD), hdlc);
+	hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD), dev);
 
 #ifdef __HD64570_H
 	/* MSCI TX INT and RX INT A IRQ enable */
@@ -600,18 +599,18 @@
 	sca_out(CMD_TX_ENABLE, msci + CMD, card);
 	sca_out(CMD_RX_ENABLE, msci + CMD, card);
 
-	netif_start_queue(hdlc_to_dev(hdlc));
+	netif_start_queue(dev);
 }
 
 
 
-static void sca_close(hdlc_device *hdlc)
+static void sca_close(struct net_device *dev)
 {
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	card_t* card = port_to_card(port);
 
 	/* reset channel */
-	netif_stop_queue(hdlc_to_dev(hdlc));
+	netif_stop_queue(dev);
 	sca_out(CMD_RESET, get_msci(port) + CMD, port_to_card(port));
 #ifdef __HD64570_H
 	/* disable MSCI interrupts */
@@ -629,7 +628,7 @@
 
 
 
-static int sca_attach(hdlc_device *hdlc, unsigned short encoding,
+static int sca_attach(struct net_device *dev, unsigned short encoding,
 		      unsigned short parity)
 {
 	if (encoding != ENCODING_NRZ &&
@@ -650,17 +649,17 @@
 	    parity != PARITY_CRC16_PR1_CCITT)
 		return -EINVAL;
 
-	hdlc_to_port(hdlc)->encoding = encoding;
-	hdlc_to_port(hdlc)->parity = parity;
+	dev_to_port(dev)->encoding = encoding;
+	dev_to_port(dev)->parity = parity;
 	return 0;
 }
 
 
 
 #ifdef DEBUG_RINGS
-static void sca_dump_rings(hdlc_device *hdlc)
+static void sca_dump_rings(struct net_device *dev)
 {
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	card_t *card = port_to_card(port);
 	u16 cnt;
 #if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED)
@@ -729,8 +728,7 @@
 
 static int sca_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	card_t *card = port_to_card(port);
 	pkt_desc *desc;
 	u32 buff, len;
@@ -753,7 +751,7 @@
 	}
 
 #ifdef DEBUG_PKT
-	printk(KERN_DEBUG "%s TX(%i):", hdlc_to_name(hdlc), skb->len);
+	printk(KERN_DEBUG "%s TX(%i):", dev->name, skb->len);
 	debug_frame(skb);
 #endif
 
@@ -790,7 +788,7 @@
 
 	desc = desc_address(port, port->txin + 1, 1);
 	if (readb(&desc->stat)) /* allow 1 packet gap */
-		netif_stop_queue(hdlc_to_dev(&port->hdlc));
+		netif_stop_queue(dev);
 
 	spin_unlock_irq(&port->lock);
 
diff -Nru a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
--- a/drivers/net/wan/hdlc_cisco.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/hdlc_cisco.c	Wed Feb 11 22:30:57 2004
@@ -57,7 +57,7 @@
 
 
 
-static void cisco_keepalive_send(hdlc_device *hdlc, u32 type,
+static void cisco_keepalive_send(struct net_device *dev, u32 type,
 				 u32 par1, u32 par2)
 {
 	struct sk_buff *skb;
@@ -67,12 +67,11 @@
 	if (!skb) {
 		printk(KERN_WARNING
 		       "%s: Memory squeeze on cisco_keepalive_send()\n",
-		       hdlc_to_name(hdlc));
+		       dev->name);
 		return;
 	}
 	skb_reserve(skb, 4);
-	cisco_hard_header(skb, hdlc_to_dev(hdlc), CISCO_KEEPALIVE,
-			  NULL, NULL, 0);
+	cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
 	data = (cisco_packet*)skb->tail;
 
 	data->type = htonl(type);
@@ -84,7 +83,7 @@
 
 	skb_put(skb, sizeof(cisco_packet));
 	skb->priority = TC_PRIO_CONTROL;
-	skb->dev = hdlc_to_dev(hdlc);
+	skb->dev = dev;
 	skb->nh.raw = skb->data;
 
 	dev_queue_xmit(skb);
@@ -118,7 +117,8 @@
 
 static int cisco_rx(struct sk_buff *skb)
 {
-	hdlc_device *hdlc = dev_to_hdlc(skb->dev);
+	struct net_device *dev = skb->dev;
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	hdlc_header *data = (hdlc_header*)skb->data;
 	cisco_packet *cisco_data;
 	struct in_device *in_dev;
@@ -142,7 +142,7 @@
 		    skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) {
 			printk(KERN_INFO "%s: Invalid length of Cisco "
 			       "control packet (%d bytes)\n",
-			       hdlc_to_name(hdlc), skb->len);
+			       dev->name, skb->len);
 			goto rx_error;
 		}
 
@@ -150,7 +150,7 @@
 
 		switch(ntohl (cisco_data->type)) {
 		case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
-			in_dev = hdlc_to_dev(hdlc)->ip_ptr;
+			in_dev = dev->ip_ptr;
 			addr = 0;
 			mask = ~0; /* is the mask correct? */
 
@@ -158,7 +158,7 @@
 				struct in_ifaddr **ifap = &in_dev->ifa_list;
 
 				while (*ifap != NULL) {
-					if (strcmp(hdlc_to_name(hdlc),
+					if (strcmp(dev->name,
 						   (*ifap)->ifa_label) == 0) {
 						addr = (*ifap)->ifa_local;
 						mask = (*ifap)->ifa_mask;
@@ -167,7 +167,7 @@
 					ifap = &(*ifap)->ifa_next;
 				}
 
-				cisco_keepalive_send(hdlc, CISCO_ADDR_REPLY,
+				cisco_keepalive_send(dev, CISCO_ADDR_REPLY,
 						     addr, mask);
 			}
 			dev_kfree_skb_any(skb);
@@ -175,7 +175,7 @@
 
 		case CISCO_ADDR_REPLY:
 			printk(KERN_INFO "%s: Unexpected Cisco IP address "
-			       "reply\n", hdlc_to_name(hdlc));
+			       "reply\n", dev->name);
 			goto rx_error;
 
 		case CISCO_KEEPALIVE_REQ:
@@ -190,7 +190,7 @@
 					days = hrs / 24; hrs -= days * 24;
 					printk(KERN_INFO "%s: Link up (peer "
 					       "uptime %ud%uh%um%us)\n",
-					       hdlc_to_name(hdlc), days, hrs,
+					       dev->name, days, hrs,
 					       min, sec);
 				}
 				hdlc->state.cisco.up = 1;
@@ -201,7 +201,7 @@
 		} /* switch(keepalive type) */
 	} /* switch(protocol) */
 
-	printk(KERN_INFO "%s: Unsupported protocol %x\n", hdlc_to_name(hdlc),
+	printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name,
 	       data->protocol);
 	dev_kfree_skb_any(skb);
 	return NET_RX_DROP;
@@ -216,17 +216,18 @@
 
 static void cisco_timer(unsigned long arg)
 {
-	hdlc_device *hdlc = (hdlc_device*)arg;
+	struct net_device *dev = (struct net_device *)arg;
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 
 	if (hdlc->state.cisco.up && jiffies - hdlc->state.cisco.last_poll >=
 	    hdlc->state.cisco.settings.timeout * HZ) {
 		hdlc->state.cisco.up = 0;
-		printk(KERN_INFO "%s: Link down\n", hdlc_to_name(hdlc));
-		if (netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_off(&hdlc->netdev);
+		printk(KERN_INFO "%s: Link down\n", dev->name);
+		if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
 	}
 
-	cisco_keepalive_send(hdlc, CISCO_KEEPALIVE_REQ,
+	cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
 			     ++hdlc->state.cisco.txseq,
 			     hdlc->state.cisco.rxseq);
 	hdlc->state.cisco.timer.expires = jiffies +
@@ -238,8 +239,9 @@
 
 
 
-static void cisco_start(hdlc_device *hdlc)
+static void cisco_start(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	hdlc->state.cisco.last_poll = 0;
 	hdlc->state.cisco.up = 0;
 	hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0;
@@ -247,27 +249,27 @@
 	init_timer(&hdlc->state.cisco.timer);
 	hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/
 	hdlc->state.cisco.timer.function = cisco_timer;
-	hdlc->state.cisco.timer.data = (unsigned long)hdlc;
+	hdlc->state.cisco.timer.data = (unsigned long)dev;
 	add_timer(&hdlc->state.cisco.timer);
 }
 
 
 
-static void cisco_stop(hdlc_device *hdlc)
+static void cisco_stop(struct net_device *dev)
 {
-	del_timer_sync(&hdlc->state.cisco.timer);
-	if (netif_carrier_ok(&hdlc->netdev))
-		netif_carrier_off(&hdlc->netdev);
+	del_timer_sync(&dev_to_hdlc(dev)->state.cisco.timer);
+	if (netif_carrier_ok(dev))
+		netif_carrier_off(dev);
 }
 
 
 
-int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	cisco_proto *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco;
 	const size_t size = sizeof(cisco_proto);
 	cisco_proto new_settings;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
@@ -295,7 +297,7 @@
 		    new_settings.timeout < 2)
 			return -EINVAL;
 
-		result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
+		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
 
 		if (result)
 			return result;
diff -Nru a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
--- a/drivers/net/wan/hdlc_fr.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/hdlc_fr.c	Wed Feb 11 22:30:57 2004
@@ -146,8 +146,9 @@
 }
 
 
-static inline pvc_device* add_pvc(hdlc_device *hdlc, u16 dlci)
+static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc;
 
 	while (*pvc_p) {
@@ -164,7 +165,7 @@
 
 	memset(pvc, 0, sizeof(pvc_device));
 	pvc->dlci = dlci;
-	pvc->master = hdlc;
+	pvc->master = dev;
 	pvc->next = *pvc_p;	/* Put it in the chain */
 	*pvc_p = pvc;
 	return pvc;
@@ -311,15 +312,16 @@
 {
 	pvc_device *pvc = dev_to_pvc(dev);
 
-	if ((hdlc_to_dev(pvc->master)->flags & IFF_UP) == 0)
+	if ((pvc->master->flags & IFF_UP) == 0)
 		return -EIO;  /* Master must be UP in order to activate PVC */
 
 	if (pvc->open_count++ == 0) {
-		if (pvc->master->state.fr.settings.lmi == LMI_NONE)
-			pvc->state.active = pvc->master->carrier;
+		hdlc_device *hdlc = dev_to_hdlc(pvc->master);
+		if (hdlc->state.fr.settings.lmi == LMI_NONE)
+			pvc->state.active = hdlc->carrier;
 
 		pvc_carrier(pvc->state.active, pvc);
-		pvc->master->state.fr.dce_changed = 1;
+		hdlc->state.fr.dce_changed = 1;
 	}
 	return 0;
 }
@@ -331,11 +333,12 @@
 	pvc_device *pvc = dev_to_pvc(dev);
 
 	if (--pvc->open_count == 0) {
-		if (pvc->master->state.fr.settings.lmi == LMI_NONE)
+		hdlc_device *hdlc = dev_to_hdlc(pvc->master);
+		if (hdlc->state.fr.settings.lmi == LMI_NONE)
 			pvc->state.active = 0;
 
-		if (pvc->master->state.fr.settings.dce) {
-			pvc->master->state.fr.dce_changed = 1;
+		if (hdlc->state.fr.settings.dce) {
+			hdlc->state.fr.dce_changed = 1;
 			pvc->state.active = 0;
 		}
 	}
@@ -362,7 +365,7 @@
 		}
 
 		info.dlci = pvc->dlci;
-		memcpy(info.master, hdlc_to_name(pvc->master), IFNAMSIZ);
+		memcpy(info.master, pvc->master->name, IFNAMSIZ);
 		if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info,
 				 &info, sizeof(info)))
 			return -EFAULT;
@@ -375,8 +378,7 @@
 
 static inline struct net_device_stats *pvc_get_stats(struct net_device *dev)
 {
-	return (struct net_device_stats *)
-		((char *)dev + sizeof(struct net_device));
+	return netdev_priv(dev);
 }
 
 
@@ -408,7 +410,7 @@
 			stats->tx_packets++;
 			if (pvc->state.fecn) /* TX Congestion counter */
 				stats->tx_compressed++;
-			skb->dev = hdlc_to_dev(pvc->master);
+			skb->dev = pvc->master;
 			dev_queue_xmit(skb);
 			return 0;
 		}
@@ -434,7 +436,7 @@
 static inline void fr_log_dlci_active(pvc_device *pvc)
 {
 	printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
-	       hdlc_to_name(pvc->master),
+	       pvc->master->name,
 	       pvc->dlci,
 	       pvc->main ? pvc->main->name : "",
 	       pvc->main && pvc->ether ? " " : "",
@@ -454,8 +456,9 @@
 
 
 
-static void fr_lmi_send(hdlc_device *hdlc, int fullrep)
+static void fr_lmi_send(struct net_device *dev, int fullrep)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	struct sk_buff *skb;
 	pvc_device *pvc = hdlc->state.fr.first_pvc;
 	int len = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH
@@ -468,7 +471,7 @@
 		len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
 		if (len > HDLC_MAX_MRU) {
 			printk(KERN_WARNING "%s: Too many PVCs while sending "
-			       "LMI full report\n", hdlc_to_name(hdlc));
+			       "LMI full report\n", dev->name);
 			return;
 		}
 	}
@@ -476,7 +479,7 @@
 	skb = dev_alloc_skb(len);
 	if (!skb) {
 		printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n",
-		       hdlc_to_name(hdlc));
+		       dev->name);
 		return;
 	}
 	memset(skb->data, 0, len);
@@ -529,7 +532,7 @@
 
 	skb_put(skb, i);
 	skb->priority = TC_PRIO_CONTROL;
-	skb->dev = hdlc_to_dev(hdlc);
+	skb->dev = dev;
 	skb->nh.raw = skb->data;
 
 	dev_queue_xmit(skb);
@@ -537,14 +540,15 @@
 
 
 
-static void fr_set_link_state(int reliable, hdlc_device *hdlc)
+static void fr_set_link_state(int reliable, struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pvc_device *pvc = hdlc->state.fr.first_pvc;
 
 	hdlc->state.fr.reliable = reliable;
 	if (reliable) {
-		if (!netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_on(&hdlc->netdev);
+		if (!netif_carrier_ok(dev))
+			netif_carrier_on(dev);
 
 		hdlc->state.fr.n391cnt = 0; /* Request full status */
 		hdlc->state.fr.dce_changed = 1;
@@ -558,8 +562,8 @@
 			}
 		}
 	} else {
-		if (netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_off(&hdlc->netdev);
+		if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
 
 		while (pvc) {		/* Deactivate all PVCs */
 			pvc_carrier(0, pvc);
@@ -574,7 +578,8 @@
 
 static void fr_timer(unsigned long arg)
 {
-	hdlc_device *hdlc = (hdlc_device*)arg;
+	struct net_device *dev = (struct net_device *)arg;
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int i, cnt = 0, reliable;
 	u32 list;
 
@@ -586,7 +591,7 @@
 		if (hdlc->state.fr.request) {
 			if (hdlc->state.fr.reliable)
 				printk(KERN_INFO "%s: No LMI status reply "
-				       "received\n", hdlc_to_name(hdlc));
+				       "received\n", dev->name);
 			hdlc->state.fr.last_errors |= 1;
 		}
 
@@ -598,9 +603,9 @@
 	}
 
 	if (hdlc->state.fr.reliable != reliable) {
-		printk(KERN_INFO "%s: Link %sreliable\n", hdlc_to_name(hdlc),
+		printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
 		       reliable ? "" : "un");
-		fr_set_link_state(reliable, hdlc);
+		fr_set_link_state(reliable, dev);
 	}
 
 	if (hdlc->state.fr.settings.dce)
@@ -610,7 +615,7 @@
 		if (hdlc->state.fr.n391cnt)
 			hdlc->state.fr.n391cnt--;
 
-		fr_lmi_send(hdlc, hdlc->state.fr.n391cnt == 0);
+		fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0);
 
 		hdlc->state.fr.request = 1;
 		hdlc->state.fr.timer.expires = jiffies +
@@ -624,8 +629,9 @@
 
 
 
-static int fr_lmi_recv(hdlc_device *hdlc, struct sk_buff *skb)
+static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int stat_len;
 	pvc_device *pvc;
 	int reptype = -1, error, no_ram;
@@ -634,14 +640,14 @@
 
 	if (skb->len < ((hdlc->state.fr.settings.lmi == LMI_ANSI)
 			? LMI_ANSI_LENGTH : LMI_LENGTH)) {
-		printk(KERN_INFO "%s: Short LMI frame\n", hdlc_to_name(hdlc));
+		printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
 		return 1;
 	}
 
 	if (skb->data[5] != (!hdlc->state.fr.settings.dce ?
 			     LMI_STATUS : LMI_STATUS_ENQUIRY)) {
 		printk(KERN_INFO "%s: LMI msgtype=%x, Not LMI status %s\n",
-		       hdlc_to_name(hdlc), skb->data[2],
+		       dev->name, skb->data[2],
 		       hdlc->state.fr.settings.dce ? "enquiry" : "reply");
 		return 1;
 	}
@@ -652,7 +658,7 @@
 	    ((hdlc->state.fr.settings.lmi == LMI_CCITT)
 	     ? LMI_CCITT_REPTYPE : LMI_REPTYPE)) {
 		printk(KERN_INFO "%s: Not a report type=%x\n",
-		       hdlc_to_name(hdlc), skb->data[i]);
+		       dev->name, skb->data[i]);
 		return 1;
 	}
 	i++;
@@ -665,7 +671,7 @@
 	    ((hdlc->state.fr.settings.lmi == LMI_CCITT)
 	     ? LMI_CCITT_ALIVE : LMI_ALIVE)) {
 		printk(KERN_INFO "%s: Unsupported status element=%x\n",
-		       hdlc_to_name(hdlc), skb->data[i]);
+		       dev->name, skb->data[i]);
 		return 1;
 	}
 	i++;
@@ -680,7 +686,7 @@
 	if (hdlc->state.fr.settings.dce) {
 		if (reptype != LMI_FULLREP && reptype != LMI_INTEGRITY) {
 			printk(KERN_INFO "%s: Unsupported report type=%x\n",
-			       hdlc_to_name(hdlc), reptype);
+			       dev->name, reptype);
 			return 1;
 		}
 	}
@@ -716,7 +722,7 @@
 			hdlc->state.fr.dce_changed = 0;
 		}
 
-		fr_lmi_send(hdlc, reptype == LMI_FULLREP ? 1 : 0);
+		fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
 		return 0;
 	}
 
@@ -741,26 +747,26 @@
 		if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT)
 				     ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) {
 			printk(KERN_WARNING "%s: Invalid PVCSTAT ID: %x\n",
-			       hdlc_to_name(hdlc), skb->data[i]);
+			       dev->name, skb->data[i]);
 			return 1;
 		}
 		i++;
 
 		if (skb->data[i] != stat_len) {
 			printk(KERN_WARNING "%s: Invalid PVCSTAT length: %x\n",
-			       hdlc_to_name(hdlc), skb->data[i]);
+			       dev->name, skb->data[i]);
 			return 1;
 		}
 		i++;
 
 		dlci = status_to_dlci(skb->data + i, &active, &new);
 
-		pvc = add_pvc(hdlc, dlci);
+		pvc = add_pvc(dev, dlci);
 
 		if (!pvc && !no_ram) {
 			printk(KERN_WARNING
 			       "%s: Memory squeeze on fr_lmi_recv()\n",
-			       hdlc_to_name(hdlc));
+			       dev->name);
 			no_ram = 1;
 		}
 
@@ -802,7 +808,8 @@
 
 static int fr_rx(struct sk_buff *skb)
 {
-	hdlc_device *hdlc = dev_to_hdlc(skb->dev);
+	struct net_device *ndev = skb->dev;
+	hdlc_device *hdlc = dev_to_hdlc(ndev);
 	fr_hdr *fh = (fr_hdr*)skb->data;
 	u8 *data = skb->data;
 	u16 dlci;
@@ -819,7 +826,7 @@
 			goto rx_error; /* LMI packet with no LMI? */
 
 		if (data[3] == LMI_PROTO) {
-			if (fr_lmi_recv(hdlc, skb))
+			if (fr_lmi_recv(ndev, skb))
 				goto rx_error;
 			else {
 				/* No request pending */
@@ -831,7 +838,7 @@
 		}
 
 		printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
-		       hdlc_to_name(hdlc));
+		       ndev->name);
 		goto rx_error;
 	}
 
@@ -839,7 +846,7 @@
 	if (!pvc) {
 #ifdef DEBUG_PKT
 		printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
-		       hdlc_to_name(hdlc), dlci);
+		       ndev->name, dlci);
 #endif
 		dev_kfree_skb_any(skb);
 		return NET_RX_DROP;
@@ -847,7 +854,7 @@
 
 	if (pvc->state.fecn != fh->fecn) {
 #ifdef DEBUG_ECN
-		printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", hdlc_to_name(pvc),
+		printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name,
 		       dlci, fh->fecn ? "N" : "FF");
 #endif
 		pvc->state.fecn ^= 1;
@@ -855,7 +862,7 @@
 
 	if (pvc->state.becn != fh->becn) {
 #ifdef DEBUG_ECN
-		printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", hdlc_to_name(pvc),
+		printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name,
 		       dlci, fh->becn ? "N" : "FF");
 #endif
 		pvc->state.becn ^= 1;
@@ -899,13 +906,13 @@
 
 		default:
 			printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
-			       "PID=%x\n", hdlc_to_name(hdlc), oui, pid);
+			       "PID=%x\n", ndev->name, oui, pid);
 			dev_kfree_skb_any(skb);
 			return NET_RX_DROP;
 		}
 	} else {
 		printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
-		       "length = %i\n", hdlc_to_name(hdlc), data[3], skb->len);
+		       "length = %i\n", ndev->name, data[3], skb->len);
 		dev_kfree_skb_any(skb);
 		return NET_RX_DROP;
 	}
@@ -932,14 +939,15 @@
 
 
 
-static void fr_start(hdlc_device *hdlc)
+static void fr_start(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "fr_start\n");
 #endif
 	if (hdlc->state.fr.settings.lmi != LMI_NONE) {
-		if (netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_off(&hdlc->netdev);
+		if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
 		hdlc->state.fr.last_poll = 0;
 		hdlc->state.fr.reliable = 0;
 		hdlc->state.fr.dce_changed = 1;
@@ -953,28 +961,30 @@
 		/* First poll after 1 s */
 		hdlc->state.fr.timer.expires = jiffies + HZ;
 		hdlc->state.fr.timer.function = fr_timer;
-		hdlc->state.fr.timer.data = (unsigned long)hdlc;
+		hdlc->state.fr.timer.data = (unsigned long)dev;
 		add_timer(&hdlc->state.fr.timer);
 	} else
-		fr_set_link_state(1, hdlc);
+		fr_set_link_state(1, dev);
 }
 
 
 
-static void fr_stop(hdlc_device *hdlc)
+static void fr_stop(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "fr_stop\n");
 #endif
 	if (hdlc->state.fr.settings.lmi != LMI_NONE)
 		del_timer_sync(&hdlc->state.fr.timer);
-	fr_set_link_state(0, hdlc);
+	fr_set_link_state(0, dev);
 }
 
 
 
-static void fr_close(hdlc_device *hdlc)
+static void fr_close(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pvc_device *pvc = hdlc->state.fr.first_pvc;
 
 	while (pvc) {		/* Shutdown all PVCs for this FRAD */
@@ -986,10 +996,17 @@
 	}
 }
 
+static void dlci_setup(struct net_device *dev)
+{
+	dev->type = ARPHRD_DLCI;
+	dev->flags = IFF_POINTOPOINT;
+	dev->hard_header_len = 10;
+	dev->addr_len = 2;
+}
 
-
-static int fr_add_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
+static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
 {
+	hdlc_device *hdlc = dev_to_hdlc(master);
 	pvc_device *pvc = NULL;
 	struct net_device *dev;
 	int result, used;
@@ -998,9 +1015,9 @@
 	if (type == ARPHRD_ETHER)
 		prefix = "pvceth%d";
 
-	if ((pvc = add_pvc(hdlc, dlci)) == NULL) {
+	if ((pvc = add_pvc(master, dlci)) == NULL) {
 		printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
-		       hdlc_to_name(hdlc));
+		       master->name);
 		return -ENOBUFS;
 	}
 
@@ -1009,26 +1026,24 @@
 
 	used = pvc_is_used(pvc);
 
-	dev = kmalloc(sizeof(struct net_device) +
-		      sizeof(struct net_device_stats), GFP_KERNEL);
+	if (type == ARPHRD_ETHER)
+		dev = alloc_netdev(sizeof(struct net_device_stats),
+				   "pvceth%d", ether_setup);
+	else
+		dev = alloc_netdev(sizeof(struct net_device_stats),
+				   "pvc%d", dlci_setup);
+
 	if (!dev) {
 		printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
-		       hdlc_to_name(hdlc));
+		       master->name);
 		delete_unused_pvcs(hdlc);
 		return -ENOBUFS;
 	}
-	memset(dev, 0, sizeof(struct net_device) +
-	       sizeof(struct net_device_stats));
 
 	if (type == ARPHRD_ETHER) {
-		ether_setup(dev);
 		memcpy(dev->dev_addr, "\x00\x01", 2);
                 get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2);
 	} else {
-		dev->type = ARPHRD_DLCI;
-		dev->flags = IFF_POINTOPOINT;
-		dev->hard_header_len = 10;
-		dev->addr_len = 2;
 		*(u16*)dev->dev_addr = htons(dlci);
 		dlci_to_q922(dev->broadcast, dlci);
 	}
@@ -1042,15 +1057,15 @@
 	dev->tx_queue_len = 0;
 	dev->priv = pvc;
 
-	result = dev_alloc_name(dev, prefix);
+	result = dev_alloc_name(dev, dev->name);
 	if (result < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		delete_unused_pvcs(hdlc);
 		return result;
 	}
 
 	if (register_netdevice(dev) != 0) {
-		kfree(dev);
+		free_netdev(dev);
 		delete_unused_pvcs(hdlc);
 		return -EIO;
 	}
@@ -1080,7 +1095,7 @@
 	if (dev->flags & IFF_UP)
 		return -EBUSY;		/* PVC in use */
 
-	unregister_netdevice(dev); /* the destructor will kfree(dev) */
+	unregister_netdevice(dev); /* the destructor will free_netdev(dev) */
 	*get_dev_p(pvc, type) = NULL;
 
 	if (!pvc_is_used(pvc)) {
@@ -1104,7 +1119,8 @@
 
 	while (pvc) {
 		pvc_device *next = pvc->next;
-		if (pvc->main)	/* the destructor will kfree(main + ether) */
+		/* destructors will free_netdev() main and ether */
+		if (pvc->main)
 			unregister_netdevice(pvc->main);
 
 		if (pvc->ether)
@@ -1117,12 +1133,12 @@
 
 
 
-int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	fr_proto *fr_s = ifr->ifr_settings.ifs_ifsu.fr;
 	const size_t size = sizeof(fr_proto);
 	fr_proto new_settings;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	fr_proto_pvc pvc;
 	int result;
 
@@ -1163,7 +1179,7 @@
 		     new_settings.dce != 1))
 			return -EINVAL;
 
-		result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
+		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
 		if (result)
 			return result;
 
@@ -1210,7 +1226,7 @@
 
 		if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC ||
 		    ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC)
-			return fr_add_pvc(hdlc, pvc.dlci, result);
+			return fr_add_pvc(dev, pvc.dlci, result);
 		else
 			return fr_del_pvc(hdlc, pvc.dlci, result);
 	}
diff -Nru a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
--- a/drivers/net/wan/hdlc_generic.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/wan/hdlc_generic.c	Wed Feb 11 22:30:56 2004
@@ -50,7 +50,7 @@
 
 static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
 {
-	return &dev_to_hdlc(dev)->stats;
+	return hdlc_stats(dev);
 }
 
 
@@ -69,8 +69,9 @@
 
 
 
-void hdlc_set_carrier(int on, hdlc_device *hdlc)
+void hdlc_set_carrier(int on, struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	on = on ? 1 : 0;
 
 #ifdef DEBUG_LINK
@@ -82,7 +83,7 @@
 	if (hdlc->carrier == on)
 		goto carrier_exit; /* no change in DCD line level */
 
-	printk(KERN_INFO "%s: carrier %s\n", hdlc_to_name(hdlc),
+	printk(KERN_INFO "%s: carrier %s\n", dev->name,
 	       on ? "ON" : "off");
 	hdlc->carrier = on;
 
@@ -91,15 +92,15 @@
 
 	if (hdlc->carrier) {
 		if (hdlc->proto.start)
-			hdlc->proto.start(hdlc);
-		else if (!netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_on(&hdlc->netdev);
+			hdlc->proto.start(dev);
+		else if (!netif_carrier_ok(dev))
+			netif_carrier_on(dev);
 
 	} else { /* no carrier */
 		if (hdlc->proto.stop)
-			hdlc->proto.stop(hdlc);
-		else if (netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_off(&hdlc->netdev);
+			hdlc->proto.stop(dev);
+		else if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
 	}
 
  carrier_exit:
@@ -108,8 +109,9 @@
 
 
 /* Must be called by hardware driver when HDLC device is being opened */
-int hdlc_open(hdlc_device *hdlc)
+int hdlc_open(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "hdlc_open carrier %i open %i\n",
 	       hdlc->carrier, hdlc->open);
@@ -119,7 +121,7 @@
 		return -ENOSYS;	/* no protocol attached */
 
 	if (hdlc->proto.open) {
-		int result = hdlc->proto.open(hdlc);
+		int result = hdlc->proto.open(dev);
 		if (result)
 			return result;
 	}
@@ -128,12 +130,12 @@
 
 	if (hdlc->carrier) {
 		if (hdlc->proto.start)
-			hdlc->proto.start(hdlc);
-		else if (!netif_carrier_ok(&hdlc->netdev))
-			netif_carrier_on(&hdlc->netdev);
+			hdlc->proto.start(dev);
+		else if (!netif_carrier_ok(dev))
+			netif_carrier_on(dev);
 
-	} else if (netif_carrier_ok(&hdlc->netdev))
-		netif_carrier_off(&hdlc->netdev);
+	} else if (netif_carrier_ok(dev))
+		netif_carrier_off(dev);
 
 	hdlc->open = 1;
 
@@ -144,8 +146,9 @@
 
 
 /* Must be called by hardware driver when HDLC device is being closed */
-void hdlc_close(hdlc_device *hdlc)
+void hdlc_close(struct net_device *dev)
 {
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "hdlc_close carrier %i open %i\n",
 	       hdlc->carrier, hdlc->open);
@@ -155,38 +158,38 @@
 
 	hdlc->open = 0;
 	if (hdlc->carrier && hdlc->proto.stop)
-		hdlc->proto.stop(hdlc);
+		hdlc->proto.stop(dev);
 
 	spin_unlock_irq(&hdlc->state_lock);
 
 	if (hdlc->proto.close)
-		hdlc->proto.close(hdlc);
+		hdlc->proto.close(dev);
 }
 
 
 
 #ifndef CONFIG_HDLC_RAW
-#define hdlc_raw_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_raw_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_RAW_ETH
-#define hdlc_raw_eth_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_raw_eth_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_PPP
-#define hdlc_ppp_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_ppp_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_CISCO
-#define hdlc_cisco_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_cisco_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_FR
-#define hdlc_fr_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_fr_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 #ifndef CONFIG_HDLC_X25
-#define hdlc_x25_ioctl(hdlc, ifr)	-ENOSYS
+#define hdlc_x25_ioctl(dev, ifr)	-ENOSYS
 #endif
 
 
@@ -213,22 +216,49 @@
 	}
 
 	switch(proto) {
-	case IF_PROTO_HDLC:	return hdlc_raw_ioctl(hdlc, ifr);
-	case IF_PROTO_HDLC_ETH:	return hdlc_raw_eth_ioctl(hdlc, ifr);
-	case IF_PROTO_PPP:	return hdlc_ppp_ioctl(hdlc, ifr);
-	case IF_PROTO_CISCO:	return hdlc_cisco_ioctl(hdlc, ifr);
-	case IF_PROTO_FR:	return hdlc_fr_ioctl(hdlc, ifr);
-	case IF_PROTO_X25:	return hdlc_x25_ioctl(hdlc, ifr);
+	case IF_PROTO_HDLC:	return hdlc_raw_ioctl(dev, ifr);
+	case IF_PROTO_HDLC_ETH:	return hdlc_raw_eth_ioctl(dev, ifr);
+	case IF_PROTO_PPP:	return hdlc_ppp_ioctl(dev, ifr);
+	case IF_PROTO_CISCO:	return hdlc_cisco_ioctl(dev, ifr);
+	case IF_PROTO_FR:	return hdlc_fr_ioctl(dev, ifr);
+	case IF_PROTO_X25:	return hdlc_x25_ioctl(dev, ifr);
 	default:		return -EINVAL;
 	}
 }
 
+static void hdlc_setup(struct net_device *dev)
+{
+	hdlc_device *hdlc = dev_to_hdlc(dev);
+
+	dev->get_stats = hdlc_get_stats;
+	dev->change_mtu = hdlc_change_mtu;
+	dev->mtu = HDLC_MAX_MTU;
+
+	dev->type = ARPHRD_RAWHDLC;
+	dev->hard_header_len = 16;
+
+	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+
+	hdlc->proto.id = -1;
+	hdlc->proto.detach = NULL;
+	hdlc->carrier = 1;
+	hdlc->open = 0;
+	spin_lock_init(&hdlc->state_lock);
+}
 
+struct net_device *alloc_hdlcdev(void *priv)
+{
+	struct net_device *dev;
+	dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup);
+	if (dev)
+		dev_to_hdlc(dev)->priv = priv;
+	return dev;
+}
 
-int register_hdlc_device(hdlc_device *hdlc)
+int register_hdlc_device(struct net_device *dev)
 {
 	int result;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 
 	dev->get_stats = hdlc_get_stats;
 	dev->change_mtu = hdlc_change_mtu;
@@ -258,11 +288,11 @@
 
 
 
-void unregister_hdlc_device(hdlc_device *hdlc)
+void unregister_hdlc_device(struct net_device *dev)
 {
 	rtnl_lock();
-	hdlc_proto_detach(hdlc);
-	unregister_netdevice(hdlc_to_dev(hdlc));
+	hdlc_proto_detach(dev_to_hdlc(dev));
+	unregister_netdevice(dev);
 	rtnl_unlock();
 }
 
@@ -276,6 +306,7 @@
 EXPORT_SYMBOL(hdlc_close);
 EXPORT_SYMBOL(hdlc_set_carrier);
 EXPORT_SYMBOL(hdlc_ioctl);
+EXPORT_SYMBOL(alloc_hdlcdev);
 EXPORT_SYMBOL(register_hdlc_device);
 EXPORT_SYMBOL(unregister_hdlc_device);
 
diff -Nru a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
--- a/drivers/net/wan/hdlc_ppp.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/wan/hdlc_ppp.c	Wed Feb 11 22:30:56 2004
@@ -24,9 +24,9 @@
 #include <linux/hdlc.h>
 
 
-static int ppp_open(hdlc_device *hdlc)
+static int ppp_open(struct net_device *dev)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	void *old_ioctl;
 	int result;
 
@@ -52,9 +52,9 @@
 
 
 
-static void ppp_close(hdlc_device *hdlc)
+static void ppp_close(struct net_device *dev)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 
 	sppp_close(dev);
 	sppp_detach(dev);
@@ -74,9 +74,9 @@
 
 
 
-int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
@@ -93,7 +93,7 @@
 
 		/* no settable parameters */
 
-		result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
+		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
 		if (result)
 			return result;
 
diff -Nru a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c
--- a/drivers/net/wan/hdlc_raw.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/hdlc_raw.c	Wed Feb 11 22:30:57 2004
@@ -32,12 +32,12 @@
 
 
 
-int hdlc_raw_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
 	const size_t size = sizeof(raw_hdlc_proto);
 	raw_hdlc_proto new_settings;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
@@ -67,7 +67,7 @@
 		if (new_settings.parity == PARITY_DEFAULT)
 			new_settings.parity = PARITY_CRC16_PR1_CCITT;
 
-		result = hdlc->attach(hdlc, new_settings.encoding,
+		result = hdlc->attach(dev, new_settings.encoding,
 				      new_settings.parity);
 		if (result)
 			return result;
diff -Nru a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c
--- a/drivers/net/wan/hdlc_raw_eth.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/hdlc_raw_eth.c	Wed Feb 11 22:30:57 2004
@@ -33,7 +33,7 @@
 		int len = skb->len;
 		if (skb_tailroom(skb) < pad)
 			if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) {
-				dev_to_hdlc(dev)->stats.tx_dropped++;
+				hdlc_stats(dev)->tx_dropped++;
 				dev_kfree_skb(skb);
 				return 0;
 			}
@@ -44,12 +44,12 @@
 }
 
 
-int hdlc_raw_eth_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
 	const size_t size = sizeof(raw_hdlc_proto);
 	raw_hdlc_proto new_settings;
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 	void *old_ch_mtu;
 	int old_qlen;
@@ -81,7 +81,7 @@
 		if (new_settings.parity == PARITY_DEFAULT)
 			new_settings.parity = PARITY_CRC16_PR1_CCITT;
 
-		result = hdlc->attach(hdlc, new_settings.encoding,
+		result = hdlc->attach(dev, new_settings.encoding,
 				      new_settings.parity);
 		if (result)
 			return result;
diff -Nru a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
--- a/drivers/net/wan/hdlc_x25.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/hdlc_x25.c	Wed Feb 11 22:30:57 2004
@@ -25,21 +25,20 @@
 
 /* These functions are callbacks called by LAPB layer */
 
-static void x25_connect_disconnect(void *token, int reason, int code)
+static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
 {
-	hdlc_device *hdlc = token;
 	struct sk_buff *skb;
 	unsigned char *ptr;
 
 	if ((skb = dev_alloc_skb(1)) == NULL) {
-		printk(KERN_ERR "%s: out of memory\n", hdlc_to_name(hdlc));
+		printk(KERN_ERR "%s: out of memory\n", dev->name);
 		return;
 	}
 
 	ptr = skb_put(skb, 1);
 	*ptr = code;
 
-	skb->dev = hdlc_to_dev(hdlc);
+	skb->dev = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -49,23 +48,22 @@
 
 
 
-static void x25_connected(void *token, int reason)
+static void x25_connected(struct net_device *dev, int reason)
 {
-	x25_connect_disconnect(token, reason, 1);
+	x25_connect_disconnect(dev, reason, 1);
 }
 
 
 
-static void x25_disconnected(void *token, int reason)
+static void x25_disconnected(struct net_device *dev, int reason)
 {
-	x25_connect_disconnect(token, reason, 2);
+	x25_connect_disconnect(dev, reason, 2);
 }
 
 
 
-static int x25_data_indication(void *token, struct sk_buff *skb)
+static int x25_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
-	hdlc_device *hdlc = token;
 	unsigned char *ptr;
 
 	skb_push(skb, 1);
@@ -76,7 +74,7 @@
 	ptr  = skb->data;
 	*ptr = 0;
 
-	skb->dev = hdlc_to_dev(hdlc);
+	skb->dev = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -86,17 +84,16 @@
 
 
 
-static void x25_data_transmit(void *token, struct sk_buff *skb)
+static void x25_data_transmit(struct net_device *dev, struct sk_buff *skb)
 {
-	hdlc_device *hdlc = token;
-	hdlc->xmit(skb, hdlc_to_dev(hdlc)); /* Ignore return value :-( */
+	hdlc_device *hdlc = dev_to_hdlc(dev);
+	hdlc->xmit(skb, dev); /* Ignore return value :-( */
 }
 
 
 
 static int x25_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 
@@ -104,31 +101,31 @@
 	switch (skb->data[0]) {
 	case 0:		/* Data to be transmitted */
 		skb_pull(skb, 1);
-		if ((result = lapb_data_request(hdlc, skb)) != LAPB_OK)
+		if ((result = lapb_data_request(dev, skb)) != LAPB_OK)
 			dev_kfree_skb(skb);
 		return 0;
 
 	case 1:
-		if ((result = lapb_connect_request(hdlc))!= LAPB_OK) {
+		if ((result = lapb_connect_request(dev))!= LAPB_OK) {
 			if (result == LAPB_CONNECTED)
 				/* Send connect confirm. msg to level 3 */
-				x25_connected(hdlc, 0);
+				x25_connected(dev, 0);
 			else
 				printk(KERN_ERR "%s: LAPB connect request "
 				       "failed, error code = %i\n",
-				       hdlc_to_name(hdlc), result);
+				       dev->name, result);
 		}
 		break;
 
 	case 2:
-		if ((result = lapb_disconnect_request(hdlc)) != LAPB_OK) {
+		if ((result = lapb_disconnect_request(dev)) != LAPB_OK) {
 			if (result == LAPB_NOTCONNECTED)
 				/* Send disconnect confirm. msg to level 3 */
-				x25_disconnected(hdlc, 0);
+				x25_disconnected(dev, 0);
 			else
 				printk(KERN_ERR "%s: LAPB disconnect request "
 				       "failed, error code = %i\n",
-				       hdlc_to_name(hdlc), result);
+				       dev->name, result);
 		}
 		break;
 
@@ -142,7 +139,7 @@
 
 
 
-static int x25_open(hdlc_device *hdlc)
+static int x25_open(struct net_device *dev)
 {
 	struct lapb_register_struct cb;
 	int result;
@@ -154,7 +151,7 @@
 	cb.data_indication = x25_data_indication;
 	cb.data_transmit = x25_data_transmit;
 
-	result = lapb_register(hdlc, &cb);
+	result = lapb_register(dev, &cb);
 	if (result != LAPB_OK)
 		return result;
 	return 0;
@@ -162,9 +159,9 @@
 
 
 
-static void x25_close(hdlc_device *hdlc)
+static void x25_close(struct net_device *dev)
 {
-	lapb_unregister(hdlc);
+	lapb_unregister(dev);
 }
 
 
@@ -178,7 +175,7 @@
 		return NET_RX_DROP;
 	}
 
-	if (lapb_data_received(hdlc, skb) == LAPB_OK)
+	if (lapb_data_received(skb->dev, skb) == LAPB_OK)
 		return NET_RX_SUCCESS;
 
 	hdlc->stats.rx_errors++;
@@ -188,9 +185,9 @@
 
 
 
-int hdlc_x25_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
+int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
@@ -205,7 +202,7 @@
 		if(dev->flags & IFF_UP)
 			return -EBUSY;
 
-		result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
+		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
 		if (result)
 			return result;
 
diff -Nru a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
--- a/drivers/net/wan/hostess_sv11.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/hostess_sv11.c	Wed Feb 11 22:30:57 2004
@@ -122,7 +122,6 @@
 	 */
 
 	netif_start_queue(d);
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -154,7 +153,6 @@
 			z8530_sync_txdma_close(d, &sv11->sync.chanA);
 			break;
 	}
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -203,6 +201,16 @@
 	return 0;
 }
 
+static void sv11_setup(struct net_device *dev)
+{	
+	dev->open = hostess_open;
+	dev->stop = hostess_close;
+	dev->hard_start_xmit = hostess_queue_xmit;
+	dev->get_stats = hostess_get_stats;
+	dev->do_ioctl = hostess_ioctl;
+	dev->neigh_setup = hostess_neigh_setup_dev;
+}
+
 /*
  *	Description block for a Comtrol Hostess SV11 card
  */
@@ -229,10 +237,12 @@
 	memset(sv, 0, sizeof(*sv));
 	sv->if_ptr=&sv->netdev;
 	
-	sv->netdev.dev=(struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	sv->netdev.dev = alloc_netdev(0, "hdlc%d", sv11_setup);
 	if(!sv->netdev.dev)
 		goto fail2;
 
+	SET_MODULE_OWNER(sv->netdev.dev);
+
 	dev=&sv->sync;
 	
 	/*
@@ -326,23 +336,14 @@
 		d->base_addr = iobase;
 		d->irq = irq;
 		d->priv = sv;
-		d->init = NULL;
-		
-		d->open = hostess_open;
-		d->stop = hostess_close;
-		d->hard_start_xmit = hostess_queue_xmit;
-		d->get_stats = hostess_get_stats;
-		d->set_multicast_list = NULL;
-		d->do_ioctl = hostess_ioctl;
-		d->neigh_setup = hostess_neigh_setup_dev;
-		d->set_mac_address = NULL;
 		
 		if(register_netdev(d))
 		{
 			printk(KERN_ERR "%s: unable to register device.\n",
 				d->name);
-			goto fail;
-		}				
+			sppp_detach(d);
+			goto dmafail2;
+		}
 
 		z8530_describe(dev, "I/O", iobase);
 		dev->active=1;
@@ -357,7 +358,7 @@
 fail:
 	free_irq(irq, dev);
 fail1:
-	kfree(sv->netdev.dev);
+	free_netdev(sv->netdev.dev);
 fail2:
 	kfree(sv);
 fail3:
@@ -368,8 +369,8 @@
 static void sv11_shutdown(struct sv11_device *dev)
 {
 	sppp_detach(dev->netdev.dev);
-	z8530_shutdown(&dev->sync);
 	unregister_netdev(dev->netdev.dev);
+	z8530_shutdown(&dev->sync);
 	free_irq(dev->sync.irq, dev);
 	if(dma)
 	{
@@ -378,6 +379,8 @@
 		free_dma(dev->sync.chanA.txdma);
 	}
 	release_region(dev->sync.chanA.ctrlio-1, 8);
+	free_netdev(dev->netdev.dev);
+	kfree(dev);
 }
 
 #ifdef MODULE
diff -Nru a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
--- a/drivers/net/wan/lapbether.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/lapbether.c	Wed Feb 11 22:30:57 2004
@@ -110,7 +110,7 @@
 	skb_pull(skb, 2);	/* Remove the length bytes */
 	skb_trim(skb, len);	/* Set the length of the data */
 
-	if ((err = lapb_data_received(lapbeth, skb)) != LAPB_OK) {
+	if ((err = lapb_data_received(lapbeth->axdev, skb)) != LAPB_OK) {
 		printk(KERN_DEBUG "lapbether: lapb_data_received err - %d\n", err);
 		goto drop_unlock;
 	}
@@ -125,9 +125,8 @@
 	return 0;
 }
 
-static int lapbeth_data_indication(void *token, struct sk_buff *skb)
+static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)token;
 	unsigned char *ptr;
 
 	skb_push(skb, 1);
@@ -138,7 +137,7 @@
 	ptr  = skb->data;
 	*ptr = 0x00;
 
-	skb->dev      = lapbeth->axdev;
+	skb->dev      = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw  = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -152,7 +151,6 @@
  */
 static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)dev->priv;
 	int err = -ENODEV;
 
 	/*
@@ -168,12 +166,12 @@
 		err = 0;
 		break;
 	case 0x01:
-		if ((err = lapb_connect_request(lapbeth)) != LAPB_OK)
+		if ((err = lapb_connect_request(dev)) != LAPB_OK)
 			printk(KERN_ERR "lapbeth: lapb_connect_request "
 			       "error: %d\n", err);
 		goto drop_ok;
 	case 0x02:
-		if ((err = lapb_disconnect_request(lapbeth)) != LAPB_OK)
+		if ((err = lapb_disconnect_request(dev)) != LAPB_OK)
 			printk(KERN_ERR "lapbeth: lapb_disconnect_request "
 			       "err: %d\n", err);
 		/* Fall thru */
@@ -183,7 +181,7 @@
 
 	skb_pull(skb, 1);
 
-	if ((err = lapb_data_request(lapbeth, skb)) != LAPB_OK) {
+	if ((err = lapb_data_request(dev, skb)) != LAPB_OK) {
 		printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
 		err = -ENOMEM;
 		goto drop;
@@ -198,9 +196,9 @@
 	goto out;
 }
 
-static void lapbeth_data_transmit(void *token, struct sk_buff *skb)
+static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)token;
+	struct lapbethdev *lapbeth = ndev->priv;
 	unsigned char *ptr;
 	struct net_device *dev;
 	int size = skb->len;
@@ -222,9 +220,8 @@
 	dev_queue_xmit(skb);
 }
 
-static void lapbeth_connected(void *token, int reason)
+static void lapbeth_connected(struct net_device *dev, int reason)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)token;
 	unsigned char *ptr;
 	struct sk_buff *skb = dev_alloc_skb(1);
 
@@ -236,7 +233,7 @@
 	ptr  = skb_put(skb, 1);
 	*ptr = 0x01;
 
-	skb->dev      = lapbeth->axdev;
+	skb->dev      = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw  = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -245,9 +242,8 @@
 	netif_rx(skb);
 }
 
-static void lapbeth_disconnected(void *token, int reason)
+static void lapbeth_disconnected(struct net_device *dev, int reason)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)token;
 	unsigned char *ptr;
 	struct sk_buff *skb = dev_alloc_skb(1);
 
@@ -259,7 +255,7 @@
 	ptr  = skb_put(skb, 1);
 	*ptr = 0x02;
 
-	skb->dev      = lapbeth->axdev;
+	skb->dev      = dev;
 	skb->protocol = htons(ETH_P_X25);
 	skb->mac.raw  = skb->data;
 	skb->pkt_type = PACKET_HOST;
@@ -303,11 +299,9 @@
  */
 static int lapbeth_open(struct net_device *dev)
 {
-	struct lapbethdev *lapbeth;
 	int err;
 
-	lapbeth = (struct lapbethdev *)dev->priv;
-	if ((err = lapb_register(lapbeth, &lapbeth_callbacks)) != LAPB_OK) {
+	if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) {
 		printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err);
 		return -ENODEV;
 	}
@@ -318,12 +312,11 @@
 
 static int lapbeth_close(struct net_device *dev)
 {
-	struct lapbethdev *lapbeth = (struct lapbethdev *)dev->priv;
 	int err;
 
 	netif_stop_queue(dev);
 
-	if ((err = lapb_unregister(lapbeth)) != LAPB_OK)
+	if ((err = lapb_unregister(dev)) != LAPB_OK)
 		printk(KERN_ERR "lapbeth: lapb_unregister error - %d\n", err);
 
 	return 0;
@@ -382,6 +375,7 @@
 	return rc;
 fail:
 	dev_put(dev);
+	free_netdev(ndev);
 	kfree(lapbeth);
 	goto out;
 }
diff -Nru a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
--- a/drivers/net/wan/n2.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/n2.c	Wed Feb 11 22:30:57 2004
@@ -92,7 +92,7 @@
 
 
 typedef struct port_s {
-	hdlc_device hdlc;	/* HDLC device struct - must be first */
+	struct net_device *dev;
 	struct card_s *card;
 	spinlock_t lock;	/* TX lock */
 	sync_serial_settings settings;
@@ -215,13 +215,12 @@
 
 static int n2_open(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	int io = port->card->io;
 	u8 mcr = inb(io + N2_MCR) | (port->phy_node ? TX422_PORT1:TX422_PORT0);
 	int result;
 
-	result = hdlc_open(hdlc);
+	result = hdlc_open(dev);
 	if (result)
 		return result;
 
@@ -230,7 +229,7 @@
 
 	outb(inb(io + N2_PCR) | PCR_ENWIN, io + N2_PCR); /* open window */
 	outb(inb(io + N2_PSR) | PSR_DMAEN, io + N2_PSR); /* enable dma */
-	sca_open(hdlc);
+	sca_open(dev);
 	n2_set_iface(port);
 	return 0;
 }
@@ -239,15 +238,14 @@
 
 static int n2_close(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	int io = port->card->io;
 	u8 mcr = inb(io+N2_MCR) | (port->phy_node ? TX422_PORT1 : TX422_PORT0);
 
-	sca_close(hdlc);
+	sca_close(dev);
 	mcr |= port->phy_node ? DTR_PORT1 : DTR_PORT0; /* set DTR OFF */
 	outb(mcr, io + N2_MCR);
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	return 0;
 }
 
@@ -257,12 +255,11 @@
 {
 	const size_t size = sizeof(sync_serial_settings);
 	sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 #ifdef DEBUG_RINGS
 	if (cmd == SIOCDEVPRIVATE) {
-		sca_dump_rings(hdlc);
+		sca_dump_rings(dev);
 		return 0;
 	}
 #endif
@@ -312,8 +309,10 @@
 	int cnt;
 
 	for (cnt = 0; cnt < 2; cnt++)
-		if (card->ports[cnt].card)
-			unregister_hdlc_device(&card->ports[cnt].hdlc);
+		if (card->ports[cnt].card) {
+			struct net_device *dev = port_to_dev(&card->ports[cnt]);
+			unregister_hdlc_device(dev);
+		}
 
 	if (card->irq)
 		free_irq(card->irq, card);
@@ -325,6 +324,10 @@
 
 	if (card->io)
 		release_region(card->io, N2_IOPORTS);
+	if (card->ports[0].dev)
+		free_netdev(card->ports[0].dev);
+	if (card->ports[1].dev)
+		free_netdev(card->ports[1].dev);
 	kfree(card);
 }
 
@@ -359,6 +362,14 @@
 	}
 	memset(card, 0, sizeof(card_t));
 
+	card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
+	card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
+	if (!card->ports[0].dev || !card->ports[1].dev) {
+		printk(KERN_ERR "n2: unable to allocate memory\n");
+		n2_destroy_card(card);
+		return -ENOMEM;
+	}
+
 	if (!request_region(io, N2_IOPORTS, devname)) {
 		printk(KERN_ERR "n2: I/O port region in use\n");
 		n2_destroy_card(card);
@@ -435,7 +446,8 @@
 	sca_init(card, 0);
 	for (cnt = 0; cnt < 2; cnt++) {
 		port_t *port = &card->ports[cnt];
-		struct net_device *dev = hdlc_to_dev(&port->hdlc);
+		struct net_device *dev = port_to_dev(port);
+		hdlc_device *hdlc = dev_to_hdlc(dev);
 
 		if ((cnt == 0 && !valid0) || (cnt == 1 && !valid1))
 			continue;
@@ -455,21 +467,22 @@
 		dev->do_ioctl = n2_ioctl;
 		dev->open = n2_open;
 		dev->stop = n2_close;
-		port->hdlc.attach = sca_attach;
-		port->hdlc.xmit = sca_xmit;
+		hdlc->attach = sca_attach;
+		hdlc->xmit = sca_xmit;
 		port->settings.clock_type = CLOCK_EXT;
+		port->card = card;
 
-		if (register_hdlc_device(&port->hdlc)) {
+		if (register_hdlc_device(dev)) {
 			printk(KERN_WARNING "n2: unable to register hdlc "
 			       "device\n");
+			port->card = NULL;
 			n2_destroy_card(card);
 			return -ENOBUFS;
 		}
-		port->card = card;
 		sca_init_sync_port(port); /* Set up SCA memory */
 
 		printk(KERN_INFO "%s: RISCom/N2 node %d\n",
-		       hdlc_to_name(&port->hdlc), port->phy_node);
+		       dev->name, port->phy_node);
 	}
 
 	*new_card = card;
diff -Nru a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h
--- a/drivers/net/wan/pc300.h	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/pc300.h	Wed Feb 11 22:30:57 2004
@@ -331,7 +331,7 @@
 	uclong line_off;
 #ifdef __KERNEL__
 	char name[16];
-	hdlc_device *hdlc;
+	struct net_device *dev;
 
 	void *private;
 	struct sk_buff *tx_skb;
@@ -483,7 +483,7 @@
 void tx_dma_stop(pc300_t *, int);
 void rx_dma_stop(pc300_t *, int);
 int cpc_queue_xmit(struct sk_buff *, struct net_device *);
-void cpc_net_rx(hdlc_device *);
+void cpc_net_rx(struct net_device *);
 void cpc_sca_status(pc300_t *, int);
 int cpc_change_mtu(struct net_device *, int);
 int cpc_ioctl(struct net_device *, struct ifreq *, int);
diff -Nru a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
--- a/drivers/net/wan/pc300_drv.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/pc300_drv.c	Wed Feb 11 22:30:57 2004
@@ -290,7 +290,7 @@
 static uclong detect_ram(pc300_t *);
 static void plx_init(pc300_t *);
 static void cpc_trace(struct net_device *, struct sk_buff *, char);
-static int cpc_attach(hdlc_device *, unsigned short, unsigned short);
+static int cpc_attach(struct net_device *, unsigned short, unsigned short);
 
 #ifdef CONFIG_PC300_MLPPP
 void cpc_tty_init(pc300dev_t * dev);
@@ -1774,7 +1774,7 @@
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	struct net_device_stats *stats = &d->hdlc->stats;
+	struct net_device_stats *stats = hdlc_stats(dev);
 	int ch = chan->channel;
 	uclong flags;
 	ucchar ilar;
@@ -1802,7 +1802,7 @@
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	struct net_device_stats *stats = &d->hdlc->stats;
+	struct net_device_stats *stats = hdlc_stats(dev);
 	int ch = chan->channel;
 	uclong flags;
 #ifdef PC300_DEBUG_TX
@@ -1880,13 +1880,12 @@
 	return 0;
 }
 
-void cpc_net_rx(hdlc_device * hdlc)
+void cpc_net_rx(struct net_device *dev)
 {
-	struct net_device *dev = hdlc_to_dev(hdlc);
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	struct net_device_stats *stats = &d->hdlc->stats;
+	struct net_device_stats *stats = hdlc_stats(dev);
 	int ch = chan->channel;
 #ifdef PC300_DEBUG_RX
 	int i;
@@ -1975,7 +1974,7 @@
 	pc300_t *card = (pc300_t *)chan->card; 
 	int ch = chan->channel; 
 	volatile pcsca_bd_t * ptdescr; 
-	struct net_device_stats *stats = &dev->hdlc->stats; 
+	struct net_device_stats *stats = hdlc_stats(dev->dev);
 
     /* Clean up descriptors from previous transmission */
 	ptdescr = (pcsca_bd_t *)(card->hw.rambase +
@@ -1999,7 +1998,7 @@
 	} else {
 #endif
 	/* Tell the upper layer we are ready to transmit more packets */
-		netif_wake_queue((struct net_device*)dev->hdlc);
+		netif_wake_queue(dev->dev);
 #ifdef CONFIG_PC300_MLPPP
 	}
 #endif
@@ -2017,8 +2016,8 @@
 		for (ch = 0; ch < card->hw.nchan; ch++) {
 			pc300ch_t *chan = &card->chan[ch];
 			pc300dev_t *d = &chan->d;
-			hdlc_device *hdlc = d->hdlc;
-			struct net_device *dev = hdlc_to_dev(hdlc);
+			struct net_device *dev = d->dev;
+			hdlc_device *hdlc = dev_to_hdlc(dev);
 
 			spin_lock(&card->card_lock);
 
@@ -2049,7 +2048,7 @@
 							if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
 								rx_dma_stop(card, ch);
 							}
-							cpc_net_rx(hdlc);
+							cpc_net_rx(dev);
 							/* Discard invalid frames */
 							hdlc->stats.rx_errors++;
 							hdlc->stats.rx_over_errors++;
@@ -2073,10 +2072,10 @@
 							/* verify if driver is TTY */
 							cpc_tty_receive(d);
 						} else {
-							cpc_net_rx(hdlc);
+							cpc_net_rx(dev);
 						}
 #else
-						cpc_net_rx(hdlc);
+						cpc_net_rx(dev);
 #endif
 						if (card->hw.type == PC300_TE) {
 							cpc_writeb(card->hw.falcbase +
@@ -2829,12 +2828,7 @@
 
 static struct net_device_stats *cpc_get_stats(struct net_device *dev)
 {
-	pc300dev_t *d = (pc300dev_t *) dev->priv;
-
-	if (d)
-		return &d->hdlc->stats;
-	else
-		return NULL;
+	return hdlc_stats(dev);
 }
 
 static int clock_rate_calc(uclong rate, uclong clock, int *br_io)
@@ -3075,10 +3069,9 @@
 	return 0;
 }
 
-static int cpc_attach(hdlc_device * hdlc, unsigned short encoding,
+static int cpc_attach(struct net_device *dev, unsigned short encoding,
 		      unsigned short parity)
 {
-	struct net_device * dev = hdlc_to_dev(hdlc);
 	pc300dev_t *d = (pc300dev_t *)dev->priv;
 	pc300ch_t *chan = (pc300ch_t *)d->chan;
 	pc300_t *card = (pc300_t *)chan->card;
@@ -3168,7 +3161,7 @@
 		d->if_ptr = &hdlc->state.ppp.pppdev;
 	}
 
-	result = hdlc_open(hdlc);
+	result = hdlc_open(dev);
 	if (hdlc->proto.id == IF_PROTO_PPP) {
 		dev->priv = d;
 	}
@@ -3200,7 +3193,7 @@
 	cpc_closech(d);
 	CPC_UNLOCK(card, flags);
 
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	if (hdlc->proto.id == IF_PROTO_PPP) {
 		d->if_ptr = NULL;
 	}
@@ -3369,17 +3362,14 @@
 		d->line_on = 0;
 		d->line_off = 0;
 
-		d->hdlc = (hdlc_device *) kmalloc(sizeof(hdlc_device), GFP_KERNEL);
-		if (d->hdlc == NULL)
+		dev = alloc_hdlcdev(NULL);
+		if (dev == NULL)
 			continue;
-		memset(d->hdlc, 0, sizeof(hdlc_device));
 
-		hdlc = d->hdlc;
+		hdlc = dev_to_hdlc(dev);
 		hdlc->xmit = cpc_queue_xmit;
 		hdlc->attach = cpc_attach;
-
-		dev = hdlc_to_dev(hdlc);
-
+		d->dev = dev;
 		dev->mem_start = card->hw.ramphys;
 		dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1;
 		dev->irq = card->hw.irq;
@@ -3397,7 +3387,7 @@
 		dev->change_mtu = cpc_change_mtu;
 		dev->do_ioctl = cpc_ioctl;
 
-		if (register_hdlc_device(hdlc) == 0) {
+		if (register_hdlc_device(dev) == 0) {
 			dev->priv = d;	/* We need 'priv', hdlc doesn't */
 			printk("%s: Cyclades-PC300/", dev->name);
 			switch (card->hw.type) {
@@ -3425,8 +3415,7 @@
 		} else {
 			printk ("Dev%d on card(0x%08lx): unable to allocate i/f name.\n",
 				 i + 1, card->hw.ramphys);
-			*(dev->name) = 0;
-			kfree(d->hdlc);
+			free_netdev(dev);
 			continue;
 		}
 	}
@@ -3658,7 +3647,7 @@
 			   cpc_readw(card->hw.plxbase + card->hw.intctl_reg) & ~(0x0040));
 
 		for (i = 0; i < card->hw.nchan; i++) {
-			unregister_hdlc_device(card->chan[i].d.hdlc);
+			unregister_hdlc_device(card->chan[i].d.dev);
 		}
 		iounmap((void *) card->hw.plxbase);
 		iounmap((void *) card->hw.scabase);
@@ -3671,6 +3660,9 @@
 			iounmap((void *) card->hw.falcbase);
 			release_mem_region(card->hw.falcphys, card->hw.falcsize);
 		}
+		for (i = 0; i < card->hw.nchan; i++)
+			if (card->chan[i].d.dev);
+				free_netdev(card->chan[i].d.dev);
 		if (card->hw.irq)
 			free_irq(card->hw.irq, card);
 		kfree(card);
diff -Nru a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
--- a/drivers/net/wan/pc300_tty.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/pc300_tty.c	Wed Feb 11 22:30:57 2004
@@ -155,7 +155,7 @@
 	unsigned long flags; 
 
 	CPC_TTY_DBG("%s-tty: Clear signal %x\n",
-		((struct net_device*)(pc300dev->hdlc))->name, signal);
+		pc300dev->dev->name, signal);
 	CPC_TTY_LOCK(card, flags); 
 	cpc_writeb(card->hw.scabase + M_REG(CTL,ch), 
 		cpc_readb(card->hw.scabase+M_REG(CTL,ch))& signal);
@@ -173,7 +173,7 @@
 	unsigned long flags; 
 
 	CPC_TTY_DBG("%s-tty: Set signal %x\n",
-		((struct net_device*)(pc300dev->hdlc))->name, signal);
+		pc300dev->dev->name, signal);
 	CPC_TTY_LOCK(card, flags); 
 	cpc_writeb(card->hw.scabase + M_REG(CTL,ch), 
 		cpc_readb(card->hw.scabase+M_REG(CTL,ch))& ~signal);
@@ -196,17 +196,17 @@
 	st_cpc_tty_area * cpc_tty;
 
 	/* hdlcX - X=interface number */
-	port = ((struct net_device*)(pc300dev->hdlc))->name[4] - '0';
+	port = pc300dev->dev->name[4] - '0';
 	if (port >= CPC_TTY_NPORTS) {
 		printk("%s-tty: invalid interface selected (0-%i): %i", 
-			((struct net_device*)(pc300dev->hdlc))->name,
+			pc300dev->dev->name,
 			CPC_TTY_NPORTS-1,port);
 		return;
 	}
 
 	if (cpc_tty_cnt == 0) { /* first TTY connection -> register driver */
 		CPC_TTY_DBG("%s-tty: driver init, major:%i, minor range:%i=%i\n",
-			((struct net_device*)(pc300dev->hdlc))->name,
+			pc300dev->dev->name,
 			CPC_TTY_MAJOR, CPC_TTY_MINOR_START,
 			CPC_TTY_MINOR_START+CPC_TTY_NPORTS);
 		/* initialize tty driver struct */
@@ -239,7 +239,7 @@
 		/* register the TTY driver */
 		if (tty_register_driver(&serial_drv)) { 
 			printk("%s-tty: Failed to register serial driver! ",
-				((struct net_device*)(pc300dev->hdlc))->name);
+				pc300dev->dev->name);
 		   	return;
 		} 
 
@@ -251,7 +251,7 @@
 	
 	if (cpc_tty->state != CPC_TTY_ST_IDLE) {
 		CPC_TTY_DBG("%s-tty: TTY port %i, already in use.\n",
-					((struct net_device*)(pc300dev->hdlc))->name,port);
+				pc300dev->dev->name, port);
 		return;
 	}
 
@@ -268,11 +268,11 @@
 
 	pc300dev->cpc_tty = (void *)cpc_tty; 
 	
-	aux = strlen(((struct net_device*)(pc300dev->hdlc))->name);
-	memcpy(cpc_tty->name,((struct net_device*)(pc300dev->hdlc))->name,aux);
+	aux = strlen(pc300dev->dev->name);
+	memcpy(cpc_tty->name, pc300dev->dev->name, aux);
 	memcpy(&cpc_tty->name[aux], "-tty", 5);
 	
-	cpc_open((struct net_device *)pc300dev->hdlc);
+	cpc_open(pc300dev->dev);
 	cpc_tty_signal_off(pc300dev, CTL_DTR);
 
 	CPC_TTY_DBG("%s: Initializing TTY Sync Driver, tty major#%d minor#%i\n",
@@ -457,7 +457,7 @@
 		(from_user)?"from user" : "from kernel",count);
 	
 	pc300chan = (pc300ch_t *)((pc300dev_t*)cpc_tty->pc300dev)->chan; 
-	stats = &((pc300dev_t*)cpc_tty->pc300dev)->hdlc->stats;
+	stats = hdlc_stats(((pc300dev_t*)cpc_tty->pc300dev)->dev);
 	card = (pc300_t *) pc300chan->card;
 	ch = pc300chan->channel; 
 
@@ -756,7 +756,7 @@
 	pc300_t *card = (pc300_t *)pc300chan->card; 
 	int ch = pc300chan->channel; 
 	volatile pcsca_bd_t * ptdescr; 
-	struct net_device_stats *stats = &pc300dev->hdlc->stats; 
+	struct net_device_stats *stats = hdlc_stats(pc300dev->dev);
 	int rx_len, rx_aux; 
 	volatile unsigned char status; 
 	unsigned short first_bd = pc300chan->rx_first_bd;
@@ -932,7 +932,7 @@
 	pc300ch_t *chan = (pc300ch_t *)dev->chan; 
 	pc300_t *card = (pc300_t *)chan->card; 
 	int ch = chan->channel; 
-	struct net_device_stats *stats = &dev->hdlc->stats; 
+	struct net_device_stats *stats = hdlc_stats(dev->dev);
 	unsigned long flags; 
 	volatile pcsca_bd_t * ptdescr; 
 	int i, nchar;
@@ -1016,19 +1016,18 @@
 
 	if ((skb = dev_alloc_skb(10 + len)) == NULL) { 
 		/* out of memory */ 
-		CPC_TTY_DBG("%s: tty_trace - out of memory\n",
-			((struct net_device *)(dev->hdlc))->name);
+		CPC_TTY_DBG("%s: tty_trace - out of memory\n", dev->dev->name);
 		return; 
 	}
 
 	skb_put (skb, 10 + len); 
-	skb->dev = (struct net_device *) dev->hdlc; 
+	skb->dev = dev->dev; 
 	skb->protocol = htons(ETH_P_CUST); 
 	skb->mac.raw = skb->data; 
 	skb->pkt_type = PACKET_HOST; 
 	skb->len = 10 + len; 
 
-	memcpy(skb->data,((struct net_device *)(dev->hdlc))->name,5);
+	memcpy(skb->data,dev->dev->name,5);
 	skb->data[5] = '['; 
 	skb->data[6] = rxtx; 
 	skb->data[7] = ']'; 
@@ -1050,15 +1049,14 @@
 	int res;
 
 	if ((cpc_tty= (st_cpc_tty_area *) pc300dev->cpc_tty) == 0) { 
-		CPC_TTY_DBG("%s: interface is not TTY\n",
-			((struct net_device *)(pc300dev->hdlc))->name);
+		CPC_TTY_DBG("%s: interface is not TTY\n", pc300dev->dev->name);
 		return; 
 	}
 	CPC_TTY_DBG("%s: cpc_tty_unregister_service", cpc_tty->name);
 
 	if (cpc_tty->pc300dev != pc300dev) { 
 		CPC_TTY_DBG("%s: invalid tty ptr=%s\n", 
-		((struct net_device *)(pc300dev->hdlc))->name, cpc_tty->name);
+		pc300dev->dev->name, cpc_tty->name);
 		return; 
 	}
 
diff -Nru a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
--- a/drivers/net/wan/pci200syn.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/wan/pci200syn.c	Wed Feb 11 22:30:56 2004
@@ -73,7 +73,7 @@
 
 
 typedef struct port_s {
-	hdlc_device hdlc;	/* HDLC device struct - must be first */
+	struct net_device *dev;
 	struct card_s *card;
 	spinlock_t lock;	/* TX lock */
 	sync_serial_settings settings;
@@ -177,14 +177,13 @@
 
 static int pci200_open(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
-	int result = hdlc_open(hdlc);
+	int result = hdlc_open(dev);
 	if (result)
 		return result;
 
-	sca_open(hdlc);
+	sca_open(dev);
 	pci200_set_iface(port);
 	sca_flush(port_to_card(port));
 	return 0;
@@ -194,10 +193,9 @@
 
 static int pci200_close(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	sca_close(hdlc);
+	sca_close(dev);
 	sca_flush(port_to_card(dev_to_port(dev)));
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	return 0;
 }
 
@@ -207,12 +205,11 @@
 {
 	const size_t size = sizeof(sync_serial_settings);
 	sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 #ifdef DEBUG_RINGS
 	if (cmd == SIOCDEVPRIVATE) {
-		sca_dump_rings(hdlc);
+		sca_dump_rings(dev);
 		return 0;
 	}
 #endif
@@ -265,8 +262,10 @@
 	card_t *card = pci_get_drvdata(pdev);
 
 	for(i = 0; i < 2; i++)
-		if (card->ports[i].card)
-			unregister_hdlc_device(&card->ports[i].hdlc);
+		if (card->ports[i].card) {
+			struct net_device *dev = port_to_dev(&card->ports[i]);
+			unregister_hdlc_device(dev);
+		}
 
 	if (card->irq)
 		free_irq(card->irq, card);
@@ -281,6 +280,10 @@
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
+	if (card->ports[0].dev)
+		free_netdev(card->ports[0].dev);
+	if (card->ports[1].dev)
+		free_netdev(card->ports[1].dev);
 	kfree(card);
 }
 
@@ -323,6 +326,13 @@
 	}
 	memset(card, 0, sizeof(card_t));
 	pci_set_drvdata(pdev, card);
+	card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
+	card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
+	if (!card->ports[0].dev || !card->ports[1].dev) {
+		printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+		pci200_pci_remove_one(pdev);
+		return -ENOMEM;
+	}
 
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
 	if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
@@ -397,7 +407,8 @@
 
 	for(i = 0; i < 2; i++) {
 		port_t *port = &card->ports[i];
-		struct net_device *dev = hdlc_to_dev(&port->hdlc);
+		struct net_device *dev = port_to_dev(port);
+		hdlc_device *hdlc = dev_to_hdlc(dev);
 		port->phy_node = i;
 
 		spin_lock_init(&port->lock);
@@ -409,20 +420,21 @@
 		dev->do_ioctl = pci200_ioctl;
 		dev->open = pci200_open;
 		dev->stop = pci200_close;
-		port->hdlc.attach = sca_attach;
-		port->hdlc.xmit = sca_xmit;
+		hdlc->attach = sca_attach;
+		hdlc->xmit = sca_xmit;
 		port->settings.clock_type = CLOCK_EXT;
-		if(register_hdlc_device(&port->hdlc)) {
+		port->card = card;
+		if(register_hdlc_device(dev)) {
 			printk(KERN_ERR "pci200syn: unable to register hdlc "
 			       "device\n");
+			port->card = NULL;
 			pci200_pci_remove_one(pdev);
 			return -ENOBUFS;
 		}
-		port->card = card;
 		sca_init_sync_port(port);	/* Set up SCA memory */
 
 		printk(KERN_INFO "%s: PCI200SYN node %d\n",
-		       hdlc_to_name(&port->hdlc), port->phy_node);
+		       dev->name, port->phy_node);
 	}
 
 	sca_flush(card);
diff -Nru a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
--- a/drivers/net/wan/sbni.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/sbni.c	Wed Feb 11 22:30:57 2004
@@ -210,7 +210,6 @@
 static void __init sbni_devsetup(struct net_device *dev)
 {
 	ether_setup( dev );
-	dev->init 		= &sbni_init;
 	dev->open		= &sbni_open;
 	dev->stop		= &sbni_close;
 	dev->hard_start_xmit	= &sbni_start_xmit;
@@ -234,8 +233,15 @@
 	sprintf(dev->name, "sbni%d", unit);
 	netdev_boot_setup_check(dev);
 
+	err = sbni_init(dev);
+	if (err) {
+		free_netdev(dev);
+		return err;
+	}
+
 	err = register_netdev(dev);
 	if (err) {
+		release_region( dev->base_addr, SBNI_IO_EXTENT );
 		free_netdev(dev);
 		return err;
 	}
@@ -304,8 +310,13 @@
 		/* Avoid already found cards from previous calls */
 		if( !request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) {
 			pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys );
-			if( subsys != 2  ||	/* Dual adapter is present */
-			    check_region( pci_ioaddr += 4, SBNI_IO_EXTENT ) )
+
+			if (subsys != 2)
+				continue;
+
+			/* Dual adapter is present */
+			if (!request_region(pci_ioaddr += 4, SBNI_IO_EXTENT,
+							dev->name ) )
 				continue;
 		}
 
@@ -318,8 +329,10 @@
 				pci_irq_line );
 
 		/* avoiding re-enable dual adapters */
-		if( (pci_ioaddr & 7) == 0  &&  pci_enable_device( pdev ) )
+		if( (pci_ioaddr & 7) == 0  &&  pci_enable_device( pdev ) ) {
+			release_region( pci_ioaddr, SBNI_IO_EXTENT );
 			return  -EIO;
+		}
 		if( sbni_probe1( dev, pci_ioaddr, pci_irq_line ) )
 			return  0;
 	}
@@ -1482,19 +1495,25 @@
 init_module( void )
 {
 	struct net_device  *dev;
+	int err;
 
 	while( num < SBNI_MAX_NUM_CARDS ) {
 		dev = alloc_netdev(sizeof(struct net_local), 
 				   "sbni%d", sbni_devsetup);
-		if( !dev) {
-			printk( KERN_ERR "sbni: unable to allocate device!\n" );
-			return  -ENOMEM;
-		}
+		if( !dev)
+			break;
 
 		sprintf( dev->name, "sbni%d", num );
 
+		err = sbni_init(dev);
+		if (err) {
+			free_netdev(dev);
+			break;
+		}
+
 		if( register_netdev( dev ) ) {
-			kfree( dev );
+			release_region( dev->base_addr, SBNI_IO_EXTENT );
+			free_netdev( dev );
 			break;
 		}
 	}
diff -Nru a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
--- a/drivers/net/wan/sdla.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/sdla.c	Wed Feb 11 22:30:57 2004
@@ -1339,6 +1339,8 @@
 	struct frad_local *flp;
 	int               i;
 	char              byte;
+	unsigned base;
+	int err = -EINVAL;
 
 	flp = dev->priv;
 
@@ -1352,108 +1354,90 @@
 	if (i == sizeof(valid_port) / sizeof(int))
 		return(-EINVAL);
 
-	dev->base_addr = map->base_addr;
-	if (!request_region(dev->base_addr, SDLA_IO_EXTENTS, dev->name)){
+	if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
 		printk(KERN_WARNING "SDLA: io-port 0x%04lx in use \n", dev->base_addr);
 		return(-EINVAL);
 	}
+	base = map->base_addr;
+
 	/* test for card types, S502A, S502E, S507, S508                 */
 	/* these tests shut down the card completely, so clear the state */
 	flp->type = SDLA_UNKNOWN;
 	flp->state = 0;
    
 	for(i=1;i<SDLA_IO_EXTENTS;i++)
-		if (inb(dev->base_addr + i) != 0xFF)
+		if (inb(base + i) != 0xFF)
 			break;
 
-	if (i == SDLA_IO_EXTENTS)
-	{   
-		outb(SDLA_HALT, dev->base_addr + SDLA_REG_Z80_CONTROL);
-		if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x08)
-		{
-			outb(SDLA_S502E_INTACK, dev->base_addr + SDLA_REG_CONTROL);
-			if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x0C)
-			{
-				outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
+	if (i == SDLA_IO_EXTENTS) {   
+		outb(SDLA_HALT, base + SDLA_REG_Z80_CONTROL);
+		if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x08) {
+			outb(SDLA_S502E_INTACK, base + SDLA_REG_CONTROL);
+			if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x0C) {
+				outb(SDLA_HALT, base + SDLA_REG_CONTROL);
 				flp->type = SDLA_S502E;
+				goto got_type;
 			}
 		}
 	}
 
-	if (flp->type == SDLA_UNKNOWN)
-	{
-		for(byte=inb(dev->base_addr),i=0;i<SDLA_IO_EXTENTS;i++)
-			if (inb(dev->base_addr + i) != byte)
-				break;
+	for(byte=inb(base),i=0;i<SDLA_IO_EXTENTS;i++)
+		if (inb(base + i) != byte)
+			break;
 
-		if (i == SDLA_IO_EXTENTS)
-		{
-			outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
-			if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x30)
-			{
-				outb(SDLA_S507_ENABLE, dev->base_addr + SDLA_REG_CONTROL);
-				if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x32)
-				{
-					outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
-					flp->type = SDLA_S507;
-				}
+	if (i == SDLA_IO_EXTENTS) {
+		outb(SDLA_HALT, base + SDLA_REG_CONTROL);
+		if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x30) {
+			outb(SDLA_S507_ENABLE, base + SDLA_REG_CONTROL);
+			if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x32) {
+				outb(SDLA_HALT, base + SDLA_REG_CONTROL);
+				flp->type = SDLA_S507;
+				goto got_type;
 			}
 		}
 	}
 
-	if (flp->type == SDLA_UNKNOWN)
-	{
-		outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
-		if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x00)
-		{
-			outb(SDLA_S508_INTEN, dev->base_addr + SDLA_REG_CONTROL);
-			if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x10)
-			{
-				outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
-				flp->type = SDLA_S508;
-			}
+	outb(SDLA_HALT, base + SDLA_REG_CONTROL);
+	if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x00) {
+		outb(SDLA_S508_INTEN, base + SDLA_REG_CONTROL);
+		if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x10) {
+			outb(SDLA_HALT, base + SDLA_REG_CONTROL);
+			flp->type = SDLA_S508;
+			goto got_type;
 		}
 	}
 
-	if (flp->type == SDLA_UNKNOWN)
-	{
-		outb(SDLA_S502A_HALT, dev->base_addr + SDLA_REG_CONTROL);
-		if (inb(dev->base_addr + SDLA_S502_STS) == 0x40)
-		{
-			outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL);
-			if (inb(dev->base_addr + SDLA_S502_STS) == 0x40)
-			{
-				outb(SDLA_S502A_INTEN, dev->base_addr + SDLA_REG_CONTROL);
-				if (inb(dev->base_addr + SDLA_S502_STS) == 0x44)
-				{
-					outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL);
-					flp->type = SDLA_S502A;
-				}
+	outb(SDLA_S502A_HALT, base + SDLA_REG_CONTROL);
+	if (inb(base + SDLA_S502_STS) == 0x40) {
+		outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
+		if (inb(base + SDLA_S502_STS) == 0x40) {
+			outb(SDLA_S502A_INTEN, base + SDLA_REG_CONTROL);
+			if (inb(base + SDLA_S502_STS) == 0x44) {
+				outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
+				flp->type = SDLA_S502A;
+				goto got_type;
 			}
 		}
 	}
 
-	if (flp->type == SDLA_UNKNOWN)
-	{
-		printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
-		return(-ENODEV);
-	}
+	printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
+	err = -ENODEV;
+	goto fail;
 
-	switch(dev->base_addr)
-	{
+got_type:
+	switch(base) {
 		case 0x270:
 		case 0x280:
 		case 0x380: 
 		case 0x390:
-			if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507))
-				return(-EINVAL);
+			if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
+				goto fail;
 	}
 
-	switch (map->irq)
-	{
+	switch (map->irq) {
 		case 2:
 			if (flp->type != SDLA_S502E)
-				return(-EINVAL);
+				goto fail;
 			break;
 
 		case 10:
@@ -1461,28 +1445,26 @@
 		case 12:
 		case 15:
 		case 4:
-			if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507))
-				return(-EINVAL);
-
+			if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
+				goto fail;
+			break;
 		case 3:
 		case 5:
 		case 7:
 			if (flp->type == SDLA_S502A)
-				return(-EINVAL);
+				goto fail;
 			break;
 
 		default:
-			return(-EINVAL);
+			goto fail;
 	}
-	dev->irq = map->irq;
 
+	err = -EAGAIN;
 	if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev)) 
-		return(-EAGAIN);
+		goto fail;
 
-	if (flp->type == SDLA_S507)
-	{
-		switch(dev->irq)
-		{
+	if (flp->type == SDLA_S507) {
+		switch(dev->irq) {
 			case 3:
 				flp->state = SDLA_S507_IRQ3;
 				break;
@@ -1514,35 +1496,25 @@
 		if (valid_mem[i] == map->mem_start)
 			break;   
 
+	err = -EINVAL;
 	if (i == sizeof(valid_mem) / sizeof(int))
-	/*
-	 *	FIXME:
-	 *	BUG BUG BUG: MUST RELEASE THE IRQ WE ALLOCATED IN
-	 *	ALL THESE CASES
-	 *
-	 */
-		return(-EINVAL);
+		goto fail2;
 
-	if ((flp->type == SDLA_S502A) && (((map->mem_start & 0xF000) >> 12) == 0x0E))
-		return(-EINVAL);
-
-	if ((flp->type != SDLA_S507) && ((map->mem_start >> 16) == 0x0B))
-		return(-EINVAL);
+	if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E)
+		goto fail2;
 
-	if ((flp->type == SDLA_S507) && ((map->mem_start >> 16) == 0x0D))
-		return(-EINVAL);
+	if (flp->type != SDLA_S507 && map->mem_start >> 16 == 0x0B)
+		goto fail2;
 
-	dev->mem_start = map->mem_start;
-	dev->mem_end = dev->mem_start + 0x2000;
+	if (flp->type == SDLA_S507 && map->mem_start >> 16 == 0x0D)
+		goto fail2;
 
 	byte = flp->type != SDLA_S508 ? SDLA_8K_WINDOW : 0;
 	byte |= (map->mem_start & 0xF000) >> (12 + (flp->type == SDLA_S508 ? 1 : 0));
-	switch(flp->type)
-	{
+	switch(flp->type) {
 		case SDLA_S502A:
 		case SDLA_S502E:
-			switch (map->mem_start >> 16)
-			{
+			switch (map->mem_start >> 16) {
 				case 0x0A:
 					byte |= SDLA_S502_SEG_A;
 					break;
@@ -1558,8 +1530,7 @@
 			}
 			break;
 		case SDLA_S507:
-			switch (map->mem_start >> 16)
-			{
+			switch (map->mem_start >> 16) {
 				case 0x0A:
 					byte |= SDLA_S507_SEG_A;
 					break;
@@ -1575,8 +1546,7 @@
 			}
 			break;
 		case SDLA_S508:
-			switch (map->mem_start >> 16)
-			{
+			switch (map->mem_start >> 16) {
 				case 0x0A:
 					byte |= SDLA_S508_SEG_A;
 					break;
@@ -1594,7 +1564,7 @@
 	}
 
 	/* set the memory bits, and enable access */
-	outb(byte, dev->base_addr + SDLA_REG_PC_WINDOW);
+	outb(byte, base + SDLA_REG_PC_WINDOW);
 
 	switch(flp->type)
 	{
@@ -1608,10 +1578,20 @@
 			flp->state = SDLA_MEMEN;
 			break;
 	}
-	outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
+	outb(flp->state, base + SDLA_REG_CONTROL);
 
+	dev->irq = map->irq;
+	dev->base_addr = base;
+	dev->mem_start = map->mem_start;
+	dev->mem_end = dev->mem_start + 0x2000;
 	flp->initialized = 1;
-	return(0);
+	return 0;
+
+fail2:
+	free_irq(map->irq, dev);
+fail:
+	release_region(base, SDLA_IO_EXTENTS);
+	return err;
 }
  
 static struct net_device_stats *sdla_stats(struct net_device *dev)
@@ -1676,13 +1656,13 @@
 
 static void __exit exit_sdla(void)
 {
-	struct frad_local *flp;
+	struct frad_local *flp = sdla->priv;
 
 	unregister_netdev(sdla);
-	if (sdla->irq)
+	if (flp->initialized) {
 		free_irq(sdla->irq, sdla);
-
-	flp = sdla->priv;
+		release_region(sdla->base_addr, SDLA_IO_EXTENTS);
+	}
 	del_timer_sync(&flp->timer);
 	free_netdev(sdla);
 }
diff -Nru a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
--- a/drivers/net/wan/sealevel.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/sealevel.c	Wed Feb 11 22:30:57 2004
@@ -420,6 +420,7 @@
 	/* DMA off on the card, drop DTR */
 	outb(0, b->iobase);
 	release_region(b->iobase, 8);
+	kfree(b);
 }
 
 
diff -Nru a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
--- a/drivers/net/wan/wanxl.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wan/wanxl.c	Wed Feb 11 22:30:57 2004
@@ -51,7 +51,7 @@
 
 
 typedef struct {
-	hdlc_device hdlc;	/* HDLC device struct - must be first */
+	struct net_device *dev;
 	struct card_t *card;
 	spinlock_t lock;	/* for wanxl_xmit */
         int node;		/* physical port #0 - 3 */
@@ -78,31 +78,26 @@
 	struct sk_buff *rx_skbs[RX_QUEUE_LENGTH];
 	card_status_t *status;	/* shared between host and card */
 	dma_addr_t status_address;
+	port_t __ports[0];
 }card_t;
 
 
 
-static inline port_t* hdlc_to_port(hdlc_device *hdlc)
-{
-        return (port_t*)hdlc;
-}
-
-
 static inline port_t* dev_to_port(struct net_device *dev)
 {
-        return hdlc_to_port(dev_to_hdlc(dev));
+        return (port_t *)dev_to_hdlc(dev)->priv;
 }
 
 
 static inline struct net_device *port_to_dev(port_t* port)
 {
-        return hdlc_to_dev(&port->hdlc);
+        return port->dev;
 }
 
 
 static inline const char* port_name(port_t *port)
 {
-	return hdlc_to_name((hdlc_device*)port);
+	return port_to_dev(port)->name;
 }
 
 
@@ -172,7 +167,7 @@
 	printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n",
 	       port_name(port), pm, dte, cable, dsr, dcd);
 
-	hdlc_set_carrier(value & STATUS_CABLE_DCD, &port->hdlc);
+	hdlc_set_carrier(value & STATUS_CABLE_DCD, port_to_dev(port));
 }
 
 
@@ -180,6 +175,8 @@
 /* Transmit complete interrupt service */
 static inline void wanxl_tx_intr(port_t *port)
 {
+	struct net_device *dev = port_to_dev(port);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	while (1) {
                 desc_t *desc = &get_status(port)->tx_descs[port->tx_in];
 		struct sk_buff *skb = port->tx_skbs[port->tx_in];
@@ -187,17 +184,17 @@
 		switch (desc->stat) {
 		case PACKET_FULL:
 		case PACKET_EMPTY:
-			netif_wake_queue(port_to_dev(port));
+			netif_wake_queue(dev);
 			return;
 
 		case PACKET_UNDERRUN:
-			port->hdlc.stats.tx_errors++;
-			port->hdlc.stats.tx_fifo_errors++;
+			stats->tx_errors++;
+			stats->tx_fifo_errors++;
 			break;
 
 		default:
-			port->hdlc.stats.tx_packets++;
-			port->hdlc.stats.tx_bytes += skb->len;
+			stats->tx_packets++;
+			stats->tx_bytes += skb->len;
 		}
                 desc->stat = PACKET_EMPTY; /* Free descriptor */
 		pci_unmap_single(port->card->pdev, desc->address, skb->len,
@@ -218,13 +215,14 @@
 		struct sk_buff *skb = card->rx_skbs[card->rx_in];
 		port_t *port = card->ports[desc->stat & PACKET_PORT_MASK];
 		struct net_device *dev = port_to_dev(port);
+		struct net_device_stats *stats = hdlc_stats(dev);
 
 		if ((desc->stat & PACKET_PORT_MASK) > card->n_ports)
 			printk(KERN_CRIT "wanXL %s: received packet for"
 			       " nonexistent port\n", card_name(card->pdev));
 
 		else if (!skb)
-			port->hdlc.stats.rx_dropped++;
+			stats->rx_dropped++;
 
 		else {
 			pci_unmap_single(card->pdev, desc->address,
@@ -236,8 +234,8 @@
 			       skb->len);
 			debug_frame(skb);
 #endif
-			port->hdlc.stats.rx_packets++;
-			port->hdlc.stats.rx_bytes += skb->len;
+			stats->rx_packets++;
+			stats->rx_bytes += skb->len;
 			skb->mac.raw = skb->data;
 			skb->dev = dev;
 			dev->last_rx = jiffies;
@@ -290,8 +288,7 @@
 
 static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-        port_t *port = hdlc_to_port(hdlc);
+        port_t *port = dev_to_port(dev);
 	desc_t *desc;
 
         spin_lock(&port->lock);
@@ -338,10 +335,10 @@
 
 
 
-static int wanxl_attach(hdlc_device *hdlc, unsigned short encoding,
+static int wanxl_attach(struct net_device *dev, unsigned short encoding,
 			unsigned short parity)
 {
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 	if (encoding != ENCODING_NRZ &&
 	    encoding != ENCODING_NRZI)
@@ -365,8 +362,7 @@
 {
 	const size_t size = sizeof(sync_serial_settings);
 	sync_serial_settings line;
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 
 	if (cmd != SIOCWANDEV)
 		return hdlc_ioctl(dev, ifr, cmd);
@@ -415,8 +411,7 @@
 
 static int wanxl_open(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	u8 *dbr = port->card->plx + PLX_DOORBELL_TO_CARD;
 	unsigned long timeout;
 	int i;
@@ -425,7 +420,7 @@
 		printk(KERN_ERR "%s: port already open\n", port_name(port));
 		return -EIO;
 	}
-	if ((i = hdlc_open(hdlc)) != 0)
+	if ((i = hdlc_open(dev)) != 0)
 		return i;
 
 	port->tx_in = port->tx_out = 0;
@@ -450,12 +445,11 @@
 
 static int wanxl_close(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	port_t *port = dev_to_port(dev);
 	unsigned long timeout;
 	int i;
 
-	hdlc_close(hdlc);
+	hdlc_close(dev);
 	/* signal the card */
 	writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node),
 	       port->card->plx + PLX_DOORBELL_TO_CARD);
@@ -487,14 +481,13 @@
 
 static struct net_device_stats *wanxl_get_stats(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	port_t *port = hdlc_to_port(hdlc);
+	struct net_device_stats *stats = hdlc_stats(dev);
+	port_t *port = dev_to_port(dev);
 
-	hdlc->stats.rx_over_errors = get_status(port)->rx_overruns;
-	hdlc->stats.rx_frame_errors = get_status(port)->rx_frame_errors;
-	hdlc->stats.rx_errors = hdlc->stats.rx_over_errors +
-		hdlc->stats.rx_frame_errors;
-        return &hdlc->stats;
+	stats->rx_over_errors = get_status(port)->rx_overruns;
+	stats->rx_frame_errors = get_status(port)->rx_frame_errors;
+	stats->rx_errors = stats->rx_over_errors + stats->rx_frame_errors;
+        return stats;
 }
 
 
@@ -535,14 +528,16 @@
 	card_t *card = pci_get_drvdata(pdev);
 	int i;
 
+	for (i = 0; i < 4; i++)
+		if (card->ports[i]) {
+			struct net_device *dev = port_to_dev(card->ports[i]);
+			unregister_hdlc_device(dev);
+		}
+
 	/* unregister and free all host resources */
 	if (card->irq)
 		free_irq(card->irq, card);
 
-	for (i = 0; i < 4; i++)
-		if (card->ports[i])
-			unregister_hdlc_device(&card->ports[i]->hdlc);
-
 	wanxl_reset(card);
 
 	for (i = 0; i < RX_QUEUE_LENGTH; i++)
@@ -560,6 +555,10 @@
 		pci_free_consistent(pdev, sizeof(card_status_t),
 				    card->status, card->status_address);
 
+	for (i = 0; i < card->n_ports; i++)
+		if (card->__ports[i].dev)
+			free_netdev(card->__ports[i].dev);
+
 	pci_set_drvdata(pdev, NULL);
 	kfree(card);
 	pci_release_regions(pdev);
@@ -628,6 +627,16 @@
 	card->pdev = pdev;
 	card->n_ports = ports;
 
+	for (i = 0; i < ports; i++) {
+		card->__ports[i].dev = alloc_hdlcdev(&card->__ports[i]);
+		if (!card->__ports[i].dev) {
+			printk(KERN_ERR "wanXL %s: unable to allocate memory\n",
+			       card_name(pdev));
+			wanxl_pci_remove_one(pdev);
+			return -ENOMEM;
+		}
+	}
+
 	card->status = pci_alloc_consistent(pdev, sizeof(card_status_t),
 					    &card->status_address);
 	if (card->status == NULL) {
@@ -708,31 +717,6 @@
 		return -ENODEV;
 	}
 
-	for (i = 0; i < ports; i++) {
-		port_t *port = (void *)card + sizeof(card_t) +
-			i * sizeof(port_t);
-		struct net_device *dev = hdlc_to_dev(&port->hdlc);
-		spin_lock_init(&port->lock);
-		SET_MODULE_OWNER(dev);
-		dev->tx_queue_len = 50;
-		dev->do_ioctl = wanxl_ioctl;
-		dev->open = wanxl_open;
-		dev->stop = wanxl_close;
-		port->hdlc.attach = wanxl_attach;
-		port->hdlc.xmit = wanxl_xmit;
-		if(register_hdlc_device(&port->hdlc)) {
-			printk(KERN_ERR "wanXL %s: unable to register hdlc"
-			       " device\n", card_name(pdev));
-			wanxl_pci_remove_one(pdev);
-			return -ENOBUFS;
-		}
-		card->ports[i] = port;
-		dev->get_stats = wanxl_get_stats;
-		port->card = card;
-		port->node = i;
-		get_status(port)->clocking = CLOCK_EXT;
-	}
-
 	for (i = 0; i < RX_QUEUE_LENGTH; i++) {
 		struct sk_buff *skb = dev_alloc_skb(BUFFER_LENGTH);
 		card->rx_skbs[i] = skb;
@@ -800,6 +784,32 @@
 		return -EBUSY;
 	}
 	card->irq = pdev->irq;
+
+	for (i = 0; i < ports; i++) {
+		port_t *port = &card->__ports[i];
+		struct net_device *dev = port_to_dev(port);
+		hdlc_device *hdlc = dev_to_hdlc(dev);
+		spin_lock_init(&port->lock);
+		SET_MODULE_OWNER(dev);
+		dev->tx_queue_len = 50;
+		dev->do_ioctl = wanxl_ioctl;
+		dev->open = wanxl_open;
+		dev->stop = wanxl_close;
+		hdlc->attach = wanxl_attach;
+		hdlc->xmit = wanxl_xmit;
+		card->ports[i] = port;
+		dev->get_stats = wanxl_get_stats;
+		port->card = card;
+		port->node = i;
+		get_status(port)->clocking = CLOCK_EXT;
+		if (register_hdlc_device(dev)) {
+			printk(KERN_ERR "wanXL %s: unable to register hdlc"
+			       " device\n", card_name(pdev));
+			card->ports[i] = NULL;
+			wanxl_pci_remove_one(pdev);
+			return -ENOBUFS;
+		}
+	}
 
 	return 0;
 }
diff -Nru a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
--- a/drivers/net/wan/x25_asy.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/wan/x25_asy.c	Wed Feb 11 22:30:56 2004
@@ -213,7 +213,7 @@
 	memcpy(skb_put(skb,count), sl->rbuff, count);
 	skb->mac.raw=skb->data;
 	skb->protocol=htons(ETH_P_X25);
-	if((err=lapb_data_received(sl,skb))!=LAPB_OK)
+	if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK)
 	{
 		kfree_skb(skb);
 		printk(KERN_DEBUG "x25_asy: data received err - %d\n",err);
@@ -324,12 +324,12 @@
 	{
 		case 0x00:break;
 		case 0x01: /* Connection request .. do nothing */
-			if((err=lapb_connect_request(sl))!=LAPB_OK)
+			if((err=lapb_connect_request(dev))!=LAPB_OK)
 				printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
 			kfree_skb(skb);
 			return 0;
 		case 0x02: /* Disconnect request .. do nothing - hang up ?? */
-			if((err=lapb_disconnect_request(sl))!=LAPB_OK)
+			if((err=lapb_disconnect_request(dev))!=LAPB_OK)
 				printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
 		default:
 			kfree_skb(skb);
@@ -347,7 +347,7 @@
 	 *        14 Oct 1994  Dmitry Gorodchanin.
 	 */
 	
-	if((err=lapb_data_request(sl,skb))!=LAPB_OK)
+	if((err=lapb_data_request(dev,skb))!=LAPB_OK)
 	{
 		printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
 		kfree_skb(skb);
@@ -366,7 +366,7 @@
  *	at the net layer.
  */
   
-static int x25_asy_data_indication(void *token, struct sk_buff *skb)
+static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
 	skb->dev->last_rx = jiffies;
 	return netif_rx(skb);
@@ -378,9 +378,9 @@
  *	perhaps lapb should allow us to bounce this ?
  */
  
-static void x25_asy_data_transmit(void *token, struct sk_buff *skb)
+static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
 {
-	struct x25_asy *sl=token;
+	struct x25_asy *sl=dev->priv;
 	
 	spin_lock(&sl->lock);
 	if (netif_queue_stopped(sl->dev) || sl->tty == NULL)
@@ -405,9 +405,9 @@
  *	LAPB connection establish/down information.
  */
  
-static void x25_asy_connected(void *token, int reason)
+static void x25_asy_connected(struct net_device *dev, int reason)
 {
-	struct x25_asy *sl = token;
+	struct x25_asy *sl = dev->priv;
 	struct sk_buff *skb;
 	unsigned char *ptr;
 
@@ -428,9 +428,9 @@
 	sl->dev->last_rx = jiffies;
 }
 
-static void x25_asy_disconnected(void *token, int reason)
+static void x25_asy_disconnected(struct net_device *dev, int reason)
 {
-	struct x25_asy *sl = token;
+	struct x25_asy *sl = dev->priv;
 	struct sk_buff *skb;
 	unsigned char *ptr;
 
@@ -500,7 +500,7 @@
 	/*
 	 *	Now attach LAPB
 	 */
-	if((err=lapb_register(sl, &x25_asy_callbacks))==LAPB_OK)
+	if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK)
 		return 0;
 
 	/* Cleanup */
@@ -525,7 +525,7 @@
 	netif_stop_queue(dev);
 	sl->rcount = 0;
 	sl->xleft  = 0;
-	if((err=lapb_unregister(sl))!=LAPB_OK)
+	if((err=lapb_unregister(dev))!=LAPB_OK)
 		printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
 	spin_unlock(&sl->lock);
 	return 0;
diff -Nru a/drivers/net/wd.c b/drivers/net/wd.c
--- a/drivers/net/wd.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/wd.c	Wed Feb 11 22:30:56 2004
@@ -333,6 +333,9 @@
 	ei_status.get_8390_hdr = &wd_get_8390_hdr;
 	dev->open = &wd_open;
 	dev->stop = &wd_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
 	NS8390_init(dev, 0);
 
 #if 1
diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
--- a/drivers/net/wireless/airo.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/wireless/airo.c	Wed Feb 11 22:30:56 2004
@@ -2599,10 +2599,8 @@
 	return rc;
 }
 
-static void wifi_setup(struct net_device *dev, struct net_device *ethdev)
+static void wifi_setup(struct net_device *dev)
 {
-	struct airo_info *ai = ethdev->priv;
-	dev->priv = ai;
 	dev->hard_header        = 0;
 	dev->rebuild_header     = 0;
 	dev->hard_header_cache  = 0;
@@ -2620,14 +2618,11 @@
 	dev->change_mtu = &airo_change_mtu;
 	dev->open = &airo_open;
 	dev->stop = &airo_close;
-	dev->irq = ethdev->irq;
-	dev->base_addr = ethdev->base_addr;
 
 	dev->type               = ARPHRD_IEEE80211;
 	dev->hard_header_len    = ETH_HLEN;
 	dev->mtu                = 2312;
 	dev->addr_len           = ETH_ALEN;
-	memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
 	dev->tx_queue_len       = 100; 
 
 	memset(dev->broadcast,0xFF, ETH_ALEN);
@@ -2639,17 +2634,17 @@
 					struct net_device *ethdev)
 {
 	int err;
-	struct net_device *dev = (struct net_device*)kmalloc(sizeof *dev,GFP_KERNEL);
-	if (!dev) return 0;
-	memset(dev, 0, sizeof(*dev));
-
-	strcpy(dev->name, "wifi%d");
-	dev->priv = ai;
-	wifi_setup(dev, ethdev);
+	struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
+	if (!dev)
+		return NULL;
+	dev->priv = ethdev->priv;
+	dev->irq = ethdev->irq;
+	dev->base_addr = ethdev->base_addr;
+	memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
 	err = register_netdev(dev);
 	if (err<0) {
-		kfree(dev);
-		return 0;
+		free_netdev(dev);
+		return NULL;
 	}
 	return dev;
 }
@@ -2809,7 +2804,7 @@
 	kill_proc(ai->thr_pid, SIGTERM, 1);
 	wait_for_completion(&ai->thr_exited);
 err_out_free:
-	kfree(dev);
+	free_netdev(dev);
 	return NULL;
 }
 
diff -Nru a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
--- a/drivers/net/wireless/airport.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wireless/airport.c	Wed Feb 11 22:30:57 2004
@@ -40,7 +40,7 @@
 #define AIRPORT_IO_LEN	(0x1000)	/* one page */
 
 struct airport {
-	struct device_node *node;
+	struct macio_dev *mdev;
 	void *vaddr;
 	int irq_requested;
 	int ndev_registered;
@@ -51,7 +51,6 @@
 {
 	struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
 	struct orinoco_private *priv = dev->priv;
-	struct airport *card = priv->card;
 	unsigned long flags;
 	int err;
 
@@ -76,7 +75,7 @@
 	orinoco_unlock(priv, &flags);
 
 	disable_irq(dev->irq);
-	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
+	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
 
 	return 0;
 }
@@ -86,14 +85,14 @@
 {
 	struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
 	struct orinoco_private *priv = dev->priv;
-	struct airport *card = priv->card;
 	unsigned long flags;
 	int err;
 
 	printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
 
-	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
-	mdelay(200);
+	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ/5);
 
 	enable_irq(dev->irq);
 
@@ -142,15 +141,13 @@
 		iounmap(card->vaddr);
 	card->vaddr = 0;
 
-	dev->base_addr = 0;
+	macio_release_resource(mdev, 0);
 
-	release_OF_resource(card->node, 0);
-
-	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
-	current->state = TASK_UNINTERRUPTIBLE;
+	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ);
 
-	dev_set_drvdata(&mdev->ofdev.dev, NULL);
+	macio_set_drvdata(mdev, NULL);
 	free_netdev(dev);
 
 	return 0;
@@ -173,11 +170,11 @@
 	 * off. */
 	disable_irq(dev->irq);
 
-	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
-	current->state = TASK_UNINTERRUPTIBLE;
+	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0);
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ);
-	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
-	current->state = TASK_UNINTERRUPTIBLE;
+	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1);
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ);
 
 	enable_irq(dev->irq);
@@ -194,10 +191,9 @@
 	struct net_device *dev;
 	struct airport *card;
 	unsigned long phys_addr;
-	struct device_node *of_node = mdev->ofdev.node;
 	hermes_t *hw;
 
-	if (of_node->n_addrs < 1 || of_node->n_intrs < 1) {
+	if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
 		printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
 		return -ENODEV;
 	}
@@ -212,27 +208,26 @@
 	card = priv->card;
 
 	hw = &priv->hw;
-	card->node = of_node;
+	card->mdev = mdev;
 
-	if (! request_OF_resource(of_node, 0, " (airport)")) {
+	if (macio_request_resource(mdev, 0, "airport")) {
 		printk(KERN_ERR "airport: can't request IO resource !\n");
 		free_netdev(dev);
-		return -ENODEV;
+		return -EBUSY;
 	}
 
-	dev->name[0] = '\0';	/* register_netdev will give us an ethX name */
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
 
-	dev_set_drvdata(&mdev->ofdev.dev, dev);
+	macio_set_drvdata(mdev, dev);
 
 	/* Setup interrupts & base address */
-	dev->irq = of_node->intrs[0].line;
-	phys_addr = of_node->addrs[0].address;  /* Physical address */
+	dev->irq = macio_irq(mdev, 0);
+	phys_addr = macio_resource_start(mdev, 0);  /* Physical address */
 	printk(KERN_DEBUG "Airport at physical address %lx\n", phys_addr);
 	dev->base_addr = phys_addr;
 	card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
-	if (! card->vaddr) {
+	if (!card->vaddr) {
 		printk("airport: ioremap() failed\n");
 		goto failed;
 	}
@@ -241,8 +236,8 @@
 			HERMES_MEM, HERMES_16BIT_REGSPACING);
 		
 	/* Power up card */
-	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
-	current->state = TASK_UNINTERRUPTIBLE;
+	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ);
 
 	/* Reset it before we get the interrupt */
diff -Nru a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
--- a/drivers/net/wireless/orinoco.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/wireless/orinoco.c	Wed Feb 11 22:30:58 2004
@@ -4129,6 +4129,8 @@
 	struct orinoco_private *priv;
 
 	dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
+	if (!dev)
+		return NULL;
 	priv = (struct orinoco_private *)dev->priv;
 	priv->ndev = dev;
 	if (sizeof_card)
diff -Nru a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
--- a/drivers/net/wireless/wl3501_cs.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/net/wireless/wl3501_cs.c	Wed Feb 11 22:30:56 2004
@@ -1580,7 +1580,7 @@
 	*linkp = link->next;
 
 	if (link->priv)
-		kfree(link->priv);
+		free_netdev(link->priv);
 	kfree(link);
 out:
 	return;
diff -Nru a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
--- a/drivers/net/zorro8390.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/net/zorro8390.c	Wed Feb 11 22:30:57 2004
@@ -222,6 +222,9 @@
     ei_status.reg_offset = zorro8390_offsets;
     dev->open = &zorro8390_open;
     dev->stop = &zorro8390_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+    dev->poll_controller = ei_poll;
+#endif
 #ifdef MODULE
     ei_status.priv = (unsigned long)root_zorro8390_dev;
     root_zorro8390_dev = dev;
diff -Nru a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
--- a/drivers/s390/net/lcs.c	Wed Feb 11 22:30:56 2004
+++ b/drivers/s390/net/lcs.c	Wed Feb 11 22:30:56 2004
@@ -360,7 +360,7 @@
 		kfree(ipm_list);
 	}
 #endif
-	kfree(card->dev);
+	free_netdev(card->dev);
 	/* Cleanup channels. */
 	lcs_cleanup_channel(&card->write);
 	lcs_cleanup_channel(&card->read);
@@ -1858,8 +1858,7 @@
 	lcs_stopcard(card);
 	return 0;
 out:
-	lcs_cleanup_channel(&card->read);
-	lcs_cleanup_channel(&card->write);
+	lcs_cleanup_card(card);
 	lcs_free_card(card);
 	return -ENODEV;
 }
diff -Nru a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
--- a/drivers/s390/net/netiucv.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/s390/net/netiucv.c	Wed Feb 11 22:30:57 2004
@@ -1473,6 +1473,14 @@
 	sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
 }
 
+/*
+ * XXX: Don't use sysfs unless you know WTF you are doing.
+ * This particular turd registers sysfs objects embedded into netiucv_priv
+ * which is kfreed without any regard to possible sysfs references.
+ * As the result, the wanker who'd decided that sysfs exports were too hip and
+ * cute to resist had generated a set of user-exploitable holes in this driver.
+ */
+
 static int
 netiucv_register_device(struct net_device *ndev, int ifno)
 {
@@ -1592,6 +1600,22 @@
 	}
 }
 
+static void setup_netiucv(struct net_device *dev)
+{
+	dev->mtu	         = NETIUCV_MTU_DEFAULT;
+	dev->hard_start_xmit     = netiucv_tx;
+	dev->open	         = netiucv_open;
+	dev->stop	         = netiucv_close;
+	dev->get_stats	         = netiucv_stats;
+	dev->change_mtu          = netiucv_change_mtu;
+	dev->hard_header_len     = NETIUCV_HDRLEN;
+	dev->addr_len            = 0;
+	dev->type                = ARPHRD_SLIP;
+	dev->tx_queue_len        = NETIUCV_QUEUELEN_DEFAULT;
+	dev->flags	         = IFF_POINTOPOINT | IFF_NOARP;
+	SET_MODULE_OWNER(dev);
+}
+
 /**
  * Allocate and initialize everything of a net device.
  */
@@ -1601,16 +1625,15 @@
 	struct netiucv_priv *privptr;
 	int          priv_size;
 
-	struct net_device *dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	struct net_device *dev = alloc_netdev(0, "", setup_netiucv);
 	if (!dev)
 		return NULL;
-	memset(dev, 0, sizeof(struct net_device));
 	sprintf(dev->name, "iucv%d", ifno);
 
 	priv_size = sizeof(struct netiucv_priv);
 	dev->priv = kmalloc(priv_size, GFP_KERNEL);
 	if (dev->priv == NULL) {
-		kfree(dev);
+		free_netdev(dev);
 		return NULL;
 	}
         memset(dev->priv, 0, priv_size);
@@ -1620,30 +1643,18 @@
 				dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
 	if (privptr->fsm == NULL) {
 		kfree(privptr);
-		kfree(dev);
+		free_netdev(dev);
 		return NULL;
 	}
 	privptr->conn = netiucv_new_connection(dev, username);
 	if (!privptr->conn) {
 		kfree_fsm(privptr->fsm);
 		kfree(privptr);
-		kfree(dev);
+		free_netdev(dev);
 		return NULL;
 	}
 
 	fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
-	dev->mtu	         = NETIUCV_MTU_DEFAULT;
-	dev->hard_start_xmit     = netiucv_tx;
-	dev->open	         = netiucv_open;
-	dev->stop	         = netiucv_close;
-	dev->get_stats	         = netiucv_stats;
-	dev->change_mtu          = netiucv_change_mtu;
-	dev->hard_header_len     = NETIUCV_HDRLEN;
-	dev->addr_len            = 0;
-	dev->type                = ARPHRD_SLIP;
-	dev->tx_queue_len        = NETIUCV_QUEUELEN_DEFAULT;
-	dev->flags	         = IFF_POINTOPOINT | IFF_NOARP;
-	SET_MODULE_OWNER(dev);
 	return dev;
 }
 
diff -Nru a/drivers/s390/net/qeth.c b/drivers/s390/net/qeth.c
--- a/drivers/s390/net/qeth.c	Wed Feb 11 22:30:58 2004
+++ b/drivers/s390/net/qeth.c	Wed Feb 11 22:30:58 2004
@@ -6707,15 +6707,6 @@
 }
 
 static void
-qeth_destructor(struct net_device *dev)
-{
-	struct qeth_card *card;
-
-	card = (struct qeth_card *) (dev->priv);
-	QETH_DBF_CARD2(0, trace, "dstr", card);
-}
-
-static void
 qeth_set_multicast_list(struct net_device *dev)
 {
 	struct qeth_card *card = dev->priv;
@@ -7655,28 +7646,11 @@
 
 	QETH_DBF_CARD3(0, trace, "inid", card);
 
-	dev->tx_timeout = &qeth_tx_timeout;
-	dev->watchdog_timeo = QETH_TX_TIMEOUT;
-	dev->open = qeth_open;
-	dev->stop = qeth_stop;
-	dev->set_config = qeth_set_config;
-	dev->hard_start_xmit = qeth_hard_start_xmit;
-	dev->do_ioctl = qeth_do_ioctl;
-	dev->get_stats = qeth_get_stats;
-	dev->change_mtu = qeth_change_mtu;
-#ifdef QETH_VLAN
-	dev->vlan_rx_register = qeth_vlan_rx_register;
-	dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
-#endif
 	dev->rebuild_header = __qeth_rebuild_header_func(card);
 	dev->hard_header = __qeth_hard_header_func(card);
 	dev->header_cache_update = __qeth_header_cache_update_func(card);
 	dev->hard_header_cache = __qeth_hard_header_cache_func(card);
 	dev->hard_header_parse = NULL;
-	dev->destructor = qeth_destructor;
-	dev->set_multicast_list = qeth_set_multicast_list;
-	dev->set_mac_address = qeth_set_mac_address;
-	dev->neigh_setup = qeth_neigh_setup;
 
 	dev->flags |= qeth_get_additional_dev_flags(card->type);
 
@@ -7694,8 +7668,6 @@
 	dev->tx_queue_len = qeth_get_device_tx_q_len(card->type);
 	dev->hard_header_len =
 		qeth_get_hlen(card->link_type) + card->options.add_hhlen;
-	dev->addr_len = OSA_ADDR_LEN;	/* is ok for eth, tr, atm lane */
-	SET_MODULE_OWNER(dev);
 	netif_start_queue(dev);
 
 	dev->mtu = card->initial_mtu;
@@ -8358,6 +8330,28 @@
 	card->options.fake_ll = DONT_FAKE_LL;
 }
 
+static void qeth_setup(struct net_device *dev)
+{
+	dev->tx_timeout = &qeth_tx_timeout;
+	dev->watchdog_timeo = QETH_TX_TIMEOUT;
+	dev->open = qeth_open;
+	dev->stop = qeth_stop;
+	dev->set_config = qeth_set_config;
+	dev->hard_start_xmit = qeth_hard_start_xmit;
+	dev->do_ioctl = qeth_do_ioctl;
+	dev->get_stats = qeth_get_stats;
+	dev->change_mtu = qeth_change_mtu;
+#ifdef QETH_VLAN
+	dev->vlan_rx_register = qeth_vlan_rx_register;
+	dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
+#endif
+	dev->set_multicast_list = qeth_set_multicast_list;
+	dev->set_mac_address = qeth_set_mac_address;
+	dev->neigh_setup = qeth_neigh_setup;
+	dev->addr_len = OSA_ADDR_LEN;	/* is ok for eth, tr, atm lane */
+	SET_MODULE_OWNER(dev);
+}
+
 static int
 qeth_alloc_card_stuff(struct qeth_card *card)
 {
@@ -8385,11 +8379,9 @@
 		goto exit_dma2;
 	memset(card->dma_stuff->sendbuf, 0, QETH_BUFSIZE);
 
-	card->dev = (struct net_device *) kmalloc(sizeof (struct net_device),
-						  GFP_KERNEL);
+	card->dev = alloc_netdev(0, "", qeth_setup);
 	if (!card->dev)
 		goto exit_dev;
-	memset(card->dev, 0, sizeof (struct net_device));
 
 	card->stats =
 	    (struct net_device_stats *)
diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
--- a/drivers/usb/net/catc.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/usb/net/catc.c	Wed Feb 11 22:30:57 2004
@@ -838,7 +838,7 @@
 			usb_free_urb(catc->rx_urb);
 		if (catc->irq_urb)
 			usb_free_urb(catc->irq_urb);
-		kfree(netdev);
+		free_netdev(netdev);
 		kfree(catc);
 		return -ENOMEM;
 	}
@@ -943,7 +943,7 @@
 		usb_free_urb(catc->tx_urb);
 		usb_free_urb(catc->rx_urb);
 		usb_free_urb(catc->irq_urb);
-		kfree(netdev);
+		free_netdev(netdev);
 		kfree(catc);
 		return -EIO;
 	}
diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
--- a/drivers/usb/net/kaweth.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/usb/net/kaweth.c	Wed Feb 11 22:30:57 2004
@@ -1150,7 +1150,7 @@
 err_only_tx:
 	usb_free_urb(kaweth->tx_urb);
 err_no_urb:
-	kfree(netdev);
+	free_netdev(netdev);
 err_no_netdev:
 	kfree(kaweth);
 	return -EIO;
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/usb/net/pegasus.c	Wed Feb 11 22:30:57 2004
@@ -1283,7 +1283,7 @@
 	usb_set_intfdata(intf, NULL);
 	free_skb_pool(pegasus);
 out3:
-	kfree(net);
+	free_netdev(net);
 out2:
 	free_all_urbs(pegasus);
 out1:
diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
--- a/drivers/usb/net/rtl8150.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/usb/net/rtl8150.c	Wed Feb 11 22:30:57 2004
@@ -852,7 +852,7 @@
 	free_all_urbs(dev);
 out:
 	kfree(dev->intr_buff);
-	kfree(netdev);
+	free_netdev(netdev);
 	kfree(dev);
 	return -EIO;
 }
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	Wed Feb 11 22:30:57 2004
+++ b/drivers/usb/net/usbnet.c	Wed Feb 11 22:30:57 2004
@@ -2981,7 +2981,7 @@
 	if (dev->driver_info->unbind)
 		dev->driver_info->unbind (dev, intf);
 
-	kfree(dev->net);
+	free_netdev(dev->net);
 	kfree (dev);
 	usb_put_dev (xdev);
 }
@@ -3111,7 +3111,7 @@
 	if (info->unbind)
 		info->unbind (dev, udev);
 out2:
-	kfree(net);
+	free_netdev(net);
 out1:
 	kfree(dev);
 out:
diff -Nru a/include/linux/hdlc.h b/include/linux/hdlc.h
--- a/include/linux/hdlc.h	Wed Feb 11 22:30:57 2004
+++ b/include/linux/hdlc.h	Wed Feb 11 22:30:57 2004
@@ -75,7 +75,7 @@
 
 
 typedef struct pvc_device_struct {
-	struct hdlc_device_struct *master;
+	struct net_device *master;
 	struct net_device *main;
 	struct net_device *ether; /* bridged Ethernet interface */
 	struct pvc_device_struct *next;	/* Sorted in ascending DLCI order */
@@ -96,11 +96,10 @@
 
 typedef struct hdlc_device_struct {
 	/* To be initialized by hardware driver */
-	struct net_device netdev; /* master net device - must be first */
 	struct net_device_stats stats;
 
 	/* used by HDLC layer to take control over HDLC device from hw driver*/
-	int (*attach)(struct hdlc_device_struct *hdlc,
+	int (*attach)(struct net_device *dev,
 		      unsigned short encoding, unsigned short parity);
 
 	/* hardware driver must handle this instead of dev->hard_start_xmit */
@@ -109,13 +108,13 @@
 
 	/* Things below are for HDLC layer internal use only */
 	struct {
-		int (*open)(struct hdlc_device_struct *hdlc);
-		void (*close)(struct hdlc_device_struct *hdlc);
+		int (*open)(struct net_device *dev);
+		void (*close)(struct net_device *dev);
 
 		/* if open & DCD */
-		void (*start)(struct hdlc_device_struct *hdlc);
+		void (*start)(struct net_device *dev);
 		/* if open & !DCD */
-		void (*stop)(struct hdlc_device_struct *hdlc);
+		void (*stop)(struct net_device *dev);
 
 		void (*detach)(struct hdlc_device_struct *hdlc);
 		int (*netif_rx)(struct sk_buff *skb);
@@ -167,16 +166,17 @@
 					      int new_mtu);
 		}ppp;
 	}state;
+	void *priv;
 }hdlc_device;
 
 
 
-int hdlc_raw_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_raw_eth_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
-int hdlc_x25_ioctl(hdlc_device *hdlc, struct ifreq *ifr);
+int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr);
+int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr);
 
 
 /* Exported from hdlc.o */
@@ -185,19 +185,14 @@
 int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 
 /* Must be used by hardware driver on module startup/exit */
-int register_hdlc_device(hdlc_device *hdlc);
-void unregister_hdlc_device(hdlc_device *hdlc);
-
-
-static __inline__ struct net_device* hdlc_to_dev(hdlc_device *hdlc)
-{
-	return &hdlc->netdev;
-}
+int register_hdlc_device(struct net_device *dev);
+void unregister_hdlc_device(struct net_device *dev);
 
+struct net_device *alloc_hdlcdev(void *priv);
 
 static __inline__ hdlc_device* dev_to_hdlc(struct net_device *dev)
 {
-	return (hdlc_device*)dev;
+	return netdev_priv(dev);
 }
 
 
@@ -207,12 +202,6 @@
 }
 
 
-static __inline__ const char *hdlc_to_name(hdlc_device *hdlc)
-{
-	return hdlc_to_dev(hdlc)->name;
-}
-
-
 static __inline__ void debug_frame(const struct sk_buff *skb)
 {
 	int i;
@@ -229,11 +218,11 @@
 
 
 /* Must be called by hardware driver when HDLC device is being opened */
-int hdlc_open(hdlc_device *hdlc);
+int hdlc_open(struct net_device *dev);
 /* Must be called by hardware driver when HDLC device is being closed */
-void hdlc_close(hdlc_device *hdlc);
+void hdlc_close(struct net_device *dev);
 /* Called by hardware driver when DCD line level changes */
-void hdlc_set_carrier(int on, hdlc_device *hdlc);
+void hdlc_set_carrier(int on, struct net_device *dev);
 
 /* May be used by hardware driver to gain control over HDLC device */
 static __inline__ void hdlc_proto_detach(hdlc_device *hdlc)
@@ -241,6 +230,12 @@
 	if (hdlc->proto.detach)
 		hdlc->proto.detach(hdlc);
 	hdlc->proto.detach = NULL;
+}
+
+
+static __inline__ struct net_device_stats *hdlc_stats(struct net_device *dev)
+{
+	return &dev_to_hdlc(dev)->stats;
 }
 
 
diff -Nru a/include/linux/if_bonding.h b/include/linux/if_bonding.h
--- a/include/linux/if_bonding.h	Wed Feb 11 22:30:57 2004
+++ b/include/linux/if_bonding.h	Wed Feb 11 22:30:57 2004
@@ -32,6 +32,9 @@
  * 2003/05/01 - Amir Noam <amir.noam at intel dot com>
  *	- Added ABI version control to restore compatibility between
  *	  new/old ifenslave and new/old bonding.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
 #ifndef _LINUX_IF_BONDING_H
@@ -86,7 +89,7 @@
 typedef struct ifslave
 {
 	__s32 slave_id; /* Used as an IN param to the BOND_SLAVE_INFO_QUERY ioctl */
-	__s8 slave_name[IFNAMSIZ];
+	char slave_name[IFNAMSIZ];
 	__s8 link;
 	__s8 state;
 	__u32  link_failure_count;
diff -Nru a/include/linux/if_pppvar.h b/include/linux/if_pppvar.h
--- a/include/linux/if_pppvar.h	Wed Feb 11 22:30:57 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,138 +0,0 @@
-/*	From: if_pppvar.h,v 1.2 1995/06/12 11:36:51 paulus Exp */
-/*
- * if_pppvar.h - private structures and declarations for PPP.
- *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies.  This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-/*
- *  ==FILEVERSION 990806==
- *
- *  NOTE TO MAINTAINERS:
- *   If you modify this file at all, please set the above date.
- *   if_pppvar.h is shipped with a PPP distribution as well as with the kernel;
- *   if everyone increases the FILEVERSION number above, then scripts
- *   can do the right thing when deciding whether to install a new if_pppvar.h
- *   file.  Don't change the format of that line otherwise, so the
- *   installation script can recognize it.
- */
-
-/*
- * Supported network protocols.  These values are used for
- * indexing sc_npmode.
- */
-
-#define NP_IP	0		/* Internet Protocol */
-#define NP_IPX	1		/* IPX protocol */
-#define NP_AT	2		/* Appletalk protocol */
-#define NP_IPV6	3		/* Internet Protocol */
-#define NUM_NP	4		/* Number of NPs. */
-
-#define OBUFSIZE	256	/* # chars of output buffering */
-
-/*
- * Structure describing each ppp unit.
- */
-
-struct ppp {
-	int		magic;		/* magic value for structure	*/
-	struct ppp	*next;		/* unit with next index		*/
-	unsigned long	inuse;		/* are we allocated?		*/
-	int		line;		/* network interface unit #	*/
-	__u32		flags;		/* miscellaneous control flags	*/
-	int		mtu;		/* maximum xmit frame size	*/
-	int		mru;		/* maximum receive frame size	*/
-	struct slcompress *slcomp;	/* for TCP header compression	*/
-	struct sk_buff_head xmt_q;	/* frames to send from pppd	*/
-	struct sk_buff_head rcv_q;	/* frames for pppd to read	*/
-	unsigned long	xmit_busy;	/* bit 0 set when xmitter busy  */
-
-	/* Information specific to using ppp on async serial lines. */
-	struct tty_struct *tty;		/* ptr to TTY structure	*/
-	struct tty_struct *backup_tty;	/* TTY to use if tty gets closed */
-	__u8		escape;		/* 0x20 if prev char was PPP_ESC */
-	__u8		toss;		/* toss this frame		*/
-	volatile __u8	tty_pushing;	/* internal state flag		*/
-	volatile __u8	woke_up;	/* internal state flag		*/
-	__u32		xmit_async_map[8]; /* 1 bit means that given control 
-					   character is quoted on output*/
-	__u32		recv_async_map; /* 1 bit means that given control 
-					   character is ignored on input*/
-	__u32		bytes_sent;	/* Bytes sent on frame	*/
-	__u32		bytes_rcvd;	/* Bytes recvd on frame	*/
-
-	/* Async transmission information */
-	struct sk_buff	*tpkt;		/* frame currently being sent	*/
-	int		tpkt_pos;	/* how much of it we've done	*/
-	__u16		tfcs;		/* FCS so far for it		*/
-	unsigned char	*optr;		/* where we're up to in sending */
-	unsigned char	*olim;		/* points past last valid char	*/
-
-	/* Async reception information */
-	struct sk_buff	*rpkt;		/* frame currently being rcvd	*/
-	__u16		rfcs;		/* FCS so far of rpkt		*/
-
-	/* Queues for select() functionality */
-	wait_queue_head_t read_wait;	/* queue for reading processes	*/
-
-	/* info for detecting idle channels */
-	unsigned long	last_xmit;	/* time of last transmission	*/
-	unsigned long	last_recv;	/* time last packet received    */
-
-	/* Statistic information */
-	struct pppstat	stats;		/* statistic information	*/
-
-	/* PPP compression protocol information */
-	struct	compressor *sc_xcomp;	/* transmit compressor */
-	void	*sc_xc_state;		/* transmit compressor state */
-	struct	compressor *sc_rcomp;	/* receive decompressor */
-	void	*sc_rc_state;		/* receive decompressor state */
-
-	enum	NPmode sc_npmode[NUM_NP]; /* what to do with each NP */
-	int	 sc_xfer;		/* PID of reserved PPP table */
-	char	name[16];		/* space for unit name */
-	struct net_device	dev;		/* net device structure */
-	struct net_device_stats estats;	/* more detailed stats */
-
-	/* tty output buffer */
-	unsigned char	obuf[OBUFSIZE];	/* buffer for characters to send */
-};
-
-#define PPP_MAGIC	0x5002
-#define PPP_VERSION	"2.3.7"
diff -Nru a/include/linux/isdn.h b/include/linux/isdn.h
--- a/include/linux/isdn.h	Wed Feb 11 22:30:57 2004
+++ b/include/linux/isdn.h	Wed Feb 11 22:30:57 2004
@@ -192,7 +192,6 @@
 
 #include <linux/ppp_defs.h>
 #include <linux/if_ppp.h>
-#include <linux/if_pppvar.h>
 
 #include <linux/isdn_ppp.h>
 #endif
diff -Nru a/include/linux/lapb.h b/include/linux/lapb.h
--- a/include/linux/lapb.h	Wed Feb 11 22:30:57 2004
+++ b/include/linux/lapb.h	Wed Feb 11 22:30:57 2004
@@ -24,12 +24,12 @@
 #define	LAPB_DCE		0x04
 
 struct lapb_register_struct {
-	void (*connect_confirmation)(void *token, int reason);
-	void (*connect_indication)(void *token, int reason);
-	void (*disconnect_confirmation)(void *token, int reason);
-	void (*disconnect_indication)(void *token, int reason);
-	int  (*data_indication)(void *token, struct sk_buff *skb);
-	void (*data_transmit)(void *token, struct sk_buff *skb);
+	void (*connect_confirmation)(struct net_device *dev, int reason);
+	void (*connect_indication)(struct net_device *dev, int reason);
+	void (*disconnect_confirmation)(struct net_device *dev, int reason);
+	void (*disconnect_indication)(struct net_device *dev, int reason);
+	int  (*data_indication)(struct net_device *dev, struct sk_buff *skb);
+	void (*data_transmit)(struct net_device *dev, struct sk_buff *skb);
 };
 
 struct lapb_parms_struct {
@@ -44,13 +44,13 @@
 	unsigned int mode;
 };
 
-extern int lapb_register(void *token, struct lapb_register_struct *callbacks);
-extern int lapb_unregister(void *token);
-extern int lapb_getparms(void *token, struct lapb_parms_struct *parms);
-extern int lapb_setparms(void *token, struct lapb_parms_struct *parms);
-extern int lapb_connect_request(void *token);
-extern int lapb_disconnect_request(void *token);
-extern int lapb_data_request(void *token, struct sk_buff *skb);
-extern int lapb_data_received(void *token, struct sk_buff *skb);
+extern int lapb_register(struct net_device *dev, struct lapb_register_struct *callbacks);
+extern int lapb_unregister(struct net_device *dev);
+extern int lapb_getparms(struct net_device *dev, struct lapb_parms_struct *parms);
+extern int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms);
+extern int lapb_connect_request(struct net_device *dev);
+extern int lapb_disconnect_request(struct net_device *dev);
+extern int lapb_data_request(struct net_device *dev, struct sk_buff *skb);
+extern int lapb_data_received(struct net_device *dev, struct sk_buff *skb);
 
 #endif
diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h	Wed Feb 11 22:30:57 2004
+++ b/include/linux/netdevice.h	Wed Feb 11 22:30:57 2004
@@ -456,6 +456,12 @@
 						     unsigned char *haddr);
 	int			(*neigh_setup)(struct net_device *dev, struct neigh_parms *);
 	int			(*accept_fastpath)(struct net_device *, struct dst_entry*);
+#ifdef CONFIG_NETPOLL_RX
+	int			netpoll_rx;
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	void                    (*poll_controller)(struct net_device *dev);
+#endif
 
 	/* bridge stuff */
 	struct net_bridge_port	*br_port;
@@ -545,6 +551,9 @@
 extern struct net_device	*dev_get_by_index(int ifindex);
 extern struct net_device	*__dev_get_by_index(int ifindex);
 extern int		dev_restart(struct net_device *dev);
+#ifdef CONFIG_NETPOLL_TRAP
+extern int		netpoll_trap(void);
+#endif
 
 typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len);
 extern int		register_gifconf(unsigned int family, gifconf_func_t * gifconf);
@@ -603,12 +612,20 @@
 
 static inline void netif_wake_queue(struct net_device *dev)
 {
+#ifdef CONFIG_NETPOLL_TRAP
+	if (netpoll_trap())
+		return;
+#endif
 	if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state))
 		__netif_schedule(dev);
 }
 
 static inline void netif_stop_queue(struct net_device *dev)
 {
+#ifdef CONFIG_NETPOLL_TRAP
+	if (netpoll_trap())
+		return;
+#endif
 	set_bit(__LINK_STATE_XOFF, &dev->state);
 }
 
diff -Nru a/include/linux/netpoll.h b/include/linux/netpoll.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/netpoll.h	Wed Feb 11 22:30:58 2004
@@ -0,0 +1,38 @@
+/*
+ * Common code for low-level network console, dump, and debugger code
+ *
+ * Derived from netconsole, kgdb-over-ethernet, and netdump patches
+ */
+
+#ifndef _LINUX_NETPOLL_H
+#define _LINUX_NETPOLL_H
+
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+
+struct netpoll;
+
+struct netpoll {
+	struct net_device *dev;
+	char dev_name[16], *name;
+	void (*rx_hook)(struct netpoll *, int, char *, int);
+	u32 local_ip, remote_ip;
+	u16 local_port, remote_port;
+	unsigned char local_mac[6], remote_mac[6];
+	struct list_head rx_list;
+};
+
+void netpoll_poll(struct netpoll *np);
+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
+void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
+int netpoll_parse_options(struct netpoll *np, char *opt);
+int netpoll_setup(struct netpoll *np);
+int netpoll_trap(void);
+void netpoll_set_trap(int trap);
+void netpoll_cleanup(struct netpoll *np);
+int netpoll_rx(struct sk_buff *skb);
+
+
+#endif
diff -Nru a/include/linux/ppp.h b/include/linux/ppp.h
--- a/include/linux/ppp.h	Wed Feb 11 22:30:56 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,4 +0,0 @@
-/*
- *	Back compatibility for a while.
- */
-#include <linux/if_ppp.h>
diff -Nru a/include/net/lapb.h b/include/net/lapb.h
--- a/include/net/lapb.h	Wed Feb 11 22:30:57 2004
+++ b/include/net/lapb.h	Wed Feb 11 22:30:57 2004
@@ -80,7 +80,7 @@
  */
 struct lapb_cb {
 	struct list_head	node;
-	void			*token;
+	struct net_device	*dev;
 
 	/* Link status fields */
 	unsigned int		mode;
diff -Nru a/net/8021q/vlan.c b/net/8021q/vlan.c
--- a/net/8021q/vlan.c	Wed Feb 11 22:30:57 2004
+++ b/net/8021q/vlan.c	Wed Feb 11 22:30:57 2004
@@ -566,7 +566,7 @@
 	goto out_put_dev;
 
 out_free_newdev:
-	kfree(new_dev);
+	free_netdev(new_dev);
 
 out_unlock:
 	rtnl_unlock();
diff -Nru a/net/Kconfig b/net/Kconfig
--- a/net/Kconfig	Wed Feb 11 22:30:56 2004
+++ b/net/Kconfig	Wed Feb 11 22:30:56 2004
@@ -664,4 +664,20 @@
 
 source "net/bluetooth/Kconfig"
 
+config NETPOLL
+	def_bool NETCONSOLE
+
+config NETPOLL_RX
+	bool "Netpoll support for trapping incoming packets"
+	default n
+	depends on NETPOLL
+
+config NETPOLL_TRAP
+	bool "Netpoll traffic trapping"
+	default n
+	depends on NETPOLL
+
+config NET_POLL_CONTROLLER
+	def_bool NETPOLL
+
 endmenu
diff -Nru a/net/atm/lec.c b/net/atm/lec.c
--- a/net/atm/lec.c	Wed Feb 11 22:30:57 2004
+++ b/net/atm/lec.c	Wed Feb 11 22:30:57 2004
@@ -798,7 +798,7 @@
                         return -ENOMEM;
                 snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
                 if (register_netdev(dev_lec[i])) {
-                        kfree(dev_lec[i]);
+                        free_netdev(dev_lec[i]);
                         return -EINVAL;
                 }
 
diff -Nru a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
--- a/net/bluetooth/bnep/core.c	Wed Feb 11 22:30:57 2004
+++ b/net/bluetooth/bnep/core.c	Wed Feb 11 22:30:57 2004
@@ -501,7 +501,7 @@
 	__bnep_unlink_session(s);
 
 	up_write(&bnep_session_sem);
-	kfree(dev);
+	free_netdev(dev);
 	return 0;
 }
 
@@ -588,7 +588,7 @@
 
 failed:
 	up_write(&bnep_session_sem);
-	kfree(dev);
+	free_netdev(dev);
 	return err;
 }
 
diff -Nru a/net/core/Makefile b/net/core/Makefile
--- a/net/core/Makefile	Wed Feb 11 22:30:57 2004
+++ b/net/core/Makefile	Wed Feb 11 22:30:57 2004
@@ -13,3 +13,4 @@
 obj-$(CONFIG_NET_DIVERT) += dv.o
 obj-$(CONFIG_NET_PKTGEN) += pktgen.o
 obj-$(CONFIG_NET_RADIO) += wireless.o
+obj-$(CONFIG_NETPOLL) += netpoll.o
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	Wed Feb 11 22:30:57 2004
+++ b/net/core/dev.c	Wed Feb 11 22:30:57 2004
@@ -105,6 +105,7 @@
 #include <linux/kmod.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
+#include <linux/netpoll.h>
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>		/* Note : will define WIRELESS_EXT */
 #include <net/iw_handler.h>
@@ -1572,6 +1573,13 @@
 	struct softnet_data *queue;
 	unsigned long flags;
 
+#ifdef CONFIG_NETPOLL_RX
+	if (skb->dev->netpoll_rx && netpoll_rx(skb)) {
+		kfree_skb(skb);
+		return NET_RX_DROP;
+	}
+#endif
+
 	if (!skb->stamp.tv_sec)
 		do_gettimeofday(&skb->stamp);
 
@@ -1726,6 +1734,13 @@
 	struct packet_type *ptype, *pt_prev;
 	int ret = NET_RX_DROP;
 	unsigned short type = skb->protocol;
+
+#ifdef CONFIG_NETPOLL_RX
+	if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {
+		kfree_skb(skb);
+		return NET_RX_DROP;
+	}
+#endif
 
 	if (!skb->stamp.tv_sec)
 		do_gettimeofday(&skb->stamp);
diff -Nru a/net/core/netpoll.c b/net/core/netpoll.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/net/core/netpoll.c	Wed Feb 11 22:30:58 2004
@@ -0,0 +1,651 @@
+/*
+ * Common framework for low-level network console, dump, and debugger code
+ *
+ * Sep 8 2003  Matt Mackall <mpm@selenic.com>
+ */
+
+#include <linux/smp_lock.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/string.h>
+#include <linux/inetdevice.h>
+#include <linux/inet.h>
+#include <linux/interrupt.h>
+#include <linux/netpoll.h>
+#include <linux/sched.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+
+/*
+ * We maintain a small pool of fully-sized skbs, to make sure the
+ * message gets out even in extreme OOM situations.
+ */
+
+#define MAX_SKBS 32
+#define MAX_UDP_CHUNK 1460
+
+static spinlock_t skb_list_lock = SPIN_LOCK_UNLOCKED;
+static int nr_skbs;
+static struct sk_buff *skbs;
+
+static spinlock_t rx_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(rx_list);
+
+static int trapped;
+
+#define MAX_SKB_SIZE \
+		(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
+				sizeof(struct iphdr) + sizeof(struct ethhdr))
+
+static void zap_completion_queue(void);
+
+static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
+			     unsigned short ulen, u32 saddr, u32 daddr)
+{
+	if (uh->check == 0)
+		return 0;
+
+	if (skb->ip_summed == CHECKSUM_HW)
+		return csum_tcpudp_magic(
+			saddr, daddr, ulen, IPPROTO_UDP, skb->csum);
+
+	skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+
+	return csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
+}
+
+void netpoll_poll(struct netpoll *np)
+{
+	int budget = 1;
+
+	if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
+		return;
+
+	/* Process pending work on NIC */
+	np->dev->poll_controller(np->dev);
+
+	/* If scheduling is stopped, tickle NAPI bits */
+	if(trapped && np->dev->poll &&
+	   test_bit(__LINK_STATE_RX_SCHED, &np->dev->state))
+		np->dev->poll(np->dev, &budget);
+	zap_completion_queue();
+}
+
+static void refill_skbs(void)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&skb_list_lock, flags);
+	while (nr_skbs < MAX_SKBS) {
+		skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
+		if (!skb)
+			break;
+
+		skb->next = skbs;
+		skbs = skb;
+		nr_skbs++;
+	}
+	spin_unlock_irqrestore(&skb_list_lock, flags);
+}
+
+static void zap_completion_queue(void)
+{
+	unsigned long flags;
+	struct softnet_data *sd = &get_cpu_var(softnet_data);
+
+	if (sd->completion_queue) {
+		struct sk_buff *clist;
+
+		local_irq_save(flags);
+		clist = sd->completion_queue;
+		sd->completion_queue = NULL;
+		local_irq_restore(flags);
+
+		while (clist != NULL) {
+			struct sk_buff *skb = clist;
+			clist = clist->next;
+			__kfree_skb(skb);
+		}
+	}
+
+	put_cpu_var(softnet_data);
+}
+
+static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve)
+{
+	int once = 1, count = 0;
+	unsigned long flags;
+	struct sk_buff *skb = NULL;
+
+	zap_completion_queue();
+repeat:
+	if (nr_skbs < MAX_SKBS)
+		refill_skbs();
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+
+	if (!skb) {
+		spin_lock_irqsave(&skb_list_lock, flags);
+		skb = skbs;
+		if (skb)
+			skbs = skb->next;
+		skb->next = NULL;
+		nr_skbs--;
+		spin_unlock_irqrestore(&skb_list_lock, flags);
+	}
+
+	if(!skb) {
+		count++;
+		if (once && (count == 1000000)) {
+			printk("out of netpoll skbs!\n");
+			once = 0;
+		}
+		netpoll_poll(np);
+		goto repeat;
+	}
+
+	atomic_set(&skb->users, 1);
+	skb_reserve(skb, reserve);
+	return skb;
+}
+
+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
+{
+	int status;
+
+repeat:
+	if(!np || !np->dev || !netif_running(np->dev)) {
+		__kfree_skb(skb);
+		return;
+	}
+
+	spin_lock(&np->dev->xmit_lock);
+	np->dev->xmit_lock_owner = smp_processor_id();
+
+	if (netif_queue_stopped(np->dev)) {
+		np->dev->xmit_lock_owner = -1;
+		spin_unlock(&np->dev->xmit_lock);
+
+		netpoll_poll(np);
+		goto repeat;
+	}
+
+	status = np->dev->hard_start_xmit(skb, np->dev);
+	np->dev->xmit_lock_owner = -1;
+	spin_unlock(&np->dev->xmit_lock);
+
+	/* transmit busy */
+	if(status)
+		goto repeat;
+}
+
+void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
+{
+	int total_len, eth_len, ip_len, udp_len;
+	struct sk_buff *skb;
+	struct udphdr *udph;
+	struct iphdr *iph;
+	struct ethhdr *eth;
+
+	udp_len = len + sizeof(*udph);
+	ip_len = eth_len = udp_len + sizeof(*iph);
+	total_len = eth_len + ETH_HLEN;
+
+	skb = find_skb(np, total_len, total_len - len);
+	if (!skb)
+		return;
+
+	memcpy(skb->data, msg, len);
+	skb->len += len;
+
+	udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
+	udph->source = htons(np->local_port);
+	udph->dest = htons(np->remote_port);
+	udph->len = htons(udp_len);
+	udph->check = 0;
+
+	iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
+
+	iph->version  = 4;
+	iph->ihl      = 5;
+	iph->tos      = 0;
+	iph->tot_len  = htons(ip_len);
+	iph->id       = 0;
+	iph->frag_off = 0;
+	iph->ttl      = 64;
+	iph->protocol = IPPROTO_UDP;
+	iph->check    = 0;
+	iph->saddr    = htonl(np->local_ip);
+	iph->daddr    = htonl(np->remote_ip);
+	iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+	eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
+
+	eth->h_proto = htons(ETH_P_IP);
+	memcpy(eth->h_source, np->local_mac, 6);
+	memcpy(eth->h_dest, np->remote_mac, 6);
+
+	netpoll_send_skb(np, skb);
+}
+
+static void arp_reply(struct sk_buff *skb)
+{
+	struct in_device *in_dev = (struct in_device *) skb->dev->ip_ptr;
+	struct arphdr *arp;
+	unsigned char *arp_ptr, *sha, *tha;
+	int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
+	u32 sip, tip;
+	struct sk_buff *send_skb;
+	unsigned long flags;
+	struct list_head *p;
+	struct netpoll *np = 0;
+
+	spin_lock_irqsave(&rx_list_lock, flags);
+	list_for_each(p, &rx_list) {
+		np = list_entry(p, struct netpoll, rx_list);
+		if ( np->dev == skb->dev )
+			break;
+		np = 0;
+	}
+	spin_unlock_irqrestore(&rx_list_lock, flags);
+
+	if (!np) return;
+
+	/* No arp on this interface */
+	if (!in_dev || skb->dev->flags & IFF_NOARP)
+		return;
+
+	if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+				 (2 * skb->dev->addr_len) +
+				 (2 * sizeof(u32)))))
+		return;
+
+	skb->h.raw = skb->nh.raw = skb->data;
+	arp = skb->nh.arph;
+
+	if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
+	     arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
+	    arp->ar_pro != htons(ETH_P_IP) ||
+	    arp->ar_op != htons(ARPOP_REQUEST))
+		return;
+
+	arp_ptr= (unsigned char *)(arp+1);
+	sha = arp_ptr;
+	arp_ptr += skb->dev->addr_len;
+	memcpy(&sip, arp_ptr, 4);
+	arp_ptr += 4;
+	tha = arp_ptr;
+	arp_ptr += skb->dev->addr_len;
+	memcpy(&tip, arp_ptr, 4);
+
+	/* Should we ignore arp? */
+	if (tip != in_dev->ifa_list->ifa_address ||
+	    LOOPBACK(tip) || MULTICAST(tip))
+		return;
+
+
+	size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
+	send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
+			    LL_RESERVED_SPACE(np->dev));
+
+	if (!send_skb)
+		return;
+
+	send_skb->nh.raw = send_skb->data;
+	arp = (struct arphdr *) skb_put(send_skb, size);
+	send_skb->dev = skb->dev;
+	send_skb->protocol = htons(ETH_P_ARP);
+
+	/* Fill the device header for the ARP frame */
+
+	if (np->dev->hard_header &&
+	    np->dev->hard_header(send_skb, skb->dev, ptype,
+				       np->remote_mac, np->local_mac,
+				       send_skb->len) < 0) {
+		kfree_skb(send_skb);
+		return;
+	}
+
+	/*
+	 * Fill out the arp protocol part.
+	 *
+	 * we only support ethernet device type,
+	 * which (according to RFC 1390) should always equal 1 (Ethernet).
+	 */
+
+	arp->ar_hrd = htons(np->dev->type);
+	arp->ar_pro = htons(ETH_P_IP);
+	arp->ar_hln = np->dev->addr_len;
+	arp->ar_pln = 4;
+	arp->ar_op = htons(type);
+
+	arp_ptr=(unsigned char *)(arp + 1);
+	memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len);
+	arp_ptr += np->dev->addr_len;
+	memcpy(arp_ptr, &tip, 4);
+	arp_ptr += 4;
+	memcpy(arp_ptr, np->local_mac, np->dev->addr_len);
+	arp_ptr += np->dev->addr_len;
+	memcpy(arp_ptr, &sip, 4);
+
+	netpoll_send_skb(np, send_skb);
+}
+
+int netpoll_rx(struct sk_buff *skb)
+{
+	int proto, len, ulen;
+	struct iphdr *iph;
+	struct udphdr *uh;
+	struct netpoll *np;
+	struct list_head *p;
+	unsigned long flags;
+
+	if (skb->dev->type != ARPHRD_ETHER)
+		goto out;
+
+	/* check if netpoll clients need ARP */
+	if (skb->protocol == __constant_htons(ETH_P_ARP) && trapped) {
+		arp_reply(skb);
+		return 1;
+	}
+
+	proto = ntohs(skb->mac.ethernet->h_proto);
+	if (proto != ETH_P_IP)
+		goto out;
+	if (skb->pkt_type == PACKET_OTHERHOST)
+		goto out;
+	if (skb_shared(skb))
+		goto out;
+
+	iph = (struct iphdr *)skb->data;
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		goto out;
+	if (iph->ihl < 5 || iph->version != 4)
+		goto out;
+	if (!pskb_may_pull(skb, iph->ihl*4))
+		goto out;
+	if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
+		goto out;
+
+	len = ntohs(iph->tot_len);
+	if (skb->len < len || len < iph->ihl*4)
+		goto out;
+
+	if (iph->protocol != IPPROTO_UDP)
+		goto out;
+
+	len -= iph->ihl*4;
+	uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
+	ulen = ntohs(uh->len);
+
+	if (ulen != len)
+		goto out;
+	if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr) < 0)
+		goto out;
+
+	spin_lock_irqsave(&rx_list_lock, flags);
+	list_for_each(p, &rx_list) {
+		np = list_entry(p, struct netpoll, rx_list);
+		if (np->dev && np->dev != skb->dev)
+			continue;
+		if (np->local_ip && np->local_ip != ntohl(iph->daddr))
+			continue;
+		if (np->remote_ip && np->remote_ip != ntohl(iph->saddr))
+			continue;
+		if (np->local_port && np->local_port != ntohs(uh->dest))
+			continue;
+
+		spin_unlock_irqrestore(&rx_list_lock, flags);
+
+		if (np->rx_hook)
+			np->rx_hook(np, ntohs(uh->source),
+				    (char *)(uh+1),
+				    ulen - sizeof(struct udphdr));
+
+		return 1;
+	}
+	spin_unlock_irqrestore(&rx_list_lock, flags);
+
+out:
+	return trapped;
+}
+
+int netpoll_parse_options(struct netpoll *np, char *opt)
+{
+	char *cur=opt, *delim;
+
+	if(*cur != '@') {
+		if ((delim = strchr(cur, '@')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->local_port=simple_strtol(cur, 0, 10);
+		cur=delim;
+	}
+	cur++;
+	printk(KERN_INFO "%s: local port %d\n", np->name, np->local_port);
+
+	if(*cur != '/') {
+		if ((delim = strchr(cur, '/')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->local_ip=ntohl(in_aton(cur));
+		cur=delim;
+
+		printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
+		       np->name, HIPQUAD(np->local_ip));
+	}
+	cur++;
+
+	if ( *cur != ',') {
+		/* parse out dev name */
+		if ((delim = strchr(cur, ',')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		strlcpy(np->dev_name, cur, sizeof(np->dev_name));
+		cur=delim;
+	}
+	cur++;
+
+	printk(KERN_INFO "%s: interface %s\n", np->name, np->dev_name);
+
+	if ( *cur != '@' ) {
+		/* dst port */
+		if ((delim = strchr(cur, '@')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_port=simple_strtol(cur, 0, 10);
+		cur=delim;
+	}
+	cur++;
+	printk(KERN_INFO "%s: remote port %d\n", np->name, np->remote_port);
+
+	/* dst ip */
+	if ((delim = strchr(cur, '/')) == NULL)
+		goto parse_failed;
+	*delim=0;
+	np->remote_ip=ntohl(in_aton(cur));
+	cur=delim+1;
+
+	printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n",
+		       np->name, HIPQUAD(np->remote_ip));
+
+	if( *cur != 0 )
+	{
+		/* MAC address */
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[0]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[1]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[2]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[3]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		if ((delim = strchr(cur, ':')) == NULL)
+			goto parse_failed;
+		*delim=0;
+		np->remote_mac[4]=simple_strtol(cur, 0, 16);
+		cur=delim+1;
+		np->remote_mac[5]=simple_strtol(cur, 0, 16);
+	}
+
+	printk(KERN_INFO "%s: remote ethernet address "
+	       "%02x:%02x:%02x:%02x:%02x:%02x\n",
+	       np->name,
+	       np->remote_mac[0],
+	       np->remote_mac[1],
+	       np->remote_mac[2],
+	       np->remote_mac[3],
+	       np->remote_mac[4],
+	       np->remote_mac[5]);
+
+	return 0;
+
+ parse_failed:
+	printk(KERN_INFO "%s: couldn't parse config at %s!\n",
+	       np->name, cur);
+	return -1;
+}
+
+int netpoll_setup(struct netpoll *np)
+{
+	struct net_device *ndev = NULL;
+	struct in_device *in_dev;
+
+	if (np->dev_name)
+		ndev = dev_get_by_name(np->dev_name);
+	if (!ndev) {
+		printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
+		       np->name, np->dev_name);
+		return -1;
+	}
+	if (!ndev->poll_controller) {
+		printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
+		       np->name, np->dev_name);
+		goto release;
+	}
+
+	if (!(ndev->flags & IFF_UP)) {
+		unsigned short oflags;
+		unsigned long atmost, atleast;
+
+		printk(KERN_INFO "%s: device %s not up yet, forcing it\n",
+		       np->name, np->dev_name);
+
+		oflags = ndev->flags;
+
+		rtnl_shlock();
+		if (dev_change_flags(ndev, oflags | IFF_UP) < 0) {
+			printk(KERN_ERR "%s: failed to open %s\n",
+			       np->name, np->dev_name);
+			rtnl_shunlock();
+			goto release;
+		}
+		rtnl_shunlock();
+
+		atleast = jiffies + HZ/10;
+ 		atmost = jiffies + 10*HZ;
+		while (!netif_carrier_ok(ndev)) {
+			if (time_after(jiffies, atmost)) {
+				printk(KERN_NOTICE
+				       "%s: timeout waiting for carrier\n",
+				       np->name);
+				break;
+			}
+			cond_resched();
+		}
+
+		if (time_before(jiffies, atleast)) {
+			printk(KERN_NOTICE "%s: carrier detect appears flaky,"
+			       " waiting 10 seconds\n",
+			       np->name);
+			while (time_before(jiffies, atmost))
+				cond_resched();
+		}
+	}
+
+	if (!memcmp(np->local_mac, "\0\0\0\0\0\0", 6) && ndev->dev_addr)
+		memcpy(np->local_mac, ndev->dev_addr, 6);
+
+	if (!np->local_ip) {
+		in_dev = in_dev_get(ndev);
+
+		if (!in_dev) {
+			printk(KERN_ERR "%s: no IP address for %s, aborting\n",
+			       np->name, np->dev_name);
+			goto release;
+		}
+
+		np->local_ip = ntohl(in_dev->ifa_list->ifa_local);
+		in_dev_put(in_dev);
+		printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
+		       np->name, HIPQUAD(np->local_ip));
+	}
+
+	np->dev = ndev;
+
+	if(np->rx_hook) {
+		unsigned long flags;
+
+#ifdef CONFIG_NETPOLL_RX
+		np->dev->netpoll_rx = 1;
+#endif
+
+		spin_lock_irqsave(&rx_list_lock, flags);
+		list_add(&np->rx_list, &rx_list);
+		spin_unlock_irqrestore(&rx_list_lock, flags);
+	}
+
+	return 0;
+ release:
+	dev_put(ndev);
+	return -1;
+}
+
+void netpoll_cleanup(struct netpoll *np)
+{
+	if(np->rx_hook) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&rx_list_lock, flags);
+		list_del(&np->rx_list);
+#ifdef CONFIG_NETPOLL_RX
+		np->dev->netpoll_rx = 0;
+#endif
+		spin_unlock_irqrestore(&rx_list_lock, flags);
+	}
+
+	dev_put(np->dev);
+	np->dev = 0;
+}
+
+int netpoll_trap()
+{
+	return trapped;
+}
+
+void netpoll_set_trap(int trap)
+{
+	trapped = trap;
+}
+
+EXPORT_SYMBOL(netpoll_set_trap);
+EXPORT_SYMBOL(netpoll_trap);
+EXPORT_SYMBOL(netpoll_parse_options);
+EXPORT_SYMBOL(netpoll_setup);
+EXPORT_SYMBOL(netpoll_cleanup);
+EXPORT_SYMBOL(netpoll_send_skb);
+EXPORT_SYMBOL(netpoll_send_udp);
+EXPORT_SYMBOL(netpoll_poll);
diff -Nru a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
--- a/net/ipv4/ip_gre.c	Wed Feb 11 22:30:57 2004
+++ b/net/ipv4/ip_gre.c	Wed Feb 11 22:30:57 2004
@@ -280,7 +280,7 @@
 	nt->parms = *parms;
 
 	if (register_netdevice(dev) < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		goto failed;
 	}
 
@@ -1276,7 +1276,7 @@
 	return err;
 fail:
 	inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
-	kfree(ipgre_fb_tunnel_dev);
+	free_netdev(ipgre_fb_tunnel_dev);
 	goto out;
 }
 
diff -Nru a/net/ipv4/ipip.c b/net/ipv4/ipip.c
--- a/net/ipv4/ipip.c	Wed Feb 11 22:30:58 2004
+++ b/net/ipv4/ipip.c	Wed Feb 11 22:30:58 2004
@@ -250,7 +250,7 @@
 	nt->parms = *parms;
 
 	if (register_netdevice(dev) < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		goto failed;
 	}
 
@@ -899,7 +899,7 @@
 	return err;
  fail:
 	xfrm4_tunnel_deregister(&ipip_handler);
-	kfree(ipip_fb_tunnel_dev);
+	free_netdev(ipip_fb_tunnel_dev);
 	goto out;
 }
 
diff -Nru a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
--- a/net/ipv4/ipmr.c	Wed Feb 11 22:30:57 2004
+++ b/net/ipv4/ipmr.c	Wed Feb 11 22:30:57 2004
@@ -209,7 +209,7 @@
 		return NULL;
 
 	if (register_netdevice(dev)) {
-		kfree(dev);
+		free_netdev(dev);
 		return NULL;
 	}
 	dev->iflink = 0;
diff -Nru a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
--- a/net/ipv6/ip6_tunnel.c	Wed Feb 11 22:30:56 2004
+++ b/net/ipv6/ip6_tunnel.c	Wed Feb 11 22:30:56 2004
@@ -245,7 +245,7 @@
 	t->parms = *p;
 
 	if ((err = register_netdevice(dev)) < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		return err;
 	}
 	dev_hold(dev);
@@ -1118,7 +1118,7 @@
 	ip6ip6_fb_tnl_dev->init = ip6ip6_fb_tnl_dev_init;
 
 	if ((err = register_netdev(ip6ip6_fb_tnl_dev))) {
-		kfree(ip6ip6_fb_tnl_dev);
+		free_netdev(ip6ip6_fb_tnl_dev);
 		goto fail;
 	}
 	return 0;
diff -Nru a/net/ipv6/sit.c b/net/ipv6/sit.c
--- a/net/ipv6/sit.c	Wed Feb 11 22:30:57 2004
+++ b/net/ipv6/sit.c	Wed Feb 11 22:30:57 2004
@@ -187,7 +187,7 @@
 	nt->parms = *parms;
 
 	if (register_netdevice(dev) < 0) {
-		kfree(dev);
+		free_netdev(dev);
 		goto failed;
 	}
 
@@ -840,6 +840,6 @@
 	return err;
  fail:
 	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
-	kfree(ipip6_fb_tunnel_dev);
+	free_netdev(ipip6_fb_tunnel_dev);
 	goto out;
 }
diff -Nru a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
--- a/net/irda/irlan/irlan_common.c	Wed Feb 11 22:30:57 2004
+++ b/net/irda/irlan/irlan_common.c	Wed Feb 11 22:30:57 2004
@@ -224,7 +224,7 @@
 		IRDA_DEBUG(2, "%s(), register_netdev() failed!\n", 
 			   __FUNCTION__ );
 		self = NULL;
-		kfree(dev);
+		free_netdev(dev);
 	} else {
 		rtnl_lock();
 		list_add_rcu(&self->dev_list, &irlans);
diff -Nru a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
--- a/net/irda/irlan/irlan_eth.c	Wed Feb 11 22:30:57 2004
+++ b/net/irda/irlan/irlan_eth.c	Wed Feb 11 22:30:57 2004
@@ -60,7 +60,7 @@
 	dev->hard_start_xmit    = irlan_eth_xmit; 
 	dev->get_stats	        = irlan_eth_get_stats;
 	dev->set_multicast_list = irlan_eth_set_multicast_list;
-	dev->destructor		= (void (*)(struct net_device *)) kfree;
+	dev->destructor		= free_netdev;
 
 	SET_MODULE_OWNER(dev);
 
diff -Nru a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
--- a/net/lapb/lapb_iface.c	Wed Feb 11 22:30:57 2004
+++ b/net/lapb/lapb_iface.c	Wed Feb 11 22:30:57 2004
@@ -81,18 +81,14 @@
 	lapb_hold(lapb);
 }
 
-/*
- *	Convert the integer token used by the device driver into a pointer
- *	to a LAPB control structure.
- */
-static struct lapb_cb *__lapb_tokentostruct(void *token)
+static struct lapb_cb *__lapb_devtostruct(struct net_device *dev)
 {
 	struct list_head *entry;
 	struct lapb_cb *lapb, *use = NULL;
 
 	list_for_each(entry, &lapb_list) {
 		lapb = list_entry(entry, struct lapb_cb, node);
-		if (lapb->token == token) {
+		if (lapb->dev == dev) {
 			use = lapb;
 			break;
 		}
@@ -104,12 +100,12 @@
 	return use;
 }
 
-static struct lapb_cb *lapb_tokentostruct(void *token)
+static struct lapb_cb *lapb_devtostruct(struct net_device *dev)
 {
 	struct lapb_cb *rc;
 
 	read_lock_bh(&lapb_list_lock);
-	rc = __lapb_tokentostruct(token);
+	rc = __lapb_devtostruct(dev);
 	read_unlock_bh(&lapb_list_lock);
 
 	return rc;
@@ -144,14 +140,14 @@
 	return lapb;
 }
 
-int lapb_register(void *token, struct lapb_register_struct *callbacks)
+int lapb_register(struct net_device *dev, struct lapb_register_struct *callbacks)
 {
 	struct lapb_cb *lapb;
 	int rc = LAPB_BADTOKEN;
 
 	write_lock_bh(&lapb_list_lock);
 
-	lapb = __lapb_tokentostruct(token);
+	lapb = __lapb_devtostruct(dev);
 	if (lapb) {
 		lapb_put(lapb);
 		goto out;
@@ -162,7 +158,7 @@
 	if (!lapb)
 		goto out;
 
-	lapb->token     = token;
+	lapb->dev       = dev;
 	lapb->callbacks = *callbacks;
 
 	__lapb_insert_cb(lapb);
@@ -175,13 +171,13 @@
 	return rc;
 }
 
-int lapb_unregister(void *token)
+int lapb_unregister(struct net_device *dev)
 {
 	struct lapb_cb *lapb;
 	int rc = LAPB_BADTOKEN;
 
 	write_unlock_bh(&lapb_list_lock);
-	lapb = __lapb_tokentostruct(token);
+	lapb = __lapb_devtostruct(dev);
 	if (!lapb)
 		goto out;
 
@@ -199,10 +195,10 @@
 	return rc;
 }
 
-int lapb_getparms(void *token, struct lapb_parms_struct *parms)
+int lapb_getparms(struct net_device *dev, struct lapb_parms_struct *parms)
 {
 	int rc = LAPB_BADTOKEN;
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 
 	if (!lapb)
 		goto out;
@@ -231,10 +227,10 @@
 	return rc;
 }
 
-int lapb_setparms(void *token, struct lapb_parms_struct *parms)
+int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms)
 {
 	int rc = LAPB_BADTOKEN;
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 
 	if (!lapb)
 		goto out;
@@ -264,9 +260,9 @@
 	return rc;
 }
 
-int lapb_connect_request(void *token)
+int lapb_connect_request(struct net_device *dev)
 {
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 	int rc = LAPB_BADTOKEN;
 
 	if (!lapb)
@@ -283,7 +279,7 @@
 	lapb_establish_data_link(lapb);
 
 #if LAPB_DEBUG > 0
-	printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->token);
+	printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->dev);
 #endif
 	lapb->state = LAPB_STATE_1;
 
@@ -294,9 +290,9 @@
 	return rc;
 }
 
-int lapb_disconnect_request(void *token)
+int lapb_disconnect_request(struct net_device *dev)
 {
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 	int rc = LAPB_BADTOKEN;
 
 	if (!lapb)
@@ -309,10 +305,10 @@
 
 		case LAPB_STATE_1:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->token);
+			printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev);
 #endif
 #if LAPB_DEBUG > 0
-			printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token);
+			printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
 #endif
 			lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 			lapb->state = LAPB_STATE_0;
@@ -333,10 +329,10 @@
 	lapb->state = LAPB_STATE_2;
 
 #if LAPB_DEBUG > 1
-	printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->token);
+	printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->dev);
 #endif
 #if LAPB_DEBUG > 0
-	printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->token);
+	printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->dev);
 #endif
 
 	rc = LAPB_OK;
@@ -346,9 +342,9 @@
 	return rc;
 }
 
-int lapb_data_request(void *token, struct sk_buff *skb)
+int lapb_data_request(struct net_device *dev, struct sk_buff *skb)
 {
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 	int rc = LAPB_BADTOKEN;
 
 	if (!lapb)
@@ -367,9 +363,9 @@
 	return rc;
 }
 
-int lapb_data_received(void *token, struct sk_buff *skb)
+int lapb_data_received(struct net_device *dev, struct sk_buff *skb)
 {
-	struct lapb_cb *lapb = lapb_tokentostruct(token);
+	struct lapb_cb *lapb = lapb_devtostruct(dev);
 	int rc = LAPB_BADTOKEN;
 
 	if (lapb) {
@@ -384,31 +380,31 @@
 void lapb_connect_confirmation(struct lapb_cb *lapb, int reason)
 {
 	if (lapb->callbacks.connect_confirmation)
-		lapb->callbacks.connect_confirmation(lapb->token, reason);
+		lapb->callbacks.connect_confirmation(lapb->dev, reason);
 }
 
 void lapb_connect_indication(struct lapb_cb *lapb, int reason)
 {
 	if (lapb->callbacks.connect_indication)
-		lapb->callbacks.connect_indication(lapb->token, reason);
+		lapb->callbacks.connect_indication(lapb->dev, reason);
 }
 
 void lapb_disconnect_confirmation(struct lapb_cb *lapb, int reason)
 {
 	if (lapb->callbacks.disconnect_confirmation)
-		lapb->callbacks.disconnect_confirmation(lapb->token, reason);
+		lapb->callbacks.disconnect_confirmation(lapb->dev, reason);
 }
 
 void lapb_disconnect_indication(struct lapb_cb *lapb, int reason)
 {
 	if (lapb->callbacks.disconnect_indication)
-		lapb->callbacks.disconnect_indication(lapb->token, reason);
+		lapb->callbacks.disconnect_indication(lapb->dev, reason);
 }
 
 int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *skb)
 {
 	if (lapb->callbacks.data_indication)
-		return lapb->callbacks.data_indication(lapb->token, skb);
+		return lapb->callbacks.data_indication(lapb->dev, skb);
 
 	kfree_skb(skb);
 	return NET_RX_CN_HIGH; /* For now; must be != NET_RX_DROP */ 
@@ -419,7 +415,7 @@
 	int used = 0;
 
 	if (lapb->callbacks.data_transmit) {
-		lapb->callbacks.data_transmit(lapb->token, skb);
+		lapb->callbacks.data_transmit(lapb->dev, skb);
 		used = 1;
 	}
 
diff -Nru a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c
--- a/net/lapb/lapb_in.c	Wed Feb 11 22:30:57 2004
+++ b/net/lapb/lapb_in.c	Wed Feb 11 22:30:57 2004
@@ -47,23 +47,23 @@
 		case LAPB_SABM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S0 RX SABM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -82,16 +82,16 @@
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S0 RX SABME(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -107,7 +107,7 @@
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
@@ -117,9 +117,9 @@
 		case LAPB_DISC:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S0 RX DISC(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb_send_control(lapb, LAPB_UA, frame->pf,
 					  LAPB_RESPONSE);
@@ -143,19 +143,19 @@
 		case LAPB_SABM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX SABM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -165,19 +165,19 @@
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX SABME(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
@@ -187,9 +187,9 @@
 		case LAPB_DISC:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX DISC(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb_send_control(lapb, LAPB_DM, frame->pf,
 					  LAPB_RESPONSE);
@@ -198,12 +198,12 @@
 		case LAPB_UA:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX UA(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf) {
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S1 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_stop_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -220,12 +220,12 @@
 		case LAPB_DM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S1 RX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf) {
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_clear_queues(lapb);
 				lapb->state = LAPB_STATE_0;
@@ -251,9 +251,9 @@
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX {SABM,SABME}(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb_send_control(lapb, LAPB_DM, frame->pf,
 					  LAPB_RESPONSE);
@@ -262,9 +262,9 @@
 		case LAPB_DISC:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb_send_control(lapb, LAPB_UA, frame->pf,
 					  LAPB_RESPONSE);
@@ -273,12 +273,12 @@
 		case LAPB_UA:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX UA(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf) {
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb->state = LAPB_STATE_0;
 				lapb_start_t1timer(lapb);
@@ -290,12 +290,12 @@
 		case LAPB_DM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf) {
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb->state = LAPB_STATE_0;
 				lapb_start_t1timer(lapb);
@@ -311,9 +311,9 @@
 		case LAPB_RR:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S2 RX {I,REJ,RNR,RR}"
-			       "(%d)\n", lapb->token, frame->pf);
+			       "(%d)\n", lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (frame->pf)
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
@@ -339,19 +339,19 @@
 		case LAPB_SABM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX SABM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -369,12 +369,12 @@
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX SABME(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -389,7 +389,7 @@
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
@@ -399,11 +399,11 @@
 		case LAPB_DISC:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 			printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n",
-			       lapb->token);
+			       lapb->dev);
 #endif
 			lapb_clear_queues(lapb);
 			lapb_send_control(lapb, LAPB_UA, frame->pf,
@@ -417,11 +417,11 @@
 		case LAPB_DM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 			printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n",
-			       lapb->token);
+			       lapb->dev);
 #endif
 			lapb_clear_queues(lapb);
 			lapb->state = LAPB_STATE_0;
@@ -433,7 +433,7 @@
 		case LAPB_RNR:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX RNR(%d) R%d\n",
-			       lapb->token, frame->pf, frame->nr);
+			       lapb->dev, frame->pf, frame->nr);
 #endif
 			lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION;
 			lapb_check_need_response(lapb, frame->cr, frame->pf);
@@ -445,7 +445,7 @@
 				lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_start_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -457,7 +457,7 @@
 		case LAPB_RR:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n",
-			       lapb->token, frame->pf, frame->nr);
+			       lapb->dev, frame->pf, frame->nr);
 #endif
 			lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
 			lapb_check_need_response(lapb, frame->cr, frame->pf);
@@ -469,7 +469,7 @@
 				lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_start_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -481,7 +481,7 @@
 		case LAPB_REJ:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n",
-			       lapb->token, frame->pf, frame->nr);
+			       lapb->dev, frame->pf, frame->nr);
 #endif
 			lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
 			lapb_check_need_response(lapb, frame->cr, frame->pf);
@@ -496,7 +496,7 @@
 				lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_start_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -508,7 +508,7 @@
 		case LAPB_I:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n",
-			       lapb->token, frame->pf, frame->ns, frame->nr);
+			       lapb->dev, frame->pf, frame->ns, frame->nr);
 #endif
 			if (!lapb_validate_nr(lapb, frame->nr)) {
 				lapb->frmr_data = *frame;
@@ -516,7 +516,7 @@
 				lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_start_t1timer(lapb);
 				lapb_stop_t2timer(lapb);
@@ -564,7 +564,7 @@
 #if LAPB_DEBUG > 1
 					printk(KERN_DEBUG
 					       "lapb: (%p) S3 TX REJ(%d) R%d\n",
-					       lapb->token, frame->pf, lapb->vr);
+					       lapb->dev, frame->pf, lapb->vr);
 #endif
 					lapb->condition |= LAPB_REJECT_CONDITION;
 					lapb_send_control(lapb, LAPB_REJ,
@@ -578,14 +578,14 @@
 		case LAPB_FRMR:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX FRMR(%d) %02X "
-			       "%02X %02X %02X %02X\n", lapb->token, frame->pf,
+			       "%02X %02X %02X %02X\n", lapb->dev, frame->pf,
 			       skb->data[0], skb->data[1], skb->data[2],
 			       skb->data[3], skb->data[4]);
 #endif
 			lapb_establish_data_link(lapb);
 #if LAPB_DEBUG > 0
 			printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n",
-			       lapb->token);
+			       lapb->dev);
 #endif
 			lapb_requeue_frames(lapb);
 			lapb->state = LAPB_STATE_1;
@@ -594,13 +594,13 @@
 		case LAPB_ILLEGAL:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			lapb->frmr_data = *frame;
 			lapb->frmr_type = LAPB_FRMR_W;
 			lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
-			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->token);
+			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
 #endif
 			lapb_start_t1timer(lapb);
 			lapb_stop_t2timer(lapb);
@@ -624,23 +624,23 @@
 		case LAPB_SABM:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S4 RX SABM(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -659,16 +659,16 @@
 		case LAPB_SABME:
 #if LAPB_DEBUG > 1
 			printk(KERN_DEBUG "lapb: (%p) S4 RX SABME(%d)\n",
-			       lapb->token, frame->pf);
+			       lapb->dev, frame->pf);
 #endif
 			if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
 				printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n",
-				       lapb->token);
+				       lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_UA, frame->pf,
 						  LAPB_RESPONSE);
@@ -684,7 +684,7 @@
 			} else {
 #if LAPB_DEBUG > 1
 				printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
-				       lapb->token, frame->pf);
+				       lapb->dev, frame->pf);
 #endif
 				lapb_send_control(lapb, LAPB_DM, frame->pf,
 						  LAPB_RESPONSE);
diff -Nru a/net/lapb/lapb_out.c b/net/lapb/lapb_out.c
--- a/net/lapb/lapb_out.c	Wed Feb 11 22:30:57 2004
+++ b/net/lapb/lapb_out.c	Wed Feb 11 22:30:57 2004
@@ -63,7 +63,7 @@
 
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX I(%d) S%d R%d\n",
-	       lapb->token, lapb->state, poll_bit, lapb->vs, lapb->vr);
+	       lapb->dev, lapb->state, poll_bit, lapb->vs, lapb->vr);
 #endif
 
 	lapb_transmit_buffer(lapb, skb, LAPB_COMMAND);	
@@ -151,7 +151,7 @@
 
 #if LAPB_DEBUG > 2
 	printk(KERN_DEBUG "lapb: (%p) S%d TX %02X %02X %02X\n",
-	       lapb->token, lapb->state,
+	       lapb->dev, lapb->state,
 	       skb->data[0], skb->data[1], skb->data[2]);
 #endif
 
@@ -167,13 +167,13 @@
 	if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
 		printk(KERN_DEBUG "lapb: (%p) S%d TX SABME(1)\n",
-		       lapb->token, lapb->state);
+		       lapb->dev, lapb->state);
 #endif
 		lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND);
 	} else {
 #if LAPB_DEBUG > 1
 		printk(KERN_DEBUG "lapb: (%p) S%d TX SABM(1)\n",
-		       lapb->token, lapb->state);
+		       lapb->dev, lapb->state);
 #endif
 		lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND);
 	}
@@ -186,7 +186,7 @@
 {
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX RR(1) R%d\n",
-	       lapb->token, lapb->state, lapb->vr);
+	       lapb->dev, lapb->state, lapb->vr);
 #endif
 
 	lapb_send_control(lapb, LAPB_RR, LAPB_POLLON, LAPB_RESPONSE);
@@ -198,7 +198,7 @@
 {
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX RR(0) R%d\n",
-	       lapb->token, lapb->state, lapb->vr);
+	       lapb->dev, lapb->state, lapb->vr);
 #endif
 	lapb_send_control(lapb, LAPB_RR, LAPB_POLLOFF, LAPB_RESPONSE);
 
diff -Nru a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c
--- a/net/lapb/lapb_subr.c	Wed Feb 11 22:30:57 2004
+++ b/net/lapb/lapb_subr.c	Wed Feb 11 22:30:57 2004
@@ -114,7 +114,7 @@
 
 #if LAPB_DEBUG > 2
 	printk(KERN_DEBUG "lapb: (%p) S%d RX %02X %02X %02X\n",
-	       lapb->token, lapb->state,
+	       lapb->dev, lapb->state,
 	       skb->data[0], skb->data[1], skb->data[2]);
 #endif
 
@@ -287,7 +287,7 @@
 
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X %02X %02X\n",
-	       lapb->token, lapb->state,
+	       lapb->dev, lapb->state,
 	       skb->data[1], skb->data[2], skb->data[3],
 	       skb->data[4], skb->data[5]);
 #endif
@@ -304,7 +304,7 @@
 
 #if LAPB_DEBUG > 1
 	printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X\n",
-	       lapb->token, lapb->state, skb->data[1],
+	       lapb->dev, lapb->state, skb->data[1],
 	       skb->data[2], skb->data[3]);
 #endif
 	}
diff -Nru a/net/lapb/lapb_timer.c b/net/lapb/lapb_timer.c
--- a/net/lapb/lapb_timer.c	Wed Feb 11 22:30:57 2004
+++ b/net/lapb/lapb_timer.c	Wed Feb 11 22:30:57 2004
@@ -107,19 +107,19 @@
 				lapb->state = LAPB_STATE_0;
 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
 #endif
 				return;
 			} else {
 				lapb->n2count++;
 				if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-					printk(KERN_DEBUG "lapb: (%p) S1 TX SABME(1)\n", lapb->token);
+					printk(KERN_DEBUG "lapb: (%p) S1 TX SABME(1)\n", lapb->dev);
 #endif
 					lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND);
 				} else {
 #if LAPB_DEBUG > 1
-					printk(KERN_DEBUG "lapb: (%p) S1 TX SABM(1)\n", lapb->token);
+					printk(KERN_DEBUG "lapb: (%p) S1 TX SABM(1)\n", lapb->dev);
 #endif
 					lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND);
 				}
@@ -135,13 +135,13 @@
 				lapb->state = LAPB_STATE_0;
 				lapb_disconnect_confirmation(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
 #endif
 				return;
 			} else {
 				lapb->n2count++;
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S2 TX DISC(1)\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S2 TX DISC(1)\n", lapb->dev);
 #endif
 				lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
 			}
@@ -157,7 +157,7 @@
 				lapb_stop_t2timer(lapb);
 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
 #endif
 				return;
 			} else {
@@ -175,7 +175,7 @@
 				lapb->state = LAPB_STATE_0;
 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->token);
+				printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->dev);
 #endif
 				return;
 			} else {