## Automatically generated incremental diff
## From:   linux-2.5.73-bk3
## To:     linux-2.5.73-bk4
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.5.73-bk3/Documentation/cpu-freq/user-guide.txt linux-2.5.73-bk4/Documentation/cpu-freq/user-guide.txt
--- linux-2.5.73-bk3/Documentation/cpu-freq/user-guide.txt	2003-06-22 11:32:32.000000000 -0700
+++ linux-2.5.73-bk4/Documentation/cpu-freq/user-guide.txt	2003-06-26 05:00:22.000000000 -0700
@@ -56,19 +56,15 @@
 AMD mobile Duron
 AMD mobile Athlon
 Cyrix Media GXm
-Intel mobile PIII [*] and Intel mobile PIII-M on certain chipsets
+Intel mobile PIII and Intel mobile PIII-M on certain chipsets
 Intel Pentium 4, Intel Xeon
 Intel Pentium M (Centrino)
 National Semiconductors Geode GX
 Transmeta Crusoe
 VIA Cyrix 3 / C3
-various processors on some ACPI 2.0-compatible systems [**]
+various processors on some ACPI 2.0-compatible systems [*]
 
-[*] only certain Intel mobile PIII processors are supported. If you
-know that you own a speedstep-capable processor, pass the option
-"speedstep_coppermine=1" to the module speedstep.o
-
-[**] Only if "ACPI Processor Performance States" are available
+[*] Only if "ACPI Processor Performance States" are available
 to the ACPI<->BIOS interface.
 
 
diff -urN linux-2.5.73-bk3/Documentation/pci.txt linux-2.5.73-bk4/Documentation/pci.txt
--- linux-2.5.73-bk3/Documentation/pci.txt	2003-06-22 11:32:44.000000000 -0700
+++ linux-2.5.73-bk4/Documentation/pci.txt	2003-06-26 05:00:22.000000000 -0700
@@ -155,17 +155,11 @@
 VENDOR_ID or DEVICE_ID.  This allows searching for any device from a
 specific vendor, for example.
 
-   In case you need to decide according to some more complex criteria,
-you can walk the list of all known PCI devices yourself:
-
-	struct pci_dev *dev;
-	pci_for_each_dev(dev) {
-		... do anything you want with dev ...
-	}
-
-For compatibility with device ordering in older kernels, you can also
-use pci_for_each_dev_reverse(dev) for walking the list in the opposite
-direction.
+Note that these functions are not hotplug-safe.  Their hotplug-safe
+replacements are pci_get_device(), pci_get_class() and pci_get_subsys().
+They increment the reference count on the pci_dev that they return.
+You must eventually (possibly at module unload) decrement the reference
+count on these devices by calling pci_dev_put().
 
 
 3. Enabling devices
@@ -193,6 +187,10 @@
 string by pcibios_strerror. Most drivers expect that accesses to valid PCI
 devices don't fail.
 
+   If you don't have a struct pci_dev available, you can call
+pci_bus_(read|write)_config_(byte|word|dword) to access a given device
+and function on that bus.
+
    If you access fields in the standard portion of the config header, please
 use symbolic names of locations and bits declared in <linux/pci.h>.
 
@@ -253,14 +251,23 @@
 
 8. Obsolete functions
 ~~~~~~~~~~~~~~~~~~~~~
-There are several functions kept only for compatibility with old drivers
-not updated to the new PCI interface. Please don't use them in new code.
+There are several functions which you might come across when trying to
+port an old driver to the new PCI interface.  They are no longer present
+in the kernel as they aren't compatible with hotplug or PCI domains or
+having sane locking.
 
-pcibios_present()		Since ages, you don't need to test presence
-				of PCI subsystem when trying to talk with it.
+pcibios_present() and		Since ages, you don't need to test presence
+pci_present()			of PCI subsystem when trying to talk to it.
 				If it's not there, the list of PCI devices
 				is empty and all functions for searching for
 				devices just return NULL.
 pcibios_(read|write)_*		Superseded by their pci_(read|write)_*
 				counterparts.
 pcibios_find_*			Superseded by their pci_find_* counterparts.
+pci_for_each_dev()		Superseded by pci_find_device()
+pci_for_each_dev_reverse()	Superseded by pci_find_device_reverse()
+pci_for_each_bus()		Superseded by pci_find_next_bus()
+pci_find_device()		Superseded by pci_get_device()
+pci_find_subsys()		Superseded by pci_get_subsys()
+pcibios_find_class()		Superseded by pci_find_class()
+pci_(read|write)_*_nodev()	Superseded by pci_bus_(read|write)_*()
diff -urN linux-2.5.73-bk3/MAINTAINERS linux-2.5.73-bk4/MAINTAINERS
--- linux-2.5.73-bk3/MAINTAINERS	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk4/MAINTAINERS	2003-06-26 05:00:22.000000000 -0700
@@ -1628,8 +1628,8 @@
 
 SGI VISUAL WORKSTATION 320 AND 540
 P:	Andrey Panin
-M:	pazke@orbita1.ru
-L:	linux-visws@lists.sf.net
+M:	pazke@donpac.ru
+L:	linux-visws-devel@lists.sf.net
 W:	http://linux-visws.sf.net
 S:	Maintained for 2.5.
 
diff -urN linux-2.5.73-bk3/Makefile linux-2.5.73-bk4/Makefile
--- linux-2.5.73-bk3/Makefile	2003-06-26 04:59:42.000000000 -0700
+++ linux-2.5.73-bk4/Makefile	2003-06-26 05:00:22.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 73
-EXTRAVERSION = -bk3
+EXTRAVERSION = -bk4
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.73-bk3/arch/i386/kernel/Makefile linux-2.5.73-bk4/arch/i386/kernel/Makefile
--- linux-2.5.73-bk3/arch/i386/kernel/Makefile	2003-06-22 11:32:35.000000000 -0700
+++ linux-2.5.73-bk4/arch/i386/kernel/Makefile	2003-06-26 05:00:22.000000000 -0700
@@ -47,7 +47,7 @@
       cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
 		          -Wl,-T,$(filter-out FORCE,$^) -o $@
 
-vsyscall-flags = -shared -s -Wl,-soname=linux-vsyscall.so.1
+vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1
 SYSCFLAGS_vsyscall-sysenter.so	= $(vsyscall-flags)
 SYSCFLAGS_vsyscall-int80.so	= $(vsyscall-flags)
 
diff -urN linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/Kconfig linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/Kconfig
--- linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/Kconfig	2003-06-22 11:32:36.000000000 -0700
+++ linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/Kconfig	2003-06-26 05:00:22.000000000 -0700
@@ -123,6 +123,11 @@
 	  
 	  If in doubt, say N.
 
+config X86_SPEEDSTEP_LIB
+       tristate
+       depends on X86_SPEEDSTEP_ICH
+       default X86_SPEEDSTEP_ICH
+
 config X86_P4_CLOCKMOD
 	tristate "Intel Pentium 4 clock modulation"
 	depends on CPU_FREQ_TABLE
diff -urN linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/Makefile linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/Makefile
--- linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/Makefile	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/Makefile	2003-06-26 05:00:22.000000000 -0700
@@ -8,6 +8,7 @@
 obj-$(CONFIG_X86_ACPI_CPUFREQ)	+= acpi.o
 obj-$(CONFIG_X86_SPEEDSTEP_ICH)	+= speedstep-ich.o
 obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
+obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o
 
 ifdef CONFIG_X86_ACPI_CPUFREQ
   ifdef CONFIG_ACPI_DEBUG
diff -urN linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
--- linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c	2003-06-26 05:00:22.000000000 -0700
@@ -29,7 +29,7 @@
 #define PFX		"speedstep-centrino: "
 #define MAINTAINER	"Jeremy Fitzhardinge <jeremy@goop.org>"
 
-#define CENTRINO_DEBUG
+/*#define CENTRINO_DEBUG*/
 
 #ifdef CENTRINO_DEBUG
 #define dprintk(msg...) printk(msg)
diff -urN linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
--- linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c	2003-06-22 11:32:28.000000000 -0700
+++ linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c	2003-06-26 05:00:22.000000000 -0700
@@ -1,6 +1,4 @@
 /*
- *  $Id: speedstep.c,v 1.70 2003/02/22 10:23:46 db Exp $
- *
  * (C) 2001  Dave Jones, Arjan van de ven.
  * (C) 2002 - 2003  Dominik Brodowski <linux@brodo.de>
  *
@@ -27,46 +25,32 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 
-#include <asm/msr.h>
+#include "speedstep-lib.h"
+
 
 /* speedstep_chipset:
  *   It is necessary to know which chipset is used. As accesses to 
  * this device occur at various places in this module, we need a 
  * static struct pci_dev * pointing to that device.
  */
-static unsigned int                     speedstep_chipset;
-static struct pci_dev                   *speedstep_chipset_dev;
+static struct pci_dev			*speedstep_chipset_dev;
 
-#define SPEEDSTEP_CHIPSET_ICH2M         0x00000002
-#define SPEEDSTEP_CHIPSET_ICH3M         0x00000003
-#define SPEEDSTEP_CHIPSET_ICH4M         0x00000004
 
 /* speedstep_processor
  */
-static unsigned int                     speedstep_processor = 0;
-static int                              speedstep_coppermine = 0;
-
-#define SPEEDSTEP_PROCESSOR_PIII_C      0x00000001  /* Coppermine core */
-#define SPEEDSTEP_PROCESSOR_PIII_T      0x00000002  /* Tualatin core */
-#define SPEEDSTEP_PROCESSOR_P4M         0x00000003  /* P4-M with 100 MHz FSB */
+static unsigned int			speedstep_processor = 0;
 
 
-/* speedstep_[low,high]_freq
+/* 
  *   There are only two frequency states for each processor. Values
  * are in kHz for the time being.
  */
-#define SPEEDSTEP_HIGH                  0x00000000
-#define SPEEDSTEP_LOW                   0x00000001
-
 static struct cpufreq_frequency_table speedstep_freqs[] = {
 	{SPEEDSTEP_HIGH, 	0},
 	{SPEEDSTEP_LOW,		0},
 	{0,			CPUFREQ_TABLE_END},
 };
 
-#define speedstep_low_freq	speedstep_freqs[SPEEDSTEP_LOW].frequency
-#define speedstep_high_freq	speedstep_freqs[SPEEDSTEP_HIGH].frequency
-
 
 /* DEBUG
  *   Define it if you want verbose debug output, e.g. for bug reporting
@@ -80,149 +64,82 @@
 #endif
 
 
-
-/*********************************************************************
- *                    LOW LEVEL CHIPSET INTERFACE                    *
- *********************************************************************/
-
-/**
- * speedstep_get_state - read the current SpeedStep state
- * @state: Speedstep state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
- *
- *   Tries to read the SpeedStep state. Returns -EIO when there has been
- * trouble to read the status or write to the control register, -EINVAL
- * on an unsupported chipset, and zero on success.
- */
-static int speedstep_get_state (unsigned int *state)
-{
-	unsigned long   flags;
-	u32             pmbase;
-	u8              value;
-
-	if (!speedstep_chipset_dev || !state)
-		return -EINVAL;
-
-	switch (speedstep_chipset) {
-	case SPEEDSTEP_CHIPSET_ICH2M:
-	case SPEEDSTEP_CHIPSET_ICH3M:
-	case SPEEDSTEP_CHIPSET_ICH4M:
-		/* get PMBASE */
-		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
-		if (!(pmbase & 0x01))
-			return -EIO;
-
-		pmbase &= 0xFFFFFFFE;
-		if (!pmbase) 
-			return -EIO;
-
-		/* read state */
-		local_irq_save(flags);
-		value = inb(pmbase + 0x50);
-		local_irq_restore(flags);
-
-		dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
-
-		*state = value & 0x01;
-		return 0;
-
-	}
-
-	printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n");
-	return -EINVAL;
-}
-
-
 /**
  * speedstep_set_state - set the SpeedStep state
  * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
  *
  *   Tries to change the SpeedStep state. 
  */
-static void speedstep_set_state (unsigned int state, int notify)
+static void speedstep_set_state (unsigned int state, unsigned int notify)
 {
-	u32                     pmbase;
-	u8	                pm2_blk;
-	u8                      value;
-	unsigned long           flags;
-	unsigned int            oldstate;
-	struct cpufreq_freqs    freqs;
+	u32			pmbase;
+	u8			pm2_blk;
+	u8			value;
+	unsigned long		flags;
+	struct cpufreq_freqs	freqs;
 
 	if (!speedstep_chipset_dev || (state > 0x1))
 		return;
 
-	if (speedstep_get_state(&oldstate))
-		return;
-
-	if (oldstate == state)
-		return;
-
-	freqs.old = (oldstate == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq;
-	freqs.new = (state == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq;
+	freqs.old = speedstep_get_processor_frequency(speedstep_processor);
+	freqs.new = speedstep_freqs[SPEEDSTEP_LOW].frequency;
 	freqs.cpu = 0; /* speedstep.c is UP only driver */
 	
 	if (notify)
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	switch (speedstep_chipset) {
-	case SPEEDSTEP_CHIPSET_ICH2M:
-	case SPEEDSTEP_CHIPSET_ICH3M:
-	case SPEEDSTEP_CHIPSET_ICH4M:
-		/* get PMBASE */
-		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
-		if (!(pmbase & 0x01))
-		{
-			printk(KERN_ERR "cpufreq: could not find speedstep register\n");
-			return;
-		}
+	/* get PMBASE */
+	pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
+	if (!(pmbase & 0x01))
+	{
+		printk(KERN_ERR "cpufreq: could not find speedstep register\n");
+		return;
+	}
 
-		pmbase &= 0xFFFFFFFE;
-		if (!pmbase) {
-			printk(KERN_ERR "cpufreq: could not find speedstep register\n");
-			return;
-		}
+	pmbase &= 0xFFFFFFFE;
+	if (!pmbase) {
+		printk(KERN_ERR "cpufreq: could not find speedstep register\n");
+		return;
+	}
 
-		/* Disable IRQs */
-		local_irq_save(flags);
+	/* Disable IRQs */
+	local_irq_save(flags);
 
-		/* read state */
-		value = inb(pmbase + 0x50);
+	/* read state */
+	value = inb(pmbase + 0x50);
 
-		dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
+	dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
 
-		/* write new state */
-		value &= 0xFE;
-		value |= state;
+	/* write new state */
+	value &= 0xFE;
+	value |= state;
 
-		dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase);
+	dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase);
 
-		/* Disable bus master arbitration */
-		pm2_blk = inb(pmbase + 0x20);
-		pm2_blk |= 0x01;
-		outb(pm2_blk, (pmbase + 0x20));
+	/* Disable bus master arbitration */
+	pm2_blk = inb(pmbase + 0x20);
+	pm2_blk |= 0x01;
+	outb(pm2_blk, (pmbase + 0x20));
 
-		/* Actual transition */
-		outb(value, (pmbase + 0x50));
+	/* Actual transition */
+	outb(value, (pmbase + 0x50));
 
-		/* Restore bus master arbitration */
-		pm2_blk &= 0xfe;
-		outb(pm2_blk, (pmbase + 0x20));
+	/* Restore bus master arbitration */
+	pm2_blk &= 0xfe;
+	outb(pm2_blk, (pmbase + 0x20));
 
-		/* check if transition was successful */
-		value = inb(pmbase + 0x50);
+	/* check if transition was successful */
+	value = inb(pmbase + 0x50);
 
-		/* Enable IRQs */
-		local_irq_restore(flags);
+	/* Enable IRQs */
+	local_irq_restore(flags);
 
-		dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
+	dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
 
-		if (state == (value & 0x1)) {
-			dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (freqs.new / 1000));
-		} else {
-			printk (KERN_ERR "cpufreq: change failed - I/O error\n");
-		}
-		break;
-	default:
-		printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n");
+	if (state == (value & 0x1)) {
+		dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (freqs.new / 1000));
+	} else {
+		printk (KERN_ERR "cpufreq: change failed - I/O error\n");
 	}
 
 	if (notify)
@@ -240,31 +157,21 @@
  */
 static int speedstep_activate (void)
 {
+	u16		value = 0;
+
 	if (!speedstep_chipset_dev)
 		return -EINVAL;
 
-	switch (speedstep_chipset) {
-	case SPEEDSTEP_CHIPSET_ICH2M:
-	case SPEEDSTEP_CHIPSET_ICH3M:
-	case SPEEDSTEP_CHIPSET_ICH4M:
-	{
-		u16             value = 0;
-
-		pci_read_config_word(speedstep_chipset_dev, 
-				     0x00A0, &value);
-		if (!(value & 0x08)) {
-			value |= 0x08;
-			dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n");
-			pci_write_config_word(speedstep_chipset_dev, 
-					      0x00A0, value);
-		}
-
-		return 0;
-	}
+	pci_read_config_word(speedstep_chipset_dev, 
+			     0x00A0, &value);
+	if (!(value & 0x08)) {
+		value |= 0x08;
+		dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n");
+		pci_write_config_word(speedstep_chipset_dev, 
+				      0x00A0, value);
 	}
-	
-	printk (KERN_ERR "cpufreq: SpeedStep (TM) on this chipset unsupported.\n");
-	return -EINVAL;
+
+	return 0;
 }
 
 
@@ -284,7 +191,7 @@
 			      PCI_ANY_ID,
 			      NULL);
 	if (speedstep_chipset_dev)
-		return SPEEDSTEP_CHIPSET_ICH4M;
+		return 4; /* 4-M */
 
 	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82801CA_12, 
@@ -292,7 +199,7 @@
 			      PCI_ANY_ID,
 			      NULL);
 	if (speedstep_chipset_dev)
-		return SPEEDSTEP_CHIPSET_ICH3M;
+		return 3; /* 3-M */
 
 
 	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
@@ -305,7 +212,7 @@
 		 * 8100 which use a pretty old revision of the 82815 
 		 * host brige. Abort on these systems.
 		 */
-		static struct pci_dev   *hostbridge;
+		static struct pci_dev	*hostbridge;
 		u8			rev = 0;
 
 		hostbridge  = pci_find_subsys(PCI_VENDOR_ID_INTEL,
@@ -315,7 +222,7 @@
 			      NULL);
 
 		if (!hostbridge)
-			return SPEEDSTEP_CHIPSET_ICH2M;
+			return 2; /* 2-M */
 			
 		pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);
 		if (rev < 5) {
@@ -324,266 +231,9 @@
 			return 0;
 		}
 
-		return SPEEDSTEP_CHIPSET_ICH2M;
-	}
-
-	return 0;
-}
-
-
-
-/*********************************************************************
- *                   LOW LEVEL PROCESSOR INTERFACE                   *
- *********************************************************************/
-
-
-/**
- * pentium3_get_frequency - get the core frequencies for PIIIs
- *
- *   Returns the core frequency of a Pentium III processor (in kHz)
- */
-static unsigned int pentium3_get_frequency (void)
-{
-        /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */
-	struct {
-		unsigned int ratio;	/* Frequency Multiplier (x10) */
-		u8 bitmap;	        /* power on configuration bits
-					   [27, 25:22] (in MSR 0x2a) */
-	} msr_decode_mult [] = {
-		{ 30, 0x01 },
-		{ 35, 0x05 },
-		{ 40, 0x02 },
-		{ 45, 0x06 },
-		{ 50, 0x00 },
-		{ 55, 0x04 },
-		{ 60, 0x0b },
-		{ 65, 0x0f },
-		{ 70, 0x09 },
-		{ 75, 0x0d },
-		{ 80, 0x0a },
-		{ 85, 0x26 },
-		{ 90, 0x20 },
-		{ 100, 0x2b },
-		{ 0, 0xff }     /* error or unknown value */
-	};
-	/* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */
-	struct {
-		unsigned int value;     /* Front Side Bus speed in MHz */
-		u8 bitmap;              /* power on configuration bits [18: 19]
-					   (in MSR 0x2a) */
-	} msr_decode_fsb [] = {
-		{  66, 0x0 },
-		{ 100, 0x2 },
-		{ 133, 0x1 },
-		{   0, 0xff}
-	};
-	u32     msr_lo, msr_tmp;
-	int     i = 0, j = 0;
-	struct  cpuinfo_x86 *c = cpu_data;
-
-	/* read MSR 0x2a - we only need the low 32 bits */
-	rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
-	dprintk(KERN_DEBUG "cpufreq: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
-	msr_tmp = msr_lo;
-
-	/* decode the FSB */
-	msr_tmp &= 0x00c0000;
-	msr_tmp >>= 18;
-	while (msr_tmp != msr_decode_fsb[i].bitmap) {
-		if (msr_decode_fsb[i].bitmap == 0xff)
-			return -EINVAL;
-		i++;
-	}
-
-	/* decode the multiplier */
-	if ((c->x86_model == 0x08) && (c->x86_mask == 0x01)) 
-                /* different on early Coppermine PIII */
-		msr_lo &= 0x03c00000;
-	else
-		msr_lo &= 0x0bc00000;
-	msr_lo >>= 22;
-	while (msr_lo != msr_decode_mult[j].bitmap) {
-		if (msr_decode_mult[j].bitmap == 0xff)
-			return -EINVAL;
-		j++;
-	}
-
-	return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100);
-}
-
-
-/**
- * pentium4_get_frequency - get the core frequency for P4-Ms
- *
- *   Should return the core frequency (in kHz) for P4-Ms. 
- */
-static unsigned int pentium4_get_frequency(void)
-{
-	u32 msr_lo, msr_hi;
-
-	rdmsr(0x2c, msr_lo, msr_hi);
-
-	dprintk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
-
-	/* First 12 bits seem to change a lot (0x511, 0x410 and 0x30f seen 
-	 * yet). Next 12 bits always seem to be 0x300. If this is not true 
-	 * on this CPU, complain. Last 8 bits are frequency (in 100MHz).
-	 */
-	if (msr_hi || ((msr_lo & 0x00FFF000) != 0x300000)) {
-		printk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
-		printk(KERN_INFO "cpufreq: problem in initialization. Please contact Dominik Brodowski\n");
-		printk(KERN_INFO "cpufreq: <linux@brodo.de> and attach this dmesg. Thanks in advance\n");
-		return 0;
-	}
-
-	msr_lo >>= 24;
-	return (msr_lo * 100000);
-}
-
-
-/** 
- * speedstep_detect_processor - detect Intel SpeedStep-capable processors.
- *
- *   Returns the SPEEDSTEP_PROCESSOR_-number for the detected processor, 
- * or zero on failure.
- */
-static unsigned int speedstep_detect_processor (void)
-{
-	struct cpuinfo_x86 *c = cpu_data;
-	u32                     ebx;
-
-	if ((c->x86_vendor != X86_VENDOR_INTEL) || 
-	    ((c->x86 != 6) && (c->x86 != 0xF)))
-		return 0;
-
-	if (c->x86 == 0xF) {
-		/* Intel Pentium 4 Mobile P4-M */
-		if (c->x86_model != 2)
-			return 0;
-
-		if ((c->x86_mask != 4) && (c->x86_mask != 7))
-			return 0;
-
-		ebx = cpuid_ebx(0x00000001);
-		ebx &= 0x000000FF;
-		if ((ebx != 0x0e) && (ebx != 0x0f))
-			return 0;
-
-		return SPEEDSTEP_PROCESSOR_P4M;
-	}
-
-	switch (c->x86_model) {
-	case 0x0B: /* Intel PIII [Tualatin] */
-		/* cpuid_ebx(1) is 0x04 for desktop PIII, 
-		                   0x06 for mobile PIII-M */
-		ebx = cpuid_ebx(0x00000001);
-
-		ebx &= 0x000000FF;
-		if (ebx != 0x06)
-			return 0;
-
-		/* So far all PIII-M processors support SpeedStep. See
-		 * Intel's 24540633.pdf of August 2002 
-		 */
-
-		return SPEEDSTEP_PROCESSOR_PIII_T;
-
-	case 0x08: /* Intel PIII [Coppermine] */
- 	        {
-			u32     msr_lo, msr_hi;
-
-			/* all mobile PIII Coppermines have FSB 100 MHz
-			 * ==> sort out a few desktop PIIIs. */
-			rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi);
-			dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_EBL_Cr_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi);
-			msr_lo &= 0x00c0000;
-			if (msr_lo != 0x0080000)
-				return 0;
-
-			if (speedstep_coppermine)
-				return SPEEDSTEP_PROCESSOR_PIII_C;
-
-			/*
-			 * If the processor is a mobile version,
-			 * platform ID has bit 50 set
-			 * it has SpeedStep technology if either
-			 * bit 56 or 57 is set
-			 */
-			rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi);
-			dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi);
-			if ((msr_hi & (1<<18)) && (msr_hi & (3<<24)))
-				return SPEEDSTEP_PROCESSOR_PIII_C;
-
-			printk(KERN_INFO "cpufreq: in case this is a SpeedStep-capable Intel Pentium III Coppermine\n");
-			printk(KERN_INFO "cpufreq: processor, please pass the boot option or module parameter\n");
-			printk(KERN_INFO "cpufreq: `speedstep_coppermine=1` to the kernel. Thanks!\n");
-			return 0;
-		}
-
-	default:
-		return 0;
-	}
-}
-
-
-
-/*********************************************************************
- *                        HIGH LEVEL FUNCTIONS                       *
- *********************************************************************/
-
-/**
- * speedstep_detect_speeds - detects low and high CPU frequencies.
- *
- *   Detects the low and high CPU frequencies in kHz. Returns 0 on
- * success or -EINVAL / -EIO on problems. 
- */
-static int speedstep_detect_speeds (void)
-{
-	unsigned long   flags;
-	unsigned int    state;
-	int             i, result;
-
-	/* Disable irqs for entire detection process */
-	local_irq_save(flags);
-
-	for (i=0; i<2; i++) {
-		/* read the current state */
-		result = speedstep_get_state(&state);
-		if (result) {
-			local_irq_restore(flags);
-			return result;
-		}
-
-		/* save the correct value, and switch to other */
-		if (state == SPEEDSTEP_LOW) {
-			switch (speedstep_processor) {
-			case SPEEDSTEP_PROCESSOR_PIII_C:
-			case SPEEDSTEP_PROCESSOR_PIII_T:
-				speedstep_low_freq = pentium3_get_frequency();
-				break;
-			case SPEEDSTEP_PROCESSOR_P4M:
-				speedstep_low_freq = pentium4_get_frequency();
-			}
-			speedstep_set_state(SPEEDSTEP_HIGH, 0);
-		} else {
-			switch (speedstep_processor) {
-			case SPEEDSTEP_PROCESSOR_PIII_C:
-			case SPEEDSTEP_PROCESSOR_PIII_T:
-				speedstep_high_freq = pentium3_get_frequency();
-				break;
-			case SPEEDSTEP_PROCESSOR_P4M:
-				speedstep_high_freq = pentium4_get_frequency();
-			}
-			speedstep_set_state(SPEEDSTEP_LOW, 0);
-		}
+		return 2; /* 2-M */
 	}
 
-	local_irq_restore(flags);
-
-	if (!speedstep_low_freq || !speedstep_high_freq || 
-	    (speedstep_low_freq == speedstep_high_freq))
-		return -EIO;
-
 	return 0;
 }
 
@@ -598,7 +248,7 @@
 			     unsigned int target_freq,
 			     unsigned int relation)
 {
-	unsigned int    newstate = 0;
+	unsigned int	newstate = 0;
 
 	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
 		return -EINVAL;
@@ -632,22 +282,24 @@
 		return -ENODEV;
 
 	/* detect low and high frequency */
-	result = speedstep_detect_speeds();
+	result = speedstep_get_freqs(speedstep_processor,
+				     &speedstep_freqs[SPEEDSTEP_LOW].frequency,
+				     &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+				     &speedstep_set_state);
 	if (result)
 		return result;
 
 	/* get current speed setting */
-	result = speedstep_get_state(&speed);
-	if (result)
-		return result;
+	speed = speedstep_get_processor_frequency(speedstep_processor);
+	if (!speed)
+		return -EIO;
 
-	speed = (speed == SPEEDSTEP_LOW) ? speedstep_low_freq : speedstep_high_freq;
 	dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", 
 		(speed == speedstep_low_freq) ? "low" : "high",
 		(speed / 1000));
 
 	/* cpuinfo and default policy values */
-	policy->policy = (speed == speedstep_low_freq) ? 
+	policy->policy = (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? 
 		CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE;
 	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 	policy->cur = speed;
@@ -656,26 +308,6 @@
 }
 
 
-#ifndef MODULE
-/**
- * speedstep_setup  speedstep command line parameter parsing
- *
- * speedstep command line parameter.  Use:
- *  speedstep_coppermine=1
- * if the CPU in your notebook is a SpeedStep-capable Intel
- * Pentium III Coppermine. These processors cannot be detected
- * automatically, as Intel continues to consider the detection 
- * algorithm as proprietary material.
- */
-static int __init speedstep_setup(char *str)
-{
-	speedstep_coppermine = simple_strtoul(str, &str, 0);
-	return 1;
-}
-__setup("speedstep_coppermine=", speedstep_setup);
-#endif
-
-
 static struct cpufreq_driver speedstep_driver = {
 	.name		= "speedstep",
 	.verify 	= speedstep_verify,
@@ -694,20 +326,17 @@
  */
 static int __init speedstep_init(void)
 {
-	/* detect chipset */
-	speedstep_chipset = speedstep_detect_chipset(); 
+	/* detect processor */
+	speedstep_processor = speedstep_detect_processor();
+	if (!speedstep_processor)
+		return -ENODEV;
 
 	/* detect chipset */
-	if (speedstep_chipset)
-		speedstep_processor = speedstep_detect_processor();
-
-	if ((!speedstep_chipset) || (!speedstep_processor)) {
-		printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_chipset ? "processor" : "chipset");
+	if (!speedstep_detect_chipset()) {
+		printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n");
 		return -ENODEV;
 	}
 
-	dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.70 $\n");
-
 	/* activate speedstep support */
 	if (speedstep_activate())
 		return -EINVAL;
@@ -727,10 +356,8 @@
 }
 
 
-MODULE_PARM (speedstep_coppermine, "i");
-
 MODULE_AUTHOR ("Dave Jones <davej@suse.de>, Dominik Brodowski <linux@brodo.de>");
-MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors.");
+MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors on chipsets with ICH-M southbridges.");
 MODULE_LICENSE ("GPL");
 
 module_init(speedstep_init);
diff -urN linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
--- linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c	2003-06-26 05:00:22.000000000 -0700
@@ -0,0 +1,275 @@
+/*
+ * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  Library for common functions for Intel SpeedStep v.1 and v.2 support
+ *
+ *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h> 
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/msr.h>
+#include "speedstep-lib.h"
+
+
+/* DEBUG
+ *   Define it if you want verbose debug output, e.g. for bug reporting
+ */
+//#define SPEEDSTEP_DEBUG
+
+#ifdef SPEEDSTEP_DEBUG
+#define dprintk(msg...) printk(msg)
+#else
+#define dprintk(msg...) do { } while(0)
+#endif
+
+/*********************************************************************
+ *                   GET PROCESSOR CORE SPEED IN KHZ                 *
+ *********************************************************************/
+
+static unsigned int pentium3_get_frequency (unsigned int processor)
+{
+        /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */
+	struct {
+		unsigned int ratio;	/* Frequency Multiplier (x10) */
+		u8 bitmap;	        /* power on configuration bits
+					   [27, 25:22] (in MSR 0x2a) */
+	} msr_decode_mult [] = {
+		{ 30, 0x01 },
+		{ 35, 0x05 },
+		{ 40, 0x02 },
+		{ 45, 0x06 },
+		{ 50, 0x00 },
+		{ 55, 0x04 },
+		{ 60, 0x0b },
+		{ 65, 0x0f },
+		{ 70, 0x09 },
+		{ 75, 0x0d },
+		{ 80, 0x0a },
+		{ 85, 0x26 },
+		{ 90, 0x20 },
+		{ 100, 0x2b },
+		{ 0, 0xff }     /* error or unknown value */
+	};
+
+	/* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */
+	struct {
+		unsigned int value;     /* Front Side Bus speed in MHz */
+		u8 bitmap;              /* power on configuration bits [18: 19]
+					   (in MSR 0x2a) */
+	} msr_decode_fsb [] = {
+		{  66, 0x0 },
+		{ 100, 0x2 },
+		{ 133, 0x1 },
+		{   0, 0xff}
+	};
+
+	u32     msr_lo, msr_tmp;
+	int     i = 0, j = 0;
+
+	/* read MSR 0x2a - we only need the low 32 bits */
+	rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
+	dprintk(KERN_DEBUG "speedstep-lib: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
+	msr_tmp = msr_lo;
+
+	/* decode the FSB */
+	msr_tmp &= 0x00c0000;
+	msr_tmp >>= 18;
+	while (msr_tmp != msr_decode_fsb[i].bitmap) {
+		if (msr_decode_fsb[i].bitmap == 0xff)
+			return 0;
+		i++;
+	}
+
+	/* decode the multiplier */
+	if (processor == SPEEDSTEP_PROCESSOR_PIII_C_EARLY)
+		msr_lo &= 0x03c00000;
+	else
+		msr_lo &= 0x0bc00000;
+	msr_lo >>= 22;
+	while (msr_lo != msr_decode_mult[j].bitmap) {
+		if (msr_decode_mult[j].bitmap == 0xff)
+			return 0;
+		j++;
+	}
+
+	return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100);
+}
+
+
+static unsigned int pentium4_get_frequency(void)
+{
+	u32 msr_lo, msr_hi;
+
+	rdmsr(0x2c, msr_lo, msr_hi);
+
+	dprintk(KERN_DEBUG "speedstep-lib: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
+
+	msr_lo >>= 24;
+	return (msr_lo * 100000);
+}
+
+ 
+unsigned int speedstep_get_processor_frequency(unsigned int processor)
+{
+	switch (processor) {
+	case SPEEDSTEP_PROCESSOR_P4M:
+		return pentium4_get_frequency();
+	case SPEEDSTEP_PROCESSOR_PIII_T:
+	case SPEEDSTEP_PROCESSOR_PIII_C:
+	case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
+		return pentium3_get_frequency(processor);
+	default:
+		return 0;
+	};
+	return 0;
+}
+EXPORT_SYMBOL_GPL(speedstep_get_processor_frequency);
+
+
+/*********************************************************************
+ *                 DETECT SPEEDSTEP-CAPABLE PROCESSOR                *
+ *********************************************************************/
+
+unsigned int speedstep_detect_processor (void)
+{
+	struct cpuinfo_x86 *c = cpu_data;
+	u32			ebx, msr_lo, msr_hi;
+
+	if ((c->x86_vendor != X86_VENDOR_INTEL) || 
+	    ((c->x86 != 6) && (c->x86 != 0xF)))
+		return 0;
+
+	if (c->x86 == 0xF) {
+		/* Intel Mobile Pentium 4-M
+		 * or Intel Mobile Pentium 4 with 533 MHz FSB */
+		if (c->x86_model != 2)
+			return 0;
+
+		if ((c->x86_mask != 4) && /* B-stepping [M-P4-M] */
+			(c->x86_mask != 7) && /* C-stepping [M-P4-M] */
+			(c->x86_mask != 9))   /* D-stepping [M-P4-M or M-P4/533] */
+			return 0;
+
+		ebx = cpuid_ebx(0x00000001);
+		ebx &= 0x000000FF;
+		if ((ebx != 0x0e) && (ebx != 0x0f))
+			return 0;
+
+		return SPEEDSTEP_PROCESSOR_P4M;
+	}
+
+	switch (c->x86_model) {
+	case 0x0B: /* Intel PIII [Tualatin] */
+		/* cpuid_ebx(1) is 0x04 for desktop PIII, 
+		                   0x06 for mobile PIII-M */
+		ebx = cpuid_ebx(0x00000001);
+
+		ebx &= 0x000000FF;
+		if (ebx != 0x06)
+			return 0;
+
+		/* So far all PIII-M processors support SpeedStep. See
+		 * Intel's 24540640.pdf of June 2003 
+		 */
+
+		return SPEEDSTEP_PROCESSOR_PIII_T;
+
+	case 0x08: /* Intel PIII [Coppermine] */
+
+		/* all mobile PIII Coppermines have FSB 100 MHz
+		 * ==> sort out a few desktop PIIIs. */
+		rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi);
+		dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi);
+		msr_lo &= 0x00c0000;
+		if (msr_lo != 0x0080000)
+			return 0;
+
+		/*
+		 * If the processor is a mobile version,
+		 * platform ID has bit 50 set
+		 * it has SpeedStep technology if either
+		 * bit 56 or 57 is set
+		 */
+		rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi);
+		dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi);
+		if ((msr_hi & (1<<18)) && (msr_hi & (3<<24))) {
+			if (c->x86_mask == 0x01)
+				return SPEEDSTEP_PROCESSOR_PIII_C_EARLY;
+			else
+				return SPEEDSTEP_PROCESSOR_PIII_C;
+		}
+
+	default:
+		return 0;
+	}
+}
+EXPORT_SYMBOL_GPL(speedstep_detect_processor);
+
+
+/*********************************************************************
+ *                     DETECT SPEEDSTEP SPEEDS                       *
+ *********************************************************************/
+
+unsigned int speedstep_get_freqs(unsigned int processor,
+				  unsigned int *low_speed,
+				  unsigned int *high_speed,
+				  void (*set_state) (unsigned int state,
+						     unsigned int notify)
+				 )
+{
+	unsigned int prev_speed;
+	unsigned int ret = 0;
+	unsigned long flags;
+
+	if ((!processor) || (!low_speed) || (!high_speed) || (!set_state))
+		return EINVAL;
+
+	/* get current speed */
+	prev_speed = speedstep_get_processor_frequency(processor);
+	if (!prev_speed)
+		return EIO;
+	
+	local_irq_save(flags);
+
+	/* switch to low state */
+	set_state(SPEEDSTEP_LOW, 0);
+	*low_speed = speedstep_get_processor_frequency(processor);
+	if (!*low_speed) {
+		ret = EIO;
+		goto out;
+	}
+
+	/* switch to high state */
+	set_state(SPEEDSTEP_HIGH, 0);
+	*high_speed = speedstep_get_processor_frequency(processor);
+	if (!*high_speed) {
+		ret = EIO;
+		goto out;
+	}
+
+	if (*low_speed == *high_speed) {
+		ret = ENODEV;
+		goto out;
+	}
+
+	/* switch to previous state, if necessary */
+	if (*high_speed != prev_speed)
+		set_state(SPEEDSTEP_LOW, 0);
+
+ out:
+	local_irq_restore(flags);
+	return (ret);
+}
+EXPORT_SYMBOL_GPL(speedstep_get_freqs);
+
+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION ("Library for Intel SpeedStep 1 or 2 cpufreq drivers.");
+MODULE_LICENSE ("GPL");
diff -urN linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
--- linux-2.5.73-bk3/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk4/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h	2003-06-26 05:00:22.000000000 -0700
@@ -0,0 +1,41 @@
+/*
+ * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  Library for common functions for Intel SpeedStep v.1 and v.2 support
+ *
+ *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
+ */
+
+
+
+/* processors */
+
+#define SPEEDSTEP_PROCESSOR_PIII_C_EARLY	0x00000001  /* Coppermine core */
+#define SPEEDSTEP_PROCESSOR_PIII_C		0x00000002  /* Coppermine core */
+#define SPEEDSTEP_PROCESSOR_PIII_T 		0x00000003  /* Tualatin core */
+#define SPEEDSTEP_PROCESSOR_P4M			0x00000004  /* P4-M with 100 MHz FSB */
+
+/* speedstep states -- only two of them */
+
+#define SPEEDSTEP_HIGH                  0x00000000
+#define SPEEDSTEP_LOW                   0x00000001
+
+
+/* detect a speedstep-capable processor */
+extern unsigned int speedstep_detect_processor (void);
+
+/* detect the current speed (in khz) of the processor */
+extern unsigned int speedstep_get_processor_frequency(unsigned int processor);
+
+
+/* detect the low and high speeds of the processor. The callback 
+ * set_state"'s first argument is either SPEEDSTEP_HIGH or 
+ * SPEEDSTEP_LOW; the second argument is zero so that no 
+ * cpufreq_notify_transition calls are initiated.
+ */
+extern unsigned int speedstep_get_freqs(unsigned int processor,
+	  unsigned int *low_speed,
+	  unsigned int *high_speed,
+	  void (*set_state) (unsigned int state, unsigned int notify));
diff -urN linux-2.5.73-bk3/arch/i386/kernel/i386_ksyms.c linux-2.5.73-bk4/arch/i386/kernel/i386_ksyms.c
--- linux-2.5.73-bk3/arch/i386/kernel/i386_ksyms.c	2003-06-22 11:33:35.000000000 -0700
+++ linux-2.5.73-bk4/arch/i386/kernel/i386_ksyms.c	2003-06-26 05:00:22.000000000 -0700
@@ -159,6 +159,7 @@
 
 /* TLB flushing */
 EXPORT_SYMBOL(flush_tlb_page);
+EXPORT_SYMBOL_GPL(flush_tlb_all);
 #endif
 
 #ifdef CONFIG_X86_IO_APIC
diff -urN linux-2.5.73-bk3/arch/i386/kernel/io_apic.c linux-2.5.73-bk4/arch/i386/kernel/io_apic.c
--- linux-2.5.73-bk3/arch/i386/kernel/io_apic.c	2003-06-26 04:59:42.000000000 -0700
+++ linux-2.5.73-bk4/arch/i386/kernel/io_apic.c	2003-06-26 05:00:22.000000000 -0700
@@ -1272,10 +1272,10 @@
 void __init print_IO_APIC(void)
 {
 	int apic, i;
-	struct IO_APIC_reg_00 reg_00;
-	struct IO_APIC_reg_01 reg_01;
-	struct IO_APIC_reg_02 reg_02;
-	struct IO_APIC_reg_03 reg_03;
+	union IO_APIC_reg_00 reg_00;
+	union IO_APIC_reg_01 reg_01;
+	union IO_APIC_reg_02 reg_02;
+	union IO_APIC_reg_03 reg_03;
 	unsigned long flags;
 
  	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
@@ -1292,47 +1292,47 @@
 	for (apic = 0; apic < nr_ioapics; apic++) {
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	*(int *)&reg_00 = io_apic_read(apic, 0);
-	*(int *)&reg_01 = io_apic_read(apic, 1);
-	if (reg_01.version >= 0x10)
-		*(int *)&reg_02 = io_apic_read(apic, 2);
-	if (reg_01.version >= 0x20)
-		*(int *)&reg_03 = io_apic_read(apic, 3);
+	reg_00.raw = io_apic_read(apic, 0);
+	reg_01.raw = io_apic_read(apic, 1);
+	if (reg_01.bits.version >= 0x10)
+		reg_02.raw = io_apic_read(apic, 2);
+	if (reg_01.bits.version >= 0x20)
+		reg_03.raw = io_apic_read(apic, 3);
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	printk("\n");
 	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
-	printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)&reg_00);
-	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.ID);
-	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.delivery_type);
-	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.LTS);
-	if (reg_00.ID >= APIC_BROADCAST_ID)
+	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
+	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
+	if (reg_00.bits.ID >= APIC_BROADCAST_ID)
 		UNEXPECTED_IO_APIC();
-	if (reg_00.__reserved_1 || reg_00.__reserved_2)
+	if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
 		UNEXPECTED_IO_APIC();
 
-	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
-	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.entries);
-	if (	(reg_01.entries != 0x0f) && /* older (Neptune) boards */
-		(reg_01.entries != 0x17) && /* typical ISA+PCI boards */
-		(reg_01.entries != 0x1b) && /* Compaq Proliant boards */
-		(reg_01.entries != 0x1f) && /* dual Xeon boards */
-		(reg_01.entries != 0x22) && /* bigger Xeon boards */
-		(reg_01.entries != 0x2E) &&
-		(reg_01.entries != 0x3F)
+	printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);
+	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
+	if (	(reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
+		(reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
+		(reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
+		(reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
+		(reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
+		(reg_01.bits.entries != 0x2E) &&
+		(reg_01.bits.entries != 0x3F)
 	)
 		UNEXPECTED_IO_APIC();
 
-	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.PRQ);
-	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.version);
-	if (	(reg_01.version != 0x01) && /* 82489DX IO-APICs */
-		(reg_01.version != 0x10) && /* oldest IO-APICs */
-		(reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */
-		(reg_01.version != 0x13) && /* Xeon IO-APICs */
-		(reg_01.version != 0x20)    /* Intel P64H (82806 AA) */
+	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
+	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
+	if (	(reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
+		(reg_01.bits.version != 0x10) && /* oldest IO-APICs */
+		(reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
+		(reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
+		(reg_01.bits.version != 0x20)    /* Intel P64H (82806 AA) */
 	)
 		UNEXPECTED_IO_APIC();
-	if (reg_01.__reserved_1 || reg_01.__reserved_2)
+	if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
 		UNEXPECTED_IO_APIC();
 
 	/*
@@ -1340,10 +1340,10 @@
 	 * but the value of reg_02 is read as the previous read register
 	 * value, so ignore it if reg_02 == reg_01.
 	 */
-	if (reg_01.version >= 0x10 && *(int *)&reg_02 != *(int *)&reg_01) {
-		printk(KERN_DEBUG ".... register #02: %08X\n", *(int *)&reg_02);
-		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.arbitration);
-		if (reg_02.__reserved_1 || reg_02.__reserved_2)
+	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
+		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
+		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
+		if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
 			UNEXPECTED_IO_APIC();
 	}
 
@@ -1352,11 +1352,11 @@
 	 * or reg_03, but the value of reg_0[23] is read as the previous read
 	 * register value, so ignore it if reg_03 == reg_0[12].
 	 */
-	if (reg_01.version >= 0x20 && *(int *)&reg_03 != *(int *)&reg_02 &&
-	    *(int *)&reg_03 != *(int *)&reg_01) {
-		printk(KERN_DEBUG ".... register #03: %08X\n", *(int *)&reg_03);
-		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.boot_DT);
-		if (reg_03.__reserved_1)
+	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
+	    reg_03.raw != reg_01.raw) {
+		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
+		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
+		if (reg_03.bits.__reserved_1)
 			UNEXPECTED_IO_APIC();
 	}
 
@@ -1365,7 +1365,7 @@
 	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
 			  " Stat Dest Deli Vect:   \n");
 
-	for (i = 0; i <= reg_01.entries; i++) {
+	for (i = 0; i <= reg_01.bits.entries; i++) {
 		struct IO_APIC_route_entry entry;
 
 		spin_lock_irqsave(&ioapic_lock, flags);
@@ -1546,7 +1546,7 @@
 
 static void __init enable_IO_APIC(void)
 {
-	struct IO_APIC_reg_01 reg_01;
+	union IO_APIC_reg_01 reg_01;
 	int i;
 	unsigned long flags;
 
@@ -1563,9 +1563,9 @@
 	 */
 	for (i = 0; i < nr_ioapics; i++) {
 		spin_lock_irqsave(&ioapic_lock, flags);
-		*(int *)&reg_01 = io_apic_read(i, 1);
+		reg_01.raw = io_apic_read(i, 1);
 		spin_unlock_irqrestore(&ioapic_lock, flags);
-		nr_ioapic_registers[i] = reg_01.entries+1;
+		nr_ioapic_registers[i] = reg_01.bits.entries+1;
 	}
 
 	/*
@@ -1597,7 +1597,7 @@
 #ifndef CONFIG_X86_NUMAQ
 static void __init setup_ioapic_ids_from_mpc(void)
 {
-	struct IO_APIC_reg_00 reg_00;
+	union IO_APIC_reg_00 reg_00;
 	unsigned long phys_id_present_map;
 	int apic;
 	int i;
@@ -1617,7 +1617,7 @@
 
 		/* Read the register 0 value */
 		spin_lock_irqsave(&ioapic_lock, flags);
-		*(int *)&reg_00 = io_apic_read(apic, 0);
+		reg_00.raw = io_apic_read(apic, 0);
 		spin_unlock_irqrestore(&ioapic_lock, flags);
 		
 		old_id = mp_ioapics[apic].mpc_apicid;
@@ -1626,8 +1626,8 @@
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
 				apic, mp_ioapics[apic].mpc_apicid);
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
-				reg_00.ID);
-			mp_ioapics[apic].mpc_apicid = reg_00.ID;
+				reg_00.bits.ID);
+			mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
 		}
 
 		/*
@@ -1671,18 +1671,18 @@
 		printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
 					mp_ioapics[apic].mpc_apicid);
 
-		reg_00.ID = mp_ioapics[apic].mpc_apicid;
+		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
 		spin_lock_irqsave(&ioapic_lock, flags);
-		io_apic_write(apic, 0, *(int *)&reg_00);
+		io_apic_write(apic, 0, reg_00.raw);
 		spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		/*
 		 * Sanity check
 		 */
 		spin_lock_irqsave(&ioapic_lock, flags);
-		*(int *)&reg_00 = io_apic_read(apic, 0);
+		reg_00.raw = io_apic_read(apic, 0);
 		spin_unlock_irqrestore(&ioapic_lock, flags);
-		if (reg_00.ID != mp_ioapics[apic].mpc_apicid)
+		if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
 			panic("could not set ID!\n");
 		else
 			printk(" ok.\n");
@@ -2220,7 +2220,7 @@
 
 int __init io_apic_get_unique_id (int ioapic, int apic_id)
 {
-	struct IO_APIC_reg_00 reg_00;
+	union IO_APIC_reg_00 reg_00;
 	static unsigned long apic_id_map = 0;
 	unsigned long flags;
 	int i = 0;
@@ -2238,13 +2238,13 @@
 		apic_id_map = phys_cpu_present_map;
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	*(int *)&reg_00 = io_apic_read(ioapic, 0);
+	reg_00.raw = io_apic_read(ioapic, 0);
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	if (apic_id >= IO_APIC_MAX_ID) {
 		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
-			"%d\n", ioapic, apic_id, reg_00.ID);
-		apic_id = reg_00.ID;
+			"%d\n", ioapic, apic_id, reg_00.bits.ID);
+		apic_id = reg_00.bits.ID;
 	}
 
 	/*
@@ -2269,16 +2269,16 @@
 
 	apic_id_map |= apicid_to_cpu_present(apic_id);
 
-	if (reg_00.ID != apic_id) {
-		reg_00.ID = apic_id;
+	if (reg_00.bits.ID != apic_id) {
+		reg_00.bits.ID = apic_id;
 
 		spin_lock_irqsave(&ioapic_lock, flags);
-		io_apic_write(ioapic, 0, *(int *)&reg_00);
-		*(int *)&reg_00 = io_apic_read(ioapic, 0);
+		io_apic_write(ioapic, 0, reg_00.raw);
+		reg_00.raw = io_apic_read(ioapic, 0);
 		spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		/* Sanity check */
-		if (reg_00.ID != apic_id)
+		if (reg_00.bits.ID != apic_id)
 			panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
 	}
 
@@ -2290,27 +2290,27 @@
 
 int __init io_apic_get_version (int ioapic)
 {
-	struct IO_APIC_reg_01	reg_01;
+	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	*(int *)&reg_01 = io_apic_read(ioapic, 1);
+	reg_01.raw = io_apic_read(ioapic, 1);
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
-	return reg_01.version;
+	return reg_01.bits.version;
 }
 
 
 int __init io_apic_get_redir_entries (int ioapic)
 {
-	struct IO_APIC_reg_01	reg_01;
+	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	*(int *)&reg_01 = io_apic_read(ioapic, 1);
+	reg_01.raw = io_apic_read(ioapic, 1);
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
-	return reg_01.entries;
+	return reg_01.bits.entries;
 }
 
 
diff -urN linux-2.5.73-bk3/arch/i386/kernel/traps.c linux-2.5.73-bk4/arch/i386/kernel/traps.c
--- linux-2.5.73-bk3/arch/i386/kernel/traps.c	2003-06-22 11:32:35.000000000 -0700
+++ linux-2.5.73-bk4/arch/i386/kernel/traps.c	2003-06-26 05:00:22.000000000 -0700
@@ -123,19 +123,20 @@
 	show_trace(tsk, (unsigned long *)esp);
 }
 
-void show_stack(struct task_struct *task, unsigned long * esp)
+void show_stack(struct task_struct *task, unsigned long *esp)
 {
 	unsigned long *stack;
 	int i;
 
-	// debugging aid: "show_stack(NULL);" prints the
-	// back trace for this cpu.
-
-	if(esp==NULL)
-		esp=(unsigned long*)&esp;
+	if (esp == NULL) {
+		if (task)
+			esp = (unsigned long*)task->thread.esp;
+		else
+			esp = (unsigned long *)&esp;
+	}
 
 	stack = esp;
-	for(i=0; i < kstack_depth_to_print; i++) {
+	for(i = 0; i < kstack_depth_to_print; i++) {
 		if (((long) stack & (THREAD_SIZE-1)) == 0)
 			break;
 		if (i && ((i % 8) == 0))
diff -urN linux-2.5.73-bk3/arch/i386/pci/acpi.c linux-2.5.73-bk4/arch/i386/pci/acpi.c
--- linux-2.5.73-bk3/arch/i386/pci/acpi.c	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk4/arch/i386/pci/acpi.c	2003-06-26 05:00:22.000000000 -0700
@@ -3,6 +3,16 @@
 #include <linux/init.h>
 #include "pci.h"
 
+struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
+{
+	if (domain != 0) {
+		printk(KERN_WARNING "PCI: Multiple domains not supported\n");
+		return NULL;
+	}
+
+	return pcibios_scan_root(busnum);
+}
+
 static int __init pci_acpi_init(void)
 {
 	if (pcibios_scanned)
diff -urN linux-2.5.73-bk3/arch/ia64/pci/pci.c linux-2.5.73-bk4/arch/ia64/pci/pci.c
--- linux-2.5.73-bk3/arch/ia64/pci/pci.c	2003-06-26 04:59:42.000000000 -0700
+++ linux-2.5.73-bk4/arch/ia64/pci/pci.c	2003-06-26 05:00:22.000000000 -0700
@@ -284,21 +284,21 @@
 }
 
 struct pci_bus *
-pcibios_scan_root (void *handle, int seg, int bus)
+pci_acpi_scan_root (struct acpi_device *device, int domain, int bus)
 {
 	struct pci_root_info info;
 	struct pci_controller *controller;
 	unsigned int windows = 0;
 	char *name;
 
-	printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus);
-	controller = alloc_pci_controller(seg);
+	printk("PCI: Probing PCI hardware on bus (%04x:%02x)\n", domain, bus);
+	controller = alloc_pci_controller(domain);
 	if (!controller)
 		goto out1;
 
-	controller->acpi_handle = handle;
+	controller->acpi_handle = device->handle;
 
-	acpi_walk_resources(handle, METHOD_NAME__CRS, count_window, &windows);
+	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, &windows);
 	controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL);
 	if (!controller->window)
 		goto out2;
@@ -307,10 +307,10 @@
 	if (!name)
 		goto out3;
 
-	sprintf(name, "PCI Bus %02x:%02x", seg, bus);
+	sprintf(name, "PCI Bus %04x:%02x", domain, bus);
 	info.controller = controller;
 	info.name = name;
-	acpi_walk_resources(handle, METHOD_NAME__CRS, add_window, &info);
+	acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, &info);
 
 	return scan_root_bus(bus, &pci_root_ops, controller);
 
diff -urN linux-2.5.73-bk3/arch/ppc/kernel/entry.S linux-2.5.73-bk4/arch/ppc/kernel/entry.S
--- linux-2.5.73-bk3/arch/ppc/kernel/entry.S	2003-06-26 04:59:44.000000000 -0700
+++ linux-2.5.73-bk4/arch/ppc/kernel/entry.S	2003-06-26 05:00:25.000000000 -0700
@@ -200,9 +200,6 @@
 	andi.	r11,r11,_TIF_FORCE_NOERROR
 	bne	30f
 	neg	r3,r3
-	cmpi	0,r3,ERESTARTNOHAND
-	bne	22f
-	li	r3,EINTR
 22:	lwz	r10,_CCR(r1)	/* Set SO bit in CR */
 	oris	r10,r10,0x1000
 	stw	r10,_CCR(r1)
diff -urN linux-2.5.73-bk3/drivers/acpi/pci_root.c linux-2.5.73-bk4/drivers/acpi/pci_root.c
--- linux-2.5.73-bk3/drivers/acpi/pci_root.c	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk4/drivers/acpi/pci_root.c	2003-06-26 05:00:25.000000000 -0700
@@ -246,8 +246,6 @@
 	switch (status) {
 	case AE_OK:
 		root->id.segment = (u16) value;
-		printk("_SEG exists! Unsupported. Abort.\n");
-		BUG();
 		break;
 	case AE_NOT_FOUND:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
@@ -309,7 +307,7 @@
 	 * PCI namespace does not get created until this call is made (and 
 	 * thus the root bridge's pci_dev does not exist).
 	 */
-	root->bus = pcibios_scan_root(root->id.bus);
+	root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus);
 	if (!root->bus) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
 			"Bus %02x:%02x not present in PCI namespace\n", 
diff -urN linux-2.5.73-bk3/drivers/block/rd.c linux-2.5.73-bk4/drivers/block/rd.c
--- linux-2.5.73-bk3/drivers/block/rd.c	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk4/drivers/block/rd.c	2003-06-26 05:00:25.000000000 -0700
@@ -271,9 +271,6 @@
 {
 	unsigned unit = minor(inode->i_rdev);
 
-	if (unit >= NUM_RAMDISKS)
-		return -ENODEV;
-
 	/*
 	 * Immunize device against invalidate_buffers() and prune_icache().
 	 */
diff -urN linux-2.5.73-bk3/drivers/char/agp/nvidia-agp.c linux-2.5.73-bk4/drivers/char/agp/nvidia-agp.c
--- linux-2.5.73-bk3/drivers/char/agp/nvidia-agp.c	2003-06-22 11:32:36.000000000 -0700
+++ linux-2.5.73-bk4/drivers/char/agp/nvidia-agp.c	2003-06-26 05:00:25.000000000 -0700
@@ -169,7 +169,8 @@
 		mem->is_flushed = TRUE;
 	}
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
-		agp_bridge->gatt_table[nvidia_private.pg_offset + j] = mem->memory[i];
+		agp_bridge->gatt_table[nvidia_private.pg_offset + j] =
+				agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
diff -urN linux-2.5.73-bk3/drivers/char/agp/sis-agp.c linux-2.5.73-bk4/drivers/char/agp/sis-agp.c
--- linux-2.5.73-bk3/drivers/char/agp/sis-agp.c	2003-06-22 11:32:31.000000000 -0700
+++ linux-2.5.73-bk4/drivers/char/agp/sis-agp.c	2003-06-26 05:00:25.000000000 -0700
@@ -151,6 +151,10 @@
 		.device_id	= PCI_DEVICE_ID_SI_550,
 		.chipset_name	= "550",
 	},
+	{
+		.device_id	= PCI_DEVICE_ID_SI_655,
+		.chipset_name	= "655",
+	},
 	{ }, /* dummy final entry, always present */
 };
 
diff -urN linux-2.5.73-bk3/drivers/char/ip2main.c linux-2.5.73-bk4/drivers/char/ip2main.c
--- linux-2.5.73-bk3/drivers/char/ip2main.c	2003-06-22 11:33:36.000000000 -0700
+++ linux-2.5.73-bk4/drivers/char/ip2main.c	2003-06-26 05:00:25.000000000 -0700
@@ -707,40 +707,42 @@
 				} 
 			} 
 #else /* LINUX_VERSION_CODE > 2.1.99 */
-			struct pci_dev *pci_dev_i = NULL;
-			pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE,
-						  PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
-			if (pci_dev_i != NULL) {
-				unsigned int addr;
-				unsigned char pci_irq;
-
-				ip2config.type[i] = PCI;
-				status =
-				pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
-				if ( addr & 1 ) {
-					ip2config.addr[i]=(USHORT)(addr&0xfffe);
-				} else {
-					printk( KERN_ERR "IP2: PCI I/O address error\n");
-				}
-				status =
-				pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq);
+			{
+				struct pci_dev *pci_dev_i = NULL;
+				pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE,
+							  PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
+				if (pci_dev_i != NULL) {
+					unsigned int addr;
+					unsigned char pci_irq;
+
+					ip2config.type[i] = PCI;
+					status =
+					pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
+					if ( addr & 1 ) {
+						ip2config.addr[i]=(USHORT)(addr&0xfffe);
+					} else {
+						printk( KERN_ERR "IP2: PCI I/O address error\n");
+					}
+					status =
+					pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq);
 
 //		If the PCI BIOS assigned it, lets try and use it.  If we
 //		can't acquire it or it screws up, deal with it then.
 
-//				if (!is_valid_irq(pci_irq)) {
-//					printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
-//					pci_irq = 0;
-//				}
-				ip2config.irq[i] = pci_irq;
-			} else {	// ann error
-				ip2config.addr[i] = 0;
-				if (status == PCIBIOS_DEVICE_NOT_FOUND) {
-					printk( KERN_ERR "IP2: PCI board %d not found\n", i );
-				} else {
-					pcibios_strerror(status);
-				}
-			} 
+//					if (!is_valid_irq(pci_irq)) {
+//						printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
+//						pci_irq = 0;
+//					}
+					ip2config.irq[i] = pci_irq;
+				} else {	// ann error
+					ip2config.addr[i] = 0;
+					if (status == PCIBIOS_DEVICE_NOT_FOUND) {
+						printk( KERN_ERR "IP2: PCI board %d not found\n", i );
+					} else {
+						pcibios_strerror(status);
+					}
+				} 
+			}
 #endif	/* ! 2_0_X */
 #else
 			printk( KERN_ERR "IP2: PCI card specified but PCI support not\n");
diff -urN linux-2.5.73-bk3/drivers/char/n_tty.c linux-2.5.73-bk4/drivers/char/n_tty.c
--- linux-2.5.73-bk3/drivers/char/n_tty.c	2003-06-22 11:32:30.000000000 -0700
+++ linux-2.5.73-bk4/drivers/char/n_tty.c	2003-06-26 05:00:25.000000000 -0700
@@ -325,7 +325,7 @@
 {
 	if (tty->erasing) {
 		put_char('/', tty);
-		tty->column += 2;
+		tty->column++;
 		tty->erasing = 0;
 	}
 }
diff -urN linux-2.5.73-bk3/drivers/ide/ide-pnp.c linux-2.5.73-bk4/drivers/ide/ide-pnp.c
--- linux-2.5.73-bk3/drivers/ide/ide-pnp.c	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk4/drivers/ide/ide-pnp.c	2003-06-26 05:00:25.000000000 -0700
@@ -4,7 +4,7 @@
  * This file provides autodetection for ISA PnP IDE interfaces.
  * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
  *
- * Copyright (C) 2000 Andrey Panin <pazke@orbita.don.sitek.net>
+ * Copyright (C) 2000 Andrey Panin <pazke@donpac.ru>
  *
  * 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
diff -urN linux-2.5.73-bk3/drivers/net/Kconfig linux-2.5.73-bk4/drivers/net/Kconfig
--- linux-2.5.73-bk3/drivers/net/Kconfig	2003-06-22 11:33:13.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/Kconfig	2003-06-26 05:00:28.000000000 -0700
@@ -492,16 +492,16 @@
 	help
 	  Say Y here to support the Ethernet subsystem on your GT96100 card.
 
-config MIPS_AU1000_ENET
+config MIPS_AU1X00_ENET
 	bool "MIPS AU1000 Ethernet support"
-	depends on NET_ETHERNET && MIPS_AU1000
+	depends on NET_ETHERNET && SOC_AU1X00
 	help
-	  If you have an Alchemy Semi AU1000 ethernet controller
-	  on an SGI MIPS system, say Y.  Otherwise, say N.
+	  If you have an Alchemy Semi AU1X00 based system
+	  say Y.  Otherwise, say N.
 
 config NET_SB1250_MAC
 	tristate "SB1250 Ethernet support"
-	depends on NET_ETHERNET && SIBYTE_SB1250
+	depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC
 
 config SGI_IOC3_ETH
 	bool "SGI IOC3 Ethernet"
@@ -511,6 +511,10 @@
 	  the Ethernet-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>.
 
+config SGI_O2MACE_ETH
+	tristate "SGI O2 MACE Fast Ethernet support"
+	depends on NET_ETHERNET && SGI_IP32=y
+
 config STNIC
 	tristate "National DP83902AV  support"
 	depends on NET_ETHERNET && SUPERH
@@ -1391,6 +1395,10 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module will be
 	  called cs89x.
 
+config TC35815
+	tristate "TOSHIBA TC35815 Ethernet support"
+	depends on NET_PCI && PCI
+
 config DGRS
 	tristate "Digi Intl. RightSwitch SE-X support"
 	depends on NET_PCI && (PCI || EISA)
@@ -1839,14 +1847,14 @@
 	  The module will be called de620.
 
 config SGISEEQ
-	bool "SGI Seeq ethernet controller support"
+	tristate "SGI Seeq ethernet controller support"
 	depends on NET_ETHERNET && SGI_IP22
 	help
 	  Say Y here if you have an Seeq based Ethernet network card. This is
 	  used in many Silicon Graphics machines.
 
 config DECLANCE
-	bool "DEC LANCE ethernet controller support"
+	tristate "DEC LANCE ethernet controller support"
 	depends on NET_ETHERNET && DECSTATION
 	help
 	  This driver is for the series of Ethernet controllers produced by
diff -urN linux-2.5.73-bk3/drivers/net/Makefile linux-2.5.73-bk4/drivers/net/Makefile
--- linux-2.5.73-bk3/drivers/net/Makefile	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/Makefile	2003-06-26 05:00:28.000000000 -0700
@@ -117,6 +117,7 @@
 obj-$(CONFIG_SUN3LANCE) += sun3lance.o
 obj-$(CONFIG_DEFXX) += defxx.o
 obj-$(CONFIG_SGISEEQ) += sgiseeq.o
+obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o
 obj-$(CONFIG_AT1700) += at1700.o
 obj-$(CONFIG_FMV18X) += fmv18x.o
 obj-$(CONFIG_EL1) += 3c501.o
@@ -156,7 +157,7 @@
 obj-$(CONFIG_EQUALIZER) += eql.o
 obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
 obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
-obj-$(CONFIG_MIPS_AU1000_ENET) += au1000_eth.o
+obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
 obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
 obj-$(CONFIG_BAGETLANCE) += bagetlance.o
 obj-$(CONFIG_DECLANCE) += declance.o
diff -urN linux-2.5.73-bk3/drivers/net/Makefile.lib linux-2.5.73-bk4/drivers/net/Makefile.lib
--- linux-2.5.73-bk3/drivers/net/Makefile.lib	2003-06-22 11:33:11.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/Makefile.lib	2003-06-26 05:00:28.000000000 -0700
@@ -24,6 +24,7 @@
 obj-$(CONFIG_PCMCIA_SMC91C92)	+= crc32.o
 obj-$(CONFIG_PCMCIA_XIRTULIP)	+= crc32.o
 obj-$(CONFIG_PCNET32)		+= crc32.o
+obj-$(CONFIG_SGI_IOC3_ETH)	+= crc32.o
 obj-$(CONFIG_SIS900)		+= crc32.o
 obj-$(CONFIG_SMC9194)		+= crc32.o
 obj-$(CONFIG_ADAPTEC_STARFIRE)	+= crc32.o
diff -urN linux-2.5.73-bk3/drivers/net/Space.c linux-2.5.73-bk4/drivers/net/Space.c
--- linux-2.5.73-bk3/drivers/net/Space.c	2003-06-22 11:32:32.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/Space.c	2003-06-26 05:00:28.000000000 -0700
@@ -82,7 +82,6 @@
 extern int SK_init(struct net_device *);
 extern int seeq8005_probe(struct net_device *);
 extern int smc_init( struct net_device * );
-extern int sgiseeq_probe(struct net_device *);
 extern int atarilance_probe(struct net_device *);
 extern int sun3lance_probe(struct net_device *);
 extern int sun3_82586_probe(struct net_device *);
@@ -343,14 +342,6 @@
 	{NULL, 0},
 };
 
-
-static struct devprobe sgi_probes[] __initdata = {
-#ifdef CONFIG_SGISEEQ
-	{sgiseeq_probe, 0},
-#endif
-	{NULL, 0},
-};
-
 static struct devprobe mips_probes[] __initdata = {
 #ifdef CONFIG_MIPS_JAZZ_SONIC
 	{sonic_probe, 0},
@@ -385,8 +376,6 @@
 		return 0;
 	if (probe_list(dev, mips_probes) == 0)
 		return 0;
-	if (probe_list(dev, sgi_probes) == 0)
-		return 0;
 	if (probe_list(dev, eisa_probes) == 0)
 		return 0;
 	if (probe_list(dev, mca_probes) == 0)
diff -urN linux-2.5.73-bk3/drivers/net/acenic.c linux-2.5.73-bk4/drivers/net/acenic.c
--- linux-2.5.73-bk3/drivers/net/acenic.c	2003-06-22 11:32:44.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/acenic.c	2003-06-26 05:00:28.000000000 -0700
@@ -3026,9 +3026,6 @@
 		return 0;
 
 	case ETHTOOL_SSET:
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-
 		link = readl(&regs->GigLnkState);
 		if (link & LNK_1000MB)
 			speed = SPEED_1000;
diff -urN linux-2.5.73-bk3/drivers/net/au1000_eth.c linux-2.5.73-bk4/drivers/net/au1000_eth.c
--- linux-2.5.73-bk3/drivers/net/au1000_eth.c	2003-06-22 11:32:55.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/au1000_eth.c	2003-06-26 05:00:28.000000000 -0700
@@ -1,13 +1,10 @@
 /*
- *
  * Alchemy Semi Au1000 ethernet driver
  *
  * Copyright 2001 MontaVista Software Inc.
  * Author: MontaVista Software, Inc.
  *         	ppopov@mvista.com or source@mvista.com
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -20,16 +17,8 @@
  *  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.
- *
- * ########################################################################
- *
- * 
  */
-
-#ifndef __mips__
-#error This driver only works with MIPS architectures!
-#endif
-
+#include <linux/config.h>
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -125,7 +114,7 @@
 	},
   au1100_iflist[NUM_INTERFACES] = {
 		{AU1000_ETH0_BASE, AU1000_ETH0_IRQ}, 
-		{NULL, NULL}
+		{0, 0}
 	};
 
 static char version[] __devinitdata =
@@ -152,13 +141,6 @@
  * code.
  */
 
-static char *phy_link[] = 
-	{"unknown", 
-	"10Base2", "10BaseT", 
-	"AUI",
-	"100BaseT", "100BaseTX", "100BaseFX"
-	};
-
 int bcm_5201_init(struct net_device *dev, int phy_addr)
 {
 	s16 data;
@@ -184,6 +166,11 @@
 	data &= ~MII_FDX_LED;
 	mdio_write(dev, phy_addr, MII_INT, data);
 
+	/* Enable TX LED instead of FDX */
+	data = mdio_read(dev, phy_addr, MII_INT);
+	data &= ~MII_FDX_LED;
+	mdio_write(dev, phy_addr, MII_INT, data);
+
 	if (au1000_debug > 4) dump_mii(dev, phy_addr);
 	return 0;
 }
@@ -640,7 +627,7 @@
 	int prid;
 	int base_addr, irq;
 
-	prid = read_32bit_cp0_register(CP0_PRID);
+	prid = read_c0_prid();
 	for (i=0; i<NUM_INTERFACES; i++) {
 		if ( (prid & 0xffff0000) == 0x00030000 ) {
 			base_addr = au1000_iflist[i].port;
@@ -657,11 +644,11 @@
 		}
 		// check for valid entries, au1100 only has one entry
 		if (base_addr && irq) {
-		if (au1000_probe1(NULL, base_addr, irq, i) != 0) {
-			return -ENODEV;
+			if (au1000_probe1(NULL, base_addr, irq, i) != 0) {
+				return -ENODEV;
+			}
 		}
 	}
-	}
 	return 0;
 }
 
@@ -675,10 +662,11 @@
 	char *pmac, *argptr;
 	char ethaddr[6];
 
-	if (!request_region(ioaddr, MAC_IOSIZE, "Au1000 ENET"))
+	if (!request_region(PHYSADDR(ioaddr), MAC_IOSIZE, "Au1000 ENET"))
 		 return -ENODEV;
 
-	if (version_printed++ == 0) printk(version);
+	if (version_printed++ == 0)
+		printk(version);
 
 	if (!dev)
 		dev = init_etherdev(NULL, sizeof(struct au1000_private));
@@ -690,7 +678,7 @@
 	}
 
 	printk("%s: Au1xxx ethernet found at 0x%lx, irq %d\n", 
-			dev->name, ioaddr, irq);
+	       dev->name, ioaddr, irq);
 
 	aup = dev->priv;
 
@@ -816,7 +804,7 @@
 	return 0;
 
 free_region:
-	release_region(ioaddr, MAC_IOSIZE);
+	release_region(PHYSADDR(ioaddr), MAC_IOSIZE);
 	unregister_netdev(dev);
 	if (aup->vaddr) 
 		dma_free((void *)aup->vaddr, 
@@ -1047,8 +1035,9 @@
 	ptxd = aup->tx_dma_ring[aup->tx_tail];
 
 	while (ptxd->buff_stat & TX_T_DONE) {
-		update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
+ 		update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_tail]  & 0x3ff);
 		ptxd->buff_stat &= ~TX_T_DONE;
+ 		aup->tx_len[aup->tx_tail] = 0;
 		ptxd->len = 0;
 		au_sync();
 
@@ -1088,7 +1077,8 @@
 		return 1;
 	}
 	else if (buff_stat & TX_T_DONE) {
-		update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
+ 		update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_head] & 0x3ff);
+ 		aup->tx_len[aup->tx_head] = 0;
 		ptxd->len = 0;
 	}
 
@@ -1103,11 +1093,13 @@
 		for (i=skb->len; i<MAC_MIN_PKT_SIZE; i++) { 
 			((char *)pDB->vaddr)[i] = 0;
 		}
+ 		aup->tx_len[aup->tx_head] = MAC_MIN_PKT_SIZE;
 		ptxd->len = MAC_MIN_PKT_SIZE;
 	}
-	else
+	else {
+ 		aup->tx_len[aup->tx_head] = skb->len;
 		ptxd->len = skb->len;
-
+	}
 	ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
 	au_sync();
 	dev_kfree_skb(skb);
@@ -1244,6 +1236,8 @@
 	printk(KERN_ERR "%s: au1000_tx_timeout: dev=%p\n", dev->name, dev);
 	reset_mac(dev);
 	au1000_init(dev);
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
 }
 
 static void set_rx_mode(struct net_device *dev)
@@ -1269,7 +1263,8 @@
 		mc_filter[1] = mc_filter[0] = 0;
 		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
 			 i++, mclist = mclist->next) {
-			set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter);
+			set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr)>>26, 
+					mc_filter);
 		}
 		aup->mac->multi_hash_high = mc_filter[1];
 		aup->mac->multi_hash_low = mc_filter[0];
@@ -1285,18 +1280,21 @@
 
 	/* fixme */
 	switch(cmd) { 
-	case SIOCGMIIPHY:		/* Get the address of the PHY in use. */
+	case SIOCGMIIPHY:	/* Get the address of the PHY in use. */
 		data[0] = PHY_ADDRESS;
+		return 0;
 
-	case SIOCGMIIREG:		/* Read the specified MII register. */
+	case SIOCGMIIREG:	/* Read the specified MII register. */
 		//data[3] = mdio_read(ioaddr, data[0], data[1]); 
 		return 0;
 
-	case SIOCSMIIREG:		/* Write the specified MII register */
+	case SIOCSMIIREG:	/* Write the specified MII register */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
+
 		//mdio_write(ioaddr, data[0], data[1], data[2]);
 		return 0;
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff -urN linux-2.5.73-bk3/drivers/net/au1000_eth.h linux-2.5.73-bk4/drivers/net/au1000_eth.h
--- linux-2.5.73-bk3/drivers/net/au1000_eth.h	2003-06-22 11:32:40.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/au1000_eth.h	2003-06-26 05:00:28.000000000 -0700
@@ -1,13 +1,10 @@
 /*
- *
  * Alchemy Semi Au1000 ethernet driver include file
  *
  * Author: Pete Popov <ppopov@mvista.com>
  *
  * Copyright 2001 MontaVista Software Inc.
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -20,11 +17,8 @@
  *  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.
- *
- * ########################################################################
- *
- * 
  */
+#include <linux/config.h>
 
 
 #define NUM_INTERFACES 2
@@ -137,7 +131,7 @@
 #define MII_AUX_100      0x0002
 #define MII_AUX_F100     0x0004
 #define MII_AUX_ANEG     0x0008
-#define MII_FDX_LED      0x8000
+#define MII_FDX_LED	 0x8000
 
 typedef struct mii_phy {
 	struct mii_phy * next;
@@ -203,6 +197,7 @@
 	db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS];
 	volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA];
 	volatile tx_dma_t *tx_dma_ring[NUM_TX_DMA];
+	int tx_len[NUM_TX_DMA];
 	db_dest_t *rx_db_inuse[NUM_RX_DMA];
 	db_dest_t *tx_db_inuse[NUM_TX_DMA];
 	u32 rx_head;
diff -urN linux-2.5.73-bk3/drivers/net/declance.c linux-2.5.73-bk4/drivers/net/declance.c
--- linux-2.5.73-bk3/drivers/net/declance.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/declance.c	2003-06-26 05:00:28.000000000 -0700
@@ -5,6 +5,8 @@
  *
  *      adopted from sunlance.c by Richard van den Berg
  *
+ *      Copyright (C) 2002, 2003  Maciej W. Rozycki
+ *
  *      additional sources:
  *      - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
  *        Revision 1.2
@@ -16,76 +18,71 @@
  *      v0.002: Removed most sparc stuff, left only some module and dma stuff.
  *
  *      v0.003: Enhanced base address calculation from proposals by
- *      Harald Koerfgen and Thomas Riemer.
+ *              Harald Koerfgen and Thomas Riemer.
  *
  *      v0.004: lance-regs is pointing at the right addresses, added prom
- *      check. First start of address mapping and DMA.
+ *              check. First start of address mapping and DMA.
  *
- *      v0.005: started to play around with LANCE-DMA. This driver will not work
- *      for non IOASIC lances. HK
+ *      v0.005: started to play around with LANCE-DMA. This driver will not
+ *              work for non IOASIC lances. HK
  *
- *      v0.006: added pointer arrays to lance_private and setup routine for them
- *      in dec_lance_init. HK
+ *      v0.006: added pointer arrays to lance_private and setup routine for
+ *              them in dec_lance_init. HK
  *
- *      v0.007: Big shit. The LANCE seems to use a different DMA mechanism to access
- *      the init block. This looks like one (short) word at a time, but the smallest
- *      amount the IOASIC can transfer is a (long) word. So we have a 2-2 padding here.
- *      Changed lance_init_block accordingly. The 16-16 padding for the buffers
- *      seems to be correct. HK
+ *      v0.007: Big shit. The LANCE seems to use a different DMA mechanism to
+ *              access the init block. This looks like one (short) word at a
+ *              time, but the smallest amount the IOASIC can transfer is a
+ *              (long) word. So we have a 2-2 padding here. Changed
+ *              lance_init_block accordingly. The 16-16 padding for the buffers
+ *              seems to be correct. HK
  *
- *     v0.008 - mods to make PMAX_LANCE work. 01/09/1999 triemer
- */
-
-#undef DEBUG_DRIVER
-
-static char *version =
-"declance.c: v0.008 by Linux Mips DECstation task force\n";
-
-static char *lancestr = "LANCE";
-
-/*
- * card types
+ *      v0.008: mods to make PMAX_LANCE work. 01/09/1999 triemer
+ *
+ *      v0.009: Module support fixes, multiple interfaces support, various
+ *              bits. macro
  */
-#define ASIC_LANCE 1
-#define PMAD_LANCE 2
-#define PMAX_LANCE 3
 
+#include <linux/config.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/if_ether.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/spinlock.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
 
+#include <asm/addrspace.h>
 #include <asm/dec/interrupts.h>
-#include <asm/dec/ioasic_ints.h>
+#include <asm/dec/ioasic.h>
 #include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/kn01.h>
 #include <asm/dec/machtype.h>
 #include <asm/dec/tc.h>
-#include <asm/dec/kn01.h>
-#include <asm/wbflush.h>
-#include <asm/addrspace.h>
+#include <asm/system.h>
 
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/utsname.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/delay.h>
-#include <linux/crc32.h>
-#include <asm/io.h>
-#include <linux/etherdevice.h>
+static char version[] __devinitdata =
+"declance.c: v0.009 by Linux MIPS DECstation task force\n";
+
+MODULE_AUTHOR("Linux MIPS DECstation task force");
+MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * card types
+ */
+#define ASIC_LANCE 1
+#define PMAD_LANCE 2
+#define PMAX_LANCE 3
 
 #ifndef CONFIG_TC
 unsigned long system_base;
 unsigned long dmaptr;
 #endif
-static int type;
 
 #define LE_CSR0 0
 #define LE_CSR1 1
@@ -160,8 +157,6 @@
 #define TX_BUFF_SIZE            PKT_BUF_SZ
 
 #undef TEST_HITS
-#define DEBUG_DRIVER 1
-
 #define ZERO 0
 
 /* The DS2000/3000 have a linear 64 KB buffer.
@@ -179,26 +174,26 @@
  */
 
 struct lance_rx_desc {
-	unsigned short rmd0;	/* low address of packet */
+	unsigned short rmd0;		/* low address of packet */
 	short gap0;
 	unsigned char rmd1_hadr;	/* high address of packet */
 	unsigned char rmd1_bits;	/* descriptor bits */
 	short gap1;
-	short length;		/* This length is 2s complement (negative)!
-				   * Buffer length
-				 */
+	short length;			/* 2s complement (negative!)
+					   of buffer length */
 	short gap2;
-	unsigned short mblength;	/* This is the actual number of bytes received */
+	unsigned short mblength;	/* actual number of bytes received */
 	short gap3;
 };
 
 struct lance_tx_desc {
-	unsigned short tmd0;	/* low address of packet */
+	unsigned short tmd0;		/* low address of packet */
 	short gap0;
 	unsigned char tmd1_hadr;	/* high address of packet */
 	unsigned char tmd1_bits;	/* descriptor bits */
 	short gap1;
-	short length;		/* Length is 2s complement (negative)! */
+	short length;			/* 2s complement (negative!)
+					   of buffer length */
 	short gap2;
 	unsigned short misc;
 	short gap3;
@@ -207,28 +202,26 @@
 
 /* First part of the LANCE initialization block, described in databook. */
 struct lance_init_block {
-	unsigned short mode;	/* Pre-set mode (reg. 15) */
+	unsigned short mode;		/* pre-set mode (reg. 15) */
 	short gap0;
 
-	unsigned char phys_addr[12];	/* Physical ethernet address
-					   * only 0, 1, 4, 5, 8, 9 are valid
-					   * 2, 3, 6, 7, 10, 11 are gaps
-					 */
-	unsigned short filter[8];	/* Multicast filter.
-					   * only 0, 2, 4, 6 are valid
-					   * 1, 3, 5, 7 are gaps
-					 */
+	unsigned char phys_addr[12];	/* physical ethernet address
+					   only 0, 1, 4, 5, 8, 9 are valid
+					   2, 3, 6, 7, 10, 11 are gaps */
+	unsigned short filter[8];	/* multicast filter
+					   only 0, 2, 4, 6 are valid
+					   1, 3, 5, 7 are gaps */
 
 	/* Receive and transmit ring base, along with extra bits. */
-	unsigned short rx_ptr;	/* receive descriptor addr */
+	unsigned short rx_ptr;		/* receive descriptor addr */
 	short gap1;
-	unsigned short rx_len;	/* receive len and high addr */
+	unsigned short rx_len;		/* receive len and high addr */
 	short gap2;
-	unsigned short tx_ptr;	/* transmit descriptor addr */
+	unsigned short tx_ptr;		/* transmit descriptor addr */
 	short gap3;
-	unsigned short tx_len;	/* transmit len and high addr */
+	unsigned short tx_len;		/* transmit len and high addr */
 	short gap4;
-	char gap5[16];
+	short gap5[8];
 
 	/* The buffer descriptors */
 	struct lance_rx_desc brx_ring[RX_RING_SIZE];
@@ -247,10 +240,12 @@
 #define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
 
 struct lance_private {
-	char *name;
+	struct net_device *next;
+	int type;
+	int slot;
+	int dma_irq;
 	volatile struct lance_regs *ll;
 	volatile struct lance_init_block *init_block;
-	volatile unsigned long *dma_ptr_reg;
 
 	spinlock_t	lock;
 
@@ -261,8 +256,6 @@
 
 	unsigned short busmaster_regval;
 
-	struct net_device *dev;	/* Backpointer        */
-	struct lance_private *next_module;
 	struct timer_list       multicast_timer;
 
 	/* Pointers to the ring buffers as seen from the CPU */
@@ -292,16 +285,12 @@
 
 int dec_lance_debug = 2;
 
-/*
-   #ifdef MODULE
-   static struct lance_private *root_lance_dev = NULL;
-   #endif
- */
+static struct net_device *root_lance_dev;
 
 static inline void writereg(volatile unsigned short *regptr, short value)
 {
 	*regptr = value;
-	wbflush();
+	iob();
 }
 
 /* Load the CSR registers */
@@ -330,7 +319,7 @@
  * Our specialized copy routines
  *
  */
-void cp_to_buf(void *to, const void *from, __kernel_size_t len)
+void cp_to_buf(const int type, void *to, const void *from, int len)
 {
 	unsigned short *tp, *fp, clen;
 	unsigned char *rtp, *rfp;
@@ -381,10 +370,10 @@
 		}
 	}
 
-	wbflush();
+	iob();
 }
 
-void cp_from_buf(void *to, unsigned char *from, int len)
+void cp_from_buf(const int type, void *to, const void *from, int len)
 {
 	unsigned short *tp, *fp, clen;
 	unsigned char *rtp, *rfp;
@@ -509,7 +498,7 @@
 		if (i < 3 && ZERO)
 			printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]);
 	}
-	wbflush();
+	iob();
 }
 
 static int init_restart_lance(struct lance_private *lp)
@@ -551,22 +540,21 @@
 
 #ifdef TEST_HITS
 	{
-	int i;
+		int i;
 
-	printk("[");
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		if (i == lp->rx_new)
-			printk("%s",
-			       ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "_" : "X");
-		else
-			printk("%s",
-			       ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "." : "1");
-	}
-	printk("]");
+		printk("[");
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			if (i == lp->rx_new)
+				printk("%s", ib->brx_ring[i].rmd1_bits &
+					     LE_R1_OWN ? "_" : "X");
+			else
+				printk("%s", ib->brx_ring[i].rmd1_bits &
+					     LE_R1_OWN ? "." : "1");
+		}
+		printk("]");
 	}
 #endif
 
-
 	for (rd = &ib->brx_ring[lp->rx_new];
 	     !((bits = rd->rmd1_bits) & LE_R1_OWN);
 	     rd = &ib->brx_ring[lp->rx_new]) {
@@ -608,8 +596,8 @@
 			skb_reserve(skb, 2);	/* 16 byte align */
 			skb_put(skb, len);	/* make room */
 
-			cp_from_buf(skb->data,
-				 (char *) lp->rx_buf_ptr_cpu[lp->rx_new],
+			cp_from_buf(lp->type, skb->data,
+				    (char *)lp->rx_buf_ptr_cpu[lp->rx_new],
 				    len);
 
 			skb->protocol = eth_type_trans(skb, dev);
@@ -709,6 +697,14 @@
 	spin_unlock(&lp->lock);
 }
 
+static void lance_dma_merr_int(const int irq, void *dev_id,
+				struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+
+	printk("%s: DMA error\n", dev->name);
+}
+
 static irqreturn_t
 lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -741,19 +737,8 @@
 		lp->stats.rx_errors++;
 
 	if (csr0 & LE_C0_MERR) {
-		volatile unsigned long int_stat = *(unsigned long *) (system_base + IOCTL + SIR);
-
 		printk("%s: Memory error, status %04x\n", dev->name, csr0);
 
-		if (int_stat & LANCE_DMA_MEMRDERR) {
-			printk("%s: DMA error\n", dev->name);
-			int_stat |= LANCE_DMA_MEMRDERR;
-			/*
-			 * re-enable LANCE DMA
-			 */
-			*(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
-			wbflush();
-		}
 		writereg(&ll->rdp, LE_C0_STOP);
 
 		lance_init_ring(dev);
@@ -800,10 +785,30 @@
 	netif_start_queue(dev);
 
 	/* Associate IRQ with lance_interrupt */
-	if (request_irq(dev->irq, &lance_interrupt, 0, lp->name, dev)) {
-		printk("Lance: Can't get irq %d\n", dev->irq);
+	if (request_irq(dev->irq, &lance_interrupt, 0, "lance", dev)) {
+		printk("lance: Can't get IRQ %d\n", dev->irq);
 		return -EAGAIN;
 	}
+	if (lp->dma_irq >= 0) {
+		unsigned long flags;
+
+		if (request_irq(lp->dma_irq, &lance_dma_merr_int, 0,
+				"lance error", dev)) {
+			free_irq(dev->irq, dev);
+			printk("lance: Can't get DMA IRQ %d\n", lp->dma_irq);
+			return -EAGAIN;
+		}
+
+		spin_lock_irqsave(&ioasic_ssr_lock, flags);
+
+		fast_mb();
+		/* Enable I/O ASIC LANCE DMA.  */
+		ioasic_write(IO_REG_SSR,
+			     ioasic_read(IO_REG_SSR) | IO_SSR_LANCE_DMA_EN);
+
+		fast_mb();
+		spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
+	}
 
 	status = init_restart_lance(lp);
 
@@ -827,7 +832,22 @@
 	writereg(&ll->rap, LE_CSR0);
 	writereg(&ll->rdp, LE_C0_STOP);
 
-	free_irq(dev->irq, (void *) dev);
+	if (lp->dma_irq >= 0) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&ioasic_ssr_lock, flags);
+
+		fast_mb();
+		/* Disable I/O ASIC LANCE DMA.  */
+		ioasic_write(IO_REG_SSR,
+			     ioasic_read(IO_REG_SSR) & ~IO_SSR_LANCE_DMA_EN);
+
+		fast_iob();
+		spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
+
+		free_irq(lp->dma_irq, dev);
+	}
+	free_irq(dev->irq, dev);
 	/*
 	   MOD_DEC_USE_COUNT;
 	 */
@@ -886,7 +906,8 @@
 	ib->btx_ring[entry].length = (-len);
 	ib->btx_ring[entry].misc = 0;
 
-	cp_to_buf((char *) lp->tx_buf_ptr_cpu[entry], skb->data, skblen);
+	cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data,
+		  skblen);
 
 	/* Clear the slack of the packet, do I need this? */
 	/* For a firewall it's a good idea - AC */
@@ -926,7 +947,7 @@
 	volatile u16 *mcast_table = (u16 *) & ib->filter;
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
-	int i, j, bit, byte;
+	int i;
 	u32 crc;
 
 	/* set all multicast bits */
@@ -952,7 +973,7 @@
 		if (!(*addrs & 1))
 			continue;
 
-		crc = ether_crc_le(6, addrs);
+		crc = ether_crc_le(ETH_ALEN, addrs);
 		crc = crc >> 26;
 		mcast_table[2 * (crc >> 4)] |= 1 << (crc & 0xf);
 	}
@@ -1001,7 +1022,7 @@
 	lance_set_multicast(dev);
 }
 
-static int __init dec_lance_init(struct net_device *dev, const int type)
+static int __init dec_lance_init(const int type, const int slot)
 {
 	static unsigned version_printed;
 	struct net_device *dev;
@@ -1013,25 +1034,29 @@
 
 #ifndef CONFIG_TC
 	system_base = KN01_LANCE_BASE;
-#else
-	int slot;
 #endif
 
 	if (dec_lance_debug && version_printed++ == 0)
 		printk(version);
 
-	dev = init_etherdev(0, sizeof(struct lance_private));
+	dev = init_etherdev(NULL, sizeof(struct lance_private));
 	if (!dev)
 		return -ENOMEM;
+	SET_MODULE_OWNER(dev);
 
-	/* init_etherdev ensures the data structures used by the LANCE are aligned. */
+	/*
+	 * init_etherdev ensures the data structures used by the LANCE
+	 * are aligned.
+	 */
 	lp = (struct lance_private *) dev->priv;
 	spin_lock_init(&lp->lock);
 
+	lp->type = type;
+	lp->slot = slot;
 	switch (type) {
 #ifdef CONFIG_TC
 	case ASIC_LANCE:
-		dev->base_addr = system_base + LANCE;
+		dev->base_addr = system_base + IOASIC_LANCE;
 
 		/* buffer space for the on-board LANCE shared memory */
 		/*
@@ -1039,78 +1064,101 @@
 		 */
 		dev->mem_start = KSEG1ADDR(0x00020000);
 		dev->mem_end = dev->mem_start + 0x00020000;
-		dev->irq = ETHER;
-		esar_base = system_base + ESAR;
-	
+		dev->irq = dec_interrupt[DEC_IRQ_LANCE];
+		esar_base = system_base + IOASIC_ESAR;
+
 		/* Workaround crash with booting KN04 2.1k from Disk */
-		memset(dev->mem_start, 0, dev->mem_end - dev->mem_start);
+		memset((void *)dev->mem_start, 0,
+		       dev->mem_end - dev->mem_start);
 
 		/*
 		 * setup the pointer arrays, this sucks [tm] :-(
 		 */
 		for (i = 0; i < RX_RING_SIZE; i++) {
-			lp->rx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU
-						 + 2 * i * RX_BUFF_SIZE);
-			lp->rx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC
-						     + i * RX_BUFF_SIZE);
+			lp->rx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + BUF_OFFSET_CPU +
+					 2 * i * RX_BUFF_SIZE);
+			lp->rx_buf_ptr_lnc[i] =
+				(char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
 		}
 		for (i = 0; i < TX_RING_SIZE; i++) {
-			lp->tx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU
-					+ 2 * RX_RING_SIZE * RX_BUFF_SIZE
-						 + 2 * i * TX_BUFF_SIZE);
-			lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC
-					    + RX_RING_SIZE * RX_BUFF_SIZE
-						     + i * TX_BUFF_SIZE);
+			lp->tx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + BUF_OFFSET_CPU +
+					 2 * RX_RING_SIZE * RX_BUFF_SIZE +
+					 2 * i * TX_BUFF_SIZE);
+			lp->tx_buf_ptr_lnc[i] =
+				(char *)(BUF_OFFSET_LNC +
+					 RX_RING_SIZE * RX_BUFF_SIZE +
+					 i * TX_BUFF_SIZE);
 		}
 
-		/*
-		 * setup and enable IOASIC LANCE DMA
-		 */
-		lp->dma_ptr_reg = (unsigned long *) (system_base + IOCTL + LANCE_DMA_P);
-		*(lp->dma_ptr_reg) = PHYSADDR(dev->mem_start) << 3;
-		*(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
-		wbflush();
+		/* Setup I/O ASIC LANCE DMA.  */
+		lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
+		ioasic_write(IO_REG_LANCE_DMA_P,
+			     PHYSADDR(dev->mem_start) << 3);
 
 		break;
+
 	case PMAD_LANCE:
-		slot = search_tc_card("PMAD-AA");
 		claim_tc_card(slot);
 
 		dev->mem_start = get_tc_base_addr(slot);
 		dev->base_addr = dev->mem_start + 0x100000;
 		dev->irq = get_tc_irq_nr(slot);
 		esar_base = dev->mem_start + 0x1c0002;
+		lp->dma_irq = -1;
+
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			lp->rx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + BUF_OFFSET_CPU +
+					 i * RX_BUFF_SIZE);
+			lp->rx_buf_ptr_lnc[i] =
+				(char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
+		}
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			lp->tx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + BUF_OFFSET_CPU +
+					 RX_RING_SIZE * RX_BUFF_SIZE +
+					 i * TX_BUFF_SIZE);
+			lp->tx_buf_ptr_lnc[i] =
+				(char *)(BUF_OFFSET_LNC +
+					 RX_RING_SIZE * RX_BUFF_SIZE +
+					 i * TX_BUFF_SIZE);
+		}
+
 		break;
 #endif
+
 	case PMAX_LANCE:
-		dev->irq = ETHER;
+		dev->irq = dec_interrupt[DEC_IRQ_LANCE];
 		dev->base_addr = KN01_LANCE_BASE;
 		dev->mem_start = KN01_LANCE_BASE + 0x01000000;
 		esar_base = KN01_RTC_BASE + 1;
+		lp->dma_irq = -1;
+
 		/*
 		 * setup the pointer arrays, this sucks [tm] :-(
 		 */
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			lp->rx_buf_ptr_cpu[i] =
-			    (char *) (dev->mem_start + BUF_OFFSET_CPU
-				      + 2 * i * RX_BUFF_SIZE);
-
+				(char *)(dev->mem_start + BUF_OFFSET_CPU +
+					 2 * i * RX_BUFF_SIZE);
 			lp->rx_buf_ptr_lnc[i] =
-			    (char *) (BUF_OFFSET_LNC
-				      + i * RX_BUFF_SIZE);
-
+				(char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
 		}
 		for (i = 0; i < TX_RING_SIZE; i++) {
 			lp->tx_buf_ptr_cpu[i] =
-			    (char *) (dev->mem_start + BUF_OFFSET_CPU
-				      + 2 * RX_RING_SIZE * RX_BUFF_SIZE
-				      + 2 * i * TX_BUFF_SIZE);
-			lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC
-					    + RX_RING_SIZE * RX_BUFF_SIZE
-						     + i * TX_BUFF_SIZE);
-
+				(char *)(dev->mem_start + BUF_OFFSET_CPU +
+					 2 * RX_RING_SIZE * RX_BUFF_SIZE +
+					 2 * i * TX_BUFF_SIZE);
+			lp->tx_buf_ptr_lnc[i] =
+				(char *)(BUF_OFFSET_LNC +
+					 RX_RING_SIZE * RX_BUFF_SIZE +
+					 i * TX_BUFF_SIZE);
 		}
+
 		break;
+
 	default:
 		printk("declance_init called with unknown type\n");
 		ret = -ENODEV;
@@ -1140,6 +1188,9 @@
 		}
 	}
 
+	lp->next = root_lance_dev;
+	root_lance_dev = dev;
+
 	/* Copy the ethernet address to the device structure, later to the
 	 * lance initialization block so the lance gets it every time it's
 	 * (re)initialized.
@@ -1162,7 +1213,6 @@
 
 	printk(" irq = %d\n", dev->irq);
 
-	lp->dev = dev;
 	dev->open = &lance_open;
 	dev->stop = &lance_close;
 	dev->hard_start_xmit = &lance_start_xmit;
@@ -1174,8 +1224,6 @@
 	/* lp->ll is the location of the registers for lance card */
 	lp->ll = ll;
 
-	lp->name = lancestr;
-
 	/* busmaster_regval (CSR3) should be zero according to the PMAD-AA
 	 * specification.
 	 */
@@ -1183,8 +1231,6 @@
 
 	dev->dma = 0;
 
-	ether_setup(dev);
-
 	/* We cannot sleep if the chip is busy during a
 	 * multicast list update event, because such events
 	 * can occur from interrupts (ex. IPv6).  So we
@@ -1194,11 +1240,6 @@
 	lp->multicast_timer.data = (unsigned long) dev;
 	lp->multicast_timer.function = &lance_set_multicast_retry;
 
-#ifdef MODULE
-	dev->ifindex = dev_new_index();
-	lp->next_module = root_lance_dev;
-	root_lance_dev = lp;
-#endif
 	return 0;
 
 err_out:
@@ -1211,61 +1252,51 @@
 /* Find all the lance cards on the system and initialize them */
 static int __init dec_lance_probe(void)
 {
-	struct net_device *dev = NULL;
-	static int called;
-
-#ifdef MODULE
-	root_lance_dev = NULL;
-#endif
-
+	int count = 0;
 
+	/* Scan slots for PMAD-AA cards first. */
 #ifdef CONFIG_TC
-	int slot = -1;
-
 	if (TURBOCHANNEL) {
-		if (IOASIC && !called) {
-			called = 1;
-			type = ASIC_LANCE;
-		} else {
-			if ((slot = search_tc_card("PMAD-AA")) >= 0) {
-				type = PMAD_LANCE;
-			} else {
-				return -ENODEV;
-			}
-		}
-	} else {
-		if (!called) {
-			called = 1;
-			type = PMAX_LANCE;
-		} else {
-			return -ENODEV;
+		int slot;
+
+		while ((slot = search_tc_card("PMAD-AA")) >= 0) {
+			if (dec_lance_init(PMAD_LANCE, slot) < 0)
+				break;
+			count++;
 		}
 	}
-#else
-	if (!called && !TURBOCHANNEL) {
-		called = 1;
-		type = PMAX_LANCE;
-	} else {
-		return -ENODEV;
-	}
 #endif
 
-	return dec_lance_init(dev, type);
+	/* Then handle onboard devices. */
+	if (dec_interrupt[DEC_IRQ_LANCE] >= 0) {
+		if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) {
+#ifdef CONFIG_TC
+			if (dec_lance_init(ASIC_LANCE, -1) >= 0)
+				count++;
+#endif
+		} else if (!TURBOCHANNEL) {
+			if (dec_lance_init(PMAX_LANCE, -1) >= 0)
+				count++;
+		}
+	}
+
+	return (count > 0) ? 0 : -ENODEV;
 }
 
 static void __exit dec_lance_cleanup(void)
 {
-#ifdef MODULE
-   struct lance_private *lp;
-
-   while (root_lance_dev) {
-   lp = root_lance_dev->next_module;
+	while (root_lance_dev) {
+		struct net_device *dev = root_lance_dev;
+		struct lance_private *lp = (struct lance_private *)dev->priv;
 
-   unregister_netdev(root_lance_dev->dev);
-   kfree(root_lance_dev->dev);
-   root_lance_dev = lp;
-   }
-#endif /* MODULE */
+#ifdef CONFIG_TC
+		if (lp->slot >= 0)
+			release_tc_card(lp->slot);
+#endif
+		root_lance_dev = lp->next;
+		unregister_netdev(dev);
+		kfree(dev);
+	}
 }
 
 module_init(dec_lance_probe);
diff -urN linux-2.5.73-bk3/drivers/net/e100/e100_main.c linux-2.5.73-bk4/drivers/net/e100/e100_main.c
--- linux-2.5.73-bk3/drivers/net/e100/e100_main.c	2003-06-22 11:32:44.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/e100/e100_main.c	2003-06-26 05:00:28.000000000 -0700
@@ -3424,10 +3424,6 @@
 	int ethtool_new_speed_duplex;
 	struct ethtool_cmd ecmd;
 
-	if (!capable(CAP_NET_ADMIN)) {
-		return -EPERM;
-	}
-
 	bdp = dev->priv;
 	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) {
 		return -EFAULT;
@@ -3545,8 +3541,6 @@
 	void *addr = ifr->ifr_data;
 	u16 mdi_reg;
 
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
 	bdp = dev->priv;
 
 	if(copy_from_user(&regs, addr, sizeof(regs)))
@@ -3574,9 +3568,6 @@
 {
 	struct e100_private *bdp;
 
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
 	bdp = dev->priv;
 
 	if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) &&
@@ -3632,9 +3623,6 @@
 	void *ptr;
 	u8 *eeprom_data_bytes = (u8 *)eeprom_data;
 
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
 	bdp = dev->priv;
 
 	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
@@ -3912,9 +3900,6 @@
 	struct ethtool_wolinfo wolinfo;
 	int res = 0;
 
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
 	bdp = dev->priv;
 
 	if (copy_from_user(&wolinfo, ifr->ifr_data, sizeof (wolinfo))) {
diff -urN linux-2.5.73-bk3/drivers/net/e1000/e1000_ethtool.c linux-2.5.73-bk4/drivers/net/e1000/e1000_ethtool.c
--- linux-2.5.73-bk3/drivers/net/e1000/e1000_ethtool.c	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/e1000/e1000_ethtool.c	2003-06-26 05:00:28.000000000 -0700
@@ -1289,8 +1289,6 @@
 	}
 	case ETHTOOL_SSET: {
 		struct ethtool_cmd ecmd;
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
 		if(copy_from_user(&ecmd, addr, sizeof(ecmd)))
 			return -EFAULT;
 		return e1000_ethtool_sset(adapter, &ecmd);
@@ -1363,8 +1361,6 @@
 		return 0;
 	}
 	case ETHTOOL_NWAY_RST: {
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
 		if(netif_running(netdev)) {
 			e1000_down(adapter);
 			e1000_up(adapter);
@@ -1393,8 +1389,6 @@
 	}
 	case ETHTOOL_SWOL: {
 		struct ethtool_wolinfo wol;
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
 		if(copy_from_user(&wol, addr, sizeof(wol)) != 0)
 			return -EFAULT;
 		return e1000_ethtool_swol(adapter, &wol);
@@ -1436,9 +1430,6 @@
 	case ETHTOOL_SEEPROM: {
 		struct ethtool_eeprom eeprom;
 
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-
 		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
 			return -EFAULT;
 
@@ -1470,9 +1461,6 @@
 		} test = { {ETHTOOL_TEST} };
 		int err;
 
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-
 		if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test)))
 			return -EFAULT;
 
diff -urN linux-2.5.73-bk3/drivers/net/eepro100.c linux-2.5.73-bk4/drivers/net/eepro100.c
--- linux-2.5.73-bk3/drivers/net/eepro100.c	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/eepro100.c	2003-06-26 05:00:28.000000000 -0700
@@ -116,6 +116,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -670,7 +671,7 @@
 	if (tx_ring_space == NULL)
 		return -1;
 
-	dev = init_etherdev(NULL, sizeof(struct speedo_private));
+	dev = alloc_etherdev(sizeof(struct speedo_private));
 	if (dev == NULL) {
 		printk(KERN_ERR "eepro100: Could not allocate ethernet device.\n");
 		pci_free_consistent(pdev, size, tx_ring_space, tx_ring_dma);
@@ -687,6 +688,10 @@
 	else
 		option = 0;
 
+	rtnl_lock();
+	if (dev_alloc_name(dev, dev->name) < 0) 
+		goto err_free_unlock;
+
 	/* Read the station address EEPROM before doing the reset.
 	   Nominally his should even be done before accepting the device, but
 	   then we wouldn't have a device name with which to report the error.
@@ -881,7 +886,16 @@
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &speedo_ioctl;
 
+	if (register_netdevice(dev))
+		goto err_free_unlock;
+	rtnl_unlock();
+
 	return 0;
+
+ err_free_unlock:
+	rtnl_unlock();
+	kfree(dev);
+	return -1;
 }
 
 static void do_slow_command(struct net_device *dev, int cmd)
diff -urN linux-2.5.73-bk3/drivers/net/gt96100eth.c linux-2.5.73-bk4/drivers/net/gt96100eth.c
--- linux-2.5.73-bk3/drivers/net/gt96100eth.c	2003-06-22 11:33:07.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/gt96100eth.c	2003-06-26 05:00:28.000000000 -0700
@@ -3,8 +3,6 @@
  * Author: MontaVista Software, Inc.
  *         	stevel@mvista.com or source@mvista.com
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -18,8 +16,6 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * Ethernet driver for the MIPS GT96100 Advanced Communication Controller.
  * 
  *  Revision history
@@ -32,18 +28,7 @@
  *                gt96100_cleanup_module(), and other general code cleanups
  *                <stevel@mvista.com>.
  */
-
-#ifndef __OPTIMIZE__
-#error You must compile this file with the correct options!
-#error See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
-#ifndef __mips__
-#error This driver only works with MIPS architectures!
-#endif
-
-
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff -urN linux-2.5.73-bk3/drivers/net/ioc3-eth.c linux-2.5.73-bk4/drivers/net/ioc3-eth.c
--- linux-2.5.73-bk3/drivers/net/ioc3-eth.c	2003-06-22 11:32:32.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/ioc3-eth.c	2003-06-26 05:00:28.000000000 -0700
@@ -5,7 +5,7 @@
  *
  * Driver for SGI's IOC3 based Ethernet cards as found in the PCI card.
  *
- * Copyright (C) 1999, 2000, 2001 Ralf Baechle
+ * Copyright (C) 1999, 2000, 2001, 2003 Ralf Baechle
  * Copyright (C) 1995, 1999, 2000, 2001 by Silicon Graphics, Inc.
  *
  * References:
@@ -36,7 +36,7 @@
 #include <linux/pci.h>
 #include <linux/crc32.h>
 
-#ifdef CONFIG_SERIAL
+#ifdef CONFIG_SERIAL_8250
 #include <linux/serial.h>
 #include <asm/serial.h>
 #define IOC3_BAUD (22000000 / (3*16))
@@ -377,82 +377,6 @@
 		ip->dev->dev_addr[i - 2] = nic[i];
 }
 
-#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
-/*
- * Get the ether-address on SN1 nodes
- */
-static void ioc3_get_eaddr_sn(struct ioc3_private *ip)
-{
-	int ibrick_mac_addr_get(nasid_t, char *);
-	struct ioc3 *ioc3 = ip->regs;
-	nasid_t nasid_of_ioc3;
-	char io7eaddr[20];
-	long mac;
-	int err_val;
-
-	/*
-	 * err_val = ibrick_mac_addr_get(get_nasid(), io7eaddr );
-	 * 
-	 * BAD!!  The above call uses get_nasid() and assumes that
-	 * the ioc3 pointed to by struct ioc3 is hooked up to the
-	 * cbrick that we're running on.  The proper way to make this call
-	 * is to figure out which nasid the ioc3 is connected to
-	 * and use that to call ibrick_mac_addr_get.  Below is
-	 * a hack to do just that.
-	 */
-
-	/*
-	 * Get the nasid of the ioc3 from the ioc3's base addr.
-	 * FIXME: the 8 at the end assumes we're in memory mode, 
-	 * not node mode (for that, we'd change it to a 9).
-	 * Is there a call to extract this info from a physical
-	 * addr somewhere in an sn header file already?  If so,
-	 * we should probably use that, or restructure this routine
-	 * to use pci_dev and generic numa nodeid getting stuff.
-	 */
-	nasid_of_ioc3 = (((unsigned long)ioc3 >> 33) & ~(-1 << 8));
-	err_val = ibrick_mac_addr_get(nasid_of_ioc3, io7eaddr );
-
-
-	if (err_val) {
-		/* Couldn't read the eeprom; try OSLoadOptions. */
-		printk("WARNING: ibrick_mac_addr_get failed: %d\n", err_val);
-
-		/* this is where we hardwire the mac address
- 		 * 1st ibrick had 08:00:69:11:34:75
- 		 * 2nd ibrick had 08:00:69:11:35:35
- 		 *
- 		 * Eagan Machines:
- 		 *      mankato1 08:00:69:11:BE:95
- 		 *      warroad  08:00:69:11:bd:60
- 		 *      duron    08:00:69:11:34:60
- 		 *
- 		 * an easy way to get the mac address is to hook
- 		 * up an ip35, then from L1 do 'cti serial'
- 		 * and then look for MAC line XXX THIS DOESN"T QUITE WORK!!
- 		 */
-		printk("ioc3_get_eaddr: setting ethernet address to:\n -----> ");
-		ip->dev->dev_addr[0] = 0x8;
-		ip->dev->dev_addr[1] = 0x0;
-		ip->dev->dev_addr[2] = 0x69;
-		ip->dev->dev_addr[3] = 0x11;
-		ip->dev->dev_addr[4] = 0x34;
-		ip->dev->dev_addr[5] = 0x60;
-	}
-	else {
-		long simple_strtol(const char *,char **,unsigned int);
-
-		mac = simple_strtol(io7eaddr, (char **)0, 16);
-		ip->dev->dev_addr[0] = (mac >> 40) & 0xff;
-		ip->dev->dev_addr[1] = (mac >> 32) & 0xff;
-		ip->dev->dev_addr[2] = (mac >> 24) & 0xff;
-		ip->dev->dev_addr[3] = (mac >> 16) & 0xff;
-		ip->dev->dev_addr[4] = (mac >> 8) & 0xff;
-		ip->dev->dev_addr[5] = mac & 0xff;
-	}
-}
-#endif
-
 /*
  * Ok, this is hosed by design.  It's necessary to know what machine the
  * NIC is in in order to know how to read the NIC address.  We also have
@@ -460,30 +384,15 @@
  */
 static void ioc3_get_eaddr(struct ioc3_private *ip)
 {
-	void (*do_get_eaddr)(struct ioc3_private *ip) = NULL;
 	int i;
 
-	/*
-	 * We should also use this code for PCI cards, no matter what host
-	 * machine but how to know that we're a PCI card?
-	 */
-#ifdef CONFIG_SGI_IP27
-	do_get_eaddr = ioc3_get_eaddr_nic;
-#endif
-#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
-	do_get_eaddr = ioc3_get_eaddr_sn;
-#endif
 
-	if (!do_get_eaddr) {
-		printk(KERN_ERR "Don't know how to read MAC address of this "
-		       "IOC3 NIC\n");
-		return;
-	}
+	ioc3_get_eaddr_nic(ip);
 
 	printk("Ethernet address is ");
 	for (i = 0; i < 6; i++) {
 		printk("%02x", ip->dev->dev_addr[i]);
-		if (i < 7)
+		if (i < 5)
 			printk(":");
 	}
 	printk(".\n");
@@ -588,7 +497,7 @@
 			ip->stats.rx_frame_errors++;
 next:
 		ip->rx_skbs[n_entry] = new_skb;
-		rxr[n_entry] = cpu_to_be32((0xa5UL << 56) |
+		rxr[n_entry] = cpu_to_be64((0xa5UL << 56) |
 		                         ((unsigned long) rxb & TO_PHYS_MASK));
 		rxb->w0 = 0;				/* Clear valid flag */
 		n_entry = (n_entry + 1) & 511;		/* Update erpir */
@@ -1550,7 +1459,7 @@
 	}
 	ip->regs = ioc3;
 
-#ifdef CONFIG_SERIAL
+#ifdef CONFIG_SERIAL_8250
 	ioc3_serial_probe(pdev, ioc3);
 #endif
 
@@ -1613,6 +1522,7 @@
 	struct ioc3_private *ip = dev->priv;
 	struct ioc3 *ioc3 = ip->regs;
 
+	unregister_netdev(dev);
 	iounmap(ioc3);
 	pci_release_regions(pdev);
 	kfree(dev);
@@ -1844,9 +1754,6 @@
 				return -EFAULT;
 			return 0;
 		} else if (ecmd.cmd == ETHTOOL_SSET) {
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-
 			/* Verify the settings we care about. */
 			if (ecmd.autoneg != AUTONEG_ENABLE &&
 			    ecmd.autoneg != AUTONEG_DISABLE)
diff -urN linux-2.5.73-bk3/drivers/net/irda/Kconfig linux-2.5.73-bk4/drivers/net/irda/Kconfig
--- linux-2.5.73-bk3/drivers/net/irda/Kconfig	2003-06-22 11:33:04.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/irda/Kconfig	2003-06-26 05:00:28.000000000 -0700
@@ -289,6 +289,10 @@
 	  <file:Documentation/modules.txt>.
 	  The module will be called donauboe.
 
+config AU1000_FIR
+	tristate "Alchemy Au1000 SIR/FIR"
+	depends on MIPS_AU1000 && IRDA
+
 config SMC_IRCC_OLD
 	tristate "SMC IrCC (old driver) (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && IRDA
diff -urN linux-2.5.73-bk3/drivers/net/irda/Makefile linux-2.5.73-bk4/drivers/net/irda/Makefile
--- linux-2.5.73-bk3/drivers/net/irda/Makefile	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/irda/Makefile	2003-06-26 05:00:28.000000000 -0700
@@ -28,6 +28,7 @@
 obj-$(CONFIG_OLD_BELKIN_DONGLE)	+= old_belkin.o
 obj-$(CONFIG_EP7211_IR)		+= ep7211_ir.o
 obj-$(CONFIG_MCP2120_DONGLE)	+= mcp2120.o
+obj-$(CONFIG_AU1000_FIR)	+= au1k_ir.o
 obj-$(CONFIG_ACT200L_DONGLE)	+= act200l.o
 obj-$(CONFIG_MA600_DONGLE)	+= ma600.o
 # New SIR drivers
diff -urN linux-2.5.73-bk3/drivers/net/irda/au1k_ir.c linux-2.5.73-bk4/drivers/net/irda/au1k_ir.c
--- linux-2.5.73-bk3/drivers/net/irda/au1k_ir.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk4/drivers/net/irda/au1k_ir.c	2003-06-26 05:00:28.000000000 -0700
@@ -0,0 +1,868 @@
+/*
+ *
+ * Alchemy Semi Au1000 IrDA driver
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope 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.
+ *
+ * ########################################################################
+ *
+ * 
+ */
+
+#ifndef __mips__
+#error This driver only works with MIPS architectures!
+#endif
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/rtnetlink.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/au1000.h>
+#include <asm/pb1000.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+#include "net/irda/au1000_ircc.h"
+
+static int au1k_irda_net_init(struct net_device *);
+static int au1k_irda_start(struct net_device *);
+static int au1k_irda_stop(struct net_device *dev);
+static int au1k_irda_hard_xmit(struct sk_buff *, struct net_device *);
+static int au1k_irda_rx(struct net_device *);
+static void au1k_irda_interrupt(int, void *, struct pt_regs *);
+static void au1k_tx_timeout(struct net_device *);
+static struct net_device_stats *au1k_irda_stats(struct net_device *);
+static int au1k_irda_ioctl(struct net_device *, struct ifreq *, int);
+static int au1k_irda_set_speed(struct net_device *dev, int speed);
+
+static void *dma_alloc(size_t, dma_addr_t *);
+static void dma_free(void *, size_t);
+
+static int qos_mtt_bits = 0x07;  /* 1 ms or more */
+static struct net_device *ir_devs[NUM_IR_IFF];
+static char version[] __devinitdata =
+    "au1k_ircc:1.0 ppopov@mvista.com\n";
+
+#define RUN_AT(x) (jiffies + (x))
+
+static spinlock_t ir_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * IrDA peripheral bug. You have to read the register
+ * twice to get the right value.
+ */
+u32 read_ir_reg(u32 addr) 
+{ 
+	readl(addr);
+	return readl(addr);
+}
+
+
+/*
+ * Buffer allocation/deallocation routines. The buffer descriptor returned
+ * has the virtual and dma address of a buffer suitable for 
+ * both, receive and transmit operations.
+ */
+static db_dest_t *GetFreeDB(struct au1k_private *aup)
+{
+	db_dest_t *pDB;
+	pDB = aup->pDBfree;
+
+	if (pDB) {
+		aup->pDBfree = pDB->pnext;
+	}
+	return pDB;
+}
+
+static void ReleaseDB(struct au1k_private *aup, db_dest_t *pDB)
+{
+	db_dest_t *pDBfree = aup->pDBfree;
+	if (pDBfree)
+		pDBfree->pnext = pDB;
+	aup->pDBfree = pDB;
+}
+
+
+/*
+  DMA memory allocation, derived from pci_alloc_consistent.
+  However, the Au1000 data cache is coherent (when programmed
+  so), therefore we return KSEG0 address, not KSEG1.
+*/
+static void *dma_alloc(size_t size, dma_addr_t * dma_handle)
+{
+	void *ret;
+	int gfp = GFP_ATOMIC | GFP_DMA;
+
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_bus(ret);
+		ret = KSEG0ADDR(ret);
+	}
+	return ret;
+}
+
+
+static void dma_free(void *vaddr, size_t size)
+{
+	vaddr = KSEG0ADDR(vaddr);
+	free_pages((unsigned long) vaddr, get_order(size));
+}
+
+
+static void 
+setup_hw_rings(struct au1k_private *aup, u32 rx_base, u32 tx_base)
+{
+	int i;
+	for (i=0; i<NUM_IR_DESC; i++) {
+		aup->rx_ring[i] = (volatile ring_dest_t *) 
+			(rx_base + sizeof(ring_dest_t)*i);
+	}
+	for (i=0; i<NUM_IR_DESC; i++) {
+		aup->tx_ring[i] = (volatile ring_dest_t *) 
+			(tx_base + sizeof(ring_dest_t)*i);
+	}
+}
+
+
+/* 
+ * Device has already been stopped at this point.
+ */
+static void au1k_irda_net_uninit(struct net_device *dev)
+{
+	dev->hard_start_xmit = NULL;
+	dev->open            = NULL;
+	dev->stop            = NULL;
+	dev->do_ioctl        = NULL;
+	dev->get_stats       = NULL;
+	dev->priv            = NULL;
+}
+
+
+static int au1k_irda_init(void)
+{
+	static unsigned version_printed = 0;
+	struct net_device *dev;
+	int err;
+
+	if (version_printed++ == 0) printk(version);
+
+	rtnl_lock();
+	dev = dev_alloc("irda%d", &err);
+	if (dev) {
+		dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */
+		dev->init = au1k_irda_net_init;
+		dev->uninit = au1k_irda_net_uninit;
+		err = register_netdevice(dev);
+
+		if (err)
+			kfree(dev);
+		else
+			ir_devs[0] = dev;
+		printk(KERN_INFO "IrDA: Registered device %s\n", dev->name);
+	}
+	rtnl_unlock();
+	return err;
+}
+
+static int au1k_irda_init_iobuf(iobuff_t *io, int size)
+{
+	io->head = kmalloc(size, GFP_KERNEL);
+	if (io->head != NULL) {
+		io->truesize = size;
+		io->in_frame = FALSE;
+		io->state    = OUTSIDE_FRAME;
+		io->data     = io->head;
+	}
+	return io->head ? 0 : -ENOMEM;
+}
+
+static int au1k_irda_net_init(struct net_device *dev)
+{
+	struct au1k_private *aup = NULL;
+	int i, retval = 0, err;
+	db_dest_t *pDB, *pDBfree;
+	unsigned long temp;
+
+	dev->priv = kmalloc(sizeof(struct au1k_private), GFP_KERNEL);
+	if (dev->priv == NULL) {
+		retval = -ENOMEM;
+		goto out;
+	}
+	memset(dev->priv, 0, sizeof(struct au1k_private));
+	aup = dev->priv;
+
+	err = au1k_irda_init_iobuf(&aup->rx_buff, 14384);
+	if (err)
+		goto out;
+
+	dev->open = au1k_irda_start;
+	dev->hard_start_xmit = au1k_irda_hard_xmit;
+	dev->stop = au1k_irda_stop;
+	dev->get_stats = au1k_irda_stats;
+	dev->do_ioctl = au1k_irda_ioctl;
+	dev->tx_timeout = au1k_tx_timeout;
+
+	irda_device_setup(dev);
+	irda_init_max_qos_capabilies(&aup->qos);
+
+	/* The only value we must override it the baudrate */
+	aup->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200|IR_576000 |(IR_4000000 << 8);
+	
+	aup->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&aup->qos);
+
+
+	/* Tx ring follows rx ring + 512 bytes */
+	/* we need a 1k aligned buffer */
+	aup->rx_ring[0] = (ring_dest_t *)
+		dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)), &temp);
+
+	/* allocate the data buffers */
+	aup->db[0].vaddr = 
+		(void *)dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC, &temp);
+	if (!aup->db[0].vaddr || !aup->rx_ring[0]) {
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512);
+
+	pDBfree = NULL;
+	pDB = aup->db;
+	for (i=0; i<(2*NUM_IR_DESC); i++) {
+		pDB->pnext = pDBfree;
+		pDBfree = pDB;
+		pDB->vaddr = 
+			(u32 *)((unsigned)aup->db[0].vaddr + MAX_BUF_SIZE*i);
+		pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
+		pDB++;
+	}
+	aup->pDBfree = pDBfree;
+
+	/* attach a data buffer to each descriptor */
+	for (i=0; i<NUM_IR_DESC; i++) {
+		pDB = GetFreeDB(aup);
+		if (!pDB) goto out;
+		aup->rx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
+		aup->rx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
+		aup->rx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
+		aup->rx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff);
+		aup->rx_db_inuse[i] = pDB;
+	}
+	for (i=0; i<NUM_IR_DESC; i++) {
+		pDB = GetFreeDB(aup);
+		if (!pDB) goto out;
+		aup->tx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
+		aup->tx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
+		aup->tx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
+		aup->tx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff);
+		aup->tx_ring[i]->count_0 = 0;
+		aup->tx_ring[i]->count_1 = 0;
+		aup->tx_ring[i]->flags = 0;
+		aup->tx_db_inuse[i] = pDB;
+	}
+	return 0;
+
+out:
+	if (aup->db[0].vaddr) 
+		dma_free((void *)aup->db[0].vaddr, 
+				MAX_BUF_SIZE * 2*NUM_IR_DESC);
+	if (aup->rx_ring[0])
+		kfree((void *)aup->rx_ring[0]);
+	if (aup->rx_buff.head)
+		kfree(aup->rx_buff.head);
+	if (dev->priv != NULL)
+		kfree(dev->priv);
+	unregister_netdevice(dev);
+	printk(KERN_ERR "%s: au1k_init_module failed.  Returns %d\n",
+	       dev->name, retval);
+	return retval;
+}
+
+
+static int au1k_init(struct net_device *dev)
+{
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+	int i;
+	u32 control;
+	u32 ring_address;
+
+	/* bring the device out of reset */
+	control = 0xe; /* coherent, clock enable, one half system clock */
+			  
+#ifndef CONFIG_CPU_LITTLE_ENDIAN
+	control |= 1;
+#endif
+	aup->tx_head = 0;
+	aup->tx_tail = 0;
+	aup->rx_head = 0;
+
+	for (i=0; i<NUM_IR_DESC; i++) {
+		aup->rx_ring[i]->flags = AU_OWN;
+	}
+
+	writel(control, IR_INTERFACE_CONFIG);
+	au_sync_delay(10);
+
+	writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE); /* disable PHY */
+	au_sync_delay(1);
+
+	writel(MAX_BUF_SIZE, IR_MAX_PKT_LEN);
+
+	ring_address = (u32)virt_to_phys((void *)aup->rx_ring[0]);
+	writel(ring_address >> 26, IR_RING_BASE_ADDR_H);
+	writel((ring_address >> 10) & 0xffff, IR_RING_BASE_ADDR_L);
+
+	writel(RING_SIZE_64<<8 | RING_SIZE_64<<12, IR_RING_SIZE);
+
+	writel(1<<2 | IR_ONE_PIN, IR_CONFIG_2); /* 48MHz */
+	writel(0, IR_RING_ADDR_CMPR);
+
+	au1k_irda_set_speed(dev, 9600);
+	return 0;
+}
+
+static int au1k_irda_start(struct net_device *dev)
+{
+	int retval;
+	char hwname[32];
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+
+	MOD_INC_USE_COUNT;
+
+	if ((retval = au1k_init(dev))) {
+		printk(KERN_ERR "%s: error in au1k_init\n", dev->name);
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+
+	if ((retval = request_irq(AU1000_IRDA_TX_INT, &au1k_irda_interrupt, 
+					0, dev->name, dev))) {
+		printk(KERN_ERR "%s: unable to get IRQ %d\n", 
+				dev->name, dev->irq);
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+	if ((retval = request_irq(AU1000_IRDA_RX_INT, &au1k_irda_interrupt, 
+					0, dev->name, dev))) {
+		free_irq(AU1000_IRDA_TX_INT, dev);
+		printk(KERN_ERR "%s: unable to get IRQ %d\n", 
+				dev->name, dev->irq);
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+
+	/* Give self a hardware name */
+	sprintf(hwname, "Au1000 SIR/FIR");
+	aup->irlap = irlap_open(dev, &aup->qos, hwname);
+	netif_start_queue(dev);
+
+	writel(read_ir_reg(IR_CONFIG_2) | 1<<8, IR_CONFIG_2); /* int enable */
+
+	aup->timer.expires = RUN_AT((3*HZ)); 
+	aup->timer.data = (unsigned long)dev;
+	return 0;
+}
+
+static int au1k_irda_stop(struct net_device *dev)
+{
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+
+	/* disable interrupts */
+	writel(read_ir_reg(IR_CONFIG_2) & ~(1<<8), IR_CONFIG_2);
+	writel(0, IR_CONFIG_1); 
+	writel(0, IR_INTERFACE_CONFIG); /* disable clock */
+	au_sync();
+
+	if (aup->irlap) {
+		irlap_close(aup->irlap);
+		aup->irlap = NULL;
+	}
+
+	netif_stop_queue(dev);
+	del_timer(&aup->timer);
+
+	/* disable the interrupt */
+	free_irq(AU1000_IRDA_TX_INT, dev);
+	free_irq(AU1000_IRDA_RX_INT, dev);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static void __exit au1k_irda_exit(void)
+{
+	struct net_device *dev = ir_devs[0];
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+
+	if (!dev) {
+		printk(KERN_ERR "au1k_ircc no dev found\n");
+		return;
+	}
+	if (aup->db[0].vaddr)  {
+		dma_free((void *)aup->db[0].vaddr, 
+				MAX_BUF_SIZE * 2*NUM_IR_DESC);
+		aup->db[0].vaddr = 0;
+	}
+	if (aup->rx_ring[0]) {
+		dma_free((void *)aup->rx_ring[0], 
+				2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
+		aup->rx_ring[0] = 0;
+	}
+	rtnl_lock();
+	unregister_netdevice(dev);
+	rtnl_unlock();
+	ir_devs[0] = 0;
+}
+
+
+static inline void 
+update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len)
+{
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+	struct net_device_stats *ps = &aup->stats;
+
+	ps->tx_packets++;
+	ps->tx_bytes += pkt_len;
+
+	if (status & IR_TX_ERROR) {
+		ps->tx_errors++;
+		ps->tx_aborted_errors++;
+	}
+}
+
+
+static void au1k_tx_ack(struct net_device *dev)
+{
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+	volatile ring_dest_t *ptxd;
+
+	ptxd = aup->tx_ring[aup->tx_tail];
+	while (!(ptxd->flags & AU_OWN) && (aup->tx_tail != aup->tx_head)) {
+		update_tx_stats(dev, ptxd->flags, 
+				ptxd->count_1<<8 | ptxd->count_0);
+		ptxd->count_0 = 0;
+		ptxd->count_1 = 0;
+		au_sync();
+
+		aup->tx_tail = (aup->tx_tail + 1) & (NUM_IR_DESC - 1);
+		ptxd = aup->tx_ring[aup->tx_tail];
+
+		if (aup->tx_full) {
+			aup->tx_full = 0;
+			netif_wake_queue(dev);
+		}
+	}
+
+	if (aup->tx_tail == aup->tx_head) {
+		if (aup->newspeed) {
+			au1k_irda_set_speed(dev, aup->newspeed);
+			aup->newspeed = 0;
+		}
+		else {
+			writel(read_ir_reg(IR_CONFIG_1) & ~IR_TX_ENABLE, 
+					IR_CONFIG_1); 
+			au_sync();
+			writel(read_ir_reg(IR_CONFIG_1) | IR_RX_ENABLE, 
+					IR_CONFIG_1); 
+			writel(0, IR_RING_PROMPT);
+			au_sync();
+		}
+	}
+}
+
+
+/*
+ * Au1000 transmit routine.
+ */
+static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+	int speed = irda_get_next_speed(skb);
+	volatile ring_dest_t *ptxd;
+	u32 len;
+
+	u32 flags;
+	db_dest_t *pDB;
+
+	if (speed != aup->speed && speed != -1) {
+		aup->newspeed = speed;
+	}
+
+	if ((skb->len == 0) && (aup->newspeed)) {
+		if (aup->tx_tail == aup->tx_head) {
+			au1k_irda_set_speed(dev, speed);
+			aup->newspeed = 0;
+		}
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	ptxd = aup->tx_ring[aup->tx_head];
+	flags = ptxd->flags;
+
+	if (flags & AU_OWN) {
+		printk(KERN_INFO "%s: tx_full\n", dev->name);
+		netif_stop_queue(dev);
+		aup->tx_full = 1;
+		return 1;
+	}
+	else if (((aup->tx_head + 1) & (NUM_IR_DESC - 1)) == aup->tx_tail) {
+		printk(KERN_INFO "%s: tx_full\n", dev->name);
+		netif_stop_queue(dev);
+		aup->tx_full = 1;
+		return 1;
+	}
+
+	pDB = aup->tx_db_inuse[aup->tx_head];
+
+#if 0
+	if (read_ir_reg(IR_RX_BYTE_CNT) != 0) {
+		printk("tx warning: rx byte cnt %x\n", 
+				read_ir_reg(IR_RX_BYTE_CNT));
+	}
+#endif
+	
+	if (aup->speed == 4000000) {
+		/* FIR */
+		memcpy((void *)pDB->vaddr, skb->data, skb->len);
+		ptxd->count_0 = skb->len & 0xff;
+		ptxd->count_1 = (skb->len >> 8) & 0xff;
+	}
+	else {
+		/* SIR */
+		len = async_wrap_skb(skb, (u8 *)pDB->vaddr, MAX_BUF_SIZE);
+		ptxd->count_0 = len & 0xff;
+		ptxd->count_1 = (len >> 8) & 0xff;
+		ptxd->flags |= IR_DIS_CRC;
+	}
+	ptxd->flags |= AU_OWN;
+	au_sync();
+
+	writel(read_ir_reg(IR_CONFIG_1) | IR_TX_ENABLE, IR_CONFIG_1); 
+	writel(0, IR_RING_PROMPT);
+	au_sync();
+
+	dev_kfree_skb(skb);
+	aup->tx_head = (aup->tx_head + 1) & (NUM_IR_DESC - 1);
+	dev->trans_start = jiffies;
+	return 0;
+}
+
+
+static inline void 
+update_rx_stats(struct net_device *dev, u32 status, u32 count)
+{
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+	struct net_device_stats *ps = &aup->stats;
+
+	ps->rx_packets++;
+
+	if (status & IR_RX_ERROR) {
+		ps->rx_errors++;
+		if (status & (IR_PHY_ERROR|IR_FIFO_OVER))
+			ps->rx_missed_errors++;
+		if (status & IR_MAX_LEN)
+			ps->rx_length_errors++;
+		if (status & IR_CRC_ERROR)
+			ps->rx_crc_errors++;
+	}
+	else 
+		ps->rx_bytes += count;
+}
+
+/*
+ * Au1000 receive routine.
+ */
+static int au1k_irda_rx(struct net_device *dev)
+{
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+	struct sk_buff *skb;
+	volatile ring_dest_t *prxd;
+	u32 flags, count;
+	db_dest_t *pDB;
+
+	prxd = aup->rx_ring[aup->rx_head];
+	flags = prxd->flags;
+
+	while (!(flags & AU_OWN))  {
+		pDB = aup->rx_db_inuse[aup->rx_head];
+		count = prxd->count_1<<8 | prxd->count_0;
+		if (!(flags & IR_RX_ERROR))  {
+			/* good frame */
+			update_rx_stats(dev, flags, count);
+			skb=alloc_skb(count+1,GFP_ATOMIC);
+			if (skb == NULL) {
+				aup->stats.rx_dropped++;
+				continue;
+			}
+			skb_reserve(skb, 1);
+			if (aup->speed == 4000000)
+				skb_put(skb, count);
+			else
+				skb_put(skb, count-2);
+			memcpy(skb->data, (void *)pDB->vaddr, count-2);
+			skb->dev = dev;
+			skb->mac.raw = skb->data;
+			skb->protocol = htons(ETH_P_IRDA);
+			netif_rx(skb);
+			prxd->count_0 = 0;
+			prxd->count_1 = 0;
+		}
+		prxd->flags |= AU_OWN;
+		aup->rx_head = (aup->rx_head + 1) & (NUM_IR_DESC - 1);
+		writel(0, IR_RING_PROMPT);
+		au_sync();
+
+		/* next descriptor */
+		prxd = aup->rx_ring[aup->rx_head];
+		flags = prxd->flags;
+		dev->last_rx = jiffies;
+
+	}
+	return 0;
+}
+
+
+void au1k_irda_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+
+	if (dev == NULL) {
+		printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
+		return;
+	}
+
+	writel(0, IR_INT_CLEAR); /* ack irda interrupts */
+
+	au1k_irda_rx(dev);
+	au1k_tx_ack(dev);
+}
+
+
+/*
+ * The Tx ring has been full longer than the watchdog timeout
+ * value. The transmitter must be hung?
+ */
+static void au1k_tx_timeout(struct net_device *dev)
+{
+	u32 speed;
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+
+	printk(KERN_ERR "%s: tx timeout\n", dev->name);
+	speed = aup->speed;
+	aup->speed = 0;
+	au1k_irda_set_speed(dev, speed);
+	aup->tx_full = 0;
+	netif_wake_queue(dev);
+}
+
+
+/*
+ * Set the IrDA communications speed.
+ */
+static int 
+au1k_irda_set_speed(struct net_device *dev, int speed)
+{
+	unsigned long flags;
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+	u32 control;
+	int ret = 0, timeout = 10, i;
+	volatile ring_dest_t *ptxd;
+
+	if (speed == aup->speed)
+		return ret;
+
+	spin_lock_irqsave(&ir_lock, flags);
+
+	/* disable PHY first */
+	writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE);
+
+	/* disable RX/TX */
+	writel(read_ir_reg(IR_CONFIG_1) & ~(IR_RX_ENABLE|IR_TX_ENABLE), 
+			IR_CONFIG_1);
+	au_sync_delay(1);
+	while (read_ir_reg(IR_ENABLE) & (IR_RX_STATUS | IR_TX_STATUS)) {
+		mdelay(1);
+		if (!timeout--) {
+			printk(KERN_ERR "%s: rx/tx disable timeout\n",
+					dev->name);
+			break;
+		}
+	}
+
+	/* disable DMA */
+	writel(read_ir_reg(IR_CONFIG_1) & ~IR_DMA_ENABLE, IR_CONFIG_1);
+	au_sync_delay(1);
+
+	/* 
+	 *  After we disable tx/rx. the index pointers
+ 	 * go back to zero.
+	 */
+	aup->tx_head = aup->tx_tail = aup->rx_head = 0;
+	for (i=0; i<NUM_IR_DESC; i++) {
+		ptxd = aup->tx_ring[i];
+		ptxd->flags = 0;
+		ptxd->count_0 = 0;
+		ptxd->count_1 = 0;
+	}
+
+	for (i=0; i<NUM_IR_DESC; i++) {
+		ptxd = aup->rx_ring[i];
+		ptxd->count_0 = 0;
+		ptxd->count_1 = 0;
+		ptxd->flags = AU_OWN;
+	}
+
+	if (speed == 4000000)
+		writel(1<<13, CPLD_AUX1);
+	else
+		writel(readl(CPLD_AUX1) & ~(1<<13), CPLD_AUX1);
+
+	switch (speed) {
+	case 9600:	
+		writel(11<<10 | 12<<5, IR_WRITE_PHY_CONFIG); 
+		writel(IR_SIR_MODE, IR_CONFIG_1); 
+		break;
+	case 19200:	
+		writel(5<<10 | 12<<5, IR_WRITE_PHY_CONFIG); 
+		writel(IR_SIR_MODE, IR_CONFIG_1); 
+		break;
+	case 38400:
+		writel(2<<10 | 12<<5, IR_WRITE_PHY_CONFIG); 
+		writel(IR_SIR_MODE, IR_CONFIG_1); 
+		break;
+	case 57600:	
+		writel(1<<10 | 12<<5, IR_WRITE_PHY_CONFIG); 
+		writel(IR_SIR_MODE, IR_CONFIG_1); 
+		break;
+	case 115200: 
+		writel(12<<5, IR_WRITE_PHY_CONFIG); 
+		writel(IR_SIR_MODE, IR_CONFIG_1); 
+		break;
+	case 4000000:
+		writel(0xF, IR_WRITE_PHY_CONFIG);
+		writel(IR_FIR|IR_DMA_ENABLE|IR_RX_ENABLE, IR_CONFIG_1); 
+		break;
+	default:
+		printk(KERN_ERR "%s unsupported speed %x\n", dev->name, speed);
+		ret = -EINVAL;
+		break;
+	}
+
+	aup->speed = speed;
+	writel(read_ir_reg(IR_ENABLE) | 0x8000, IR_ENABLE);
+	au_sync();
+
+	control = read_ir_reg(IR_ENABLE);
+	writel(0, IR_RING_PROMPT);
+	au_sync();
+
+	if (control & (1<<14)) {
+		printk(KERN_ERR "%s: configuration error\n", dev->name);
+	}
+	else {
+		if (control & (1<<11))
+			printk(KERN_INFO "%s Valid SIR config\n", dev->name);
+		if (control & (1<<12))
+			printk(KERN_INFO "%s Valid MIR config\n", dev->name);
+		if (control & (1<<13))
+			printk(KERN_INFO "%s Valid FIR config\n", dev->name);
+		if (control & (1<<10))
+			printk(KERN_INFO "%s TX enabled\n", dev->name);
+		if (control & (1<<9))
+			printk(KERN_INFO "%s RX enabled\n", dev->name);
+	}
+
+	spin_unlock_irqrestore(&ir_lock, flags);
+	return ret;
+}
+
+static int 
+au1k_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
+{
+	struct if_irda_req *rq = (struct if_irda_req *)ifreq;
+	struct au1k_private *aup = dev->priv;
+	int ret = -EOPNOTSUPP;
+
+	switch (cmd) {
+	case SIOCSBANDWIDTH:
+		if (capable(CAP_NET_ADMIN)) {
+			/*
+			 * We are unable to set the speed if the
+			 * device is not running.
+			 */
+			if (aup->open)
+				ret = au1k_irda_set_speed(dev,
+						rq->ifr_baudrate);
+			else {
+				printk(KERN_ERR "%s ioctl: !netif_running\n",
+						dev->name);
+				ret = 0;
+			}
+		}
+		break;
+
+	case SIOCSMEDIABUSY:
+		ret = -EPERM;
+		if (capable(CAP_NET_ADMIN)) {
+			irda_device_set_media_busy(dev, TRUE);
+			ret = 0;
+		}
+		break;
+
+	case SIOCGRECEIVING:
+		rq->ifr_receiving = 0;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+
+static struct net_device_stats *au1k_irda_stats(struct net_device *dev)
+{
+	struct au1k_private *aup = (struct au1k_private *) dev->priv;
+	return &aup->stats;
+}
+
+#ifdef MODULE
+MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
+MODULE_DESCRIPTION("Au1000 IrDA Device Driver");
+
+module_init(au1k_irda_init);
+module_exit(au1k_irda_exit);
+#endif /* MODULE */
diff -urN linux-2.5.73-bk3/drivers/net/ixgb/ixgb_ethtool.c linux-2.5.73-bk4/drivers/net/ixgb/ixgb_ethtool.c
--- linux-2.5.73-bk3/drivers/net/ixgb/ixgb_ethtool.c	2003-06-22 11:33:15.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/ixgb/ixgb_ethtool.c	2003-06-26 05:00:28.000000000 -0700
@@ -448,8 +448,6 @@
 	case ETHTOOL_SSET:{
 			struct ethtool_cmd ecmd;
 
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
 			if (copy_from_user(&ecmd, addr, sizeof (ecmd)))
 				return -EFAULT;
 			return ixgb_ethtool_sset(adapter, &ecmd);
@@ -482,9 +480,6 @@
 #endif				/* ETHTOOL_GREGS */
 	case ETHTOOL_NWAY_RST:{
 			IXGB_DBG("ETHTOOL_NWAY_RST\n");
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-
 			ixgb_down(adapter);
 			ixgb_up(adapter);
 
@@ -539,9 +534,6 @@
 			struct ethtool_eeprom eeprom;
 
 			IXGB_DBG("ETHTOOL_SEEPROM\n");
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-
 			if (copy_from_user(&eeprom, addr, sizeof (eeprom)))
 				return -EFAULT;
 
diff -urN linux-2.5.73-bk3/drivers/net/meth.c linux-2.5.73-bk4/drivers/net/meth.c
--- linux-2.5.73-bk3/drivers/net/meth.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk4/drivers/net/meth.c	2003-06-26 05:00:28.000000000 -0700
@@ -0,0 +1,862 @@
+/*
+ * meth.c -- O2 Builtin 10/100 Ethernet driver
+ *
+ * Copyright (C) 2001 Ilya Volynets
+ *
+ *	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.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h> /* printk() */
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+#include <linux/pci.h>
+
+#include <linux/in.h>
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/tcp.h>         /* struct tcphdr */
+#include <linux/skbuff.h>
+#include <linux/mii.h> /*MII definitions */
+
+#include <asm/ip32/crime.h>
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
+
+#include "meth.h"
+
+#include <linux/in6.h>
+#include <asm/checksum.h>
+
+#ifndef MFE_DEBUG
+#define MFE_DEBUG 0
+#endif
+
+#if MFE_DEBUG>=1
+#define DPRINTK(str,args...) printk (KERN_DEBUG "meth(%ld): %s: " str, jiffies, __FUNCTION__ , ## args)
+#define MFE_RX_DEBUG 2
+#else
+#define DPRINTK(str,args...)
+#define MFE_RX_DEBUG 0
+#endif
+
+
+static const char *version="meth.c: Ilya Volynets (ilya@theIlya.com)";
+static const char *meth_str="SGI O2 Fast Ethernet";
+MODULE_AUTHOR("Ilya Volynets");
+MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
+
+/* This is a load-time options */
+/*static int eth = 0;
+MODULE_PARM(eth, "i");*/
+
+#define HAVE_TX_TIMEOUT
+/* The maximum time waited (in jiffies) before assuming a Tx failed. (400ms) */
+#define TX_TIMEOUT (400*HZ/1000)
+
+#ifdef HAVE_TX_TIMEOUT
+static int timeout = TX_TIMEOUT;
+MODULE_PARM(timeout, "i");
+#endif
+
+int meth_eth;
+
+/*
+ * This structure is private to each device. It is used to pass
+ * packets in and out, so there is place for a packet
+ */
+
+typedef struct meth_private {
+    struct net_device_stats stats;
+	volatile struct meth_regs *regs;
+	u64 mode; /* in-memory copy of MAC control register */
+	int  phy_addr; /* address of phy, used by mdio_* functions, initialized in mdio_probe*/
+	tx_packet *tx_ring;
+	dma_addr_t tx_ring_dma;
+	int free_space;
+	struct sk_buff *tx_skbs[TX_RING_ENTRIES];
+	dma_addr_t      tx_skb_dmas[TX_RING_ENTRIES];
+	int tx_read,tx_write;
+	int tx_count;
+
+	rx_packet *rx_ring[RX_RING_ENTRIES];
+	dma_addr_t rx_ring_dmas[RX_RING_ENTRIES];
+	int rx_write;
+
+    spinlock_t meth_lock;
+} meth_private;
+
+extern struct net_device meth_devs[];
+void meth_tx_timeout (struct net_device *dev);
+void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs);
+        
+/* global, initialized in ip32-setup.c */
+char o2meth_eaddr[8]={0,0,0,0,0,0,0,0};
+
+static inline void load_eaddr(struct net_device *dev,
+			      volatile struct meth_regs *regs)
+{
+	int i;
+	DPRINTK("Loading MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+		(int)o2meth_eaddr[0]&0xFF,(int)o2meth_eaddr[1]&0xFF,(int)o2meth_eaddr[2]&0xFF,
+		(int)o2meth_eaddr[3]&0xFF,(int)o2meth_eaddr[4]&0xFF,(int)o2meth_eaddr[5]&0xFF);
+	//memcpy(dev->dev_addr,o2meth_eaddr+2,6);
+	for (i=0; i<6; i++)
+		dev->dev_addr[i]=o2meth_eaddr[i];
+	regs->mac_addr= //dev->dev_addr[0]|(dev->dev_addr[1]<<8)|
+					//dev->dev_addr[2]<<16|(dev->dev_addr[3]<<24)|
+					//dev->dev_addr[4]<<32|(dev->dev_addr[5]<<40);
+	(*(u64*)o2meth_eaddr)>>16;
+	DPRINTK("MAC, finally is %0lx\n",regs->mac_addr);
+}
+
+/*
+ *Waits for BUSY status of mdio bus to clear
+ */
+#define WAIT_FOR_PHY(___regs, ___rval)			\
+	while((___rval=___regs->phy_data)&MDIO_BUSY){	\
+		udelay(25);								\
+	}
+/*read phy register, return value read */
+static int mdio_read(meth_private *priv,int phyreg)
+{
+	volatile meth_regs* regs=priv->regs;
+	volatile u32 rval;
+	WAIT_FOR_PHY(regs,rval)
+	regs->phy_registers=(priv->phy_addr<<5)|(phyreg&0x1f);
+	udelay(25);
+	regs->phy_trans_go=1;
+	udelay(25);
+	WAIT_FOR_PHY(regs,rval)
+	return rval&MDIO_DATA_MASK;
+}
+
+/*write phy register */
+static void mdio_write(meth_private* priv,int pfyreg,int val)
+{
+	volatile meth_regs* regs=priv->regs;
+	int rval;
+///	DPRINTK("Trying to write value %i to reguster %i\n",val, pfyreg);
+	spin_lock_irq(&priv->meth_lock);
+	WAIT_FOR_PHY(regs,rval)
+	regs->phy_registers=(priv->phy_addr<<5)|(pfyreg&0x1f);
+	regs->phy_data=val;
+	udelay(25);
+	WAIT_FOR_PHY(regs,rval)
+	spin_unlock_irq(&priv->meth_lock);
+}
+
+/* Modify phy register using given mask and value */
+static void mdio_update(meth_private* priv,int phyreg, int val, int mask)
+{
+	int rval;
+	DPRINTK("RMW value %i to PHY register %i with mask %i\n",val,phyreg,mask);
+	rval=mdio_read(priv,phyreg);
+	rval=(rval&~mask)|(val&mask);
+	mdio_write(priv,phyreg,rval);
+}
+
+/* handle errata data on MDIO bus */
+//static void mdio_errata(meth_private *priv)
+//{
+	/* Hmmm... what the hell is phyerrata? does it come from sys init parameters in IRIX */
+//}
+static int mdio_probe(meth_private *priv)
+{
+	int i, p2, p3;
+	DPRINTK("Detecting PHY kind\n");
+	/* check if phy is detected already */
+	if(priv->phy_addr>=0&&priv->phy_addr<32)
+		return 0;
+	spin_lock_irq(&priv->meth_lock);
+	for (i=0;i<32;++i){
+		priv->phy_addr=(char)i;
+		p2=mdio_read(priv,2);
+#ifdef MFE_DEBUG
+		p3=mdio_read(priv,3);
+		switch ((p2<<12)|(p3>>4)){
+			case PHY_QS6612X:
+				DPRINTK("PHY is QS6612X\n");
+				break;
+			case PHY_ICS1889:
+				DPRINTK("PHY is ICS1889\n");
+				break;
+			case PHY_ICS1890:
+				DPRINTK("PHY is ICS1890\n");
+				break;
+			case PHY_DP83840:
+				DPRINTK("PHY is DP83840\n");
+				break;
+		}
+#endif
+		if(p2!=0xffff&&p2!=0x0000){
+			DPRINTK("PHY code: %x\n",(p2<<12)|(p3>>4));
+			break;
+		}
+	}
+	spin_unlock_irq(&priv->meth_lock);
+	if(priv->phy_addr<32) {
+		return 0;
+	}
+	DPRINTK("Oopsie! PHY is not known!\n");
+	priv->phy_addr=-1;
+	return -ENODEV;
+}
+
+static void meth_check_link(struct net_device *dev)
+{
+	struct meth_private *priv = (struct meth_private *) dev->priv;
+	int mii_partner = mdio_read(priv, 5);
+	int mii_advertising = mdio_read(priv, 4);
+	int negotiated = mii_advertising & mii_partner;
+	int duplex, speed;
+
+	if (mii_partner == 0xffff)
+		return;
+
+	duplex = ((negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040)?METH_PHY_FDX:0;
+	speed = (negotiated & 0x0380)?METH_100MBIT:0;
+
+	if ((priv->mode & METH_PHY_FDX) ^ duplex)
+	{
+		DPRINTK("Setting %s-duplex\n", duplex ? "full" : "half");
+		if (duplex)
+			priv->mode |= METH_PHY_FDX;
+		else
+			priv->mode &= ~METH_PHY_FDX;
+		priv->regs->mac_ctrl = priv->mode;
+	}
+
+	if ((priv->mode & METH_100MBIT) ^ speed)
+	{
+		DPRINTK("Setting %dMbs mode\n", speed ? 100 : 10);
+		if (duplex)
+			priv->mode |= METH_100MBIT;
+		else
+			priv->mode &= ~METH_100MBIT;
+		priv->regs->mac_ctrl = priv->mode;
+	}
+}
+
+
+static int meth_init_tx_ring(meth_private *priv)
+{
+	/* Init TX ring */
+	DPRINTK("Initializing TX ring\n");
+	priv->tx_ring = (tx_packet *) pci_alloc_consistent(NULL,TX_RING_BUFFER_SIZE,&(priv->tx_ring_dma));
+	if(!priv->tx_ring)
+		return -ENOMEM;
+	memset(priv->tx_ring, 0, TX_RING_BUFFER_SIZE);
+	priv->tx_count = priv->tx_read = priv->tx_write = 0;
+	priv->regs->tx_ring_base = priv->tx_ring_dma;
+	priv->free_space = TX_RING_ENTRIES;
+	/* Now init skb save area */
+	memset(priv->tx_skbs,0,sizeof(priv->tx_skbs));
+	memset(priv->tx_skb_dmas,0,sizeof(priv->tx_skb_dmas));
+	DPRINTK("Done with TX ring init\n");
+	return 0;
+}
+
+static int meth_init_rx_ring(meth_private *priv)
+{
+	int i;
+	DPRINTK("Initializing RX ring\n");
+	for(i=0;i<RX_RING_ENTRIES;i++){
+		DPRINTK("\t1:\t%i\t",i);
+		/*if(!(priv->rx_ring[i]=get_free_page(GFP_KERNEL)))
+			return -ENOMEM;
+		DPRINTK("\t2:\t%i\n",i);*/
+		priv->rx_ring[i]=(rx_packet*)pci_alloc_consistent(NULL,METH_RX_BUFF_SIZE,&(priv->rx_ring_dmas[i]));
+		/* I'll need to re-sync it after each RX */
+		DPRINTK("\t%p\n",priv->rx_ring[i]);
+		priv->regs->rx_fifo=priv->rx_ring_dmas[i];
+	}
+	priv->rx_write = 0;
+	DPRINTK("Done with RX ring\n");
+	return 0;
+}
+static void meth_free_tx_ring(meth_private *priv)
+{
+	int i;
+
+	/* Remove any pending skb */
+	for (i = 0; i < TX_RING_ENTRIES; i++) {
+	  if (priv->tx_skbs[i])
+		dev_kfree_skb(priv->tx_skbs[i]);
+		priv->tx_skbs[i] = NULL;
+	}
+	pci_free_consistent(NULL,
+			    TX_RING_BUFFER_SIZE,
+			    priv->tx_ring,
+			    priv->tx_ring_dma);
+}
+static void meth_free_rx_ring(meth_private *priv)
+{
+	int i;
+
+	for(i=0;i<RX_RING_ENTRIES;i++)
+		pci_free_consistent(NULL,
+				    METH_RX_BUFF_SIZE,
+				    priv->rx_ring[i],
+				    priv->rx_ring_dmas[i]);
+}
+
+int meth_reset(struct net_device *dev)
+{
+	struct meth_private *priv = (struct meth_private *) dev->priv;
+
+	/* Reset card */
+	priv->regs->mac_ctrl = SGI_MAC_RESET;
+	priv->regs->mac_ctrl = 0;
+	udelay(25);
+	DPRINTK("MAC control after reset: %016lx\n", priv->regs->mac_ctrl);
+
+	/* Load ethernet address */
+	load_eaddr(dev, priv->regs);
+	/* Should load some "errata", but later */
+	
+	/* Check for device */
+	if(mdio_probe(priv) < 0) {
+		DPRINTK("Unable to find PHY\n");
+		return -ENODEV;
+	}
+
+	/* Initial mode -- 10|Half-duplex|Accept normal packets */
+	priv->mode=METH_ACCEPT_MCAST|METH_DEFAULT_IPG;
+	if(dev->flags | IFF_PROMISC)
+		priv->mode |= METH_PROMISC;
+	priv->regs->mac_ctrl = priv->mode;
+
+	/* Autonegociate speed and duplex mode */
+	meth_check_link(dev);
+
+	/* Now set dma control, but don't enable DMA, yet */
+	priv->regs->dma_ctrl= (4 << METH_RX_OFFSET_SHIFT) |
+		              (RX_RING_ENTRIES << METH_RX_DEPTH_SHIFT);
+
+	return(0);
+}
+
+/*============End Helper Routines=====================*/
+
+/*
+ * Open and close
+ */
+
+int meth_open(struct net_device *dev)
+{
+	meth_private *priv=dev->priv;
+	volatile meth_regs *regs=priv->regs;
+
+	MOD_INC_USE_COUNT;
+
+	/* Start DMA */
+	regs->dma_ctrl|=
+	        METH_DMA_TX_EN|/*METH_DMA_TX_INT_EN|*/
+		METH_DMA_RX_EN|METH_DMA_RX_INT_EN;
+
+	if(request_irq(dev->irq,meth_interrupt,SA_SHIRQ,meth_str,dev)){
+		printk(KERN_ERR "%s: Can't get irq %d\n", dev->name, dev->irq);
+		return -EAGAIN;
+	}
+	netif_start_queue(dev);
+	DPRINTK("Opened... DMA control=0x%08lx\n", regs->dma_ctrl);
+	return 0;
+}
+
+int meth_release(struct net_device *dev)
+{
+    netif_stop_queue(dev); /* can't transmit any more */
+	/* shut down dma */
+	((meth_private*)(dev->priv))->regs->dma_ctrl&=
+		~(METH_DMA_TX_EN|METH_DMA_TX_INT_EN|
+		METH_DMA_RX_EN|METH_DMA_RX_INT_EN);
+	free_irq(dev->irq, dev);
+    MOD_DEC_USE_COUNT;
+    return 0;
+}
+
+/*
+ * Configuration changes (passed on by ifconfig)
+ */
+int meth_config(struct net_device *dev, struct ifmap *map)
+{
+    if (dev->flags & IFF_UP) /* can't act on a running interface */
+        return -EBUSY;
+
+    /* Don't allow changing the I/O address */
+    if (map->base_addr != dev->base_addr) {
+        printk(KERN_WARNING "meth: Can't change I/O address\n");
+        return -EOPNOTSUPP;
+    }
+
+    /* Allow changing the IRQ */
+    if (map->irq != dev->irq) {
+        printk(KERN_WARNING "meth: Can't change IRQ\n");
+        return -EOPNOTSUPP;
+    }
+	DPRINTK("Configured\n");
+
+    /* ignore other fields */
+    return 0;
+}
+
+/*
+ * Receive a packet: retrieve, encapsulate and pass over to upper levels
+ */
+void meth_rx(struct net_device* dev)
+{
+    struct sk_buff *skb;
+    struct meth_private *priv = (struct meth_private *) dev->priv;
+	rx_packet *rxb;
+	DPRINTK("RX...\n");
+	// TEMP	while((rxb=priv->rx_ring[priv->rx_write])->status.raw&0x8000000000000000){
+	while((rxb=priv->rx_ring[priv->rx_write])->status.raw&0x8000000000000000){
+	        int len=rxb->status.parsed.rx_len - 4; /* omit CRC */
+		DPRINTK("(%i)\n",priv->rx_write);
+		/* length sanity check */
+		if(len < 60 || len > 1518) {
+		  printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x.\n",
+			 dev->name, priv->rx_write, rxb->status.raw);
+		  priv->stats.rx_errors++;
+		  priv->stats.rx_length_errors++;
+		}
+		if(!(rxb->status.raw&METH_RX_STATUS_ERRORS)){
+			skb=alloc_skb(len+2,GFP_ATOMIC);/* Should be atomic -- we are in interrupt */
+			if(!skb){
+				/* Ouch! No memory! Drop packet on the floor */
+				DPRINTK("!!!>>>Ouch! Not enough Memory for RX buffer!\n");
+				priv->stats.rx_dropped++;
+			} else {
+				skb_reserve(skb, 2); /* align IP on 16B boundary */  
+    			memcpy(skb_put(skb, len), rxb->buf, len);
+			    /* Write metadata, and then pass to the receive level */
+			    skb->dev = dev;
+			    skb->protocol = eth_type_trans(skb, dev);
+				//skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
+			   
+				DPRINTK("passing packet\n");
+				DPRINTK("len = %d rxb->status = %x\n",
+					len, rxb->status.raw);
+				netif_rx(skb);
+				dev->last_rx = jiffies;
+				priv->stats.rx_packets++;
+				priv->stats.rx_bytes+=len;
+				DPRINTK("There we go... Whew...\n");
+			}
+		}
+		priv->regs->rx_fifo=priv->rx_ring_dmas[priv->rx_write];
+		rxb->status.raw=0;		
+		priv->rx_write=(priv->rx_write+1)&(RX_RING_ENTRIES-1);
+	}
+}
+
+static int meth_tx_full(struct net_device *dev)
+{
+	struct meth_private *priv = (struct meth_private *) dev->priv;
+
+	return(priv->tx_count >= TX_RING_ENTRIES-1);
+}
+
+void meth_tx_cleanup(struct net_device* dev, int rptr)
+{
+	meth_private *priv=dev->priv;
+	tx_packet* status;
+	struct sk_buff *skb;
+
+	spin_lock(&priv->meth_lock);
+
+	/* Stop DMA */
+	priv->regs->dma_ctrl &= ~(METH_DMA_TX_INT_EN);
+
+	while(priv->tx_read != rptr){
+		skb = priv->tx_skbs[priv->tx_read];
+		status = &priv->tx_ring[priv->tx_read];
+		if(!status->header.res.sent)
+			break;
+		if(status->header.raw & METH_TX_STATUS_DONE) {
+			priv->stats.tx_packets++;
+			priv->stats.tx_bytes += skb->len;
+		}
+		dev_kfree_skb_irq(skb);
+		priv->tx_skbs[priv->tx_read] = NULL;
+		status->header.raw = 0;
+		priv->tx_read = (priv->tx_read+1)&(TX_RING_ENTRIES-1);
+		priv->tx_count --;
+	}
+
+	/* wake up queue if it was stopped */
+	if (netif_queue_stopped(dev) && ! meth_tx_full(dev)) {
+		netif_wake_queue(dev);
+	}
+
+	spin_unlock(priv->meth_lock);
+}
+
+/*
+ * The typical interrupt entry point
+ */
+void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs)
+{
+	struct meth_private *priv;
+	union {
+		u32	reg; /*Whole status register */
+		struct {
+			u32			:	2,
+				rx_seq	:	5,
+				tx_read	:	9,
+				
+				rx_read	:	8,
+				int_mask:	8;
+		} parsed;
+	} status;
+	/*
+	 * As usual, check the "device" pointer for shared handlers.
+	 * Then assign "struct device *dev"
+	 */
+	struct net_device *dev = (struct net_device *)dev_id;
+	/* ... and check with hw if it's really ours */
+
+	if (!dev /*paranoid*/ ) return;
+
+	/* Lock the device */
+	priv = (struct meth_private *) dev->priv;
+
+	status.reg = priv->regs->int_flags;
+    
+	DPRINTK("Interrupt, status %08x...\n",status.reg);
+	if (status.parsed.int_mask & METH_INT_RX_THRESHOLD) {
+		/* send it to meth_rx for handling */
+		meth_rx(dev);
+	}
+
+	if (status.parsed.int_mask & (METH_INT_TX_EMPTY|METH_INT_TX_PKT)) {
+		/* a transmission is over: free the skb */
+		meth_tx_cleanup(dev, status.parsed.tx_read);
+	}
+	/* check for errors too... */
+	if (status.parsed.int_mask & (METH_INT_TX_LINK_FAIL))
+		printk(KERN_WARNING "meth: link failure\n");
+	if (status.parsed.int_mask & (METH_INT_MEM_ERROR))
+		printk(KERN_WARNING "meth: memory error\n");
+	if (status.parsed.int_mask & (METH_INT_TX_ABORT))
+		printk(KERN_WARNING "meth: aborted\n");
+	DPRINTK("Interrupt handling done...\n");
+	
+	priv->regs->int_flags=status.reg&0xff; /* clear interrupts */
+}
+
+/*
+ * Transmits packets that fit into TX descriptor (are <=120B)
+ */
+static void meth_tx_short_prepare(meth_private* priv, struct sk_buff* skb)
+{
+	tx_packet *desc=&priv->tx_ring[priv->tx_write];
+	int len = (skb->len<ETH_ZLEN)?ETH_ZLEN:skb->len;
+
+	DPRINTK("preparing short packet\n");
+	/* maybe I should set whole thing to 0 first... */
+	memcpy(desc->data.dt+(120-len),skb->data,skb->len);
+	if(skb->len < len)
+		memset(desc->data.dt+120-len+skb->len,0,len-skb->len);
+	desc->header.raw=METH_TX_CMD_INT_EN|(len-1)|((128-len)<<16);
+	DPRINTK("desc=%016lx\n",desc->header.raw);
+}
+#define TX_CATBUF1 BIT(25)
+static void meth_tx_1page_prepare(meth_private* priv, struct sk_buff* skb)
+{
+	tx_packet *desc=&priv->tx_ring[priv->tx_write];
+	void *buffer_data = (void *)(((u64)skb->data + 7ULL) & (~7ULL));
+	int unaligned_len = (int)((u64)buffer_data - (u64)skb->data);
+	int buffer_len = skb->len - unaligned_len;
+	dma_addr_t catbuf;
+
+	DPRINTK("preparing 1 page...\n");
+	DPRINTK("length=%d data=%p\n", skb->len, skb->data);
+	DPRINTK("unaligned_len=%d\n", unaligned_len);
+	DPRINTK("buffer_data=%p buffer_len=%d\n",
+	       buffer_data,
+	       buffer_len);
+
+	desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|(skb->len-1);
+
+	/* unaligned part */
+	if(unaligned_len){
+		memcpy(desc->data.dt+(120-unaligned_len),
+		       skb->data, unaligned_len);
+		desc->header.raw |= (128-unaligned_len) << 16;
+	}
+
+	/* first page */
+	catbuf = pci_map_single(NULL,
+				buffer_data,
+				buffer_len,
+				PCI_DMA_TODEVICE);
+	DPRINTK("catbuf=%x\n", catbuf);
+	desc->data.cat_buf[0].form.start_addr = catbuf >> 3;
+	desc->data.cat_buf[0].form.len = buffer_len-1;
+	DPRINTK("desc=%016lx\n",desc->header.raw);
+	DPRINTK("cat_buf[0].raw=%016lx\n",desc->data.cat_buf[0].raw);
+}
+#define TX_CATBUF2 BIT(26)
+static void meth_tx_2page_prepare(meth_private* priv, struct sk_buff* skb)
+{
+	tx_packet *desc=&priv->tx_ring[priv->tx_write];
+	void *buffer1_data = (void *)(((u64)skb->data + 7ULL) & (~7ULL));
+	void *buffer2_data = (void *)PAGE_ALIGN((u64)skb->data);
+	int unaligned_len = (int)((u64)buffer1_data - (u64)skb->data);
+	int buffer1_len = (int)((u64)buffer2_data - (u64)buffer1_data);
+	int buffer2_len = skb->len - buffer1_len - unaligned_len;
+	dma_addr_t catbuf1, catbuf2;
+
+	DPRINTK("preparing 2 pages... \n");
+	DPRINTK("length=%d data=%p\n", skb->len, skb->data);
+	DPRINTK("unaligned_len=%d\n", unaligned_len);
+	DPRINTK("buffer1_data=%p buffer1_len=%d\n",
+	       buffer1_data,
+	       buffer1_len);
+	DPRINTK("buffer2_data=%p buffer2_len=%d\n",
+	       buffer2_data,
+	       buffer2_len);
+
+	desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|TX_CATBUF2|(skb->len-1);
+	/* unaligned part */
+	if(unaligned_len){
+		memcpy(desc->data.dt+(120-unaligned_len),
+		       skb->data, unaligned_len);
+		desc->header.raw |= (128-unaligned_len) << 16;
+	}
+
+	/* first page */
+	catbuf1 = pci_map_single(NULL,
+				 buffer1_data,
+				 buffer1_len,
+				 PCI_DMA_TODEVICE);
+	DPRINTK("catbuf1=%x\n", catbuf1);
+	desc->data.cat_buf[0].form.start_addr = catbuf1 >> 3;
+	desc->data.cat_buf[0].form.len = buffer1_len-1;
+	/* second page */
+	catbuf2 = pci_map_single(NULL,
+				 buffer2_data,
+				 buffer2_len,
+				 PCI_DMA_TODEVICE);
+	DPRINTK("catbuf2=%x\n", catbuf2);
+	desc->data.cat_buf[1].form.start_addr = catbuf2 >> 3;
+	desc->data.cat_buf[1].form.len = buffer2_len-1;
+	DPRINTK("desc=%016lx\n",desc->header.raw);
+	DPRINTK("cat_buf[0].raw=%016lx\n",desc->data.cat_buf[0].raw);
+	DPRINTK("cat_buf[1].raw=%016lx\n",desc->data.cat_buf[1].raw);
+}
+
+
+void meth_add_to_tx_ring(meth_private *priv, struct sk_buff* skb)
+{
+	DPRINTK("Transmitting data...\n");
+	if(skb->len <= 120) {
+		/* Whole packet fits into descriptor */
+		meth_tx_short_prepare(priv,skb);
+	} else if(PAGE_ALIGN((u64)skb->data) !=
+		  PAGE_ALIGN((u64)skb->data+skb->len-1)) {
+		/* Packet crosses page boundary */
+		meth_tx_2page_prepare(priv,skb);
+	} else {
+		/* Packet is in one page */
+		meth_tx_1page_prepare(priv,skb);
+	}
+
+	/* Remember the skb, so we can free it at interrupt time */
+	priv->tx_skbs[priv->tx_write] = skb;
+	priv->tx_write = (priv->tx_write+1) & (TX_RING_ENTRIES-1);
+	priv->regs->tx_info.wptr = priv->tx_write;
+	priv->tx_count ++;
+	/* Enable DMA transfer */
+	priv->regs->dma_ctrl |= METH_DMA_TX_INT_EN;
+}
+
+/*
+ * Transmit a packet (called by the kernel)
+ */
+int meth_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct meth_private *priv = (struct meth_private *) dev->priv;
+
+	spin_lock_irq(&priv->meth_lock);
+
+	meth_add_to_tx_ring(priv, skb);
+	dev->trans_start = jiffies; /* save the timestamp */
+
+	/* If TX ring is full, tell the upper layer to stop sending packets */
+	if (meth_tx_full(dev)) {
+	        DPRINTK("TX full: stopping\n");
+		netif_stop_queue(dev);
+	}
+
+	spin_unlock_irq(&priv->meth_lock);
+
+	return 0;
+}
+
+/*
+ * Deal with a transmit timeout.
+ */
+
+void meth_tx_timeout (struct net_device *dev)
+{
+	struct meth_private *priv = (struct meth_private *) dev->priv;
+	
+	printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
+
+	/* Protect against concurrent rx interrupts */
+	spin_lock_irq(&priv->meth_lock);
+
+	/* Try to reset the adaptor. */
+	meth_reset(dev);
+
+	priv->stats.tx_errors++;
+
+	/* Clear all rings */
+	meth_free_tx_ring(priv);
+	meth_free_rx_ring(priv);
+	meth_init_tx_ring(priv);
+	meth_init_rx_ring(priv);
+
+	/* Restart dma */
+	priv->regs->dma_ctrl|=METH_DMA_TX_EN|METH_DMA_RX_EN|METH_DMA_RX_INT_EN;
+
+	/* Enable interrupt */
+	spin_unlock_irq(&priv->meth_lock);
+
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+
+	return;
+}
+
+/*
+ * Ioctl commands 
+ */
+int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ 
+    DPRINTK("ioctl\n");
+    return 0;
+}
+
+/*
+ * Return statistics to the caller
+ */
+struct net_device_stats *meth_stats(struct net_device *dev)
+{
+    struct meth_private *priv = (struct meth_private *) dev->priv;
+    return &priv->stats;
+}
+
+/*
+ * The init function (sometimes called probe).
+ * It is invoked by register_netdev()
+ */
+int meth_init(struct net_device *dev)
+{
+	meth_private *priv;
+	int ret;
+	/* 
+	 * Then, assign other fields in dev, using ether_setup() and some
+	 * hand assignments
+	 */
+	ether_setup(dev); /* assign some of the fields */
+
+	dev->open            = meth_open;
+	dev->stop            = meth_release;
+	dev->set_config      = meth_config;
+	dev->hard_start_xmit = meth_tx;
+	dev->do_ioctl        = meth_ioctl;
+	dev->get_stats       = meth_stats;
+#ifdef HAVE_TX_TIMEOUT
+	dev->tx_timeout      = meth_tx_timeout;
+	dev->watchdog_timeo  = timeout;
+#endif
+	dev->irq		 = MACE_ETHERNET_IRQ;
+	SET_MODULE_OWNER(dev);
+
+	/*
+	 * Then, allocate the priv field. This encloses the statistics
+	 * and a few private fields.
+	 */
+	priv = kmalloc(sizeof(struct meth_private), GFP_KERNEL);
+	if (priv == NULL)
+		return -ENOMEM;
+	dev->priv=priv;
+	memset(priv, 0, sizeof(struct meth_private));
+	spin_lock_init(&((struct meth_private *) dev->priv)->meth_lock);
+	/*
+	 * Make the usual checks: check_region(), probe irq, ...  -ENODEV
+	 * should be returned if no device found.  No resource should be
+	 * grabbed: this is done on open(). 
+	 */
+	priv->regs=(meth_regs*)SGI_MFE;
+	dev->base_addr=SGI_MFE;
+	priv->phy_addr = -1; /* No phy is known yet... */
+
+	/* Initialize the hardware */
+	if((ret=meth_reset(dev)) < 0)
+	        return ret;
+
+	/* Allocate the ring buffers */
+	if((ret=meth_init_tx_ring(priv))<0||(ret=meth_init_rx_ring(priv))<0){
+		meth_free_tx_ring(priv);
+		meth_free_rx_ring(priv);
+		return ret;
+	}
+
+	printk("SGI O2 Fast Ethernet rev. %ld\n", priv->regs->mac_ctrl >> 29);
+
+    return 0;
+}
+
+/*
+ * The devices
+ */
+
+struct net_device meth_devs[1] = {
+    { init: meth_init, }  /* init, nothing more */
+};
+
+/*
+ * Finally, the module stuff
+ */
+
+int meth_init_module(void)
+{
+	int result, device_present = 0;
+
+	strcpy(meth_devs[0].name, "eth%d");
+
+	if ( (result = register_netdev(meth_devs)) )
+		printk("meth: error %i registering device \"%s\"\n",
+		       result, meth_devs->name);
+	else device_present++;
+#ifndef METH_DEBUG
+	EXPORT_NO_SYMBOLS;
+#endif
+	
+	return device_present ? 0 : -ENODEV;
+}
+
+void meth_cleanup(void)
+{
+    kfree(meth_devs->priv);
+    unregister_netdev(meth_devs);
+    return;
+}
+
+module_init(meth_init_module);
+module_exit(meth_cleanup);
diff -urN linux-2.5.73-bk3/drivers/net/meth.h linux-2.5.73-bk4/drivers/net/meth.h
--- linux-2.5.73-bk3/drivers/net/meth.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk4/drivers/net/meth.h	2003-06-26 05:00:28.000000000 -0700
@@ -0,0 +1,273 @@
+
+/*
+ * snull.h -- definitions for the network module
+ *
+ * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
+ * Copyright (C) 2001 O'Reilly & Associates
+ *
+ * The source code in this file can be freely used, adapted,
+ * and redistributed in source or binary form, so long as an
+ * acknowledgment appears in derived source files.  The citation
+ * should list that the code comes from the book "Linux Device
+ * Drivers" by Alessandro Rubini and Jonathan Corbet, published
+ * by O'Reilly & Associates.   No warranty is attached;
+ * we cannot take responsibility for errors or fitness for use.
+ */
+
+/* version dependencies have been confined to a separate file */
+
+#define SGI_MFE		(MACE_BASE+MACE_ENET)
+/*		(0xBF280000)*/
+
+/* Tunable parameters */
+#define TX_RING_ENTRIES 64	/* 64-512?*/
+
+#define RX_RING_ENTRIES 16 /* Do not change */
+/* Internal constants */
+#define TX_RING_BUFFER_SIZE	(TX_RING_ENTRIES*sizeof(tx_packet))
+#define RX_BUFFER_SIZE 1546 /* ethenet packet size */
+#define METH_RX_BUFF_SIZE 4096
+#define RX_BUFFER_OFFSET (sizeof(rx_status_vector)+2) /* staus vector + 2 bytes of padding */
+#define RX_BUCKET_SIZE 256
+
+
+
+/* For more detailed explanations of what each field menas,
+   see Nick's great comments to #defines below (or docs, if
+   you are lucky enough toget hold of them :)*/
+
+/* tx status vector is written over tx command header upon
+   dma completion. */
+
+typedef struct tx_status_vector {
+	u64		sent:1; /* always set to 1...*/
+	u64		pad0:34;/* always set to 0 */
+	u64		flags:9;			/*I'm too lazy to specify each one separately at the moment*/
+	u64		col_retry_cnt:4;	/*collision retry count*/
+	u64		len:16;				/*Transmit length in bytes*/
+} tx_status_vector;
+
+/*
+ * Each packet is 128 bytes long.
+ * It consists of header, 0-3 concatination
+ * buffer pointers and up to 120 data bytes.
+ */
+typedef struct tx_packet_hdr {
+	u64		pad1:36; /*should be filled with 0 */
+	u64		cat_ptr3_valid:1,	/*Concatination pointer valid flags*/
+			cat_ptr2_valid:1,
+			cat_ptr1_valid:1;
+	u64		tx_int_flag:1;		/*Generate TX intrrupt when packet has been sent*/
+	u64		term_dma_flag:1;	/*Terminate transmit DMA on transmit abort conditions*/
+	u64		data_offset:7;		/*Starting byte offset in ring data block*/
+	u64		data_len:16;		/*Length of valid data in bytes-1*/
+} tx_packet_hdr;
+typedef union tx_cat_ptr {
+	struct {
+		u64		pad2:16; /* should be 0 */
+		u64		len:16;				/*length of buffer data - 1*/
+		u64		start_addr:29;		/*Physical starting address*/
+		u64		pad1:3; /* should be zero */
+	} form;
+	u64 raw;
+} tx_cat_ptr;
+
+typedef struct tx_packet {
+	union {
+		tx_packet_hdr header;
+		tx_status_vector res;
+		u64 raw;
+	}header;
+	union {
+		tx_cat_ptr cat_buf[3];
+		char dt[120];
+	} data;
+} tx_packet;
+
+typedef union rx_status_vector {
+	struct {
+		u64		pad1:1;/*fill it with ones*/
+		u64		pad2:15;/*fill with 0*/
+		u64		ip_chk_sum:16;
+		u64		seq_num:5;
+		u64		mac_addr_match:1;
+		u64		mcast_addr_match:1;
+		u64		carrier_event_seen:1;
+		u64		bad_packet:1;
+		u64		long_event_seen:1;
+		u64		invalid_preamble:1;
+		u64		broadcast:1;
+		u64		multicast:1;
+		u64		crc_error:1;
+		u64		huh:1;/*???*/
+		u64		rx_code_violation:1;
+		u64		rx_len:16;
+	} parsed;
+	u64 raw;
+} rx_status_vector;
+
+typedef struct rx_packet {
+	rx_status_vector status;
+        u64 pad[3]; /* For whatever reason, there needs to be 4 double-word offset */
+        u16 pad2;
+	char buf[METH_RX_BUFF_SIZE-sizeof(rx_status_vector)-3*sizeof(u64)-sizeof(u16)];/* data */
+} rx_packet;
+
+typedef struct meth_regs {
+	u64		mac_ctrl;		/*0x00,rw,31:0*/
+	u64		int_flags;		/*0x08,rw,30:0*/
+	u64		dma_ctrl;		/*0x10,rw,15:0*/
+	u64		timer;			/*0x18,rw,5:0*/
+	u64		int_tx;			/*0x20,wo,0:0*/
+	u64		int_rx;			/*0x28,wo,9:4*/
+	struct {
+		u32 tx_info_pad;
+		u32 rptr:16,wptr:16;
+	}		tx_info;		/*0x30,rw,31:0*/
+	u64		tx_info_al;		/*0x38,rw,31:0*/
+	struct {
+		u32	rx_buff_pad1;
+		u32	rx_buff_pad2:8,
+			wptr:8,
+			rptr:8,
+			depth:8;
+	}		rx_buff;		/*0x40,ro,23:0*/
+	u64		rx_buff_al1;	/*0x48,ro,23:0*/
+	u64		rx_buff_al2;	/*0x50,ro,23:0*/
+	u64		int_update;		/*0x58,wo,31:0*/
+	u32		phy_data_pad;
+	u32		phy_data;		/*0x60,rw,16:0*/
+	u32		phy_reg_pad;
+	u32		phy_registers;	/*0x68,rw,9:0*/
+	u64		phy_trans_go;	/*0x70,wo,0:0*/
+	u64		backoff_seed;	/*0x78,wo,10:0*/
+	u64		imq_reserved[4];/*0x80,ro,64:0(x4)*/
+	/*===================================*/
+	u64		mac_addr;		/*0xA0,rw,47:0, I think it's MAC address, but I'm not sure*/
+	u64		mcast_addr;		/*0xA8,rw,47:0, This seems like secondary MAC address*/
+	u64		mcast_filter;	/*0xB0,rw,63:0*/
+	u64		tx_ring_base;	/*0xB8,rw,31:13*/
+	/* Following are read-only debugging info register */
+	u64		tx_pkt1_hdr;	/*0xC0,ro,63:0*/
+	u64		tx_pkt1_ptr[3];	/*0xC8,ro,63:0(x3)*/
+	u64		tx_pkt2_hdr;	/*0xE0,ro,63:0*/
+	u64		tx_pkt2_ptr[3];	/*0xE8,ro,63:0(x3)*/
+	/*===================================*/
+	u32		rx_pad;
+	u32		rx_fifo;
+	u64		reserved[31];
+}meth_regs;
+
+	/* Bits in METH_MAC */
+
+#define SGI_MAC_RESET		BIT(0)	/* 0: MAC110 active in run mode, 1: Global reset signal to MAC110 core is active */
+#define METH_PHY_FDX		BIT(1) /* 0: Disable full duplex, 1: Enable full duplex */
+#define METH_PHY_LOOP	BIT(2) /* 0: Normal operation, follows 10/100mbit and M10T/MII select, 1: loops internal MII bus */
+				       /*    selects ignored */
+#define METH_100MBIT		BIT(3) /* 0: 10meg mode, 1: 100meg mode */
+#define METH_PHY_MII		BIT(4) /* 0: MII selected, 1: SIA selected */
+				       /*   Note: when loopback is set this bit becomes collision control.  Setting this bit will */
+				       /*         cause a collision to be reported. */
+
+				       /* Bits 5 and 6 are used to determine the the Destination address filter mode */
+#define METH_ACCEPT_MY 0			/* 00: Accept PHY address only */
+#define METH_ACCEPT_MCAST 0x20	/* 01: Accept physical, broadcast, and multicast filter matches only */
+#define METH_ACCEPT_AMCAST 0x40	/* 10: Accept physical, broadcast, and all multicast packets */
+#define METH_PROMISC 0x60		/* 11: Promiscious mode */
+
+#define METH_PHY_LINK_FAIL	BIT(7) /* 0: Link failure detection disabled, 1: Hardware scans for link failure in PHY */
+
+#define METH_MAC_IPG	0x1ffff00
+
+#define METH_DEFAULT_IPG ((17<<15) | (11<<22) | (21<<8))
+						/* 0x172e5c00 */ /* 23, 23, 23 */ /*0x54A9500 *//*21,21,21*/
+				       /* Bits 8 through 14 are used to determine Inter-Packet Gap between "Back to Back" packets */
+				       /* The gap depends on the clock speed of the link, 80ns per increment for 100baseT, 800ns  */
+				       /* per increment for 10BaseT */
+
+				       /* Bits 15 through 21 are used to determine IPGR1 */
+
+				       /* Bits 22 through 28 are used to determine IPGR2 */
+
+#define METH_REV_SHIFT 29       /* Bits 29 through 31 are used to determine the revision */
+				       /* 000: Inital revision */
+				       /* 001: First revision, Improved TX concatenation */
+
+
+/* DMA control bits */
+#define METH_RX_OFFSET_SHIFT 12 /* Bits 12:14 of DMA control register indicate starting offset of packet data for RX operation */
+#define METH_RX_DEPTH_SHIFT 4 /* Bits 8:4 define RX fifo depth -- when # of RX fifo entries != depth, interrupt is generted */
+
+#define METH_DMA_TX_EN BIT(1) /* enable TX DMA */
+#define METH_DMA_TX_INT_EN BIT(0) /* enable TX Buffer Empty interrupt */
+#define METH_DMA_RX_EN BIT(15) /* Enable RX */
+#define METH_DMA_RX_INT_EN BIT(9) /* Enable interrupt on RX packet */
+
+
+/* RX status bits */
+
+#define METH_RX_ST_RCV_CODE_VIOLATION BIT(16)
+#define METH_RX_ST_DRBL_NBL BIT(17)
+#define METH_RX_ST_CRC_ERR BIT(18)
+#define METH_RX_ST_MCAST_PKT BIT(19)
+#define METH_RX_ST_BCAST_PKT BIT(20)
+#define METH_RX_ST_INV_PREAMBLE_CTX BIT(21)
+#define METH_RX_ST_LONG_EVT_SEEN BIT(22)
+#define METH_RX_ST_BAD_PACKET BIT(23)
+#define METH_RX_ST_CARRIER_EVT_SEEN BIT(24)
+#define METH_RX_ST_MCAST_FILTER_MATCH BIT(25)
+#define METH_RX_ST_PHYS_ADDR_MATCH BIT(26)
+
+#define METH_RX_STATUS_ERRORS \
+	( \
+	METH_RX_ST_RCV_CODE_VIOLATION| \
+	METH_RX_ST_CRC_ERR| \
+	METH_RX_ST_INV_PREAMBLE_CTX| \
+	METH_RX_ST_LONG_EVT_SEEN| \
+	METH_RX_ST_BAD_PACKET| \
+	METH_RX_ST_CARRIER_EVT_SEEN \
+	)
+	/* Bits in METH_INT */
+	/* Write _1_ to corresponding bit to clear */
+#define METH_INT_TX_EMPTY	BIT(0)	/* 0: No interrupt pending, 1: The TX ring buffer is empty */
+#define METH_INT_TX_PKT		BIT(1)	/* 0: No interrupt pending */
+					      	/* 1: A TX message had the INT request bit set, the packet has been sent. */
+#define METH_INT_TX_LINK_FAIL	BIT(2)	/* 0: No interrupt pending, 1: PHY has reported a link failure */
+#define METH_INT_MEM_ERROR	BIT(3)	/* 0: No interrupt pending */
+						/* 1: A memory error occurred durring DMA, DMA stopped, Fatal */
+#define METH_INT_TX_ABORT		BIT(4)	/* 0: No interrupt pending, 1: The TX aborted operation, DMA stopped, FATAL */
+#define METH_INT_RX_THRESHOLD	BIT(5)	/* 0: No interrupt pending, 1: Selected receive threshold condition Valid */
+#define METH_INT_RX_UNDERFLOW	BIT(6)	/* 0: No interrupt pending, 1: FIFO was empty, packet could not be queued */
+#define METH_INT_RX_OVERFLOW		BIT(7)	/* 0: No interrupt pending, 1: DMA FIFO Overflow, DMA stopped, FATAL */
+
+#define METH_INT_RX_RPTR_MASK 0x0001F00		/* Bits 8 through 12 alias of RX read-pointer */
+
+						/* Bits 13 through 15 are always 0. */
+
+#define METH_INT_TX_RPTR_MASK 0x1FF0000	        /* Bits 16 through 24 alias of TX read-pointer */
+
+#define METH_INT_SEQ_MASK    0x2E000000	        /* Bits 25 through 29 are the starting seq number for the message at the */
+						/* top of the queue */
+
+#define METH_ERRORS ( \
+	METH_INT_RX_OVERFLOW|	\
+	METH_INT_RX_UNDERFLOW|	\
+	METH_INT_MEM_ERROR|			\
+	METH_INT_TX_ABORT)
+
+#define METH_INT_MCAST_HASH		BIT(30) /* If RX DMA is enabled the hash select logic output is latched here */
+
+/* TX status bits */
+#define METH_TX_STATUS_DONE BIT(23) /* Packet was transmitted successfully */
+
+/* Tx command header bits */
+#define METH_TX_CMD_INT_EN BIT(24) /* Generate TX interrupt when packet is sent */
+
+/* Phy MDIO interface busy flag */
+#define MDIO_BUSY    BIT(16)
+#define MDIO_DATA_MASK 0xFFFF
+/* PHY defines */
+#define PHY_QS6612X    0x0181441    /* Quality TX */
+#define PHY_ICS1889    0x0015F41    /* ICS FX */
+#define PHY_ICS1890    0x0015F42    /* ICS TX */
+#define PHY_DP83840    0x20005C0    /* National TX */
diff -urN linux-2.5.73-bk3/drivers/net/pcmcia/3c574_cs.c linux-2.5.73-bk4/drivers/net/pcmcia/3c574_cs.c
--- linux-2.5.73-bk3/drivers/net/pcmcia/3c574_cs.c	2003-06-22 11:32:37.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/pcmcia/3c574_cs.c	2003-06-26 05:00:28.000000000 -0700
@@ -211,7 +211,6 @@
 
 struct el3_private {
 	dev_link_t link;
-	struct net_device dev;
 	dev_node_t node;
 	struct net_device_stats stats;
 	u16 advertising, partner;		/* NWay media advertisement */
@@ -291,13 +290,12 @@
 	flush_stale_links();
 
 	/* Create the PC card device object. */
-	lp = kmalloc(sizeof(*lp), GFP_KERNEL);
-	if (!lp)
+	dev = alloc_etherdev(sizeof(struct el3_private));
+	if (!dev)
 		return NULL;
-		
-	memset(lp, 0, sizeof(*lp));
-	link = &lp->link; dev = &lp->dev;
-	link->priv = dev->priv = link->irq.Instance = lp;
+	lp = dev->priv;
+	link = &lp->link;
+	link->priv = dev;
 	
 	init_timer(&link->release);
 	link->release.function = &tc574_release;
@@ -312,6 +310,7 @@
 		for (i = 0; i < 4; i++)
 			link->irq.IRQInfo2 |= 1 << irq_list[i];
 	link->irq.Handler = &el3_interrupt;
+	link->irq.Instance = dev;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
@@ -323,7 +322,6 @@
 	dev->get_stats = &el3_get_stats;
 	dev->do_ioctl = &el3_ioctl;
 	dev->set_multicast_list = &set_rx_mode;
-	ether_setup(dev);
 	dev->open = &el3_open;
 	dev->stop = &el3_close;
 #ifdef HAVE_TX_TIMEOUT
@@ -364,7 +362,7 @@
 
 static void tc574_detach(dev_link_t *link)
 {
-	struct el3_private *lp = link->priv;
+	struct net_device *dev = link->priv;
 	dev_link_t **linkp;
 
 	DEBUG(0, "3c574_detach(0x%p)\n", link);
@@ -390,8 +388,8 @@
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
 	if (link->dev)
-		unregister_netdev(&lp->dev);
-	kfree(lp);
+		unregister_netdev(dev);
+	kfree(dev);
 
 } /* tc574_detach */
 
@@ -407,8 +405,8 @@
 static void tc574_config(dev_link_t *link)
 {
 	client_handle_t handle = link->handle;
-	struct el3_private *lp = link->priv;
-	struct net_device *dev = &lp->dev;
+	struct net_device *dev = link->priv;
+	struct el3_private *lp = dev->priv;
 	tuple_t tuple;
 	cisparse_t parse;
 	unsigned short buf[32];
@@ -599,8 +597,7 @@
 					   event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	struct el3_private *lp = link->priv;
-	struct net_device *dev = &lp->dev;
+	struct net_device *dev = link->priv;
 
 	DEBUG(1, "3c574_event(0x%06x)\n", event);
 
@@ -856,7 +853,7 @@
 	
 	tc574_reset(dev);
 	lp->media.function = &media_check;
-	lp->media.data = (unsigned long)lp;
+	lp->media.data = (unsigned long) dev;
 	lp->media.expires = jiffies + HZ;
 	add_timer(&lp->media);
 	
@@ -939,8 +936,8 @@
 /* The EL3 interrupt handler. */
 static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct el3_private *lp = dev_id;
-	struct net_device *dev = &lp->dev;
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct el3_private *lp = dev->priv;
 	ioaddr_t ioaddr, status;
 	int work_budget = max_interrupt_work;
 	int handled = 0;
@@ -1032,8 +1029,8 @@
 */
 static void media_check(unsigned long arg)
 {
-	struct el3_private *lp = (struct el3_private *)arg;
-	struct net_device *dev = &lp->dev;
+	struct net_device *dev = (struct net_device *) arg;
+	struct el3_private *lp = dev->priv;
 	ioaddr_t ioaddr = dev->base_addr;
 	unsigned long flags;
 	unsigned short /* cable, */ media, partner;
diff -urN linux-2.5.73-bk3/drivers/net/pcmcia/3c589_cs.c linux-2.5.73-bk4/drivers/net/pcmcia/3c589_cs.c
--- linux-2.5.73-bk3/drivers/net/pcmcia/3c589_cs.c	2003-06-22 11:33:18.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/pcmcia/3c589_cs.c	2003-06-26 05:00:28.000000000 -0700
@@ -106,7 +106,6 @@
 
 struct el3_private {
     dev_link_t		link;
-    struct net_device	dev;
     dev_node_t 		node;
     struct net_device_stats stats;
     /* For transceiver monitoring */
@@ -213,14 +212,14 @@
     flush_stale_links();
     
     /* Create new ethernet device */
-    lp = kmalloc(sizeof(*lp), GFP_KERNEL);
-    if (!lp) return NULL;
-    memset(lp, 0, sizeof(*lp));
+    dev = alloc_etherdev(sizeof(struct el3_private));
+    if (!dev)
+	 return NULL;
+    lp = dev->priv;
+    link = &lp->link;
+    link->priv = dev;
+
     spin_lock_init(&lp->lock);
-    
-    link = &lp->link; dev = &lp->dev;
-    link->priv = dev->priv = link->irq.Instance = lp;
-    
     init_timer(&link->release);
     link->release.function = &tc589_release;
     link->release.data = (unsigned long)link;
@@ -234,6 +233,7 @@
 	for (i = 0; i < 4; i++)
 	    link->irq.IRQInfo2 |= 1 << irq_list[i];
     link->irq.Handler = &el3_interrupt;
+    link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
@@ -246,7 +246,6 @@
     dev->set_config = &el3_config;
     dev->get_stats = &el3_get_stats;
     dev->set_multicast_list = &set_multicast_list;
-    ether_setup(dev);
     dev->open = &el3_open;
     dev->stop = &el3_close;
 #ifdef HAVE_TX_TIMEOUT
@@ -288,7 +287,7 @@
 
 static void tc589_detach(dev_link_t *link)
 {
-    struct el3_private *lp = link->priv;
+    struct net_device *dev = link->priv;
     dev_link_t **linkp;
     
     DEBUG(0, "3c589_detach(0x%p)\n", link);
@@ -314,8 +313,8 @@
     /* Unlink device structure, free bits */
     *linkp = link->next;
     if (link->dev)
-	unregister_netdev(&lp->dev);
-    kfree(lp);
+	unregister_netdev(dev);
+    kfree(dev);
     
 } /* tc589_detach */
 
@@ -333,8 +332,8 @@
 static void tc589_config(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
-    struct el3_private *lp = link->priv;
-    struct net_device *dev = &lp->dev;
+    struct net_device *dev = link->priv;
+    struct el3_private *lp = dev->priv;
     tuple_t tuple;
     cisparse_t parse;
     u16 buf[32], *phys_addr;
@@ -487,8 +486,7 @@
 		       event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct el3_private *lp = link->priv;
-    struct net_device *dev = &lp->dev;
+    struct net_device *dev = link->priv;
     
     DEBUG(1, "3c589_event(0x%06x)\n", event);
     
@@ -738,7 +736,7 @@
     tc589_reset(dev);
     init_timer(&lp->media);
     lp->media.function = &media_check;
-    lp->media.data = (unsigned long)lp;
+    lp->media.data = (unsigned long) dev;
     lp->media.expires = jiffies + HZ;
     add_timer(&lp->media);
 
@@ -818,8 +816,8 @@
 /* The EL3 interrupt handler. */
 static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-    struct el3_private *lp = dev_id;
-    struct net_device *dev = &lp->dev;
+    struct net_device *dev = (struct net_device *) dev_id;
+    struct el3_private *lp = dev->priv;
     ioaddr_t ioaddr, status;
     int i = 0, handled = 1;
     
@@ -903,8 +901,8 @@
 
 static void media_check(unsigned long arg)
 {
-    struct el3_private *lp = (struct el3_private *)(arg);
-    struct net_device *dev = &lp->dev;
+    struct net_device *dev = (struct net_device *)(arg);
+    struct el3_private *lp = dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
     u16 media, errs;
     unsigned long flags;
diff -urN linux-2.5.73-bk3/drivers/net/pcmcia/fmvj18x_cs.c linux-2.5.73-bk4/drivers/net/pcmcia/fmvj18x_cs.c
--- linux-2.5.73-bk3/drivers/net/pcmcia/fmvj18x_cs.c	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/pcmcia/fmvj18x_cs.c	2003-06-26 05:00:28.000000000 -0700
@@ -130,7 +130,6 @@
 */
 typedef struct local_info_t {
     dev_link_t link;
-    struct net_device dev;
     dev_node_t node;
     struct net_device_stats stats;
     long open_time;
@@ -273,11 +272,12 @@
     flush_stale_links();
 
     /* Make up a FMVJ18x specific data structure */
-    lp = kmalloc(sizeof(*lp), GFP_KERNEL);
-    if (!lp) return NULL;
-    memset(lp, 0, sizeof(*lp));
-    link = &lp->link; dev = &lp->dev;
-    link->priv = dev->priv = link->irq.Instance = lp;
+    dev = alloc_etherdev(sizeof(local_info_t));
+    if (!dev)
+	return NULL;
+    lp = dev->priv;
+    link = &lp->link;
+    link->priv = dev;
 
     init_timer(&link->release);
     link->release.function = &fmvj18x_release;
@@ -297,6 +297,7 @@
 	for (i = 0; i < 4; i++)
 	    link->irq.IRQInfo2 |= 1 << irq_list[i];
     link->irq.Handler = &fjn_interrupt;
+    link->irq.Instance = dev;
     
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
@@ -309,7 +310,6 @@
     dev->set_config = &fjn_config;
     dev->get_stats = &fjn_get_stats;
     dev->set_multicast_list = &set_rx_mode;
-    ether_setup(dev);
     dev->open = &fjn_open;
     dev->stop = &fjn_close;
 #ifdef HAVE_TX_TIMEOUT
@@ -344,7 +344,7 @@
 
 static void fmvj18x_detach(dev_link_t *link)
 {
-    local_info_t *lp = link->priv;
+    struct net_device *dev = link->priv;
     dev_link_t **linkp;
     
     DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
@@ -371,8 +371,8 @@
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     if (link->dev)
-	unregister_netdev(&lp->dev);
-    kfree(lp);
+	unregister_netdev(dev);
+    kfree(dev);
     
 } /* fmvj18x_detach */
 
@@ -423,8 +423,8 @@
 static void fmvj18x_config(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
-    local_info_t *lp = link->priv;
-    struct net_device *dev = &lp->dev;
+    struct net_device *dev = link->priv;
+    local_info_t *lp = dev->priv;
     tuple_t tuple;
     cisparse_t parse;
     u_short buf[32];
@@ -704,8 +704,7 @@
     memreq_t mem;
     u_char *base;
     int i, j;
-    local_info_t *lp = link->priv;
-    struct net_device *dev = &lp->dev;
+    struct net_device *dev = link->priv;
     ioaddr_t ioaddr;
 
     /* Allocate a small memory window */
@@ -776,8 +775,7 @@
 			  event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    local_info_t *lp = link->priv;
-    struct net_device *dev = &lp->dev;
+    struct net_device *dev = link->priv;
 
     DEBUG(1, "fmvj18x_event(0x%06x)\n", event);
     
@@ -847,8 +845,8 @@
 
 static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-    local_info_t *lp = dev_id;
-    struct net_device *dev = &lp->dev;
+    struct net_device *dev = dev_id;
+    local_info_t *lp = dev->priv;
     ioaddr_t ioaddr;
     unsigned short tx_stat, rx_stat;
 
diff -urN linux-2.5.73-bk3/drivers/net/pcmcia/nmclan_cs.c linux-2.5.73-bk4/drivers/net/pcmcia/nmclan_cs.c
--- linux-2.5.73-bk3/drivers/net/pcmcia/nmclan_cs.c	2003-06-22 11:32:32.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/pcmcia/nmclan_cs.c	2003-06-26 05:00:28.000000000 -0700
@@ -359,7 +359,6 @@
 
 typedef struct _mace_private {
     dev_link_t link;
-    struct net_device dev;
     dev_node_t node;
     struct net_device_stats linux_stats; /* Linux statistics counters */
     mace_statistics mace_stats; /* MACE chip statistics counters */
@@ -476,12 +475,13 @@
     flush_stale_links();
 
     /* Create new ethernet device */
-    lp = kmalloc(sizeof(*lp), GFP_KERNEL);
-    if (!lp) return NULL;
-    memset(lp, 0, sizeof(*lp));
-    link = &lp->link; dev = &lp->dev;
-    link->priv = dev->priv = link->irq.Instance = lp;
-
+    dev = alloc_etherdev(sizeof(mace_private));
+    if (!dev)
+	return NULL;
+    lp = dev->priv;
+    link = &lp->link;
+    link->priv = dev;
+    
     init_timer(&link->release);
     link->release.function = &nmclan_release;
     link->release.data = (u_long)link;
@@ -496,6 +496,7 @@
 	for (i = 0; i < 4; i++)
 	    link->irq.IRQInfo2 |= 1 << irq_list[i];
     link->irq.Handler = &mace_interrupt;
+    link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
@@ -510,7 +511,6 @@
     dev->get_stats = &mace_get_stats;
     dev->set_multicast_list = &set_multicast_list;
     dev->do_ioctl = &mace_ioctl;
-    ether_setup(dev);
     dev->open = &mace_open;
     dev->stop = &mace_close;
 #ifdef HAVE_TX_TIMEOUT
@@ -550,7 +550,7 @@
 
 static void nmclan_detach(dev_link_t *link)
 {
-    mace_private *lp = link->priv;
+    struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
     DEBUG(0, "nmclan_detach(0x%p)\n", link);
@@ -576,8 +576,8 @@
     /* Unlink device structure, free bits */
     *linkp = link->next;
     if (link->dev)
-	unregister_netdev(&lp->dev);
-    kfree(lp);
+	unregister_netdev(dev);
+    kfree(dev);
 
 } /* nmclan_detach */
 
@@ -710,8 +710,8 @@
 static void nmclan_config(dev_link_t *link)
 {
   client_handle_t handle = link->handle;
-  mace_private *lp = link->priv;
-  struct net_device *dev = &lp->dev;
+  struct net_device *dev = link->priv;;
+  mace_private *lp = dev->priv;
   tuple_t tuple;
   cisparse_t parse;
   u_char buf[64];
@@ -836,8 +836,7 @@
 		       event_callback_args_t *args)
 {
   dev_link_t *link = args->client_data;
-  mace_private *lp = link->priv;
-  struct net_device *dev = &lp->dev;
+  struct net_device *dev = link->priv;
 
   DEBUG(1, "nmclan_event(0x%06x)\n", event);
 
@@ -1145,8 +1144,8 @@
 ---------------------------------------------------------------------------- */
 static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-  mace_private *lp = (mace_private *)dev_id;
-  struct net_device *dev = &lp->dev;
+  struct net_device *dev = (struct net_device *) dev_id;
+  mace_private *lp = dev->priv;
   ioaddr_t ioaddr = dev->base_addr;
   int status;
   int IntrCnt = MACE_MAX_IR_ITERATIONS;
diff -urN linux-2.5.73-bk3/drivers/net/pcmcia/smc91c92_cs.c linux-2.5.73-bk4/drivers/net/pcmcia/smc91c92_cs.c
--- linux-2.5.73-bk3/drivers/net/pcmcia/smc91c92_cs.c	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/pcmcia/smc91c92_cs.c	2003-06-26 05:00:28.000000000 -0700
@@ -113,7 +113,6 @@
 
 struct smc_private {
     dev_link_t			link;
-    struct net_device		dev;
     spinlock_t			lock;
     u_short			manfid;
     u_short			cardid;
@@ -344,10 +343,13 @@
     flush_stale_links();
 
     /* Create new ethernet device */
-    smc = kmalloc(sizeof(struct smc_private), GFP_KERNEL);
-    if (!smc) return NULL;
-    memset(smc, 0, sizeof(struct smc_private));
-    link = &smc->link; dev = &smc->dev;
+    dev = alloc_etherdev(sizeof(struct smc_private));
+    if (!dev)
+	return NULL;
+    smc = dev->priv;
+    link = &smc->link;
+    link->priv = dev;
+
     spin_lock_init(&smc->lock);
     init_timer(&link->release);
     link->release.function = &smc91c92_release;
@@ -363,6 +365,7 @@
 	for (i = 0; i < 4; i++)
 	    link->irq.IRQInfo2 |= 1 << irq_list[i];
     link->irq.Handler = &smc_interrupt;
+    link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
@@ -373,7 +376,6 @@
     dev->get_stats = &smc_get_stats;
     dev->set_config = &s9k_config;
     dev->set_multicast_list = &set_rx_mode;
-    ether_setup(dev);
     dev->open = &smc_open;
     dev->stop = &smc_close;
     dev->do_ioctl = &smc_ioctl;
@@ -381,7 +383,6 @@
     dev->tx_timeout = smc_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
-    dev->priv = link->priv = link->irq.Instance = smc;
 
     smc->mii_if.dev = dev;
     smc->mii_if.mdio_read = mdio_read;
@@ -421,7 +422,7 @@
 
 static void smc91c92_detach(dev_link_t *link)
 {
-    struct smc_private *smc = link->priv;
+    struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
     DEBUG(0, "smc91c92_detach(0x%p)\n", link);
@@ -447,8 +448,8 @@
     /* Unlink device structure, free bits */
     *linkp = link->next;
     if (link->dev)
-	unregister_netdev(&smc->dev);
-    kfree(smc);
+	unregister_netdev(dev);
+    kfree(dev);
 
 } /* smc91c92_detach */
 
@@ -502,7 +503,8 @@
 
 static int mhz_3288_power(dev_link_t *link)
 {
-    struct smc_private *smc = link->priv;
+    struct net_device *dev = link->priv;
+    struct smc_private *smc = dev->priv;
     u_char tmp;
 
     /* Read the ISR twice... */
@@ -523,8 +525,8 @@
 
 static int mhz_mfc_config(dev_link_t *link)
 {
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
+    struct smc_private *smc = dev->priv;
     tuple_t tuple;
     cisparse_t parse;
     u_char buf[255];
@@ -590,8 +592,7 @@
 static int mhz_setup(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
     tuple_t tuple;
     cisparse_t parse;
     u_char buf[255], *station_addr;
@@ -638,8 +639,8 @@
 
 static void mot_config(dev_link_t *link)
 {
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
+    struct smc_private *smc = dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
     ioaddr_t iouart = link->io.BasePort2;
 
@@ -659,8 +660,7 @@
 
 static int mot_setup(dev_link_t *link)
 {
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
     ioaddr_t ioaddr = dev->base_addr;
     int i, wait, loop;
     u_int addr;
@@ -694,8 +694,7 @@
 
 static int smc_config(dev_link_t *link)
 {
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
     tuple_t tuple;
     cisparse_t parse;
     u_char buf[255];
@@ -727,8 +726,7 @@
 static int smc_setup(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
     tuple_t tuple;
     cisparse_t parse;
     cistpl_lan_node_id_t *node_id;
@@ -755,7 +753,6 @@
 	    return 0;
 	}
     }
-
     /* Try the third string in the Version 1 Version/ID tuple. */
     tuple.DesiredTuple = CISTPL_VERS_1;
     if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)
@@ -771,8 +768,7 @@
 
 static int osi_config(dev_link_t *link)
 {
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
     static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
     int i, j;
 
@@ -806,8 +802,7 @@
 static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
 {
     client_handle_t handle = link->handle;
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
     tuple_t tuple;
     u_char buf[255];
     int i;
@@ -862,8 +857,7 @@
 
 static int check_sig(dev_link_t *link)
 {
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
     ioaddr_t ioaddr = dev->base_addr;
     int width;
     u_short s;
@@ -921,8 +915,8 @@
 static void smc91c92_config(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
+    struct smc_private *smc = dev->priv;
     tuple_t tuple;
     cisparse_t parse;
     u_short buf[32];
@@ -1090,7 +1084,6 @@
 static void smc91c92_release(u_long arg)
 {
     dev_link_t *link = (dev_link_t *)arg;
-    struct smc_private *smc = link->priv;
 
     DEBUG(0, "smc91c92_release(0x%p)\n", link);
 
@@ -1105,6 +1098,8 @@
     CardServices(ReleaseIO, link->handle, &link->io);
     CardServices(ReleaseIRQ, link->handle, &link->irq);
     if (link->win) {
+	struct net_device *dev = link->priv;
+	struct smc_private *smc = dev->priv;
 	iounmap(smc->base);
 	CardServices(ReleaseWindow, link->win);
     }
@@ -1126,8 +1121,8 @@
 			  event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct smc_private *smc = link->priv;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = link->priv;
+    struct smc_private *smc = dev->priv;
     int i;
 
     DEBUG(1, "smc91c92_event(0x%06x)\n", event);
@@ -1302,7 +1297,7 @@
     smc_reset(dev);
     init_timer(&smc->media);
     smc->media.function = &media_check;
-    smc->media.data = (u_long)smc;
+    smc->media.data = (u_long) dev;
     smc->media.expires = jiffies + HZ;
     add_timer(&smc->media);
 
@@ -1576,8 +1571,8 @@
 
 static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-    struct smc_private *smc = dev_id;
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = dev_id;
+    struct smc_private *smc = dev->priv;
     ioaddr_t ioaddr;
     u_short saved_bank, saved_pointer, mask, status;
     unsigned int handled = 1;
@@ -1967,8 +1962,8 @@
 
 static void media_check(u_long arg)
 {
-    struct smc_private *smc = (struct smc_private *)(arg);
-    struct net_device *dev = &smc->dev;
+    struct net_device *dev = (struct net_device *) arg;
+    struct smc_private *smc = dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
     u_short i, media, saved_bank;
     u_short link;
diff -urN linux-2.5.73-bk3/drivers/net/sb1250-mac.c linux-2.5.73-bk4/drivers/net/sb1250-mac.c
--- linux-2.5.73-bk3/drivers/net/sb1250-mac.c	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/sb1250-mac.c	2003-06-26 05:00:28.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Broadcom Corporation
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -17,17 +17,21 @@
  */
 
 /*
-  This driver is designed for the Broadcom BCM12500 SOC chip's built-in
+  This driver is designed for the Broadcom SiByte SOC built-in
   Ethernet controllers.
   
-  The author may be reached as mpl@broadcom.com
+  Written by Mitch Lichtenberg at Broadcom Corp.
 */
 
 
+
+#define CONFIG_SBMAC_COALESCE
+
 /* A few user-configurable values.
    These may be modified when a driver module is loaded. */
 
 static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
+static int noisy_mii = 1;		/* mii status msgs */
 
 /* Used to pass the media type, etc.
    Both 'options[]' and 'full_duplex[]' should exist for driver
@@ -41,6 +45,10 @@
 static int full_duplex[MAX_UNITS] = {-1, -1, -1};
 #endif
 
+#ifdef CONFIG_SBMAC_COALESCE
+static int int_pktcnt = 0;
+static int int_timeout = 0;
+#endif
 
 /* Operational parameters that usually are not changed. */
 
@@ -59,22 +67,21 @@
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/config.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
-#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/64bit.h>
+#include <asm/cache.h>
 
 /* This is only here until the firmware is ready.  In that case,
    the firmware leaves the ethernet address in the register for us. */
-#ifdef CONFIG_SWARM_STANDALONE
+#ifdef CONFIG_SIBYTE_STANDALONE
 #define SBMAC_ETH0_HWADDR "40:00:00:00:01:00"
 #define SBMAC_ETH1_HWADDR "40:00:00:00:01:01"
 #define SBMAC_ETH2_HWADDR "40:00:00:00:01:02"
@@ -84,23 +91,29 @@
 /* These identify the driver base version and may not be removed. */
 #if 0
 static char version1[] __devinitdata =
-"sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg (mpl@broadcom.com)\n";
+"sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg\n";
 #endif
 
 
 
-MODULE_AUTHOR("Mitch Lichtenberg (mpl@broadcom.com)");
-MODULE_DESCRIPTION("Broadcom BCM12500 SOC GB Ethernet driver");
+MODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)");
+MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver");
 MODULE_PARM(debug, "i");
+MODULE_PARM(noisy_mii, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 
+MODULE_PARM(int_pktcnt, "i");
+MODULE_PARM(int_timeout, "i");
 
+#include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_defs.h>
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_mac.h>
 #include <asm/sibyte/sb1250_dma.h>
 #include <asm/sibyte/sb1250_int.h>
+#include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/64bit.h>
 
 
 /**********************************************************************
@@ -109,8 +122,6 @@
 
 
 typedef unsigned long sbmac_port_t;
-typedef uint64_t sbmac_physaddr_t;
-typedef uint64_t sbmac_enetaddr_t;
 
 typedef enum { sbmac_speed_auto, sbmac_speed_10,
 	       sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t;
@@ -134,24 +145,19 @@
 			  (d)->sbdma_dscrtable : (d)->f+1)
 
 
-#define CACHELINESIZE 32
-#define NUMCACHEBLKS(x) (((x)+CACHELINESIZE-1)/CACHELINESIZE)
-#define KMALLOC(x) kmalloc((x),GFP_KERNEL)
-#define KFREE(x) kfree(x)
-#define KVTOPHYS(x) virt_to_bus((void *)(x))
+#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)
 
+#define SBMAC_READCSR(t)	in64((unsigned long)t)
+#define SBMAC_WRITECSR(t,v)	out64(v, (unsigned long)t)
  
-#define SBMAC_READCSR(t)    (in64((unsigned long)(t)))
-#define SBMAC_WRITECSR(t,v) (out64(v, (unsigned long)(t)))
-
-#define PKSEG1(x) ((sbmac_port_t) KSEG1ADDR(x))
 
 #define SBMAC_MAX_TXDESCR	32
 #define SBMAC_MAX_RXDESCR	32
 
 #define ETHER_ALIGN	2
 #define ETHER_ADDR_LEN	6
-#define ENET_PACKET_SIZE	1518
+#define ENET_PACKET_SIZE	1518 
+/*#define ENET_PACKET_SIZE	9216 */ 
 
 /**********************************************************************
  *  DMA Descriptor structure
@@ -163,7 +169,6 @@
 } sbdmadscr_t;
 
 typedef unsigned long paddr_t;
-typedef unsigned long vaddr_t;
 
 /**********************************************************************
  *  DMA Controller structure
@@ -178,8 +183,13 @@
 	
 	struct sbmac_softc *sbdma_eth;	        /* back pointer to associated MAC */
 	int              sbdma_channel;	/* channel number */
-	int		     sbdma_txdir;       /* direction (1=transmit) */
-	int		     sbdma_maxdescr;	/* total # of descriptors in ring */
+	int		 sbdma_txdir;       /* direction (1=transmit) */
+	int		 sbdma_maxdescr;	/* total # of descriptors in ring */
+#ifdef CONFIG_SBMAC_COALESCE
+	int		 sbdma_int_pktcnt;  /* # descriptors rx/tx before interrupt*/
+	int		 sbdma_int_timeout; /* # usec rx/tx interrupt */
+#endif
+
 	sbmac_port_t     sbdma_config0;	/* DMA config register 0 */
 	sbmac_port_t     sbdma_config1;	/* DMA config register 1 */
 	sbmac_port_t     sbdma_dscrbase;	/* Descriptor base address */
@@ -198,7 +208,6 @@
 	paddr_t          sbdma_dscrtable_phys; /* and also the phys addr */
 	sbdmadscr_t     *sbdma_addptr;	/* next dscr for sw to add */
 	sbdmadscr_t     *sbdma_remptr;	/* next dscr for sw to remove */
-	
 } sbmacdma_t;
 
 
@@ -218,10 +227,10 @@
 	struct net_device_stats sbm_stats; 
 	int sbm_devflags;			/* current device flags */
 
-        int	     sbm_phy_oldbmsr;
-        int	     sbm_phy_oldanlpar;
-        int	     sbm_phy_oldk1stsr;
-        int          sbm_phy_oldlinkstat;
+	int	     sbm_phy_oldbmsr;
+	int	     sbm_phy_oldanlpar;
+	int	     sbm_phy_oldk1stsr;
+	int	     sbm_phy_oldlinkstat;
 	int sbm_buffersize;
 	
 	unsigned char sbm_phys[2];
@@ -230,7 +239,7 @@
 	 * Controller-specific things
 	 */
 	
-	sbmac_port_t     sbm_base;          /* MAC's base address */
+	unsigned long	sbm_base;          /* MAC's base address */
 	sbmac_state_t    sbm_state;         /* current state */
 	
 	sbmac_port_t     sbm_macenable;	/* MAC Enable Register */
@@ -246,11 +255,12 @@
 	sbmac_duplex_t   sbm_duplex;	/* current duplex */
 	sbmac_fc_t       sbm_fc;		/* current flow control setting */
 	
-	u_char           sbm_hwaddr[ETHER_ADDR_LEN];
+	unsigned char    sbm_hwaddr[ETHER_ADDR_LEN];
 	
 	sbmacdma_t       sbm_txdma;		/* for now, only use channel 0 */
 	sbmacdma_t       sbm_rxdma;
-	
+	int              rx_hw_checksum;
+	int 		 sbe_idx;
 };
 
 
@@ -267,7 +277,7 @@
 			  int chan,
 			  int txrx,
 			  int maxdescr);
-static void sbdma_channel_start(sbmacdma_t *d);
+static void sbdma_channel_start(sbmacdma_t *d, int rxtx);
 static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *m);
 static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *m);
 static void sbdma_emptyring(sbmacdma_t *d);
@@ -279,12 +289,11 @@
 static void sbmac_channel_stop(struct sbmac_softc *s);
 static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *,sbmac_state_t);
 static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff);
-/*static void sbmac_init_and_start(struct sbmac_softc *sc);*/
 static uint64_t sbmac_addr2reg(unsigned char *ptr);
 static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs);
 static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);
 static void sbmac_setmulti(struct sbmac_softc *sc);
-static int sbmac_init(struct net_device *dev);
+static int sbmac_init(struct net_device *dev, int idx);
 static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed);
 static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc);
 
@@ -308,6 +317,8 @@
  *  Globals
  ********************************************************************* */
 
+static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
+
 
 /**********************************************************************
  *  MDIO constants
@@ -328,8 +339,8 @@
 #define BMCR_DUPLEX    0x0100
 #define BMCR_COLTEST   0x0080
 #define BMCR_SPEED1    0x0040
-#define BMCR_SPEED1000 (BMCR_SPEED1|BMCR_SPEED0)
-#define BMCR_SPEED100  (BMCR_SPEED0)
+#define BMCR_SPEED1000	BMCR_SPEED1
+#define BMCR_SPEED100	BMCR_SPEED0
 #define BMCR_SPEED10 	0
 
 #define BMSR_100BT4	0x8000
@@ -437,6 +448,8 @@
 
 #define M_MAC_MDIO_DIR_OUTPUT	0		/* for clarity */
 
+#define ENABLE 		1
+#define DISABLE		0
 
 /**********************************************************************
  *  SBMAC_MII_SYNC(s)
@@ -490,7 +503,8 @@
 	curmask = 1 << (bitcnt - 1);
 	
 	for (i = 0; i < bitcnt; i++) {
-		if (data & curmask) bits |= M_MAC_MDIO_OUT;
+		if (data & curmask)
+			bits |= M_MAC_MDIO_OUT;
 		else bits &= ~M_MAC_MDIO_OUT;
 		SBMAC_WRITECSR(s->sbm_mdio,bits);
 		SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC);
@@ -571,7 +585,8 @@
 		regval <<= 1;
 		
 		if (error == 0) {
-			if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN) regval |= 1;
+			if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN)
+				regval |= 1;
 		}
 		
 		SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC);
@@ -581,7 +596,8 @@
 	/* Switch back to output */
 	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT);
 	
-	if (error == 0) return regval;
+	if (error == 0)
+		return regval;
 	return 0;
 }
 
@@ -651,20 +667,68 @@
 	d->sbdma_channel   = chan;
 	d->sbdma_txdir     = txrx;
 	
+#if 0
+	/* RMON clearing */
+	s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
+#endif
+
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)), 0);
+	SBMAC_WRITECSR(KSEG1ADDR(
+	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)), 0);
+
 	/* 
 	 * initialize register pointers 
 	 */
 	
 	d->sbdma_config0 = 
-		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0));
+		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0);
 	d->sbdma_config1 = 
-		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0));
+		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1);
 	d->sbdma_dscrbase = 
-		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE));
+		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE);
 	d->sbdma_dscrcnt = 
-		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT));
+		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT);
 	d->sbdma_curdscr = 	
-		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR));
+		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR);
 	
 	/*
 	 * Allocate memory for the ring
@@ -673,23 +737,41 @@
 	d->sbdma_maxdescr = maxdescr;
 	
 	d->sbdma_dscrtable = (sbdmadscr_t *) 
-		KMALLOC(d->sbdma_maxdescr*sizeof(sbdmadscr_t));
+		kmalloc(d->sbdma_maxdescr*sizeof(sbdmadscr_t), GFP_KERNEL);
 	
 	memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t));
 	
 	d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
 	
-	d->sbdma_dscrtable_phys = KVTOPHYS(d->sbdma_dscrtable);
+	d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable);
 	
 	/*
 	 * And context table
 	 */
 	
 	d->sbdma_ctxtable = (struct sk_buff **) 
-		KMALLOC(d->sbdma_maxdescr*sizeof(struct sk_buff *));
+		kmalloc(d->sbdma_maxdescr*sizeof(struct sk_buff *), GFP_KERNEL);
 	
 	memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *));
 	
+#ifdef CONFIG_SBMAC_COALESCE
+	/*
+	 * Setup Rx/Tx DMA coalescing defaults
+	 */
+
+	if ( int_pktcnt ) {
+		d->sbdma_int_pktcnt = int_pktcnt;
+	} else {
+		d->sbdma_int_pktcnt = 1;
+	}
+	
+	if ( int_timeout ) {
+		d->sbdma_int_timeout = int_timeout;
+	} else {
+		d->sbdma_int_timeout = 0;
+	}
+#endif
+
 }
 
 /**********************************************************************
@@ -699,33 +781,75 @@
  *  
  *  Input parameters: 
  *  	   d - DMA channel to init (context must be previously init'd
+ *         rxtx - DMA_RX or DMA_TX depending on what type of channel
  *  	   
  *  Return value:
  *  	   nothing
  ********************************************************************* */
 
-static void sbdma_channel_start(sbmacdma_t *d)
+static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
 {
 	/*
 	 * Turn on the DMA channel
 	 */
 	
+#ifdef CONFIG_SBMAC_COALESCE
+	SBMAC_WRITECSR(d->sbdma_config1,
+		       V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
+		       0);
+	SBMAC_WRITECSR(d->sbdma_config0,
+		       M_DMA_EOP_INT_EN |
+		       V_DMA_RINGSZ(d->sbdma_maxdescr) |
+		       V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) |
+		       0);
+#else
 	SBMAC_WRITECSR(d->sbdma_config1,0);
-	
-	SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
-	
 	SBMAC_WRITECSR(d->sbdma_config0,
 		       V_DMA_RINGSZ(d->sbdma_maxdescr) |
 		       0);
-	
+#endif
+
+	SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
+
 	/*
 	 * Initialize ring pointers
 	 */
-	
+
 	d->sbdma_addptr = d->sbdma_dscrtable;
 	d->sbdma_remptr = d->sbdma_dscrtable;
 }
 
+/**********************************************************************
+ *  SBDMA_CHANNEL_STOP(d)
+ *  
+ *  Initialize the hardware registers for a DMA channel.
+ *  
+ *  Input parameters: 
+ *  	   d - DMA channel to init (context must be previously init'd
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbdma_channel_stop(sbmacdma_t *d)
+{
+	/*
+	 * Turn off the DMA channel
+	 */
+	
+	SBMAC_WRITECSR(d->sbdma_config1,0);
+	
+	SBMAC_WRITECSR(d->sbdma_dscrbase,0);
+	
+	SBMAC_WRITECSR(d->sbdma_config0,0);
+	
+	/*
+	 * Zero ring pointers
+	 */
+	
+	d->sbdma_addptr = 0;
+	d->sbdma_remptr = 0;
+}
 
 static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
 {
@@ -777,7 +901,7 @@
 	if (nextdsc == d->sbdma_remptr) {
 		return -ENOSPC;
 	}
-	
+
 	/* 
 	 * Allocate a sk_buff if we don't already have one.  
 	 * If we do have an sk_buff, reset it so that it's empty.
@@ -788,25 +912,25 @@
 	 *
 	 *    1. the data does not start in the middle of a cache line.
 	 *    2. The data does not end in the middle of a cache line
-	 * 	  3. The buffer can be aligned such that the IP addresses are 
+	 *    3. The buffer can be aligned such that the IP addresses are 
 	 *       naturally aligned.
 	 *
-	 *  Remember, the SB1250's MAC writes whole cache lines at a time,
+	 *  Remember, the SOCs MAC writes whole cache lines at a time,
 	 *  without reading the old contents first.  So, if the sk_buff's
-	 *  data portion starts in the middle of a cache line, the SB1250
+	 *  data portion starts in the middle of a cache line, the SOC
 	 *  DMA will trash the beginning (and ending) portions.
 	 */
 	
 	if (sb == NULL) {
-		sb_new = dev_alloc_skb(ENET_PACKET_SIZE + CACHELINESIZE*2 + ETHER_ALIGN);
+		sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN);
 		if (sb_new == NULL) {
 			printk(KERN_INFO "%s: sk_buff allocation failed\n",
 			       d->sbdma_eth->sbm_dev->name);
 			return -ENOBUFS;
 		}
-		
-		sbdma_align_skb(sb_new,CACHELINESIZE,ETHER_ALIGN);
-		
+
+		sbdma_align_skb(sb_new, SMP_CACHE_BYTES, ETHER_ALIGN);
+
 		/* mark skbuff owned by our device */
 		sb_new->dev = d->sbdma_eth->sbm_dev;
 	}
@@ -814,7 +938,7 @@
 		sb_new = sb;
 		/* 
 		 * nothing special to reinit buffer, it's already aligned
-		 * and sb->tail already points to a good place.
+		 * and sb->data already points to a good place.
 		 */
 	}
 	
@@ -822,10 +946,19 @@
 	 * fill in the descriptor 
 	 */
 	
-	dsc->dscr_a = KVTOPHYS(sb_new->tail) |
+#ifdef CONFIG_SBMAC_COALESCE
+	/*
+	 * Do not interrupt per DMA transfer.
+	 */
+	dsc->dscr_a = virt_to_phys(sb_new->tail) |
+		V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
+		0;
+#else
+	dsc->dscr_a = virt_to_phys(sb_new->tail) |
 		V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
 		M_DMA_DSCRA_INTERRUPT;
-	
+#endif
+
 	/* receiving: no options */
 	dsc->dscr_b = 0;
 	
@@ -904,12 +1037,14 @@
 	 * while doing the calculation.
 	 */
 	
-	phys = KVTOPHYS(sb->data);
-	ncb = NUMCACHEBLKS(length+(phys & (CACHELINESIZE-1)));
-	
+	phys = virt_to_phys(sb->data);
+	ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1)));
+
 	dsc->dscr_a = phys | 
 		V_DMA_DSCRA_A_SIZE(ncb) |
+#ifndef CONFIG_SBMAC_COALESCE
 		M_DMA_DSCRA_INTERRUPT |
+#endif
 		M_DMA_ETHTX_SOP;
 	
 	/* transmitting: set outbound options and length */
@@ -986,7 +1121,8 @@
 	int idx;
 	
 	for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) {
-		if (sbdma_add_rcvbuffer(d,NULL) != 0) break;
+		if (sbdma_add_rcvbuffer(d,NULL) != 0)
+			break;
 	}
 }
 
@@ -1037,7 +1173,8 @@
 		 * the hardware is working on right now.
 		 */
 		
-		if (curidx == hwidx) break;
+		if (curidx == hwidx)
+			break;
 		
 		/*
 		 * Otherwise, get the packet's sk_buff ptr back
@@ -1058,35 +1195,51 @@
 		if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) {
 			
 			/*
-			 * Set length into the packet
-			 */
-			skb_put(sb,len);
-			
-       			/*
 			 * Add a new buffer to replace the old one.  If we fail
 			 * to allocate a buffer, we're going to drop this
 			 * packet and put it right back on the receive ring.
 			 */
 			
 			if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) {
-			    sbdma_add_rcvbuffer(d,sb);	/* re-add old buffer */
-			    }
-			else {
-			    /*
-			     * Buffer has been replaced on the receive ring.
-			     * Pass the buffer to the kernel
-			     */
-			    sc->sbm_stats.rx_bytes += len;
-			    sc->sbm_stats.rx_packets++;
-			    sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev);
-			    netif_rx(sb);
-			    }
-		}
-		else {
+				sc->sbm_stats.rx_dropped++;
+				sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */
+			} else {
+				/*
+				 * Set length into the packet
+				 */
+				skb_put(sb,len);
+				
+				/*
+				 * Buffer has been replaced on the
+				 * receive ring.  Pass the buffer to
+				 * the kernel */
+				sc->sbm_stats.rx_bytes += len;
+				sc->sbm_stats.rx_packets++;
+				sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev);
+				if (sc->rx_hw_checksum == ENABLE) {
+					/* if the ip checksum is good
+					   indicate in skb.  else set
+					   CHECKSUM_NONE as device
+					   failed to checksum the
+					   packet */
+					
+					if (((dsc->dscr_b) |M_DMA_ETHRX_BADTCPCS) ||
+					    ((dsc->dscr_a)| M_DMA_ETHRX_BADIP4CS)) {
+						sb->ip_summed = CHECKSUM_NONE;
+					} else {
+						printk(KERN_DEBUG "hw checksum fail .\n");
+						sb->ip_summed = CHECKSUM_UNNECESSARY;
+					}
+				} /* rx_hw_checksum */
+				
+				netif_rx(sb);
+			}
+		} else {
 			/*
 			 * Packet was mangled somehow.  Just drop it and
 			 * put it back on the receive ring.
 			 */
+			sc->sbm_stats.rx_errors++;
 			sbdma_add_rcvbuffer(d,sb);
 		}
 		
@@ -1143,21 +1296,27 @@
 		
 		curidx = d->sbdma_remptr - d->sbdma_dscrtable;
 		{
-			/* XXX This is gross, ugly, and only here because justin hacked it
-			   in to fix a problem without really understanding it. 
-			   
-			   It seems that, for whatever reason, this routine is invoked immediately upon the enabling of interrupts.
-			   So then the Read below returns zero, making hwidx a negative number, and anti-hilarity
-			   ensues.
-			   
-			   I'm guessing there's a proper fix involving clearing out interrupt state from old packets
-			   before enabling interrupts, but I'm not sure.  
-
-			   Anyways, this hack seems to work, and is Good Enough for 11 PM.  :)
-			   
-			   -Justin
-			*/
-			  
+			/* XXX This is gross, ugly, and only here
+			 * because justin hacked it in to fix a
+			 * problem without really understanding it.
+			 * 
+			 * It seems that, for whatever reason, this
+			 * routine is invoked immediately upon the
+			 * enabling of interrupts.  So then the Read
+			 * below returns zero, making hwidx a negative
+			 * number, and anti-hilarity ensues.
+			 * 
+			 * I'm guessing there's a proper fix involving
+			 * clearing out interrupt state from old
+			 * packets before enabling interrupts, but I'm
+			 * not sure.
+			 *
+			 * Anyways, this hack seems to work, and is
+			 * Good Enough for 11 PM.  :)
+			 * 
+			 * -Justin
+			 */
+
 			uint64_t tmp = SBMAC_READCSR(d->sbdma_curdscr);
 			if (!tmp) {
 				break;
@@ -1171,7 +1330,8 @@
 		 * the hardware is working on right now.
 		 */
 		
-		if (curidx == hwidx) break;
+		if (curidx == hwidx)
+			break;
 		
 		/*
 		 * Otherwise, get the packet's sk_buff ptr back
@@ -1238,14 +1398,14 @@
 	 * figure out the addresses of some ports 
 	 */
 	
-	s->sbm_macenable = PKSEG1(s->sbm_base + R_MAC_ENABLE);
-	s->sbm_maccfg    = PKSEG1(s->sbm_base + R_MAC_CFG);
-	s->sbm_fifocfg   = PKSEG1(s->sbm_base + R_MAC_THRSH_CFG);
-	s->sbm_framecfg  = PKSEG1(s->sbm_base + R_MAC_FRAMECFG);
-	s->sbm_rxfilter  = PKSEG1(s->sbm_base + R_MAC_ADFILTER_CFG);
-	s->sbm_isr       = PKSEG1(s->sbm_base + R_MAC_STATUS);
-	s->sbm_imr       = PKSEG1(s->sbm_base + R_MAC_INT_MASK);
-	s->sbm_mdio      = PKSEG1(s->sbm_base + R_MAC_MDIO);
+	s->sbm_macenable = s->sbm_base + R_MAC_ENABLE;
+	s->sbm_maccfg    = s->sbm_base + R_MAC_CFG;
+	s->sbm_fifocfg   = s->sbm_base + R_MAC_THRSH_CFG;
+	s->sbm_framecfg  = s->sbm_base + R_MAC_FRAMECFG;
+	s->sbm_rxfilter  = s->sbm_base + R_MAC_ADFILTER_CFG;
+	s->sbm_isr       = s->sbm_base + R_MAC_STATUS;
+	s->sbm_imr       = s->sbm_base + R_MAC_INT_MASK;
+	s->sbm_mdio      = s->sbm_base + R_MAC_MDIO;
 
 	s->sbm_phys[0]   = 1;
 	s->sbm_phys[1]   = 0;
@@ -1284,12 +1444,12 @@
 static void sbdma_uninitctx(struct sbmacdma_s *d)
 {
 	if (d->sbdma_dscrtable) {
-		KFREE(d->sbdma_dscrtable);
+		kfree(d->sbdma_dscrtable);
 		d->sbdma_dscrtable = NULL;
 	}
 	
 	if (d->sbdma_ctxtable) {
-		KFREE(d->sbdma_ctxtable);
+		kfree(d->sbdma_ctxtable);
 		d->sbdma_ctxtable = NULL;
 	}
 }
@@ -1319,13 +1479,14 @@
 	uint64_t reg;
 	sbmac_port_t port;
 	uint64_t cfg,fifo,framecfg;
-	int idx;
+	int idx, th_value;
 	
 	/*
 	 * Don't do this if running
 	 */
 
-	if (s->sbm_state == sbmac_state_on) return;
+	if (s->sbm_state == sbmac_state_on)
+		return;
 	
 	/*
 	 * Bring the controller out of reset, but leave it off.
@@ -1351,26 +1512,36 @@
 		M_MAC_SS_EN |
 		0;
 	
+	/* 
+	 * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars
+	 * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
+	 * Use a larger RD_THRSH for gigabit
+	 */
+	if (periph_rev >= 2) 
+		th_value = 64;
+	else 
+		th_value = 28;
+
 	fifo = V_MAC_TX_WR_THRSH(4) |	/* Must be '4' or '8' */
-		V_MAC_TX_RD_THRSH(4) |
+		((s->sbm_speed == sbmac_speed_1000)
+		 ? V_MAC_TX_RD_THRSH(th_value) : V_MAC_TX_RD_THRSH(4)) |
 		V_MAC_TX_RL_THRSH(4) |
 		V_MAC_RX_PL_THRSH(4) |
 		V_MAC_RX_RD_THRSH(4) |	/* Must be '4' */
 		V_MAC_RX_PL_THRSH(4) |
 		V_MAC_RX_RL_THRSH(8) |
 		0;
-	
+
 	framecfg = V_MAC_MIN_FRAMESZ_DEFAULT |
 		V_MAC_MAX_FRAMESZ_DEFAULT |
 		V_MAC_BACKOFF_SEL(1);
-	
-	
+
 	/*
 	 * Clear out the hash address map 
 	 */
 	
-	port = PKSEG1(s->sbm_base + R_MAC_HASH_BASE);
-        for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
+	port = s->sbm_base + R_MAC_HASH_BASE;
+	for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
 		SBMAC_WRITECSR(port,0);
 		port += sizeof(uint64_t);
 	}
@@ -1379,7 +1550,7 @@
 	 * Clear out the exact-match table
 	 */
 	
-	port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE);
+	port = s->sbm_base + R_MAC_ADDR_BASE;
 	for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
 		SBMAC_WRITECSR(port,0);
 		port += sizeof(uint64_t);
@@ -1389,14 +1560,14 @@
 	 * Clear out the DMA Channel mapping table registers
 	 */
 	
-	port = PKSEG1(s->sbm_base + R_MAC_CHUP0_BASE);
+	port = s->sbm_base + R_MAC_CHUP0_BASE;
 	for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
 		SBMAC_WRITECSR(port,0);
 		port += sizeof(uint64_t);
 	}
 
 
-	port = PKSEG1(s->sbm_base + R_MAC_CHLO0_BASE);
+	port = s->sbm_base + R_MAC_CHLO0_BASE;
 	for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
 		SBMAC_WRITECSR(port,0);
 		port += sizeof(uint64_t);
@@ -1409,13 +1580,13 @@
 	
 	reg = sbmac_addr2reg(s->sbm_hwaddr);
 	
-	port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE);
+	port = s->sbm_base + R_MAC_ADDR_BASE;
 	SBMAC_WRITECSR(port,reg);
-	port = PKSEG1(s->sbm_base + R_MAC_ETHERNET_ADDR);
+	port = s->sbm_base + R_MAC_ETHERNET_ADDR;
 
 #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
 	/*
-	 * Pass1 SB1250s do not receive packets addressed to the
+	 * Pass1 SOCs do not receive packets addressed to the
 	 * destination address in the R_MAC_ETHERNET_ADDR register.
 	 * Set the value to zero.
 	 */
@@ -1439,8 +1610,8 @@
 	 * Initialize DMA channels (rings should be ok now)
 	 */
 	
-	sbdma_channel_start(&(s->sbm_rxdma));
-	sbdma_channel_start(&(s->sbm_txdma));
+	sbdma_channel_start(&(s->sbm_rxdma), DMA_RX);
+	sbdma_channel_start(&(s->sbm_txdma), DMA_TX);
 	
 	/*
 	 * Configure the speed, duplex, and flow control
@@ -1467,12 +1638,22 @@
 	
 	
 
+
+#ifdef CONFIG_SBMAC_COALESCE
+	/*
+	 * Accept any TX interrupt and EOP count/timer RX interrupts on ch 0
+	 */
+	SBMAC_WRITECSR(s->sbm_imr,
+		       ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
+		       ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0));
+#else
 	/*
 	 * Accept any kind of interrupt on TX and RX DMA channel 0
 	 */
 	SBMAC_WRITECSR(s->sbm_imr,
 		       (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
 		       (M_MAC_INT_CHANNEL << S_MAC_RX_CH0));
+#endif
 	
 	/* 
 	 * Enable receiving unicasts and broadcasts 
@@ -1517,11 +1698,10 @@
 
 static void sbmac_channel_stop(struct sbmac_softc *s)
 {
-	uint64_t ctl;
-	
 	/* don't do this if already stopped */
 	
-	if (s->sbm_state == sbmac_state_off) return;
+	if (s->sbm_state == sbmac_state_off)
+		return;
 	
 	/* don't accept any packets, disable all interrupts */
 	
@@ -1534,14 +1714,18 @@
 	
 	/* turn off receiver and transmitter */
 	
-	ctl = SBMAC_READCSR(s->sbm_macenable);
-	ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0);
-	SBMAC_WRITECSR(s->sbm_macenable,ctl);
+	SBMAC_WRITECSR(s->sbm_macenable,0);
 	
 	/* We're stopped now. */
 	
 	s->sbm_state = sbmac_state_off;
 	
+	/*
+	 * Stop DMA channels (rings should be ok now)
+	 */
+	
+	sbdma_channel_stop(&(s->sbm_rxdma));
+	sbdma_channel_stop(&(s->sbm_txdma));
 	
 	/* Empty the receive and transmit rings */
 	
@@ -1610,7 +1794,8 @@
 {
 	uint64_t reg;
 	
-	if (sc->sbm_state != sbmac_state_on) return;
+	if (sc->sbm_state != sbmac_state_on)
+		return;
 	
 	if (onoff) {
 		reg = SBMAC_READCSR(sc->sbm_rxfilter);
@@ -1624,31 +1809,36 @@
 	}
 }
 
-
-
-#if 0
 /**********************************************************************
- *  SBMAC_INIT_AND_START(sc)
+ *  SBMAC_SETIPHDR_OFFSET(sc,onoff)
  *  
- *  Stop the channel and restart it.  This is generally used
- *  when we have to do something to the channel that requires
- *  a swift kick.
+ *  Set the iphdr offset as 15 assuming ethernet encapsulation
  *  
  *  Input parameters: 
  *  	   sc - softc
+ *  	   
+ *  Return value:
+ *  	   nothing
  ********************************************************************* */
 
-static void sbmac_init_and_start(struct sbmac_softc *sc)
+static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
 {
-	unsigned long flags;
-	
-	spin_lock_irqsave(&(sc->sbm_lock),flags);
+	uint64_t reg;
 	
-	sbmac_set_channel_state(sc,sbmac_state_on);
+	/* Hard code the off set to 15 for now */
+	reg = SBMAC_READCSR(sc->sbm_rxfilter);
+	reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
+	SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
 	
-	spin_unlock_irqrestore(&(sc->sbm_lock),flags);
+	/* read system identification to determine revision */
+	if (periph_rev >= 2) {
+		printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
+		       sc->sbm_dev->name);
+		sc->rx_hw_checksum = ENABLE;
+	} else {
+		sc->rx_hw_checksum = DISABLE;
+	}
 }
-#endif
 
 
 /**********************************************************************
@@ -1712,7 +1902,8 @@
 	
 	s->sbm_speed = speed;
 	
-	if (s->sbm_state == sbmac_state_on) return 0;	/* save for next restart */
+	if (s->sbm_state == sbmac_state_on)
+		return 0;	/* save for next restart */
 
 	/*
 	 * Read current register values 
@@ -1772,7 +1963,6 @@
 	SBMAC_WRITECSR(s->sbm_maccfg,cfg);
 	
 	return 1;
-	
 }
 
 /**********************************************************************
@@ -1802,7 +1992,8 @@
 	s->sbm_duplex = duplex;
 	s->sbm_fc = fc;
 	
-	if (s->sbm_state == sbmac_state_on) return 0;	/* save for next restart */
+	if (s->sbm_state == sbmac_state_on)
+		return 0;	/* save for next restart */
 	
 	/*
 	 * Read current register values 
@@ -1886,7 +2077,7 @@
  *  Return value:
  *  	   nothing
  ********************************************************************* */
-static void sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
+static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct sbmac_softc *sc = (struct sbmac_softc *) (dev->priv);
@@ -1896,14 +2087,17 @@
 	for (;;) {
 		
 		/*
-		 * Read the ISR (this clears the bits in the real register)
+		 * Read the ISR (this clears the bits in the real
+		 * register, except for counter addr)
 		 */
 		
-		isr = SBMAC_READCSR(sc->sbm_isr);
+		isr = SBMAC_READCSR(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
 		
 		if (isr == 0)
 			break;
+
 		handled = 1;
+		
 		/*
 		 * Transmits on channel 0
 		 */
@@ -1915,6 +2109,23 @@
 		/*
 		 * Receives on channel 0
 		 */
+
+		/*
+		 * It's important to test all the bits (or at least the
+		 * EOP_SEEN bit) when deciding to do the RX process
+		 * particularly when coalescing, to make sure we
+		 * take care of the following:
+		 *
+		 * If you have some packets waiting (have been received
+		 * but no interrupt) and get a TX interrupt before
+		 * the RX timer or counter expires, reading the ISR
+		 * above will clear the timer and counter, and you
+		 * won't get another interrupt until a packet shows
+		 * up to start the timer again.  Testing
+		 * EOP_SEEN here takes care of this case.
+		 * (EOP_SEEN is part of M_MAC_INT_CHANNEL << S_MAC_RX_CH0)
+		 */
+		 
 		
 		if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
 			sbdma_rx_process(sc,&(sc->sbm_rxdma));
@@ -1952,6 +2163,9 @@
 	if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
 		/* XXX save skb that we could not send */
 		netif_stop_queue(dev);
+		spin_unlock_irq(&sc->sbm_lock);
+
+		return 1;
 	}
 	
 	dev->trans_start = jiffies;
@@ -1990,12 +2204,12 @@
 	 */
 	
 	for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
-		port = PKSEG1(sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)));
+		port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t));
 		SBMAC_WRITECSR(port,0);	
 	}
 	
 	for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
-		port = PKSEG1(sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t)));
+		port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t));
 		SBMAC_WRITECSR(port,0);	
 	}
 	
@@ -2032,8 +2246,7 @@
 	mclist = dev->mc_list;
 	while (mclist && (idx < MAC_ADDR_COUNT)) {
 		reg = sbmac_addr2reg(mclist->dmi_addr);
-		port = PKSEG1(sc->sbm_base + 
-			      R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)));
+		port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t));
 		SBMAC_WRITECSR(port,reg);
 		idx++;
 		mclist = mclist->next;
@@ -2070,10 +2283,14 @@
 {
 	int digit;
 	
-	if ((str >= '0') && (str <= '9')) digit = str - '0';
-	else if ((str >= 'a') && (str <= 'f')) digit = str - 'a' + 10;
-	else if ((str >= 'A') && (str <= 'F')) digit = str - 'A' + 10;
-	else return -1;
+	if ((str >= '0') && (str <= '9'))
+		digit = str - '0';
+	else if ((str >= 'a') && (str <= 'f'))
+		digit = str - 'a' + 10;
+	else if ((str >= 'A') && (str <= 'F'))
+		digit = str - 'A' + 10;
+	else
+		return -1;
 	
 	return digit;
 }
@@ -2092,16 +2309,18 @@
  *  	   0 if ok, else -1
  ********************************************************************* */
 
-static int sbmac_parse_hwaddr(char *str,u_char *hwaddr)
+static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
 {
 	int digit1,digit2;
 	int idx = 6;
 	
 	while (*str && (idx > 0)) {
 		digit1 = sbmac_parse_xdigit(*str);
-		if (digit1 < 0) return -1;
+		if (digit1 < 0)
+			return -1;
 		str++;
-		if (!*str) return -1;
+		if (!*str)
+			return -1;
 		
 		if ((*str == ':') || (*str == '-')) {
 			digit2 = digit1;
@@ -2109,20 +2328,32 @@
 		}
 		else {
 			digit2 = sbmac_parse_xdigit(*str);
-			if (digit2 < 0) return -1;
+			if (digit2 < 0)
+				return -1;
 			str++;
 		}
 		
 		*hwaddr++ = (digit1 << 4) | digit2;
 		idx--;
 		
-		if (*str == '-') str++;
-		if (*str == ':') str++;
+		if (*str == '-')
+			str++;
+		if (*str == ':')
+			str++;
 	}
 	return 0;
 }
 #endif
 
+static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
+{
+	if (new_mtu >  ENET_PACKET_SIZE)
+		return -EINVAL;
+	_dev->mtu = new_mtu;
+	printk(KERN_INFO "changing the mtu to %d\n", new_mtu);
+	return 0;
+}
+
 /**********************************************************************
  *  SBMAC_INIT(dev)
  *  
@@ -2135,19 +2366,20 @@
  *  	   status
  ********************************************************************* */
 
-static int sbmac_init(struct net_device *dev)
+static int sbmac_init(struct net_device *dev, int idx)
 {
 	struct sbmac_softc *sc;
-	u_char *eaddr;
+	unsigned char *eaddr;
 	uint64_t ea_reg;
-	int idx;
+	int i;
 	
 	sc = (struct sbmac_softc *)dev->priv;
 	
 	/* Determine controller base address */
 	
-	sc->sbm_base = (sbmac_port_t) dev->base_addr;
+	sc->sbm_base = KSEG1ADDR(dev->base_addr);
 	sc->sbm_dev = dev;
+	sc->sbe_idx = idx;
 	
 	eaddr = sc->sbm_hwaddr;
 	
@@ -2156,16 +2388,15 @@
 	 * for us in the ethernet address register for each mac.
 	 */
 	
-	ea_reg = SBMAC_READCSR(PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR));
-	SBMAC_WRITECSR(PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR), 0);
-	for (idx = 0; idx < 6; idx++) {
-		eaddr[idx] = (uint8_t) (ea_reg & 0xFF);
+	ea_reg = SBMAC_READCSR(sc->sbm_base + R_MAC_ETHERNET_ADDR);
+	SBMAC_WRITECSR(sc->sbm_base + R_MAC_ETHERNET_ADDR, 0);
+	for (i = 0; i < 6; i++) {
+		eaddr[i] = (uint8_t) (ea_reg & 0xFF);
 		ea_reg >>= 8;
 	}
 	
-	
-	for (idx = 0; idx < 6; idx++) {
-		dev->dev_addr[idx] = eaddr[idx];
+	for (i = 0; i < 6; i++) {
+		dev->dev_addr[i] = eaddr[i];
 	}
 	
 	
@@ -2173,8 +2404,8 @@
 	 * Init packet size 
 	 */
 	
-	sc->sbm_buffersize = ENET_PACKET_SIZE + CACHELINESIZE*2 + ETHER_ALIGN;
-	
+	sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN;
+
 	/* 
 	 * Initialize context (get pointers to registers and stuff), then
 	 * allocate the memory for the descriptor tables.
@@ -2184,13 +2415,13 @@
 	
 	
 	/*
-	 * Display Ethernet address (this is called during the config process
-	 * so we need to finish off the config message that was being displayed)
+	 * Display Ethernet address (this is called during the config
+	 * process so we need to finish off the config message that
+	 * was being displayed)
 	 */
 	printk(KERN_INFO
-	       "%s: SB1250 Ethernet at 0x%08lX, address: %02X-%02X-%02X-%02X-%02X-%02X\n", 
-	       dev->name,
-	       (unsigned long) sc->sbm_base,
+	       "%s: SiByte Ethernet at 0x%08lX, address: %02X-%02X-%02X-%02X-%02X-%02X\n", 
+	       dev->name, dev->base_addr,
 	       eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]);
 	
 	/*
@@ -2208,9 +2439,13 @@
 	dev->do_ioctl           = sbmac_mii_ioctl;
 	dev->tx_timeout         = sbmac_tx_timeout;
 	dev->watchdog_timeo     = TX_TIMEOUT;
+
+	dev->change_mtu         = sb1250_change_mtu;
+
+	/* This is needed for PASS2 for Rx H/W checksum feature */
+	sbmac_set_iphdr_offset(sc);
 	
 	return 0;
-	
 }
 
 
@@ -2237,7 +2472,7 @@
 	 * Configure default speed 
 	 */
 
-	sbmac_mii_poll(sc,1);
+	sbmac_mii_poll(sc,noisy_mii);
 	
 	/*
 	 * Turn on the channel
@@ -2319,7 +2554,8 @@
 	chg = 1;
 	}
 
-    if (chg == 0) return 0;
+    if (chg == 0)
+	    return 0;
 
     p += sprintf(p,"Link speed: ");
 
@@ -2371,8 +2607,6 @@
 }
 
 
-
-
 static void sbmac_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
@@ -2399,19 +2633,19 @@
 	 * Poll the PHY to see what speed we should be running at
 	 */
 
-	if (sbmac_mii_poll(sc,1)) {
-	    if (sc->sbm_state != sbmac_state_off) {
-		/*
-		 * something changed, restart the channel
-		 */
-		if (debug > 1) {
-		    printk("%s: restarting channel because speed changed\n",
-			   sc->sbm_dev->name);
-		    }
-		sbmac_channel_stop(sc);
-		sbmac_channel_start(sc);
+	if (sbmac_mii_poll(sc,noisy_mii)) {
+		if (sc->sbm_state != sbmac_state_off) {
+			/*
+			 * something changed, restart the channel
+			 */
+			if (debug > 1) {
+				printk("%s: restarting channel because speed changed\n",
+				       sc->sbm_dev->name);
+			}
+			sbmac_channel_stop(sc);
+			sbmac_channel_start(sc);
 		}
-	    }
+	}
 	
 	spin_unlock_irq (&sc->sbm_lock);
 	
@@ -2479,7 +2713,8 @@
 	spin_unlock_irqrestore(&sc->sbm_lock, flags);
 	
 	if (msg_flag) {
-		printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n", dev->name,(msg_flag==1)?"en":"dis");
+		printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n",
+		       dev->name,(msg_flag==1)?"en":"dis");
 	}
 	
 	/*
@@ -2530,31 +2765,31 @@
 {
 	struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
 	unsigned long flags;
-	
+	int irq;
+
 	sbmac_set_channel_state(sc,sbmac_state_off);
-	
+
 	del_timer_sync(&sc->sbm_timer);
-	
+
 	spin_lock_irqsave(&sc->sbm_lock, flags);
-	
+
 	netif_stop_queue(dev);
-	
+
 	if (debug > 1) {
 		printk(KERN_DEBUG "%s: Shutting down ethercard\n",dev->name);
 	}
-	
+
 	spin_unlock_irqrestore(&sc->sbm_lock, flags);
-	
-	/* Make sure there is no irq-handler running on a different CPU. */
-	synchronize_irq(dev->irq);
-	
-	free_irq(dev->irq, dev);
-	
+
+	irq = dev->irq;
+	synchronize_irq(irq);
+	free_irq(irq, dev);
+
 	sbdma_emptyring(&(sc->sbm_txdma));
 	sbdma_emptyring(&(sc->sbm_rxdma));
 	
 	MOD_DEC_USE_COUNT;
-	
+
 	return 0;
 }
 
@@ -2571,8 +2806,8 @@
 	port = A_MAC_CHANNEL_BASE(chan);
 	sbmac_parse_hwaddr(addr,eaddr);
 	val = sbmac_addr2reg(eaddr);
-	SBMAC_WRITECSR(PKSEG1(port+R_MAC_ETHERNET_ADDR),val);
-	val = SBMAC_READCSR(PKSEG1(port+R_MAC_ETHERNET_ADDR));
+	SBMAC_WRITECSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR),val);
+	val = SBMAC_READCSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR));
 }
 #endif
 
@@ -2585,6 +2820,7 @@
 	int macidx = 0;
 	struct net_device *dev;
 	sbmac_port_t port;
+	int chip_max_units;
 	
 	/*
 	 * For bringup when not using the firmware, we can pre-fill
@@ -2605,8 +2841,25 @@
 	 * Walk through the Ethernet controllers and find
 	 * those who have their MAC addresses set.
 	 */
-	
-	for (idx = 0; idx < MAX_UNITS; idx++) {
+	switch (soc_type) {
+	case K_SYS_SOC_TYPE_BCM1250:
+	case K_SYS_SOC_TYPE_BCM1250_ALT:
+		chip_max_units = 3;
+		break;
+	case K_SYS_SOC_TYPE_BCM1120:
+	case K_SYS_SOC_TYPE_BCM1125:
+	case K_SYS_SOC_TYPE_BCM1125H:
+	case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */
+		chip_max_units = 2;
+		break;
+	default:
+		chip_max_units = 0;
+		break;
+	}
+	if (chip_max_units > MAX_UNITS)
+		chip_max_units = MAX_UNITS;
+
+	for (idx = 0; idx < chip_max_units; idx++) {
 
 	        /*
 	         * This is the base address of the MAC.
@@ -2620,25 +2873,31 @@
 		 * If we find a zero, skip this MAC.
 		 */
 
-		if (SBMAC_READCSR(PKSEG1(port+R_MAC_ETHERNET_ADDR)) == 0) {
+		sbmac_orig_hwaddr[idx] = SBMAC_READCSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR));
+		if (sbmac_orig_hwaddr[idx] == 0) {
+			printk(KERN_DEBUG "sbmac: not configuring MAC at "
+			       "%lx\n", port);
 		    continue;
-		    }
+		}
 
 		/*
 		 * Okay, cool.  Initialize this MAC.
 		 */
 
 		dev = init_etherdev(NULL,sizeof(struct sbmac_softc));
-		if (!dev) break;			/* problems, get out now. */
+		if (!dev) 
+		  return -ENOMEM;	/* return ENOMEM */
+
+		printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
+
 		dev->irq = K_INT_MAC_0 + idx;
 		dev->base_addr = port;
 		dev->mem_end = 0;
 		/*dev->init = sbmac_init;*/
-		sbmac_init(dev);
+		sbmac_init(dev, macidx);
 
 		dev_sbmac[macidx] = dev;
 		macidx++;
-
 	}
 
 	/*
@@ -2654,9 +2913,11 @@
 {
 	int idx;
 	struct net_device *dev;
+	sbmac_port_t port;
 	for (idx = 0; idx < MAX_UNITS; idx++) {
 		dev = dev_sbmac[idx];
-		if (dev == NULL) continue;
+		if (dev == NULL)
+			continue;
 		if (dev->priv != NULL) {
 			struct sbmac_softc *sc = (struct sbmac_softc *) dev->priv;
 			
@@ -2664,9 +2925,11 @@
 			
 			sbmac_uninitctx(sc);
 			
-			KFREE(sc);
 		}
-		KFREE(dev);
+
+	        port = A_MAC_CHANNEL_BASE(idx);
+		SBMAC_WRITECSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR), sbmac_orig_hwaddr[idx] );
+		kfree(dev);
 		dev_sbmac[idx] = NULL;
 	}
 }
diff -urN linux-2.5.73-bk3/drivers/net/sgiseeq.c linux-2.5.73-bk4/drivers/net/sgiseeq.c
--- linux-2.5.73-bk3/drivers/net/sgiseeq.c	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/sgiseeq.c	2003-06-26 05:00:28.000000000 -0700
@@ -5,6 +5,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
@@ -25,8 +26,8 @@
 #include <asm/bitops.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/sgi/sgihpc.h>
-#include <asm/sgi/sgint23.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ip22.h>
 #include <asm/sgialib.h>
 
 #include "sgiseeq.h"
@@ -90,8 +91,8 @@
 struct sgiseeq_private {
 	volatile struct sgiseeq_init_block srings;
 	char *name;
-	volatile struct hpc3_ethregs *hregs;
-	volatile struct sgiseeq_regs *sregs;
+	struct hpc3_ethregs *hregs;
+	struct sgiseeq_regs *sregs;
 
 	/* Ring entry counters. */
 	unsigned int rx_new, tx_new;
@@ -102,17 +103,22 @@
 	unsigned char mode;
 
 	struct net_device_stats stats;
+
+	struct net_device *next_module;
 };
 
-static inline void hpc3_eth_reset(volatile struct hpc3_ethregs *hregs)
+/* A list of all installed seeq devices, for removing the driver module. */
+static struct net_device *root_sgiseeq_dev;
+
+static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
 {
 	hregs->rx_reset = (HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ);
 	udelay(20);
 	hregs->rx_reset = 0;
 }
 
-static inline void reset_hpc3_and_seeq(volatile struct hpc3_ethregs *hregs,
-				       volatile struct sgiseeq_regs *sregs)
+static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
+				       struct sgiseeq_regs *sregs)
 {
 	hregs->rx_ctrl = hregs->tx_ctrl = 0;
 	hpc3_eth_reset(hregs);
@@ -122,15 +128,15 @@
 		       SEEQ_RCMD_IDRIB | SEEQ_RCMD_ICRC)
 
 static inline void seeq_go(struct sgiseeq_private *sp,
-			   volatile struct hpc3_ethregs *hregs,
-			   volatile struct sgiseeq_regs *sregs)
+			   struct hpc3_ethregs *hregs,
+			   struct sgiseeq_regs *sregs)
 {
 	sregs->rstat = sp->mode | RSTAT_GO_BITS;
 	hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE;
 }
 
 static inline void seeq_load_eaddr(struct net_device *dev,
-				   volatile struct sgiseeq_regs *sregs)
+				   struct sgiseeq_regs *sregs)
 {
 	int i;
 
@@ -171,7 +177,6 @@
 				return -ENOMEM;
 			ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
 			ib->tx_desc[i].tdma.pbuf = PHYSADDR(buffer);
-//			flush_cache_all();
 		}
 		ib->tx_desc[i].tdma.cntinfo = (TCNTINFO_INIT);
 	}
@@ -186,7 +191,6 @@
 				return -ENOMEM;
 			ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
 			ib->rx_desc[i].rdma.pbuf = PHYSADDR(buffer);
-//			flush_cache_all();
 		}
 		ib->rx_desc[i].rdma.cntinfo = (RCNTINFO_INIT);
 	}
@@ -203,7 +207,7 @@
 	static int once;
 	struct sgiseeq_rx_desc *r = gpriv->srings.rx_desc;
 	struct sgiseeq_tx_desc *t = gpriv->srings.tx_desc;
-	volatile struct hpc3_ethregs *hregs = gpriv->hregs;
+	struct hpc3_ethregs *hregs = gpriv->hregs;
 	int i;
 
 	if(once)
@@ -242,9 +246,9 @@
 #define RDMACFG_INIT    (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
 
 static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
-		      volatile struct sgiseeq_regs *sregs)
+		     struct sgiseeq_regs *sregs)
 {
-	volatile struct hpc3_ethregs *hregs = sp->hregs;
+	struct hpc3_ethregs *hregs = sp->hregs;
 	int err;
 
 	reset_hpc3_and_seeq(hregs, sregs);
@@ -285,8 +289,8 @@
 }
 
 static inline void rx_maybe_restart(struct sgiseeq_private *sp,
-				    volatile struct hpc3_ethregs *hregs,
-				    volatile struct sgiseeq_regs *sregs)
+				    struct hpc3_ethregs *hregs,
+				    struct sgiseeq_regs *sregs)
 {
 	if (!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) {
 		hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[sp->rx_new]);
@@ -299,8 +303,8 @@
 				(rd) = &(sp)->srings.rx_desc[(sp)->rx_new])
 
 static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp,
-			      volatile struct hpc3_ethregs *hregs,
-			      volatile struct sgiseeq_regs *sregs)
+			      struct hpc3_ethregs *hregs,
+			      struct sgiseeq_regs *sregs)
 {
 	struct sgiseeq_rx_desc *rd;
 	struct sk_buff *skb = 0;
@@ -332,7 +336,7 @@
 				sp->stats.rx_packets++;
 				sp->stats.rx_bytes += len;
 			} else {
-				printk ("%s: Memory squeeze, deferring packet.\n",
+				printk (KERN_NOTICE "%s: Memory squeeze, deferring packet.\n",
 					dev->name);
 				sp->stats.rx_dropped++;
 			}
@@ -350,7 +354,7 @@
 }
 
 static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp,
-					     volatile struct sgiseeq_regs *sregs)
+					     struct sgiseeq_regs *sregs)
 {
 	if (sp->is_edlc) {
 		sregs->rw.wregs.control = sp->control & ~(SEEQ_CTRL_XCNT);
@@ -359,7 +363,7 @@
 }
 
 static inline void kick_tx(struct sgiseeq_tx_desc *td,
-			   volatile struct hpc3_ethregs *hregs)
+			   struct hpc3_ethregs *hregs)
 {
 	/* If the HPC aint doin nothin, and there are more packets
 	 * with ETXD cleared and XIU set we must make very certain
@@ -377,8 +381,8 @@
 }
 
 static inline void sgiseeq_tx(struct net_device *dev, struct sgiseeq_private *sp,
-			      volatile struct hpc3_ethregs *hregs,
-			      volatile struct sgiseeq_regs *sregs)
+			      struct hpc3_ethregs *hregs,
+			      struct sgiseeq_regs *sregs)
 {
 	struct sgiseeq_tx_desc *td;
 	unsigned long status = hregs->tx_ctrl;
@@ -420,8 +424,8 @@
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
-	volatile struct hpc3_ethregs *hregs = sp->hregs;
-	volatile struct sgiseeq_regs *sregs = sp->sregs;
+	struct hpc3_ethregs *hregs = sp->hregs;
+	struct sgiseeq_regs *sregs = sp->sregs;
 
 	/* Ack the IRQ and set software state. */
 	hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
@@ -429,7 +433,7 @@
 	/* Always check for received packets. */
 	sgiseeq_rx(dev, sp, hregs, sregs);
 
-	/* Only check for tx acks iff we have something queued. */
+	/* Only check for tx acks if we have something queued. */
 	if (sp->tx_old != sp->tx_new)
 		sgiseeq_tx(dev, sp, hregs, sregs);
 
@@ -442,47 +446,34 @@
 static int sgiseeq_open(struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *)dev->priv;
-	volatile struct sgiseeq_regs *sregs = sp->sregs;
-	unsigned long flags;
-	int err;
-
-	local_irq_save(flags);
+	struct sgiseeq_regs *sregs = sp->sregs;
 
-	err = -EAGAIN;
-	if (request_irq(dev->irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) {
-		printk("Seeq8003: Can't get irq %d\n", dev->irq);
-		goto out;
-	}
-	err = init_seeq(dev, sp, sregs);
+	int err = init_seeq(dev, sp, sregs);
 	if (err)
-		goto out;
+		return err;
 
 	netif_start_queue(dev);
 
-out:
-	local_irq_restore(flags);
-	return err;
+	return 0;
 }
 
 static int sgiseeq_close(struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
-	volatile struct sgiseeq_regs *sregs = sp->sregs;
+	struct sgiseeq_regs *sregs = sp->sregs;
 
 	netif_stop_queue(dev);
 
 	/* Shutdown the Seeq. */
 	reset_hpc3_and_seeq(sp->hregs, sregs);
 
-	free_irq(dev->irq, dev);
-
 	return 0;
 }
 
 static inline int sgiseeq_reset(struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
-	volatile struct sgiseeq_regs *sregs = sp->sregs;
+	struct sgiseeq_regs *sregs = sp->sregs;
 	int err;
 
 	err = init_seeq(dev, sp, sregs);
@@ -504,12 +495,12 @@
 static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
-	volatile struct hpc3_ethregs *hregs = sp->hregs;
+	struct hpc3_ethregs *hregs = sp->hregs;
 	unsigned long flags;
 	struct sgiseeq_tx_desc *td;
 	int skblen, len, entry;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 
 	/* Setup... */
 	skblen = skb->len;
@@ -553,14 +544,14 @@
 
 	if (!TX_BUFFS_AVAIL(sp))
 		netif_stop_queue(dev);
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 	return 0;
 }
 
 static void timeout(struct net_device *dev)
 {
-	printk("%s: transmit timed out, resetting\n", dev->name);
+	printk(KERN_NOTICE "%s: transmit timed out, resetting\n", dev->name);
 	sgiseeq_reset(dev);
 
 	dev->trans_start = jiffies;
@@ -603,41 +594,56 @@
 	buf[i].rdma.pnext = PHYSADDR(&buf[0]);
 }
 
-static char onboard_eth_addr[6];
-
 #define ALIGNED(x)  ((((unsigned long)(x)) + 0xf) & ~(0xf))
 
-int sgiseeq_init(struct net_device *dev, struct sgiseeq_regs *sregs,
-		 struct hpc3_ethregs *hregs, int irq)
+int sgiseeq_init(struct hpc3_regs* regs, int irq)
 {
-	static unsigned version_printed;
-	int i;
+	struct net_device *dev;
 	struct sgiseeq_private *sp;
-
-	dev->priv = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
-	if (dev->priv == NULL)
+	int i;
+	
+	sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
+	if (!sp) {
+		printk (KERN_ERR
+			"Seeq8003: Could not allocate private data.\n");
 		return -ENOMEM;
+	}
 
-	if (!version_printed++)
-		printk(version);
-
-	printk("%s: SGI Seeq8003 ", dev->name);
-
-	for (i = 0; i < 6; i++)
-		printk("%2.2x%c",
-		       dev->dev_addr[i] = onboard_eth_addr[i],
-		       i == 5 ? ' ': ':');
+	dev = init_etherdev(NULL, 0);
+	if (!dev) {
+		printk (KERN_ERR
+			"Seeq8003: Could not allocate memory for device.\n");
+		free_page((unsigned long) sp);
+		return -ENOMEM;
+	}
 
+	if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) {
+		printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq);
+		free_page((unsigned long) sp);
+		unregister_netdev(dev);
+		return -EAGAIN;
+	}
+
+	printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
+
+#define EADDR_NVOFS     250
+	for (i = 0; i < 3; i++) {
+		unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i);
+
+		printk("%2.2x:%2.2x%c",
+			dev->dev_addr[2 * i]     = tmp >> 8,
+			dev->dev_addr[2 * i + 1] = tmp & 0xff,
+			i == 2 ? ' ' : ':');
+	}
 	printk("\n");
 
-	sp = (struct sgiseeq_private *) dev->priv;
+	dev->priv = sp;
 #ifdef DEBUG
 	gpriv = sp;
 	gdev = dev;
 #endif
-	memset((char *)dev->priv, 0, sizeof(struct sgiseeq_private));
-	sp->sregs = sregs;
-	sp->hregs = hregs;
+	sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
+	sp->hregs = &hpc3c0->ethregs;
 	sp->name = sgiseeqstr;
 
 	sp->srings.rx_desc = (struct sgiseeq_rx_desc *)
@@ -654,14 +660,13 @@
 	setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS);
 
 	/* Reset the chip. */
-	hpc3_eth_reset((volatile struct hpc3_ethregs *) hregs);
+	hpc3_eth_reset(sp->hregs);
 
-	sp->is_edlc = !(sregs->rw.rregs.collision_tx[0] & 0xff);
-	if (sp->is_edlc) {
+	sp->is_edlc = !(sp->sregs->rw.rregs.collision_tx[0] & 0xff);
+	if (sp->is_edlc)
 		sp->control = (SEEQ_CTRL_XCNT | SEEQ_CTRL_ACCNT |
 			       SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT |
 			       SEEQ_CTRL_ENCARR);
-	}
 
 	dev->open                 = sgiseeq_open;
 	dev->stop                 = sgiseeq_close;
@@ -674,51 +679,37 @@
 	dev->dma                  = 0;
 	ether_setup(dev);
 
+	sp->next_module = root_sgiseeq_dev;
+	root_sgiseeq_dev = dev;
+
 	return 0;
 }
 
-static inline unsigned char str2hexnum(unsigned char c)
+static int __init sgiseeq_probe(void)
 {
-	if (c >= '0' && c <= '9')
-		return c - '0';
-	if (c >= 'a' && c <= 'f')
-		return c - 'a' + 10;
-	return 0; /* foo */
+	printk(version);
+
+	/* On board adapter on 1st HPC is always present */
+	return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
 }
 
-static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+static void __exit sgiseeq_exit(void)
 {
-	int i;
-
-	for (i = 0; i < 6; i++) {
-		unsigned char num;
+	struct sgiseeq_private *sp;
+	struct net_device *next, *dev = root_sgiseeq_dev;
 
-		if(*str == ':')
-			str++;
-		num = str2hexnum(*str++) << 4;
-		num |= (str2hexnum(*str++));
-		ea[i] = num;
+	while (dev) {
+		sp = (struct sgiseeq_private *) dev->priv;
+		next = sp->next_module;
+		free_irq(dev->irq, dev);
+		free_page((unsigned long) sp);
+		unregister_netdev(dev);
+		kfree(dev);
+		dev = next;
 	}
 }
 
-int sgiseeq_probe(struct net_device *dev)
-{
-	static int initialized;
-	char *ep;
-
-	if (initialized)	/* Already initialized? */
-		return 1;
-	initialized++;
-
-	/* First get the ethernet address of the onboard interface from ARCS.
-	 * This is fragile; PROM doesn't like running from cache.
-	 * On MIPS64 it crashes for some other, yet unknown reason ...
-	 */
-	ep = ArcGetEnvironmentVariable("eaddr");
-	str2eaddr(onboard_eth_addr, ep);
-	return sgiseeq_init(dev,
-			    (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
-			    &hpc3c0->ethregs, SGI_ENET_IRQ);
-}
+module_init(sgiseeq_probe);
+module_exit(sgiseeq_exit);
 
 MODULE_LICENSE("GPL");
diff -urN linux-2.5.73-bk3/drivers/net/sgiseeq.h linux-2.5.73-bk4/drivers/net/sgiseeq.h
--- linux-2.5.73-bk3/drivers/net/sgiseeq.h	2003-06-22 11:32:44.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/sgiseeq.h	2003-06-26 05:00:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: sgiseeq.h,v 1.4 1999/10/09 00:01:24 ralf Exp $
+/*
  * sgiseeq.h: Defines for the Seeq8003 ethernet controller.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
diff -urN linux-2.5.73-bk3/drivers/net/sungem.c linux-2.5.73-bk4/drivers/net/sungem.c
--- linux-2.5.73-bk3/drivers/net/sungem.c	2003-06-22 11:33:18.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/sungem.c	2003-06-26 05:00:28.000000000 -0700
@@ -2384,9 +2384,6 @@
 		return 0;
 
 	case ETHTOOL_SSET:
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-
 		/* Verify the settings we care about. */
 		if (ecmd.autoneg != AUTONEG_ENABLE &&
 		    ecmd.autoneg != AUTONEG_DISABLE)
diff -urN linux-2.5.73-bk3/drivers/net/sunhme.c linux-2.5.73-bk4/drivers/net/sunhme.c
--- linux-2.5.73-bk3/drivers/net/sunhme.c	2003-06-22 11:32:41.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/sunhme.c	2003-06-26 05:00:28.000000000 -0700
@@ -2481,9 +2481,6 @@
 			return -EFAULT;
 		return 0;
 	} else if (ecmd.cmd == ETHTOOL_SSET) {
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-
 		/* Verify the settings we care about. */
 		if (ecmd.autoneg != AUTONEG_ENABLE &&
 		    ecmd.autoneg != AUTONEG_DISABLE)
diff -urN linux-2.5.73-bk3/drivers/net/tulip/tulip_core.c linux-2.5.73-bk4/drivers/net/tulip/tulip_core.c
--- linux-2.5.73-bk3/drivers/net/tulip/tulip_core.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk4/drivers/net/tulip/tulip_core.c	2003-06-26 05:00:28.000000000 -0700
@@ -94,6 +94,8 @@
 static int csr0 = 0x01A00000 | 0x9000;
 #elif defined(__arm__) || defined(__sh__)
 static int csr0 = 0x01A00000 | 0x4800;
+#elif defined(__mips__)
+static int csr0 = 0x00200000 | 0x4000;
 #else
 #warning Processor architecture undefined!
 static int csr0 = 0x00A00000 | 0x4800;
@@ -1491,6 +1493,16 @@
                        tp->flags &= ~HAS_MEDIA_TABLE;
                }
 #endif
+#ifdef CONFIG_MIPS_COBALT
+               if ((pdev->bus->number == 0) && 
+                   ((PCI_SLOT(pdev->devfn) == 7) ||
+                    (PCI_SLOT(pdev->devfn) == 12))) {
+                       /* Cobalt MAC address in first EEPROM locations. */
+                       sa_offset = 0;
+                       /* No media table either */
+                       tp->flags &= ~HAS_MEDIA_TABLE;
+               }
+#endif
 #ifdef __hppa__
 		/* 3x5 HSC (J3514A) has a broken srom */
 		if(ee_data[0] == 0x61 && ee_data[1] == 0x10) {
diff -urN linux-2.5.73-bk3/drivers/pci/Makefile linux-2.5.73-bk4/drivers/pci/Makefile
--- linux-2.5.73-bk3/drivers/pci/Makefile	2003-06-26 04:59:56.000000000 -0700
+++ linux-2.5.73-bk4/drivers/pci/Makefile	2003-06-26 05:00:28.000000000 -0700
@@ -8,7 +8,7 @@
 obj-$(CONFIG_PROC_FS) += proc.o
 
 ifndef CONFIG_SPARC64
-obj-$(CONFIG_PCI) += setup-res.o
+obj-y += setup-res.o
 endif
 
 obj-$(CONFIG_HOTPLUG) += hotplug.o
@@ -29,12 +29,7 @@
 obj-$(CONFIG_SGI_IP32) += setup-irq.o
 obj-$(CONFIG_X86_VISWS) += setup-irq.o
 
-# CompactPCI hotplug requires the pbus_* functions
-ifdef CONFIG_HOTPLUG_PCI_CPCI
-obj-y += setup-bus.o
-endif
-
-# Hotplug (eg, cardbus) now requires setup-bus
+# Cardbus & CompactPCI use setup-bus
 obj-$(CONFIG_HOTPLUG) += setup-bus.o
 
 ifndef CONFIG_X86
diff -urN linux-2.5.73-bk3/drivers/pci/hotplug/Kconfig linux-2.5.73-bk4/drivers/pci/hotplug/Kconfig
--- linux-2.5.73-bk3/drivers/pci/hotplug/Kconfig	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk4/drivers/pci/hotplug/Kconfig	2003-06-26 05:00:28.000000000 -0700
@@ -21,6 +21,31 @@
 
 	  When in doubt, say N.
 
+config HOTPLUG_PCI_FAKE
+	tristate "Fake PCI Hotplug driver"
+	depends on HOTPLUG_PCI
+	help
+	  Say Y here if you want to use the fake PCI hotplug driver. It can
+	  be used to simulate PCI hotplug events if even if your system is
+	  not PCI hotplug capable.
+
+	  This driver will "emulate" removing PCI devices from the system.
+	  If the "power" file is written to with "0" then the specified PCI
+	  device will be completely removed from the kernel.
+
+	  WARNING, this does NOT turn off the power to the PCI device.
+	  This is a "logical" removal, not a physical or electrical
+	  removal.
+
+	  Use this module at your own risk.  You have been warned!
+
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called fakephp. If you want to compile it
+	  as a module, say M here and read <file:Documentation/modules.txt>.
+
+	  When in doubt, say N.
+
 config HOTPLUG_PCI_COMPAQ
 	tristate "Compaq PCI Hotplug driver"
 	depends on HOTPLUG_PCI && X86
diff -urN linux-2.5.73-bk3/drivers/pci/hotplug/Makefile linux-2.5.73-bk4/drivers/pci/hotplug/Makefile
--- linux-2.5.73-bk3/drivers/pci/hotplug/Makefile	2003-06-22 11:32:59.000000000 -0700
+++ linux-2.5.73-bk4/drivers/pci/hotplug/Makefile	2003-06-26 05:00:28.000000000 -0700
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_HOTPLUG_PCI)		+= pci_hotplug.o
+obj-$(CONFIG_HOTPLUG_PCI_FAKE)		+= fakephp.o 
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
diff -urN linux-2.5.73-bk3/drivers/pci/hotplug/fakephp.c linux-2.5.73-bk4/drivers/pci/hotplug/fakephp.c
--- linux-2.5.73-bk3/drivers/pci/hotplug/fakephp.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk4/drivers/pci/hotplug/fakephp.c	2003-06-26 05:00:28.000000000 -0700
@@ -0,0 +1,232 @@
+/*
+ * Fake PCI Hot Plug Controller Driver
+ *
+ * Copyright (c) 2003 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (c) 2003 IBM Corp.
+ * Copyright (c) 2003 Rolf Eike Beer <eike-kernel@sf-tec.de>
+ *
+ * Based on ideas and code from:
+ * 	Vladimir Kondratiev <vladimir.kondratiev@intel.com>
+ *	Rolf Eike Beer <eike-kernel@sf-tec.de>
+ *
+ * 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, version 2 of the License.
+ *
+ * Send feedback to <greg@kroah.com>
+ */
+
+/*
+ *
+ * This driver will "emulate" removing PCI devices from the system.  If
+ * the "power" file is written to with "0" then the specified PCI device
+ * will be completely removed from the kernel.
+ *
+ * WARNING, this does NOT turn off the power to the PCI device.  This is
+ * a "logical" removal, not a physical or electrical removal.
+ *
+ * Use this module at your own risk, you have been warned!
+ *
+ * Enabling PCI devices is left as an exercise for the reader...
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci_hotplug.h"
+#include "../pci.h"
+
+#if !defined(CONFIG_HOTPLUG_PCI_FAKE_MODULE)
+	#define MY_NAME	"fakephp"
+#else
+	#define MY_NAME	THIS_MODULE->name
+#endif
+
+#define dbg(format, arg...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG "%s: " format,	\
+				MY_NAME , ## arg); 		\
+	} while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
+
+#define DRIVER_AUTHOR	"Greg Kroah-Hartman <greg@kroah.com>"
+#define DRIVER_DESC	"Fake PCI Hot Plug Controller Driver"
+
+struct dummy_slot {
+	struct list_head node;
+	struct hotplug_slot *slot;
+	struct pci_dev *dev;
+};
+
+static int debug;
+static LIST_HEAD(slot_list);
+
+static int enable_slot (struct hotplug_slot *slot);
+static int disable_slot (struct hotplug_slot *slot);
+
+static struct hotplug_slot_ops dummy_hotplug_slot_ops = {
+	.owner			= THIS_MODULE,
+	.enable_slot		= enable_slot,
+	.disable_slot		= disable_slot,
+};
+
+static void dummy_release(struct hotplug_slot *slot)
+{
+	struct dummy_slot *dslot = slot->private;
+
+	list_del(&dslot->node);
+	kfree(dslot->slot->info);
+	kfree(dslot->slot);
+	pci_dev_put(dslot->dev);
+	kfree(dslot);
+}
+
+static int add_slot(struct pci_dev *dev)
+{
+	struct dummy_slot *dslot;
+	struct hotplug_slot *slot;
+	int retval = -ENOMEM;
+
+	slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+	if (!slot)
+		goto error;
+	memset(slot, 0, sizeof(*slot));
+
+	slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
+	if (!slot->info)
+		goto error_slot;
+	memset(slot->info, 0, sizeof(struct hotplug_slot_info));
+
+	slot->info->power_status = 1;
+	slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
+	slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
+
+	slot->name = &dev->dev.bus_id[0];
+	dbg("slot->name = %s\n", slot->name);
+
+	dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL);
+	if (!dslot)
+		goto error_info;
+
+	slot->ops = &dummy_hotplug_slot_ops;
+	slot->release = &dummy_release;
+	slot->private = dslot;
+
+	retval = pci_hp_register(slot);
+	if (retval) {
+		err("pci_hp_register failed with error %d\n", retval);
+		goto error_dslot;
+	}
+
+	dslot->slot = slot;
+	dslot->dev = pci_dev_get(dev);
+	list_add (&dslot->node, &slot_list);
+	return retval;
+
+error_dslot:
+	kfree(dslot);
+error_info:
+	kfree(slot->info);
+error_slot:
+	kfree(slot);
+error:
+	return retval;
+}
+
+static int __init pci_scan_buses(void)
+{
+	struct pci_dev *dev = NULL;
+	int retval = 0;
+
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		retval = add_slot(dev);
+		if (retval) {
+			pci_dev_put(dev);
+			break;
+		}
+	}
+
+	return retval;
+}
+
+static void remove_slot(struct dummy_slot *dslot)
+{
+	int retval;
+
+	dbg("removing slot %s\n", dslot->slot->name);
+	retval = pci_hp_deregister(dslot->slot);
+	if (retval)
+		err("Problem unregistering a slot %s\n", dslot->slot->name);
+}
+
+static int enable_slot(struct hotplug_slot *hotplug_slot)
+{
+	return -ENODEV;
+}
+
+static int disable_slot(struct hotplug_slot *slot)
+{
+	struct dummy_slot *dslot;
+
+	if (!slot)
+		return -ENODEV;
+	dslot = slot->private;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, slot->name);
+
+	/* don't disable bridged devices just yet, we can't handle them easily... */
+	if (dslot->dev->subordinate) {
+		err("Can't remove PCI devices with other PCI devices behind it yet.\n");
+		return -ENODEV;
+	}
+
+	/* remove the device from the pci core */
+	pci_remove_bus_device(dslot->dev);
+
+	/* blow away this sysfs entry and other parts. */
+	remove_slot(dslot);
+
+	return 0;
+}
+
+static void cleanup_slots (void)
+{
+	struct list_head *tmp;
+	struct list_head *next;
+	struct dummy_slot *dslot;
+
+	list_for_each_safe (tmp, next, &slot_list) {
+		dslot = list_entry (tmp, struct dummy_slot, node);
+		remove_slot(dslot);
+	}
+	
+}
+
+static int __init dummyphp_init(void)
+{
+	info(DRIVER_DESC "\n");
+
+	return pci_scan_buses();
+}
+
+
+static void __exit dummyphp_exit(void)
+{
+	cleanup_slots();
+}
+
+module_init(dummyphp_init);
+module_exit(dummyphp_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+
diff -urN linux-2.5.73-bk3/drivers/pci/hotplug/ibmphp_hpc.c linux-2.5.73-bk4/drivers/pci/hotplug/ibmphp_hpc.c
--- linux-2.5.73-bk3/drivers/pci/hotplug/ibmphp_hpc.c	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk4/drivers/pci/hotplug/ibmphp_hpc.c	2003-06-26 05:00:28.000000000 -0700
@@ -152,11 +152,11 @@
 	u8 status;
 	int i;
 	void *wpg_addr;		// base addr + offset
-	ulong wpg_data,		// data to/from WPG LOHI format
-	ultemp, data;		// actual data HILO format
+	unsigned long wpg_data;	// data to/from WPG LOHI format
+	unsigned long ultemp;
+	unsigned long data;	// actual data HILO format
 
-
-	debug_polling ("%s - Entry WPGBbar[%lx] index[%x] \n", __FUNCTION__, (ulong) WPGBbar, index);
+	debug_polling ("%s - Entry WPGBbar[%p] index[%x] \n", __FUNCTION__, WPGBbar, index);
 
 	//--------------------------------------------------------------------
 	// READ - step 1
@@ -165,17 +165,17 @@
 	if (ctlr_ptr->ctlr_type == 0x02) {
 		data = WPG_READATADDR_MASK;
 		// fill in I2C address
-		ultemp = (ulong) ctlr_ptr->u.wpeg_ctlr.i2c_addr;
+		ultemp = (unsigned long)ctlr_ptr->u.wpeg_ctlr.i2c_addr;
 		ultemp = ultemp >> 1;
 		data |= (ultemp << 8);
 
 		// fill in index
-		data |= (ulong) index;
+		data |= (unsigned long)index;
 	} else if (ctlr_ptr->ctlr_type == 0x04) {
 		data = WPG_READDIRECT_MASK;
 
 		// fill in index
-		ultemp = (ulong) index;
+		ultemp = (unsigned long)index;
 		ultemp = ultemp << 8;
 		data |= ultemp;
 	} else {
@@ -184,14 +184,14 @@
 	}
 
 	wpg_data = swab32 (data);	// swap data before writing
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
 	// READ - step 2 : clear the message buffer
 	data = 0x00000000;
 	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
@@ -199,7 +199,7 @@
 	//                 2020 : [20] OR operation at [20] offset 0x20
 	data = WPG_I2CMCNTL_STARTOP_MASK;
 	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR;
+	wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
@@ -207,7 +207,7 @@
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
 		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET;
+		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
 		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
@@ -223,7 +223,7 @@
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
 		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET;
+		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
 		if (HPC_I2CSTATUS_CHECK (data))
@@ -237,7 +237,7 @@
 
 	//--------------------------------------------------------------------
 	// READ - step 6 : get DATA
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
 	wpg_data = readl (wpg_addr);
 	data = swab32 (wpg_data);
 
@@ -259,12 +259,12 @@
 {
 	u8 rc;
 	void *wpg_addr;		// base addr + offset
-	ulong wpg_data,		// data to/from WPG LOHI format 
-	ultemp, data;		// actual data HILO format
+	unsigned long wpg_data;	// data to/from WPG LOHI format 
+	unsigned long ultemp;
+	unsigned long data;	// actual data HILO format
 	int i;
 
-
-	debug_polling ("%s - Entry WPGBbar[%lx] index[%x] cmd[%x]\n", __FUNCTION__, (ulong) WPGBbar, index, cmd);
+	debug_polling ("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n", __FUNCTION__, WPGBbar, index, cmd);
 
 	rc = 0;
 	//--------------------------------------------------------------------
@@ -276,17 +276,17 @@
 	if (ctlr_ptr->ctlr_type == 0x02) {
 		data = WPG_WRITEATADDR_MASK;
 		// fill in I2C address
-		ultemp = (ulong) ctlr_ptr->u.wpeg_ctlr.i2c_addr;
+		ultemp = (unsigned long)ctlr_ptr->u.wpeg_ctlr.i2c_addr;
 		ultemp = ultemp >> 1;
 		data |= (ultemp << 8);
 
 		// fill in index
-		data |= (ulong) index;
+		data |= (unsigned long)index;
 	} else if (ctlr_ptr->ctlr_type == 0x04) {
 		data = WPG_WRITEDIRECT_MASK;
 
 		// fill in index
-		ultemp = (ulong) index;
+		ultemp = (unsigned long)index;
 		ultemp = ultemp << 8;
 		data |= ultemp;
 	} else {
@@ -295,14 +295,14 @@
 	}
 
 	wpg_data = swab32 (data);	// swap data before writing
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
 	// WRITE - step 2 : clear the message buffer
-	data = 0x00000000 | (ulong) cmd;
+	data = 0x00000000 | (unsigned long)cmd;
 	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
@@ -310,7 +310,7 @@
 	//                 2020 : [20] OR operation at [20] offset 0x20
 	data = WPG_I2CMCNTL_STARTOP_MASK;
 	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR;
+	wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
@@ -318,7 +318,7 @@
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
 		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET;
+		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
 		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
@@ -335,7 +335,7 @@
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
 		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET;
+		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
 		if (HPC_I2CSTATUS_CHECK (data))
@@ -543,7 +543,7 @@
 	int rc = 0;
 	int busindex;
 
-	debug_polling ("%s - Entry pslot[%lx] cmd[%x] pstatus[%lx]\n", __FUNCTION__, (ulong) pslot, cmd, (ulong) pstatus);
+	debug_polling ("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n", __FUNCTION__, pslot, cmd, pstatus);
 
 	if ((pslot == NULL)
 	    || ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) {
@@ -683,7 +683,7 @@
 	int rc = 0;
 	int timeout;
 
-	debug_polling ("%s - Entry pslot[%lx] cmd[%x]\n", __FUNCTION__, (ulong) pslot, cmd);
+	debug_polling ("%s - Entry pslot[%p] cmd[%x]\n", __FUNCTION__, pslot, cmd);
 	if (pslot == NULL) {
 		rc = -EINVAL;
 		err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc);
@@ -976,7 +976,7 @@
 {
 	int rc = 0;
 
-	debug ("%s - Entry pslot[%lx]\n", __FUNCTION__, (ulong) pslot);
+	debug ("%s - Entry pslot[%p]\n", __FUNCTION__, pslot);
 	rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
 	debug ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
 	return rc;
@@ -1004,8 +1004,7 @@
 	u8 disable = FALSE;
 	u8 update = FALSE;
 
-	debug ("process_changeinstatus - Entry pslot[%lx], poldslot[%lx]\n", (ulong) pslot,
-	       (ulong) poldslot);
+	debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot);
 
 	// bit 0 - HPC_SLOT_POWER
 	if ((pslot->status & 0x01) != (poldslot->status & 0x01))
diff -urN linux-2.5.73-bk3/drivers/pci/hotplug/ibmphp_res.c linux-2.5.73-bk4/drivers/pci/hotplug/ibmphp_res.c
--- linux-2.5.73-bk3/drivers/pci/hotplug/ibmphp_res.c	2003-06-22 11:33:13.000000000 -0700
+++ linux-2.5.73-bk4/drivers/pci/hotplug/ibmphp_res.c	2003-06-26 05:00:28.000000000 -0700
@@ -42,7 +42,7 @@
 static int update_bridge_ranges (struct bus_node **);
 static int add_range (int type, struct range_node *, struct bus_node *);
 static void fix_resources (struct bus_node *);
-static inline struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);
+static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);
 
 static LIST_HEAD(gbuses);
 LIST_HEAD(ibmphp_res_head);
@@ -1757,7 +1757,7 @@
 	return find_bus_wprev (bus_number, NULL, 0);
 }
 
-static inline struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag)
+static struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag)
 {
 	struct bus_node *bus_cur;
 	struct list_head *tmp;
diff -urN linux-2.5.73-bk3/drivers/pci/hotplug/pci_hotplug.h linux-2.5.73-bk4/drivers/pci/hotplug/pci_hotplug.h
--- linux-2.5.73-bk3/drivers/pci/hotplug/pci_hotplug.h	2003-06-22 11:32:41.000000000 -0700
+++ linux-2.5.73-bk4/drivers/pci/hotplug/pci_hotplug.h	2003-06-26 05:00:28.000000000 -0700
@@ -51,6 +51,8 @@
 	ssize_t (*show)(struct hotplug_slot *, char *);
 	ssize_t (*store)(struct hotplug_slot *, const char *, size_t);
 };
+#define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute, attr);
+
 /**
  * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
  * @owner: The module owner of this structure
@@ -130,12 +132,14 @@
 	char				*name;
 	struct hotplug_slot_ops		*ops;
 	struct hotplug_slot_info	*info;
+	void (*release) (struct hotplug_slot *slot);
 	void				*private;
 
 	/* Variables below this are for use only by the hotplug pci core. */
 	struct list_head		slot_list;
 	struct kobject			kobj;
 };
+#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj)
 
 extern int pci_hp_register		(struct hotplug_slot *slot);
 extern int pci_hp_deregister		(struct hotplug_slot *slot);
diff -urN linux-2.5.73-bk3/drivers/pci/hotplug/pci_hotplug_core.c linux-2.5.73-bk4/drivers/pci/hotplug/pci_hotplug_core.c
--- linux-2.5.73-bk3/drivers/pci/hotplug/pci_hotplug_core.c	2003-06-22 11:33:09.000000000 -0700
+++ linux-2.5.73-bk4/drivers/pci/hotplug/pci_hotplug_core.c	2003-06-26 05:00:28.000000000 -0700
@@ -74,20 +74,16 @@
 static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
 		struct attribute *attr, char *buf)
 {
-	struct hotplug_slot *slot=container_of(kobj,
-			struct hotplug_slot,kobj);
-	struct hotplug_slot_attribute *attribute =
-		container_of(attr, struct hotplug_slot_attribute, attr);
+	struct hotplug_slot *slot = to_hotplug_slot(kobj);
+	struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
 	return attribute->show ? attribute->show(slot, buf) : 0;
 }
 
 static ssize_t hotplug_slot_attr_store(struct kobject *kobj,
 		struct attribute *attr, const char *buf, size_t len)
 {
-	struct hotplug_slot *slot=container_of(kobj,
-			struct hotplug_slot,kobj);
-	struct hotplug_slot_attribute *attribute =
-		container_of(attr, struct hotplug_slot_attribute, attr);
+	struct hotplug_slot *slot = to_hotplug_slot(kobj);
+	struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
 	return attribute->store ? attribute->store(slot, buf, len) : 0;
 }
 
@@ -96,8 +92,16 @@
 	.store = hotplug_slot_attr_store,
 };
 
+static void hotplug_slot_release(struct kobject *kobj)
+{
+	struct hotplug_slot *slot = to_hotplug_slot(kobj);
+	if (slot->release)
+		slot->release(slot);
+}
+
 static struct kobj_type hotplug_slot_ktype = {
-	.sysfs_ops = &hotplug_slot_sysfs_ops
+	.sysfs_ops = &hotplug_slot_sysfs_ops,
+	.release = &hotplug_slot_release,
 };
 
 static decl_subsys(hotplug_slots, &hotplug_slot_ktype, NULL);
diff -urN linux-2.5.73-bk3/drivers/pci/probe.c linux-2.5.73-bk4/drivers/pci/probe.c
--- linux-2.5.73-bk3/drivers/pci/probe.c	2003-06-22 11:32:59.000000000 -0700
+++ linux-2.5.73-bk4/drivers/pci/probe.c	2003-06-26 05:00:28.000000000 -0700
@@ -18,7 +18,10 @@
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
 #define CARDBUS_RESERVE_BUSNR	3
 
+/* Ugh.  Need to stop exporting this to modules. */
 LIST_HEAD(pci_root_buses);
+EXPORT_SYMBOL(pci_root_buses);
+
 LIST_HEAD(pci_devices);
 
 /*
@@ -643,7 +646,7 @@
 	return 0;
 }
 
-static struct pci_bus * __devinit pci_alloc_primary_bus_parented(struct device *parent, int bus)
+struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata)
 {
 	struct pci_bus *b;
 
@@ -656,46 +659,39 @@
 	b = pci_alloc_bus();
 	if (!b)
 		return NULL;
-	
+
 	b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL);
 	if (!b->dev){
 		kfree(b);
 		return NULL;
 	}
-	
+
+	b->sysdata = sysdata;
+	b->ops = ops;
+
 	list_add_tail(&b->node, &pci_root_buses);
 
 	memset(b->dev,0,sizeof(*(b->dev)));
-	sprintf(b->dev->bus_id,"pci%d",bus);
-	strcpy(b->dev->name,"Host/PCI Bridge");
 	b->dev->parent = parent;
+	sprintf(b->dev->bus_id,"pci%04x:%02x", pci_domain_nr(b), bus);
+	strcpy(b->dev->name,"Host/PCI Bridge");
 	device_register(b->dev);
 
 	b->number = b->secondary = bus;
 	b->resource[0] = &ioport_resource;
 	b->resource[1] = &iomem_resource;
-	return b;
-}
 
-struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata)
-{
-	struct pci_bus *b = pci_alloc_primary_bus_parented(parent, bus);
-	if (b) {
-		b->sysdata = sysdata;
-		b->ops = ops;
-		b->subordinate = pci_scan_child_bus(b);
-		pci_bus_add_devices(b);
-	}
+	b->subordinate = pci_scan_child_bus(b);
+
+	pci_bus_add_devices(b);
+
 	return b;
 }
 EXPORT_SYMBOL(pci_scan_bus_parented);
 
-EXPORT_SYMBOL(pci_root_buses);
-
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pci_add_new_bus);
 EXPORT_SYMBOL(pci_do_scan_bus);
 EXPORT_SYMBOL(pci_scan_slot);
-EXPORT_SYMBOL(pci_scan_bus);
 EXPORT_SYMBOL(pci_scan_bridge);
 #endif
diff -urN linux-2.5.73-bk3/drivers/pnp/resource.c linux-2.5.73-bk4/drivers/pnp/resource.c
--- linux-2.5.73-bk3/drivers/pnp/resource.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk4/drivers/pnp/resource.c	2003-06-26 05:00:28.000000000 -0700
@@ -85,7 +85,6 @@
 
 int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data)
 {
-	int i;
 	struct pnp_irq *ptr;
 	if (!option)
 		return -EINVAL;
@@ -101,9 +100,13 @@
 		option->irq = data;
 
 #ifdef CONFIG_PCI
-	for (i=0; i<16; i++)
-		if (data->map & (1<<i))
-			pcibios_penalize_isa_irq(i);
+	{
+		int i;
+
+		for (i=0; i<16; i++)
+			if (data->map & (1<<i))
+				pcibios_penalize_isa_irq(i);
+	}
 #endif
 	return 0;
 }
diff -urN linux-2.5.73-bk3/drivers/scsi/NCR53C9x.c linux-2.5.73-bk4/drivers/scsi/NCR53C9x.c
--- linux-2.5.73-bk3/drivers/scsi/NCR53C9x.c	2003-06-22 11:32:37.000000000 -0700
+++ linux-2.5.73-bk4/drivers/scsi/NCR53C9x.c	2003-06-26 05:00:28.000000000 -0700
@@ -893,7 +893,7 @@
 int esp_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length,
 		  int inout)
 {
-	struct NCR_ESP *esp = (struct NCR_ESP *) SCpnt->device->host->hostdata;
+	struct NCR_ESP *esp = (struct NCR_ESP *)shost->hostdata;
 
 	if(inout)
 		return -EINVAL; /* not yet */
diff -urN linux-2.5.73-bk3/drivers/scsi/fd_mcs.c linux-2.5.73-bk4/drivers/scsi/fd_mcs.c
--- linux-2.5.73-bk3/drivers/scsi/fd_mcs.c	2003-06-22 11:32:41.000000000 -0700
+++ linux-2.5.73-bk4/drivers/scsi/fd_mcs.c	2003-06-26 05:00:28.000000000 -0700
@@ -589,7 +589,6 @@
 static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
 {
 	int len = 0;
-	int i;
 
 	if (inout)
 		return (-ENOSYS);
diff -urN linux-2.5.73-bk3/drivers/scsi/gdth.c linux-2.5.73-bk4/drivers/scsi/gdth.c
--- linux-2.5.73-bk3/drivers/scsi/gdth.c	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk4/drivers/scsi/gdth.c	2003-06-26 05:00:29.000000000 -0700
@@ -3662,7 +3662,7 @@
             pci_unmap_single(ha->pdev,scp->SCp.dma_handle,
                          scp->request_bufflen,scp->SCp.Message);
         if (scp->SCp.buffer) 
-            pci_unmap_single(ha->pdev,(dma_addr_t)(u32)scp->SCp.buffer,
+            pci_unmap_single(ha->pdev,(dma_addr_t)scp->SCp.buffer,
 						16,PCI_DMA_FROMDEVICE);
 #endif
         if (ha->status == S_OK) {
diff -urN linux-2.5.73-bk3/drivers/serial/8250_cs.c linux-2.5.73-bk4/drivers/serial/8250_cs.c
--- linux-2.5.73-bk3/drivers/serial/8250_cs.c	2003-06-26 04:59:57.000000000 -0700
+++ linux-2.5.73-bk4/drivers/serial/8250_cs.c	2003-06-26 05:00:29.000000000 -0700
@@ -435,7 +435,7 @@
 
 	i = CardServices(GetConfigurationInfo, handle, &config);
 	if (i != CS_SUCCESS) {
-		cs_error(handle, GetConfiguration, i);
+		cs_error(handle, GetConfigurationInfo, i);
 		return -1;
 	}
 	link->conf.Vcc = config.Vcc;
diff -urN linux-2.5.73-bk3/drivers/serial/8250_pci.c linux-2.5.73-bk4/drivers/serial/8250_pci.c
--- linux-2.5.73-bk3/drivers/serial/8250_pci.c	2003-06-22 11:33:06.000000000 -0700
+++ linux-2.5.73-bk4/drivers/serial/8250_pci.c	2003-06-26 05:00:29.000000000 -0700
@@ -322,7 +322,7 @@
  * hope) because it doesn't touch EEPROM settings to prevent conflicts
  * with other OSes (like M$ DOS).
  *
- *  SIIG support added by Andrey Panin <pazke@mail.tp.ru>, 10/1999
+ *  SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999
  * 
  * There is two family of SIIG serial cards with different PCI
  * interface chip and different configuration methods:
diff -urN linux-2.5.73-bk3/drivers/video/i810/i810_main.c linux-2.5.73-bk4/drivers/video/i810/i810_main.c
--- linux-2.5.73-bk3/drivers/video/i810/i810_main.c	2003-06-22 11:32:39.000000000 -0700
+++ linux-2.5.73-bk4/drivers/video/i810/i810_main.c	2003-06-26 05:00:30.000000000 -0700
@@ -1075,8 +1075,6 @@
 	struct i810fb_par *par = (struct i810fb_par *) info->par;
 	u8 *mmio = par->mmio_start_virtual, temp;
 
-	if (regno > 255) return 1;
-
 	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
 		if ((info->var.green.length == 5 && regno > 31) ||
 		    (info->var.green.length == 6 && regno > 63))
diff -urN linux-2.5.73-bk3/drivers/video/vgastate.c linux-2.5.73-bk4/drivers/video/vgastate.c
--- linux-2.5.73-bk3/drivers/video/vgastate.c	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk4/drivers/video/vgastate.c	2003-06-26 05:00:30.000000000 -0700
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/fb.h>
+#include <linux/vmalloc.h>
 #include <video/vga.h>
 
 struct regstate {
diff -urN linux-2.5.73-bk3/fs/binfmt_elf.c linux-2.5.73-bk4/fs/binfmt_elf.c
--- linux-2.5.73-bk3/fs/binfmt_elf.c	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk4/fs/binfmt_elf.c	2003-06-26 05:00:30.000000000 -0700
@@ -35,6 +35,7 @@
 #include <linux/compiler.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
@@ -191,6 +192,7 @@
 	NEW_AUX_ENT(AT_EUID, (elf_addr_t) tsk->euid);
 	NEW_AUX_ENT(AT_GID, (elf_addr_t) tsk->gid);
 	NEW_AUX_ENT(AT_EGID, (elf_addr_t) tsk->egid);
+ 	NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm));
 	if (k_platform) {
 		NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(long)u_platform);
 	}
diff -urN linux-2.5.73-bk3/fs/compat.c linux-2.5.73-bk4/fs/compat.c
--- linux-2.5.73-bk3/fs/compat.c	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk4/fs/compat.c	2003-06-26 05:00:30.000000000 -0700
@@ -451,7 +451,6 @@
 			break;
 		old_fs = get_fs();
 		set_fs(KERNEL_DS);
-		ret = sys_fcntl(fd, F_GETLK, (unsigned long)&f);
 		ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK :
 				((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
 				(unsigned long)&f);
diff -urN linux-2.5.73-bk3/fs/dcache.c linux-2.5.73-bk4/fs/dcache.c
--- linux-2.5.73-bk3/fs/dcache.c	2003-06-22 11:32:33.000000000 -0700
+++ linux-2.5.73-bk4/fs/dcache.c	2003-06-26 05:00:30.000000000 -0700
@@ -232,14 +232,17 @@
 	 * we might still populate it if it was a
 	 * working directory or similar).
 	 */
+	spin_lock(&dentry->d_lock);
 	if (atomic_read(&dentry->d_count) > 1) {
 		if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
+			spin_unlock(&dentry->d_lock);
 			spin_unlock(&dcache_lock);
 			return -EBUSY;
 		}
 	}
 
 	__d_drop(dentry);
+	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
 	return 0;
 }
diff -urN linux-2.5.73-bk3/fs/ext3/inode.c linux-2.5.73-bk4/fs/ext3/inode.c
--- linux-2.5.73-bk3/fs/ext3/inode.c	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk4/fs/ext3/inode.c	2003-06-26 05:00:30.000000000 -0700
@@ -1662,33 +1662,21 @@
  * This required during truncate. We need to physically zero the tail end
  * of that block so it doesn't yield old data if the file is later grown.
  */
-static int ext3_block_truncate_page(handle_t *handle,
+static int ext3_block_truncate_page(handle_t *handle, struct page *page,
 		struct address_space *mapping, loff_t from)
 {
 	unsigned long index = from >> PAGE_CACHE_SHIFT;
 	unsigned offset = from & (PAGE_CACHE_SIZE-1);
 	unsigned blocksize, iblock, length, pos;
 	struct inode *inode = mapping->host;
-	struct page *page;
 	struct buffer_head *bh;
 	int err;
 	void *kaddr;
 
 	blocksize = inode->i_sb->s_blocksize;
-	length = offset & (blocksize - 1);
-
-	/* Block boundary? Nothing to do */
-	if (!length)
-		return 0;
-
-	length = blocksize - length;
+	length = blocksize - (offset & (blocksize - 1));
 	iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 
-	page = grab_cache_page(mapping, index);
-	err = -ENOMEM;
-	if (!page)
-		goto out;
-
 	if (!page_has_buffers(page))
 		create_empty_buffers(page, blocksize, 0);
 
@@ -1756,7 +1744,6 @@
 unlock:
 	unlock_page(page);
 	page_cache_release(page);
-out:
 	return err;
 }
 
@@ -2137,13 +2124,15 @@
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	u32 *i_data = ei->i_data;
 	int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
+	struct address_space *mapping = inode->i_mapping;
 	int offsets[4];
 	Indirect chain[4];
 	Indirect *partial;
 	int nr = 0;
 	int n;
 	long last_block;
-	unsigned blocksize;
+	unsigned blocksize = inode->i_sb->s_blocksize;
+	struct page *page;
 
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 	    S_ISLNK(inode->i_mode)))
@@ -2155,16 +2144,36 @@
 
 	ext3_discard_prealloc(inode);
 
+	/*
+	 * We have to lock the EOF page here, because lock_page() nests
+	 * outside journal_start().
+	 */
+	if ((inode->i_size & (blocksize - 1)) == 0) {
+		/* Block boundary? Nothing to do */
+		page = NULL;
+	} else {
+		page = grab_cache_page(mapping,
+				inode->i_size >> PAGE_CACHE_SHIFT);
+		if (!page)
+			return;
+	}
+
 	handle = start_transaction(inode);
 	if (IS_ERR(handle)) {
+		if (page) {
+			clear_highpage(page);
+			flush_dcache_page(page);
+			unlock_page(page);
+			page_cache_release(page);
+		}
 		return;		/* AKPM: return what? */
 	}
 
-	blocksize = inode->i_sb->s_blocksize;
 	last_block = (inode->i_size + blocksize-1)
 					>> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
 
-	ext3_block_truncate_page(handle, inode->i_mapping, inode->i_size);
+	if (page)
+		ext3_block_truncate_page(handle, page, mapping, inode->i_size);
 
 	n = ext3_block_to_path(inode, last_block, offsets, NULL);
 	if (n == 0)
diff -urN linux-2.5.73-bk3/fs/ext3/namei.c linux-2.5.73-bk4/fs/ext3/namei.c
--- linux-2.5.73-bk3/fs/ext3/namei.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk4/fs/ext3/namei.c	2003-06-26 05:00:30.000000000 -0700
@@ -1295,12 +1295,12 @@
 	}
 	root = (struct dx_root *) bh->b_data;
 
-	EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
 	bh2 = ext3_append (handle, dir, &block, &retval);
 	if (!(bh2)) {
 		brelse(bh);
 		return retval;
 	}
+	EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
 	data1 = bh2->b_data;
 
 	/* The 0th block becomes the root, move the dirents out */
diff -urN linux-2.5.73-bk3/fs/hpfs/namei.c linux-2.5.73-bk4/fs/hpfs/namei.c
--- linux-2.5.73-bk3/fs/hpfs/namei.c	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk4/fs/hpfs/namei.c	2003-06-26 05:00:30.000000000 -0700
@@ -372,12 +372,15 @@
 		if (rep)
 			goto ret;
 		d_drop(dentry);
+		spin_lock(&dentry->d_lock);
 		if (atomic_read(&dentry->d_count) > 1 ||
 		    permission(inode, MAY_WRITE) ||
 		    get_write_access(inode)) {
+			spin_unlock(&dentry->d_lock);
 			d_rehash(dentry);
 			goto ret;
 		}
+		spin_unlock(&dentry->d_lock);
 		/*printk("HPFS: truncating file before delete.\n");*/
 		newattrs.ia_size = 0;
 		newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
diff -urN linux-2.5.73-bk3/fs/jbd/commit.c linux-2.5.73-bk4/fs/jbd/commit.c
--- linux-2.5.73-bk3/fs/jbd/commit.c	2003-06-22 11:33:15.000000000 -0700
+++ linux-2.5.73-bk4/fs/jbd/commit.c	2003-06-26 05:00:30.000000000 -0700
@@ -727,9 +727,8 @@
 			__journal_unfile_buffer(jh);
 			jh->b_transaction = 0;
 			jbd_unlock_bh_state(bh);
-			journal_remove_journal_head(bh);
-			if (buffer_freed(bh))
-				release_buffer_page(bh);
+			journal_remove_journal_head(bh);  /* needs a brelse */
+			release_buffer_page(bh);
 		}
 		spin_unlock(&journal->j_list_lock);
 	}
diff -urN linux-2.5.73-bk3/fs/nfs/dir.c linux-2.5.73-bk4/fs/nfs/dir.c
--- linux-2.5.73-bk3/fs/nfs/dir.c	2003-06-22 11:32:45.000000000 -0700
+++ linux-2.5.73-bk4/fs/nfs/dir.c	2003-06-26 05:00:30.000000000 -0700
@@ -1015,7 +1015,9 @@
 
 	lock_kernel();
 	spin_lock(&dcache_lock);
+	spin_lock(&dentry->d_lock);
 	if (atomic_read(&dentry->d_count) > 1) {
+		spin_unlock(&dentry->d_lock);
 		spin_unlock(&dcache_lock);
 		error = nfs_sillyrename(dir, dentry);
 		unlock_kernel();
@@ -1025,6 +1027,7 @@
 		__d_drop(dentry);
 		need_rehash = 1;
 	}
+	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
 	error = nfs_safe_remove(dentry);
 	if (!error)
diff -urN linux-2.5.73-bk3/fs/smbfs/inode.c linux-2.5.73-bk4/fs/smbfs/inode.c
--- linux-2.5.73-bk3/fs/smbfs/inode.c	2003-06-22 11:32:33.000000000 -0700
+++ linux-2.5.73-bk4/fs/smbfs/inode.c	2003-06-26 05:00:31.000000000 -0700
@@ -526,6 +526,7 @@
 		goto out_no_mem;
 
 	server->ops = mem;
+	smb_install_null_ops(server->ops);
 	server->mnt = mem + sizeof(struct smb_ops);
 
 	/* Setup NLS stuff */
diff -urN linux-2.5.73-bk3/fs/smbfs/proc.c linux-2.5.73-bk4/fs/smbfs/proc.c
--- linux-2.5.73-bk3/fs/smbfs/proc.c	2003-06-22 11:32:33.000000000 -0700
+++ linux-2.5.73-bk4/fs/smbfs/proc.c	2003-06-26 05:00:31.000000000 -0700
@@ -2802,6 +2802,13 @@
 	return result;
 }
 
+static int
+smb_proc_getattr_null(struct smb_sb_info *server, struct dentry *dir,
+		      struct smb_fattr *attr)
+{
+	return -EIO;
+}
+
 int
 smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr)
 {
@@ -3429,3 +3436,14 @@
 	/* .setattr	= smb_proc_setattr_unix, */
 	.truncate	= smb_proc_trunc64,
 };
+
+/* Place holder until real ops are in place */
+static struct smb_ops smb_ops_null =
+{
+	.getattr	= smb_proc_getattr_null,
+};
+
+void smb_install_null_ops(struct smb_ops *ops)
+{
+	install_ops(ops, &smb_ops_null);
+}
diff -urN linux-2.5.73-bk3/include/acpi/acpi_drivers.h linux-2.5.73-bk4/include/acpi/acpi_drivers.h
--- linux-2.5.73-bk3/include/acpi/acpi_drivers.h	2003-06-22 11:33:01.000000000 -0700
+++ linux-2.5.73-bk4/include/acpi/acpi_drivers.h	2003-06-26 05:00:31.000000000 -0700
@@ -73,6 +73,10 @@
 int acpi_pci_bind (struct acpi_device *device);
 int acpi_pci_bind_root (struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *bus);
 
+/* Arch-defined function to add a bus to the system */
+
+struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, int bus);
+
 #endif /*CONFIG_ACPI_PCI*/
 
 
diff -urN linux-2.5.73-bk3/include/asm-i386/io_apic.h linux-2.5.73-bk4/include/asm-i386/io_apic.h
--- linux-2.5.73-bk3/include/asm-i386/io_apic.h	2003-06-26 04:59:59.000000000 -0700
+++ linux-2.5.73-bk4/include/asm-i386/io_apic.h	2003-06-26 05:00:31.000000000 -0700
@@ -22,32 +22,44 @@
 /*
  * The structure of the IO-APIC:
  */
-struct IO_APIC_reg_00 {
-	__u32	__reserved_2	: 14,
-		LTS		:  1,
-		delivery_type	:  1,
-		__reserved_1	:  8,
-		ID		:  8;
-} __attribute__ ((packed));
+union IO_APIC_reg_00 {
+	u32	raw;
+	struct {
+		u32	__reserved_2	: 14,
+			LTS		:  1,
+			delivery_type	:  1,
+			__reserved_1	:  8,
+			ID		:  8;
+	} __attribute__ ((packed)) bits;
+};
 
-struct IO_APIC_reg_01 {
-	__u32	version		:  8,
-		__reserved_2	:  7,
-		PRQ		:  1,
-		entries		:  8,
-		__reserved_1	:  8;
-} __attribute__ ((packed));
+union IO_APIC_reg_01 {
+	u32	raw;
+	struct {
+		u32	version		:  8,
+			__reserved_2	:  7,
+			PRQ		:  1,
+			entries		:  8,
+			__reserved_1	:  8;
+	} __attribute__ ((packed)) bits;
+};
 
-struct IO_APIC_reg_02 {
-	__u32	__reserved_2	: 24,
-		arbitration	:  4,
-		__reserved_1	:  4;
-} __attribute__ ((packed));
+union IO_APIC_reg_02 {
+	u32	raw;
+	struct {
+		u32	__reserved_2	: 24,
+			arbitration	:  4,
+			__reserved_1	:  4;
+	} __attribute__ ((packed)) bits;
+};
 
-struct IO_APIC_reg_03 {
-	__u32	boot_DT		:  1,
-		__reserved_1	: 31;
-} __attribute__ ((packed));
+union IO_APIC_reg_03 {
+	u32	raw;
+	struct {
+		u32	boot_DT		:  1,
+			__reserved_1	: 31;
+	} __attribute__ ((packed)) bits;
+};
 
 /*
  * # of IO-APICs and # of IRQ routing registers
diff -urN linux-2.5.73-bk3/include/asm-ia64/pci.h linux-2.5.73-bk4/include/asm-ia64/pci.h
--- linux-2.5.73-bk3/include/asm-ia64/pci.h	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk4/include/asm-ia64/pci.h	2003-06-26 05:00:31.000000000 -0700
@@ -21,7 +21,6 @@
 #define PCIBIOS_MIN_MEM		0x10000000
 
 void pcibios_config_init(void);
-struct pci_bus * pcibios_scan_root(void *acpi_handle, int segment, int bus);
 
 struct pci_dev;
 
diff -urN linux-2.5.73-bk3/include/linux/elf.h linux-2.5.73-bk4/include/linux/elf.h
--- linux-2.5.73-bk3/include/linux/elf.h	2003-06-22 11:32:34.000000000 -0700
+++ linux-2.5.73-bk4/include/linux/elf.h	2003-06-26 05:00:32.000000000 -0700
@@ -163,6 +163,8 @@
 #define AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
 #define AT_CLKTCK 17	/* frequency at which times() increments */
 
+#define AT_SECURE 23   /* secure mode boolean */
+
 typedef struct dynamic{
   Elf32_Sword d_tag;
   union{
diff -urN linux-2.5.73-bk3/include/linux/security.h linux-2.5.73-bk4/include/linux/security.h
--- linux-2.5.73-bk3/include/linux/security.h	2003-06-22 11:33:02.000000000 -0700
+++ linux-2.5.73-bk4/include/linux/security.h	2003-06-26 05:00:32.000000000 -0700
@@ -45,6 +45,7 @@
 extern void cap_capset_set (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
 extern int cap_bprm_set_security (struct linux_binprm *bprm);
 extern void cap_bprm_compute_creds (struct linux_binprm *bprm);
+extern int cap_bprm_secureexec(struct linux_binprm *bprm);
 extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
 extern void cap_task_reparent_to_init (struct task_struct *p);
 extern int cap_syslog (int type);
@@ -131,6 +132,12 @@
  * 	first.
  * 	@bprm contains the linux_binprm structure.
  *	Return 0 if the hook is successful and permission is granted.
+ * @bprm_secureexec:
+ *      Return a boolean value (0 or 1) indicating whether a "secure exec" 
+ *      is required.  The flag is passed in the auxiliary table
+ *      on the initial stack to the ELF interpreter to indicate whether libc 
+ *      should enable secure mode.
+ *      @bprm contains the linux_binprm structure.
  *
  * Security hooks for filesystem operations.
  *
@@ -988,6 +995,7 @@
 	void (*bprm_compute_creds) (struct linux_binprm * bprm);
 	int (*bprm_set_security) (struct linux_binprm * bprm);
 	int (*bprm_check_security) (struct linux_binprm * bprm);
+	int (*bprm_secureexec) (struct linux_binprm * bprm);
 
 	int (*sb_alloc_security) (struct super_block * sb);
 	void (*sb_free_security) (struct super_block * sb);
@@ -1246,11 +1254,17 @@
 {
 	return security_ops->bprm_set_security (bprm);
 }
+
 static inline int security_bprm_check (struct linux_binprm *bprm)
 {
 	return security_ops->bprm_check_security (bprm);
 }
 
+static inline int security_bprm_secureexec (struct linux_binprm *bprm)
+{
+	return security_ops->bprm_secureexec (bprm);
+}
+
 static inline int security_sb_alloc (struct super_block *sb)
 {
 	return security_ops->sb_alloc_security (sb);
@@ -1907,6 +1921,11 @@
 	return 0;
 }
 
+static inline int security_bprm_secureexec (struct linux_binprm *bprm)
+{
+	return cap_bprm_secureexec(bprm);
+}
+
 static inline int security_sb_alloc (struct super_block *sb)
 {
 	return 0;
diff -urN linux-2.5.73-bk3/include/linux/smb_fs.h linux-2.5.73-bk4/include/linux/smb_fs.h
--- linux-2.5.73-bk3/include/linux/smb_fs.h	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk4/include/linux/smb_fs.h	2003-06-26 05:00:32.000000000 -0700
@@ -198,7 +198,7 @@
 	return (SMB_I(i)->open == server_from_inode(i)->generation);
 }
 
-
+extern void smb_install_null_ops(struct smb_ops *);
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SMB_FS_H */
diff -urN linux-2.5.73-bk3/include/linux/spinlock.h linux-2.5.73-bk4/include/linux/spinlock.h
--- linux-2.5.73-bk3/include/linux/spinlock.h	2003-06-22 11:32:45.000000000 -0700
+++ linux-2.5.73-bk4/include/linux/spinlock.h	2003-06-26 05:00:32.000000000 -0700
@@ -146,8 +146,13 @@
 /*
  * gcc versions before ~2.95 have a nasty bug with empty initializers.
  */
-typedef struct { } spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { }
+#if (__GNUC__ > 2)
+  typedef struct { } spinlock_t;
+  #define SPIN_LOCK_UNLOCKED (spinlock_t) { }
+#else
+  typedef struct { int gcc_is_buggy; } spinlock_t;
+  #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+#endif
 
 /*
  * If CONFIG_SMP is unset, declare the _raw_* definitions as nops
diff -urN linux-2.5.73-bk3/kernel/sched.c linux-2.5.73-bk4/kernel/sched.c
--- linux-2.5.73-bk3/kernel/sched.c	2003-06-22 11:33:08.000000000 -0700
+++ linux-2.5.73-bk4/kernel/sched.c	2003-06-26 05:00:32.000000000 -0700
@@ -784,7 +784,13 @@
 
 	minload = 10000000;
 	for_each_node_with_cpus(i) {
-		load = atomic_read(&node_nr_running[i]);
+		/*
+		 * Node load is always divided by nr_cpus_node to normalise 
+		 * load values in case cpu count differs from node to node.
+		 * We first multiply node_nr_running by 10 to get a little
+		 * better resolution.   
+		 */
+		load = 10 * atomic_read(&node_nr_running[i]) / nr_cpus_node(i);
 		if (load < minload) {
 			minload = load;
 			node = i;
@@ -820,19 +826,26 @@
  * geometrically deccaying weight to the load measure:
  *      load_{t} = load_{t-1}/2 + nr_node_running_{t}
  * This way sudden load peaks are flattened out a bit.
+ * Node load is divided by nr_cpus_node() in order to compare nodes
+ * of different cpu count but also [first] multiplied by 10 to 
+ * provide better resolution.
  */
 static int find_busiest_node(int this_node)
 {
 	int i, node = -1, load, this_load, maxload;
 
+	if (!nr_cpus_node(this_node))
+		return node;
 	this_load = maxload = (this_rq()->prev_node_load[this_node] >> 1)
-		+ atomic_read(&node_nr_running[this_node]);
+		+ (10 * atomic_read(&node_nr_running[this_node])
+		/ nr_cpus_node(this_node));
 	this_rq()->prev_node_load[this_node] = this_load;
-	for (i = 0; i < numnodes; i++) {
+	for_each_node_with_cpus(i) {
 		if (i == this_node)
 			continue;
 		load = (this_rq()->prev_node_load[i] >> 1)
-			+ atomic_read(&node_nr_running[i]);
+			+ (10 * atomic_read(&node_nr_running[i])
+			/ nr_cpus_node(i));
 		this_rq()->prev_node_load[i] = load;
 		if (load > maxload && (100*load > NODE_THRESHOLD*this_load)) {
 			maxload = load;
@@ -1691,6 +1704,7 @@
 {
 	struct sched_param lp;
 	int retval = -EINVAL;
+	int oldprio;
 	prio_array_t *array;
 	unsigned long flags;
 	runqueue_t *rq;
@@ -1757,12 +1771,24 @@
 	retval = 0;
 	p->policy = policy;
 	p->rt_priority = lp.sched_priority;
+	oldprio = p->prio;
 	if (policy != SCHED_NORMAL)
 		p->prio = MAX_USER_RT_PRIO-1 - p->rt_priority;
 	else
 		p->prio = p->static_prio;
-	if (array)
+	if (array) {
 		__activate_task(p, task_rq(p));
+		/*
+		 * Reschedule if we are currently running on this runqueue and
+		 * our priority decreased, or if we are not currently running on
+		 * this runqueue and our priority is higher than the current's
+		 */
+		if (rq->curr == p) {
+			if (p->prio > oldprio)
+				resched_task(rq->curr);
+		} else if (p->prio < rq->curr->prio)
+			resched_task(rq->curr);
+	}
 
 out_unlock:
 	task_rq_unlock(rq, &flags);
diff -urN linux-2.5.73-bk3/kernel/sys.c linux-2.5.73-bk4/kernel/sys.c
--- linux-2.5.73-bk3/kernel/sys.c	2003-06-26 05:00:10.000000000 -0700
+++ linux-2.5.73-bk4/kernel/sys.c	2003-06-26 05:00:32.000000000 -0700
@@ -5,6 +5,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/utsname.h>
@@ -1220,7 +1221,7 @@
 			? -EFAULT : 0;
 }
 
-#if !defined(__ia64__) && !defined(CONFIG_V850)
+#if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64) || defined(CONFIG_V850))
 
 /*
  *	Back compatibility for getrlimit. Needed for some apps.
diff -urN linux-2.5.73-bk3/mm/mmap.c linux-2.5.73-bk4/mm/mmap.c
--- linux-2.5.73-bk3/mm/mmap.c	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk4/mm/mmap.c	2003-06-26 05:00:33.000000000 -0700
@@ -777,7 +777,7 @@
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	int found_hole = 0;
+	unsigned long start_addr;
 
 	if (len > TASK_SIZE)
 		return -ENOMEM;
@@ -789,21 +789,29 @@
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
-	addr = mm->free_area_cache;
+	start_addr = addr = mm->free_area_cache;
 
+full_search:
 	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
 		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (TASK_SIZE - len < addr)
+		if (TASK_SIZE - len < addr) {
+			/*
+			 * Start a new search - just in case we missed
+			 * some holes.
+			 */
+			if (start_addr != TASK_UNMAPPED_BASE) {
+				start_addr = addr = TASK_UNMAPPED_BASE;
+				goto full_search;
+			}
 			return -ENOMEM;
-		/*
-		 * Record the first available hole.
-		 */
-		if (!found_hole && (!vma || addr < vma->vm_start)) {
-			mm->free_area_cache = addr;
-			found_hole = 1;
 		}
-		if (!vma || addr + len <= vma->vm_start)
+		if (!vma || addr + len <= vma->vm_start) {
+			/*
+			 * Remember the place where we stopped the search:
+			 */
+			mm->free_area_cache = addr + len;
 			return addr;
+		}
 		addr = vma->vm_end;
 	}
 }
diff -urN linux-2.5.73-bk3/security/capability.c linux-2.5.73-bk4/security/capability.c
--- linux-2.5.73-bk3/security/capability.c	2003-06-22 11:32:41.000000000 -0700
+++ linux-2.5.73-bk4/security/capability.c	2003-06-26 05:00:35.000000000 -0700
@@ -158,6 +158,17 @@
 	current->keep_capabilities = 0;
 }
 
+int cap_bprm_secureexec (struct linux_binprm *bprm)
+{
+	/* If/when this module is enhanced to incorporate capability
+	   bits on files, the test below should be extended to also perform a 
+	   test between the old and new capability sets.  For now,
+	   it simply preserves the legacy decision algorithm used by
+	   the old userland. */
+	return (current->euid != current->uid ||
+		current->egid != current->gid);
+}
+
 /* moved from kernel/sys.c. */
 /* 
  * cap_emulate_setxuid() fixes the effective / permitted capabilities of
@@ -271,6 +282,7 @@
 EXPORT_SYMBOL(cap_capset_set);
 EXPORT_SYMBOL(cap_bprm_set_security);
 EXPORT_SYMBOL(cap_bprm_compute_creds);
+EXPORT_SYMBOL(cap_bprm_secureexec);
 EXPORT_SYMBOL(cap_task_post_setuid);
 EXPORT_SYMBOL(cap_task_reparent_to_init);
 EXPORT_SYMBOL(cap_syslog);
@@ -289,6 +301,7 @@
 
 	.bprm_compute_creds =		cap_bprm_compute_creds,
 	.bprm_set_security =		cap_bprm_set_security,
+	.bprm_secureexec =		cap_bprm_secureexec,
 
 	.task_post_setuid =		cap_task_post_setuid,
 	.task_reparent_to_init =	cap_task_reparent_to_init,
diff -urN linux-2.5.73-bk3/security/dummy.c linux-2.5.73-bk4/security/dummy.c
--- linux-2.5.73-bk3/security/dummy.c	2003-06-22 11:32:36.000000000 -0700
+++ linux-2.5.73-bk4/security/dummy.c	2003-06-26 05:00:35.000000000 -0700
@@ -122,6 +122,16 @@
 	return 0;
 }
 
+static int dummy_bprm_secureexec (struct linux_binprm *bprm)
+{
+	/* The new userland will simply use the value provided
+	   in the AT_SECURE field to decide whether secure mode
+	   is required.  Hence, this logic is required to preserve
+	   the legacy decision algorithm used by the old userland. */
+	return (current->euid != current->uid ||
+		current->egid != current->gid);
+}
+
 static int dummy_sb_alloc_security (struct super_block *sb)
 {
 	return 0;
@@ -788,6 +798,7 @@
 	set_to_dummy_if_null(ops, bprm_compute_creds);
 	set_to_dummy_if_null(ops, bprm_set_security);
 	set_to_dummy_if_null(ops, bprm_check_security);
+	set_to_dummy_if_null(ops, bprm_secureexec);
 	set_to_dummy_if_null(ops, sb_alloc_security);
 	set_to_dummy_if_null(ops, sb_free_security);
 	set_to_dummy_if_null(ops, sb_kern_mount);
