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

diff -urN linux-2.5.73-bk9/Makefile linux-2.5.73-bk10/Makefile
--- linux-2.5.73-bk9/Makefile	2003-07-02 04:57:13.000000000 -0700
+++ linux-2.5.73-bk10/Makefile	2003-07-02 04:57:22.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 73
-EXTRAVERSION = -bk9
+EXTRAVERSION = -bk10
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -388,7 +388,7 @@
 kallsyms.o := .tmp_kallsyms2.o
 
 quiet_cmd_kallsyms = KSYM    $@
-cmd_kallsyms = $(NM) -n $< | scripts/kallsyms > $@
+cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) > $@
 
 .tmp_kallsyms1.o .tmp_kallsyms2.o: %.o: %.S scripts FORCE
 	$(call if_changed_dep,as_o_S)
diff -urN linux-2.5.73-bk9/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S linux-2.5.73-bk10/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S
--- linux-2.5.73-bk9/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S	2003-06-22 11:32:41.000000000 -0700
+++ linux-2.5.73-bk10/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S	2003-07-02 04:57:22.000000000 -0700
@@ -110,6 +110,8 @@
 	movc  %d0,%CACR
 	nop
 
+
+#ifdef CONFIG_ROMFS_FS
 	/*
 	 *	Move ROM filesystem above bss :-)
 	 */
@@ -131,6 +133,12 @@
 	cmp.l	%a0, %a2			/* Check if at end */
 	bne	_copy_romfs
 
+#else /* CONFIG_ROMFS_FS */
+	lea.l	_ebss, %a1
+	move.l	%a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
+
 	/*
 	 *	Zero out the bss region.
 	 */
diff -urN linux-2.5.73-bk9/arch/m68knommu/platform/68360/ints.c linux-2.5.73-bk10/arch/m68knommu/platform/68360/ints.c
--- linux-2.5.73-bk9/arch/m68knommu/platform/68360/ints.c	2003-06-22 11:32:27.000000000 -0700
+++ linux-2.5.73-bk10/arch/m68knommu/platform/68360/ints.c	2003-07-02 04:57:22.000000000 -0700
@@ -40,23 +40,21 @@
 
 extern void *_ramvec[];
 
+/* The number of spurious interrupts */
+volatile unsigned int num_spurious;
+unsigned int local_irq_count[NR_CPUS];
+
 /* irq node variables for the 32 (potential) on chip sources */
-static irq_node_t *int_irq_list[INTERNAL_IRQS];
+static irq_node_t int_irq_list[INTERNAL_IRQS];
 
-static int int_irq_count[INTERNAL_IRQS];
 static short int_irq_ablecount[INTERNAL_IRQS];
 
-static void int_badint(int irq, void *dev_id, struct pt_regs *fp)
-{
-	num_spurious += 1;
-}
-
 /*
  * This function should be called during kernel startup to initialize
  * IRQ handling routines.
  */
 
-void M68360_init_IRQ(void)
+void init_IRQ(void)
 {
 	int i;
 	int vba = (CPM_VECTOR_BASE<<4);
@@ -128,13 +126,14 @@
 
 	/* initialize handlers */
 	for (i = 0; i < INTERNAL_IRQS; i++) {
-		int_irq_list[i] = NULL;
-
-		int_irq_ablecount[i] = 0;
-		int_irq_count[i] = 0;
+		int_irq_list[i].handler = NULL;
+		int_irq_list[i].flags   = IRQ_FLG_STD;
+		int_irq_list[i].dev_id  = NULL;
+		int_irq_list[i].devname = NULL;
 	}
 }
 
+#if 0
 void M68360_insert_irq(irq_node_t **list, irq_node_t *node)
 {
 	unsigned long flags;
@@ -178,9 +177,10 @@
 	local_irq_restore(flags);
 	printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
 }
+#endif
 
-int M68360_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-                         unsigned long flags, const char *devname, void *dev_id)
+int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+                unsigned long flags, const char *devname, void *dev_id)
 {
 	int mask = (1<<irq);
 
@@ -191,27 +191,22 @@
 		return -ENXIO;
 	}
 
-	if (!int_irq_list[irq]) {
-		int_irq_list[irq] = new_irq_node();
-		int_irq_list[irq]->flags   = IRQ_FLG_STD;
-	}
-
-	if (!(int_irq_list[irq]->flags & IRQ_FLG_STD)) {
-		if (int_irq_list[irq]->flags & IRQ_FLG_LOCK) {
+	if (!(int_irq_list[irq].flags & IRQ_FLG_STD)) {
+		if (int_irq_list[irq].flags & IRQ_FLG_LOCK) {
 			printk("%s: IRQ %d from %s is not replaceable\n",
-			       __FUNCTION__, irq, int_irq_list[irq]->devname);
+			       __FUNCTION__, irq, int_irq_list[irq].devname);
 			return -EBUSY;
 		}
 		if (flags & IRQ_FLG_REPLACE) {
 			printk("%s: %s can't replace IRQ %d from %s\n",
-			       __FUNCTION__, devname, irq, int_irq_list[irq]->devname);
+			       __FUNCTION__, devname, irq, int_irq_list[irq].devname);
 			return -EBUSY;
 		}
 	}
-	int_irq_list[irq]->handler = handler;
-	int_irq_list[irq]->flags   = flags;
-	int_irq_list[irq]->dev_id  = dev_id;
-	int_irq_list[irq]->devname = devname;
+	int_irq_list[irq].handler = handler;
+	int_irq_list[irq].flags   = flags;
+	int_irq_list[irq].dev_id  = dev_id;
+	int_irq_list[irq].devname = devname;
 
 	/* enable in the CIMR */
 	if (!int_irq_ablecount[irq])
@@ -221,24 +216,25 @@
 	return 0;
 }
 
-void M68360_free_irq(unsigned int irq, void *dev_id)
+void free_irq(unsigned int irq, void *dev_id)
 {
 	if (irq >= INTERNAL_IRQS) {
 		printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
 		return;
 	}
 
-	if (int_irq_list[irq]->dev_id != dev_id)
+	if (int_irq_list[irq].dev_id != dev_id)
 		printk("%s: removing probably wrong IRQ %d from %s\n",
-		       __FUNCTION__, irq, int_irq_list[irq]->devname);
-	int_irq_list[irq]->handler = int_badint;
-	int_irq_list[irq]->flags   = IRQ_FLG_STD;
-	int_irq_list[irq]->dev_id  = NULL;
-	int_irq_list[irq]->devname = NULL;
+		       __FUNCTION__, irq, int_irq_list[irq].devname);
+	int_irq_list[irq].handler = NULL;
+	int_irq_list[irq].flags   = IRQ_FLG_STD;
+	int_irq_list[irq].dev_id  = NULL;
+	int_irq_list[irq].devname = NULL;
 
 	*(volatile unsigned long *)0xfffff304 |= 1<<irq;
 }
 
+#if 0
 /*
  * Enable/disable a particular machine specific interrupt source.
  * Note that this may affect other interrupts in case of a shared interrupt.
@@ -273,6 +269,27 @@
 	/* disable the interrupt */
 	*(volatile unsigned long *)0xfffff304 |= 1<<irq;
 }
+#endif
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+	int i;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		if (int_irq_list[i].flags & IRQ_FLG_STD)
+			continue;
+
+		seq_printf(p, "%3d: %10u ", i, kstat_cpu(0).irqs[i]);
+		if (int_irq_list[i].flags & IRQ_FLG_LOCK)
+			seq_printf(p, "L ");
+		else
+			seq_printf(p, "  ");
+		seq_printf(p, "%s\n", int_irq_list[i].devname);
+	}
+	seq_printf(p, "   : %10u   spurious\n", num_spurious);
+
+	return 0;
+}
 
 /* The 68k family did not have a good way to determine the source
  * of interrupts until later in the family.  The EC000 core does
@@ -280,7 +297,7 @@
  * into one vector and look in the blasted mask register...
  * This code is designed to be fast, almost constant time, not clean!
  */
-void M68360_do_irq(int vec, struct pt_regs *fp)
+void process_int(int vec, struct pt_regs *fp)
 {
 	int irq;
 	int mask;
@@ -295,25 +312,14 @@
 	/* Bugger all that weirdness. For the moment, I seem to know where I came from;
 	 * vec is passed from a specific ISR, so I'll use it. */
 
-	if (int_irq_list[irq] && int_irq_list[irq]->handler) {
-		int_irq_list[irq]->handler(irq , int_irq_list[irq]->dev_id, fp);
-		int_irq_count[irq]++;
+	if (int_irq_list[irq].handler) {
+		int_irq_list[irq].handler(irq , int_irq_list[irq].dev_id, fp);
+		kstat_cpu(0).irqs[irq]++;
 		pquicc->intr_cisr = (1 << vec); /* indicate that irq has been serviced */
 	} else {
 		printk("unregistered interrupt %d!\nTurning it off in the CIMR...\n", irq);
 		/* *(volatile unsigned long *)0xfffff304 |= mask; */
 		pquicc->intr_cimr &= ~(1 << vec);
+		num_spurious += 1;
 	}
 }
-
-void config_M68360_irq(void)
-{
-	mach_default_handler = NULL;
-	mach_init_IRQ        = M68360_init_IRQ;
-	mach_request_irq     = M68360_request_irq;
-	mach_free_irq        = M68360_free_irq;
-	mach_enable_irq      = M68360_enable_irq;
-	mach_disable_irq     = M68360_disable_irq;
-	mach_process_int     = M68360_do_irq;
-}
-
diff -urN linux-2.5.73-bk9/arch/ppc64/kernel/cputable.c linux-2.5.73-bk10/arch/ppc64/kernel/cputable.c
--- linux-2.5.73-bk9/arch/ppc64/kernel/cputable.c	2003-06-22 11:32:30.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/kernel/cputable.c	2003-07-02 04:57:23.000000000 -0700
@@ -37,7 +37,8 @@
 struct cpu_spec	cpu_specs[] = {
     {	/* Power3 */
 	    0xffff0000, 0x00400000, "Power3 (630)",
-	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
+	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
 	    128, 128,
 	    __setup_cpu_power3,
@@ -45,7 +46,8 @@
     },
     {	/* Power3+ */
 	    0xffff0000, 0x00410000, "Power3 (630+)",
-	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
+	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
 	    128, 128,
 	    __setup_cpu_power3,
@@ -53,7 +55,8 @@
     },
     {	/* Northstar */
 	    0xffff0000, 0x00330000, "Northstar",
-	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
+	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
 	    128, 128,
 	    __setup_cpu_power3,
@@ -61,7 +64,8 @@
     },
     {	/* Pulsar */
 	    0xffff0000, 0x00340000, "Pulsar",
-	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
+	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
 	    128, 128,
 	    __setup_cpu_power3,
@@ -69,7 +73,8 @@
     },
     {	/* I-star */
 	    0xffff0000, 0x00360000, "I-star",
-	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
+	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
 	    128, 128,
 	    __setup_cpu_power3,
@@ -77,7 +82,8 @@
     },
     {	/* S-star */
 	    0xffff0000, 0x00370000, "S-star",
-	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
+	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+		    CPU_FTR_DABR | CPU_FTR_IABR,
 	    COMMON_USER_PPC64,
 	    128, 128,
 	    __setup_cpu_power3,
@@ -86,7 +92,7 @@
     {	/* Power4 */
 	    0xffff0000, 0x00350000, "Power4",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-	    CPU_FTR_PPCAS_ARCH_V2,
+	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR,
 	    COMMON_USER_PPC64,
 	    128, 128,
 	    __setup_cpu_power4,
@@ -95,7 +101,7 @@
     {	/* Power4+ */
 	    0xffff0000, 0x00380000, "Power4+",
 	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-	    CPU_FTR_PPCAS_ARCH_V2,
+	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR,
 	    COMMON_USER_PPC64,
 	    128, 128,
 	    __setup_cpu_power4,
@@ -104,7 +110,7 @@
     {	/* default match */
 	    0x00000000, 0x00000000, "(Power4-Compatible)",
   	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-	    CPU_FTR_PPCAS_ARCH_V2,
+	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR,
 	    COMMON_USER_PPC64,
 	    128, 128,
 	    __setup_cpu_power4,
diff -urN linux-2.5.73-bk9/arch/ppc64/kernel/entry.S linux-2.5.73-bk10/arch/ppc64/kernel/entry.S
--- linux-2.5.73-bk9/arch/ppc64/kernel/entry.S	2003-06-22 11:32:30.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/kernel/entry.S	2003-07-02 04:57:23.000000000 -0700
@@ -141,9 +141,6 @@
 	cmpl	0,r3,r10
 	blt	30f
 	neg	r3,r3
-	cmpi	0,r3,ERESTARTNOHAND
-	bne	22f
-	li	r3,EINTR
 22:	ld	r10,_CCR(r1)	/* Set SO bit in CR */
 	oris	r10,r10,0x1000
 	std	r10,_CCR(r1)
@@ -199,9 +196,6 @@
 	cmpl	0,r3,r10
 	blt	60f
 	neg	r3,r3
-	cmpi	0,r3,ERESTARTNOHAND
-	bne	57f
-	li	r3,EINTR
 57:	ld	r10,_CCR(r1)	/* Set SO bit in CR */
 	oris	r10,r10,0x1000
 	std	r10,_CCR(r1)
diff -urN linux-2.5.73-bk9/arch/ppc64/kernel/pSeries_pci.c linux-2.5.73-bk10/arch/ppc64/kernel/pSeries_pci.c
--- linux-2.5.73-bk9/arch/ppc64/kernel/pSeries_pci.c	2003-06-22 11:33:36.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/kernel/pSeries_pci.c	2003-07-02 04:57:23.000000000 -0700
@@ -295,6 +295,7 @@
 	int *buid_vals;
 	char *model;
 	enum phb_types phb_type;
+ 	struct property *of_prop;
 
 	model = (char *)get_property(dev, "model", NULL);
 
@@ -341,6 +342,21 @@
 		return NULL;
 	}
 
+	of_prop = (struct property *)alloc_bootmem(sizeof(struct property) +
+			sizeof(phb->global_number));        
+
+	if (!of_prop) {
+		kfree(phb);
+		return NULL;
+	}
+
+	memset(of_prop, 0, sizeof(struct property));
+	of_prop->name = "linux,pci-domain";
+	of_prop->length = sizeof(phb->global_number);
+	of_prop->value = (unsigned char *)&of_prop[1];
+	memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));
+	prom_add_property(dev, of_prop);
+
 	phb->first_busno =  bus_range[0];
 	phb->last_busno  =  bus_range[1];
 
@@ -352,26 +368,12 @@
 	if (buid_vals == NULL) {
 		phb->buid = 0;
 	} else {
-		struct pci_bus check;
-		if (sizeof(check.number) == 1 || sizeof(check.primary) == 1 ||
-		    sizeof(check.secondary) == 1 || sizeof(check.subordinate) == 1) {
-			udbg_printf("pSeries_pci:  this system has large bus numbers and the kernel was not\n"
-			      "built with the patch that fixes include/linux/pci.h struct pci_bus so\n"
-			      "number, primary, secondary and subordinate are ints.\n");
-			panic("pSeries_pci:  this system has large bus numbers and the kernel was not\n"
-			      "built with the patch that fixes include/linux/pci.h struct pci_bus so\n"
-			      "number, primary, secondary and subordinate are ints.\n");
-		}
-
 		if (len < 2 * sizeof(int))
 			// Support for new OF that only has 1 integer for buid.
 			phb->buid = (unsigned long)buid_vals[0];
 		else
 			phb->buid = (((unsigned long)buid_vals[0]) << 32UL) |
 				(((unsigned long)buid_vals[1]) & 0xffffffff);
-
-		phb->first_busno += (phb->global_number << 8);
-		phb->last_busno += (phb->global_number << 8);
 	}
 
 	return phb;
diff -urN linux-2.5.73-bk9/arch/ppc64/kernel/pci.c linux-2.5.73-bk10/arch/ppc64/kernel/pci.c
--- linux-2.5.73-bk9/arch/ppc64/kernel/pci.c	2003-06-22 11:33:13.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/kernel/pci.c	2003-07-02 04:57:23.000000000 -0700
@@ -380,6 +380,19 @@
 	return hose->global_number;
 }
 
+/* Set the name of the bus as it appears in /proc/bus/pci */
+int pci_name_bus(char *name, struct pci_bus *bus)
+{
+	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+
+	if (hose->buid)
+		sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
+	else
+		sprintf(name, "%02x", bus->number);
+
+	return 0;
+}
+
 /*
  * Platform support for /proc/bus/pci/X/Y mmap()s,
  * modelled on the sparc64 implementation by Dave Miller.
diff -urN linux-2.5.73-bk9/arch/ppc64/kernel/pci.h linux-2.5.73-bk10/arch/ppc64/kernel/pci.h
--- linux-2.5.73-bk9/arch/ppc64/kernel/pci.h	2003-06-22 11:32:28.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/kernel/pci.h	2003-07-02 04:57:23.000000000 -0700
@@ -42,14 +42,6 @@
 void pci_fix_bus_sysdata(void);
 struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
-/*******************************************************************
- * Helper macros for extracting data from pci structures.  
- *   PCI_GET_PHB_PTR(struct pci_dev*)    returns the Phb pointer.
- *   PCI_GET_PHB_NUMBER(struct pci_dev*) returns the Phb number.
- *   PCI_GET_BUS_NUMBER(struct pci_dev*) returns the bus number.
- *******************************************************************/
 #define PCI_GET_PHB_PTR(dev)    (((struct device_node *)(dev)->sysdata)->phb)
-#define PCI_GET_PHB_NUMBER(dev) (((dev)->bus->number&0x00FFFF00)>>8)
-#define PCI_GET_BUS_NUMBER(dev) ((dev)->bus->number&0x0000FF)
 
 #endif /* __PPC_KERNEL_PCI_H__ */
diff -urN linux-2.5.73-bk9/arch/ppc64/kernel/pci_dn.c linux-2.5.73-bk10/arch/ppc64/kernel/pci_dn.c
--- linux-2.5.73-bk9/arch/ppc64/kernel/pci_dn.c	2003-06-22 11:33:35.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/kernel/pci_dn.c	2003-07-02 04:57:23.000000000 -0700
@@ -196,23 +196,11 @@
 {
 	struct list_head *ln;
 	struct pci_bus *bus;
-	struct pci_controller *phb;
-	int newnum;
 
 	for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
 		bus = pci_bus_b(ln);
-		if (bus->self) {
+		if (bus->self)
 			bus->sysdata = bus->self->sysdata;
-			/* Also fixup the bus number on large bus systems to
-			 * include the PHB# in the next byte
-			 */
-			phb = PCI_GET_DN(bus)->phb;
-			if (phb && phb->buid) {
-				newnum = (phb->global_number << 8) | bus->number;
-				bus->number = newnum;
-				sprintf(bus->name, "PCI Bus #%x", bus->number);
-			}
-		}
 		pci_fixup_bus_sysdata_list(&bus->children);
 	}
 }
diff -urN linux-2.5.73-bk9/arch/ppc64/kernel/prom.c linux-2.5.73-bk10/arch/ppc64/kernel/prom.c
--- linux-2.5.73-bk9/arch/ppc64/kernel/prom.c	2003-06-22 11:33:01.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/kernel/prom.c	2003-07-02 04:57:23.000000000 -0700
@@ -1538,137 +1538,185 @@
 	return mem_start;
 }
 
-/* This routine walks the interrupt tree for a given device node and gather 
- * all necessary informations according to the draft interrupt mapping
- * for CHRP. The current version was only tested on Apple "Core99" machines
- * and may not handle cascaded controllers correctly.
+/*
+ * Find the interrupt parent of a node.
  */
-__init
-static unsigned long
-finish_node_interrupts(struct device_node *np, unsigned long mem_start)
+static struct device_node * __init
+intr_parent(struct device_node *p)
 {
-	/* Finish this node */
-	unsigned int *isizep, *asizep, *interrupts, *map, *map_mask, *reg;
-	phandle *parent, map_parent;
-	struct device_node *node, *parent_node;
-	int l, isize, ipsize, asize, map_size, regpsize;
+	phandle *parp;
 
-	/* Currently, we don't look at all nodes with no "interrupts" property */
+	parp = (phandle *) get_property(p, "interrupt-parent", NULL);
+	if (parp == NULL)
+		return p->parent;
+	return find_phandle(*parp);
+}
 
-	interrupts = (unsigned int *)get_property(np, "interrupts", &l);
-	if (interrupts == NULL)
-		return mem_start;
-	ipsize = l>>2;
+/*
+ * Find out the size of each entry of the interrupts property
+ * for a node.
+ */
+static int __init
+prom_n_intr_cells(struct device_node *np)
+{
+	struct device_node *p;
+	unsigned int *icp;
 
-	reg = (unsigned int *)get_property(np, "reg", &l);
-	regpsize = l>>2;
+	for (p = np; (p = intr_parent(p)) != NULL; ) {
+		icp = (unsigned int *)
+			get_property(p, "#interrupt-cells", NULL);
+		if (icp != NULL)
+			return *icp;
+		if (get_property(p, "interrupt-controller", NULL) != NULL
+		    || get_property(p, "interrupt-map", NULL) != NULL) {
+			printk("oops, node %s doesn't have #interrupt-cells\n",
+			       p->full_name);
+		return 1;
+		}
+	}
+#ifdef DEBUG_IRQ
+	printk("prom_n_intr_cells failed for %s\n", np->full_name);
+#endif
+	return 1;
+}
 
-	/* We assume default interrupt cell size is 1 (bugus ?) */
-	isize = 1;
-	node = np;
-	
-	do {
-	    /* We adjust the cell size if the current parent contains an #interrupt-cells
-	     * property */
-	    isizep = (unsigned int *)get_property(node, "#interrupt-cells", &l);
-	    if (isizep)
-	    	isize = *isizep;
-
-	    /* We don't do interrupt cascade (ISA) for now, we stop on the first 
-	     * controller found
-	     */
-	    if (get_property(node, "interrupt-controller", &l)) {
-	    	int i,j;
-
-	    	np->intrs = (struct interrupt_info *) mem_start;
-		np->n_intrs = ipsize / isize;
-		mem_start += np->n_intrs * sizeof(struct interrupt_info);
-		for (i = 0; i < np->n_intrs; ++i) {
-		    np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(*interrupts++));
-		    np->intrs[i].sense = 1;
-		    if (isize > 1)
-		        np->intrs[i].sense = *interrupts++;
-		    for (j=2; j<isize; j++)
-		    	interrupts++;
+/*
+ * Map an interrupt from a device up to the platform interrupt
+ * descriptor.
+ */
+static int __init
+map_interrupt(unsigned int **irq, struct device_node **ictrler,
+	      struct device_node *np, unsigned int *ints, int nintrc)
+{
+	struct device_node *p, *ipar;
+	unsigned int *imap, *imask, *ip;
+	int i, imaplen, match;
+	int newintrc, newaddrc;
+	unsigned int *reg;
+	int naddrc;
+
+	reg = (unsigned int *) get_property(np, "reg", NULL);
+	naddrc = prom_n_addr_cells(np);
+	p = intr_parent(np);
+	while (p != NULL) {
+		if (get_property(p, "interrupt-controller", NULL) != NULL)
+			/* this node is an interrupt controller, stop here */
+			break;
+		imap = (unsigned int *)
+			get_property(p, "interrupt-map", &imaplen);
+		if (imap == NULL) {
+			p = intr_parent(p);
+			continue;
+		}
+		imask = (unsigned int *)
+			get_property(p, "interrupt-map-mask", NULL);
+		if (imask == NULL) {
+			printk("oops, %s has interrupt-map but no mask\n",
+			       p->full_name);
+			return 0;
+		}
+		imaplen /= sizeof(unsigned int);
+		match = 0;
+		ipar = NULL;
+		while (imaplen > 0 && !match) {
+			/* check the child-interrupt field */
+			match = 1;
+			for (i = 0; i < naddrc && match; ++i)
+				match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
+			for (; i < naddrc + nintrc && match; ++i)
+				match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
+			imap += naddrc + nintrc;
+			imaplen -= naddrc + nintrc;
+			/* grab the interrupt parent */
+			ipar = find_phandle((phandle) *imap++);
+			--imaplen;
+			if (ipar == NULL) {
+				printk("oops, no int parent %x in map of %s\n",
+				       imap[-1], p->full_name);
+				return 0;
+			}
+			/* find the parent's # addr and intr cells */
+			ip = (unsigned int *)
+				get_property(ipar, "#interrupt-cells", NULL);
+			if (ip == NULL) {
+				printk("oops, no #interrupt-cells on %s\n",
+				       ipar->full_name);
+				return 0;
+			}
+			newintrc = *ip;
+			ip = (unsigned int *)
+				get_property(ipar, "#address-cells", NULL);
+			newaddrc = (ip == NULL)? 0: *ip;
+			imap += newaddrc + newintrc;
+			imaplen -= newaddrc + newintrc;
+		}
+		if (imaplen < 0) {
+			printk("oops, error decoding int-map on %s, len=%d\n",
+			       p->full_name, imaplen);
+			return 0;
+		}
+		if (!match) {
+#ifdef DEBUG_IRQ
+			printk("oops, no match in %s int-map for %s\n",
+			       p->full_name, np->full_name);
+#endif
+			return 0;
 		}
+		p = ipar;
+		naddrc = newaddrc;
+		nintrc = newintrc;
+		ints = imap - nintrc;
+		reg = ints - naddrc;
+	}
+#ifdef DEBUG_IRQ
+	if (p == NULL)
+		printk("hmmm, int tree for %s doesn't have ctrler\n",
+		       np->full_name);
+#endif
+	*irq = ints;
+	*ictrler = p;
+	return nintrc;
+}
+
+/*
+ * New version of finish_node_interrupts.
+ */
+static unsigned long __init
+finish_node_interrupts(struct device_node *np, unsigned long mem_start)
+{
+	unsigned int *ints;
+	int intlen, intrcells;
+	int i, j, n;
+	unsigned int *irq;
+	struct device_node *ic;
+
+	ints = (unsigned int *) get_property(np, "interrupts", &intlen);
+	if (ints == NULL)
 		return mem_start;
-	    }
-	    /* We lookup for an interrupt-map. This code can only handle one interrupt
-	     * per device in the map. We also don't handle #address-cells in the parent
-	     * I skip the pci node itself here, may not be necessary but I don't like it's
-	     * reg property.
-	     */
-	    if (np != node)
-	        map = (unsigned int *)get_property(node, "interrupt-map", &l);
-	     else
-	     	map = NULL;
-	    if (map && l) {
-	    	int i, found, temp_isize, temp_asize;
-	        map_size = l>>2;
-	        map_mask = (unsigned int *)get_property(node, "interrupt-map-mask", &l);
-	        asizep = (unsigned int *)get_property(node, "#address-cells", &l);
-	        if (asizep && l == sizeof(unsigned int))
-	            asize = *asizep;
-	        else
-	            asize = 0;
-	        found = 0;
-	        while (map_size>0 && !found) {
-	            found = 1;
-	            for (i=0; i<asize; i++) {
-	            	unsigned int mask = map_mask ? map_mask[i] : 0xffffffff;
-	            	if (!reg || (i>=regpsize) || ((mask & *map) != (mask & reg[i])))
-	           	    found = 0;
-	           	map++;
-	           	map_size--;
-	            }
-	            for (i=0; i<isize; i++) {
-	            	unsigned int mask = map_mask ? map_mask[i+asize] : 0xffffffff;
-	            	if ((mask & *map) != (mask & interrupts[i]))
-	            	    found = 0;
-	            	map++;
-	            	map_size--;
-	            }
-	            map_parent = *((phandle *)map);
-	            map+=1; map_size-=1;
-	            parent_node = find_phandle(map_parent);
-	            temp_isize = isize;
-		    temp_asize = 0;
-	            if (parent_node) {
-			isizep = (unsigned int *)get_property(parent_node, "#interrupt-cells", &l);
-	    		if (isizep)
-	    		    temp_isize = *isizep;
-			asizep = (unsigned int *)get_property(parent_node, "#address-cells", &l);
-			if (asizep && l == sizeof(unsigned int))
-				temp_asize = *asizep;
-	            }
-	            if (!found) {
-			map += temp_isize + temp_asize;
-			map_size -= temp_isize + temp_asize;
-	            }
-	        }
-	        if (found) {
-		    /* Mapped to a new parent.  Use the reg and interrupts specified in
-		     * the map as the new search parameters.  Then search from the parent.
-		     */
-	            node = parent_node;
-		    reg = map;
-		    regpsize = temp_asize;
-		    interrupts = map + temp_asize;
-		    ipsize = temp_isize;
-		    continue;
-	        }
-	    }
-	    /* We look for an explicit interrupt-parent.
-	     */
-	    parent = (phandle *)get_property(node, "interrupt-parent", &l);
-	    if (parent && (l == sizeof(phandle)) &&
-	    	(parent_node = find_phandle(*parent))) {
-	    	node = parent_node;
-	    	continue;
-	    }
-	    /* Default, get real parent */
-	    node = node->parent;
-	} while (node);
+	intrcells = prom_n_intr_cells(np);
+	intlen /= intrcells * sizeof(unsigned int);
+	np->n_intrs = intlen;
+	np->intrs = (struct interrupt_info *) mem_start;
+	mem_start += intlen * sizeof(struct interrupt_info);
+
+	for (i = 0; i < intlen; ++i) {
+		np->intrs[i].line = 0;
+		np->intrs[i].sense = 1;
+		n = map_interrupt(&irq, &ic, np, ints, intrcells);
+		if (n <= 0)
+			continue;
+		np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(irq[0]));
+		if (n > 1)
+			np->intrs[i].sense = irq[1];
+		if (n > 2) {
+			printk("hmmm, got %d intr cells for %s:", n,
+			       np->full_name);
+			for (j = 0; j < n; ++j)
+				printk(" %d", irq[j]);
+			printk("\n");
+		}
+		ints += intrcells;
+	}
 
 	return mem_start;
 }
diff -urN linux-2.5.73-bk9/arch/ppc64/kernel/smp.c linux-2.5.73-bk10/arch/ppc64/kernel/smp.c
--- linux-2.5.73-bk9/arch/ppc64/kernel/smp.c	2003-06-22 11:33:03.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/kernel/smp.c	2003-07-02 04:57:23.000000000 -0700
@@ -57,7 +57,7 @@
 
 static struct smp_ops_t *smp_ops;
 
-volatile unsigned int cpu_callin_map[NR_CPUS];
+static volatile unsigned int cpu_callin_map[NR_CPUS];
 
 extern unsigned char stab_array[];
 
diff -urN linux-2.5.73-bk9/arch/ppc64/kernel/sys_ppc32.c linux-2.5.73-bk10/arch/ppc64/kernel/sys_ppc32.c
--- linux-2.5.73-bk9/arch/ppc64/kernel/sys_ppc32.c	2003-06-22 11:32:59.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/kernel/sys_ppc32.c	2003-07-02 04:57:23.000000000 -0700
@@ -1147,7 +1147,7 @@
 	u32 totalhigh;
 	u32 freehigh;
 	u32 mem_unit;
-	char _f[20-2*sizeof(long)-sizeof(int)];
+	char _f[20-2*sizeof(int)-sizeof(int)];
 };
 
 extern asmlinkage long sys_sysinfo(struct sysinfo *info);
diff -urN linux-2.5.73-bk9/arch/ppc64/xmon/ppc-opc.c linux-2.5.73-bk10/arch/ppc64/xmon/ppc-opc.c
--- linux-2.5.73-bk9/arch/ppc64/xmon/ppc-opc.c	2003-06-22 11:32:44.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/xmon/ppc-opc.c	2003-07-02 04:57:23.000000000 -0700
@@ -394,18 +394,13 @@
 
 /*ARGSUSED*/
 static unsigned long 
-insert_bat (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_bat(unsigned long insn, long value, const char **errmsg)
 {
   return insn | (((insn >> 21) & 0x1f) << 16);
 }
 
 static long
-extract_bat (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_bat(unsigned long insn, int *invalid)
 {
   if (invalid != (int *) NULL
       && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f))
@@ -421,18 +416,13 @@
 
 /*ARGSUSED*/
 static unsigned long
-insert_bba (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_bba(unsigned long insn, long value, const char **errmsg)
 {
   return insn | (((insn >> 16) & 0x1f) << 11);
 }
 
 static long
-extract_bba (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_bba(unsigned long insn, int *invalid)
 {
   if (invalid != (int *) NULL
       && ((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f))
@@ -445,19 +435,14 @@
 
 /*ARGSUSED*/
 static unsigned long
-insert_bd (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_bd(unsigned long insn, long value, const char **errmsg)
 {
   return insn | (value & 0xfffc);
 }
 
 /*ARGSUSED*/
 static long
-extract_bd (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_bd(unsigned long insn, int *invalid)
 {
   if ((insn & 0x8000) != 0)
     return (insn & 0xfffc) - 0x10000;
@@ -474,10 +459,7 @@
 
 /*ARGSUSED*/
 static unsigned long
-insert_bdm (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_bdm(unsigned long insn, long value, const char **errmsg)
 {
   if ((value & 0x8000) != 0)
     insn |= 1 << 21;
@@ -485,9 +467,7 @@
 }
 
 static long
-extract_bdm (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_bdm(unsigned long insn, int *invalid)
 {
   if (invalid != (int *) NULL
       && ((insn & (1 << 21)) == 0
@@ -505,10 +485,7 @@
 
 /*ARGSUSED*/
 static unsigned long
-insert_bdp (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_bdp(unsigned long insn, long value, const char **errmsg)
 {
   if ((value & 0x8000) == 0)
     insn |= 1 << 21;
@@ -516,9 +493,7 @@
 }
 
 static long
-extract_bdp (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_bdp(unsigned long insn, int *invalid)
 {
   if (invalid != (int *) NULL
       && ((insn & (1 << 21)) == 0
@@ -561,10 +536,7 @@
    the field to an illegal value.  */
 
 static unsigned long
-insert_bo (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_bo(unsigned long insn, long value, const char **errmsg)
 {
   if (errmsg != (const char **) NULL
       && ! valid_bo (value))
@@ -573,9 +545,7 @@
 }
 
 static long
-extract_bo (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_bo(unsigned long insn, int *invalid)
 {
   long value;
 
@@ -591,10 +561,7 @@
    extracting it, we force it to be even.  */
 
 static unsigned long
-insert_boe (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_boe(unsigned long insn, long value, const char **errmsg)
 {
   if (errmsg != (const char **) NULL)
     {
@@ -607,9 +574,7 @@
 }
 
 static long
-extract_boe (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_boe(unsigned long insn, int *invalid)
 {
   long value;
 
@@ -625,19 +590,14 @@
 
 /*ARGSUSED*/
 static unsigned long
-insert_ds (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_ds(unsigned long insn, long value, const char **errmsg)
 {
   return insn | (value & 0xfffc);
 }
 
 /*ARGSUSED*/
 static long
-extract_ds (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_ds(unsigned long insn, int *invalid)
 {
   if ((insn & 0x8000) != 0)
     return (insn & 0xfffc) - 0x10000;
@@ -650,19 +610,14 @@
 
 /*ARGSUSED*/
 static unsigned long
-insert_li (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_li(unsigned long insn, long value, const char **errmsg)
 {
   return insn | (value & 0x3fffffc);
 }
 
 /*ARGSUSED*/
 static long
-extract_li (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_li(unsigned long insn, int *invalid)
 {
   if ((insn & 0x2000000) != 0)
     return (insn & 0x3fffffc) - 0x4000000;
@@ -676,10 +631,7 @@
    instruction which uses a field of this type.  */
 
 static unsigned long
-insert_mbe (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_mbe(unsigned long insn, long value, const char **errmsg)
 {
   unsigned long uval;
   int mb, me;
@@ -718,9 +670,7 @@
 }
 
 static long
-extract_mbe (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_mbe(unsigned long insn, int *invalid)
 {
   long ret;
   int mb, me;
@@ -742,19 +692,14 @@
 
 /*ARGSUSED*/
 static unsigned long
-insert_mb6 (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_mb6(unsigned long insn, long value, const char **errmsg)
 {
   return insn | ((value & 0x1f) << 6) | (value & 0x20);
 }
 
 /*ARGSUSED*/
 static long
-extract_mb6 (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_mb6(unsigned long insn, int *invalid)
 {
   return ((insn >> 6) & 0x1f) | (insn & 0x20);
 }
@@ -763,10 +708,7 @@
    0.  */
 
 static unsigned long
-insert_nb (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_nb(unsigned long insn, long value, const char **errmsg)
 {
   if (value < 0 || value > 32)
     *errmsg = "value out of range";
@@ -777,9 +719,7 @@
 
 /*ARGSUSED*/
 static long
-extract_nb (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_nb(unsigned long insn, int *invalid)
 {
   long ret;
 
@@ -796,18 +736,13 @@
 
 /*ARGSUSED*/
 static unsigned long
-insert_nsi (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_nsi(unsigned long insn, long value, const char **errmsg)
 {
   return insn | ((- value) & 0xffff);
 }
 
 static long
-extract_nsi (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_nsi(unsigned long insn, int *invalid)
 {
   if (invalid != (int *) NULL)
     *invalid = 1;
@@ -822,10 +757,7 @@
    equal the RT field.  */
 
 static unsigned long
-insert_ral (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_ral(unsigned long insn, long value, const char **errmsg)
 {
   if (value == 0
       || value == ((insn >> 21) & 0x1f))
@@ -837,10 +769,7 @@
    restrictions.  */
 
 static unsigned long
-insert_ram (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_ram(unsigned long insn, long value, const char **errmsg)
 {
   if (value >= ((insn >> 21) & 0x1f))
     *errmsg = "index register in load range";
@@ -852,10 +781,7 @@
    field may not be zero.  */
 
 static unsigned long
-insert_ras (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_ras(unsigned long insn, long value, const char **errmsg)
 {
   if (value == 0)
     *errmsg = "invalid register operand when updating";
@@ -870,18 +796,13 @@
 
 /*ARGSUSED*/
 static unsigned long 
-insert_rbs (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_rbs(unsigned long insn, long value, const char **errmsg)
 {
   return insn | (((insn >> 21) & 0x1f) << 11);
 }
 
 static long
-extract_rbs (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_rbs(unsigned long insn, int *invalid)
 {
   if (invalid != (int *) NULL
       && ((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f))
@@ -893,19 +814,14 @@
 
 /*ARGSUSED*/
 static unsigned long
-insert_sh6 (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_sh6(unsigned long insn, long value, const char **errmsg)
 {
   return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
 }
 
 /*ARGSUSED*/
 static long
-extract_sh6 (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_sh6(unsigned long insn, int *invalid)
 {
   return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20);
 }
@@ -914,18 +830,13 @@
    lower 5 bits are stored in the upper 5 and vice- versa.  */
 
 static unsigned long
-insert_spr (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_spr(unsigned long insn, long value, const char **errmsg)
 {
   return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
 }
 
 static long
-extract_spr (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_spr(unsigned long insn, int *invalid)
 {
   return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
 }
@@ -941,10 +852,7 @@
 #define TB (268)
 
 static unsigned long
-insert_tbr (insn, value, errmsg)
-     unsigned long insn;
-     long value;
-     const char **errmsg;
+insert_tbr(unsigned long insn, long value, const char **errmsg)
 {
   if (value == 0)
     value = TB;
@@ -952,9 +860,7 @@
 }
 
 static long
-extract_tbr (insn, invalid)
-     unsigned long insn;
-     int *invalid;
+extract_tbr(unsigned long insn, int *invalid)
 {
   long ret;
 
diff -urN linux-2.5.73-bk9/arch/ppc64/xmon/xmon.c linux-2.5.73-bk10/arch/ppc64/xmon/xmon.c
--- linux-2.5.73-bk9/arch/ppc64/xmon/xmon.c	2003-06-22 11:33:13.000000000 -0700
+++ linux-2.5.73-bk10/arch/ppc64/xmon/xmon.c	2003-07-02 04:57:23.000000000 -0700
@@ -26,6 +26,7 @@
 #include <asm/naca.h>
 #include <asm/paca.h>
 #include <asm/ppcdebug.h>
+#include <asm/cputable.h>
 #include "nonstdio.h"
 #include "privinst.h"
 
@@ -469,9 +470,9 @@
 		}
 	}
 
-	if (cpu_has_dabr() && dabr.enabled)
+	if ((cur_cpu_spec->cpu_features & CPU_FTR_DABR) && dabr.enabled)
 		set_dabr(dabr.address);
-	if (cpu_has_iabr() && iabr.enabled)
+	if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR) && iabr.enabled)
 		set_iabr(iabr.address);
 }
 
@@ -485,9 +486,9 @@
 	if (systemcfg->platform != PLATFORM_PSERIES)
 		return;
 
-	if (cpu_has_dabr())
+	if ((cur_cpu_spec->cpu_features & CPU_FTR_DABR))
 		set_dabr(0);
-	if (cpu_has_iabr())
+	if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR))
 		set_iabr(0);
 
 	bp = bpts;
@@ -777,7 +778,7 @@
 	cmd = inchar();
 	switch (cmd) {
 	case 'd':	/* bd - hardware data breakpoint */
-		if (cpu_has_dabr()) {
+		if (!(cur_cpu_spec->cpu_features & CPU_FTR_DABR)) {
 			printf("Not implemented on this cpu\n");
 			break;
 		}
@@ -797,7 +798,7 @@
 			dabr.address = (dabr.address & ~7) | mode;
 		break;
 	case 'i':	/* bi - hardware instr breakpoint */
-		if (cpu_has_iabr()) {
+		if (!(cur_cpu_spec->cpu_features & CPU_FTR_IABR)) {
 			printf("Not implemented on POWER4\n");
 			break;
 		}
diff -urN linux-2.5.73-bk9/arch/s390/Kconfig linux-2.5.73-bk10/arch/s390/Kconfig
--- linux-2.5.73-bk9/arch/s390/Kconfig	2003-07-02 04:57:15.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/Kconfig	2003-07-02 04:57:23.000000000 -0700
@@ -45,6 +45,34 @@
 	depends on ARCH_S390X = 'n'
 	default y
 
+choice 
+	prompt "Processor type"
+	default MARCH_G5
+
+config MARCH_G5
+	bool "S/390 model G5 and G6"
+	depends on ARCH_S390_31
+	help
+	  Select this to build a 31 bit kernel that works
+	  on all S/390 and zSeries machines.
+
+config MARCH_Z900
+	bool "IBM eServer zSeries model z800 and z900"
+	help
+	  Select this to optimize for zSeries machines. This
+	  will enable some optimizations that are not available
+	  on older 31 bit only CPUs.
+
+config MARCH_Z990
+	bool "IBM eServer zSeries model z990"
+	help
+	  Select this enable optimizations for model z990.
+	  This will be slightly faster but does not work on
+	  older machines such as the z900.
+
+endchoice 
+
+
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -90,7 +118,7 @@
 
 config MATHEMU
 	bool "IEEE FPU emulation"
-	depends on ARCH_S390X = n
+	depends on MARCH_G5
 	help
 	  This option is required for IEEE compliant floating point arithmetic
 	  on older S/390 machines. Say Y unless you know your machine doesn't 
@@ -130,7 +158,7 @@
 	tristate "QDIO support"
 	---help---
 	  This driver provides the Queued Direct I/O base support for the
-	  IBM S/390 (G5 and G6) and eServer zSeries (z800 and z900).
+	  IBM S/390 (G5 and G6) and eServer zSeries (z800, z900 and z990).
 
 	  For details please refer to the documentation provided by IBM at
 	  <http://www10.software.ibm.com/developerworks/opensource/linux390>
diff -urN linux-2.5.73-bk9/arch/s390/Makefile linux-2.5.73-bk10/arch/s390/Makefile
--- linux-2.5.73-bk9/arch/s390/Makefile	2003-06-22 11:32:35.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -13,10 +13,13 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
+check_gcc = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+
 ifdef CONFIG_ARCH_S390_31
 LDFLAGS		:= -m elf_s390
 LDFLAGS_BLOB	:= --format binary --oformat elf32-s390
 CFLAGS		+= -m31
+AFLAGS		+= -m31
 UTS_MACHINE	:= s390
 endif
 
@@ -25,12 +28,20 @@
 MODFLAGS	+= -fpic -D__PIC__
 LDFLAGS_BLOB	:= --format binary --oformat elf64-s390
 CFLAGS		+= -m64
+AFLAGS		+= -m64
 UTS_MACHINE	:= s390x
 endif
 
+cflags-$(CONFIG_MARCH_G5)   += $(call check_gcc,-march=g5,)
+cflags-$(CONFIG_MARCH_Z900) += $(call check_gcc,-march=z900,)
+cflags-$(CONFIG_MARCH_Z990) += $(call check_gcc,-march=trex,)
+
+CFLAGS		+= $(cflags-y)
+CFLAGS		+= $(call check_gcc,-finline-limit=10000,)
+CFLAGS 		+= -pipe -fno-strength-reduce -Wno-sign-compare 
+
 OBJCOPYFLAGS	:= -O binary
 LDFLAGS_vmlinux := -e start
-CFLAGS 		+= -pipe -fno-strength-reduce -finline-limit-10000 -Wno-sign-compare 
 
 head-$(CONFIG_ARCH_S390_31)	+= arch/$(ARCH)/kernel/head.o
 head-$(CONFIG_ARCH_S390X)	+= arch/$(ARCH)/kernel/head64.o
diff -urN linux-2.5.73-bk9/arch/s390/defconfig linux-2.5.73-bk10/arch/s390/defconfig
--- linux-2.5.73-bk9/arch/s390/defconfig	2003-07-02 04:57:15.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/defconfig	2003-07-02 04:57:23.000000000 -0700
@@ -41,6 +41,9 @@
 #
 # CONFIG_ARCH_S390X is not set
 CONFIG_ARCH_S390_31=y
+CONFIG_MARCH_G5=y
+# CONFIG_MARCH_Z900 is not set
+# CONFIG_MARCH_Z990 is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 CONFIG_MATHEMU=y
@@ -266,7 +269,14 @@
 CONFIG_LCS=m
 CONFIG_CTC=m
 CONFIG_IUCV=m
-CONFIG_CCWGROUP=m
+CONFIG_QETH=y
+
+#
+# Gigabit Ethernet default settings
+#
+# CONFIG_QETH_IPV6 is not set
+# CONFIG_QETH_PERF_STATS is not set
+CONFIG_CCWGROUP=y
 
 #
 # File systems
diff -urN linux-2.5.73-bk9/arch/s390/kernel/Makefile linux-2.5.73-bk10/arch/s390/kernel/Makefile
--- linux-2.5.73-bk9/arch/s390/kernel/Makefile	2003-06-22 11:33:32.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/kernel/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -23,11 +23,6 @@
 obj-$(CONFIG_ARCH_S390_31)	+= entry.o reipl.o
 obj-$(CONFIG_ARCH_S390X)	+= entry64.o reipl64.o
 
-ifdef CONFIG_ARCH_S390X
-$(obj)%.o: $(patsubst arch/s390/%,arch/s390x/%,$(src))%.c
-	$(call if_changed_dep,cc_o_c)
-endif
-
 #
 # This is just to get the dependencies...
 #
diff -urN linux-2.5.73-bk9/arch/s390/kernel/compat_linux.c linux-2.5.73-bk10/arch/s390/kernel/compat_linux.c
--- linux-2.5.73-bk9/arch/s390/kernel/compat_linux.c	2003-07-02 04:57:15.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/kernel/compat_linux.c	2003-07-02 04:57:23.000000000 -0700
@@ -373,12 +373,45 @@
 	unsigned int		__unused5;
 };
 
-                                                        
-/*
- * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
- *
- * This is really horribly ugly.
- */
+extern int sem_ctls[];
+#define sc_semopm	(sem_ctls[2])
+#define SEMOPM_FAST	64  /* ~ 372 bytes on stack */
+
+static long
+do_sys32_semtimedop (int semid, struct sembuf *tsops, int nsops,
+		     struct compat_timespec *timeout32)
+{
+	struct sembuf *sops, fast_sops[SEMOPM_FAST];
+	struct timespec t;
+	mm_segment_t oldfs;
+	long ret;
+
+	/* parameter checking precedence should mirror sys_semtimedop() */
+	if (nsops < 1 || semid < 0)
+		return -EINVAL;
+	if (nsops > sc_semopm)
+		return -E2BIG;
+	if (nsops <= SEMOPM_FAST)
+		sops = fast_sops;
+	else {
+		sops = kmalloc(nsops * sizeof(*sops), GFP_KERNEL);
+		if (sops == NULL)
+			return -ENOMEM;
+	}
+	if (copy_from_user(sops, tsops, nsops * sizeof(*tsops)) ||
+	    get_compat_timespec(&t, timeout32))
+		ret = -EFAULT;
+	else {
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+		ret = sys_semtimedop(semid, sops, nsops, &t);
+		set_fs(oldfs);
+	}
+	if (sops != fast_sops)
+		kfree(sops);
+	return ret;
+}
+
 #define IPCOP_MASK(__x)	(1UL << (__x))
 static int do_sys32_semctl(int first, int second, int third, void *uptr)
 {
@@ -763,7 +796,12 @@
 	return err;
 }
 
-asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+/*
+ * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr)
 {
 	int version, err;
 
@@ -773,11 +811,22 @@
 	if(version)
 		return -EINVAL;
 
-	if (call <= SEMCTL)
+	if (call <= SEMTIMEDOP)
 		switch (call) {
+		case SEMTIMEDOP:
+			if (third) {
+				err = do_sys32_semtimedop(first,
+					(struct sembuf *)AA(ptr),
+					second,
+					(struct compat_timespec *)
+						AA((u32)third));
+				goto out;
+			}
+			/* else fall through for normal semop() */
 		case SEMOP:
 			/* struct sembuf is the same on 32 and 64bit :)) */
-			err = sys_semop (first, (struct sembuf *)AA(ptr), second);
+			err = sys_semtimedop (first, (struct sembuf *)AA(ptr),
+					      second, NULL);
 			goto out;
 		case SEMGET:
 			err = sys_semget (first, second, third);
diff -urN linux-2.5.73-bk9/arch/s390/kernel/entry.S linux-2.5.73-bk10/arch/s390/kernel/entry.S
--- linux-2.5.73-bk9/arch/s390/kernel/entry.S	2003-06-22 11:32:35.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/kernel/entry.S	2003-07-02 04:57:23.000000000 -0700
@@ -267,7 +267,7 @@
 	st	%r7,SP_R2(%r15)
 	basr	%r14,%r1
 	clc	SP_R2(4,%r15),BASED(.Lnr_syscalls)
-	bl	BASED(sysc_tracego)
+	bnl	BASED(sysc_tracenogo)
 	l	%r7,SP_R2(%r15)        # strace might have changed the 
 	sll	%r7,2                  #  system call
 	l	%r8,sys_call_table-entry_base(%r7,%r13)
@@ -276,6 +276,7 @@
 	l	%r2,SP_ORIG_R2(%r15)
 	basr	%r14,%r8          # call sys_xxx
 	st	%r2,SP_R2(%r15)   # store return value
+sysc_tracenogo:
 	tm	__TI_flags+3(%r9),_TIF_SYSCALL_TRACE
         bno     BASED(sysc_return)
 	l	%r1,BASED(.Ltrace)
@@ -486,7 +487,7 @@
 	st	%r7,SP_R2(%r15)
         basr    %r14,%r1
 	clc	SP_R2(4,%r15),BASED(.Lnr_syscalls)
-	bl	BASED(pgm_svc_go)
+	bnl	BASED(pgm_svc_nogo)
 	l	%r7,SP_R2(%r15)   # strace changed the syscall
 	sll     %r7,2
 	l	%r8,sys_call_table-entry_base(%r7,%r13)
@@ -495,6 +496,7 @@
 	l       %r2,SP_ORIG_R2(%r15)
         basr    %r14,%r8          # call sys_xxx
         st      %r2,SP_R2(%r15)   # store return value
+pgm_svc_nogo:
 	tm	__TI_flags+3(%r9),_TIF_SYSCALL_TRACE
         bno     BASED(pgm_svcret)
         l       %r1,BASED(.Ltrace)
diff -urN linux-2.5.73-bk9/arch/s390/kernel/entry64.S linux-2.5.73-bk10/arch/s390/kernel/entry64.S
--- linux-2.5.73-bk9/arch/s390/kernel/entry64.S	2003-06-22 11:32:35.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/kernel/entry64.S	2003-07-02 04:57:23.000000000 -0700
@@ -254,7 +254,7 @@
         brasl   %r14,syscall_trace
 	larl	%r1,.Lnr_syscalls
 	clc	SP_R2(8,%r15),0(%r1)
-	jl	sysc_tracego
+	jnl	sysc_tracenogo
 	lg	%r7,SP_R2(%r15)   # strace might have changed the
 	sll     %r7,2             #  system call
 	lgf	%r8,0(%r7,%r10)
@@ -263,6 +263,7 @@
 	lg      %r2,SP_ORIG_R2(%r15)
         basr    %r14,%r8            # call sys_xxx
         stg     %r2,SP_R2(%r15)     # store return value
+sysc_tracenogo:
 	tm	__TI_flags+7(%r9),_TIF_SYSCALL_TRACE
         jno     sysc_return
 	larl	%r14,sysc_return    # return point is sysc_return
@@ -481,7 +482,7 @@
 #
 pgm_svcper:
 	SAVE_ALL __LC_SVC_OLD_PSW,1
-	llgh    %r8,__LC_SVC_INT_CODE # get svc number from lowcore
+	llgh    %r7,__LC_SVC_INT_CODE # get svc number from lowcore
 	stosm   48(%r15),0x03     # reenable interrupts
         GET_THREAD_INFO           # load pointer to task_struct to R9
 	slag	%r7,%r7,2         # *4 and test for svc 0
@@ -490,15 +491,15 @@
 	clg	%r1,.Lnr_syscalls-.Lconst(%r14)
 	slag	%r7,%r1,2
 pgm_svcstd:
-	larl    %r7,sys_call_table
+	larl    %r10,sys_call_table
 #ifdef CONFIG_S390_SUPPORT
         tm      SP_PSW+3(%r15),0x01  # are we running in 31 bit mode ?
         jo      pgm_svcper_noemu
-	larl    %r7,sys_call_table_emu # use 31 bit emulation system calls
+	larl    %r10,sys_call_table_emu # use 31 bit emulation system calls
 pgm_svcper_noemu:
 #endif
 	tm	__TI_flags+3(%r9),_TIF_SYSCALL_TRACE
-        lgf     %r8,0(%r8,%r7)    # load address of system call routine
+        lgf     %r8,0(%r7,%r10)   # load address of system call routine
         jo      pgm_tracesys
         basr    %r14,%r8          # call sys_xxxx
         stg     %r2,SP_R2(%r15)   # store return value (change R2 on stack)
@@ -522,19 +523,20 @@
 # call trace before and after sys_call
 #
 pgm_tracesys:
-	lgfr	%r7,%r7
+	srlg	%r7,%r7,2
 	stg	%r7,SP_R2(%r15)
         brasl   %r14,syscall_trace
 	clc	SP_R2(8,%r15),.Lnr_syscalls
-	jnl     pgm_svc_go
-	lg      %r2,SP_R2(%r15)
-	sllg    %r2,%r2,3           # strace wants to change the syscall
-	lgf	%r8,0(%r2,%r7)
+	jnl     pgm_svc_nogo
+	lg      %r7,SP_R2(%r15)
+	sllg    %r7,%r7,2           # strace wants to change the syscall
+	lgf	%r8,0(%r7,%r10)
 pgm_svc_go:
 	lmg     %r3,%r6,SP_R3(%r15)
 	lg      %r2,SP_ORIG_R2(%r15)
         basr    %r14,%r8            # call sys_xxx
         stg     %r2,SP_R2(%r15)     # store return value
+pgm_svc_nogo:
 	tm	__TI_flags+7(%r9),_TIF_SYSCALL_TRACE
         jno     pgm_svcret
 	larl	%r14,pgm_svcret     # return point is sysc_return
diff -urN linux-2.5.73-bk9/arch/s390/kernel/head.S linux-2.5.73-bk10/arch/s390/kernel/head.S
--- linux-2.5.73-bk9/arch/s390/kernel/head.S	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/kernel/head.S	2003-07-02 04:57:23.000000000 -0700
@@ -533,6 +533,10 @@
         bne    .Lnop390-.LPG1(%r13)
         oi     3(%r12),4                # set P/390 flag
 .Lnop390:
+	chi    %r0,0x2084		# new stidp format?
+	bne    .Loldfmt-.LPG1(%r13)
+	oi     3(%r12),64		# set new stidp flag
+.Loldfmt:	
 
 #
 # find out if we have an IEEE fpu
diff -urN linux-2.5.73-bk9/arch/s390/kernel/head64.S linux-2.5.73-bk10/arch/s390/kernel/head64.S
--- linux-2.5.73-bk9/arch/s390/kernel/head64.S	2003-06-22 11:32:39.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/kernel/head64.S	2003-07-02 04:57:23.000000000 -0700
@@ -553,6 +553,10 @@
         bne    1f-.LPG1(%r13)
         oi     7(%r12),4                # set P/390 flag
 1:
+	chi    %r0,0x2084		# new stidp format?
+	bne    2f-.LPG1(%r13)
+	oi     7(%r12),64		# set new stidp flag
+2:	
 
 #
 # find out if we have the MVPG instruction
diff -urN linux-2.5.73-bk9/arch/s390/kernel/module.c linux-2.5.73-bk10/arch/s390/kernel/module.c
--- linux-2.5.73-bk9/arch/s390/kernel/module.c	2003-06-22 11:33:16.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/kernel/module.c	2003-07-02 04:57:23.000000000 -0700
@@ -67,12 +67,14 @@
 	switch (ELF_R_TYPE (rela->r_info)) {
 	case R_390_GOT12:	/* 12 bit GOT offset.  */
 	case R_390_GOT16:	/* 16 bit GOT offset.  */
+	case R_390_GOT20:	/* 20 bit GOT offset.  */
 	case R_390_GOT32:	/* 32 bit GOT offset.  */
 	case R_390_GOT64:	/* 64 bit GOT offset.  */
 	case R_390_GOTENT:	/* 32 bit PC rel. to GOT entry shifted by 1. */
 	case R_390_GOTPLT12:	/* 12 bit offset to jump slot.	*/
-	case R_390_GOTPLT16:	/* 16 bit offset to jump slot. */
-	case R_390_GOTPLT32:	/* 32 bit offset to jump slot. */
+	case R_390_GOTPLT16:	/* 16 bit offset to jump slot.  */
+	case R_390_GOTPLT20:	/* 20 bit offset to jump slot.  */
+	case R_390_GOTPLT32:	/* 32 bit offset to jump slot.  */
 	case R_390_GOTPLT64:	/* 64 bit offset to jump slot.	*/
 	case R_390_GOTPLTENT:	/* 32 bit rel. offset to jump slot >> 1. */
 		if (info->got_offset == -1UL) {
@@ -201,6 +203,7 @@
 	case R_390_8:		/* Direct 8 bit.   */
 	case R_390_12:		/* Direct 12 bit.  */
 	case R_390_16:		/* Direct 16 bit.  */
+	case R_390_20:		/* Direct 20 bit.  */
 	case R_390_32:		/* Direct 32 bit.  */
 	case R_390_64:		/* Direct 64 bit.  */
 		val += rela->r_addend;
@@ -211,6 +214,10 @@
 				(*(unsigned short *) loc & 0xf000);
 		else if (r_type == R_390_16)
 			*(unsigned short *) loc = val;
+		else if (r_type == R_390_20)
+			*(unsigned int *) loc =
+				(*(unsigned int *) loc & 0xf00000ff) |
+				(val & 0xfff) << 16 | (val & 0xff000) >> 4;
 		else if (r_type == R_390_32)
 			*(unsigned int *) loc = val;
 		else if (r_type == R_390_64)
@@ -235,12 +242,14 @@
 		break;
 	case R_390_GOT12:	/* 12 bit GOT offset.  */
 	case R_390_GOT16:	/* 16 bit GOT offset.  */
+	case R_390_GOT20:	/* 20 bit GOT offset.  */
 	case R_390_GOT32:	/* 32 bit GOT offset.  */
 	case R_390_GOT64:	/* 64 bit GOT offset.  */
 	case R_390_GOTENT:	/* 32 bit PC rel. to GOT entry shifted by 1. */
 	case R_390_GOTPLT12:	/* 12 bit offset to jump slot.	*/
-	case R_390_GOTPLT16:	/* 16 bit offset to jump slot. */
-	case R_390_GOTPLT32:	/* 32 bit offset to jump slot. */
+	case R_390_GOTPLT20:	/* 20 bit offset to jump slot.  */
+	case R_390_GOTPLT16:	/* 16 bit offset to jump slot.  */
+	case R_390_GOTPLT32:	/* 32 bit offset to jump slot.  */
 	case R_390_GOTPLT64:	/* 64 bit offset to jump slot.	*/
 	case R_390_GOTPLTENT:	/* 32 bit rel. offset to jump slot >> 1. */
 		if (info->got_initialized == 0) {
@@ -259,6 +268,11 @@
 		else if (r_type == R_390_GOT16 ||
 			 r_type == R_390_GOTPLT16)
 			*(unsigned short *) loc = val;
+		else if (r_type == R_390_GOT20 ||
+			 r_type == R_390_GOTPLT20)
+			*(unsigned int *) loc =
+				(*(unsigned int *) loc & 0xf00000ff) |
+				(val & 0xfff) << 16 | (val & 0xff000) >> 4;
 		else if (r_type == R_390_GOT32 ||
 			 r_type == R_390_GOTPLT32)
 			*(unsigned int *) loc = val;
diff -urN linux-2.5.73-bk9/arch/s390/kernel/sys_s390.c linux-2.5.73-bk10/arch/s390/kernel/sys_s390.c
--- linux-2.5.73-bk9/arch/s390/kernel/sys_s390.c	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk10/arch/s390/kernel/sys_s390.c	2003-07-02 04:57:23.000000000 -0700
@@ -184,8 +184,7 @@
  * This is really horribly ugly.
  */
 asmlinkage __SYS_RETTYPE sys_ipc (uint call, int first, int second, 
-				  unsigned long third, void *ptr,
-				  unsigned long fifth)
+				  unsigned long third, void *ptr)
 {
         struct ipc_kludge tmp;
 	int ret;
@@ -195,8 +194,8 @@
 		return sys_semtimedop (first, (struct sembuf *) ptr, second,
 				       NULL);
 	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf *) ptr, second,
-				      (const struct timespec *) fifth);
+		return sys_semtimedop (first, (struct sembuf *) ptr, second,
+				       (const struct timespec *) third);
         case SEMGET:
                 return sys_semget (first, second, third);
         case SEMCTL: {
diff -urN linux-2.5.73-bk9/arch/sh/boards/adx/mach.c linux-2.5.73-bk10/arch/sh/boards/adx/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/adx/mach.c	2003-06-22 11:32:45.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/adx/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -60,7 +60,5 @@
 	mv_isa_port2addr:	adx_isa_port2addr,
 
 	mv_init_irq:		init_adx_IRQ,
-
-	mv_hw_adx:		1,
 };
 ALIAS_MV(adx)
diff -urN linux-2.5.73-bk9/arch/sh/boards/dmida/mach.c linux-2.5.73-bk10/arch/sh/boards/dmida/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/dmida/mach.c	2003-06-22 11:32:34.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/dmida/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -66,8 +66,6 @@
 
 	mv_rtc_gettimeofday:	sh_rtc_gettimeofday,
 	mv_rtc_settimeofday:	sh_rtc_settimeofday,
-
-	mv_hw_hd64465:		1,
 };
 ALIAS_MV(dmida)
 
diff -urN linux-2.5.73-bk9/arch/sh/boards/dreamcast/mach.c linux-2.5.73-bk10/arch/sh/boards/dreamcast/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/dreamcast/mach.c	2003-06-22 11:32:35.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/dreamcast/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- *	$Id: mach.c,v 1.1.2.5 2002/03/01 11:22:17 lethal Exp $
+ *	$Id: mach.c,v 1.4 2003/05/20 03:04:36 lethal Exp $
  *	SEGA Dreamcast machine vector
  */
 
@@ -56,7 +56,5 @@
 
 	mv_isa_port2addr:	dreamcast_isa_port2addr,
 	mv_irq_demux:		systemasic_irq_demux,
-
-	mv_hw_dreamcast:	1,
 };
 ALIAS_MV(dreamcast)
diff -urN linux-2.5.73-bk9/arch/sh/boards/hp6xx/hp620/mach.c linux-2.5.73-bk10/arch/sh/boards/hp6xx/hp620/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/hp6xx/hp620/mach.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/hp6xx/hp620/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -60,9 +60,5 @@
 
         mv_rtc_gettimeofday:    sh_rtc_gettimeofday,
         mv_rtc_settimeofday:    sh_rtc_settimeofday,
-
-        mv_hw_hp600:            1,
-        mv_hw_hp620:            1,
-        mv_hw_hd64461:          1,
 };
 ALIAS_MV(hp620)
diff -urN linux-2.5.73-bk9/arch/sh/boards/hp6xx/hp680/mach.c linux-2.5.73-bk10/arch/sh/boards/hp6xx/hp680/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/hp6xx/hp680/mach.c	2003-06-22 11:33:33.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/hp6xx/hp680/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -56,9 +56,5 @@
 
         mv_rtc_gettimeofday:    sh_rtc_gettimeofday,
         mv_rtc_settimeofday:    sh_rtc_settimeofday,
-
-        mv_hw_hp600:            1,
-        mv_hw_hp680:            1,
-        mv_hw_hd64461:          1,
 };
 ALIAS_MV(hp680)
diff -urN linux-2.5.73-bk9/arch/sh/boards/hp6xx/hp690/mach.c linux-2.5.73-bk10/arch/sh/boards/hp6xx/hp690/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/hp6xx/hp690/mach.c	2003-06-22 11:33:34.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/hp6xx/hp690/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -56,9 +56,5 @@
 
         mv_rtc_gettimeofday:    sh_rtc_gettimeofday,
         mv_rtc_settimeofday:    sh_rtc_settimeofday,
-
-        mv_hw_hp600:            1,
-        mv_hw_hp690:            1,
-        mv_hw_hd64461:          1,
 };
 ALIAS_MV(hp690)
diff -urN linux-2.5.73-bk9/arch/sh/boards/mpc1211/Makefile linux-2.5.73-bk10/arch/sh/boards/mpc1211/Makefile
--- linux-2.5.73-bk9/arch/sh/boards/mpc1211/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/boards/mpc1211/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,12 @@
+#
+# Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+obj-y	 := mach.o setup.o io.o rtc.o led.o
+
+obj-$(CONFIG_PCI) += pci.o
+
diff -urN linux-2.5.73-bk9/arch/sh/boards/mpc1211/io.c linux-2.5.73-bk10/arch/sh/boards/mpc1211/io.c
--- linux-2.5.73-bk9/arch/sh/boards/mpc1211/io.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/boards/mpc1211/io.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,158 @@
+/*
+ * linux/arch/sh/kernel/io_mpc1211.c
+ *
+ * Copyright (C) 2001  Saito.K & Jeanne
+ *
+ * I/O routine for Interface MPC-1211.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/mpc1211/pci.h>
+
+static inline void delay(void)
+{
+	ctrl_inw(0xa0000000);
+}
+
+static inline unsigned long port2adr(unsigned long port)
+{
+        return port + PA_PCI_IO;
+}
+
+unsigned char mpc1211_inb(unsigned long port)
+{
+        return *(__u8 *)port2adr(port);
+}
+
+unsigned short mpc1211_inw(unsigned long port)
+{
+        return *(__u16 *)port2adr(port);
+}
+
+unsigned int mpc1211_inl(unsigned long port)
+{
+        return *(__u32 *)port2adr(port);
+}
+
+void mpc1211_outb(unsigned char value, unsigned long port)
+{
+	*(__u8 *)port2adr(port) = value; 
+}
+
+void mpc1211_outw(unsigned short value, unsigned long port)
+{
+	*(__u16 *)port2adr(port) = value; 
+}
+
+void mpc1211_outl(unsigned int value, unsigned long port)
+{
+	*(__u32 *)port2adr(port) = value; 
+}
+
+unsigned char mpc1211_inb_p(unsigned long port)
+{
+	unsigned char v;
+
+	v = *(__u8 *)port2adr(port);
+	delay();
+	return v;
+}
+
+void mpc1211_outb_p(unsigned char value, unsigned long port)
+{
+	*(__u8 *)port2adr(port) = value; 
+	delay();
+}
+
+void mpc1211_insb(unsigned long port, void *addr, unsigned long count)
+{
+	volatile __u8 *p = (__u8 *)port2adr(port);
+
+	while (count--) {
+	        *((__u8 *)addr)++ = *p;
+	}
+}
+
+void mpc1211_insw(unsigned long port, void *addr, unsigned long count)
+{
+	volatile __u16 *p = (__u16 *)port2adr(port);
+
+	while (count--) {
+	        *((__u16 *)addr)++ = *p;
+	}
+}
+
+void mpc1211_insl(unsigned long port, void *addr, unsigned long count)
+{
+	volatile __u32 *p = (__u32 *)port2adr(port);
+
+	while (count--) {
+	        *((__u32 *)addr)++ = *p;
+	}
+}
+
+void mpc1211_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+	volatile __u8 *p = (__u8 *)port2adr(port);
+
+	while (count--) {
+	        *p = *((__u8 *)addr)++;
+	}
+}
+
+void mpc1211_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+	volatile __u16 *p = (__u16 *)port2adr(port);
+
+	while (count--) {
+	        *p = *((__u16 *)addr)++;
+	}
+}
+
+void mpc1211_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+	volatile __u32 *p = (__u32 *)port2adr(port);
+
+	while (count--) {
+	        *p = *((__u32 *)addr)++;
+	}
+}
+
+unsigned char mpc1211_readb(unsigned long addr)
+{
+	return *(volatile unsigned char *)addr;
+}
+
+unsigned short mpc1211_readw(unsigned long addr)
+{
+	return *(volatile unsigned short *)addr;
+}
+
+unsigned int mpc1211_readl(unsigned long addr)
+{
+	return *(volatile unsigned int *)addr;
+}
+
+void mpc1211_writeb(unsigned char b, unsigned long addr)
+{
+	*(volatile unsigned char *)addr = b;
+}
+
+void mpc1211_writew(unsigned short b, unsigned long addr)
+{
+	*(volatile unsigned short *)addr = b;
+}
+
+void mpc1211_writel(unsigned int b, unsigned long addr)
+{
+        *(volatile unsigned int *)addr = b;
+}
+
+unsigned long mpc1211_isa_port2addr(unsigned long offset)
+{
+	return port2adr(offset);
+}
diff -urN linux-2.5.73-bk9/arch/sh/boards/mpc1211/led.c linux-2.5.73-bk10/arch/sh/boards/mpc1211/led.c
--- linux-2.5.73-bk9/arch/sh/boards/mpc1211/led.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/boards/mpc1211/led.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,64 @@
+/*
+ * linux/arch/sh/kernel/led_mpc1211.c
+ *
+ * Copyright (C) 2001  Saito.K & Jeanne
+ *
+ * This file contains Interface MPC-1211 specific LED code.
+ */
+
+#include <linux/config.h>
+
+static void mach_led(int position, int value)
+{
+	volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
+
+	if (value) {
+		*p |= 1;
+	} else {
+		*p &= ~1;
+	}
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_mpc1211(void)
+{
+	static unsigned int cnt = 0, period = 0;
+	volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
+	static unsigned bit = 0, up = 1;
+
+	cnt += 1;
+	if (cnt < period) {
+		return;
+	}
+
+	cnt = 0;
+
+	/* Go through the points (roughly!):
+	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+	 */
+	period = 110 - ( (300<<FSHIFT)/
+			 ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+	if (up) {
+		if (bit == 7) {
+			bit--;
+			up=0;
+		} else {
+			bit ++;
+		}
+	} else {
+		if (bit == 0) {
+			bit++;
+			up=1;
+		} else {
+			bit--;
+		}
+	}
+	*p = 1<<bit;
+
+}
+#endif /* CONFIG_HEARTBEAT */
diff -urN linux-2.5.73-bk9/arch/sh/boards/mpc1211/mach.c linux-2.5.73-bk10/arch/sh/boards/mpc1211/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/mpc1211/mach.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/boards/mpc1211/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,77 @@
+/*
+ * linux/arch/sh/kernel/mach_mpc1211.c
+ *
+ * Copyright (C) 2001 Saito.K & Jeanne
+ *
+ * Machine vector for the Interface MPC-1211
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/mpc1211/io.h>
+
+void heartbeat_mpc1211(void);
+void setup_mpc1211(void);
+void init_mpc1211_IRQ(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_mpc1211 __initmv = {
+	.mv_name		= "MPC-1211",
+
+	.mv_nr_irqs		= 48,
+
+	.mv_inb			= mpc1211_inb,
+	.mv_inw			= mpc1211_inw,
+	.mv_inl			= mpc1211_inl,
+	.mv_outb		= mpc1211_outb,
+	.mv_outw		= mpc1211_outw,
+	.mv_outl		= mpc1211_outl,
+
+	.mv_inb_p		= mpc1211_inb_p,
+	.mv_inw_p		= mpc1211_inw,
+	.mv_inl_p		= mpc1211_inl,
+	.mv_outb_p		= mpc1211_outb_p,
+	.mv_outw_p		= mpc1211_outw,
+	.mv_outl_p		= mpc1211_outl,
+
+	.mv_insb		= mpc1211_insb,
+	.mv_insw		= mpc1211_insw,
+	.mv_insl		= mpc1211_insl,
+	.mv_outsb		= mpc1211_outsb,
+	.mv_outsw		= mpc1211_outsw,
+	.mv_outsl		= mpc1211_outsl,
+
+	.mv_readb		= mpc1211_readb,
+	.mv_readw		= mpc1211_readw,
+	.mv_readl		= mpc1211_readl,
+	.mv_writeb		= mpc1211_writeb,
+	.mv_writew		= mpc1211_writew,
+	.mv_writel		= mpc1211_writel,
+
+	.mv_ioremap		= generic_ioremap,
+	.mv_iounmap		= generic_iounmap,
+
+	.mv_isa_port2addr	= mpc1211_isa_port2addr,
+
+	.mv_irq_demux		= mpc1211_irq_demux,
+
+	.mv_init_arch		= setup_mpc1211,
+	.mv_init_irq		= init_mpc1211_IRQ,
+	//	mv_init_pci            = mpc1211_pcibios_init,
+
+#ifdef CONFIG_HEARTBEAT
+	.mv_heartbeat		= heartbeat_mpc1211,
+#endif
+
+	.mv_rtc_gettimeofday	= mpc1211_rtc_gettimeofday,
+	.mv_rtc_settimeofday	= mpc1211_rtc_settimeofday,
+};
+ALIAS_MV(mpc1211)
diff -urN linux-2.5.73-bk9/arch/sh/boards/mpc1211/pci.c linux-2.5.73-bk10/arch/sh/boards/mpc1211/pci.c
--- linux-2.5.73-bk9/arch/sh/boards/mpc1211/pci.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/boards/mpc1211/pci.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,304 @@
+/*
+ *	Low-Level PCI Support for the MPC-1211(CTP/PCI/MPC-SH02)
+ *
+ *  (c) 2002-2003 Saito.K & Jeanne
+ *
+ *  Dustin McIntire (dustin@sensoria.com)
+ *	Derived from arch/i386/kernel/pci-*.c which bore the message:
+ *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *	
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/mpc1211/pci.h>
+
+static struct resource mpcpci_io_resource = {
+	"MPCPCI IO",
+	0x00000000,
+	0xffffffff,
+	IORESOURCE_IO
+};
+
+static struct resource mpcpci_mem_resource = {
+	"MPCPCI mem",
+	0x00000000,
+	0xffffffff,
+	IORESOURCE_MEM
+};
+
+static struct pci_ops pci_direct_conf1;
+struct pci_channel board_pci_channels[] = {
+	{&pci_direct_conf1, &mpcpci_io_resource, &mpcpci_mem_resource, 0, 256},
+	{NULL, NULL, NULL, 0, 0},
+};
+
+/*
+ * Direct access to PCI hardware...
+ */
+
+
+#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+	u32 word;
+	unsigned long flags;
+
+	/* 
+	 * PCIPDR may only be accessed as 32 bit words, 
+	 * so we must do byte alignment by hand 
+	 */
+	local_irq_save(flags);
+	writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
+	word = readl(PCIPDR);
+	local_irq_restore(flags);
+
+	switch (size) {
+	case 1:
+		switch (where & 0x3) {
+		case 3:
+			*value = (u8)(word >> 24);
+			break;
+		case 2:
+			*value = (u8)(word >> 16);
+			break;
+		case 1:
+			*value = (u8)(word >> 8);
+			break;
+		default:
+			*value = (u8)word;
+			break;
+		}
+		break;
+	case 2:
+		switch (where & 0x3) {
+		case 3:
+			*value = (u16)(word >> 24);
+			local_irq_save(flags);
+			writel(CONFIG_CMD(bus,devfn,(where+1)), PCIPAR);
+			word = readl(PCIPDR);
+			local_irq_restore(flags);
+			*value |= ((word & 0xff) << 8);
+			break;
+		case 2:
+			*value = (u16)(word >> 16);
+			break;
+		case 1:
+			*value = (u16)(word >> 8);
+			break;
+		default:
+			*value = (u16)word;
+			break;
+		}
+		break;
+	case 4:
+		*value = word;
+		break;
+	}
+	PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value); 
+	return PCIBIOS_SUCCESSFUL;    
+}
+
+/* 
+ * Since MPC-1211 only does 32bit access we'll have to do a read,mask,write operation.  
+ * We'll allow an odd byte offset, though it should be illegal.
+ */ 
+static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+	u32 word,mask = 0;
+	unsigned long flags;
+	u32 shift = (where & 3) * 8;
+
+	if(size == 1) {
+		mask = ((1 << 8) - 1) << shift;  // create the byte mask
+	} else if(size == 2){
+		if(shift == 24)
+			return PCIBIOS_BAD_REGISTER_NUMBER;           
+		mask = ((1 << 16) - 1) << shift;  // create the word mask
+	}
+	local_irq_save(flags);
+	writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
+	if(size == 4){
+		writel(value, PCIPDR);
+		local_irq_restore(flags);
+		PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	word = readl(PCIPDR);
+	word &= ~mask;
+	word |= ((value << shift) & mask);
+	writel(word, PCIPDR);
+	local_irq_restore(flags);
+	PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+#undef CONFIG_CMD
+
+static struct pci_ops pci_direct_conf1 = {
+	.read =		pci_conf1_read,
+	.write = 	pci_conf1_write,
+};
+
+static void __devinit quirk_ali_ide_ports(struct pci_dev *dev)
+{
+        dev->resource[0].start = 0x1f0;
+	dev->resource[0].end   = 0x1f7;
+	dev->resource[0].flags = IORESOURCE_IO;
+        dev->resource[1].start = 0x3f6;
+	dev->resource[1].end   = 0x3f6;
+	dev->resource[1].flags = IORESOURCE_IO;
+        dev->resource[2].start = 0x170;
+	dev->resource[2].end   = 0x177;
+	dev->resource[2].flags = IORESOURCE_IO;
+        dev->resource[3].start = 0x376;
+	dev->resource[3].end   = 0x376;
+	dev->resource[3].flags = IORESOURCE_IO;
+        dev->resource[4].start = 0xf000;
+	dev->resource[4].end   = 0xf00f;
+	dev->resource[4].flags = IORESOURCE_IO;
+}
+
+
+/* Add future fixups here... */
+struct pci_fixup pcibios_fixups[] = {
+  { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports },
+	{ 0 }
+};
+
+char * __devinit pcibios_setup(char *str)
+{
+	return str;
+}
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+	pci_read_bridge_bases(b);
+}
+
+/* 
+ * 	IRQ functions 
+ */
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+        return (((pin-1) + slot) % 4) + 1;
+}
+
+static inline u8 bridge_swizzle_pci_1(u8 pin, u8 slot)
+{
+        return (((pin-1) - slot) & 3) + 1;
+}
+
+static u8 __init mpc1211_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+	unsigned long flags;
+        u8 pin = *pinp;
+	u32 word;
+
+	for ( ; dev->bus->self; dev = dev->bus->self) {
+		if (!pin)
+			continue;
+
+		if (dev->bus->number == 1) {
+			local_irq_save(flags);
+			writel(0x80000000 | 0x2c, PCIPAR);
+			word = readl(PCIPDR);
+			local_irq_restore(flags);
+			word >>= 16;
+
+			if (word == 0x0001)
+				pin = bridge_swizzle_pci_1(pin, PCI_SLOT(dev->devfn));
+			else
+				pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		} else
+			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+	}
+
+	*pinp = pin;
+
+	return PCI_SLOT(dev->devfn);
+}
+
+static int __init map_mpc1211_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq = -1;
+
+	/* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
+	if (dev->bus->number == 0) {
+		switch (slot) {
+		case 13:   irq =  9; break;   /* USB */
+		case 22:   irq = 10; break;   /* LAN */
+		default:   irq =  0; break;
+	  	}
+	} else {
+		switch (pin) {
+		case 0:   irq =  0; break;
+		case 1:   irq =  7; break;
+		case 2:   irq =  9; break;
+		case 3:   irq = 10; break;
+		case 4:   irq = 11; break;
+		}
+	}
+
+	if( irq < 0 ) {
+		PCIDBG(3, "PCI: Error mapping IRQ on device %s\n", dev->slot_name);
+		return irq;
+	}
+	
+	PCIDBG(2, "Setting IRQ for slot %s to %d\n", dev->slot_name, irq);
+
+	return irq;
+}
+
+void __init pcibios_fixup(void) { /* Do nothing. */ }
+
+void __init pcibios_fixup_irqs(void)
+{
+	pci_fixup_irqs(mpc1211_swizzle, map_mpc1211_irq);
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+			    unsigned long size, unsigned long align)
+{
+	unsigned long start = res->start;
+
+	if (res->flags & IORESOURCE_IO) {
+		if (start >= 0x10000UL) {
+			if ((start & 0xffffUL) < 0x4000UL) {
+				start = (start & 0xffff0000UL) + 0x4000UL;
+			} else if ((start & 0xffffUL) >= 0xf000UL) {
+				start = (start & 0xffff0000UL) + 0x10000UL;
+			}
+			res->start = start;
+		} else {
+			if (start & 0x300) {
+				start = (start + 0x3ff) & ~0x3ff;
+				res->start = start;
+			}
+		}
+	}
+}
+
diff -urN linux-2.5.73-bk9/arch/sh/boards/mpc1211/rtc.c linux-2.5.73-bk10/arch/sh/boards/mpc1211/rtc.c
--- linux-2.5.73-bk9/arch/sh/boards/mpc1211/rtc.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/boards/mpc1211/rtc.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,145 @@
+/*
+ * linux/arch/sh/kernel/rtc-mpc1211.c -- MPC-1211 on-chip RTC support
+ *
+ *  Copyright (C) 2002  Saito.K & Jeanne
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/mc146818rtc.h>
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+/* arc/i386/kernel/time.c */
+unsigned long get_cmos_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int i;
+
+	spin_lock(&rtc_lock);
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+	  {
+	    BCD_TO_BIN(sec);
+	    BCD_TO_BIN(min);
+	    BCD_TO_BIN(hour);
+	    BCD_TO_BIN(day);
+	    BCD_TO_BIN(mon);
+	    BCD_TO_BIN(year);
+	  }
+	spin_unlock(&rtc_lock);
+	if ((year += 1900) < 1970)
+		year += 100;
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+void mpc1211_rtc_gettimeofday(struct timeval *tv)
+{
+
+	tv->tv_sec = get_cmos_time();
+	tv->tv_usec = 0;
+}
+
+/* arc/i386/kernel/time.c */
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you'll only notice that after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	/* gets recalled with irq locally disabled */
+	spin_lock(&rtc_lock);
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+		retval = -1;
+	}
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	spin_unlock(&rtc_lock);
+
+	return retval;
+}
+
+int mpc1211_rtc_settimeofday(const struct timeval *tv)
+{
+	unsigned long nowtime = tv->tv_sec;
+
+	return set_rtc_mmss(nowtime);
+}
diff -urN linux-2.5.73-bk9/arch/sh/boards/mpc1211/setup.c linux-2.5.73-bk10/arch/sh/boards/mpc1211/setup.c
--- linux-2.5.73-bk9/arch/sh/boards/mpc1211/setup.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/boards/mpc1211/setup.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,336 @@
+/*
+ * linux/arch/sh/board/mpc1211/setup.c
+ *
+ * Copyright (C) 2002  Saito.K & Jeanne,  Fujii.Y
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/mpc1211/mpc1211.h>
+#include <asm/mpc1211/m1543c.h>
+
+
+/* ALI15X3 SMBus address offsets */
+#define SMBHSTSTS   (0 + 0x3100)
+#define SMBHSTCNT   (1 + 0x3100)
+#define SMBHSTSTART (2 + 0x3100)
+#define SMBHSTCMD   (7 + 0x3100)
+#define SMBHSTADD   (3 + 0x3100)
+#define SMBHSTDAT0  (4 + 0x3100)
+#define SMBHSTDAT1  (5 + 0x3100)
+#define SMBBLKDAT   (6 + 0x3100)
+
+/* Other settings */
+#define MAX_TIMEOUT 500		/* times 1/100 sec */
+
+/* ALI15X3 command constants */
+#define ALI15X3_ABORT      0x04
+#define ALI15X3_T_OUT      0x08
+#define ALI15X3_QUICK      0x00
+#define ALI15X3_BYTE       0x10
+#define ALI15X3_BYTE_DATA  0x20
+#define ALI15X3_WORD_DATA  0x30
+#define ALI15X3_BLOCK_DATA 0x40
+#define ALI15X3_BLOCK_CLR  0x80
+
+/* ALI15X3 status register bits */
+#define ALI15X3_STS_IDLE	0x04
+#define ALI15X3_STS_BUSY	0x08
+#define ALI15X3_STS_DONE	0x10
+#define ALI15X3_STS_DEV		0x20	/* device error */
+#define ALI15X3_STS_COLL	0x40	/* collision or no response */
+#define ALI15X3_STS_TERM	0x80	/* terminated by abort */
+#define ALI15X3_STS_ERR		0xE0	/* all the bad error bits */
+
+const char *get_system_type(void)
+{
+	return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
+}
+
+void platform_setup(void)
+{
+}
+
+static void __init pci_write_config(unsigned long busNo,
+				    unsigned long devNo,
+				    unsigned long fncNo,
+				    unsigned long cnfAdd,
+				    unsigned long cnfData)
+{
+	ctrl_outl((0x80000000 
+                + ((busNo & 0xff) << 16) 
+                + ((devNo & 0x1f) << 11) 
+                + ((fncNo & 0x07) <<  8) 
+		+ (cnfAdd & 0xfc)), PCIPAR);
+
+        ctrl_outl(cnfData, PCIPDR);
+}
+
+/*
+  Initialize IRQ setting
+*/
+
+static unsigned char m_irq_mask = 0xfb;
+static unsigned char s_irq_mask = 0xff;
+volatile unsigned long irq_err_count;
+
+static void disable_mpc1211_irq(unsigned int irq)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	if( irq < 8) {
+		m_irq_mask |= (1 << irq);
+		outb(m_irq_mask,I8259_M_MR);
+	} else {
+		s_irq_mask |= (1 << (irq - 8));
+		outb(s_irq_mask,I8259_S_MR);
+	}
+	restore_flags(flags);
+
+}
+
+static void enable_mpc1211_irq(unsigned int irq)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+
+	if( irq < 8) {
+		m_irq_mask &= ~(1 << irq);
+		outb(m_irq_mask,I8259_M_MR);
+	} else {
+		s_irq_mask &= ~(1 << (irq - 8));
+		outb(s_irq_mask,I8259_S_MR);
+	}
+	restore_flags(flags);
+}
+
+static inline int mpc1211_irq_real(unsigned int irq)
+{
+	int value;
+	int irqmask;
+
+	if ( irq < 8) {
+		irqmask = 1<<irq;
+		outb(0x0b,I8259_M_CR);		/* ISR register */
+		value = inb(I8259_M_CR) & irqmask;
+		outb(0x0a,I8259_M_CR);		/* back ro the IPR reg */
+		return value;
+	}
+	irqmask = 1<<(irq - 8);
+	outb(0x0b,I8259_S_CR);		/* ISR register */
+	value = inb(I8259_S_CR) & irqmask;
+	outb(0x0a,I8259_S_CR);		/* back ro the IPR reg */
+	return value;
+}
+
+static void mask_and_ack_mpc1211(unsigned int irq)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+
+	if(irq < 8) {
+		if(m_irq_mask & (1<<irq)){
+		  if(!mpc1211_irq_real(irq)){
+		    irq_err_count++;
+		    printk("spurious 8259A interrupt: IRQ %x\n",irq);
+		   }
+		} else {
+			m_irq_mask |= (1<<irq);
+		}
+		inb(I8259_M_MR);		/* DUMMY */
+		outb(m_irq_mask,I8259_M_MR);	/* disable */
+		outb(0x60+irq,I8259_M_CR);	/* EOI */
+		
+	} else {
+		if(s_irq_mask & (1<<(irq - 8))){
+		  if(!mpc1211_irq_real(irq)){
+		    irq_err_count++;
+		    printk("spurious 8259A interrupt: IRQ %x\n",irq);
+		  }
+		} else {
+			s_irq_mask |= (1<<(irq - 8));
+		}
+		inb(I8259_S_MR);		/* DUMMY */
+		outb(s_irq_mask,I8259_S_MR);	/* disable */
+		outb(0x60+(irq-8),I8259_S_CR); 	/* EOI */
+		outb(0x60+2,I8259_M_CR);
+	}
+	restore_flags(flags);
+}
+
+static void end_mpc1211_irq(unsigned int irq)
+{
+	enable_mpc1211_irq(irq);
+}
+
+static unsigned int startup_mpc1211_irq(unsigned int irq)
+{
+	enable_mpc1211_irq(irq);
+	return 0;
+}
+
+static void shutdown_mpc1211_irq(unsigned int irq)
+{
+	disable_mpc1211_irq(irq);
+}
+
+static struct hw_interrupt_type mpc1211_irq_type = {
+	.typename	= "MPC1211-IRQ",
+	.startup	= startup_mpc1211_irq,
+	.shutdown	= shutdown_mpc1211_irq,
+	.enable		= enable_mpc1211_irq,
+	.disable	= disable_mpc1211_irq,
+	.ack		= mask_and_ack_mpc1211,
+	.end		= end_mpc1211_irq
+};
+
+static void make_mpc1211_irq(unsigned int irq)
+{
+	irq_desc[irq].handler = &mpc1211_irq_type;
+	irq_desc[irq].status  = IRQ_DISABLED;
+	irq_desc[irq].action  = 0;
+	irq_desc[irq].depth   = 1;
+	disable_mpc1211_irq(irq);
+}
+
+int mpc1211_irq_demux(int irq)
+{
+	unsigned int poll;
+
+	if( irq == 2 ) {
+		outb(0x0c,I8259_M_CR);
+		poll = inb(I8259_M_CR);
+		if(poll & 0x80) {
+			irq = (poll & 0x07);
+		}
+		if( irq == 2) {
+			outb(0x0c,I8259_S_CR);
+			poll = inb(I8259_S_CR);
+			irq = (poll & 0x07) + 8;
+		}
+	}
+	return irq;
+}
+
+void __init init_mpc1211_IRQ(void)
+{
+	int i;
+	/*
+	 * Super I/O (Just mimic PC):
+	 *  1: keyboard
+	 *  3: serial 1
+	 *  4: serial 0
+	 *  5: printer
+	 *  6: floppy
+	 *  8: rtc
+	 * 10: lan
+	 * 12: mouse
+	 * 14: ide0
+	 * 15: ide1
+	 */
+
+	pci_write_config(0,0,0,0x54, 0xb0b0002d);
+	outb(0x11, I8259_M_CR); 	/* mater icw1 edge trigger  */
+	outb(0x11, I8259_S_CR);		/* slave icw1 edge trigger  */
+	outb(0x20, I8259_M_MR); 	/* m icw2 base vec 0x08	    */
+	outb(0x28, I8259_S_MR);		/* s icw2 base vec 0x70	    */
+	outb(0x04, I8259_M_MR);		/* m icw3 slave irq2	    */
+	outb(0x02, I8259_S_MR);		/* s icw3 slave id	    */
+	outb(0x01, I8259_M_MR);		/* m icw4 non buf normal eoi*/
+	outb(0x01, I8259_S_MR);		/* s icw4 non buf normal eo1*/
+	outb(0xfb, I8259_M_MR);		/* disable irq0--irq7  */
+	outb(0xff, I8259_S_MR);		/* disable irq8--irq15 */
+
+	for ( i=0; i < 16; i++) {
+		if(i != 2) {
+			make_mpc1211_irq(i);
+		}
+	}
+}
+
+/*
+  Initialize the board
+*/
+
+
+static void delay (void)
+{
+  volatile unsigned short tmp;
+  tmp = *(volatile unsigned short *) 0xa0000000;
+}
+
+static void delay1000 (void)
+{
+  int i;
+  for (i=0; i<1000; i++)
+    delay ();
+}
+
+static int put_smb_blk(unsigned char *p, int address, int command, int no)
+{
+	int temp;
+	int timeout;
+	int i;
+
+	outb(0xff, SMBHSTSTS);
+	temp = inb(SMBHSTSTS);
+	for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) {
+		delay1000();
+		temp = inb(SMBHSTSTS);
+	}
+	if (timeout >= MAX_TIMEOUT){
+		return -1;
+	}
+
+	outb(((address & 0x7f) << 1), SMBHSTADD);
+	outb(0xc0, SMBHSTCNT);
+	outb(command & 0xff, SMBHSTCMD);
+	outb(no & 0x1f, SMBHSTDAT0);
+
+	for(i = 1; i <= no; i++) {
+		outb(*p++, SMBBLKDAT);
+	}
+	outb(0xff, SMBHSTSTART);
+
+	temp = inb(SMBHSTSTS);
+	for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) {
+		delay1000();
+		temp = inb(SMBHSTSTS);
+	}
+	if (timeout >= MAX_TIMEOUT) {
+		return -2;
+	}
+	if ( temp & ALI15X3_STS_ERR ){
+		return -3;
+	}
+	return 0;
+}
+
+void __init setup_mpc1211(void)
+{
+  unsigned char spd_buf[128];
+  pci_write_config(0,0,0,0x54, 0xb0b00000);
+
+retry:
+  outb(ALI15X3_ABORT, SMBHSTCNT);
+  spd_buf[0] = 0x0c;
+  spd_buf[1] = 0x43;
+  spd_buf[2] = 0x7f;
+  spd_buf[3] = 0x03;
+  spd_buf[4] = 0x00;
+  spd_buf[5] = 0x03;
+  spd_buf[6] = 0x00;
+  if (put_smb_blk(spd_buf, 0x69, 0, 7) < 0) {
+    goto retry;
+  }
+}
diff -urN linux-2.5.73-bk9/arch/sh/boards/saturn/mach.c linux-2.5.73-bk10/arch/sh/boards/saturn/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/saturn/mach.c	2003-06-22 11:33:32.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/saturn/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -53,8 +53,6 @@
 
         mv_ioremap:             saturn_ioremap,
         mv_iounmap:             saturn_iounmap,
-
-        mv_hw_saturn:           1,
 };
 
 ALIAS_MV(saturn)
diff -urN linux-2.5.73-bk9/arch/sh/boards/se/770x/mach.c linux-2.5.73-bk10/arch/sh/boards/se/770x/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/se/770x/mach.c	2003-06-22 11:33:14.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/se/770x/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -72,6 +72,5 @@
 #ifdef CONFIG_HEARTBEAT
 	mv_heartbeat:		heartbeat_se,
 #endif
-	mv_hw_se:		1,
 };
 ALIAS_MV(se)
diff -urN linux-2.5.73-bk9/arch/sh/boards/se/7751/mach.c linux-2.5.73-bk10/arch/sh/boards/se/7751/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/se/7751/mach.c	2003-06-22 11:32:55.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/se/7751/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -65,6 +65,5 @@
 #ifdef CONFIG_HEARTBEAT
 	mv_heartbeat:		heartbeat_7751se,
 #endif
-	mv_hw_7751se:		1,
 };
 ALIAS_MV(7751se)
diff -urN linux-2.5.73-bk9/arch/sh/boards/sh2000/mach.c linux-2.5.73-bk10/arch/sh/boards/sh2000/mach.c
--- linux-2.5.73-bk9/arch/sh/boards/sh2000/mach.c	2003-06-22 11:33:09.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boards/sh2000/mach.c	2003-07-02 04:57:23.000000000 -0700
@@ -53,7 +53,5 @@
 
         mv_ioremap:             generic_ioremap,
         mv_iounmap:             generic_iounmap,
-
-        mv_hw_sh2000:           1,
 };
 ALIAS_MV(sh2000)
diff -urN linux-2.5.73-bk9/arch/sh/boot/Makefile linux-2.5.73-bk10/arch/sh/boot/Makefile
--- linux-2.5.73-bk9/arch/sh/boot/Makefile	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/boot/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -8,25 +8,13 @@
 # Copyright (C) 1999 Stuart Menefy
 #
 
-SYSTEM  =$(TOPDIR)/vmlinux
+targets := zImage
+subdir- := compressed
 
-Image:	$(SYSTEM)
-	$(OBJCOPY) $(OBJCOPYFLAGS) $< $@
+$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+	$(call if_changed,objcopy)
+	@echo 'Kernel: $@ is ready'
 
-zImage: compressed/vmlinux
-	$(OBJCOPY) $(OBJCOPYFLAGS) $< $@
+$(obj)/compressed/vmlinux: FORCE
+	$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed $@
 
-compressed/vmlinux: $(TOPDIR)/vmlinux
-	$(MAKE) -C compressed vmlinux
-
-install: Image
-	sh -x ./install.sh $(KERNELRELEASE) Image $(TOPDIR)/System.map "$(INSTALL_PATH)"
-
-zinstall: zImage
-	sh -x ./install.sh $(KERNELRELEASE) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
-
-clean:
-	rm -f tools/build
-	rm -f setup bootsect zImage compressed/vmlinux.out
-	rm -f bsetup bbootsect bzImage compressed/bvmlinux.out
-	@$(MAKE) -C compressed clean
diff -urN linux-2.5.73-bk9/arch/sh/cchips/hd6446x/hd64465/gpio.c linux-2.5.73-bk10/arch/sh/cchips/hd6446x/hd64465/gpio.c
--- linux-2.5.73-bk9/arch/sh/cchips/hd6446x/hd64465/gpio.c	2003-06-22 11:33:03.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/cchips/hd6446x/hd64465/gpio.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * $Id: gpio.c,v 1.1.2.3 2002/11/04 20:33:57 lethal Exp $
+ * $Id: gpio.c,v 1.4 2003/05/19 22:24:18 lethal Exp $
  * by Greg Banks <gbanks@pocketpenguins.com>
  * (c) 2000 PocketPenguins Inc
  *
@@ -85,7 +85,7 @@
     void *dev;
 } handlers[GPIO_NPORTS * 8];
 
-static void hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs)
 {
     	unsigned short port, pin, isr, mask, portpin;
 	
@@ -107,6 +107,8 @@
 	    /* Write 1s back to ISR to clear it?  That's what the manual says.. */
 	    outw(isr, GPIO_ISR(port));
 	}
+
+	return IRQ_HANDLED;
 }
 
 void hd64465_gpio_register_irq(int portpin, int mode,
@@ -165,13 +167,20 @@
 
 static int __init hd64465_gpio_init(void)
 {
-    	/* TODO: check return values */
-    	request_region(HD64465_REG_GPACR, 0x1000, MODNAME);
-	request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt,
-	    SA_INTERRUPT, MODNAME, 0);
+	if (!request_region(HD64465_REG_GPACR, 0x1000, MODNAME))
+		return -EBUSY;
+	if (request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt,
+	    		SA_INTERRUPT, MODNAME, 0))
+		goto out_irqfailed;
 
     	printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO);
+
 	return 0;
+
+out_irqfailed:
+	release_region(HD64465_REG_GPACR, 0x1000);
+
+	return -EINVAL;
 }
 
 static void __exit hd64465_gpio_exit(void)
@@ -182,3 +191,6 @@
 
 module_init(hd64465_gpio_init);
 module_exit(hd64465_gpio_exit);
+
+MODULE_LICENSE("GPL");
+
diff -urN linux-2.5.73-bk9/arch/sh/configs/defconfig-adx linux-2.5.73-bk10/arch/sh/configs/defconfig-adx
--- linux-2.5.73-bk9/arch/sh/configs/defconfig-adx	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/configs/defconfig-adx	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,277 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor type and features
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+CONFIG_SH_ADX=y
+# CONFIG_SH_UNKNOWN is not set
+CONFIG_SH_RTC=y
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MEMORY_START=08000000
+CONFIG_MEMORY_SIZE=00400000
+CONFIG_MEMORY_SET=y
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+# CONFIG_NET is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=b8000000
+# CONFIG_HD64461 is not set
+# CONFIG_HD64465 is not set
+# CONFIG_SH_DMA is not set
+# CONFIG_PCI is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+CONFIG_SH_SCI=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_PSMOUSE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_SH_STANDARD_BIOS=y
+CONFIG_SH_EARLY_PRINTK=y
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
diff -urN linux-2.5.73-bk9/arch/sh/configs/defconfig-cqreek linux-2.5.73-bk10/arch/sh/configs/defconfig-cqreek
--- linux-2.5.73-bk9/arch/sh/configs/defconfig-cqreek	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/configs/defconfig-cqreek	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,275 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor type and features
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+CONFIG_SH_CQREEK=y
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_UNKNOWN is not set
+CONFIG_SH_RTC=y
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+CONFIG_CPU_SUBTYPE_SH7708=y
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+CONFIG_CPU_SH3=y
+# CONFIG_CPU_SH4 is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MEMORY_START=0c000000
+CONFIG_MEMORY_SIZE=00400000
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+# CONFIG_NET is not set
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=b8000000
+# CONFIG_HD64461 is not set
+# CONFIG_HD64465 is not set
+# CONFIG_SH_DMA is not set
+# CONFIG_PCI is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+CONFIG_SH_SCI=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_PSMOUSE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_SH_STANDARD_BIOS=y
+CONFIG_SH_EARLY_PRINTK=y
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
diff -urN linux-2.5.73-bk9/arch/sh/configs/defconfig-dreamcast linux-2.5.73-bk10/arch/sh/configs/defconfig-dreamcast
--- linux-2.5.73-bk9/arch/sh/configs/defconfig-dreamcast	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/configs/defconfig-dreamcast	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,488 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor type and features
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+CONFIG_SH_DREAMCAST=y
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_SH_RTC is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MEMORY_START=0c000000
+CONFIG_MEMORY_SIZE=00400000
+CONFIG_MEMORY_SET=y
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+CONFIG_NET=y
+# CONFIG_HD64461 is not set
+# CONFIG_HD64465 is not set
+# CONFIG_SH_DMA is not set
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GODIRECT is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+# CONFIG_SH_PCIDMA_NONCOHERENT is not set
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_STNIC is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_TULIP is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+CONFIG_8139TOO_DREAMCAST=y
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_RHINE_MMIO is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=y
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Maple Bus support
+#
+CONFIG_MAPLE=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+# CONFIG_SERIAL is not set
+CONFIG_SH_SCI=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# Maple Bus input peripherals
+#
+CONFIG_MAPLE_KEYBOARD=y
+CONFIG_MAPLE_MOUSE=y
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_INPUT_SERIO is not set
+# CONFIG_INPUT_SERPORT is not set
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
+CONFIG_INPUT_MAPLE_CONTROL=y
+# CONFIG_PSMOUSE is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_SH_WDT=y
+# CONFIG_RTC is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_VIDEO_SELECT is not set
+# CONFIG_MDA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_CLGEN is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_PVR2=y
+CONFIG_FB_PVR2_DEBUG=y
+# CONFIG_FB_E1355 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_SH_STANDARD_BIOS is not set
diff -urN linux-2.5.73-bk9/arch/sh/defconfig linux-2.5.73-bk10/arch/sh/defconfig
--- linux-2.5.73-bk9/arch/sh/defconfig	2003-06-22 11:32:55.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/defconfig	2003-07-02 04:57:23.000000000 -0700
@@ -17,7 +17,6 @@
 #
 # Processor type and features
 #
-CONFIG_SH_GENERIC=y
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_OVERDRIVE is not set
 # CONFIG_SH_HP600 is not set
diff -urN linux-2.5.73-bk9/arch/sh/kernel/Makefile linux-2.5.73-bk10/arch/sh/kernel/Makefile
--- linux-2.5.73-bk9/arch/sh/kernel/Makefile	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -14,7 +14,8 @@
 obj-$(CONFIG_CF_ENABLER)	+= cf-enabler.o
 obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
 obj-$(CONFIG_SH_KGDB)		+= kgdb_stub.o kgdb_jmp.o
-obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
+obj-$(CONFIG_SH_CPU_FREQ)	+= cpufreq.o
+obj-$(CONFIG_MODULES)		+= module.o
 
 ifneq ($(CONFIG_SH_DREAMCAST),y)
 obj-$(CONFIG_PCI)		+= pci-dma.o
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cf-enabler.c linux-2.5.73-bk10/arch/sh/kernel/cf-enabler.c
--- linux-2.5.73-bk9/arch/sh/kernel/cf-enabler.c	2003-06-22 11:32:59.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/cf-enabler.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: cf-enabler.c,v 1.8 2001/07/18 12:32:21 gniibe Exp $
+/* $Id: cf-enabler.c,v 1.3 2003/05/04 19:29:52 lethal Exp $
  *
  *  linux/drivers/block/cf-enabler.c
  *
@@ -29,7 +29,7 @@
  * 0xB8001000 : Common Memory
  * 0xBA000000 : I/O
  */
-#if defined(CONFIG_IDE) && defined(__SH4__)
+#if defined(CONFIG_IDE) && defined(CONFIG_CPU_SH4)
 /* SH4 can't access PCMCIA interface through P2 area.
  * we must remap it with appropreate attribute bit of the page set.
  * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */
@@ -76,7 +76,7 @@
 /* You must have enabled the card, and set the level interrupt
  * before reaching this point. Possibly in boot ROM or boot loader.
  */
-#if defined(CONFIG_IDE) && defined(__SH4__)
+#if defined(CONFIG_IDE) && defined(CONFIG_CPU_SH4)
 	allocate_cf_area();
 #endif
 #if defined(CONFIG_SH_UNKNOWN)
@@ -87,7 +87,7 @@
 	return 0;
 }
 
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_SOLUTION_ENGINE)
+#if defined(CONFIG_SH_SOLUTION_ENGINE)
 #include <asm/hitachi_se.h>
 
 /*
@@ -148,7 +148,7 @@
 
 int __init cf_init(void)
 {
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_SOLUTION_ENGINE)
+#if defined(CONFIG_SH_SOLUTION_ENGINE)
 	if (MACH_SE)
 		return cf_init_se();
 #endif
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/Makefile linux-2.5.73-bk10/arch/sh/kernel/cpu/Makefile
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,16 @@
+#
+# Makefile for the Linux/SuperH CPU-specifc backends.
+#
+
+obj-y	:= irq_ipr.o irq_imask.o
+
+obj-$(CONFIG_CPU_SH2)		+= sh2/
+obj-$(CONFIG_CPU_SH3)		+= sh3/
+obj-$(CONFIG_CPU_SH4)		+= sh4/
+
+obj-$(CONFIG_SH_DMA)            += dma.o
+obj-$(CONFIG_SH_RTC)            += rtc.o
+obj-$(CONFIG_UBC_WAKEUP)	+= ubc.o
+
+USE_STANDARD_AS_RULE := true
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/dma.c linux-2.5.73-bk10/arch/sh/kernel/cpu/dma.c
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/dma.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/dma.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,211 @@
+/*
+ * arch/sh/kernel/cpu/dma.c
+ *
+ * Copyright (C) 2000 Takashi YOSHII
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * PC like DMA API for SuperH's DMAC.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/signal.h>
+#include <asm/dma.h>
+
+static struct dma_info_t *dma_info[MAX_DMA_CHANNELS];
+static struct dma_info_t *autoinit_info[SH_MAX_DMA_CHANNELS] = {0};
+extern spinlock_t dma_spin_lock;
+
+/*
+ * The SuperH DMAC supports a number of transmit sizes, we list them here,
+ * with their respective values as they appear in the CHCR registers.
+ *
+ * Defaults to a 64-bit transfer size.
+ */
+enum {
+	XMIT_SZ_64BIT	= 0,
+	XMIT_SZ_8BIT	= 1,
+	XMIT_SZ_16BIT	= 2,
+	XMIT_SZ_32BIT	= 3,
+	XMIT_SZ_256BIT	= 4,
+};
+
+/*
+ * The DMA count is defined as the number of bytes to transfer.
+ */
+static unsigned int ts_shift[] = {
+	[XMIT_SZ_64BIT]		3,
+	[XMIT_SZ_8BIT]		0,
+	[XMIT_SZ_16BIT]		1,
+	[XMIT_SZ_32BIT]		2,
+	[XMIT_SZ_256BIT]	5,
+};
+
+/*
+ * We determine the correct shift size based off of the CHCR transmit size
+ * for the given channel. Since we know that it will take:
+ *
+ * 	info->count >> ts_shift[transmit_size]
+ *
+ * iterations to complete the transfer.
+ */
+static inline unsigned int calc_xmit_shift(struct dma_info_t *info)
+{
+	return ts_shift[(ctrl_inl(CHCR[info->chan]) >> 4) & 0x0007];
+}
+
+static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int chan = irq - DMTE_IRQ[0];
+	struct dma_info_t *info = autoinit_info[chan];
+
+	if( info->mode & DMA_MODE_WRITE )
+		ctrl_outl(info->mem_addr, SAR[info->chan]);
+	else
+		ctrl_outl(info->mem_addr, DAR[info->chan]);
+
+	ctrl_outl(info->count >> calc_xmit_shift(info), DMATCR[info->chan]);
+	ctrl_outl(ctrl_inl(CHCR[info->chan])&~CHCR_TE, CHCR[info->chan]);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction irq_tei = {
+	.handler	= dma_tei,
+	.flags		= SA_INTERRUPT,
+	.name		= "dma_tei",
+};
+
+void setup_dma(unsigned int dmanr, struct dma_info_t *info)
+{
+	make_ipr_irq(DMTE_IRQ[info->chan], DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+	setup_irq(DMTE_IRQ[info->chan], &irq_tei);
+	dma_info[dmanr] = info;
+}
+
+unsigned long claim_dma_lock(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dma_spin_lock, flags);
+	return flags;
+}
+
+void release_dma_lock(unsigned long flags)
+{
+	spin_unlock_irqrestore(&dma_spin_lock, flags);
+}
+
+void enable_dma(unsigned int dmanr)
+{
+	struct dma_info_t *info = dma_info[dmanr];
+	unsigned long chcr;
+
+	chcr = ctrl_inl(CHCR[info->chan]);
+	chcr |= CHCR_DE;
+	ctrl_outl(chcr, CHCR[info->chan]);
+}
+
+void disable_dma(unsigned int dmanr)
+{
+	struct dma_info_t *info = dma_info[dmanr];
+	unsigned long chcr;
+
+	chcr = ctrl_inl(CHCR[info->chan]);
+	chcr &= ~CHCR_DE;
+	ctrl_outl(chcr, CHCR[info->chan]);
+}
+
+void set_dma_mode(unsigned int dmanr, char mode)
+{
+	struct dma_info_t *info = dma_info[dmanr];
+
+	info->mode = mode;
+	set_dma_addr(dmanr, info->mem_addr);
+	set_dma_count(dmanr, info->count);
+	autoinit_info[info->chan] = info;
+}
+
+void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+	struct dma_info_t *info = dma_info[dmanr];
+	unsigned long sar, dar;
+
+	info->mem_addr = a;
+	sar = (info->mode & DMA_MODE_WRITE)? info->mem_addr: info->dev_addr;
+	dar = (info->mode & DMA_MODE_WRITE)? info->dev_addr: info->mem_addr;
+	ctrl_outl(sar, SAR[info->chan]);
+	ctrl_outl(dar, DAR[info->chan]);
+}
+
+void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+	struct dma_info_t *info = dma_info[dmanr];
+	info->count = count;
+	ctrl_outl(count >> calc_xmit_shift(info), DMATCR[info->chan]);
+}
+
+int get_dma_residue(unsigned int dmanr)
+{
+	struct dma_info_t *info = dma_info[dmanr];
+	return (ctrl_inl(DMATCR[info->chan]) << calc_xmit_shift(info));
+}
+
+#if defined(CONFIG_CPU_SH4)
+static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs)
+{
+	printk(KERN_WARNING "DMAE: DMAOR=%x\n",ctrl_inl(DMAOR));
+	ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR);
+	ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR);
+	ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction irq_err = {
+	.handler	= dma_err,
+	.flags		= SA_INTERRUPT,
+	.name		= "dma_err",
+};
+#endif
+
+int __init init_dma(void)
+{
+#if defined(CONFIG_CPU_SH4)
+	make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+	setup_irq(DMAE_IRQ, &irq_err);
+#endif
+
+	ctrl_outl(DMAOR_DME, DMAOR);
+	return 0;
+}
+
+static void __exit exit_dma(void)
+{
+#ifdef CONFIG_CPU_SH4
+	free_irq(DMAE_IRQ, 0);
+#endif
+}
+
+module_init(init_dma);
+module_exit(exit_dma);
+
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(setup_dma);
+EXPORT_SYMBOL(claim_dma_lock);
+EXPORT_SYMBOL(release_dma_lock);
+EXPORT_SYMBOL(enable_dma);
+EXPORT_SYMBOL(disable_dma);
+EXPORT_SYMBOL(set_dma_mode);
+EXPORT_SYMBOL(set_dma_addr);
+EXPORT_SYMBOL(set_dma_count);
+EXPORT_SYMBOL(get_dma_residue);
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/irq_imask.c linux-2.5.73-bk10/arch/sh/kernel/cpu/irq_imask.c
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/irq_imask.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/irq_imask.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,116 @@
+/* $Id: irq_imask.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $
+ *
+ * linux/arch/sh/kernel/irq_imask.c
+ *
+ * Copyright (C) 1999, 2000  Niibe Yutaka
+ *
+ * Simple interrupt handling using IMASK of SR register.
+ *
+ */
+
+/* NOTE: Will not work on level 15 */
+
+
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+#include <linux/irq.h>
+
+/* Bitmap of IRQ masked */
+static unsigned long imask_mask = 0x7fff;
+static int interrupt_priority = 0;
+
+static void enable_imask_irq(unsigned int irq);
+static void disable_imask_irq(unsigned int irq);
+static void shutdown_imask_irq(unsigned int irq);
+static void mask_and_ack_imask(unsigned int);
+static void end_imask_irq(unsigned int irq);
+
+#define IMASK_PRIORITY	15
+
+static unsigned int startup_imask_irq(unsigned int irq)
+{ 
+	/* Nothing to do */
+	return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type imask_irq_type = {
+	"SR.IMASK",
+	startup_imask_irq,
+	shutdown_imask_irq,
+	enable_imask_irq,
+	disable_imask_irq,
+	mask_and_ack_imask,
+	end_imask_irq
+};
+
+void static inline set_interrupt_registers(int ip)
+{
+	unsigned long __dummy;
+
+	asm volatile("ldc	%2, r6_bank\n\t"
+		     "stc	sr, %0\n\t"
+		     "and	#0xf0, %0\n\t"
+		     "shlr2	%0\n\t"
+		     "cmp/eq	#0x3c, %0\n\t"
+		     "bt/s	1f	! CLI-ed\n\t"
+		     " stc	sr, %0\n\t"
+		     "and	%1, %0\n\t"
+		     "or	%2, %0\n\t"
+		     "ldc	%0, sr\n"
+		     "1:"
+		     : "=&z" (__dummy)
+		     : "r" (~0xf0), "r" (ip << 4)
+		     : "t");
+}
+
+static void disable_imask_irq(unsigned int irq)
+{
+	clear_bit(irq, &imask_mask);
+	if (interrupt_priority < IMASK_PRIORITY - irq)
+		interrupt_priority = IMASK_PRIORITY - irq;
+
+	set_interrupt_registers(interrupt_priority);
+}
+
+static void enable_imask_irq(unsigned int irq)
+{
+	set_bit(irq, &imask_mask);
+	interrupt_priority = IMASK_PRIORITY - ffz(imask_mask);
+
+	set_interrupt_registers(interrupt_priority);
+}
+
+static void mask_and_ack_imask(unsigned int irq)
+{
+	disable_imask_irq(irq);
+}
+
+static void end_imask_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_imask_irq(irq);
+}
+
+static void shutdown_imask_irq(unsigned int irq)
+{
+	/* Nothing to do */
+}
+
+void make_imask_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+	irq_desc[irq].handler = &imask_irq_type;
+	enable_irq(irq);
+}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/irq_ipr.c linux-2.5.73-bk10/arch/sh/kernel/cpu/irq_ipr.c
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/irq_ipr.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/irq_ipr.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,309 @@
+/* $Id: irq_ipr.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $
+ *
+ * linux/arch/sh/kernel/irq_ipr.c
+ *
+ * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Interrupt handling for IPR-based IRQ.
+ *
+ * Supported system:
+ *	On-chip supporting modules (TMU, RTC, etc.).
+ *	On-chip supporting modules for SH7709/SH7709A/SH7729.
+ *	Hitachi SolutionEngine external I/O:
+ *		MS7709SE01, MS7709ASE01, and MS7750SE01
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/machvec.h>
+
+struct ipr_data {
+	unsigned int addr;	/* Address of Interrupt Priority Register */
+	int shift;		/* Shifts of the 16-bit data */
+	int priority;		/* The priority */
+};
+static struct ipr_data ipr_data[NR_IRQS];
+
+static void enable_ipr_irq(unsigned int irq);
+static void disable_ipr_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_ipr_irq disable_ipr_irq
+
+static void mask_and_ack_ipr(unsigned int);
+static void end_ipr_irq(unsigned int irq);
+
+static unsigned int startup_ipr_irq(unsigned int irq)
+{ 
+	enable_ipr_irq(irq);
+	return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type ipr_irq_type = {
+	"IPR-IRQ",
+	startup_ipr_irq,
+	shutdown_ipr_irq,
+	enable_ipr_irq,
+	disable_ipr_irq,
+	mask_and_ack_ipr,
+	end_ipr_irq
+};
+
+static void disable_ipr_irq(unsigned int irq)
+{
+	unsigned long val, flags;
+	unsigned int addr = ipr_data[irq].addr;
+	unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift);
+
+	/* Set the priority in IPR to 0 */
+	local_irq_save(flags);
+	val = ctrl_inw(addr);
+	val &= mask;
+	ctrl_outw(val, addr);
+	local_irq_restore(flags);
+}
+
+static void enable_ipr_irq(unsigned int irq)
+{
+	unsigned long val, flags;
+	unsigned int addr = ipr_data[irq].addr;
+	int priority = ipr_data[irq].priority;
+	unsigned short value = (priority << ipr_data[irq].shift);
+
+	/* Set priority in IPR back to original value */
+	local_irq_save(flags);
+	val = ctrl_inw(addr);
+	val |= value;
+	ctrl_outw(val, addr);
+	local_irq_restore(flags);
+}
+
+static void mask_and_ack_ipr(unsigned int irq)
+{
+	disable_ipr_irq(irq);
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+	/* This is needed when we use edge triggered setting */
+	/* XXX: Is it really needed? */
+	if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) {
+		/* Clear external interrupt request */
+		int a = ctrl_inb(INTC_IRR0);
+		a &= ~(1 << (irq - IRQ0_IRQ));
+		ctrl_outb(a, INTC_IRR0);
+	}
+#endif
+}
+
+static void end_ipr_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_ipr_irq(irq);
+}
+
+void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
+{
+	disable_irq_nosync(irq);
+	ipr_data[irq].addr = addr;
+	ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
+	ipr_data[irq].priority = priority;
+
+	irq_desc[irq].handler = &ipr_irq_type;
+	disable_ipr_irq(irq);
+}
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+static unsigned char pint_map[256];
+static unsigned long portcr_mask = 0;
+
+static void enable_pint_irq(unsigned int irq);
+static void disable_pint_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_pint_irq disable_pint_irq
+
+static void mask_and_ack_pint(unsigned int);
+static void end_pint_irq(unsigned int irq);
+
+static unsigned int startup_pint_irq(unsigned int irq)
+{ 
+	enable_pint_irq(irq);
+	return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type pint_irq_type = {
+	"PINT-IRQ",
+	startup_pint_irq,
+	shutdown_pint_irq,
+	enable_pint_irq,
+	disable_pint_irq,
+	mask_and_ack_pint,
+	end_pint_irq
+};
+
+static void disable_pint_irq(unsigned int irq)
+{
+	unsigned long val, flags;
+
+	local_irq_save(flags);
+	val = ctrl_inw(INTC_INTER);
+	val &= ~(1 << (irq - PINT_IRQ_BASE));
+	ctrl_outw(val, INTC_INTER);	/* disable PINTn */
+	portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2);
+	local_irq_restore(flags);
+}
+
+static void enable_pint_irq(unsigned int irq)
+{
+	unsigned long val, flags;
+
+	local_irq_save(flags);
+	val = ctrl_inw(INTC_INTER);
+	val |= 1 << (irq - PINT_IRQ_BASE);
+	ctrl_outw(val, INTC_INTER);	/* enable PINTn */
+	portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2;
+	local_irq_restore(flags);
+}
+
+static void mask_and_ack_pint(unsigned int irq)
+{
+	disable_pint_irq(irq);
+}
+
+static void end_pint_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_pint_irq(irq);
+}
+
+void make_pint_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+	irq_desc[irq].handler = &pint_irq_type;
+	disable_pint_irq(irq);
+}
+#endif
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+	int i;
+#endif
+
+	make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
+	make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
+
+#ifdef SCI_ERI_IRQ
+	make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+	make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+	make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+#endif
+
+#ifdef SCIF1_ERI_IRQ
+	make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+	make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+	make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+	make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+#endif
+
+#ifdef SCIF_ERI_IRQ
+	make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+	make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+	make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+	make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+#endif
+
+#ifdef IRDA_ERI_IRQ
+	make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+	make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+	make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+	make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+	/*
+	 * Initialize the Interrupt Controller (INTC)
+	 * registers to their power on values
+	 */ 
+
+	/*
+	 * Enable external irq (INTC IRQ mode).
+	 * You should set corresponding bits of PFC to "00"
+	 * to enable these interrupts.
+	 */
+	make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY);
+	make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
+	make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
+	make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY);
+	make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY);
+	make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY);
+	make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY);
+	make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY);
+	enable_ipr_irq(PINT0_IRQ);
+	enable_ipr_irq(PINT8_IRQ);
+
+	for(i = 0; i < 16; i++)
+		make_pint_irq(PINT_IRQ_BASE + i);
+	for(i = 0; i < 256; i++)
+	{
+		if(i & 1) pint_map[i] = 0;
+		else if(i & 2) pint_map[i] = 1;
+		else if(i & 4) pint_map[i] = 2;
+		else if(i & 8) pint_map[i] = 3;
+		else if(i & 0x10) pint_map[i] = 4;
+		else if(i & 0x20) pint_map[i] = 5;
+		else if(i & 0x40) pint_map[i] = 6;
+		else if(i & 0x80) pint_map[i] = 7;
+	}
+#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */
+
+	/* Perform the machine specific initialisation */
+	if (sh_mv.mv_init_irq != NULL) {
+		sh_mv.mv_init_irq();
+	}
+}
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+int ipr_irq_demux(int irq)
+{
+	unsigned long creg, dreg, d, sav;
+
+	if(irq == PINT0_IRQ)
+	{
+#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+		creg = PORT_PACR;
+		dreg = PORT_PADR;
+#else
+		creg = PORT_PCCR;
+		dreg = PORT_PCDR;
+#endif
+		sav = ctrl_inw(creg);
+		ctrl_outw(sav | portcr_mask, creg);
+		d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & ctrl_inw(INTC_INTER) & 0xff;
+		ctrl_outw(sav, creg);
+		if(d == 0) return irq;
+		return PINT_IRQ_BASE + pint_map[d];
+	}
+	else if(irq == PINT8_IRQ)
+	{
+#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+		creg = PORT_PBCR;
+		dreg = PORT_PBDR;
+#else
+		creg = PORT_PFCR;
+		dreg = PORT_PFDR;
+#endif
+		sav = ctrl_inw(creg);
+		ctrl_outw(sav | (portcr_mask >> 16), creg);
+		d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & (ctrl_inw(INTC_INTER) >> 8) & 0xff;
+		ctrl_outw(sav, creg);
+		if(d == 0) return irq;
+		return PINT_IRQ_BASE + 8 + pint_map[d];
+	}
+	return irq;
+}
+#endif
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/rtc.c linux-2.5.73-bk10/arch/sh/kernel/cpu/rtc.c
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/rtc.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/rtc.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,135 @@
+/*
+ * linux/arch/sh/kernel/rtc.c -- SH3 / SH4 on-chip RTC support
+ *
+ *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
+ *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/io.h>
+#include <asm/rtc.h>
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+void sh_rtc_gettimeofday(struct timespec *ts)
+{
+	unsigned int sec128, sec, min, hr, wk, day, mon, yr, yr100;
+
+ again:
+	do {
+		ctrl_outb(0, RCR1);  /* Clear CF-bit */
+		sec128 = ctrl_inb(R64CNT);
+		sec = ctrl_inb(RSECCNT);
+		min = ctrl_inb(RMINCNT);
+		hr  = ctrl_inb(RHRCNT);
+		wk  = ctrl_inb(RWKCNT);
+		day = ctrl_inb(RDAYCNT);
+		mon = ctrl_inb(RMONCNT);
+#if defined(CONFIG_CPU_SH4)
+		yr  = ctrl_inw(RYRCNT);
+		yr100 = (yr >> 8);
+		yr &= 0xff;
+#else
+		yr  = ctrl_inb(RYRCNT);
+		yr100 = (yr == 0x99) ? 0x19 : 0x20;
+#endif
+	} while ((ctrl_inb(RCR1) & RCR1_CF) != 0);
+
+#if RTC_BIT_INVERTED != 0
+	/* Work around to avoid reading incorrect value. */
+	if (sec128 == RTC_BIT_INVERTED) {
+		schedule_timeout(1);
+		goto again;
+	}
+#endif
+
+	BCD_TO_BIN(yr100);
+	BCD_TO_BIN(yr);
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(hr);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(sec);
+
+	if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
+	    hr > 23 || min > 59 || sec > 59) {
+		printk(KERN_ERR
+		       "SH RTC: invalid value, resetting to 1 Jan 2000\n");
+		ctrl_outb(RCR2_RESET, RCR2);  /* Reset & Stop */
+		ctrl_outb(0, RSECCNT);
+		ctrl_outb(0, RMINCNT);
+		ctrl_outb(0, RHRCNT);
+		ctrl_outb(6, RWKCNT);
+		ctrl_outb(1, RDAYCNT);
+		ctrl_outb(1, RMONCNT);
+#if defined(CONFIG_CPU_SH4)
+		ctrl_outw(0x2000, RYRCNT);
+#else
+		ctrl_outb(0, RYRCNT);
+#endif
+		ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2);  /* Start */
+		goto again;
+	}
+
+#if RTC_BIT_INVERTED != 0
+	if ((sec128 & RTC_BIT_INVERTED))
+		sec--;
+#endif
+
+	ts->tv_sec = mktime(yr100 * 100 + yr, mon, day, hr, min, sec);
+	ts->tv_nsec = ((sec128 * 1000000) / 128) * 1000;
+}
+
+/*
+ * Changed to only care about tv_sec, and not the full timespec struct
+ * (i.e. tv_nsec).  It can easily be switched to timespec for future cpus
+ * that support setting usec or nsec RTC values.
+ */
+int sh_rtc_settimeofday(const time_t secs)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+
+	ctrl_outb(RCR2_RESET, RCR2);  /* Reset pre-scaler & stop RTC */
+
+	cmos_minutes = ctrl_inb(RMINCNT);
+	BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = secs % 60;
+	real_minutes = secs / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;	/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		BIN_TO_BCD(real_seconds);
+		BIN_TO_BCD(real_minutes);
+		ctrl_outb(real_seconds, RSECCNT);
+		ctrl_outb(real_minutes, RMINCNT);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_time: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+		retval = -1;
+	}
+
+	ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2);  /* Start RTC */
+
+	return retval;
+}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/sh2/Makefile linux-2.5.73-bk10/arch/sh/kernel/cpu/sh2/Makefile
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/sh2/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/sh2/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,4 @@
+#
+# Makefile for the Linux/SuperH SH-2 backends.
+#
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/sh3/Makefile linux-2.5.73-bk10/arch/sh/kernel/cpu/sh3/Makefile
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/sh3/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/sh3/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,4 @@
+#
+# Makefile for the Linux/SuperH SH-3 backends.
+#
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/Makefile linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/Makefile
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,14 @@
+#
+# Makefile for the Linux/SuperH SH-4 backends.
+#
+
+obj-y	:= fpu.o
+
+obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)	+= irq_intc2.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751)	+= irq_intc2.o
+
+ifeq ($(CONFIG_PCI),y)
+obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)	+= pci-st40.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751)	+= pci-sh7751.o 
+endif
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/fpu.c linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/fpu.c
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/fpu.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/fpu.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,314 @@
+/* $Id: fpu.c,v 1.2 2003/05/04 19:29:54 lethal Exp $
+ *
+ * linux/arch/sh/kernel/fpu.c
+ *
+ * Save/restore floating point context for signal handlers.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
+ *
+ * FIXME! These routines can be optimized in big endian case.
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+/*
+ * Save FPU registers onto task structure.
+ * Assume called with FPU enabled (SR.FD=0).
+ */
+void
+save_fpu(struct task_struct *tsk)
+{
+	asm volatile("sts.l	fpul, @-%0\n\t"
+		     "sts.l	fpscr, @-%0\n\t"
+		     "lds	%1, fpscr\n\t"
+		     "frchg\n\t"
+		     "fmov.s	fr15, @-%0\n\t"
+		     "fmov.s	fr14, @-%0\n\t"
+		     "fmov.s	fr13, @-%0\n\t"
+		     "fmov.s	fr12, @-%0\n\t"
+		     "fmov.s	fr11, @-%0\n\t"
+		     "fmov.s	fr10, @-%0\n\t"
+		     "fmov.s	fr9, @-%0\n\t"
+		     "fmov.s	fr8, @-%0\n\t"
+		     "fmov.s	fr7, @-%0\n\t"
+		     "fmov.s	fr6, @-%0\n\t"
+		     "fmov.s	fr5, @-%0\n\t"
+		     "fmov.s	fr4, @-%0\n\t"
+		     "fmov.s	fr3, @-%0\n\t"
+		     "fmov.s	fr2, @-%0\n\t"
+		     "fmov.s	fr1, @-%0\n\t"
+		     "fmov.s	fr0, @-%0\n\t"
+		     "frchg\n\t"
+		     "fmov.s	fr15, @-%0\n\t"
+		     "fmov.s	fr14, @-%0\n\t"
+		     "fmov.s	fr13, @-%0\n\t"
+		     "fmov.s	fr12, @-%0\n\t"
+		     "fmov.s	fr11, @-%0\n\t"
+		     "fmov.s	fr10, @-%0\n\t"
+		     "fmov.s	fr9, @-%0\n\t"
+		     "fmov.s	fr8, @-%0\n\t"
+		     "fmov.s	fr7, @-%0\n\t"
+		     "fmov.s	fr6, @-%0\n\t"
+		     "fmov.s	fr5, @-%0\n\t"
+		     "fmov.s	fr4, @-%0\n\t"
+		     "fmov.s	fr3, @-%0\n\t"
+		     "fmov.s	fr2, @-%0\n\t"
+		     "fmov.s	fr1, @-%0\n\t"
+		     "fmov.s	fr0, @-%0"
+		     : /* no output */
+		     : "r" ((char *)(&tsk->thread.fpu.hard.status)),
+		       "r" (FPSCR_INIT)
+		     : "memory");
+
+	clear_tsk_thread_flag(tsk, TIF_USEDFPU);
+	release_fpu();
+}
+
+static void
+restore_fpu(struct task_struct *tsk)
+{
+	asm volatile("lds	%1, fpscr\n\t"
+		     "fmov.s	@%0+, fr0\n\t"
+		     "fmov.s	@%0+, fr1\n\t"
+		     "fmov.s	@%0+, fr2\n\t"
+		     "fmov.s	@%0+, fr3\n\t"
+		     "fmov.s	@%0+, fr4\n\t"
+		     "fmov.s	@%0+, fr5\n\t"
+		     "fmov.s	@%0+, fr6\n\t"
+		     "fmov.s	@%0+, fr7\n\t"
+		     "fmov.s	@%0+, fr8\n\t"
+		     "fmov.s	@%0+, fr9\n\t"
+		     "fmov.s	@%0+, fr10\n\t"
+		     "fmov.s	@%0+, fr11\n\t"
+		     "fmov.s	@%0+, fr12\n\t"
+		     "fmov.s	@%0+, fr13\n\t"
+		     "fmov.s	@%0+, fr14\n\t"
+		     "fmov.s	@%0+, fr15\n\t"
+		     "frchg\n\t"
+		     "fmov.s	@%0+, fr0\n\t"
+		     "fmov.s	@%0+, fr1\n\t"
+		     "fmov.s	@%0+, fr2\n\t"
+		     "fmov.s	@%0+, fr3\n\t"
+		     "fmov.s	@%0+, fr4\n\t"
+		     "fmov.s	@%0+, fr5\n\t"
+		     "fmov.s	@%0+, fr6\n\t"
+		     "fmov.s	@%0+, fr7\n\t"
+		     "fmov.s	@%0+, fr8\n\t"
+		     "fmov.s	@%0+, fr9\n\t"
+		     "fmov.s	@%0+, fr10\n\t"
+		     "fmov.s	@%0+, fr11\n\t"
+		     "fmov.s	@%0+, fr12\n\t"
+		     "fmov.s	@%0+, fr13\n\t"
+		     "fmov.s	@%0+, fr14\n\t"
+		     "fmov.s	@%0+, fr15\n\t"
+		     "frchg\n\t"
+		     "lds.l	@%0+, fpscr\n\t"
+		     "lds.l	@%0+, fpul\n\t"
+		     : /* no output */
+		     : "r" (&tsk->thread.fpu), "r" (FPSCR_INIT)
+		     : "memory");
+}
+
+/*
+ * Load the FPU with signalling NANS.  This bit pattern we're using
+ * has the property that no matter wether considered as single or as
+ * double precission represents signaling NANS.  
+ */
+
+static void
+fpu_init(void)
+{
+	asm volatile("lds	%0, fpul\n\t"
+		     "lds	%1, fpscr\n\t"
+		     "fsts	fpul, fr0\n\t"
+		     "fsts	fpul, fr1\n\t"
+		     "fsts	fpul, fr2\n\t"
+		     "fsts	fpul, fr3\n\t"
+		     "fsts	fpul, fr4\n\t"
+		     "fsts	fpul, fr5\n\t"
+		     "fsts	fpul, fr6\n\t"
+		     "fsts	fpul, fr7\n\t"
+		     "fsts	fpul, fr8\n\t"
+		     "fsts	fpul, fr9\n\t"
+		     "fsts	fpul, fr10\n\t"
+		     "fsts	fpul, fr11\n\t"
+		     "fsts	fpul, fr12\n\t"
+		     "fsts	fpul, fr13\n\t"
+		     "fsts	fpul, fr14\n\t"
+		     "fsts	fpul, fr15\n\t"
+		     "frchg\n\t"
+		     "fsts	fpul, fr0\n\t"
+		     "fsts	fpul, fr1\n\t"
+		     "fsts	fpul, fr2\n\t"
+		     "fsts	fpul, fr3\n\t"
+		     "fsts	fpul, fr4\n\t"
+		     "fsts	fpul, fr5\n\t"
+		     "fsts	fpul, fr6\n\t"
+		     "fsts	fpul, fr7\n\t"
+		     "fsts	fpul, fr8\n\t"
+		     "fsts	fpul, fr9\n\t"
+		     "fsts	fpul, fr10\n\t"
+		     "fsts	fpul, fr11\n\t"
+		     "fsts	fpul, fr12\n\t"
+		     "fsts	fpul, fr13\n\t"
+		     "fsts	fpul, fr14\n\t"
+		     "fsts	fpul, fr15\n\t"
+		     "frchg"
+		     : /* no output */
+		     : "r" (0), "r" (FPSCR_INIT));
+}
+
+/**
+ *	denormal_to_double - Given denormalized float number,
+ *	                     store double float
+ *
+ *	@fpu: Pointer to sh_fpu_hard structure
+ *	@n: Index to FP register
+ */
+static void
+denormal_to_double (struct sh_fpu_hard_struct *fpu, int n)
+{
+	unsigned long du, dl;
+	unsigned long x = fpu->fpul;
+	int exp = 1023 - 126;
+
+	if (x != 0 && (x & 0x7f800000) == 0) {
+		du = (x & 0x80000000);
+		while ((x & 0x00800000) == 0) {
+			x <<= 1;
+			exp--;
+		}
+		x &= 0x007fffff;
+		du |= (exp << 20) | (x >> 3);
+		dl = x << 29;
+
+		fpu->fp_regs[n] = du;
+		fpu->fp_regs[n+1] = dl;
+	}
+}
+
+/**
+ *	ieee_fpe_handler - Handle denormalized number exception
+ *
+ *	@regs: Pointer to register structure
+ *
+ *	Returns 1 when it's handled (should not cause exception).
+ */
+static int
+ieee_fpe_handler (struct pt_regs *regs)
+{
+	unsigned short insn = *(unsigned short *) regs->pc;
+	unsigned short finsn;
+	unsigned long nextpc;
+	int nib[4] = {
+		(insn >> 12) & 0xf,
+		(insn >> 8) & 0xf,
+		(insn >> 4) & 0xf,
+		insn & 0xf};
+
+	if (nib[0] == 0xb ||
+	    (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */
+		regs->pr = regs->pc + 4;
+  
+	if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */
+		nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3);
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */
+		if (regs->sr & 1)
+			nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+		else
+			nextpc = regs->pc + 4;
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */
+		if (regs->sr & 1)
+			nextpc = regs->pc + 4;
+		else
+			nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (nib[0] == 0x4 && nib[3] == 0xb &&
+		 (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */
+		nextpc = regs->regs[nib[1]];
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (nib[0] == 0x0 && nib[3] == 0x3 &&
+		 (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */
+		nextpc = regs->pc + 4 + regs->regs[nib[1]];
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (insn == 0x000b) { /* rts */
+		nextpc = regs->pr;
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else {
+		nextpc = regs->pc + 2;
+		finsn = insn;
+	}
+
+	if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
+		struct task_struct *tsk = current;
+
+		save_fpu(tsk);
+		if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) {
+			/* FPU error */
+			denormal_to_double (&tsk->thread.fpu.hard,
+					    (finsn >> 8) & 0xf);
+			tsk->thread.fpu.hard.fpscr &=
+				~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
+			grab_fpu();
+			restore_fpu(tsk);
+			set_tsk_thread_flag(tsk, TIF_USEDFPU);
+		} else {
+			tsk->thread.trap_no = 11;
+			tsk->thread.error_code = 0;
+			force_sig(SIGFPE, tsk);
+		}
+
+		regs->pc = nextpc;
+		return 1;
+	}
+
+	return 0;
+}
+
+asmlinkage void
+do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7,
+	     struct pt_regs regs)
+{
+	struct task_struct *tsk = current;
+
+	if (ieee_fpe_handler (&regs))
+		return;
+
+	regs.pc += 2;
+	save_fpu(tsk);
+	tsk->thread.trap_no = 11;
+	tsk->thread.error_code = 0;
+	force_sig(SIGFPE, tsk);
+}
+
+asmlinkage void
+do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
+		     unsigned long r7, struct pt_regs regs)
+{
+	struct task_struct *tsk = current;
+
+	grab_fpu();
+	if (!user_mode(&regs)) {
+		printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
+		return;
+	}
+
+	if (tsk->used_math) {
+		/* Using the FPU again.  */
+		restore_fpu(tsk);
+	} else	{
+		/* First time FPU user.  */
+		fpu_init();
+		tsk->used_math = 1;
+	}
+	set_tsk_thread_flag(tsk, TIF_USEDFPU);
+}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/irq_intc2.c linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/irq_intc2.c
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/irq_intc2.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/irq_intc2.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,127 @@
+/*
+ * linux/arch/sh/kernel/irq_intc2.c
+ *
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Interrupt handling for INTC2-based IRQ.
+ *
+ * These are the "new Hitachi style" interrupts, as present on the 
+ * Hitachi 7751 and the STM ST40 STB1.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/machvec.h>
+
+
+struct intc2_data {
+	unsigned int addr;	/* Address of Interrupt Priority Register */
+	int mask; /*Mask to apply */
+};
+
+
+static struct intc2_data intc2_data[NR_INTC2_IRQS];
+
+static void enable_intc2_irq(unsigned int irq);
+static void disable_intc2_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_intc2_irq disable_intc2_irq
+
+static void mask_and_ack_intc2(unsigned int);
+static void end_intc2_irq(unsigned int irq);
+
+static unsigned int startup_intc2_irq(unsigned int irq)
+{ 
+	enable_intc2_irq(irq);
+	return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type intc2_irq_type = {
+	"INTC2-IRQ",
+	startup_intc2_irq,
+	shutdown_intc2_irq,
+	enable_intc2_irq,
+	disable_intc2_irq,
+	mask_and_ack_intc2,
+	end_intc2_irq
+};
+
+static void disable_intc2_irq(unsigned int irq)
+{
+	unsigned addr;
+	int offset=irq-INTC2_FIRST_IRQ;
+	unsigned val,flags;
+
+	// Sanity check
+	if(offset<0 || offset>=NR_INTC2_IRQS) return;
+
+	addr=intc2_data[offset].addr+INTC2_INTMSK_OFFSET;
+
+	local_irq_save(flags);
+	val=ctrl_inl(addr);
+	val|=intc2_data[offset].mask;
+	ctrl_outl(val,addr);
+
+	local_irq_restore(flags);
+}
+
+static void enable_intc2_irq(unsigned int irq)
+{
+	int offset=irq-INTC2_FIRST_IRQ;
+
+	// Sanity check
+	if(offset<0 || offset>=NR_INTC2_IRQS) return;
+
+	ctrl_outl(intc2_data[offset].mask,
+		  intc2_data[offset].addr+INTC2_INTMSKCLR_OFFSET);
+
+}
+
+static void mask_and_ack_intc2(unsigned int irq)
+{
+	disable_intc2_irq(irq);
+}
+
+static void end_intc2_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_intc2_irq(irq);
+}
+
+void make_intc2_irq(unsigned int irq, unsigned int addr, 
+		    unsigned int group,int pos, int priority)
+{
+	int offset=irq-INTC2_FIRST_IRQ;
+	unsigned flags,val;
+
+	if(offset<0 || offset>=NR_INTC2_IRQS) {
+		return;
+	}
+
+	disable_irq_nosync(irq);
+	/* Fill the data we need */
+	intc2_data[offset].addr=addr;
+	intc2_data[offset].mask=1<<pos;
+		
+	/* Set the priority level */
+	local_irq_save(flags);
+	val=ctrl_inl(addr+INTC2_INTPRI_OFFSET);
+	val|=(priority)<< (group<<4);
+	ctrl_outl(val,addr+INTC2_INTPRI_OFFSET);
+	local_irq_restore(flags);
+
+	irq_desc[irq].handler=&intc2_irq_type;
+
+	disable_intc2_irq(irq);
+}
+
+
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/pci-sh7751.c linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/pci-sh7751.c
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/pci-sh7751.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/pci-sh7751.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,503 @@
+/*
+ *	Low-Level PCI Support for the SH7751
+ *
+ *  Dustin McIntire (dustin@sensoria.com)
+ *	Derived from arch/i386/kernel/pci-*.c which bore the message:
+ *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *	
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/pci-sh7751.h>
+
+struct pci_ops *pci_check_direct(void);
+void pcibios_resource_survey(void);
+static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin);
+static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin);
+
+unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1;
+int pcibios_last_bus = -1;
+struct pci_bus *pci_root_bus;
+struct pci_ops *pci_root_ops;
+
+/*
+ * Direct access to PCI hardware...
+ */
+
+#ifdef CONFIG_PCI_DIRECT
+
+
+#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+#define PCI_REG(reg) (SH7751_PCIREG_BASE+reg)
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+	unsigned long flags;
+	u32 word;
+
+	/* 
+	 * PCIPDR may only be accessed as 32 bit words, 
+	 * so we must do byte alignment by hand 
+	 */
+	local_irq_save(flags);
+	outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
+	word = inl(PCI_REG(SH7751_PCIPDR));
+	local_irq_restore(flags);
+
+	switch (size) {
+	case 1:
+		switch (where & 0x3) {
+		    	case 3: *value = (u8)(word >> 24); break;
+			case 2: *value = (u8)(word >> 16); break;
+			case 1: *value = (u8)(word >> 8);  break;
+		}
+		break;
+	case 2:
+		switch (where & 0x2) {
+			case 2:	*value = (u16)(word >> 16); break;
+			case 1: *value = (u16)(word >> 8);  break;
+		}
+		break;
+	case 4:
+		*value = word;
+		break;
+	}
+
+	PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value); 
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/* 
+ * Since SH7751 only does 32bit access we'll have to do a read,mask,write operation.  
+ * We'll allow an odd byte offset, though it should be illegal.
+ */ 
+static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+	u32 word,mask;
+	unsigned long flags;
+	u32 shift = (where & 3) * 8;
+
+	if(size == 1) {
+		mask = ((1 << 8) - 1) << shift;  // create the byte mask
+	} else if(size == 2){
+		if(shift == 24)
+			return PCIBIOS_BAD_REGISTER_NUMBER;           
+		mask = ((1 << 16) - 1) << shift;  // create the word mask
+	}
+
+	local_irq_save(flags);
+	outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
+
+	if(size == 4){
+		outl(value, PCI_REG(SH7751_PCIPDR));
+		local_irq_restore(flags);
+
+		PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value);
+
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	word = inl(PCI_REG(SH7751_PCIPDR)) ;
+	word &= ~mask;
+	word |= value << shift;
+	outl(word, PCI_REG(SH7751_PCIPDR));
+	local_irq_restore(flags);
+
+	PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+#undef CONFIG_CMD
+
+static struct pci_ops pci_direct_conf1 = {
+	.read =		pci_conf1_read,
+	.write = 	pci_conf1_write,
+};
+
+struct pci_ops * __init pci_check_direct(void)
+{
+	unsigned int tmp, id;
+
+	/* check for SH7751 hardware */
+	id = (SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID;
+	if(inl(SH7751_PCIREG_BASE+SH7751_PCICONF0) != id) {
+		PCIDBG(2,"PCI: This is not an SH7751\n");
+		return NULL;
+	}
+	/*
+	 * Check if configuration works.
+	 */
+	if (pci_probe & PCI_PROBE_CONF1) {
+		tmp = inl (PCI_REG(SH7751_PCIPAR));
+		outl (0x80000000, PCI_REG(SH7751_PCIPAR));
+		if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) {
+			outl (tmp, PCI_REG(SH7751_PCIPAR));
+			printk(KERN_INFO "PCI: Using configuration type 1\n");
+			request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1");
+			return &pci_direct_conf1;
+		}
+		outl (tmp, PCI_REG(SH7751_PCIPAR));
+	}
+
+	PCIDBG(2,"PCI: pci_check_direct failed\n");
+	return NULL;
+}
+
+#endif
+
+/*
+ * BIOS32 and PCI BIOS handling.
+ * 
+ * The BIOS version of the pci functions is not yet implemented but it is left
+ * in for completeness.  Currently an error will be generated at compile time. 
+ */
+ 
+#ifdef CONFIG_PCI_BIOS
+
+#error PCI BIOS is not yet supported on SH7751
+
+#endif /* CONFIG_PCI_BIOS */
+
+/***************************************************************************************/
+
+/*
+ *  Handle bus scanning and fixups ....
+ */
+
+
+/*
+ * Discover remaining PCI buses in case there are peer host bridges.
+ * We use the number of last PCI bus provided by the PCI BIOS.
+ */
+static void __init pcibios_fixup_peer_bridges(void)
+{
+	int n;
+	struct pci_bus bus;
+	struct pci_dev dev;
+	u16 l;
+
+	if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
+		return;
+	PCIDBG(2,"PCI: Peer bridge fixup\n");
+	for (n=0; n <= pcibios_last_bus; n++) {
+		if (pci_bus_exists(&pci_root_buses, n))
+			continue;
+		bus.number = n;
+		bus.ops = pci_root_ops;
+		dev.bus = &bus;
+		for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
+			if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
+			    l != 0x0000 && l != 0xffff) {
+				PCIDBG(3,"Found device at %02x:%02x [%04x]\n", n, dev.devfn, l);
+				printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
+				pci_scan_bus(n, pci_root_ops, NULL);
+				break;
+			}
+	}
+}
+
+
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+	int i;
+
+	/*
+	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
+	 */
+	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return;
+	PCIDBG(3,"PCI: IDE base address fixup for %s\n", d->slot_name);
+	for(i=0; i<4; i++) {
+		struct resource *r = &d->resource[i];
+		if ((r->start & ~0x80) == 0x374) {
+			r->start |= 2;
+			r->end = r->start;
+		}
+	}
+}
+
+
+/* Add future fixups here... */
+struct pci_fixup pcibios_fixups[] = {
+	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
+	{ 0 }
+};
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+	pci_read_bridge_bases(b);
+}
+
+/*
+ * Initialization. Try all known PCI access methods. Note that we support
+ * using both PCI BIOS and direct access: in such cases, we use I/O ports
+ * to access config space.
+ * 
+ * Note that the platform specific initialization (BSC registers, and memory
+ * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it
+ * exitst and via the platform defined function pcibios_init_platform().  
+ * See pci_bigsur.c for implementation;
+ * 
+ * The BIOS version of the pci functions is not yet implemented but it is left
+ * in for completeness.  Currently an error will be genereated at compile time. 
+ */
+
+void __init pcibios_init(void)
+{
+	struct pci_ops *bios = NULL;
+	struct pci_ops *dir = NULL;
+
+	PCIDBG(1,"PCI: Starting intialization.\n");
+#ifdef CONFIG_PCI_BIOS
+	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
+		pci_probe |= PCI_BIOS_SORT;
+		pci_bios_present = 1;
+	}
+#endif
+#ifdef CONFIG_PCI_DIRECT
+	if (pci_probe & PCI_PROBE_CONF1 )
+		dir = pci_check_direct();
+#endif
+	if (dir) {
+		pci_root_ops = dir;
+	    if(!pcibios_init_platform())
+			PCIDBG(1,"PCI: Initialization failed\n");
+	    if (sh_mv.mv_init_pci != NULL)
+            sh_mv.mv_init_pci();
+	}
+	else if (bios)
+		pci_root_ops = bios;
+	else {
+		PCIDBG(1,"PCI: No PCI bus detected\n");
+		return;
+	}
+
+	PCIDBG(1,"PCI: Probing PCI hardware\n");
+	pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
+	//pci_assign_unassigned_resources();
+	pci_fixup_irqs(pcibios_swizzle, pcibios_lookup_irq);
+	pcibios_fixup_peer_bridges();
+	pcibios_resource_survey();
+
+#ifdef CONFIG_PCI_BIOS
+	if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
+		pcibios_sort();
+#endif
+}
+
+char * __init pcibios_setup(char *str)
+{
+	if (!strcmp(str, "off")) {
+		pci_probe = 0;
+		return NULL;
+	}
+#ifdef CONFIG_PCI_BIOS
+	else if (!strcmp(str, "bios")) {
+		pci_probe = PCI_PROBE_BIOS;
+		return NULL;
+	} else if (!strcmp(str, "nobios")) {
+		pci_probe &= ~PCI_PROBE_BIOS;
+		return NULL;
+	} else if (!strcmp(str, "nosort")) {
+		pci_probe |= PCI_NO_SORT;
+		return NULL;
+	} else if (!strcmp(str, "biosirq")) {
+		pci_probe |= PCI_BIOS_IRQ_SCAN;
+		return NULL;
+	}
+#endif
+#ifdef CONFIG_PCI_DIRECT
+	else if (!strcmp(str, "conf1")) {
+		pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS;
+		return NULL;
+	}
+#endif
+	else if (!strcmp(str, "rom")) {
+		pci_probe |= PCI_ASSIGN_ROMS;
+		return NULL;
+	} else if (!strncmp(str, "lastbus=", 8)) {
+		pcibios_last_bus = simple_strtol(str+8, NULL, 0);
+		return NULL;
+	}
+	return str;
+}
+
+/*
+ *    Allocate the bridge and device resources
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+	struct list_head *ln;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
+	int idx;
+	struct resource *r, *pr;
+	
+	PCIDBG(2,"PCI: pcibios_allocate_bus_reasources called\n" );
+	/* Depth-First Search on bus tree */
+	for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+		bus = pci_bus_b(ln);
+		if ((dev = bus->self)) {
+			for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+				r = &dev->resource[idx];
+				if (!r->start)
+					continue;
+				pr = pci_find_parent_resource(dev, r);
+				if (!pr || request_resource(pr, r) < 0)
+					printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
+			}
+		}
+		pcibios_allocate_bus_resources(&bus->children);
+	}
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+	struct pci_dev *dev;
+	int idx, disabled;
+	u16 command;
+	struct resource *r, *pr;
+
+	PCIDBG(2,"PCI: pcibios_allocate_resources pass %d called\n", pass);
+	pci_for_each_dev(dev) {
+		pci_read_config_word(dev, PCI_COMMAND, &command);
+		for(idx = 0; idx < 6; idx++) {
+			r = &dev->resource[idx];
+			if (r->parent)		/* Already allocated */
+				continue;
+			if (!r->start)		/* Address not assigned at all */
+				continue;
+			if (r->flags & IORESOURCE_IO)
+				disabled = !(command & PCI_COMMAND_IO);
+			else
+				disabled = !(command & PCI_COMMAND_MEMORY);
+			if (pass == disabled) {
+				PCIDBG(3,"PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
+				    r->start, r->end, r->flags, disabled, pass);
+				pr = pci_find_parent_resource(dev, r);
+				if (!pr || request_resource(pr, r) < 0) {
+					printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name);
+					/* We'll assign a new address later */
+					r->end -= r->start;
+					r->start = 0;
+				}
+			}
+		}
+		if (!pass) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
+				/* Turn the ROM off, leave the resource region, but keep it unregistered. */
+				u32 reg;
+				PCIDBG(3,"PCI: Switching off ROM of %s\n", dev->slot_name);
+				r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
+				pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+				pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+			}
+		}
+	}
+}
+
+static void __init pcibios_assign_resources(void)
+{
+	struct pci_dev *dev;
+	int idx;
+	struct resource *r;
+
+	PCIDBG(2,"PCI: pcibios_assign_resources called\n");
+	pci_for_each_dev(dev) {
+		int class = dev->class >> 8;
+
+		/* Don't touch classless devices and host bridges */
+		if (!class || class == PCI_CLASS_BRIDGE_HOST)
+			continue;
+
+		for(idx=0; idx<6; idx++) {
+			r = &dev->resource[idx];
+
+			/*
+			 *  Don't touch IDE controllers and I/O ports of video cards!
+			 */
+			if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
+			    (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
+				continue;
+
+			/*
+			 *  We shall assign a new address to this resource, either because
+			 *  the BIOS forgot to do so or because we have decided the old
+			 *  address was unusable for some reason.
+			 */
+			if (!r->start && r->end)
+				pci_assign_resource(dev, idx);
+		}
+
+		if (pci_probe & PCI_ASSIGN_ROMS) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			r->end -= r->start;
+			r->start = 0;
+			if (r->end)
+				pci_assign_resource(dev, PCI_ROM_RESOURCE);
+		}
+	}
+}
+
+void __init pcibios_resource_survey(void)
+{
+	PCIDBG(1,"PCI: Allocating resources\n");
+	pcibios_allocate_bus_resources(&pci_root_buses);
+	pcibios_allocate_resources(0);
+	pcibios_allocate_resources(1);
+	pcibios_assign_resources();
+}
+
+
+/***************************************************************************************/
+/* 
+ * 	IRQ functions 
+ */
+static u8 __init pcibios_swizzle(struct pci_dev *dev, u8 *pin)
+{
+	/* no swizzling */
+	return PCI_SLOT(dev->devfn);
+}
+
+static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq = -1;
+
+	/* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
+	irq = pcibios_map_platform_irq(slot,pin);
+	if( irq < 0 ) {
+	    PCIDBG(3,"PCI: Error mapping IRQ on device %s\n", dev->name);
+		return irq;
+	}
+	
+	PCIDBG(2,"Setting IRQ for slot %s to %d\n", dev->slot_name, irq);
+
+	return irq;
+}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/pci-st40.c linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/pci-st40.c
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/pci-st40.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/pci-st40.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,423 @@
+/* 
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Support functions for the ST40 PCI hardware.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <asm/pci.h>
+#include <linux/irq.h>
+
+#include "pci-st40.h"
+
+/* This is in P2 of course */
+#define ST40PCI_BASE_ADDRESS     (0xb0000000)
+#define ST40PCI_MEM_ADDRESS      (ST40PCI_BASE_ADDRESS+0x0)
+#define ST40PCI_IO_ADDRESS       (ST40PCI_BASE_ADDRESS+0x06000000)
+#define ST40PCI_REG_ADDRESS      (ST40PCI_BASE_ADDRESS+0x07000000)
+
+#define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x))
+
+#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg))
+#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg))
+#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg))
+
+#define ST40PCI_READ(reg) readl(ST40PCI_REG(reg))
+#define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg))
+#define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg))
+
+#define ST40PCI_SERR_IRQ        64
+#define ST40PCI_SERR_INT_GROUP  0
+#define ST40PCI_SERR_INT_POS    0
+#define ST40PCI_SERR_INT_PRI    15
+
+#define ST40PCI_ERR_IRQ        65
+#define ST40PCI_ERR_INT_GROUP   1
+#define ST40PCI_ERR_INT_POS     1
+#define ST40PCI_ERR_INT_PRI     14
+
+
+/* Macros to extract PLL params */
+#define PLL_MDIV(reg)  ( ((unsigned)reg) & 0xff )
+#define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff )
+#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 )
+#define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff )
+
+/* Build up the appropriate settings */
+#define PLL_SET(mdiv,ndiv,pdiv,setup) \
+( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19))
+
+#define PLLPCICR (0xbb040000+0x10)
+
+#define PLLPCICR_POWERON (1<<28)
+#define PLLPCICR_OUT_EN (1<<29)
+#define PLLPCICR_LOCKSELECT (1<<30)
+#define PLLPCICR_LOCK (1<<31)
+
+
+#define PLL_25MHZ 0x793c8512
+#define PLL_33MHZ PLL_SET(18,88,3,295)
+
+
+static __init void SetPCIPLL(void)
+{
+	/* Stop the PLL */
+	writel(0, PLLPCICR);
+
+	/* Always run at 33Mhz. The PCI clock is totally async 
+	 * to the rest of the system
+	 */
+	writel(PLL_33MHZ | PLLPCICR_POWERON, PLLPCICR);
+
+	printk("ST40PCI: Waiting for PCI PLL to lock\n");
+	while ((readl(PLLPCICR) & PLLPCICR_LOCK) == 0);
+	writel(readl(PLLPCICR) | PLLPCICR_OUT_EN, PLLPCICR);
+}
+
+
+static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs)
+{
+
+	unsigned pci_int, pci_air, pci_cir, pci_aint;
+
+	pci_int = ST40PCI_READ(INT);
+	pci_cir = ST40PCI_READ(CIR);
+	pci_air = ST40PCI_READ(AIR);
+
+	if (pci_int) {
+		printk("PCI INTERRUPT!\n");
+		printk("PCI INT -> 0x%x\n", pci_int & 0xffff);
+		printk("PCI AIR -> 0x%x\n", pci_air);
+		printk("PCI CIR -> 0x%x\n", pci_cir);
+		ST40PCI_WRITE(INT, ~0);
+	}
+
+	pci_aint = ST40PCI_READ(AINT);
+	if (pci_aint) {
+		printk("PCI ARB INTERRUPT!\n");
+		printk("PCI AINT -> 0x%x\n", pci_aint);
+		printk("PCI AIR -> 0x%x\n", pci_air);
+		printk("PCI CIR -> 0x%x\n", pci_cir);
+		ST40PCI_WRITE(AINT, ~0);
+	}
+
+	return IRQ_HANDLED;
+}
+
+
+/* Rounds a number UP to the nearest power of two. Used for
+ * sizing the PCI window.
+ */
+static u32 __init r2p2(u32 num)
+{
+	int i = 31;
+	u32 tmp = num;
+
+	if (num == 0)
+		return 0;
+
+	do {
+		if (tmp & (1 << 31))
+			break;
+		i--;
+		tmp <<= 1;
+	} while (i >= 0);
+
+	tmp = 1 << i;
+	/* If the original number isn't a power of 2, round it up */
+	if (tmp != num)
+		tmp <<= 1;
+
+	return tmp;
+}
+
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+	int i;
+
+	/*
+	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
+	 */
+	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return;
+	printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+	for(i=0; i<4; i++) {
+		struct resource *r = &d->resource[i];
+		if ((r->start & ~0x80) == 0x374) {
+			r->start |= 2;
+			r->end = r->start;
+		}
+	}
+}
+
+
+/* Add future fixups here... */
+struct pci_fixup pcibios_fixups[] = {
+	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
+	{ 0 }
+};
+
+int __init st40pci_init(unsigned memStart, unsigned memSize)
+{
+	u32 lsr0;
+
+	SetPCIPLL();
+
+	/* Initialises the ST40 pci subsystem, performing a reset, then programming
+	 * up the address space decoders appropriately
+	 */
+
+	/* Should reset core here as well methink */
+
+	ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET);
+
+	/* Loop while core resets */
+	while (ST40PCI_READ(CR) & CR_SOFT_RESET);
+
+	/* Now, lets reset all the cards on the bus with extreme prejudice */
+	ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL);
+	udelay(250);
+
+	/* Set bus active, take it out of reset */
+	ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_CFINT | CR_PFCS | CR_PFE);
+
+	/* The PCI spec says that no access must be made to the bus until 1 second
+	 * after reset. This seem ludicrously long, but some delay is needed here
+	 */
+	mdelay(1000);
+
+	/* Switch off interrupts */
+	ST40PCI_WRITE(INTM, 0);
+	ST40PCI_WRITE(AINT, 0);
+
+	/* Allow it to be a master */
+
+	ST40PCI_WRITE_SHORT(CSR_CMD,
+			    PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+			    PCI_COMMAND_IO);
+
+	/* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000
+	 * on the PCI bus. This allows a nice 1-1 bus to phys mapping.
+	 */
+
+
+	ST40PCI_WRITE(MBR, 0x10000000);
+	/* Always set the max size 128M (actually, it is only 96MB wide) */
+	ST40PCI_WRITE(MBMR, 0x07ff0000);
+
+	/* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to 
+	 * allow cards that have legacy io such as vga to function correctly. This gives a 
+	 * maximum of 64K of io/space as only the bottom 16 bits of the address are copied 
+	 * over to the bus  when the transaction is made. 64K of io space is more than enough
+	 */
+	ST40PCI_WRITE(IOBR, 0x0);
+	/* Set up the 64K window */
+	ST40PCI_WRITE(IOBMR, 0x0);
+
+	/* Now we set up the mbars so the PCI bus can see the memory of the machine */
+
+	if (memSize < (64 * 1024)) {
+		printk("Ridiculous memory size of 0x%x?\n",memSize);
+		return 0;
+	}
+
+	lsr0 =
+	    (memSize >
+	     (512 * 1024 * 1024)) ? 0x1fff0001 : ((r2p2(memSize) -
+						   0x10000) | 0x1);
+
+	ST40PCI_WRITE(LSR0, lsr0);
+
+	ST40PCI_WRITE(CSR_MBAR0, memStart);
+	ST40PCI_WRITE(LAR0, memStart);
+
+	/* Maximise timeout values */
+	ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff);
+	ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff);
+	ST40PCI_WRITE_BYTE(CSR_MIT, 0xff);
+
+
+	/* Install the pci interrupt handlers */
+	make_intc2_irq(ST40PCI_SERR_IRQ, INTC2_BASE0,
+		       ST40PCI_SERR_INT_GROUP, ST40PCI_SERR_INT_POS,
+		       ST40PCI_SERR_INT_PRI);
+
+	make_intc2_irq(ST40PCI_ERR_IRQ, INTC2_BASE0, ST40PCI_ERR_INT_GROUP,
+		       ST40PCI_ERR_INT_POS, ST40PCI_ERR_INT_PRI);
+
+
+	return 1;
+}
+
+char * __init pcibios_setup(char *str)
+{
+	return str;
+}
+
+
+#define SET_CONFIG_BITS(bus,devfn,where)\
+  (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0))
+
+#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where)
+
+
+static int CheckForMasterAbort(void)
+{
+	if (ST40PCI_READ(INT) & INT_MADIM) {
+		/* Should we clear config space version as well ??? */
+		ST40PCI_WRITE(INT, INT_MADIM);
+		ST40PCI_WRITE_SHORT(CSR_STATUS, 0);
+		return 1;
+	}
+
+	return 0;
+}
+
+/* Write to config register */
+static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
+{
+	ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
+	switch (size) {
+		case 1:
+			*val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3));
+			break;
+		case 2:
+			*val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2));
+			break;
+		case 4:
+			*val = ST40PCI_READ(PDR);
+			break;
+	}
+
+	if (CheckForMasterAbort()){
+		switch (size) {
+			case 1:
+				*val = (u8)0xff;
+				break;
+			case 2:
+				*val = (u16)0xffff;
+				break;
+			case 4:
+				*val = 0xffffffff;
+				break;
+		}
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
+{
+	ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
+
+	switch (size) {
+		case 1:
+			ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val);
+			break;
+		case 2:
+			ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val);
+			break;
+		case 4:
+			ST40PCI_WRITE(PDR, val);
+			break;
+	}
+
+	CheckForMasterAbort();
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_config_ops = {
+	.read = 	st40pci_read,
+	.write = 	st40pci_write,
+};
+
+
+/* Everything hangs off this */
+static struct pci_bus *pci_root_bus;
+
+
+static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
+{
+	return PCI_SLOT(dev->devfn);
+}
+
+
+/* This needs to be shunted out of here into the board specific bit */
+#define HARP_PCI_IRQ    1
+#define HARP_BRIDGE_IRQ 2
+#define OVERDRIVE_SLOT0_IRQ 0
+
+static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	switch (slot) {
+#ifdef CONFIG_SH_STB1_HARP
+	case 2:		/*This is the PCI slot on the */
+		return HARP_PCI_IRQ;
+	case 1:		/* this is the bridge */
+		return HARP_BRIDGE_IRQ;
+#elif defined(CONFIG_SH_STB1_OVERDRIVE)
+	case 1:
+	case 2:
+	case 3:
+		return slot - 1;
+#else
+#error Unknown board
+#endif
+	default:
+		return -1;
+	}
+}
+
+void __init pcibios_init(void)
+{
+	extern unsigned long memory_start, memory_end;
+
+	if (sh_mv.mv_init_pci != NULL) {
+		sh_mv.mv_init_pci();
+	}
+
+	/* The pci subsytem needs to know where memory is and how much 
+	 * of it there is. I've simply made these globals. A better mechanism
+	 * is probably needed.
+	 */
+	st40pci_init(PHYSADDR(memory_start),
+		     PHYSADDR(memory_end) - PHYSADDR(memory_start));
+
+	if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, 
+                        SA_INTERRUPT, "st40pci", NULL)) {
+		printk(KERN_ERR "st40pci: Cannot hook interrupt\n");
+		return;
+	}
+
+	/* Enable the PCI interrupts on the device */
+	ST40PCI_WRITE(INTM, ~0);
+	ST40PCI_WRITE(AINT, ~0);
+
+	/* Map the io address apprioately */
+#ifdef CONFIG_HD64465
+	hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1,
+			 ST40_IO_ADDR + PCIBIOS_MIN_IO, 0);
+#endif
+
+	/* ok, do the scan man */
+	pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
+	pci_assign_unassigned_resources();
+	pci_fixup_irqs(no_swizzle, map_harp_irq);
+
+}
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/pci-st40.h linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/pci-st40.h
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/sh4/pci-st40.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/sh4/pci-st40.h	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,66 @@
+/* 
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Defintions for the ST40 PCI hardware.
+ */
+
+#ifndef __PCI_ST40_H__
+#define __PCI_ST40_H__
+
+#define ST40PCI_VCR_STATUS    0x00
+
+#define ST40PCI_VCR_VERSION   0x08
+
+#define ST40PCI_CR            0x10
+
+#define CR_SOFT_RESET (1<<12)
+#define CR_PFCS       (1<<11)
+#define CR_PFE        (1<<9)
+#define CR_BMAM       (1<<6)
+#define CR_HOST       (1<<5)
+#define CR_CLKEN      (1<<4)
+#define CR_SOCS       (1<<3)
+#define CR_IOCS       (1<<2)
+#define CR_RSTCTL     (1<<1)
+#define CR_CFINT      (1<<0)
+#define CR_LOCK_MASK  0x5a000000
+
+
+#define ST40PCI_LSR0          0X14
+#define ST40PCI_LAR0          0x1c
+
+#define ST40PCI_INT           0x24
+#define INT_MADIM             (1<<2)
+
+
+#define ST40PCI_INTM          0x28
+#define ST40PCI_AIR           0x2c
+#define ST40PCI_CIR           0x30
+#define ST40PCI_AINT          0x40
+#define ST40PCI_AINTM         0x44
+#define ST40PCI_BMIR          0x48
+#define ST40PCI_PAR           0x4c
+#define ST40PCI_MBR           0x50
+#define ST40PCI_IOBR          0x54
+#define ST40PCI_PINT          0x58
+#define ST40PCI_PINTM         0x5c
+#define ST40PCI_MBMR          0x70
+#define ST40PCI_IOBMR         0x74
+#define ST40PCI_PDR           0x78
+
+/* These are configs space registers */
+#define ST40PCI_CSR_VID               0x10000
+#define ST40PCI_CSR_DID               0x10002
+#define ST40PCI_CSR_CMD               0x10004
+#define ST40PCI_CSR_STATUS            0x10006
+#define ST40PCI_CSR_MBAR0             0x10010
+#define ST40PCI_CSR_TRDY              0x10040
+#define ST40PCI_CSR_RETRY             0x10041
+#define ST40PCI_CSR_MIT               0x1000d
+
+#define ST40_IO_ADDR 0xb6000000       
+
+#endif /* __PCI_ST40_H__ */
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpu/ubc.S linux-2.5.73-bk10/arch/sh/kernel/cpu/ubc.S
--- linux-2.5.73-bk9/arch/sh/kernel/cpu/ubc.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpu/ubc.S	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,59 @@
+/*
+ * arch/sh/kernel/ubc.S
+ *
+ * Set of management routines for the User Break Controller (UBC)
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * 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/linkage.h>
+#include <asm/ubc.h>
+
+#define STBCR2		0xffc00010
+
+ENTRY(ubc_sleep)
+	mov	#0, r0
+
+	mov.l	1f, r1		! Zero out UBC_BBRA ..
+	mov.w	r0, @r1
+
+	mov.l	2f, r1		! .. same for BBRB ..
+	mov.w	r0, @r1
+
+	mov.l	3f, r1		! .. and again for BRCR.
+	mov.w	r0, @r1
+
+	mov.w	@r1, r0		! Dummy read BRCR
+
+	mov.l	4f, r1		! Set MSTP5 in STBCR2
+	mov.b	@r1, r0
+	or	#0x01, r0
+	mov.b	r0, @r1
+
+	mov.b	@r1, r0		! Two dummy reads ..
+	mov.b	@r1, r0
+
+	rts
+	nop
+
+ENTRY(ubc_wakeup)
+	mov.l	4f, r1		! Clear MSTP5
+	mov.b	@r1, r0
+	and	#0xfe, r0
+	mov.b	r0, @r1
+
+	mov.b	@r1, r0		! Two more dummy reads ..
+	mov.b	@r1, r0
+
+	rts
+	nop
+
+1:	.long	UBC_BBRA
+2:	.long	UBC_BBRB
+3:	.long	UBC_BRCR
+4:	.long	STBCR2
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/cpufreq.c linux-2.5.73-bk10/arch/sh/kernel/cpufreq.c
--- linux-2.5.73-bk9/arch/sh/kernel/cpufreq.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/cpufreq.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,220 @@
+/*
+ * arch/sh/kernel/cpufreq.c
+ *
+ * cpufreq driver for the SuperH processors.
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown
+ *
+ * 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/types.h>
+#include <linux/cpufreq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+
+#include <asm/processor.h>
+#include <asm/watchdog.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+/*
+ * For SuperH, each policy change requires that we change the IFC, BFC, and
+ * PFC at the same time.  Here we define sane values that won't trash the
+ * system.
+ *
+ * Note the max set is computed at runtime, we use the divisors that we booted
+ * with to setup our maximum operating frequencies.
+ */
+struct clock_set {
+	unsigned int ifc;
+	unsigned int bfc;
+	unsigned int pfc;
+} clock_sets[] = {
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH2)
+	{ 0, 0, 0 },	/* not implemented yet */
+#elif defined(CONFIG_CPU_SH4)
+	{ 4, 8, 8 },	/* min - IFC: 1/4, BFC: 1/8, PFC: 1/8 */
+	{ 1, 2, 2 },	/* max - IFC: 1, BFC: 1/2, PFC: 1/2 */
+#endif
+};
+
+#define NR_CLOCK_SETS	(sizeof(clock_sets) / sizeof(struct clock_set))
+#define MIN_CLOCK_SET	0
+#define MAX_CLOCK_SET	(NR_CLOCK_SETS - 1)
+
+/*
+ * For the time being, we only support two frequencies, which in turn are
+ * aimed at the POWERSAVE and PERFORMANCE policies, which in turn are derived
+ * directly from the respective min/max clock sets. Technically we could
+ * support a wider range of frequencies, but these vary far too much for each
+ * CPU subtype (and we'd have to construct a frequency table for each subtype).
+ *
+ * Maybe something to implement in the future..
+ */
+#define SH_FREQ_MAX	0
+#define SH_FREQ_MIN	1
+
+static struct cpufreq_frequency_table sh_freqs[] = {
+	{ SH_FREQ_MAX,	0 },
+	{ SH_FREQ_MIN,	0 },
+	{ 0,		CPUFREQ_TABLE_END },
+};
+
+static void sh_cpufreq_update_clocks(unsigned int set)
+{
+	current_cpu_data.cpu_clock = current_cpu_data.master_clock / clock_sets[set].ifc;
+	current_cpu_data.bus_clock = current_cpu_data.master_clock / clock_sets[set].bfc;
+	current_cpu_data.module_clock = current_cpu_data.master_clock / clock_sets[set].pfc;
+	current_cpu_data.loops_per_jiffy = loops_per_jiffy;
+}
+
+/* XXX: This needs to be split out per CPU and CPU subtype. */
+/*
+ * Here we notify other drivers of the proposed change and the final change.
+ */
+static int sh_cpufreq_setstate(unsigned int cpu, unsigned int set)
+{
+	unsigned short frqcr = ctrl_inw(FRQCR);
+	unsigned long cpus_allowed;
+	struct cpufreq_freqs freqs;
+	int allowable_cpu_map;
+
+	if (!cpu_online(cpu))
+		return -ENODEV;
+
+	cpus_allowed = current->cpus_allowed;
+	allowable_cpu_map = 1 << cpu;
+	set_cpus_allowed(current, allowable_cpu_map);
+	
+	BUG_ON(!(allowable_cpu_map & (1 << smp_processor_id())));
+
+	freqs.cpu = cpu;
+	freqs.old = current_cpu_data.cpu_clock / 1000;
+	freqs.new = (current_cpu_data.master_clock / clock_sets[set].ifc) / 1000;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+#if defined(CONFIG_CPU_SH3)
+	frqcr |= (newstate & 0x4000) << 14;
+	frqcr |= (newstate & 0x000c) <<  2;
+#elif defined(CONFIG_CPU_SH4)
+	/*
+	 * FRQCR.PLL2EN is 1, we need to allow the PLL to stabilize by
+	 * initializing the WDT.
+	 */
+	if (frqcr & (1 << 9)) {
+		__u8 csr;
+
+		/*
+		 * Set the overflow period to the highest available,
+		 * in this case a 1/4096 division ratio yields a 5.25ms
+		 * overflow period. See asm-sh/watchdog.h for more
+		 * information and a range of other divisors.
+		 */
+		csr = sh_wdt_read_csr();
+		csr |= WTCSR_CKS_4096;
+		sh_wdt_write_csr(csr);
+
+		sh_wdt_write_cnt(0);
+	}
+	frqcr &= 0x0e00;	/* Clear ifc, bfc, pfc */
+	frqcr |= get_ifc_value(clock_sets[set].ifc) << 6;
+	frqcr |= get_bfc_value(clock_sets[set].bfc) << 3;
+	frqcr |= get_pfc_value(clock_sets[set].pfc);
+#endif
+	ctrl_outw(frqcr, FRQCR);
+	sh_cpufreq_update_clocks(set);
+
+	set_cpus_allowed(current, cpus_allowed);
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	
+	return 0;
+}
+
+static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	unsigned int min_freq, max_freq;
+	unsigned int ifc, bfc, pfc;
+
+	if (!cpu_online(policy->cpu))
+		return -ENODEV;
+
+	/* Update our maximum clock set */
+	get_current_frequency_divisors(&ifc, &bfc, &pfc);
+	clock_sets[MAX_CLOCK_SET].ifc = ifc;
+	clock_sets[MAX_CLOCK_SET].bfc = bfc;
+	clock_sets[MAX_CLOCK_SET].pfc = pfc;
+
+	/* Convert from Hz to kHz */
+	max_freq = current_cpu_data.cpu_clock / 1000;
+	min_freq = (current_cpu_data.master_clock / clock_sets[MIN_CLOCK_SET].ifc) / 1000;
+	
+	sh_freqs[SH_FREQ_MAX].frequency = max_freq;
+	sh_freqs[SH_FREQ_MIN].frequency = min_freq;
+
+	/* cpuinfo and default policy values */
+	policy->policy                     = CPUFREQ_POLICY_PERFORMANCE;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	policy->cur                        = max_freq;
+
+	return cpufreq_frequency_table_cpuinfo(policy, &sh_freqs[0]);
+}
+
+static int sh_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, &sh_freqs[0]);
+}
+
+static int sh_cpufreq_target(struct cpufreq_policy *policy,
+			     unsigned int target_freq,
+			     unsigned int relation)
+{
+	unsigned int set, idx = 0;
+
+	if (cpufreq_frequency_table_target(policy, &sh_freqs[0], target_freq, relation, &idx))
+		return -EINVAL;
+
+	set = (idx == SH_FREQ_MIN) ? MIN_CLOCK_SET : MAX_CLOCK_SET;
+
+	sh_cpufreq_setstate(policy->cpu, set);
+
+	return 0;
+}
+
+static struct cpufreq_driver sh_cpufreq_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "SH cpufreq",
+	.init		= sh_cpufreq_cpu_init,
+	.verify		= sh_cpufreq_verify,
+	.target		= sh_cpufreq_target,
+};
+
+static int __init sh_cpufreq_init(void)
+{
+	if (!current_cpu_data.cpu_clock)
+		return -EINVAL;
+	if (cpufreq_register_driver(&sh_cpufreq_driver))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void __exit sh_cpufreq_exit(void)
+{
+	cpufreq_unregister_driver(&sh_cpufreq_driver);
+}
+
+module_init(sh_cpufreq_init);
+module_exit(sh_cpufreq_exit);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_DESCRIPTION("cpufreq driver for SuperH");
+MODULE_LICENSE("GPL");
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/entry.S linux-2.5.73-bk10/arch/sh/kernel/entry.S
--- linux-2.5.73-bk9/arch/sh/kernel/entry.S	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/entry.S	2003-07-02 04:57:23.000000000 -0700
@@ -1,8 +1,9 @@
-/* $Id: entry.S,v 1.71 2001/07/27 11:47:50 gniibe Exp $
+/* $Id: entry.S,v 1.19 2003/05/06 23:28:47 lethal Exp $
  *
  *  linux/arch/sh/entry.S
  *
- *  Copyright (C) 1999, 2000  Niibe Yutaka
+ *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
+ *  Copyright (C) 2003  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -13,13 +14,17 @@
 #include <linux/sys.h>
 #include <linux/linkage.h>
 #include <linux/config.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
 
+#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
+#define sys_nfsservctl		sys_ni_syscall
+#endif
 
-/*
- * Define this to turn on compatibility with the previous
- * system call ABI.  This feature is not properly maintained.
- */
-#undef COMPAT_OLD_SYSCALL_ABI
+#if !defined(CONFIG_MMU)
+#define sys_madvise		sys_ni_syscall
+#define sys_readahead		sys_ni_syscall
+#endif
 
 ! NOTE:
 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -57,20 +62,10 @@
  *
  */
 
-/*
- * These are offsets into the task-struct.
- */
-flags		=  4
-#error sigpending	=  8
-#error need_resched	= 20
-#error tsk_ptrace	= 24
-
-#error PT_TRACESYS  = 0x00000002
-
 ENOSYS = 38
 EINVAL = 22
 
-#if defined(__sh3__)
+#if defined(CONFIG_CPU_SH3)
 TRA     = 0xffffffd0
 EXPEVT  = 0xffffffd4
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
@@ -79,25 +74,30 @@
 INTEVT  = 0xffffffd8
 #endif
 MMU_TEA = 0xfffffffc		! TLB Exception Address Register
-#elif defined(__SH4__)
+#elif defined(CONFIG_CPU_SH4)
 TRA     = 0xff000020
 EXPEVT  = 0xff000024
 INTEVT  = 0xff000028
 MMU_TEA = 0xff00000c		! TLB Exception Address Register
 #endif
 
+#if defined(CONFIG_KGDB_NMI)
+NMI_VEC = 0x1c0			! Must catch early for debounce
+#endif
+
 /* Offsets to the stack */
-OFF_R0         =  0		/* Return value. New ABI also arg4 */
-OFF_R1         =  4     	/* New ABI: arg5 */
-OFF_R2         =  8     	/* New ABI: arg6 */
-OFF_R3         =  12     	/* New ABI: syscall_nr */
-OFF_R4         =  16     	/* New ABI: arg0 */
-OFF_R5         =  20     	/* New ABI: arg1 */
-OFF_R6         =  24     	/* New ABI: arg2 */
-OFF_R7         =  28     	/* New ABI: arg3 */
-OFF_SP	   =  (15*4)
-OFF_SR	   =  (16*4+8)
-SYSCALL_NR =  (16*4+6*4)
+OFF_R0  =  0		/* Return value. New ABI also arg4 */
+OFF_R1  =  4     	/* New ABI: arg5 */
+OFF_R2  =  8     	/* New ABI: arg6 */
+OFF_R3  =  12     	/* New ABI: syscall_nr */
+OFF_R4  =  16     	/* New ABI: arg0 */
+OFF_R5  =  20     	/* New ABI: arg1 */
+OFF_R6  =  24     	/* New ABI: arg2 */
+OFF_R7  =  28     	/* New ABI: arg3 */
+OFF_SP	=  (15*4)
+OFF_PC  =  (16*4)
+OFF_SR	=  (16*4+8)
+OFF_TRA	=  (16*4+6*4)
 
 
 #define k0	r0
@@ -106,11 +106,10 @@
 #define k3	r3
 #define k4	r4
 
-#define current		r7	/* r7_bank1 */
+#define k_ex_code	r2_bank	/* r2_bank1 */
 #define g_imask		r6	/* r6_bank1 */
-#define k_current	r7_bank	/* r7_bank1 */
 #define k_g_imask	r6_bank	/* r6_bank1 */
-#define k_ex_code	r2_bank	/* r2_bank1 */
+#define current		r7	/* r7_bank1 */
 
 /*
  * Kernel mode register usage:
@@ -121,7 +120,7 @@
  *	k4	scratch
  *	k5	reserved
  *	k6	Global Interrupt Mask (0--15 << 4)
- *	k7	CURRENT (pointer to current task)
+ *	k7	CURRENT_THREAD_INFO (pointer to current thread info)
  */
 
 !
@@ -142,10 +141,11 @@
 	mov.l	__INV_IMASK, r11;	\
 	stc	sr, r10;		\
 	and	r11, r10;		\
-	stc	k_g_imask, r11;	\
+	stc	k_g_imask, r11;		\
 	or	r11, r10;		\
 	ldc	r10, sr
 
+#if defined(CONFIG_MMU)
 	.align	2
 tlb_miss_load:
 	bra	call_dpf
@@ -208,6 +208,7 @@
 	bra	call_dae
 	 mov	#1,r5		! writeaccess = 1
 
+	.align	2
 call_dae:
 	mov.l	1f, r0
 	mov.l	@r0, r6		! address
@@ -218,11 +219,37 @@
 	.align 2
 1:	.long	MMU_TEA
 2:	.long   do_address_error
+#endif /* CONFIG_MMU */
+
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
+! If both are configured, handle the debug traps (breakpoints) in SW,
+! but still allow BIOS traps to FW.
 
-#if defined(CONFIG_SH_STANDARD_BIOS)
 	.align	2
-	/* Unwind the stack and jmp to the debug entry */
 debug_kernel:
+#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
+	/* Force BIOS call to FW (debug_trap put TRA in r8) */
+	mov	r8,r0
+	shlr2	r0
+	cmp/eq	#0x3f,r0
+	bt	debug_kernel_fw
+#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
+
+debug_enter:		
+#if defined(CONFIG_SH_KGDB)
+	/* Jump to kgdb, pass stacked regs as arg */
+debug_kernel_sw:
+	mov.l	3f, r0
+	jmp	@r0
+	 mov	r15, r4
+	.align	2
+3:	.long	SYMBOL_NAME(kgdb_handle_exception)
+#endif /* CONFIG_SH_KGDB */
+
+#if defined(CONFIG_SH_STANDARD_BIOS)
+	/* Unwind the stack and jmp to the debug entry */
+debug_kernel_fw:
 	mov.l	@r15+, r0
 	mov.l	@r15+, r1
 	mov.l	@r15+, r2
@@ -258,67 +285,158 @@
 	.align	2
 1:	.long	0x300000f0
 2:	.long	gdb_vbr_vector
-#endif
+#endif /* CONFIG_SH_STANDARD_BIOS */
+
+#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
+
 
 	.align	2
 debug_trap:	
-#if defined(CONFIG_SH_STANDARD_BIOS)
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
 	mov	#OFF_SR, r0
 	mov.l	@(r0,r15), r0		! get status register
 	shll	r0
 	shll	r0			! kernel space?
 	bt/s	debug_kernel
 #endif
-	 mov.l	@r15, r0
+	 mov.l	@r15, r0		! Restore R0 value
 	mov.l	1f, r8
 	jmp	@r8
 	 nop
 
 	.align	2
-1:	.long	break_point_trap_software
-
-	.align	2
 error:	
 	!
 	STI()
-	mov.l	1f, r0
+	mov.l	2f, r0
 	jmp	@r0
 	 nop
+
+!
 	.align	2
-1:	.long	do_exception_error
+1:	.long	break_point_trap_software
+2:	.long	do_exception_error
 
+	.align	2
+ret_from_irq:
+ret_from_exception:
+	mov	#OFF_SR, r0
+	mov.l	@(r0,r15), r0	! get status register
+	shll	r0
+	shll	r0		! kernel space?
+	bt/s	restore_all	! Yes, it's from kernel, go back soon
+	 GET_THREAD_INFO(r8)
 
-!
-!
-!
-ENTRY(ret_from_fork)
-	mov.l	@r15+,r0
-	! Call schedule_tail
+ENTRY(resume_userspace)
+	! r8: current_thread_info
+	/* CLI */
+	stc	sr, r0
+	or	#0xf0, r0
+	ldc	r0, sr
+	!
+	mov.l	@(TI_FLAGS,r8), r0		! current_thread_info->flags
+	tst	#_TIF_WORK_MASK, r0
+	bt/s	restore_all
+	 tst	#_TIF_NEED_RESCHED, r0
+
+	.align	2
+work_pending:
+	! r0: current_thread_info->flags
+	! r8: current_thread_info
+	! t:  result of "tst	#_TIF_NEED_RESCHED, r0"
+	bf/s	work_resched
+	 tst	#_TIF_SIGPENDING, r0
+work_notifysig:
+	bt/s	restore_all
+	 mov	r15, r4
+	mov	#0, r5
+	mov.l	2f, r1
+	mova	restore_all, r0
+	jmp	@r1
+	 lds	r0, pr
+work_resched:
+#ifndef CONFIG_PREEMPT
+	! gUSA handling
+	mov.l	@(OFF_SP,r15), r0	! get user space stack pointer
+	mov	r0, r1
+	shll	r0
+	bf/s	1f
+	 shll	r0
+	bf/s	1f
+	 mov	#OFF_PC, r0
+	! 				  SP >= 0xc0000000 : gUSA mark
+	mov.l	@(r0,r15), r2		! get user space PC (program counter)
+	mov.l	@(OFF_R0,r15), r3	! end point
+	cmp/hs	r3, r2			! r2 >= r3? 
+	bt	1f
+	add	r3, r1			! rewind point #2
+	mov.l	r1, @(r0,r15)		! reset PC to rewind point #2
+	!
+1:
+#endif
 	mov.l	1f, r1
-	jsr @r1
-	 mov	r0, r4
-	! If we're being traced, return via syscall_ret_trace, otherwise
-	! return directly to ret_from_syscall
-	stc	k_current, r0
-#error	mov.l	@(tsk_ptrace,r0), r0	! Is current PTRACE_SYSCALL'd?
-#error	mov	#PT_TRACESYS, r1
-	tst	r1, r0
-	bt	ret_from_syscall
-	bra	syscall_ret_trace
-	 nop	 
+	jsr	@r1				! schedule
+	 nop
+	/* CLI */
+	stc	sr, r0
+	or	#0xf0, r0
+	ldc	r0, sr
+	!
+	mov.l	@(TI_FLAGS,r8), r0		! current_thread_info->flags
+	tst	#_TIF_WORK_MASK, r0
+	bt	restore_all
+	bra	work_pending
+	 tst	#_TIF_NEED_RESCHED, r0
 
 	.align	2
-1:	.long	schedule_tail
+1:	.long	schedule
+2:	.long	do_signal
+
+	.align	2
+syscall_exit_work:
+	! r0: current_thread_info->flags
+	! r8: current_thread_info
+	tst	#_TIF_SYSCALL_TRACE, r0
+	bt/s	work_pending
+	 tst	#_TIF_NEED_RESCHED, r0
+	STI()
+	! XXX setup arguments...
+	mov.l	4f, r0			! do_syscall_trace
+	jsr	@r0
+	 nop
+	bra	resume_userspace
+	 nop
+
+	.align	2
+syscall_trace_entry:
+	!                     	Yes it is traced.
+	! XXX setup arguments...
+	mov.l	4f, r11		! Call do_syscall_trace which notifies
+	jsr	@r11	    	! superior (will chomp R[0-7])
+	 nop
+	!			Reload R0-R4 from kernel stack, where the
+	!   	    	    	parent may have modified them using
+	!   	    	    	ptrace(POKEUSR).  (Note that R0-R2 are
+	!   	    	    	used by the system call handler directly
+	!   	    	    	from the kernel stack anyway, so don't need
+	!   	    	    	to be reloaded here.)  This allows the parent
+	!   	    	    	to rewrite system calls and args on the fly.
+	mov.l	@(OFF_R4,r15), r4   ! arg0
+	mov.l	@(OFF_R5,r15), r5
+	mov.l	@(OFF_R6,r15), r6
+	mov.l	@(OFF_R7,r15), r7   ! arg3
+	mov.l	@(OFF_R3,r15), r3   ! syscall_nr
+	!   	    	    Arrange for do_syscall_trace to be called
+	!   	    	    again as the system call returns.
+	mov.l	2f, r10			! Number of syscalls
+	cmp/hs	r10, r3
+	bf	syscall_call
+	mov	#-ENOSYS, r0
+	bra	syscall_exit
+	 mov.l	r0, @(OFF_R0,r15)	! Return value
 
 /*
- * Old syscall interface:
- *
- *	Syscall #: R0
- *	Arguments #0 to #3: R4--R7
- *	more arguments: On the stack
- *	TRA: (number of arguments on the stack) x 4
- *
- * New syscall interface:
+ * Syscall interface:
  *
  *	Syscall #: R3
  *	Arguments #0 to #3: R4--R7
@@ -340,231 +458,67 @@
  * argument.
  */
 
+	.align	2
+	.globl	ret_from_fork
+ret_from_fork:
+	mov.l	1f, r8
+	jsr	@r8
+	 mov	r0, r4
+	bra	syscall_exit
+	 nop
+	.align	2
+1:	.long	schedule_tail
+	!
 system_call:
-	mov.l	__TRA, r9
-	mov.l	@r9, r8
+	mov.l	1f, r9
+	mov.l	@r9, r8		! Read from TRA (Trap Address) Register
 	!
 	! Is the trap argument >= 0x20? (TRA will be >= 0x80)
-	mov	#0x20, r9
-	extu.b	r9, r9
-	shll2	r9
-	cmp/hs	r9, r8
-	bt	debug_trap
-	!
-	mov	#SYSCALL_NR, r14
-	add	r15, r14
-	!
-#ifdef COMPAT_OLD_SYSCALL_ABI
-	mov	#0x40, r9
-	cmp/hs	r9, r8
-	bf/s	old_abi_system_call
-	 nop
-#endif
-	! New Syscall ABI
-	add	#-0x40, r8
-	shlr2	r8
-	shll8	r8
-	shll8	r8 		    	! r8 = num_args<<16
-	mov	r3, r10
-	or	r8, r10	! Encode syscall # and # of arguments
-	mov.l	r10, @r14		! set syscall_nr
-	STI()
+	mov	#0x7f, r9
+	cmp/hi	r9, r8
+	bt/s	debug_trap
+	 mov	#OFF_TRA, r9
+	add	r15, r9
 	!
-	stc	k_current, r11
-#error	mov.l	@(tsk_ptrace,r11), r10	! Is current PTRACE_SYSCALL'd?
-#error	mov	#PT_TRACESYS, r11
-	tst	r11, r10
-	bt	5f
-	!                     	Yes it is traced.
-	mov.l	__syscall_trace, r11	! Call syscall_trace() which notifies
-	jsr	@r11	    	    	! superior (will chomp R[0-7])
-	 nop
-	!			Reload R0-R4 from kernel stack, where the
-	!   	    	    	parent may have modified them using
-	!   	    	    	ptrace(POKEUSR).  (Note that R0-R2 are
-	!   	    	    	used by the system call handler directly
-	!   	    	    	from the kernel stack anyway, so don't need
-	!   	    	    	to be reloaded here.)  This allows the parent
-	!   	    	    	to rewrite system calls and args on the fly.
-	mov.l	@(OFF_R4,r15), r4   ! arg0
-	mov.l	@(OFF_R5,r15), r5
-	mov.l	@(OFF_R6,r15), r6
-	mov.l	@(OFF_R7,r15), r7   ! arg3
-	mov.l	@(OFF_R3,r15), r3   ! syscall_nr
-	!   	    	    Arrange for syscall_trace() to be called
-	!   	    	    again as the system call returns.
-	mov.l	__syscall_ret_trace, r10
-	bra	6f
-	 lds	r10, pr
-	!   	    	    No it isn't traced.
-	!   	    	    Arrange for normal system call return.
-5:	mov.l	__syscall_ret, r10
-	lds	r10, pr
-	!   	    	    Call the system call handler through the table.
-	!   	    	    (both normal and ptrace'd)
-	!   	    	    First check for bad syscall number
-6:	mov	r3, r9
-	mov.l	__n_sys, r10
-	cmp/hs	r10, r9
-	bf	2f
-	!   	    	    Bad syscall number
-	rts			! go to syscall_ret or syscall_ret_trace
-    	 mov	#-ENOSYS, r0
-	!   	    	    Good syscall number
-2:	shll2	r9		! x4
-	mov.l	__sct, r11
-	add	r11, r9
-	mov.l	@r9, r11
-	jmp	@r11	    	! jump to specific syscall handler
-	 nop
-
-	! In case of trace
-syscall_ret_trace:
-	mov.l	r0, @(OFF_R0,r15)		! save the return value
-	mov.l	__syscall_trace, r1
-	mova	ret_from_syscall, r0
-	jmp	@r1    	! Call syscall_trace() which notifies superior
-	 lds	r0, pr    	! Then return to ret_from_syscall()
-
-
-
-#ifdef COMPAT_OLD_SYSCALL_ABI
-! Handle old ABI system call.
-! Note that ptrace(SYSCALL) is not supported for the old ABI.
-! At this point:
-!   r0, r4-7 as per ABI
-!   r8  = value of TRA register (= num_args<<2)
-!   r14 = points to SYSCALL_NR in stack frame
-old_abi_system_call:
-	mov 	r0, r9    	    	! Save system call number in r9
-	!   	    	    	    	! arrange for return which pops stack
-	mov.l	__old_abi_syscall_ret, r10
-	lds	r10, pr
-	!				  Build the stack frame if TRA > 0
-	mov	r8, r10
-	cmp/pl	r10
-	bf	0f
-	mov.l	@(OFF_SP,r15), r0	! get original user stack
-7:	add	#-4, r10
-4:	mov.l	@(r0,r10), r1	! May cause address error exception..
-	mov.l	r1, @-r15
-	cmp/pl	r10
-	bt	7b
-0:
-	mov.l	r9, @r14	    	! set syscall_nr
+	mov.l	r8, @r9			! set TRA value to tra
 	STI()
 	!   	    	    Call the system call handler through the table.
 	!   	    	    First check for bad syscall number
-	mov.l	__n_sys, r10
-	cmp/hs	r10, r9
-	bf	2f
-	!   	    	    Bad syscall number
-	rts			! return to old_abi_syscall_ret
-    	 mov	#-ENOSYS, r0
-	!   	    	    Good syscall number
-2:	shll2	r9		! x4
-	mov.l	__sct, r11
-	add	r11, r9
-	mov.l	@r9, r11
-	jmp	@r11	    	! call specific syscall handler,
+	mov	r3, r9
+	mov.l	2f, r8			! Number of syscalls
+	cmp/hs	r8, r9
+	bf/s	good_system_call
+	 GET_THREAD_INFO(r8)
+syscall_badsys:			! Bad syscall number
+	mov	#-ENOSYS, r0
+	bra	resume_userspace
+	 mov.l	r0, @(OFF_R0,r15)	! Return value
+	!
+good_system_call:		! Good syscall number
+	mov.l	@(TI_FLAGS,r8), r8
+	mov	#_TIF_SYSCALL_TRACE, r10
+	tst	r10, r8
+	bf	syscall_trace_entry
+	!
+syscall_call:
+	shll2	r9		! x4
+	mov.l	3f, r8		! Load the address of sys_call_table
+	add	r8, r9
+	mov.l	@r9, r8
+	jsr	@r8	    	! jump to specific syscall handler
 	 nop
-
-    	.align 2
-__old_abi_syscall_ret:
-	.long	old_abi_syscall_ret
-
-    	! This code gets called on address error exception when copying
-	! syscall arguments from user stack to kernel stack.  It is
-	! supposed to return -EINVAL through old_abi_syscall_ret, but it
-	! appears to have been broken for a long time in that the r0
-	! return value will be saved into the kernel stack relative to r15
-	! but the value of r15 is not correct partway through the loop.
-	! So the user prog is returned its old r0 value, not -EINVAL.
-	! Greg Banks 28 Aug 2000.
-	.section	.fixup,"ax"
-fixup_syscall_argerr:
-    	! First get r15 back to 
-	rts
-    	 mov	#-EINVAL, r0
-    	.previous
-
-	.section	__ex_table, "a"
-	.align	2
-	.long	4b,fixup_syscall_argerr
-    	.previous
-#endif
-
-	.align	2
-__TRA:	.long	TRA
-__syscall_trace:
-#error    	.long	syscall_trace
-__n_sys:.long	NR_syscalls
-__sct:	.long	sys_call_table
-__syscall_ret_trace:
-	.long	syscall_ret_trace
-__syscall_ret:
-	.long	syscall_ret
-__INV_IMASK:
-	.long	0xffffff0f	! ~(IMASK)
-
-
-	.align	2
-reschedule:
-	mova	ret_from_syscall, r0
-	mov.l	1f, r1
-	jmp	@r1
-	 lds	r0, pr
-	.align	2
-1:	.long	schedule
-
-ret_from_irq:
-ret_from_exception:
-	mov	#OFF_SR, r0
-	mov.l	@(r0,r15), r0	! get status register
-	shll	r0
-	shll	r0		! kernel space?
-	bt	restore_all	! Yes, it's from kernel, go back soon
+	mov.l	r0, @(OFF_R0,r15)		! save the return value
 	!
-	bra	ret_from_syscall
-	 nop
-
-	.align 2
-#ifdef COMPAT_OLD_SYSCALL_ABI
-old_abi_syscall_ret:
-	add	r8, r15	! pop off the arguments
-	/* fall through */
-#endif
-syscall_ret:
-	mov.l	r0, @(OFF_R0,r15)	! save the return value
-	/* fall through */
-
-ENTRY(ret_from_syscall)
+syscall_exit:
 	/* CLI */
 	stc	sr, r0
 	or	#0xf0, r0
 	ldc	r0, sr
 	!
-	stc	k_current, r1
-#error	mov.l	@(need_resched,r1), r0
-	tst	r0, r0
-	bf	reschedule
-#error	mov.l	@(sigpending,r1), r0
-	tst	r0, r0
-	bt	restore_all
-signal_return:
-	mov	r15, r4
-	mov	#0, r5
-	mov.l	__do_signal, r1
-	mova	restore_all, r0
-	jmp	@r1
-	 lds	r0, pr
-	.align	2
-__do_signal:
-#error	.long	do_signal
-__irq_stat:
-	.long	irq_stat
-
-	.align 2
+	GET_THREAD_INFO(r8)
+	mov.l	@(TI_FLAGS,r8), r0		! current_thread_info->flags
+	tst	#_TIF_ALLWORK_MASK, r0
+	bf	syscall_exit_work
 restore_all:
 	mov.l	@r15+, r0
 	mov.l	@r15+, r1
@@ -576,8 +530,8 @@
 	mov.l	@r15+, r7
 	!
 	stc	sr, r8
-	mov.l	__blrb_flags, r9	! BL =1, RB=1
-	or	r9, r8
+	mov.l	7f, r9
+	or	r9, r8			! BL =1, RB=1
 	ldc	r8, sr			! here, change the register bank
 	!
 	mov.l	@r15+, r8
@@ -598,10 +552,10 @@
 	!
 	! Calculate new SR value
 	mov	k3, k2			! original SR value
-	mov.l	1f, k1
+	mov.l	8f, k1
 	stc	sr, k0
 	and	k1, k0			! Get current FD-bit
-	mov.l	2f, k1
+	mov.l	9f, k1
 	and	k1, k2			! Mask orignal SR value
 	or	k0, k2			! Inherit current FD-bit
 	!
@@ -609,22 +563,36 @@
 	shlr2	k0
 	and	#0x3c, k0
 	cmp/eq	#0x3c, k0
-	bt/s	7f
+	bt/s	6f
 	 shll2	k0
 	mov	g_imask, k0
 	!
-7:	or	k0, k2			! Set the IMASK-bits
+6:	or	k0, k2			! Set the IMASK-bits
 	ldc	k2, ssr
 	!
+#if defined(CONFIG_KGDB_NMI)
+	! Clear in_nmi
+	mov.l	4f, k0
+	mov	#0, k1
+	mov.b	k1, @k0
+#endif
 	mov	k4, r15
 	rte
 	 nop
 
 	.align	2
-__blrb_flags:	.long	0x30000000
-1:	.long	0x00008000	! FD
-2:	.long	0xffff7f0f	! ~(IMASK+FD)
-3:	.long	0x00080000	! SZ=0, PR=1
+1:	.long	TRA
+2:	.long	NR_syscalls
+3:	.long	sys_call_table
+4:	.long	do_syscall_trace
+7:	.long	0x30000000
+8:	.long	0x00008000	! FD
+9:	.long	0xffff7f0f	! ~(IMASK+FD)
+__INV_IMASK:
+	.long	0xffffff0f	! ~(IMASK)
+#if defined(CONFIG_KGDB_NMI)
+10:	.long	in_nmi
+#endif
 
 ! Exception Vector Base
 !
@@ -641,8 +609,8 @@
 	bra	handle_exception
 	 mov.l	@k2, k2
 	.align	2
-2:	.long	ret_from_exception
 1:	.long	EXPEVT
+2:	.long	ret_from_exception
 !
 !
 	.balign 	1024,0,1024
@@ -656,6 +624,22 @@
 interrupt:
 	mov.l	2f, k2
 	mov.l	3f, k3
+#if defined(CONFIG_KGDB_NMI)
+	! Debounce (filter nested NMI)
+	mov.l	@k2, k0
+	mov.l	5f, k1
+	cmp/eq	k1, k0
+	bf	0f
+	mov.l	6f, k1
+	tas.b	@k1
+	bt	0f
+	rte
+	 nop
+	.align	2
+5:	.long	NMI_VEC
+6:	.long	SYMBOL_NAME(in_nmi)
+0:
+#endif /* defined(CONFIG_KGDB_NMI) */
 	bra	handle_exception
 	 mov.l	@k2, k2
 
@@ -667,6 +651,7 @@
 
 !
 !
+	.align	2
 handle_exception:
 	! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
 	! save all registers onto stack.
@@ -674,18 +659,18 @@
 	stc	ssr, k0		! Is it from kernel space?
 	shll	k0		! Check MD bit (bit30) by shifting it into...
 	shll	k0		!       ...the T bit
-	bt/s	9f		! It's a kernel to kernel transition.
+	bt/s	1f		! It's a kernel to kernel transition.
 	 mov	r15, k0		! save original stack to k0
 	/* User space to kernel */
 	mov	#0x20, k1
-	shll8	k1		! k1 <= 8192 == THREAD_SIZE
+	shll8	k1		! k1 := 8192 (== THREAD_SIZE)
 	add	current, k1
 	mov	k1, r15		! change to kernel stack
 	!
-9:  	mov	#-1, k4
-	mov.l	3f, k1
+1:  	mov	#-1, k4
+	mov.l	2f, k1
 	! Save the user registers on the stack.
-	mov.l	k4, @-r15	! syscall_nr (default: -1)
+	mov.l	k4, @-r15	! set TRA (default: -1)
 	!
 	sts.l	macl, @-r15
 	sts.l	mach, @-r15
@@ -707,7 +692,7 @@
 	!
 	stc	sr, r8		! Back to normal register bank, and
 	or	k1, r8		! Block all interrupts
-	mov.l	5f, k1
+	mov.l	3f, k1
 	and	k1, r8		! ...
 	ldc	r8, sr		! ...changed here.
 	!
@@ -723,17 +708,18 @@
 	stc	k_ex_code, r8
 	shlr2	r8
 	shlr	r8
-	mov.l	1f, r9
+	mov.l	4f, r9
 	add	r8, r9
 	mov.l	@r9, r9
 	jmp	@r9
 	 nop
+
 	.align	2
-1:	.long	exception_handling_table
-3:	.long	0x000000f0	! FD=0, IMASK=15
-5:	.long	0xcfffffff	! RB=0, BL=0
-6:	.long	0x00080000	! SZ=0, PR=1
+2:	.long	0x000000f0	! FD=0, IMASK=15
+3:	.long	0xcfffffff	! RB=0, BL=0
+4:	.long	exception_handling_table
 
+	.align	2
 none:
 	rts
 	 nop
@@ -742,6 +728,7 @@
 ENTRY(exception_handling_table)
 	.long	error
 	.long	error
+#if defined(CONFIG_MMU)
 	.long	tlb_miss_load
 	.long	tlb_miss_store
 	.long	initial_page_write
@@ -749,7 +736,17 @@
 	.long	tlb_protection_violation_store
 	.long	address_error_load
 	.long	address_error_store
-#if defined(__SH4__)
+#else
+	.long	error	! tlb miss load
+	.long	error	! tlb miss store
+	.long	error	! initial page write
+	.long	error	! tlb prot violation load
+	.long	error	! tlb prot violation store
+	.long	error	! address error load
+	.long	error	! address error store
+#endif
+
+#if defined(CONFIG_CPU_SH4)
 	.long	do_fpu_error
 #else
 	.long	error	! fpu_exception
@@ -759,92 +756,96 @@
 	.long	error	! reserved_instruction      (filled by trap_init)
 	.long	error	! illegal_slot_instruction  (filled by trap_init)
 ENTRY(nmi_slot)
+#if defined (CONFIG_KGDB_NMI)
+	.long	debug_enter			! Allow trap to debugger
+#else
 	.long	none				! Not implemented yet
+#endif
 ENTRY(user_break_point_trap)
 	.long	break_point_trap
 ENTRY(interrupt_table)
 	! external hardware
-	.long	do_IRQ			! 0000
-	.long	do_IRQ			! 0001
-	.long	do_IRQ			! 0010
-	.long	do_IRQ			! 0011
-	.long	do_IRQ			! 0100
-	.long	do_IRQ			! 0101
-	.long	do_IRQ			! 0110
-	.long	do_IRQ			! 0111
-	.long	do_IRQ			! 1000
-	.long	do_IRQ			! 1001
-	.long	do_IRQ			! 1010
-	.long	do_IRQ			! 1011
-	.long	do_IRQ			! 1100
-	.long	do_IRQ			! 1101
-	.long	do_IRQ			! 1110
+	.long	do_IRQ	! 0000
+	.long	do_IRQ	! 0001
+	.long	do_IRQ	! 0010
+	.long	do_IRQ	! 0011
+	.long	do_IRQ	! 0100
+	.long	do_IRQ	! 0101
+	.long	do_IRQ	! 0110
+	.long	do_IRQ	! 0111
+	.long	do_IRQ	! 1000
+	.long	do_IRQ	! 1001
+	.long	do_IRQ	! 1010
+	.long	do_IRQ	! 1011
+	.long	do_IRQ	! 1100
+	.long	do_IRQ	! 1101
+	.long	do_IRQ	! 1110
 	.long	error
 	! Internal hardware
-	.long	do_IRQ			! TMU0 tuni0
-	.long	do_IRQ			! TMU1 tuni1
-	.long	do_IRQ			! TMU2 tuni2
-	.long	do_IRQ			!      ticpi2
-	.long	do_IRQ			! RTC  ati
-	.long	do_IRQ			!      pri
-	.long	do_IRQ			!      cui
-	.long	do_IRQ			! SCI  eri
-	.long	do_IRQ			!      rxi
-	.long	do_IRQ			!      txi
-	.long	do_IRQ			!      tei
-	.long	do_IRQ			! WDT  iti
-	.long	do_IRQ			! REF  rcmi
-	.long	do_IRQ			!      rovi
-	.long	do_IRQ		
-	.long	do_IRQ		
+	.long	do_IRQ	! TMU0 tuni0
+	.long	do_IRQ	! TMU1 tuni1
+	.long	do_IRQ	! TMU2 tuni2
+	.long	do_IRQ	!      ticpi2
+	.long	do_IRQ	! RTC  ati
+	.long	do_IRQ	!      pri
+	.long	do_IRQ	!      cui
+	.long	do_IRQ	! SCI  eri
+	.long	do_IRQ	!      rxi
+	.long	do_IRQ	!      txi
+	.long	do_IRQ	!      tei
+	.long	do_IRQ	! WDT  iti
+	.long	do_IRQ	! REF  rcmi
+	.long	do_IRQ	!      rovi
+	.long	do_IRQ
+	.long	do_IRQ
 #if  defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
-	.long	do_IRQ			! 32 IRQ  irq0
-	.long	do_IRQ			! 33      irq1
-	.long	do_IRQ			! 34      irq2
-	.long	do_IRQ			! 35      irq3
-	.long	do_IRQ			! 36      irq4
-	.long	do_IRQ			! 37      irq5
-	.long	do_IRQ			! 38
-	.long	do_IRQ			! 39
-	.long	do_IRQ			! 40 PINT pint0-7
-	.long	do_IRQ			! 41      pint8-15
-	.long	do_IRQ			! 42
-	.long	do_IRQ			! 43
-	.long	do_IRQ			! 44
-	.long	do_IRQ			! 45
-	.long	do_IRQ			! 46
-	.long	do_IRQ			! 47
-	.long	do_IRQ			! 48 DMAC dei0
-	.long	do_IRQ			! 49      dei1
-	.long	do_IRQ			! 50      dei2
-	.long	do_IRQ			! 51      dei3
-	.long	do_IRQ			! 52 IrDA eri1
-	.long	do_IRQ			! 53      rxi1
-	.long	do_IRQ			! 54      bri1
-	.long	do_IRQ			! 55      txi1
-	.long	do_IRQ			! 56 SCIF eri2
-	.long	do_IRQ			! 57      rxi2
-	.long	do_IRQ			! 58      bri2
-	.long	do_IRQ			! 59      txi2
-	.long	do_IRQ			! 60 ADC  adi
+	.long	do_IRQ	! 32 IRQ  irq0
+	.long	do_IRQ	! 33      irq1
+	.long	do_IRQ	! 34      irq2
+	.long	do_IRQ	! 35      irq3
+	.long	do_IRQ	! 36      irq4
+	.long	do_IRQ	! 37      irq5
+	.long	do_IRQ	! 38
+	.long	do_IRQ	! 39
+	.long	do_IRQ	! 40 PINT pint0-7
+	.long	do_IRQ	! 41      pint8-15
+	.long	do_IRQ	! 42
+	.long	do_IRQ	! 43
+	.long	do_IRQ	! 44
+	.long	do_IRQ	! 45
+	.long	do_IRQ	! 46
+	.long	do_IRQ	! 47
+	.long	do_IRQ	! 48 DMAC dei0
+	.long	do_IRQ	! 49      dei1
+	.long	do_IRQ	! 50      dei2
+	.long	do_IRQ	! 51      dei3
+	.long	do_IRQ	! 52 IrDA eri1
+	.long	do_IRQ	! 53      rxi1
+	.long	do_IRQ	! 54      bri1
+	.long	do_IRQ	! 55      txi1
+	.long	do_IRQ	! 56 SCIF eri2
+	.long	do_IRQ	! 57      rxi2
+	.long	do_IRQ	! 58      bri2
+	.long	do_IRQ	! 59      txi2
+	.long	do_IRQ	! 60 ADC  adi
 #if defined(CONFIG_CPU_SUBTYPE_SH7707)
-	.long   do_IRQ			! 61 LCDC lcdi
-	.long   do_IRQ			! 62 PCC  pcc0i
-	.long   do_IRQ			! 63      pcc1i
+	.long   do_IRQ	! 61 LCDC lcdi
+	.long   do_IRQ	! 62 PCC  pcc0i
+	.long   do_IRQ	! 63      pcc1i
 #endif
-#elif defined(__SH4__)
-	.long	do_IRQ			! 32 Hitachi UDI
-	.long	do_IRQ			! 33 GPIO
-	.long	do_IRQ			! 34 DMAC dmte0
-	.long	do_IRQ			! 35      dmte1
-	.long	do_IRQ			! 36      dmte2
-	.long	do_IRQ			! 37      dmte3
-	.long	do_IRQ			! 38      dmae
+#elif defined(CONFIG_CPU_SH4)
+	.long	do_IRQ	! 32 Hitachi UDI
+	.long	do_IRQ	! 33 GPIO
+	.long	do_IRQ	! 34 DMAC dmte0
+	.long	do_IRQ	! 35      dmte1
+	.long	do_IRQ	! 36      dmte2
+	.long	do_IRQ	! 37      dmte3
+	.long	do_IRQ	! 38      dmae
 	.long	error			! 39
-	.long	do_IRQ			! 40 SCIF eri
-	.long	do_IRQ			! 41      rxi
-	.long	do_IRQ			! 42      bri
-	.long	do_IRQ			! 43      txi
+	.long	do_IRQ	! 40 SCIF eri
+	.long	do_IRQ	! 41      rxi
+	.long	do_IRQ	! 42      bri
+	.long	do_IRQ	! 43      txi
 	.long	error			! 44
 	.long	error			! 45
 	.long	error			! 46
@@ -867,14 +868,14 @@
 	.long	error
 	.long	error
 	.long	error
-	.long	do_IRQ			! PCI serr
-	.long	do_IRQ			!     dma3
-	.long	do_IRQ			!     dma2
-	.long	do_IRQ			!     dma1
-	.long	do_IRQ			!     dma0
-	.long	do_IRQ			!     pwon
-	.long	do_IRQ			!     pwdwn
-	.long	do_IRQ			!     err
+	.long	do_IRQ	! PCI serr
+	.long	do_IRQ	!     dma3
+	.long	do_IRQ	!     dma2
+	.long	do_IRQ	!     dma1
+	.long	do_IRQ	!     dma0
+	.long	do_IRQ	!     pwon
+	.long	do_IRQ	!     pwdwn
+	.long	do_IRQ	!     err
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 	.long	error			!  50 0x840
 	.long	error			!  51 0x860
@@ -890,25 +891,25 @@
 	.long	error			!  61 0x9a0
 	.long	error			!  62 0x9c0
 	.long	error			!  63 0x9e0
-	.long	do_IRQ			!  64 0xa00 PCI serr
-	.long	do_IRQ			!  65 0xa20     err
-	.long	do_IRQ			!  66 0xa40     ad
-	.long	do_IRQ			!  67 0xa60     pwr_dwn
+	.long	do_IRQ	!  64 0xa00 PCI serr
+	.long	do_IRQ	!  65 0xa20     err
+	.long	do_IRQ	!  66 0xa40     ad
+	.long	do_IRQ	!  67 0xa60     pwr_dwn
 	.long	error			!  68 0xa80
 	.long	error			!  69 0xaa0
 	.long	error			!  70 0xac0
 	.long	error			!  71 0xae0
-	.long	do_IRQ			!  72 0xb00 DMA INT0
-	.long	do_IRQ			!  73 0xb20     INT1
-	.long	do_IRQ			!  74 0xb40     INT2
-	.long	do_IRQ			!  75 0xb60     INT3
-	.long	do_IRQ			!  76 0xb80     INT4
+	.long	do_IRQ	!  72 0xb00 DMA INT0
+	.long	do_IRQ	!  73 0xb20     INT1
+	.long	do_IRQ	!  74 0xb40     INT2
+	.long	do_IRQ	!  75 0xb60     INT3
+	.long	do_IRQ	!  76 0xb80     INT4
 	.long	error			!  77 0xba0
-	.long	do_IRQ			!  78 0xbc0 DMA ERR
+	.long	do_IRQ	!  78 0xbc0 DMA ERR
 	.long	error			!  79 0xbe0
-	.long	do_IRQ			!  80 0xc00 PIO0
-	.long	do_IRQ			!  81 0xc20 PIO1
-	.long	do_IRQ			!  82 0xc40 PIO2
+	.long	do_IRQ	!  80 0xc00 PIO0
+	.long	do_IRQ	!  81 0xc20 PIO1
+	.long	do_IRQ	!  82 0xc40 PIO2
 	.long	error			!  83 0xc60
 	.long	error			!  84 0xc80
 	.long	error			!  85 0xca0
@@ -938,7 +939,7 @@
 	.long	error			! 109 0xfa0
 	.long	error			! 110 0xfc0
 	.long	error			! 111 0xfe0
-	.long	do_IRQ			! 112 0x1000 Mailbox
+	.long	do_IRQ	! 112 0x1000 Mailbox
 	.long	error			! 113 0x1020
 	.long	error			! 114 0x1040
 	.long	error			! 115 0x1060
@@ -966,7 +967,7 @@
 	.long	error			! 137 0x1320
 	.long	error			! 138 0x1340
 	.long	error			! 139 0x1360
-	.long	do_IRQ			! 140 0x1380 EMPI INV_ADDR
+	.long	do_IRQ	! 140 0x1380 EMPI INV_ADDR
 	.long	error			! 141 0x13a0
 	.long	error			! 142 0x13c0
 	.long	error			! 143 0x13e0
@@ -983,7 +984,7 @@
 	.long sys_waitpid
 	.long sys_creat
 	.long sys_link
-	.long sys_unlink	/* 10 */
+	.long sys_unlink		/* 10 */
 	.long sys_execve
 	.long sys_chdir
 	.long sys_time
@@ -993,7 +994,7 @@
 	.long sys_ni_syscall	/* old break syscall holder */
 	.long sys_stat
 	.long sys_lseek
-	.long sys_getpid	/* 20 */
+	.long sys_getpid		/* 20 */
 	.long sys_mount
 	.long sys_oldumount
 	.long sys_setuid16
@@ -1025,7 +1026,7 @@
 	.long sys_geteuid16
 	.long sys_getegid16	/* 50 */
 	.long sys_acct
-	.long sys_umount	/* recycled never used phys() */
+	.long sys_umount		/* recycled never used phys() */
 	.long sys_ni_syscall	/* old lock syscall holder */
 	.long sys_ioctl
 	.long sys_fcntl		/* 55 */
@@ -1038,7 +1039,7 @@
 	.long sys_ustat
 	.long sys_dup2
 	.long sys_getppid
-	.long sys_getpgrp	/* 65 */
+	.long sys_getpgrp		/* 65 */
 	.long sys_setsid
 	.long sys_sigaction
 	.long sys_sgetmask
@@ -1058,7 +1059,7 @@
 	.long sys_ni_syscall	/* sys_oldselect */
 	.long sys_symlink
 	.long sys_lstat
-	.long sys_readlink	/* 85 */
+	.long sys_readlink		/* 85 */
 	.long sys_uselib
 	.long sys_swapon
 	.long sys_reboot
@@ -1068,12 +1069,12 @@
 	.long sys_truncate
 	.long sys_ftruncate
 	.long sys_fchmod
-	.long sys_fchown16	/* 95 */
+	.long sys_fchown16		/* 95 */
 	.long sys_getpriority
 	.long sys_setpriority
 	.long sys_ni_syscall	/* old profil syscall holder */
 	.long sys_statfs
-	.long sys_fstatfs	/* 100 */
+	.long sys_fstatfs		/* 100 */
 	.long sys_ni_syscall	/* ioperm */
 	.long sys_socketcall
 	.long sys_syslog
@@ -1088,7 +1089,7 @@
 	.long sys_ni_syscall	/* idle */
 	.long sys_ni_syscall	/* vm86old */
 	.long sys_wait4
-	.long sys_swapoff	/* 115 */
+	.long sys_swapoff		/* 115 */
 	.long sys_sysinfo
 	.long sys_ipc
 	.long sys_fsync
@@ -1098,12 +1099,12 @@
 	.long sys_newuname
 	.long sys_ni_syscall	/* sys_modify_ldt */
 	.long sys_adjtimex
-	.long sys_mprotect	/* 125 */
+	.long sys_mprotect		/* 125 */
 	.long sys_sigprocmask
-	.long sys_create_module
+	.long sys_ni_syscall	/* old "create_module" */
 	.long sys_init_module
 	.long sys_delete_module
-	.long sys_get_kernel_syms	/* 130 */
+	.long sys_ni_syscall	/* 130: old "get_kernel_syms" */
 	.long sys_quotactl
 	.long sys_getpgid
 	.long sys_fchdir
@@ -1113,7 +1114,7 @@
 	.long sys_ni_syscall	/* for afs_syscall */
 	.long sys_setfsuid16
 	.long sys_setfsgid16
-	.long sys_llseek	/* 140 */
+	.long sys_llseek		/* 140 */
 	.long sys_getdents
 	.long sys_select
 	.long sys_flock
@@ -1140,7 +1141,7 @@
 	.long sys_setresuid16
 	.long sys_getresuid16	/* 165 */
 	.long sys_ni_syscall	/* vm86 */
-	.long sys_query_module
+	.long sys_ni_syscall	/* old "query_module" */
 	.long sys_poll
 	.long sys_nfsservctl
 	.long sys_setresgid16	/* 170 */
@@ -1153,27 +1154,27 @@
 	.long sys_rt_sigtimedwait
 	.long sys_rt_sigqueueinfo
 	.long sys_rt_sigsuspend
-	.long sys_pread		/* 180 */
-	.long sys_pwrite
+	.long sys_pread_wrapper	   /* 180 */
+	.long sys_pwrite_wrapper
 	.long sys_chown16
 	.long sys_getcwd
 	.long sys_capget
-	.long sys_capset	/* 185 */
+	.long sys_capset           /* 185 */
 	.long sys_sigaltstack
 	.long sys_sendfile
 	.long sys_ni_syscall	/* streams1 */
 	.long sys_ni_syscall	/* streams2 */
-	.long sys_vfork		/* 190 */
+	.long sys_vfork            /* 190 */
 	.long sys_getrlimit
 	.long sys_mmap2
 	.long sys_truncate64
 	.long sys_ftruncate64
-	.long sys_stat64	/* 195 */
+	.long sys_stat64		/* 195 */
 	.long sys_lstat64
 	.long sys_fstat64
 	.long sys_lchown
 	.long sys_getuid
-	.long sys_getgid	/* 200 */
+	.long sys_getgid		/* 200 */
 	.long sys_geteuid
 	.long sys_getegid
 	.long sys_setreuid
@@ -1188,23 +1189,61 @@
 	.long sys_chown
 	.long sys_setuid
 	.long sys_setgid
-	.long sys_setfsuid	/* 215 */
+	.long sys_setfsuid		/* 215 */
 	.long sys_setfsgid
 	.long sys_pivot_root
 	.long sys_mincore
 	.long sys_madvise
 	.long sys_getdents64	/* 220 */
 	.long sys_fcntl64
+	.long sys_ni_syscall	/* reserved for TUX */
+	.long sys_ni_syscall	/* Reserved for Security */
 	.long sys_gettid
+	.long sys_readahead	/* 225 */
+	.long sys_setxattr
+	.long sys_lsetxattr
+	.long sys_fsetxattr
+	.long sys_getxattr
+	.long sys_lgetxattr	/* 230 */
+	.long sys_fgetxattr
+	.long sys_listxattr
+	.long sys_llistxattr
+	.long sys_flistxattr
+	.long sys_removexattr	/* 235 */
+	.long sys_lremovexattr
+	.long sys_fremovexattr
 	.long sys_tkill
+	.long sys_sendfile64
+	.long sys_futex		/* 240 */
+	.long sys_sched_setaffinity
+	.long sys_sched_getaffinity
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_io_setup	/* 245 */
+	.long sys_io_destroy
+	.long sys_io_getevents
+	.long sys_io_submit
+	.long sys_io_cancel
+	.long sys_fadvise64	/* 250 */
+	.long sys_ni_syscall
+	.long sys_exit_group
+	.long sys_lookup_dcookie
+	.long sys_epoll_create
+	.long sys_epoll_ctl	/* 255 */
+	.long sys_epoll_wait
+ 	.long sys_remap_file_pages
+ 	.long sys_set_tid_address
+ 	.long sys_timer_create
+ 	.long sys_timer_settime		/* 260 */
+ 	.long sys_timer_gettime
+ 	.long sys_timer_getoverrun
+ 	.long sys_timer_delete
+ 	.long sys_clock_settime
+ 	.long sys_clock_gettime		/* 265 */
+ 	.long sys_clock_getres
+ 	.long sys_clock_nanosleep
 
-	/*
-	 * NOTE!! This doesn't have to be exact - we just have
-	 * to make sure we have _enough_ of the "sys_ni_syscall"
-	 * entries. Don't panic if you notice that this hasn't
-	 * been shrunk every time we add a new system call.
-	 */
-	.rept NR_syscalls-221
+	.rept NR_syscalls-(.-sys_call_table)/4
 		.long sys_ni_syscall
 	.endr
 
diff -urN linux-2.5.73-bk9/arch/sh/kernel/head.S linux-2.5.73-bk10/arch/sh/kernel/head.S
--- linux-2.5.73-bk9/arch/sh/kernel/head.S	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/head.S	2003-07-02 04:57:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.17 2000/03/06 12:44:24 gniibe Exp $
+/* $Id: head.S,v 1.6 2003/05/04 19:29:53 lethal Exp $
  *
  *  arch/sh/kernel/head.S
  *
@@ -48,7 +48,7 @@
 	mov	#0x20, r1	!
 	shll8	r1		! r1 = 8192
 	sub	r1, r0		!
-	ldc	r0, r7_bank	! ... and init_task
+	ldc	r0, r7_bank	! ... and initial thread_info
 	!
 	!			Enable cache
 	mov.l	6f, r0
@@ -73,4 +73,4 @@
 3:	.long	__bss_start
 4:	.long	_end
 5:	.long	start_kernel
-6:	.long	cache_init
+6:	.long	sh_cache_init
diff -urN linux-2.5.73-bk9/arch/sh/kernel/init_task.c linux-2.5.73-bk10/arch/sh/kernel/init_task.c
--- linux-2.5.73-bk9/arch/sh/kernel/init_task.c	2003-06-22 11:32:34.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/init_task.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,6 +1,5 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/init.h>
 #include <linux/init_task.h>
 
 #include <asm/uaccess.h>
@@ -8,16 +7,24 @@
 
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
- * Initial task structure.
+ * Initial thread structure.
  *
  * We need to make sure that this is 8192-byte aligned due to the
  * way process stacks are handled. This is done by having a special
  * "init_task" linker map entry..
  */
-union task_union init_task_union 
+union thread_union init_thread_union 
 	__attribute__((__section__(".data.init_task"))) =
-		{ INIT_TASK(init_task_union.task) };
+		{ INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
diff -urN linux-2.5.73-bk9/arch/sh/kernel/irq.c linux-2.5.73-bk10/arch/sh/kernel/irq.c
--- linux-2.5.73-bk9/arch/sh/kernel/irq.c	2003-06-22 11:32:41.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/irq.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.21 2001/07/17 02:26:53 gniibe Exp $
+/* $Id: irq.c,v 1.12 2003/06/28 15:34:55 lethal Exp $
  *
  * linux/arch/sh/kernel/irq.c
  *
@@ -51,7 +51,8 @@
  * Special irq handlers.
  */
 
-void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{ return IRQ_NONE; }
 
 /*
  * Generic no controller code
@@ -96,8 +97,9 @@
 	unsigned long flags;
 
 	seq_puts(p, "           ");
-	for (j=0; j<smp_num_cpus; j++)
-		seq_printf(p, "CPU%d       ",j);
+	for (j=0; j<NR_CPUS; j++)
+		if (cpu_online(j))
+			seq_printf(p, "CPU%d       ",j);
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
@@ -129,26 +131,37 @@
  */
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
-	int status;
-	int cpu = smp_processor_id();
-
-	irq_enter(cpu, irq);
-
-	status = 1;	/* Force the "do bottom halves" bit */
+	int status = 1;	/* Force the "do bottom halves" bit */
+	int retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
 		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		retval |= action->handler(irq, action->dev_id, regs);
 		action = action->next;
 	} while (action);
+
 	if (status & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
+
 	local_irq_disable();
 
-	irq_exit(cpu, irq);
+	if (retval != 1) {
+		static int count = 100;
+
+		if (count) {
+			count--;
+
+			if (retval) {
+				printk("irq event %d: bogus retval mask %x\n",
+					irq, retval);
+			} else {
+				printk("irq %d: nobody cared\n", irq);
+			}
+		}
+	}
 
 	return status;
 }
@@ -159,7 +172,7 @@
  * hardware disable after having gotten the irq
  * controller lock. 
  */
-void disable_irq_nosync(unsigned int irq)
+inline void disable_irq_nosync(unsigned int irq)
 {
 	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
@@ -179,12 +192,7 @@
 void disable_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-
-	if (!local_irq_count(smp_processor_id())) {
-		do {
-			barrier();
-		} while (irq_desc[irq].status & IRQ_INPROGRESS);
-	}
+	synchronize_irq(irq);
 }
 
 void enable_irq(unsigned int irq)
@@ -237,6 +245,8 @@
 	struct irqaction * action;
 	unsigned int status;
 
+	irq_enter();
+
 	/* Get IRQ number */
 	asm volatile("stc	r2_bank, %0\n\t"
 		     "shlr2	%0\n\t"
@@ -262,7 +272,7 @@
 	 * use the action we have.
 	 */
 	action = NULL;
-	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+	if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
 		action = desc->action;
 		status &= ~IRQ_PENDING; /* we commit to handling */
 		status |= IRQ_INPROGRESS; /* we are handling it */
@@ -275,7 +285,7 @@
 	   a different instance of this same irq, the other processor
 	   will take care of it.
 	 */
-	if (!action)
+	if (unlikely(!action))
 		goto out;
 
 	/*
@@ -293,11 +303,12 @@
 		handle_IRQ_event(irq, &regs, action);
 		spin_lock(&desc->lock);
 
-		if (!(desc->status & IRQ_PENDING))
+		if (likely(!(desc->status & IRQ_PENDING)))
 			break;
 		desc->status &= ~IRQ_PENDING;
 	}
 	desc->status &= ~IRQ_INPROGRESS;
+
 out:
 	/*
 	 * The ->end() handler has to deal with interrupts which got
@@ -306,13 +317,13 @@
 	desc->handler->end(irq);
 	spin_unlock(&desc->lock);
 
-	if (softirq_pending(cpu))
-		do_softirq();
+	irq_exit();
+
 	return 1;
 }
 
 int request_irq(unsigned int irq, 
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		unsigned long irqflags, 
 		const char * devname,
 		void *dev_id)
@@ -326,7 +337,7 @@
 		return -EINVAL;
 
 	action = (struct irqaction *)
-			kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+			kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
 	if (!action)
 		return -ENOMEM;
 
@@ -370,6 +381,7 @@
 				desc->handler->shutdown(irq);
 			}
 			spin_unlock_irqrestore(&desc->lock,flags);
+			synchronize_irq(irq);
 			kfree(action);
 			return;
 		}
@@ -412,7 +424,7 @@
 
 	/* Wait for longstanding interrupts to trigger. */
 	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
-		/* about 20ms delay */ synchronize_irq();
+		/* about 20ms delay */ barrier();
 
 	/*
 	 * enable any unassigned irqs
@@ -501,7 +513,9 @@
 	unsigned long flags;
 	irq_desc_t *desc = irq_desc + irq;
 
-	/*
+	if (desc->handler == &no_irq_type)
+		return -ENOSYS;
+ 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
 	 * so we have to be careful not to interfere with a
 	 * running system.
@@ -542,7 +556,7 @@
 
 	if (!shared) {
 		desc->depth = 0;
-		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
+		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
 		desc->handler->startup(irq);
 	}
 	spin_unlock_irqrestore(&desc->lock,flags);
@@ -555,3 +569,16 @@
 {
 }
 #endif
+
+/* Taken from the 2.5 alpha port */
+#ifdef CONFIG_SMP
+void synchronize_irq(unsigned int irq)
+{
+	/* is there anything to synchronize with? */
+	if (!irq_desc[irq].action)
+		return;
+
+	while (irq_desc[irq].status & IRQ_INPROGRESS)
+		barrier();
+}
+#endif
diff -urN linux-2.5.73-bk9/arch/sh/kernel/kgdb_jmp.S linux-2.5.73-bk10/arch/sh/kernel/kgdb_jmp.S
--- linux-2.5.73-bk9/arch/sh/kernel/kgdb_jmp.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/kgdb_jmp.S	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,33 @@
+#include <linux/linkage.h>
+
+ENTRY(setjmp)
+	add	#(9*4), r4
+	sts.l	pr, @-r4
+	mov.l	r15, @-r4
+	mov.l	r14, @-r4
+	mov.l	r13, @-r4
+	mov.l	r12, @-r4
+	mov.l	r11, @-r4
+	mov.l	r10, @-r4
+	mov.l	r9, @-r4
+	mov.l	r8, @-r4
+	rts
+	 mov	#0, r0
+
+ENTRY(longjmp)
+	mov.l	@r4+, r8
+	mov.l	@r4+, r9
+	mov.l	@r4+, r10
+	mov.l	@r4+, r11
+	mov.l	@r4+, r12
+	mov.l	@r4+, r13
+	mov.l	@r4+, r14
+	mov.l	@r4+, r15
+	lds.l	@r4+, pr
+	mov	r5, r0
+	tst	r0, r0
+	bf	1f
+	mov	#1, r0	! in case val==0
+1:	rts
+	 nop
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/kgdb_stub.c linux-2.5.73-bk10/arch/sh/kernel/kgdb_stub.c
--- linux-2.5.73-bk9/arch/sh/kernel/kgdb_stub.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/kgdb_stub.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,1491 @@
+/*
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Containes extracts from code by Glenn Engel, Jim Kingdon,
+ * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
+ * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
+ * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
+ * 
+ * This version by Henry Bell <henry.bell@st.com>
+ * Minor modifications by Jeremy Siegel <jsiegel@mvista.com>
+ * 
+ * Contains low-level support for remote debug using GDB. 
+ *
+ * To enable debugger support, two things need to happen. A call to
+ * set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * A breakpoint also needs to be generated to begin communication.  This
+ * is most easily accomplished by a call to breakpoint() which does
+ * a trapa if the initialisation phase has been successfully completed.
+ *
+ * In this case, set_debug_traps() is not used to "take over" exceptions;
+ * other kernel code is modified instead to enter the kgdb functions here
+ * when appropriate (see entry.S for breakpoint traps and NMI interrupts,
+ * see traps.c for kernel error exceptions).
+ *
+ * The following gdb commands are supported:
+ *
+ *    Command       Function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *    XAA..AA,LLLL: Same, but data is binary (not hex)     OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *    CNN;          Resume at current address with signal  SNN
+ *    CNN;AA..AA    Resume at address AA..AA with signal   SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *    SNN;          Step one instruction with signal       SNN
+ *    SNNAA..AA     Step one instruction from AA..AA w/NN  SNN
+ *
+ *    k             kill (Detach GDB)
+ *
+ *    d             Toggle debug flag
+ *    D             Detach GDB 
+ *
+ *    Hct           Set thread t for operations,           OK or ENN
+ *                  c = 'c' (step, cont), c = 'g' (other
+ *                  operations)
+ *
+ *    qC            Query current thread ID                QCpid
+ *    qfThreadInfo  Get list of current threads (first)    m<id>
+ *    qsThreadInfo   "    "  "     "      "   (subsequent)
+ *    qOffsets      Get section offsets                  Text=x;Data=y;Bss=z
+ * 
+ *    TXX           Find if thread XX is alive             OK or ENN
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *    O             Output to GDB console
+ *
+ * Remote communication protocol.
+ *
+ *    A debug packet whose contents are <data> is encapsulated for
+ *    transmission in the form:
+ *
+ *       $ <data> # CSUM1 CSUM2
+ *
+ *       <data> must be ASCII alphanumeric and cannot include characters
+ *       '$' or '#'.  If <data> starts with two characters followed by
+ *       ':', then the existing stubs interpret this as a sequence number.
+ *
+ *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit 
+ *       checksum of <data>, the most significant nibble is sent first.
+ *       the hex digits 0-9,a-f are used.
+ *
+ *    Receiver responds with:
+ *
+ *       +       - if CSUM is correct and ready for next packet
+ *       -       - if CSUM is incorrect
+ *
+ * Responses can be run-length encoded to save space.  A '*' means that
+ * the next character is an ASCII encoding giving a repeat count which
+ * stands for that many repititions of the character preceding the '*'.
+ * The encoding is n+29, yielding a printable character where n >=3 
+ * (which is where RLE starts to win).  Don't use an n > 126. 
+ *
+ * So "0* " means the same as "0000".
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/current.h>
+#include <asm/signal.h>
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+#include <asm/kgdb.h>
+
+#ifdef CONFIG_SH_KGDB_CONSOLE
+#include <linux/console.h>
+#endif
+
+/* Function pointers for linkage */
+kgdb_debug_hook_t *kgdb_debug_hook;
+kgdb_bus_error_hook_t *kgdb_bus_err_hook;
+
+int (*kgdb_getchar)(void);
+void (*kgdb_putchar)(int);
+
+static void put_debug_char(int c)
+{
+	if (!kgdb_putchar)
+		return;
+	(*kgdb_putchar)(c);
+}
+static int get_debug_char(void)
+{
+	if (!kgdb_getchar)
+		return -1;
+	return (*kgdb_getchar)();
+}
+
+/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */
+#define BUFMAX 1024
+#define NUMREGBYTES (MAXREG*4)
+#define OUTBUFMAX (NUMREGBYTES*2+512)
+
+enum regs {
+	R0 = 0, R1,  R2,  R3,   R4,   R5,  R6, R7,
+	R8, R9, R10, R11, R12,  R13,  R14, R15,
+	PC, PR, GBR, VBR, MACH, MACL, SR,
+	/*  */
+	MAXREG
+};
+
+static unsigned int registers[MAXREG];
+struct kgdb_regs trap_registers;
+
+char kgdb_in_gdb_mode;
+char in_nmi;			/* Set during NMI to prevent reentry */
+int kgdb_nofault;		/* Boolean to ignore bus errs (i.e. in GDB) */
+int kgdb_enabled = 1;		/* Default to enabled, cmdline can disable */
+int kgdb_halt;
+
+/* Exposed for user access */
+struct task_struct *kgdb_current;
+unsigned int kgdb_g_imask;
+int kgdb_trapa_val;
+int kgdb_excode;
+
+/* Default values for SCI (can override via kernel args in setup.c) */
+#ifndef CONFIG_KGDB_DEFPORT
+#define CONFIG_KGDB_DEFPORT 1
+#endif
+
+#ifndef CONFIG_KGDB_DEFBAUD
+#define CONFIG_KGDB_DEFBAUD 115200
+#endif
+
+#if defined(CONFIG_KGDB_DEFPARITY_E)
+#define CONFIG_KGDB_DEFPARITY 'E'
+#elif defined(CONFIG_KGDB_DEFPARITY_O)
+#define CONFIG_KGDB_DEFPARITY 'O'
+#else /* CONFIG_KGDB_DEFPARITY_N */
+#define CONFIG_KGDB_DEFPARITY 'N'
+#endif
+
+#ifdef CONFIG_KGDB_DEFBITS_7
+#define CONFIG_KGDB_DEFBITS '7'
+#else /* CONFIG_KGDB_DEFBITS_8 */
+#define CONFIG_KGDB_DEFBITS '8'
+#endif
+
+/* SCI/UART settings, used in kgdb_console_setup() */
+int  kgdb_portnum = CONFIG_KGDB_DEFPORT;
+int  kgdb_baud = CONFIG_KGDB_DEFBAUD;
+char kgdb_parity = CONFIG_KGDB_DEFPARITY;
+char kgdb_bits = CONFIG_KGDB_DEFBITS;
+
+/* Jump buffer for setjmp/longjmp */
+static jmp_buf rem_com_env;
+
+/* TRA differs sh3/4 */
+#if defined(CONFIG_CPU_SH3)
+#define TRA 0xffffffd0
+#elif defined(CONFIG_CPU_SH4)
+#define TRA 0xff000020
+#endif
+
+/* Macros for single step instruction identification */
+#define OPCODE_BT(op)         (((op) & 0xff00) == 0x8900)
+#define OPCODE_BF(op)         (((op) & 0xff00) == 0x8b00)
+#define OPCODE_BTF_DISP(op)   (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
+			      (((op) & 0x7f ) << 1))
+#define OPCODE_BFS(op)        (((op) & 0xff00) == 0x8f00)
+#define OPCODE_BTS(op)        (((op) & 0xff00) == 0x8d00)
+#define OPCODE_BRA(op)        (((op) & 0xf000) == 0xa000)
+#define OPCODE_BRA_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+			      (((op) & 0x7ff) << 1))
+#define OPCODE_BRAF(op)       (((op) & 0xf0ff) == 0x0023)
+#define OPCODE_BRAF_REG(op)   (((op) & 0x0f00) >> 8)
+#define OPCODE_BSR(op)        (((op) & 0xf000) == 0xb000)
+#define OPCODE_BSR_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+			      (((op) & 0x7ff) << 1))
+#define OPCODE_BSRF(op)       (((op) & 0xf0ff) == 0x0003)
+#define OPCODE_BSRF_REG(op)   (((op) >> 8) & 0xf)
+#define OPCODE_JMP(op)        (((op) & 0xf0ff) == 0x402b)
+#define OPCODE_JMP_REG(op)    (((op) >> 8) & 0xf)
+#define OPCODE_JSR(op)        (((op) & 0xf0ff) == 0x400b)
+#define OPCODE_JSR_REG(op)    (((op) >> 8) & 0xf)
+#define OPCODE_RTS(op)        ((op) == 0xb)
+#define OPCODE_RTE(op)        ((op) == 0x2b)
+
+#define SR_T_BIT_MASK           0x1
+#define STEP_OPCODE             0xc320
+#define BIOS_CALL_TRAP          0x3f
+
+/* Exception codes as per SH-4 core manual */
+#define ADDRESS_ERROR_LOAD_VEC   7
+#define ADDRESS_ERROR_STORE_VEC  8
+#define TRAP_VEC                 11
+#define INVALID_INSN_VEC         12
+#define INVALID_SLOT_VEC         13
+#define NMI_VEC                  14
+#define USER_BREAK_VEC           15
+#define SERIAL_BREAK_VEC         58
+
+/* Misc static */
+static int stepped_address;
+static short stepped_opcode;
+static const char hexchars[] = "0123456789abcdef";
+static char in_buffer[BUFMAX];
+static char out_buffer[OUTBUFMAX];
+
+static void kgdb_to_gdb(const char *s);
+
+#ifdef CONFIG_KGDB_THREAD
+static struct task_struct *trapped_thread;
+static struct task_struct *current_thread;
+typedef unsigned char threadref[8];
+#define BUF_THREAD_ID_SIZE 16
+#endif
+
+/* Return addr as a real volatile address */
+static inline unsigned int ctrl_inl(const unsigned long addr)
+{
+	return *(volatile unsigned long *) addr;
+}
+
+/* Correctly set *addr using volatile */
+static inline void ctrl_outl(const unsigned int b, unsigned long addr)
+{
+	*(volatile unsigned long *) addr = b;
+}
+
+/* Get high hex bits */
+static char highhex(const int x)
+{
+	return hexchars[(x >> 4) & 0xf];
+}
+
+/* Get low hex bits */
+static char lowhex(const int x)
+{
+	return hexchars[x & 0xf];
+}
+
+/* Convert ch to hex */
+static int hex(const char ch)
+{
+	if ((ch >= 'a') && (ch <= 'f'))
+		return (ch - 'a' + 10);
+	if ((ch >= '0') && (ch <= '9'))
+		return (ch - '0');
+	if ((ch >= 'A') && (ch <= 'F'))
+		return (ch - 'A' + 10);
+	return (-1);
+}
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+   Returns a pointer to the last char put in buf (null) */
+static char *mem_to_hex(const char *mem, char *buf, const int count)
+{
+	int i;
+	int ch;
+	unsigned short s_val;
+	unsigned long l_val;
+
+	/* Check for 16 or 32 */
+	if (count == 2 && ((long) mem & 1) == 0) {
+		s_val = *(unsigned short *) mem;
+		mem = (char *) &s_val;
+	} else if (count == 4 && ((long) mem & 3) == 0) {
+		l_val = *(unsigned long *) mem;
+		mem = (char *) &l_val;
+	}
+	for (i = 0; i < count; i++) {
+		ch = *mem++;
+		*buf++ = highhex(ch);
+		*buf++ = lowhex(ch);
+	}
+	*buf = 0;
+	return (buf);
+}
+
+/* Convert the hex array pointed to by buf into binary, to be placed in mem.
+   Return a pointer to the character after the last byte written */
+static char *hex_to_mem(const char *buf, char *mem, const int count)
+{
+	int i;
+	unsigned char ch;
+
+	for (i = 0; i < count; i++) {
+		ch = hex(*buf++) << 4;
+		ch = ch + hex(*buf++);
+		*mem++ = ch;
+	}
+	return (mem);
+}
+
+/* While finding valid hex chars, convert to an integer, then return it */
+static int hex_to_int(char **ptr, int *int_value)
+{
+	int num_chars = 0;
+	int hex_value;
+
+	*int_value = 0;
+
+	while (**ptr) {
+		hex_value = hex(**ptr);
+		if (hex_value >= 0) {
+			*int_value = (*int_value << 4) | hex_value;
+			num_chars++;
+		} else
+			break;
+		(*ptr)++;
+	}
+	return num_chars;
+}
+
+/*  Copy the binary array pointed to by buf into mem.  Fix $, #,
+    and 0x7d escaped with 0x7d.  Return a pointer to the character 
+    after the last byte written. */
+static char *ebin_to_mem(const char *buf, char *mem, int count)
+{
+	for (; count > 0; count--, buf++) {
+		if (*buf == 0x7d)
+			*mem++ = *(++buf) ^ 0x20;
+		else
+			*mem++ = *buf;
+	}
+	return mem;
+}
+
+/* Pack a hex byte */
+static char *pack_hex_byte(char *pkt, int byte)
+{
+	*pkt++ = hexchars[(byte >> 4) & 0xf];
+	*pkt++ = hexchars[(byte & 0xf)];
+	return pkt;
+}
+
+#ifdef CONFIG_KGDB_THREAD
+
+/* Pack a thread ID */
+static char *pack_threadid(char *pkt, threadref * id)
+{
+	char *limit;
+	unsigned char *altid;
+
+	altid = (unsigned char *) id;
+
+	limit = pkt + BUF_THREAD_ID_SIZE;
+	while (pkt < limit)
+		pkt = pack_hex_byte(pkt, *altid++);
+	return pkt;
+}
+
+/* Convert an integer into our threadref */
+static void int_to_threadref(threadref * id, const int value)
+{
+	unsigned char *scan = (unsigned char *) id;
+	int i = 4;
+
+	while (i--)
+		*scan++ = 0;
+
+	*scan++ = (value >> 24) & 0xff;
+	*scan++ = (value >> 16) & 0xff;
+	*scan++ = (value >> 8) & 0xff;
+	*scan++ = (value & 0xff);
+}
+
+/* Return a task structure ptr for a particular pid */
+static struct task_struct *get_thread(int pid)
+{
+	struct task_struct *thread;
+
+	/* Use PID_MAX w/gdb for pid 0 */
+	if (pid == PID_MAX) pid = 0;
+
+	/* First check via PID */
+	thread = find_task_by_pid(pid);
+
+	if (thread)
+		return thread;
+
+	/* Start at the start */
+	thread = init_tasks[0];
+
+	/* Walk along the linked list of tasks */
+	do {
+		if (thread->pid == pid)
+			return thread;
+		thread = thread->next_task;
+	} while (thread != init_tasks[0]);
+
+	return NULL;
+}
+
+#endif /* CONFIG_KGDB_THREAD */
+
+/* Scan for the start char '$', read the packet and check the checksum */
+static void get_packet(char *buffer, int buflen)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	int i;
+	int count;
+	char ch;
+
+	do {
+		/* Ignore everything until the start character */
+		while ((ch = get_debug_char()) != '$');
+
+		checksum = 0;
+		xmitcsum = -1;
+		count = 0;
+
+		/* Now, read until a # or end of buffer is found */
+		while (count < (buflen - 1)) {
+			ch = get_debug_char();
+
+			if (ch == '#')
+				break;
+
+			checksum = checksum + ch;
+			buffer[count] = ch;
+			count = count + 1;
+		}
+
+		buffer[count] = 0;
+
+		/* Continue to read checksum following # */
+		if (ch == '#') {
+			xmitcsum = hex(get_debug_char()) << 4;
+			xmitcsum += hex(get_debug_char());
+
+			/* Checksum */
+			if (checksum != xmitcsum)
+				put_debug_char('-');	/* Failed checksum */
+			else {
+				/* Ack successful transfer */
+				put_debug_char('+');
+
+				/* If a sequence char is present, reply 
+				   the sequence ID */
+				if (buffer[2] == ':') {
+					put_debug_char(buffer[0]);
+					put_debug_char(buffer[1]);
+
+					/* Remove sequence chars from buffer */
+					count = strlen(buffer);
+					for (i = 3; i <= count; i++)
+						buffer[i - 3] = buffer[i];
+				}
+			}
+		}
+	}
+	while (checksum != xmitcsum);	/* Keep trying while we fail */
+}
+
+/* Send the packet in the buffer with run-length encoding */
+static void put_packet(char *buffer)
+{
+	int checksum;
+	char *src;
+	int runlen;
+	int encode;
+
+	do {
+		src = buffer;
+		put_debug_char('$');
+		checksum = 0;
+
+		/* Continue while we still have chars left */
+		while (*src) {
+			/* Check for runs up to 99 chars long */
+			for (runlen = 1; runlen < 99; runlen++) {
+				if (src[0] != src[runlen])
+					break;
+			}
+
+			if (runlen > 3) {
+				/* Got a useful amount, send encoding */
+				encode = runlen + ' ' - 4;
+				put_debug_char(*src);   checksum += *src;
+				put_debug_char('*');    checksum += '*';
+				put_debug_char(encode); checksum += encode;
+				src += runlen;
+			} else {
+				/* Otherwise just send the current char */
+				put_debug_char(*src);   checksum += *src;
+				src += 1;
+			}
+		}
+
+		/* '#' Separator, put high and low components of checksum */
+		put_debug_char('#');
+		put_debug_char(highhex(checksum));
+		put_debug_char(lowhex(checksum));
+	}
+	while ((get_debug_char()) != '+');	/* While no ack */
+}
+
+/* A bus error has occurred - perform a longjmp to return execution and
+   allow handling of the error */
+static void kgdb_handle_bus_error(void)
+{
+	longjmp(rem_com_env, 1);
+}
+
+/* Translate SH-3/4 exception numbers to unix-like signal values */
+static int compute_signal(const int excep_code)
+{
+	int sigval;
+
+	switch (excep_code) {
+
+	case INVALID_INSN_VEC:
+	case INVALID_SLOT_VEC:
+		sigval = SIGILL;
+		break;
+	case ADDRESS_ERROR_LOAD_VEC:
+	case ADDRESS_ERROR_STORE_VEC:
+		sigval = SIGSEGV;
+		break;
+
+	case SERIAL_BREAK_VEC:
+	case NMI_VEC:
+		sigval = SIGINT;
+		break;
+
+	case USER_BREAK_VEC:
+	case TRAP_VEC:
+		sigval = SIGTRAP;
+		break;
+
+	default:
+		sigval = SIGBUS;	/* "software generated" */
+		break;
+	}
+
+	return (sigval);
+}
+
+/* Make a local copy of the registers passed into the handler (bletch) */
+static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs,
+				  int *gdb_regs)
+{
+	gdb_regs[R0] = regs->regs[R0];
+	gdb_regs[R1] = regs->regs[R1];
+	gdb_regs[R2] = regs->regs[R2];
+	gdb_regs[R3] = regs->regs[R3];
+	gdb_regs[R4] = regs->regs[R4];
+	gdb_regs[R5] = regs->regs[R5];
+	gdb_regs[R6] = regs->regs[R6];
+	gdb_regs[R7] = regs->regs[R7];
+	gdb_regs[R8] = regs->regs[R8];
+	gdb_regs[R9] = regs->regs[R9];
+	gdb_regs[R10] = regs->regs[R10];
+	gdb_regs[R11] = regs->regs[R11];
+	gdb_regs[R12] = regs->regs[R12];
+	gdb_regs[R13] = regs->regs[R13];
+	gdb_regs[R14] = regs->regs[R14];
+	gdb_regs[R15] = regs->regs[R15];
+	gdb_regs[PC] = regs->pc;
+	gdb_regs[PR] = regs->pr;
+	gdb_regs[GBR] = regs->gbr;
+	gdb_regs[MACH] = regs->mach;
+	gdb_regs[MACL] = regs->macl;
+	gdb_regs[SR] = regs->sr;
+	gdb_regs[VBR] = regs->vbr;
+}
+
+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+static void gdb_regs_to_kgdb_regs(const int *gdb_regs,
+				  struct kgdb_regs *regs)
+{
+	regs->regs[R0] = gdb_regs[R0];
+	regs->regs[R1] = gdb_regs[R1];
+	regs->regs[R2] = gdb_regs[R2];
+	regs->regs[R3] = gdb_regs[R3];
+	regs->regs[R4] = gdb_regs[R4];
+	regs->regs[R5] = gdb_regs[R5];
+	regs->regs[R6] = gdb_regs[R6];
+	regs->regs[R7] = gdb_regs[R7];
+	regs->regs[R8] = gdb_regs[R8];
+	regs->regs[R9] = gdb_regs[R9];
+	regs->regs[R10] = gdb_regs[R10];
+	regs->regs[R11] = gdb_regs[R11];
+	regs->regs[R12] = gdb_regs[R12];
+	regs->regs[R13] = gdb_regs[R13];
+	regs->regs[R14] = gdb_regs[R14];
+	regs->regs[R15] = gdb_regs[R15];
+	regs->pc = gdb_regs[PC];
+	regs->pr = gdb_regs[PR];
+	regs->gbr = gdb_regs[GBR];
+	regs->mach = gdb_regs[MACH];
+	regs->macl = gdb_regs[MACL];
+	regs->sr = gdb_regs[SR];
+	regs->vbr = gdb_regs[VBR];
+}
+
+#ifdef CONFIG_KGDB_THREAD
+/* Make a local copy of registers from the specified thread */
+asmlinkage void ret_from_fork(void);
+static void thread_regs_to_gdb_regs(const struct task_struct *thread,
+				    int *gdb_regs)
+{
+	int regno;
+	int *tregs;
+
+	/* Initialize to zero */
+	for (regno = 0; regno < MAXREG; regno++)
+		gdb_regs[regno] = 0;
+
+	/* Just making sure... */
+	if (thread == NULL)
+		return;
+
+	/* A new fork has pt_regs on the stack from a fork() call */
+	if (thread->thread.pc == (unsigned long)ret_from_fork) {
+
+		int vbr_val;
+		struct pt_regs *kregs;
+		kregs = (struct pt_regs*)thread->thread.sp;
+
+		gdb_regs[R0] = kregs->regs[R0];
+		gdb_regs[R1] = kregs->regs[R1];
+		gdb_regs[R2] = kregs->regs[R2];
+		gdb_regs[R3] = kregs->regs[R3];
+		gdb_regs[R4] = kregs->regs[R4];
+		gdb_regs[R5] = kregs->regs[R5];
+		gdb_regs[R6] = kregs->regs[R6];
+		gdb_regs[R7] = kregs->regs[R7];
+		gdb_regs[R8] = kregs->regs[R8];
+		gdb_regs[R9] = kregs->regs[R9];
+		gdb_regs[R10] = kregs->regs[R10];
+		gdb_regs[R11] = kregs->regs[R11];
+		gdb_regs[R12] = kregs->regs[R12];
+		gdb_regs[R13] = kregs->regs[R13];
+		gdb_regs[R14] = kregs->regs[R14];
+		gdb_regs[R15] = kregs->regs[R15];
+		gdb_regs[PC] = kregs->pc;
+		gdb_regs[PR] = kregs->pr;
+		gdb_regs[GBR] = kregs->gbr;
+		gdb_regs[MACH] = kregs->mach;
+		gdb_regs[MACL] = kregs->macl;
+		gdb_regs[SR] = kregs->sr;
+
+		asm("stc vbr, %0":"=r"(vbr_val));
+		gdb_regs[VBR] = vbr_val;
+		return;
+	}
+
+	/* Otherwise, we have only some registers from switch_to() */
+	tregs = (int *)thread->thread.sp;
+	gdb_regs[R15] = (int)tregs;
+	gdb_regs[R14] = *tregs++;
+	gdb_regs[R13] = *tregs++;
+	gdb_regs[R12] = *tregs++;
+	gdb_regs[R11] = *tregs++;
+	gdb_regs[R10] = *tregs++;
+	gdb_regs[R9] = *tregs++;
+	gdb_regs[R8] = *tregs++;
+	gdb_regs[PR] = *tregs++;
+	gdb_regs[GBR] = *tregs++;
+	gdb_regs[PC] = thread->thread.pc;
+}
+#endif /* CONFIG_KGDB_THREAD */
+
+/* Calculate the new address for after a step */
+static short *get_step_address(void)
+{
+	short op = *(short *) trap_registers.pc;
+	long addr;
+
+	/* BT */
+	if (OPCODE_BT(op)) {
+		if (trap_registers.sr & SR_T_BIT_MASK)
+			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+		else
+			addr = trap_registers.pc + 2;
+	}
+
+	/* BTS */
+	else if (OPCODE_BTS(op)) {
+		if (trap_registers.sr & SR_T_BIT_MASK)
+			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+		else
+			addr = trap_registers.pc + 4;	/* Not in delay slot */
+	}
+
+	/* BF */
+	else if (OPCODE_BF(op)) {
+		if (!(trap_registers.sr & SR_T_BIT_MASK))
+			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+		else
+			addr = trap_registers.pc + 2;
+	}
+
+	/* BFS */
+	else if (OPCODE_BFS(op)) {
+		if (!(trap_registers.sr & SR_T_BIT_MASK))
+			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+		else
+			addr = trap_registers.pc + 4;	/* Not in delay slot */
+	}
+
+	/* BRA */
+	else if (OPCODE_BRA(op))
+		addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
+
+	/* BRAF */
+	else if (OPCODE_BRAF(op))
+		addr = trap_registers.pc + 4
+		    + trap_registers.regs[OPCODE_BRAF_REG(op)];
+
+	/* BSR */
+	else if (OPCODE_BSR(op))
+		addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
+
+	/* BSRF */
+	else if (OPCODE_BSRF(op))
+		addr = trap_registers.pc + 4
+		    + trap_registers.regs[OPCODE_BSRF_REG(op)];
+
+	/* JMP */
+	else if (OPCODE_JMP(op))
+		addr = trap_registers.regs[OPCODE_JMP_REG(op)];
+
+	/* JSR */
+	else if (OPCODE_JSR(op))
+		addr = trap_registers.regs[OPCODE_JSR_REG(op)];
+
+	/* RTS */
+	else if (OPCODE_RTS(op))
+		addr = trap_registers.pr;
+
+	/* RTE */
+	else if (OPCODE_RTE(op))
+		addr = trap_registers.regs[15];
+
+	/* Other */
+	else
+		addr = trap_registers.pc + 2;
+
+	flush_icache_range(addr, addr + 2);
+	return (short *) addr;
+}
+
+/* Set up a single-step.  Replace the instruction immediately after the 
+   current instruction (i.e. next in the expected flow of control) with a
+   trap instruction, so that returning will cause only a single instruction
+   to be executed. Note that this model is slightly broken for instructions
+   with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch
+   and the instruction in the delay slot will be executed. */
+static void do_single_step(void)
+{
+	unsigned short *addr = 0;
+
+	/* Determine where the target instruction will send us to */
+	addr = get_step_address();
+	stepped_address = (int)addr;
+
+	/* Replace it */
+	stepped_opcode = *(short *)addr;
+	*addr = STEP_OPCODE;
+
+	/* Flush and return */
+	flush_icache_range((long) addr, (long) addr + 2);
+	return;
+}
+
+/* Undo a single step */
+static void undo_single_step(void)
+{
+	/* If we have stepped, put back the old instruction */
+	/* Use stepped_address in case we stopped elsewhere */
+	if (stepped_opcode != 0) {
+		*(short*)stepped_address = stepped_opcode;
+		flush_icache_range(stepped_address, stepped_address + 2);
+	}
+	stepped_opcode = 0;
+}
+
+/* Send a signal message */
+static void send_signal_msg(const int signum)
+{
+#ifndef CONFIG_KGDB_THREAD
+	out_buffer[0] = 'S';
+	out_buffer[1] = highhex(signum);
+	out_buffer[2] = lowhex(signum);
+	out_buffer[3] = 0;
+	put_packet(out_buffer);
+#else /* CONFIG_KGDB_THREAD */
+	int threadid;
+	threadref thref;
+	char *out = out_buffer;
+	const char *tstring = "thread";
+
+	*out++ = 'T';
+	*out++ = highhex(signum);
+	*out++ = lowhex(signum);
+
+	while (*tstring) {
+		*out++ = *tstring++;
+	}
+	*out++ = ':';
+
+	threadid = trapped_thread->pid;
+	if (threadid == 0) threadid = PID_MAX;
+	int_to_threadref(&thref, threadid);
+	pack_threadid(out, &thref);
+	out += BUF_THREAD_ID_SIZE;
+	*out++ = ';';
+
+	*out = 0;
+	put_packet(out_buffer);
+#endif /* CONFIG_KGDB_THREAD */
+}
+
+/* Reply that all was well */
+static void send_ok_msg(void)
+{
+	strcpy(out_buffer, "OK");
+	put_packet(out_buffer);
+}
+
+/* Reply that an error occurred */
+static void send_err_msg(void)
+{
+	strcpy(out_buffer, "E01");
+	put_packet(out_buffer);
+}
+
+/* Empty message indicates unrecognised command */
+static void send_empty_msg(void)
+{
+	put_packet("");
+}
+
+/* Read memory due to 'm' message */
+static void read_mem_msg(void)
+{
+	char *ptr;
+	int addr;
+	int length;
+
+	/* Jmp, disable bus error handler */
+	if (setjmp(rem_com_env) == 0) {
+
+		kgdb_nofault = 1;
+
+		/* Walk through, have m<addr>,<length> */
+		ptr = &in_buffer[1];
+		if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
+			if (hex_to_int(&ptr, &length)) {
+				ptr = 0;
+				if (length * 2 > OUTBUFMAX)
+					length = OUTBUFMAX / 2;
+				mem_to_hex((char *) addr, out_buffer, length);
+			}
+		if (ptr)
+			send_err_msg();
+		else
+			put_packet(out_buffer);
+	} else
+		send_err_msg();
+
+	/* Restore bus error handler */
+	kgdb_nofault = 0;
+}
+
+/* Write memory due to 'M' or 'X' message */
+static void write_mem_msg(int binary)
+{
+	char *ptr;
+	int addr;
+	int length;
+
+	if (setjmp(rem_com_env) == 0) {
+
+		kgdb_nofault = 1;
+
+		/* Walk through, have M<addr>,<length>:<data> */
+		ptr = &in_buffer[1];
+		if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
+			if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) {
+				if (binary)
+					ebin_to_mem(ptr, (char*)addr, length);
+				else
+					hex_to_mem(ptr, (char*)addr, length);
+				flush_icache_range(addr, addr + length);
+				ptr = 0;
+				send_ok_msg();
+			}
+		if (ptr)
+			send_err_msg();
+	} else
+		send_err_msg();
+
+	/* Restore bus error handler */
+	kgdb_nofault = 0;
+}
+
+/* Continue message  */
+static void continue_msg(void)
+{
+	/* Try to read optional parameter, PC unchanged if none */
+	char *ptr = &in_buffer[1];
+	int addr;
+
+	if (hex_to_int(&ptr, &addr))
+		trap_registers.pc = addr;
+}
+
+/* Continue message with signal */
+static void continue_with_sig_msg(void)
+{
+	int signal;
+	char *ptr = &in_buffer[1];
+	int addr;
+
+	/* Report limitation */
+	kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n");
+
+	/* Signal */
+	hex_to_int(&ptr, &signal);
+	if (*ptr == ';')
+		ptr++;
+
+	/* Optional address */
+	if (hex_to_int(&ptr, &addr))
+		trap_registers.pc = addr;
+}
+
+/* Step message */
+static void step_msg(void)
+{
+	continue_msg();
+	do_single_step();
+}
+
+/* Step message with signal */
+static void step_with_sig_msg(void)
+{
+	continue_with_sig_msg();
+	do_single_step();
+}
+
+/* Send register contents */
+static void send_regs_msg(void)
+{
+#ifdef CONFIG_KGDB_THREAD
+	if (!current_thread)
+		kgdb_regs_to_gdb_regs(&trap_registers, registers);
+	else
+		thread_regs_to_gdb_regs(current_thread, registers);
+#else
+	kgdb_regs_to_gdb_regs(&trap_registers, registers);
+#endif
+
+	mem_to_hex((char *) registers, out_buffer, NUMREGBYTES);
+	put_packet(out_buffer);
+}
+
+/* Set register contents - currently can't set other thread's registers */
+static void set_regs_msg(void)
+{
+#ifdef CONFIG_KGDB_THREAD
+	if (!current_thread) {
+#endif
+		kgdb_regs_to_gdb_regs(&trap_registers, registers);
+		hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
+		gdb_regs_to_kgdb_regs(registers, &trap_registers);
+		send_ok_msg();
+#ifdef CONFIG_KGDB_THREAD
+	} else
+		send_err_msg();
+#endif
+}
+
+
+#ifdef CONFIG_KGDB_THREAD
+
+/* Set the status for a thread */
+void set_thread_msg(void)
+{
+	int threadid;
+	struct task_struct *thread = NULL;
+	char *ptr;
+
+	switch (in_buffer[1]) {
+
+       	/* To select which thread for gG etc messages, i.e. supported */
+	case 'g':
+
+		ptr = &in_buffer[2];
+		hex_to_int(&ptr, &threadid);
+		thread = get_thread(threadid);
+
+		/* If we haven't found it */
+		if (!thread) {
+			send_err_msg();
+			break;
+		}
+
+		/* Set current_thread (or not) */
+		if (thread == trapped_thread)
+			current_thread = NULL;
+		else
+			current_thread = thread;
+		send_ok_msg();
+		break;
+
+	/* To select which thread for cCsS messages, i.e. unsupported */
+	case 'c':
+		send_ok_msg();
+		break;
+
+	default:
+		send_empty_msg();
+		break;
+	}
+}
+
+/* Is a thread alive? */
+static void thread_status_msg(void)
+{
+	char *ptr;
+	int threadid;
+	struct task_struct *thread = NULL;
+
+	ptr = &in_buffer[1];
+	hex_to_int(&ptr, &threadid);
+	thread = get_thread(threadid);
+	if (thread)
+		send_ok_msg();
+	else
+		send_err_msg();
+}
+/* Send the current thread ID */
+static void thread_id_msg(void)
+{
+	int threadid;
+	threadref thref;
+
+	out_buffer[0] = 'Q';
+	out_buffer[1] = 'C';
+
+	if (current_thread)
+		threadid = current_thread->pid;
+	else if (trapped_thread)
+		threadid = trapped_thread->pid;
+	else /* Impossible, but just in case! */
+	{
+		send_err_msg();
+		return;
+	}
+
+	/* Translate pid 0 to PID_MAX for gdb */
+	if (threadid == 0) threadid = PID_MAX;
+
+	int_to_threadref(&thref, threadid);
+	pack_threadid(out_buffer + 2, &thref);
+	out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0';
+	put_packet(out_buffer);
+}
+
+/* Send thread info */
+static void thread_info_msg(void)
+{
+	struct task_struct *thread = NULL;
+	int threadid;
+	char *pos;
+	threadref thref;
+
+	/* Start with 'm' */
+	out_buffer[0] = 'm';
+	pos = &out_buffer[1];
+
+	/* For all possible thread IDs - this will overrun if > 44 threads! */
+	/* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */
+	for (threadid = 1; threadid <= PID_MAX; threadid++) {
+
+		read_lock(&tasklist_lock);
+		thread = get_thread(threadid);
+		read_unlock(&tasklist_lock);
+
+		/* If it's a valid thread */
+		if (thread) {
+			int_to_threadref(&thref, threadid);
+			pack_threadid(pos, &thref);
+			pos += BUF_THREAD_ID_SIZE;
+			*pos++ = ',';
+		}
+	}
+	*--pos = 0;		/* Lose final comma */
+	put_packet(out_buffer);
+
+}
+
+/* Return printable info for gdb's 'info threads' command */
+static void thread_extra_info_msg(void)
+{
+	int threadid;
+	struct task_struct *thread = NULL;
+	char buffer[20], *ptr;
+	int i;
+
+	/* Extract thread ID */
+	ptr = &in_buffer[17];
+	hex_to_int(&ptr, &threadid);
+	thread = get_thread(threadid);
+
+	/* If we don't recognise it, say so */
+	if (thread == NULL)
+		strcpy(buffer, "(unknown)");
+	else
+		strcpy(buffer, thread->comm);
+
+	/* Construct packet */
+	for (i = 0, ptr = out_buffer; buffer[i]; i++)
+		ptr = pack_hex_byte(ptr, buffer[i]);
+
+	if (thread->thread.pc == (unsigned long)ret_from_fork) {
+		strcpy(buffer, "<new fork>");
+		for (i = 0; buffer[i]; i++)
+			ptr = pack_hex_byte(ptr, buffer[i]);
+	}
+
+	*ptr = '\0';
+	put_packet(out_buffer);
+}
+
+/* Handle all qFooBarBaz messages - have to use an if statement as
+   opposed to a switch because q messages can have > 1 char id. */
+static void query_msg(void)
+{
+	const char *q_start = &in_buffer[1];
+
+	/* qC = return current thread ID */
+	if (strncmp(q_start, "C", 1) == 0)
+		thread_id_msg();
+
+	/* qfThreadInfo = query all threads (first) */
+	else if (strncmp(q_start, "fThreadInfo", 11) == 0)
+		thread_info_msg();
+
+	/* qsThreadInfo = query all threads (subsequent). We know we have sent
+	   them all after the qfThreadInfo message, so there are no to send */
+	else if (strncmp(q_start, "sThreadInfo", 11) == 0)
+		put_packet("l");	/* el = last */
+
+	/* qThreadExtraInfo = supply printable information per thread */
+	else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0)
+		thread_extra_info_msg();
+
+	/* Unsupported - empty message as per spec */
+	else
+		send_empty_msg();
+}
+#endif /* CONFIG_KGDB_THREAD */
+
+/*
+ * Bring up the ports..
+ */
+static int kgdb_serial_setup(void)
+{
+	extern int kgdb_console_setup(struct console *co, char *options);
+	struct console dummy;
+
+	kgdb_console_setup(&dummy, 0);
+
+	return 0;
+}
+
+/* The command loop, read and act on requests */
+static void kgdb_command_loop(const int excep_code, const int trapa_value)
+{
+	int sigval;
+
+	if (excep_code == NMI_VEC) {
+#ifndef CONFIG_KGDB_NMI
+		KGDB_PRINTK("Ignoring unexpected NMI?\n");
+		return;
+#else /* CONFIG_KGDB_NMI */
+		if (!kgdb_enabled) {
+			kgdb_enabled = 1;
+			kgdb_init();
+		}
+#endif /* CONFIG_KGDB_NMI */
+	}
+
+	/* Ignore if we're disabled */
+	if (!kgdb_enabled)
+		return;
+
+#ifdef CONFIG_KGDB_THREAD
+	/* Until GDB specifies a thread */
+	current_thread = NULL;
+	trapped_thread = current;
+#endif
+
+	/* Enter GDB mode (e.g. after detach) */
+	if (!kgdb_in_gdb_mode) {
+		/* Do serial setup, notify user, issue preemptive ack */
+		kgdb_serial_setup();
+		KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n",
+			    (kgdb_porttype ? kgdb_porttype->name : ""),
+			    kgdb_portnum, kgdb_baud);
+		kgdb_in_gdb_mode = 1;
+		put_debug_char('+');
+	}
+
+	/* Reply to host that an exception has occurred */
+	sigval = compute_signal(excep_code);
+	send_signal_msg(sigval);
+
+	/* TRAP_VEC exception indicates a software trap inserted in place of
+	   code by GDB so back up PC by one instruction, as this instruction
+	   will later be replaced by its original one.  Do NOT do this for
+	   trap 0xff, since that indicates a compiled-in breakpoint which
+	   will not be replaced (and we would retake the trap forever) */
+	if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) {
+		trap_registers.pc -= 2;
+	}
+
+	/* Undo any stepping we may have done */
+	undo_single_step();
+
+	while (1) {
+
+		out_buffer[0] = 0;
+		get_packet(in_buffer, BUFMAX);
+
+		/* Examine first char of buffer to see what we need to do */
+		switch (in_buffer[0]) {
+
+		case '?':	/* Send which signal we've received */
+			send_signal_msg(sigval);
+			break;
+
+		case 'g':	/* Return the values of the CPU registers */
+			send_regs_msg();
+			break;
+
+		case 'G':	/* Set the value of the CPU registers */
+			set_regs_msg();
+			break;
+
+		case 'm':	/* Read LLLL bytes address AA..AA */
+			read_mem_msg();
+			break;
+
+		case 'M':	/* Write LLLL bytes address AA..AA, ret OK */
+			write_mem_msg(0);	/* 0 = data in hex */
+			break;
+
+		case 'X':	/* Write LLLL bytes esc bin address AA..AA */
+			if (kgdb_bits == '8')
+				write_mem_msg(1); /* 1 = data in binary */
+			else
+				send_empty_msg();
+			break;
+
+		case 'C':	/* Continue, signum included, we ignore it */
+			continue_with_sig_msg();
+			return;
+
+		case 'c':	/* Continue at address AA..AA (optional) */
+			continue_msg();
+			return;
+
+		case 'S':	/* Step, signum included, we ignore it */
+			step_with_sig_msg();
+			return;
+
+		case 's':	/* Step one instruction from AA..AA */
+			step_msg();
+			return;
+
+#ifdef CONFIG_KGDB_THREAD
+
+		case 'H':	/* Task related */
+			set_thread_msg();
+			break;
+
+		case 'T':	/* Query thread status */
+			thread_status_msg();
+			break;
+
+		case 'q':	/* Handle query - currently thread-related */
+			query_msg();
+			break;
+#endif
+
+		case 'k':	/* 'Kill the program' with a kernel ? */
+			break;
+
+		case 'D':	/* Detach from program, send reply OK */
+			kgdb_in_gdb_mode = 0;
+			send_ok_msg();
+			get_debug_char();
+			return;
+
+		default:
+			send_empty_msg();
+			break;
+		}
+	}
+}
+
+/* There has been an exception, most likely a breakpoint. */
+void kgdb_handle_exception(struct pt_regs *regs)
+{
+	int excep_code, vbr_val;
+	int count;
+	int trapa_value = ctrl_inl(TRA);
+
+	/* Copy kernel regs (from stack) */
+	for (count = 0; count < 16; count++)
+		trap_registers.regs[count] = regs->regs[count];
+	trap_registers.pc = regs->pc;
+	trap_registers.pr = regs->pr;
+	trap_registers.sr = regs->sr;
+	trap_registers.gbr = regs->gbr;
+	trap_registers.mach = regs->mach;
+	trap_registers.macl = regs->macl;
+
+	asm("stc vbr, %0":"=r"(vbr_val));
+	trap_registers.vbr = vbr_val;
+
+	/* Get excode for command loop call, user access */
+	asm("stc r2_bank, %0":"=r"(excep_code));
+	kgdb_excode = excep_code;
+
+	/* Other interesting environment items for reference */
+	asm("stc r6_bank, %0":"=r"(kgdb_g_imask));
+	kgdb_current = current;
+	kgdb_trapa_val = trapa_value;
+
+	/* Act on the exception */
+	kgdb_command_loop(excep_code >> 5, trapa_value);
+
+	kgdb_current = NULL;
+
+	/* Copy back the (maybe modified) registers */
+	for (count = 0; count < 16; count++)
+		regs->regs[count] = trap_registers.regs[count];
+	regs->pc = trap_registers.pc;
+	regs->pr = trap_registers.pr;
+	regs->sr = trap_registers.sr;
+	regs->gbr = trap_registers.gbr;
+	regs->mach = trap_registers.mach;
+	regs->macl = trap_registers.macl;
+
+	vbr_val = trap_registers.vbr;
+	asm("ldc %0, vbr": :"r"(vbr_val));
+
+	return;
+}
+
+/* Trigger a breakpoint by function */
+void breakpoint(void)
+{
+	if (!kgdb_enabled) {
+		kgdb_enabled = 1;
+		kgdb_init();
+	}
+	BREAKPOINT();
+}
+
+/* Initialise the KGDB data structures and serial configuration */
+int kgdb_init(void)
+{
+	if (!kgdb_enabled)
+		return 1;
+
+	in_nmi = 0;
+	kgdb_nofault = 0;
+	stepped_opcode = 0;
+	kgdb_in_gdb_mode = 0;
+
+	if (kgdb_serial_setup() != 0) {
+		KGDB_PRINTK("serial setup error\n");
+		return -1;
+	}
+
+	/* Init ptr to exception handler */
+	kgdb_debug_hook = kgdb_handle_exception;
+	kgdb_bus_err_hook = kgdb_handle_bus_error;
+
+	/* Enter kgdb now if requested, or just report init done */
+	if (kgdb_halt) {
+		kgdb_in_gdb_mode = 1;
+		put_debug_char('+');
+		breakpoint();
+	}
+	else
+	{
+		KGDB_PRINTK("stub is initialized.\n");
+	}
+
+	return 0;
+}
+
+/* Make function available for "user messages"; console will use it too. */
+
+char gdbmsgbuf[BUFMAX];
+#define MAXOUT ((BUFMAX-2)/2)
+
+static void kgdb_msg_write(const char *s, unsigned count)
+{
+	int i;
+	int wcount;
+	char *bufptr;
+
+	/* 'O'utput */
+	gdbmsgbuf[0] = 'O';
+
+	/* Fill and send buffers... */
+	while (count > 0) {
+		bufptr = gdbmsgbuf + 1;
+
+		/* Calculate how many this time */
+		wcount = (count > MAXOUT) ? MAXOUT : count;
+		
+		/* Pack in hex chars */
+		for (i = 0; i < wcount; i++)
+			bufptr = pack_hex_byte(bufptr, s[i]);
+		*bufptr = '\0';
+
+		/* Move up */
+		s += wcount;
+		count -= wcount;
+
+		/* Write packet */
+		put_packet(gdbmsgbuf);
+	}
+}
+
+static void kgdb_to_gdb(const char *s)
+{
+	kgdb_msg_write(s, strlen(s));
+}
+
+#ifdef CONFIG_SH_KGDB_CONSOLE
+void kgdb_console_write(struct console *co, const char *s, unsigned count)
+{
+	/* Bail if we're not talking to GDB */
+	if (!kgdb_in_gdb_mode)
+		return;
+
+	kgdb_msg_write(s, count);
+}
+#endif
diff -urN linux-2.5.73-bk9/arch/sh/kernel/module.c linux-2.5.73-bk10/arch/sh/kernel/module.c
--- linux-2.5.73-bk9/arch/sh/kernel/module.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/module.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,140 @@
+/*  Kernel module help for SH.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+	if (size == 0)
+		return NULL;
+	return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+			      Elf_Shdr *sechdrs,
+			      char *secstrings,
+			      struct module *mod)
+{
+	return 0;
+}
+
+#define COPY_UNALIGNED_WORD(sw, tw, align) \
+{ \
+	void *__s = &(sw), *__t = &(tw); \
+	switch ((align)) \
+	{ \
+	case 0: \
+		*(unsigned long *) __t = *(unsigned long *) __s; \
+		break; \
+	case 2: \
+		*((unsigned short *) __t)++ = *((unsigned short *) __s)++; \
+		*((unsigned short *) __t) = *((unsigned short *) __s); \
+		break; \
+	default: \
+		*((unsigned char *) __t)++ = *((unsigned char *) __s)++; \
+		*((unsigned char *) __t)++ = *((unsigned char *) __s)++; \
+		*((unsigned char *) __t)++ = *((unsigned char *) __s)++; \
+		*((unsigned char *) __t) = *((unsigned char *) __s); \
+		break; \
+	} \
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	Elf32_Addr relocation;
+	uint32_t *location;
+	uint32_t value;
+	int align;
+
+	DEBUGP("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+		relocation = sym->st_value + rel[i].r_addend;
+		align = (int)location & 3;
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_SH_DIR32:
+	    		COPY_UNALIGNED_WORD (*location, value, align);
+			value += relocation;
+	    		COPY_UNALIGNED_WORD (value, *location, align);
+			break;
+		case R_SH_REL32:
+	  		relocation = (relocation - (Elf32_Addr) location);
+	    		COPY_UNALIGNED_WORD (*location, value, align);
+			value += relocation;
+	    		COPY_UNALIGNED_WORD (value, *location, align);
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
+	       me->name);
+	return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	return 0;
+}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/pci-dma.c linux-2.5.73-bk10/arch/sh/kernel/pci-dma.c
--- linux-2.5.73-bk9/arch/sh/kernel/pci-dma.c	2003-06-22 11:33:05.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/pci-dma.c	2003-07-02 04:57:23.000000000 -0700
@@ -26,7 +26,7 @@
 	if (ret != NULL) {
 	        /* Is it necessary to do the memset? */
 		memset(ret, 0, size);
-		*dma_handle = virt_to_bus(ret);
+		*dma_handle = virt_to_phys(ret);
 	}
 	/* We must flush the cache before we pass it on to the device */
 	dma_cache_wback_inv(ret, size);
diff -urN linux-2.5.73-bk9/arch/sh/kernel/pci.c linux-2.5.73-bk10/arch/sh/kernel/pci.c
--- linux-2.5.73-bk9/arch/sh/kernel/pci.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/pci.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,153 @@
+/* arch/sh/kernel/pci.c
+ * $Id: pci.c,v 1.4 2003/05/25 01:29:24 lethal Exp $
+ *
+ * Copyright (c) 2002 M. R. Brown  <mrbrown@linux-sh.org>
+ * 
+ * 
+ * These functions are collected here to reduce duplication of common
+ * code amongst the many platform-specific PCI support code files.
+ * 
+ * These routines require the following board-specific routines:
+ * void pcibios_fixup();
+ * void pcibios_fixup_irqs();
+ *
+ * See include/asm-sh/pci.h for more information.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+static int __init pcibios_init(void)
+{
+	struct pci_channel *p;
+	struct pci_bus *bus;
+	int busno;
+
+#ifdef CONFIG_PCI_AUTO
+	/* assign resources */
+	busno=0;
+	for (p = board_pci_channels; p->pci_ops != NULL; p++) {
+		busno = pciauto_assign_resources(busno, p) + 1;
+	}
+#endif
+
+	/* scan the buses */
+	busno = 0;
+	for (p= board_pci_channels; p->pci_ops != NULL; p++) {
+		bus = pci_scan_bus(busno, p->pci_ops, p);
+		busno = bus->subordinate+1;
+	}
+
+	/* board-specific fixups */
+	pcibios_fixup();
+	pcibios_fixup_irqs();
+
+	return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+void
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			struct resource *res, int resource)
+{
+	u32 new, check;
+	int reg;
+
+	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+	if (resource < 6) {
+		reg = PCI_BASE_ADDRESS_0 + 4*resource;
+	} else if (resource == PCI_ROM_RESOURCE) {
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+		new |= PCI_ROM_ADDRESS_ENABLE;
+		reg = dev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
+	
+	pci_write_config_dword(dev, reg, new);
+	pci_read_config_dword(dev, reg, &check);
+	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+		printk(KERN_ERR "PCI: Error while updating region "
+		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       new, check);
+	}
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+			    unsigned long size, unsigned long align)
+			    __attribute__ ((weak));
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ */
+void pcibios_align_resource(void *data, struct resource *res,
+			    unsigned long size, unsigned long align)
+{
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long start = res->start;
+
+		if (start & 0x300) {
+			start = (start + 0x3ff) & ~0x3ff;
+			res->start = start;
+		}
+	}
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for(idx=0; idx<6; idx++) {
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		cmd |= PCI_COMMAND_MEMORY;
+	if (cmd != old_cmd) {
+		printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", dev->dev.name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+/*
+ *  If we set up a device for bus mastering, we need to check and set
+ *  the latency timer as it may not be properly set.
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+	u8 lat;
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+	if (lat < 16)
+		lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+	else if (lat > pcibios_max_latency)
+		lat = pcibios_max_latency;
+	else
+		return;
+	printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", dev->dev.name, lat);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
+
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/pci_auto.c linux-2.5.73-bk10/arch/sh/kernel/pci_auto.c
--- linux-2.5.73-bk9/arch/sh/kernel/pci_auto.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/kernel/pci_auto.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,502 @@
+/*
+ * PCI autoconfiguration library
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * Copyright 2000, 2001 MontaVista Software Inc.
+ * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
+ *
+ * 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.
+ */
+
+/*
+ * Modified for MIPS by Jun Sun, jsun@mvista.com
+ *
+ * . Simplify the interface between pci_auto and the rest: a single function.
+ * . Assign resources from low address to upper address.
+ * . change most int to u32.
+ *
+ * Further modified to include it as mips generic code, ppopov@mvista.com.
+ *
+ * 2001-10-26  Bradley D. LaRonde <brad@ltc.com>
+ * - Add a top_bus argument to the "early config" functions so that
+ *   they can set a fake parent bus pointer to convince the underlying
+ *   pci ops to use type 1 configuration for sub busses.
+ * - Set bridge base and limit registers correctly.
+ * - Align io and memory base properly before and after bridge setup.
+ * - Don't fall through to pci_setup_bars for bridge.
+ * - Reformat the debug output to look more like lspci's output.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#define	DEBUG
+#ifdef 	DEBUG
+#define	DBG(x...)	printk(x)
+#else
+#define	DBG(x...)	
+#endif
+
+/*
+ * These functions are used early on before PCI scanning is done
+ * and all of the pci_dev and pci_bus structures have been created.
+ */
+static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
+	int top_bus, int busnr, int devfn)
+{
+	static struct pci_dev dev;
+	static struct pci_bus bus;
+
+	dev.bus = &bus;
+	dev.sysdata = hose;
+	dev.devfn = devfn;
+	bus.number = busnr;
+	bus.ops = hose->pci_ops;
+
+	if(busnr != top_bus)
+		/* Fake a parent bus structure. */
+		bus.parent = &bus;
+	else
+		bus.parent = NULL;
+
+	return &dev;
+}
+
+#define EARLY_PCI_OP(rw, size, type)					\
+int early_##rw##_config_##size(struct pci_channel *hose,		\
+	int top_bus, int bus, int devfn, int offset, type value)	\
+{									\
+	return pci_##rw##_config_##size(				\
+		fake_pci_dev(hose, top_bus, bus, devfn),		\
+		offset, value);						\
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
+
+static struct resource *io_resource_inuse;
+static struct resource *mem_resource_inuse;
+
+static u32 pciauto_lower_iospc;
+static u32 pciauto_upper_iospc;
+
+static u32 pciauto_lower_memspc;
+static u32 pciauto_upper_memspc;
+
+static void __init 
+pciauto_setup_bars(struct pci_channel *hose,
+		   int top_bus,
+		   int current_bus,
+		   int pci_devfn)
+{
+	u32 bar_response, bar_size, bar_value;
+	u32 bar, addr_mask, bar_nr = 0;
+	u32 * upper_limit;
+	u32 * lower_limit;
+	int found_mem64 = 0;
+
+	for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4) {
+		/* Tickle the BAR and get the response */
+		early_write_config_dword(hose, top_bus,
+					 current_bus,
+					 pci_devfn,
+					 bar,
+					 0xffffffff);
+		early_read_config_dword(hose, top_bus,
+					current_bus,
+					pci_devfn,
+					bar,
+					&bar_response);
+
+		/* If BAR is not implemented go to the next BAR */
+		if (!bar_response)
+			continue;
+
+		/*
+		 * Workaround for a BAR that doesn't use its upper word,
+		 * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457).
+		 * bdl <brad@ltc.com>
+		 */
+		if (!(bar_response & 0xffff0000))
+			bar_response |= 0xffff0000;
+
+retry:
+		/* Check the BAR type and set our address mask */
+		if (bar_response & PCI_BASE_ADDRESS_SPACE) {
+			addr_mask = PCI_BASE_ADDRESS_IO_MASK;
+			upper_limit = &pciauto_upper_iospc;
+			lower_limit = &pciauto_lower_iospc;
+			DBG("        I/O");
+		} else {
+			if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+			    PCI_BASE_ADDRESS_MEM_TYPE_64)
+				found_mem64 = 1;
+
+			addr_mask = PCI_BASE_ADDRESS_MEM_MASK;		
+			upper_limit = &pciauto_upper_memspc;
+			lower_limit = &pciauto_lower_memspc;
+			DBG("        Mem");
+		}
+
+
+		/* Calculate requested size */
+		bar_size = ~(bar_response & addr_mask) + 1;
+
+		/* Allocate a base address */
+		bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size;
+
+		if ((bar_value + bar_size) > *upper_limit) {
+			if (bar_response & PCI_BASE_ADDRESS_SPACE) {
+				if (io_resource_inuse->child) {
+					io_resource_inuse = 
+						io_resource_inuse->child;
+					pciauto_lower_iospc = 
+						io_resource_inuse->start;
+					pciauto_upper_iospc = 
+						io_resource_inuse->end + 1;
+					goto retry;
+				}
+
+			} else {
+				if (mem_resource_inuse->child) {
+					mem_resource_inuse = 
+						mem_resource_inuse->child;
+					pciauto_lower_memspc = 
+						mem_resource_inuse->start;
+					pciauto_upper_memspc = 
+						mem_resource_inuse->end + 1;
+					goto retry;
+				}
+			}
+			DBG(" unavailable -- skipping, value %x size %x\n",
+					bar_value, bar_size);
+			continue;
+		}
+
+		/* Write it out and update our limit */
+		early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+					 bar, bar_value);
+
+		*lower_limit = bar_value + bar_size;
+
+		/*
+		 * If we are a 64-bit decoder then increment to the
+		 * upper 32 bits of the bar and force it to locate
+		 * in the lower 4GB of memory.
+		 */ 
+		if (found_mem64) {
+			bar += 4;
+			early_write_config_dword(hose, top_bus,
+						 current_bus,
+						 pci_devfn,
+						 bar,
+						 0x00000000);
+		}
+
+		DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size);
+
+		bar_nr++;
+	}
+
+}
+
+static void __init
+pciauto_prescan_setup_bridge(struct pci_channel *hose,
+			     int top_bus,
+			     int current_bus,
+			     int pci_devfn,
+			     int sub_bus)
+{
+	/* Configure bus number registers */
+	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+	                        PCI_PRIMARY_BUS, current_bus);
+	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+				PCI_SECONDARY_BUS, sub_bus + 1);
+	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+				PCI_SUBORDINATE_BUS, 0xff);
+
+	/* Align memory and I/O to 1MB and 4KB boundaries. */
+	pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
+		& ~(0x100000 - 1);
+	pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
+		& ~(0x1000 - 1);
+
+	/* Set base (lower limit) of address range behind bridge. */
+	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+		PCI_MEMORY_BASE, pciauto_lower_memspc >> 16);
+	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+		PCI_IO_BASE, (pciauto_lower_iospc & 0x0000f000) >> 8);
+	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+		PCI_IO_BASE_UPPER16, pciauto_lower_iospc >> 16);
+
+	/* We don't support prefetchable memory for now, so disable */
+	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+				PCI_PREF_MEMORY_BASE, 0);
+	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+				PCI_PREF_MEMORY_LIMIT, 0);
+}
+
+static void __init
+pciauto_postscan_setup_bridge(struct pci_channel *hose,
+			      int top_bus,
+			      int current_bus,
+			      int pci_devfn,
+			      int sub_bus)
+{
+	u32 temp;
+
+	pciauto_lower_memspc += 1;
+	pciauto_lower_iospc += 1;
+
+	/* Configure bus number registers */
+	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+				PCI_SUBORDINATE_BUS, sub_bus);
+
+	/* Set upper limit of address range behind bridge. */
+	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+		PCI_MEMORY_LIMIT, pciauto_lower_memspc >> 16);
+	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+		PCI_IO_LIMIT, (pciauto_lower_iospc & 0x0000f000) >> 8);
+	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+		PCI_IO_LIMIT_UPPER16, pciauto_lower_iospc >> 16);
+
+	/* Align memory and I/O to 1MB and 4KB boundaries. */
+	pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
+		& ~(0x100000 - 1);
+	pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
+		& ~(0x1000 - 1);
+
+	/* Enable memory and I/O accesses, enable bus master */
+	early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
+		PCI_COMMAND, &temp);
+	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+		PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY
+		| PCI_COMMAND_MASTER);
+}
+
+static void __init
+pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose,
+                            int top_bus,
+                            int current_bus,
+                            int pci_devfn,
+                            int sub_bus)
+{
+       /* Configure bus number registers */
+       early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+                               PCI_PRIMARY_BUS, current_bus);
+       early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+                               PCI_SECONDARY_BUS, sub_bus + 1);
+       early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+                               PCI_SUBORDINATE_BUS, 0xff);
+
+       /* Align memory and I/O to 4KB and 4 byte boundaries. */
+       pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
+               & ~(0x1000 - 1);
+       pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
+               & ~(0x4 - 1);
+
+       early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+               PCI_CB_MEMORY_BASE_0, pciauto_lower_memspc);
+       early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+               PCI_CB_IO_BASE_0, pciauto_lower_iospc);  
+}
+
+static void __init
+pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
+                             int top_bus,
+                             int current_bus,
+                             int pci_devfn,
+                             int sub_bus)
+{
+       u32 temp;
+
+       /* 
+        * [jsun] we always bump up baselines a little, so that if there 
+        * nothing behind P2P bridge, we don't wind up overlapping IO/MEM 
+        * spaces.
+        */
+       pciauto_lower_memspc += 1;
+       pciauto_lower_iospc += 1;
+
+       /*
+        * Configure subordinate bus number.  The PCI subsystem
+        * bus scan will renumber buses (reserving three additional
+        * for this PCI<->CardBus bridge for the case where a CardBus
+        * adapter contains a P2P or CB2CB bridge.
+        */
+
+       early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+                               PCI_SUBORDINATE_BUS, sub_bus);
+
+       /*
+        * Reserve an additional 4MB for mem space and 16KB for
+        * I/O space.  This should cover any additional space
+        * requirement of unusual CardBus devices with 
+        * additional bridges that can consume more address space.
+        * 
+        * Although pcmcia-cs currently will reprogram bridge
+        * windows, the goal is to add an option to leave them
+        * alone and use the bridge window ranges as the regions
+        * that are searched for free resources upon hot-insertion
+        * of a device.  This will allow a PCI<->CardBus bridge
+        * configured by this routine to happily live behind a
+        * P2P bridge in a system.
+        */
+
+       /* Align memory and I/O to 4KB and 4 byte boundaries. */
+       pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
+               & ~(0x1000 - 1);
+       pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
+               & ~(0x4 - 1);
+       /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+       early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+               PCI_CB_MEMORY_LIMIT_0, pciauto_lower_memspc - 1); 
+       early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+               PCI_CB_IO_LIMIT_0, pciauto_lower_iospc - 1);
+       
+       /* Enable memory and I/O accesses, enable bus master */
+       early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
+               PCI_COMMAND, &temp);
+       early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+               PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY
+               | PCI_COMMAND_MASTER);
+}
+
+#define      PCIAUTO_IDE_MODE_MASK           0x05
+
+static int __init
+pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
+{
+	int sub_bus;
+	u32 pci_devfn, pci_class, cmdstat, found_multi=0;
+	unsigned short vid, did;
+	unsigned char header_type;
+	int devfn_start = 0;
+	int devfn_stop = 0xff;
+
+	sub_bus = current_bus;
+	
+	if (hose->first_devfn)
+		devfn_start = hose->first_devfn;
+	if (hose->last_devfn)
+		devfn_stop = hose->last_devfn;
+	
+	for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
+
+		if (PCI_FUNC(pci_devfn) && !found_multi)
+			continue;
+
+		early_read_config_word(hose, top_bus, current_bus, pci_devfn,
+				       PCI_VENDOR_ID, &vid);
+
+		if (vid == 0xffff) continue;
+
+		early_read_config_byte(hose, top_bus, current_bus, pci_devfn,
+				       PCI_HEADER_TYPE, &header_type);
+
+		if (!PCI_FUNC(pci_devfn))
+			found_multi = header_type & 0x80;
+
+		early_read_config_word(hose, top_bus, current_bus, pci_devfn,
+				       PCI_DEVICE_ID, &did);
+
+		early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
+					PCI_CLASS_REVISION, &pci_class);
+
+		DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x",
+			current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn),
+			pci_class >> 16, vid, did);
+		if (pci_class & 0xff)
+			DBG(" (rev %.2x)", pci_class & 0xff);
+		DBG("\n");
+
+		if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+			DBG("        Bridge: primary=%.2x, secondary=%.2x\n",
+				current_bus, sub_bus + 1);
+			pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
+						     pci_devfn, sub_bus);
+			DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
+				sub_bus + 1,
+				pciauto_lower_iospc, pciauto_lower_memspc);
+			sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
+			DBG("Back to bus %.2x\n", current_bus);
+			pciauto_postscan_setup_bridge(hose, top_bus, current_bus,
+						      pci_devfn, sub_bus);
+			continue;
+                } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) {
+                        DBG("  CARDBUS  Bridge: primary=%.2x, secondary=%.2x\n",
+                                current_bus, sub_bus + 1);
+                        DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
+                        /* Place CardBus Socket/ExCA registers */
+                        pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn);
+ 
+                        pciauto_prescan_setup_cardbus_bridge(hose, top_bus, 
+                                        current_bus, pci_devfn, sub_bus);
+ 
+                        DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
+                                sub_bus + 1,
+                                pciauto_lower_iospc, pciauto_lower_memspc);
+                        sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
+                        DBG("Back to bus %.2x, sub_bus is %x\n", current_bus, sub_bus);
+                        pciauto_postscan_setup_cardbus_bridge(hose, top_bus, 
+                                        current_bus, pci_devfn, sub_bus);
+                        continue;
+		} else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
+
+			unsigned char prg_iface;
+
+			early_read_config_byte(hose, top_bus, current_bus,
+				pci_devfn, PCI_CLASS_PROG, &prg_iface);
+			if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
+				DBG("Skipping legacy mode IDE controller\n");
+				continue;
+			}
+		}
+
+ 		/*
+		 * Found a peripheral, enable some standard
+		 * settings
+		 */
+		early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
+					PCI_COMMAND, &cmdstat);
+		early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+					 PCI_COMMAND, cmdstat | PCI_COMMAND_IO |
+					 PCI_COMMAND_MEMORY |
+					 PCI_COMMAND_MASTER);
+		early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+					PCI_LATENCY_TIMER, 0x80);
+
+		/* Allocate PCI I/O and/or memory space */
+		pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn);
+	}
+	return sub_bus;
+}
+
+int __init
+pciauto_assign_resources(int busno, struct pci_channel *hose)
+{
+	/* setup resource limits */
+	io_resource_inuse = hose->io_resource;
+	mem_resource_inuse = hose->mem_resource;
+
+	pciauto_lower_iospc = io_resource_inuse->start;
+	pciauto_upper_iospc = io_resource_inuse->end + 1;
+	pciauto_lower_memspc = mem_resource_inuse->start;
+	pciauto_upper_memspc = mem_resource_inuse->end + 1;
+	DBG("Autoconfig PCI channel 0x%p\n", hose);
+	DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n",
+		busno, pciauto_lower_iospc, pciauto_upper_iospc, 
+		pciauto_lower_memspc, pciauto_upper_memspc);
+
+	return pciauto_bus_scan(hose, busno, busno);
+}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/process.c linux-2.5.73-bk10/arch/sh/kernel/process.c
--- linux-2.5.73-bk9/arch/sh/kernel/process.c	2003-06-22 11:33:01.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/process.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.35 2001/10/11 09:18:17 gniibe Exp $
+/* $Id: process.c,v 1.17 2003/05/27 21:37:11 lethal Exp $
  *
  *  linux/arch/sh/kernel/process.c
  *
@@ -13,9 +13,11 @@
 
 #include <linux/unistd.h>
 #include <linux/mm.h>
+#include <linux/elfcore.h>
 #include <linux/slab.h>
 #include <linux/a.out.h>
 #include <linux/ptrace.h>
+#include <linux/platform.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -36,16 +38,14 @@
 	hlt_counter--;
 }
 
-/*
- * The idle loop on a uniprocessor i386..
- */ 
-void cpu_idle(void *unused)
+void default_idle(void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
 		if (hlt_counter) {
-			if (need_resched())
-				break;
+			while (1)
+				if (need_resched())
+					break;
 		} else {
 			local_irq_disable();
 			while (!need_resched()) {
@@ -56,10 +56,14 @@
 			local_irq_enable();
 		}
 		schedule();
-		check_pgt_cache();
 	}
 }
 
+void cpu_idle(void *unused)
+{
+	default_idle();
+}
+
 void machine_restart(char * __unused)
 {
 	/* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
@@ -96,17 +100,16 @@
 	       regs->regs[14]);
 	printk("MACH: %08lx MACL: %08lx GBR : %08lx PR  : %08lx\n",
 	       regs->mach, regs->macl, regs->gbr, regs->pr);
-}
 
-struct task_struct * alloc_task_struct(void)
-{
-	/* Get two pages */
-	return (struct task_struct *) __get_free_pages(GFP_KERNEL,1);
-}
+	/*
+	 * If we're in kernel mode, dump the stack too..
+	 */
+	if (!user_mode(regs)) {
+		extern void show_task(unsigned long *sp);
+		unsigned long sp = regs->regs[15];
 
-void free_task_struct(struct task_struct *p)
-{
-	free_pages((unsigned long) p, 1);
+		show_task((unsigned long *)sp);
+	}
 }
 
 /*
@@ -117,29 +120,30 @@
  * This is the mechanism for creating a new kernel thread.
  *
  */
+extern void kernel_thread_helper(void);
+__asm__(".align 5\n"
+	"kernel_thread_helper:\n\t"
+	"jsr	@r5\n\t"
+	" nop\n\t"
+	"mov.l	1f, r1\n\t"
+	"jsr	@r1\n\t"
+	" mov	r0, r4\n\t"
+	".align 2\n\t"
+	"1:.long do_exit");
+
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {	/* Don't use this in BL=1(cli).  Or else, CPU resets! */
-	register unsigned long __sc0 __asm__ ("r0");
-	register unsigned long __sc3 __asm__ ("r3") = __NR_clone;
-	register unsigned long __sc4 __asm__ ("r4") = (long) flags | CLONE_VM | CLONE_UNTRACED;
-	register unsigned long __sc5 __asm__ ("r5") = 0;
-	register unsigned long __sc8 __asm__ ("r8") = (long) arg;
-	register unsigned long __sc9 __asm__ ("r9") = (long) fn;
-
-	__asm__("trapa	#0x12\n\t" 	/* Linux/SH system call */
-		"tst	r0, r0\n\t"	/* child or parent? */
-		"bf	1f\n\t"		/* parent - jump */
-		"jsr	@r9\n\t"	/* call fn */
-		" mov	r8, r4\n\t"	/* push argument */
-		"mov	r0, r4\n\t"	/* return value to arg of exit */
-		"mov	%1, r3\n\t"	/* exit */
-		"trapa	#0x11\n"
-		"1:"
-		: "=z" (__sc0)
-		: "i" (__NR_exit), "r" (__sc3), "r" (__sc4), "r" (__sc5), 
-		  "r" (__sc8), "r" (__sc9)
-		: "memory", "t");
-	return __sc0;
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+	regs.regs[4] = (unsigned long) arg;
+	regs.regs[5] = (unsigned long) fn;
+
+	regs.pc = (unsigned long) kernel_thread_helper;
+	regs.sr = (1 << 30);
+
+	/* Ok, create the new process.. */
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
 
 /*
@@ -152,10 +156,7 @@
 
 void flush_thread(void)
 {
-#if defined(__sh3__)
-	/* do nothing */
-	/* Possibly, set clear debug registers */
-#elif defined(__SH4__)
+#if defined(CONFIG_CPU_SH4)
 	struct task_struct *tsk = current;
 
 	/* Forget lazy FPU state */
@@ -172,24 +173,49 @@
 /* Fill in the fpu structure for a core dump.. */
 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 {
-#if defined(__SH4__)
-	int fpvalid;
+	int fpvalid = 0;
+
+#if defined(CONFIG_CPU_SH4)
 	struct task_struct *tsk = current;
 
 	fpvalid = tsk->used_math;
 	if (fpvalid) {
-		unsigned long flags;
-
-		save_and_cli(flags);
 		unlazy_fpu(tsk);
-		restore_flags(flags);
 		memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
 	}
+#endif
 
 	return fpvalid;
-#else
-	return 0; /* Task didn't use the fpu at all. */
+}
+
+/* 
+ * Capture the user space registers if the task is not running (in user space)
+ */
+int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
+{
+	struct pt_regs ptregs;
+	
+	ptregs = *(struct pt_regs *)
+		((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs));
+	elf_core_copy_regs(regs, &ptregs);
+
+	return 1;
+}
+
+int
+dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu)
+{
+	int fpvalid = 0;
+
+#if defined(CONFIG_CPU_SH4)
+	fpvalid = tsk->used_math;
+	if (fpvalid) {
+		unlazy_fpu(tsk);
+		memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
+	}
 #endif
+
+	return fpvalid;
 }
 
 asmlinkage void ret_from_fork(void);
@@ -199,33 +225,35 @@
 		struct task_struct *p, struct pt_regs *regs)
 {
 	struct pt_regs *childregs;
-#if defined(__SH4__)
-	struct task_struct *tsk = current;
 
-	if (tsk != &init_task) {
-		unsigned long flags;
-
-		save_and_cli(flags);
-		unlazy_fpu(tsk);
-		restore_flags(flags);
-		p->thread.fpu = current->thread.fpu;
-		p->used_math = tsk->used_math;
-	}
-#endif
-	childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1;
+	childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
 	*childregs = *regs;
 
 	if (user_mode(regs)) {
 		childregs->regs[15] = usp;
 	} else {
-		childregs->regs[15] = (unsigned long)p+2*PAGE_SIZE;
+		childregs->regs[15] = (unsigned long)p->thread_info+THREAD_SIZE;
+	}
+        if (clone_flags & CLONE_SETTLS) {
+		childregs->gbr = childregs->regs[0];
 	}
 	childregs->regs[0] = 0; /* Set return value for child */
 	childregs->sr |= SR_FD; /* Invalidate FPU flag */
+	p->set_child_tid = p->clear_child_tid = NULL;
 
 	p->thread.sp = (unsigned long) childregs;
 	p->thread.pc = (unsigned long) ret_from_fork;
 
+#if defined(CONFIG_CPU_SH4)
+	{
+		struct task_struct *tsk = current;
+
+		unlazy_fpu(tsk);
+		p->thread.fpu = tsk->thread.fpu;
+		p->used_math = tsk->used_math;
+		clear_ti_thread_flag(p->thread_info, TIF_USEDFPU);
+	}
+#endif
 	return 0;
 }
 
@@ -253,16 +281,10 @@
  *	switch_to(x,y) should switch tasks from x to y.
  *
  */
-void __switch_to(struct task_struct *prev, struct task_struct *next)
+struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next)
 {
-#if defined(__SH4__)
-	if (prev != &init_task) {
-		unsigned long flags;
-
-		save_and_cli(flags);
-		unlazy_fpu(prev);
-		restore_flags(flags);
-	}
+#if defined(CONFIG_CPU_SH4)
+	unlazy_fpu(prev);
 #endif
 	/*
 	 * Restore the kernel mode register
@@ -270,27 +292,32 @@
 	 */
 	asm volatile("ldc	%0, r7_bank"
 		     : /* no output */
-		     :"r" (next));
+		     : "r" (next->thread_info));
+
+	return prev;
 }
 
 asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
 			unsigned long r6, unsigned long r7,
 			struct pt_regs regs)
 {
-	struct task_struct *p;
-	p = do_fork(SIGCHLD, regs.regs[15], &regs, 0);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+#ifdef CONFIG_MMU
+	return do_fork(SIGCHLD, regs.regs[15], &regs, 0, NULL, NULL);
+#else
+	/* fork almost works, enough to trick you into looking elsewhere :-( */
+	return -EINVAL;
+#endif
 }
 
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 unsigned long r6, unsigned long r7,
+			 unsigned long parent_tidptr,
+			 unsigned long child_tidptr,
 			 struct pt_regs regs)
 {
-	struct task_struct *p;
 	if (!newsp)
 		newsp = regs.regs[15];
-	p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
+			(int *)parent_tidptr, (int *)child_tidptr);
 }
 
 /*
@@ -307,9 +334,8 @@
 			 unsigned long r6, unsigned long r7,
 			 struct pt_regs regs)
 {
-	struct task_struct *p;
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs, 0);
-	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs,
+		       0, NULL, NULL);
 }
 
 /*
@@ -354,7 +380,7 @@
 	/*
 	 * The same comment as on the Alpha applies here, too ...
 	 */
-	pc = thread_saved_pc(&p->thread);
+	pc = thread_saved_pc(p);
 	if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
 		schedule_frame = ((unsigned long *)(long)p->thread.sp)[1];
 		return (unsigned long)((unsigned long *)schedule_frame)[1];
@@ -362,17 +388,6 @@
 	return pc;
 }
 
-asmlinkage void print_syscall(int x)
-{
-	unsigned long flags, sr;
-	asm("stc	sr, %0": "=r" (sr));
-	save_and_cli(flags);
-	printk("%c: %c %c, %c: SYSCALL\n", (x&63)+32,
-	       (current->flags&PF_USEDFPU)?'C':' ',
-	       (init_task.flags&PF_USEDFPU)?'K':' ', (sr&SR_FD)?' ':'F');
-	restore_flags(flags);
-}
-
 asmlinkage void break_point_trap(unsigned long r4, unsigned long r5,
 				 unsigned long r6, unsigned long r7,
 				 struct pt_regs regs)
diff -urN linux-2.5.73-bk9/arch/sh/kernel/ptrace.c linux-2.5.73-bk10/arch/sh/kernel/ptrace.c
--- linux-2.5.73-bk9/arch/sh/kernel/ptrace.c	2003-06-22 11:32:33.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/ptrace.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: ptrace.c,v 1.13 2001/10/01 02:21:50 gniibe Exp $
+/* $Id: ptrace.c,v 1.9 2003/05/06 23:28:47 lethal Exp $
  *
  * linux/arch/sh/kernel/ptrace.c
  *
@@ -19,6 +19,8 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/slab.h>
+#include <linux/security.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -39,7 +41,7 @@
 {
 	unsigned char *stack;
 
-	stack = (unsigned char *)task + THREAD_SIZE - sizeof(struct pt_regs);
+	stack = (unsigned char *)task->thread_info + THREAD_SIZE - sizeof(struct pt_regs);
 	stack += offset;
 	return (*((int *)stack));
 }
@@ -52,7 +54,7 @@
 {
 	unsigned char *stack;
 
-	stack = (unsigned char *)task + THREAD_SIZE - sizeof(struct pt_regs);
+	stack = (unsigned char *)task->thread_info + THREAD_SIZE - sizeof(struct pt_regs);
 	stack += offset;
 	*(unsigned long *) stack = data;
 	return 0;
@@ -122,29 +124,25 @@
 {
 	ctrl_outl(nextpc1, UBC_BARA);
 	ctrl_outb(asid, UBC_BASRA);
-	if(UBC_TYPE_SH7729){
-		ctrl_outl(0x0fff, UBC_BAMRA);
+	ctrl_outl(0, UBC_BAMRA);
+	if(UBC_TYPE_SH7729)
 		ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
-	}else{
-		ctrl_outb(BAMR_12, UBC_BAMRA);
+	else
 		ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
-	}
 
 	if (nextpc2 != (unsigned long) -1) {
 		ctrl_outl(nextpc2, UBC_BARB);
 		ctrl_outb(asid, UBC_BASRB);
-		if(UBC_TYPE_SH7729){
-			ctrl_outl(0x0fff, UBC_BAMRB);
+		ctrl_outl(0, UBC_BAMRB);
+		if(UBC_TYPE_SH7729)
 			ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRB);
-		}else{
-			ctrl_outb(BAMR_12, UBC_BAMRB);
+		else
 			ctrl_outw(BBR_INST | BBR_READ, UBC_BBRB);
-		}
 	}
 	if(UBC_TYPE_SH7729)
-		ctrl_outl(BRCR_PCBA | BRCR_PCBB | BRCR_PCTE, UBC_BRCR);
+		ctrl_outl(BRCR_PCTE, UBC_BRCR);
 	else
-		ctrl_outw(BRCR_PCBA | BRCR_PCBB, UBC_BRCR);
+		ctrl_outw(0, UBC_BRCR);
 }
 
 /*
@@ -159,7 +157,7 @@
 
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
-	struct task_struct *child, *tsk = current;
+	struct task_struct *child;
 	struct user * dummy = NULL;
 	int ret;
 
@@ -169,6 +167,9 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
+		ret = security_ptrace(current->parent, current);
+		if (ret)
+			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
 		ret = 0;
@@ -191,15 +192,11 @@
 		ret = ptrace_attach(child);
 		goto out_tsk;
 	}
-	ret = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
-	if (child->p_pptr != tsk)
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0)
 		goto out_tsk;
+
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
@@ -279,9 +276,9 @@
 		if ((unsigned long) data > _NSIG)
 			break;
 		if (request == PTRACE_SYSCALL)
-			child->ptrace |= PT_TRACESYS;
+			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		else
-			child->ptrace &= ~PT_TRACESYS;
+			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		child->exit_code = data;
 		wake_up_process(child);
 		ret = 0;
@@ -312,7 +309,7 @@
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
-		child->ptrace &= ~PT_TRACESYS;
+		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		if ((child->ptrace & PT_DTRACE) == 0) {
 			/* Spurious delayed TF traps may occur */
 			child->ptrace |= PT_DTRACE;
@@ -320,7 +317,7 @@
 
 		/* Compute next pc.  */
 		pc = get_stack_long(child, (long)&dummy->pc);
-		regs = (struct pt_regs *)((unsigned long)child + THREAD_SIZE - sizeof(struct pt_regs));
+		regs = (struct pt_regs *)(THREAD_SIZE + (unsigned long)child->thread_info) - 1;
 		if (access_process_vm(child, pc&~3, &tmp, sizeof(tmp), 0) != sizeof(tmp))
 			break;
  
@@ -335,15 +332,17 @@
 		else
 			insn = tmp >> 16;
 #endif
-		compute_next_pc (regs, insn, &nextpc1, &nextpc2);
+		compute_next_pc(regs, insn, &nextpc1, &nextpc2);
 
 		if (nextpc1 & 0x80000000)
 			break;
 		if (nextpc2 != (unsigned long) -1 && (nextpc2 & 0x80000000))
 			break;
 
+#ifdef CONFIG_MMU
 		ubc_set_tracing(child->mm->context & MMU_CONTEXT_ASID_MASK,
 				nextpc1, nextpc2);
+#endif
 
 		child->exit_code = data;
 		/* give it a chance to run. */
@@ -356,31 +355,38 @@
 		ret = ptrace_detach(child, data);
 		break;
 
+	case PTRACE_SETOPTIONS:
+		if (data & PTRACE_O_TRACESYSGOOD)
+			child->ptrace |= PT_TRACESYSGOOD;
+		else
+			child->ptrace &= ~PT_TRACESYSGOOD;
+		ret = 0;
+		break;
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
 out_tsk:
-	free_task_struct(child);
+	put_task_struct(child);
 out:
 	unlock_kernel();
 	return ret;
 }
 
-asmlinkage void syscall_trace(void)
+asmlinkage void do_syscall_trace(void)
 {
 	struct task_struct *tsk = current;
 
-	if ((tsk->ptrace & (PT_PTRACED|PT_TRACESYS))
-	    != (PT_PTRACED|PT_TRACESYS))
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return;
+	if (!(tsk->ptrace & PT_PTRACED))
 		return;
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
-	tsk->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-				    ? 0x80 : 0);
-	tsk->state = TASK_STOPPED;
-	notify_parent(tsk, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
+
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff -urN linux-2.5.73-bk9/arch/sh/kernel/semaphore.c linux-2.5.73-bk10/arch/sh/kernel/semaphore.c
--- linux-2.5.73-bk9/arch/sh/kernel/semaphore.c	2003-06-22 11:33:07.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/semaphore.c	2003-07-02 04:57:23.000000000 -0700
@@ -7,6 +7,7 @@
  * specific changes in <asm/semaphore-helper.h>
  */
 
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <asm/semaphore.h>
diff -urN linux-2.5.73-bk9/arch/sh/kernel/setup.c linux-2.5.73-bk10/arch/sh/kernel/setup.c
--- linux-2.5.73-bk9/arch/sh/kernel/setup.c	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/setup.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,9 +1,9 @@
-/* $Id: setup.c,v 1.31 2001/08/23 16:36:40 dwmw2 Exp $
+/* $Id: setup.c,v 1.17 2003/05/20 01:51:37 lethal Exp $
  *
  *  linux/arch/sh/kernel/setup.c
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *
+ *  Copyright (C) 2002, 2003  Paul Mundt
  */
 
 /*
@@ -30,7 +30,10 @@
 #include <linux/console.h>
 #include <linux/ctype.h>
 #include <linux/seq_file.h>
+#include <linux/utsname.h>
 #include <linux/root_dev.h>
+#include <linux/utsname.h>
+#include <linux/cpu.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -43,6 +46,11 @@
 #include <asm/sh_bios.h>
 #endif
 
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+static int kgdb_parse_options(char *options);
+#endif
+
 /*
  * Machine setup..
  */
@@ -55,8 +63,9 @@
 struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, };
 struct screen_info screen_info;
 unsigned char aux_device_present = 0xaa;
+static int fpu_disabled __initdata = 0;
 
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
+#if defined(CONFIG_SH_UNKNOWN)
 struct sh_machine_vector sh_mv;
 #endif
 
@@ -74,6 +83,8 @@
 };
 
 extern void fpu_init(void);
+extern void platform_setup(void);
+extern char *get_system_type(void);
 extern int root_mountflags;
 extern int _text, _etext, _edata, _end;
 
@@ -129,6 +140,77 @@
 
 unsigned long memory_start, memory_end;
 
+/* XXX: MRB-remove - blatant hack */
+#if 1
+#define SCIF_REG	0xffe80000
+
+static void scif_sercon_putc(int c)
+{
+	while (!(ctrl_inw(SCIF_REG + 0x10) & 0x20)) ;
+
+	ctrl_outb(c, SCIF_REG + 12);
+	ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0x9f), SCIF_REG + 0x10);
+
+	if (c == '\n')
+		scif_sercon_putc('\r');
+}
+
+static void scif_sercon_flush(void)
+{
+	ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
+
+	while (!(ctrl_inw(SCIF_REG + 0x10) & 0x40)) ;
+
+	ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
+}
+
+static void scif_sercon_write(struct console *con, const char *s, unsigned count)
+{
+	while (count-- > 0)
+		scif_sercon_putc(*s++);
+
+	scif_sercon_flush();
+}
+
+static int __init scif_sercon_setup(struct console *con, char *options)
+{
+	con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8;
+
+	return 0;
+}
+
+static struct console scif_sercon = {
+	.name		= "sercon",
+	.write		= scif_sercon_write,
+	.setup		= scif_sercon_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+};
+
+void scif_sercon_init(int baud)
+{
+	ctrl_outw(0, SCIF_REG + 8);
+	ctrl_outw(0, SCIF_REG);
+
+	/* Set baud rate */
+	ctrl_outb((50000000 / (32 * baud)) - 1, SCIF_REG + 4);
+
+	ctrl_outw(12, SCIF_REG + 24);
+	ctrl_outw(8, SCIF_REG + 24);
+	ctrl_outw(0, SCIF_REG + 32);
+	ctrl_outw(0x60, SCIF_REG + 16);
+	ctrl_outw(0, SCIF_REG + 36);
+	ctrl_outw(0x30, SCIF_REG + 8);
+
+	register_console(&scif_sercon);
+}
+
+void scif_sercon_unregister(void)
+{
+	unregister_console(&scif_sercon);
+}
+#endif
+
 #ifdef CONFIG_SH_EARLY_PRINTK
 /*
  *	Print a string through the BIOS
@@ -253,7 +335,7 @@
 
 void __init setup_arch(char **cmdline_p)
 {
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
+#if defined(CONFIG_SH_UNKNOWN)
 	extern struct sh_machine_vector mv_unknown;
 #endif
 	struct sh_machine_vector *mv = NULL;
@@ -263,6 +345,10 @@
 	unsigned long bootmap_size;
 	unsigned long start_pfn, max_pfn, max_low_pfn;
 
+/* XXX: MRB-remove */
+#if 0
+	scif_sercon_init(115200);
+#endif
 #ifdef CONFIG_SH_EARLY_PRINTK
 	sh_console_init();
 #endif
@@ -289,6 +375,10 @@
 
 	parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
 
+#ifdef CONFIG_CMDLINE_BOOL
+	sprintf(*cmdline_p, CONFIG_CMDLINE);
+#endif
+
 #ifdef CONFIG_SH_GENERIC
 	if (mv == NULL) {
 		mv = &mv_unknown;
@@ -303,7 +393,7 @@
 	sh_mv = mv_unknown;
 #endif
 
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
+#if defined(CONFIG_SH_UNKNOWN)
 	if (mv_io_base != 0) {
 		sh_mv.mv_inb = generic_inb;
 		sh_mv.mv_inw = generic_inw;
@@ -378,7 +468,6 @@
 	bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
 					 __MEMORY_START>>PAGE_SHIFT,
 					 max_low_pfn);
-
 	/*
 	 * Register fully available low RAM pages with the bootmem allocator.
 	 */
@@ -435,23 +524,6 @@
 	}
 #endif
 
-#if 0
-	/*
-	 * Request the standard RAM and ROM resources -
-	 * they eat up PCI memory space
-	 */
-	request_resource(&iomem_resource, ram_resources+0);
-	request_resource(&iomem_resource, ram_resources+1);
-	request_resource(&iomem_resource, ram_resources+2);
-	request_resource(ram_resources+1, &code_resource);
-	request_resource(ram_resources+1, &data_resource);
-	probe_roms();
-
-	/* request I/O space for devices used on all i[345]86 PCs */
-	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
-		request_resource(&ioport_resource, standard_io_resources+i);
-#endif
-
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
@@ -461,15 +533,31 @@
 #endif
 
 	/* Perform the machine specific initialisation */
-	if (sh_mv.mv_init_arch != NULL) {
-		sh_mv.mv_init_arch();
+	platform_setup();
+
+#if defined(CONFIG_CPU_SH4)
+	/* FPU initialization */
+	clear_thread_flag(TIF_USEDFPU);
+	current->used_math = 0;
+#endif
+
+	/* Disable the FPU */
+	if (fpu_disabled) {
+		printk("FPU Disabled\n");
+		cpu_data->flags &= ~CPU_HAS_FPU;
+		release_fpu();
 	}
 
-#if defined(__SH4__)
-	/* We already grab/initialized FPU in head.S.  Make it consisitent. */
-	init_task.used_math = 1;
-	init_task.flags |= PF_USEDFPU;
+#ifdef CONFIG_UBC_WAKEUP
+	/*
+	 * Some brain-damaged loaders decided it would be a good idea to put
+	 * the UBC to sleep. This causes some issues when it comes to things
+	 * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB.  So ..
+	 * we wake it up and hope that all is well.
+	 */
+	ubc_wakeup();
 #endif
+
 	paging_init();
 }
 
@@ -488,52 +576,109 @@
 		struct sh_machine_vector *mv = &all_vecs[i];
 		if (mv == NULL)
 			continue;
-		if (strcasecmp(name, mv->mv_name) == 0) {
+		if (strcasecmp(name, get_system_type()) == 0) {
 			return mv;
 		}
 	}
 	return NULL;
 }
 
+static struct cpu cpu[NR_CPUS];
+
+static int __init topology_init(void)
+{
+	int cpu_id;
+
+	for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
+		if (cpu_possible(cpu_id))
+			register_cpu(&cpu[cpu_id], cpu_id, NULL);
+
+	return 0;
+}
+
+subsys_initcall(topology_init);
+
+static const char *cpu_name[] = {
+	[CPU_SH7604]	"SH7604",
+	[CPU_SH7708]	"SH7708",
+	[CPU_SH7729]	"SH7729",
+	[CPU_SH7750]	"SH7750",
+	[CPU_SH7750S]	"SH7750S",
+	[CPU_SH7750R]	"SH7750R",
+	[CPU_SH7751]	"SH7751",
+	[CPU_SH7751R]	"SH7751R",
+	[CPU_ST40RA]	"ST40RA",
+	[CPU_ST40GX1]	"ST40GX1",
+	[CPU_SH_NONE]	"Unknown"
+};
+
+const char *get_cpu_subtype(void)
+{
+	return cpu_name[boot_cpu_data.type];
+}
+
 /*
  *	Get CPU information for use by the procfs.
  */
 #ifdef CONFIG_PROC_FS
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-#if defined(__sh3__)
-	seq_printf(m, "cpu family\t: SH-3\n"
-		      "cache size\t: 8K-byte\n");
-#elif defined(__SH4__)
-	seq_printf(m, "cpu family\t: SH-4\n"
-		      "cache size\t: 8K-byte/16K-byte\n");
-#endif
-	seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
+	unsigned int dcachesz, icachesz;
+	unsigned int cpu = smp_processor_id();
+
+	icachesz = boot_cpu_data.icache.ways *
+		   boot_cpu_data.icache.sets *
+		   boot_cpu_data.icache.linesz;
+
+	if (!cpu && cpu_online(cpu))
+		seq_printf(m, "machine\t\t: %s\n", get_system_type());
+
+	seq_printf(m, "processor\t: %d\n", cpu);
+	seq_printf(m, "cpu family\t: %s\n", system_utsname.machine);
+	seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype());
+	seq_printf(m, "cache size\t: %dK-bytes", icachesz >> 10);
+
+	/*
+	 * SH-2 and SH-3 have a combined cache, thus there's no real
+	 * I/D distinction ..  so don't inadvertently double
+	 * up the output.
+	 */
+	if (strcmp(system_utsname.machine, "sh2") ||
+	    strcmp(system_utsname.machine, "sh3")) {
+		dcachesz = boot_cpu_data.dcache.ways *
+			   boot_cpu_data.dcache.sets *
+			   boot_cpu_data.dcache.linesz;
+
+		seq_printf(m, "/%dK-bytes", dcachesz >> 10);
+	}
+
+	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
 		     loops_per_jiffy/(500000/HZ),
 		     (loops_per_jiffy/(5000/HZ)) % 100);
-	seq_printf(m, "Machine: %s\n", sh_mv.mv_name);
 
 #define PRINT_CLOCK(name, value) \
-	seq_printf(m, name " clock: %d.%02dMHz\n", \
+	seq_printf(m, name " clock\t: %d.%02dMHz\n", \
 		     ((value) / 1000000), ((value) % 1000000)/10000)
 	
-	PRINT_CLOCK("CPU", boot_cpu_data.cpu_clock);
-	PRINT_CLOCK("Bus", boot_cpu_data.bus_clock);
+	PRINT_CLOCK("cpu", boot_cpu_data.cpu_clock);
+	PRINT_CLOCK("bus", boot_cpu_data.bus_clock);
 #ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-	PRINT_CLOCK("Memory", boot_cpu_data.memory_clock);
+	PRINT_CLOCK("memory", boot_cpu_data.memory_clock);
 #endif
-	PRINT_CLOCK("Peripheral module", boot_cpu_data.module_clock);
+	PRINT_CLOCK("module", boot_cpu_data.module_clock);
 
 	return 0;
 }
 
+
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	return (void*)(*pos == 0);
+	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
 }
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	return NULL;
+	++*pos;
+	return c_start(m, pos);
 }
 static void c_stop(struct seq_file *m, void *v)
 {
@@ -544,4 +689,101 @@
 	.stop	= c_stop,
 	.show	= show_cpuinfo,
 };
-#endif
+#endif /* CONFIG_PROC_FS */
+
+#ifdef CONFIG_SH_KGDB
+/*
+ * Parse command-line kgdb options.  By default KGDB is enabled,
+ * entered on error (or other action) using default serial info.
+ * The command-line option can include a serial port specification
+ * and an action to override default or configured behavior.
+ */
+struct kgdb_sermap kgdb_sci_sermap =
+{ "ttySC", 5, kgdb_sci_setup, NULL };
+
+struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap;
+struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap;
+
+void kgdb_register_sermap(struct kgdb_sermap *map)
+{
+	struct kgdb_sermap *last;
+
+	for (last = kgdb_serlist; last->next; last = last->next)
+		;
+	last->next = map;
+	if (!map->namelen) {
+		map->namelen = strlen(map->name);
+	}
+}
+
+static int __init kgdb_parse_options(char *options)
+{
+	char c;
+	int baud;
+
+	/* Check for port spec (or use default) */
+
+	/* Determine port type and instance */
+	if (!memcmp(options, "tty", 3)) {
+		struct kgdb_sermap *map = kgdb_serlist;
+
+		while (map && memcmp(options, map->name, map->namelen))
+			map = map->next;
+
+		if (!map) {
+			KGDB_PRINTK("unknown port spec in %s\n", options);
+			return -1;
+		}
+
+		kgdb_porttype = map;
+		kgdb_serial_setup = map->setup_fn;
+		kgdb_portnum = options[map->namelen] - '0';
+		options += map->namelen + 1;
+
+		options = (*options == ',') ? options+1 : options;
+		
+		/* Read optional parameters (baud/parity/bits) */
+		baud = simple_strtoul(options, &options, 10);
+		if (baud != 0) {
+			kgdb_baud = baud;
+
+			c = toupper(*options);
+			if (c == 'E' || c == 'O' || c == 'N') {
+				kgdb_parity = c;
+				options++;
+			}
+
+			c = *options;
+			if (c == '7' || c == '8') {
+				kgdb_bits = c;
+				options++;
+			}
+			options = (*options == ',') ? options+1 : options;
+		}
+	}
+
+	/* Check for action specification */
+	if (!memcmp(options, "halt", 4)) {
+		kgdb_halt = 1;
+		options += 4;
+	} else if (!memcmp(options, "disabled", 8)) {
+		kgdb_enabled = 0;
+		options += 8;
+	}
+
+	if (*options) {
+                KGDB_PRINTK("ignored unknown options: %s\n", options);
+		return 0;
+	}
+	return 1;
+}
+__setup("kgdb=", kgdb_parse_options);
+#endif /* CONFIG_SH_KGDB */
+
+static int __init fpu_setup(char *opts)
+{
+	fpu_disabled = 1;
+	return 0;
+}
+__setup("nofpu", fpu_setup);
+
diff -urN linux-2.5.73-bk9/arch/sh/kernel/sh_ksyms.c linux-2.5.73-bk10/arch/sh/kernel/sh_ksyms.c
--- linux-2.5.73-bk9/arch/sh/kernel/sh_ksyms.c	2003-06-22 11:32:36.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/sh_ksyms.c	2003-07-02 04:57:23.000000000 -0700
@@ -3,13 +3,13 @@
 #include <linux/smp.h>
 #include <linux/user.h>
 #include <linux/elfcore.h>
-#include <linux/mca.h>
 #include <linux/sched.h>
 #include <linux/in6.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 #include <linux/pci.h>
+#include <linux/irq.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
@@ -18,11 +18,11 @@
 #include <asm/io.h>
 #include <asm/hardirq.h>
 #include <asm/delay.h>
-#include <asm/pgalloc.h>
-#include <linux/irq.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(elf_fpregset_t *);
+extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
 extern struct hw_interrupt_type no_irq_type;
 
 /* platform dependent support */
@@ -60,9 +60,13 @@
 EXPORT_SYMBOL(memset_io);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(__copy_user);
 
 #ifdef CONFIG_VT
+/* XXX: MRB-remove - what was screen_info changed to?
 EXPORT_SYMBOL(screen_info);
+*/
 #endif
 
 EXPORT_SYMBOL(boot_cpu_data);
@@ -78,16 +82,17 @@
 EXPORT_SYMBOL(__const_udelay);
 
 #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL_NOVERS(name)
- 
+
 /* These symbols are generated by the compiler itself */
 DECLARE_EXPORT(__udivsi3);
+DECLARE_EXPORT(__udivdi3);
 DECLARE_EXPORT(__sdivsi3);
 DECLARE_EXPORT(__ashrdi3);
 DECLARE_EXPORT(__ashldi3);
 DECLARE_EXPORT(__lshrdi3);
 DECLARE_EXPORT(__movstr);
 
-#ifdef __SH4__
+#ifdef CONFIG_CPU_SH4
  
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
@@ -96,5 +101,11 @@
 EXPORT_SYMBOL(flush_cache_all);
 EXPORT_SYMBOL(flush_cache_range);
 EXPORT_SYMBOL(flush_dcache_page);
+EXPORT_SYMBOL(__flush_purge_region);
 #endif
 EXPORT_SYMBOL(flush_tlb_page);
+EXPORT_SYMBOL(__down_trylock);
+
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(synchronize_irq);
+#endif
diff -urN linux-2.5.73-bk9/arch/sh/kernel/signal.c linux-2.5.73-bk10/arch/sh/kernel/signal.c
--- linux-2.5.73-bk9/arch/sh/kernel/signal.c	2003-06-22 11:33:37.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/signal.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.21 2000/03/11 14:06:21 gniibe Exp $
+/* $Id: signal.c,v 1.15 2003/05/06 23:28:47 lethal Exp $
  *
  *  linux/arch/sh/kernel/signal.c
  *
@@ -21,12 +21,15 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
-#include <linux/personality.h>
 #include <linux/tty.h>
+#include <linux/personality.h>
+#include <linux/binfmts.h>
+#include <linux/suspend.h>
 
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
+#include <asm/cacheflush.h>
 
 #define DEBUG_SIG 0
 
@@ -45,11 +48,11 @@
 	sigset_t saveset;
 
 	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sighand->siglock);
 	saveset = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sighand->siglock);
 
 	regs.regs[0] = -EINTR;
 	while (1) {
@@ -74,11 +77,11 @@
 	if (copy_from_user(&newset, unewset, sizeof(newset)))
 		return -EFAULT;
 	sigdelsetmask(&newset, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sighand->siglock);
 	saveset = current->blocked;
 	current->blocked = newset;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sighand->siglock);
 
 	regs.regs[0] = -EINTR;
 	while (1) {
@@ -150,11 +153,14 @@
 	char retcode[4];
 };
 
-#if defined(__SH4__)
+#ifdef CONFIG_CPU_SH4
 static inline int restore_sigcontext_fpu(struct sigcontext *sc)
 {
 	struct task_struct *tsk = current;
 
+	if (!(cpu_data->flags & CPU_HAS_FPU))
+		return 0;
+
 	tsk->used_math = 1;
 	return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0],
 				sizeof(long)*(16*2+2));
@@ -163,31 +169,27 @@
 static inline int save_sigcontext_fpu(struct sigcontext *sc)
 {
 	struct task_struct *tsk = current;
-	unsigned long flags;
-	int val;
+
+	if (!(cpu_data->flags & CPU_HAS_FPU))
+		return 0;
 
 	if (!tsk->used_math) {
-	  val = 0;
-		__copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
+		__put_user(0, &sc->sc_ownedfp);
 		return 0;
 	}
 
-	val = 1;
-	__copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
+	__put_user(1, &sc->sc_ownedfp);
 
 	/* This will cause a "finit" to be triggered by the next
 	   attempted FPU operation by the 'current' process.
 	   */
 	tsk->used_math = 0;
 
-	save_and_cli(flags);
 	unlazy_fpu(tsk);
-	restore_flags(flags);
-
 	return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
 			      sizeof(long)*(16*2+2));
 }
-#endif
+#endif /* CONFIG_CPU_SH4 */
 
 static int
 restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p)
@@ -208,21 +210,21 @@
 	COPY(sr);	COPY(pc);
 #undef COPY
 
-#if defined(__SH4__)
-	{
+#ifdef CONFIG_CPU_SH4
+	if (cpu_data->flags & CPU_HAS_FPU) {
 		int owned_fp;
 		struct task_struct *tsk = current;
 
 		regs->sr |= SR_FD; /* Release FPU */
 		clear_fpu(tsk);
-		current->used_math = 0;
+		tsk->used_math = 0;
 		__get_user (owned_fp, &sc->sc_ownedfp);
 		if (owned_fp)
 			err |= restore_sigcontext_fpu(sc);
 	}
 #endif
 
-	regs->syscall_nr = -1;		/* disable syscall checks */
+	regs->tra = -1;		/* disable syscall checks */
 	err |= __get_user(*r0_p, &sc->sc_regs[0]);
 	return err;
 }
@@ -246,10 +248,10 @@
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sighand->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sighand->siglock);
 
 	if (restore_sigcontext(&regs, &frame->sc, &r0))
 		goto badframe;
@@ -276,10 +278,10 @@
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sighand->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sighand->siglock);
 
 	if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &r0))
 		goto badframe;
@@ -321,7 +323,7 @@
 	COPY(sr);	COPY(pc);
 #undef COPY
 
-#if defined(__SH4__)
+#ifdef CONFIG_CPU_SH4
 	err |= save_sigcontext_fpu(sc);
 #endif
 
@@ -355,10 +357,10 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	signal = current->exec_domain
-		&& current->exec_domain->signal_invmap
+	signal = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
 		&& sig < 32
-		? current->exec_domain->signal_invmap[sig]
+		? current_thread_info()->exec_domain->signal_invmap[sig]
 		: sig;
 
 	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
@@ -420,10 +422,10 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	signal = current->exec_domain
-		&& current->exec_domain->signal_invmap
+	signal = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
 		&& sig < 32
-		? current->exec_domain->signal_invmap[sig]
+		? current_thread_info()->exec_domain->signal_invmap[sig]
 		: sig;
 
 	err |= __put_user(&frame->info, &frame->pinfo);
@@ -490,10 +492,10 @@
 handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
 	struct pt_regs * regs)
 {
-	struct k_sigaction *ka = &current->sig->action[sig-1];
+	struct k_sigaction *ka = &current->sighand->action[sig-1];
 
 	/* Are we from a system call? */
-	if (regs->syscall_nr >= 0) {
+	if (regs->tra >= 0) {
 		/* If so, check system call restarting.. */
 		switch (regs->regs[0]) {
 			case -ERESTARTNOHAND:
@@ -507,9 +509,21 @@
 				}
 			/* fallthrough */
 			case -ERESTARTNOINTR:
-				regs->regs[0] = regs->syscall_nr;
 				regs->pc -= 2;
 		}
+#ifndef CONFIG_PREEMPT
+	} else {
+		/* gUSA handling */
+		if (regs->regs[15] >= 0xc0000000) {
+			int offset = (int)regs->regs[15];
+
+			/* Reset stack pointer: clear critical region mark */
+			regs->regs[15] = regs->regs[1];
+			if (regs->pc < regs->regs[0])
+				/* Go to rewind point #1 */
+				regs->pc = regs->regs[0] + offset - 2;
+		}
+#endif
 	}
 
 	/* Set up the stack frame */
@@ -522,11 +536,11 @@
 		ka->sa.sa_handler = SIG_DFL;
 
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
-		spin_lock_irq(&current->sigmask_lock);
+		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
-		spin_unlock_irq(&current->sigmask_lock);
+		spin_unlock_irq(&current->sighand->siglock);
 	}
 }
 
@@ -553,6 +567,11 @@
 	if (!user_mode(regs))
 		return 1;
 
+	if (current->flags & PF_FREEZE) {
+		refrigerator(0);
+		goto no_signal;
+	}
+
 	if (!oldset)
 		oldset = &current->blocked;
 
@@ -563,13 +582,14 @@
 		return 1;
 	}
 
+ no_signal:
 	/* Did we come from a system call? */
-	if (regs->syscall_nr >= 0) {
+	if (regs->tra >= 0) {
 		/* Restart the system call - no handlers present */
 		if (regs->regs[0] == -ERESTARTNOHAND ||
 		    regs->regs[0] == -ERESTARTSYS ||
-		    regs->regs[0] == -ERESTARTNOINTR) {
-			regs->regs[0] = regs->syscall_nr;
+		    regs->regs[0] == -ERESTARTNOINTR ||
+		    regs->regs[0] == -ERESTART_RESTARTBLOCK) {
 			regs->pc -= 2;
 		}
 	}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/sys_sh.c linux-2.5.73-bk10/arch/sh/kernel/sys_sh.c
--- linux-2.5.73-bk9/arch/sh/kernel/sys_sh.c	2003-06-22 11:33:37.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/sys_sh.c	2003-07-02 04:57:23.000000000 -0700
@@ -43,7 +43,7 @@
 	return error;
 }
 
-#if defined(__SH4__)
+#if defined(CONFIG_CPU_SH4)
 /*
  * To avoid cache alias, we map the shard page with same color.
  */
@@ -142,7 +142,12 @@
 	if (call <= SEMCTL)
 		switch (call) {
 		case SEMOP:
-			return sys_semop (first, (struct sembuf *)ptr, second);
+			return sys_semtimedop(first, (struct sembuf *)ptr,
+					      second, NULL);
+		case SEMTIMEDOP:
+			return sys_semtimedop(first, (struct sembuf *)ptr,
+					      second,
+					      (const struct timespec *)fifth);
 		case SEMGET:
 			return sys_semget (first, second, third);
 		case SEMCTL: {
@@ -231,3 +236,19 @@
 	up_read(&uts_sem);
 	return err?-EFAULT:0;
 }
+
+asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char * buf,
+			     size_t count, long dummy, loff_t pos)
+{
+	extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
+					size_t count, loff_t pos);
+	return sys_pread64(fd, buf, count, pos);
+}
+
+asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char * buf,
+			      size_t count, long dummy, loff_t pos)
+{
+	extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf,
+					size_t count, loff_t pos);
+	return sys_pwrite64(fd, buf, count, pos);
+}
diff -urN linux-2.5.73-bk9/arch/sh/kernel/time.c linux-2.5.73-bk10/arch/sh/kernel/time.c
--- linux-2.5.73-bk9/arch/sh/kernel/time.c	2003-06-22 11:32:28.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/time.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,9 +1,11 @@
-/* $Id: time.c,v 1.30 2001/09/01 14:34:31 mrbrown Exp $
+/* $Id: time.c,v 1.12 2003/06/28 15:35:28 lethal Exp $
  *
  *  linux/arch/sh/kernel/time.c
  *
  *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
+ *  Copyright (C) 2002, 2003  Paul Mundt
+ *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
  *
  *  Some code taken from i386 version.
  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
@@ -29,6 +31,10 @@
 #include <asm/delay.h>
 #include <asm/machvec.h>
 #include <asm/rtc.h>
+#include <asm/freq.h>
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#endif
 
 #include <linux/timex.h>
 #include <linux/irq.h>
@@ -39,16 +45,14 @@
 
 #define TMU0_TCR_CALIB	0x0000
 
-#if defined(__sh3__)
+#if defined(CONFIG_CPU_SH3)
 #define TMU_TOCR	0xfffffe90	/* Byte access */
 #define TMU_TSTR	0xfffffe92	/* Byte access */
 
 #define TMU0_TCOR	0xfffffe94	/* Long access */
 #define TMU0_TCNT	0xfffffe98	/* Long access */
 #define TMU0_TCR	0xfffffe9c	/* Word access */
-
-#define FRQCR		0xffffff80
-#elif defined(__SH4__)
+#elif defined(CONFIG_CPU_SH4)
 #define TMU_TOCR	0xffd80000	/* Byte access */
 #define TMU_TSTR	0xffd80004	/* Byte access */
 
@@ -56,28 +60,48 @@
 #define TMU0_TCNT	0xffd8000c	/* Long access */
 #define TMU0_TCR	0xffd80010	/* Word access */
 
-#define FRQCR		0xffc00000
-
-/* Core Processor Version Register */
-#define CCN_PVR		0xff000030
-#define CCN_PVR_CHIP_SHIFT 24
-#define CCN_PVR_CHIP_MASK  0xff
-#define CCN_PVR_CHIP_ST40STB1 0x4
-
 #ifdef CONFIG_CPU_SUBTYPE_ST40STB1
 #define CLOCKGEN_MEMCLKCR 0xbb040038
 #define MEMCLKCR_RATIO_MASK 0x7
 #endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
-#endif /* __sh3__ or __SH4__ */
+#endif /* CONFIG_CPU_SH3 or CONFIG_CPU_SH4 */
+
+extern unsigned long wall_jiffies;
+#define TICK_SIZE (TICK_NSEC / 1000)
+spinlock_t tmu0_lock = SPIN_LOCK_UNLOCKED;
 
 u64 jiffies_64 = INITIAL_JIFFIES;
 
-extern unsigned long wall_jiffies;
-#define TICK_SIZE tick
+/* XXX: Can we initialize this in a routine somewhere?  Dreamcast doesn't want
+ * these routines anywhere... */
+#ifdef CONFIG_SH_RTC
+void (*rtc_get_time)(struct timespec *) = sh_rtc_gettimeofday;
+int (*rtc_set_time)(const time_t) = sh_rtc_settimeofday;
+#else
+void (*rtc_get_time)(struct timespec *) = 0;
+int (*rtc_set_time)(const time_t) = 0;
+#endif
+
+#if defined(CONFIG_CPU_SH3)
+#error "FIXME"
+static int ifc_table[] = { 1, 2, 4, 1, 3, 1, 1, 1 };
+static int pfc_table[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
+static int stc_table[] = { 1, 2, 4, 8, 3, 6, 1, 1 };
+#elif defined(CONFIG_CPU_SH4)
+static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
+static int ifc_values[]   = { 0, 1, 2, 3, 0, 4, 0, 5 };
+#define bfc_divisors ifc_divisors	/* Same */
+#define bfc_values ifc_values
+static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
+static int pfc_values[]   = { 0, 0, 1, 2, 0, 3, 0, 4 };
+#else
+#error "Unknown ifc/bfc/pfc/stc values for this processor"
+#endif
 
 static unsigned long do_gettimeoffset(void)
 {
 	int count;
+	unsigned long flags;
 
 	static int count_p = 0x7fffffff;    /* for the first call after boot */
 	static unsigned long jiffies_p = 0;
@@ -87,6 +111,7 @@
 	 */
 	unsigned long jiffies_t;
 
+	spin_lock_irqsave(&tmu0_lock, flags);
 	/* timer count may underflow right here */
 	count = ctrl_inl(TMU0_TCNT);	/* read the latched count */
 
@@ -117,6 +142,7 @@
 		jiffies_p = jiffies_t;
 
 	count_p = count;
+	spin_unlock_irqrestore(&tmu0_lock, flags);
 
 	count = ((LATCH-1) - count) * TICK_SIZE;
 	count = (count + LATCH/2) / LATCH;
@@ -126,21 +152,21 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
 	unsigned long seq;
 	unsigned long usec, sec;
+	unsigned long lost;
 
 	do {
-		seq = read_seqbegin_irqsave(&xtime_lock, flags);
+		seq = read_seqbegin(&xtime_lock);
 		usec = do_gettimeoffset();
-		{
-			unsigned long lost = jiffies - wall_jiffies;
-			if (lost)
-				usec += lost * (1000000 / HZ);
-		}
+		
+		lost = jiffies - wall_jiffies;
+		if (lost)
+			usec += lost * (1000000 / HZ);
+
 		sec = xtime.tv_sec;
-		usec += xtime.tv_usec;
-	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+		usec += xtime.tv_nsec / 1000;
+	} while (read_seqretry(&xtime_lock, seq));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -171,18 +197,50 @@
 		tv->tv_sec--;
 	}
 
-	xtime = *tv;
+	xtime.tv_sec = tv->tv_sec;
+	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
+
 	return 0;
 }
 
 /* last time the RTC clock got updated */
 static long last_rtc_update;
 
+/* Profiling definitions */
+extern unsigned long prof_cpu_mask;
+extern unsigned int * prof_buffer;
+extern unsigned long prof_len;
+extern unsigned long prof_shift;
+extern char _stext;
+
+static inline void sh_do_profile(unsigned long pc)
+{
+	if (!prof_buffer)
+		return;
+
+	if (pc >= 0xa0000000UL && pc < 0xc0000000UL)
+		pc -= 0x20000000;
+
+	pc -= (unsigned long)&_stext;
+	pc >>= prof_shift;
+
+	/*
+	 * Don't ignore out-of-bounds PC values silently,
+	 * put them into the last histogram slot, so if
+	 * present, they will show up as a sharp peak.
+	 */
+	if (pc > prof_len - 1)
+		pc = prof_len - 1;
+
+	atomic_inc((atomic_t *)&prof_buffer[pc]);
+}
+
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -206,9 +264,9 @@
 	 */
 	if ((time_status & STA_UNSYNC) == 0 &&
 	    xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
-	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
-		if (sh_mv.mv_rtc_settimeofday(&xtime) == 0)
+	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
+	    (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
+		if (rtc_set_time(xtime.tv_sec) == 0)
 			last_rtc_update = xtime.tv_sec;
 		else
 			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
@@ -220,7 +278,7 @@
  * Time Stamp Counter value at the time of the timer interrupt, so that
  * we later on can estimate the time of day more exactly.
  */
-static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned long timer_status;
 
@@ -239,13 +297,18 @@
 	write_seqlock(&xtime_lock);
 	do_timer_interrupt(irq, NULL, regs);
 	write_sequnlock(&xtime_lock);
+
+	return IRQ_HANDLED;
 }
 
+/*
+ * Hah!  We'll see if this works (switching from usecs to nsecs).
+ */
 static unsigned int __init get_timer_frequency(void)
 {
 	u32 freq;
-	struct timeval tv1, tv2;
-	unsigned long diff_usec;
+	struct timespec ts1, ts2;
+	unsigned long diff_nsec;
 	unsigned long factor;
 
 	/* Setup the timer:  We don't want to generate interrupts, just
@@ -257,219 +320,135 @@
 	ctrl_outl(0xffffffff, TMU0_TCOR);
 	ctrl_outl(0xffffffff, TMU0_TCNT);
 
-	rtc_gettimeofday(&tv2);
+	rtc_get_time(&ts2);
 
 	do {
-		rtc_gettimeofday(&tv1);
-	} while (tv1.tv_usec == tv2.tv_usec && tv1.tv_sec == tv2.tv_sec);
+		rtc_get_time(&ts1);
+	} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
 
 	/* actually start the timer */
 	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
 
 	do {
-		rtc_gettimeofday(&tv2);
-	} while (tv1.tv_usec == tv2.tv_usec && tv1.tv_sec == tv2.tv_sec);
+		rtc_get_time(&ts2);
+	} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
 
 	freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
-	if (tv2.tv_usec < tv1.tv_usec) {
-		tv2.tv_usec += 1000000;
-		tv2.tv_sec--;
+	if (ts2.tv_nsec < ts1.tv_nsec) {
+		ts2.tv_nsec += 1000000000;
+		ts2.tv_sec--;
 	}
 
-	diff_usec = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
+	diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
 
 	/* this should work well if the RTC has a precision of n Hz, where
 	 * n is an integer.  I don't think we have to worry about the other
 	 * cases. */
-	factor = (1000000 + diff_usec/2) / diff_usec;
+	factor = (1000000000 + diff_nsec/2) / diff_nsec;
 
-	if (factor * diff_usec > 1100000 ||
-	    factor * diff_usec <  900000)
-		panic("weird RTC (diff_usec %ld)", diff_usec);
+	if (factor * diff_nsec > 1100000000 ||
+	    factor * diff_nsec <  900000000)
+		panic("weird RTC (diff_nsec %ld)", diff_nsec);
 
 	return freq * factor;
 }
 
+void (*board_time_init)(void) = 0;
+void (*board_timer_setup)(struct irqaction *irq) = 0;
+
 static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
 
-void __init time_init(void)
+void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsigned int *pfc)
 {
-	unsigned int cpu_clock, master_clock, bus_clock, module_clock;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-	unsigned int memory_clock;
+	unsigned int frqcr = ctrl_inw(FRQCR);
+
+#if defined(CONFIG_CPU_SH3)
+	unsigned int tmp;
+
+	tmp  = (frqcr & 0x8000) >> 13;
+	tmp |= (frqcr & 0x0030) >>  4;
+	*bfc = stc_table[tmp];
+	tmp  = (frqcr & 0x4000)  >> 12;
+	tmp |= (frqcr & 0x000c) >> 2;
+	*ifc  = ifc_table[tmp];
+	tmp  = (frqcr & 0x2000) >> 11;
+	tmp |= frqcr & 0x0003;
+	*pfc = pfc_table[tmp];
+#elif defined(CONFIG_CPU_SH4)
+	*ifc = ifc_divisors[(frqcr >> 6) & 0x0007];
+	*bfc = bfc_divisors[(frqcr >> 3) & 0x0007];
+	*pfc = pfc_divisors[frqcr & 0x0007];
 #endif
+}
+
+/*
+ * This bit of ugliness builds up accessor routines to get at both
+ * the divisors and the physical values.
+ */
+#define _FREQ_TABLE(x) \
+	unsigned int get_##x##_divisor(unsigned int value) 	\
+		{ return x##_divisors[value]; }			\
+								\
+	unsigned int get_##x##_value(unsigned int divisor)	\
+		{ return x##_values[(divisor - 1)]; }
+
+_FREQ_TABLE(ifc);
+_FREQ_TABLE(bfc);
+_FREQ_TABLE(pfc);
+
+void __init time_init(void)
+{
 	unsigned int timer_freq;
-	unsigned short frqcr, ifc, pfc, bfc;
+	unsigned int ifc, pfc, bfc;
 	unsigned long interval;
-#if defined(__sh3__)
-	static int ifc_table[] = { 1, 2, 4, 1, 3, 1, 1, 1 };
-	static int pfc_table[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
-	static int stc_table[] = { 1, 2, 4, 8, 3, 6, 1, 1 };
-#elif defined(__SH4__)
-	static int ifc_table[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
-#define bfc_table ifc_table	/* Same */
-	static int pfc_table[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
 
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-	struct frqcr_data {
-		unsigned short frqcr;
-		struct {
-			unsigned char multiplier;
-			unsigned char divisor;
-		} factor[3];
-	};
-
-	static struct frqcr_data st40_frqcr_table[] = {		
-		{ 0x000, {{1,1}, {1,1}, {1,2}}},
-		{ 0x002, {{1,1}, {1,1}, {1,4}}},
-		{ 0x004, {{1,1}, {1,1}, {1,8}}},
-		{ 0x008, {{1,1}, {1,2}, {1,2}}},
-		{ 0x00A, {{1,1}, {1,2}, {1,4}}},
-		{ 0x00C, {{1,1}, {1,2}, {1,8}}},
-		{ 0x011, {{1,1}, {2,3}, {1,6}}},
-		{ 0x013, {{1,1}, {2,3}, {1,3}}},
-		{ 0x01A, {{1,1}, {1,2}, {1,4}}},
-		{ 0x01C, {{1,1}, {1,2}, {1,8}}},
-		{ 0x023, {{1,1}, {2,3}, {1,3}}},
-		{ 0x02C, {{1,1}, {1,2}, {1,8}}},
-		{ 0x048, {{1,2}, {1,2}, {1,4}}},
-		{ 0x04A, {{1,2}, {1,2}, {1,6}}},
-		{ 0x04C, {{1,2}, {1,2}, {1,8}}},
-		{ 0x05A, {{1,2}, {1,3}, {1,6}}},
-		{ 0x05C, {{1,2}, {1,3}, {1,6}}},
-		{ 0x063, {{1,2}, {1,4}, {1,4}}},
-		{ 0x06C, {{1,2}, {1,4}, {1,8}}},
-		{ 0x091, {{1,3}, {1,3}, {1,6}}},
-		{ 0x093, {{1,3}, {1,3}, {1,6}}},
-		{ 0x0A3, {{1,3}, {1,6}, {1,6}}},
-		{ 0x0DA, {{1,4}, {1,4}, {1,8}}},
-		{ 0x0DC, {{1,4}, {1,4}, {1,8}}},
-		{ 0x0EC, {{1,4}, {1,8}, {1,8}}},
-		{ 0x123, {{1,4}, {1,4}, {1,8}}},
-		{ 0x16C, {{1,4}, {1,8}, {1,8}}},
-	};
-
-	struct memclk_data {
-		unsigned char multiplier;
-		unsigned char divisor;
-	};
-	static struct memclk_data st40_memclk_table[8] = {
-		{1,1},	// 000
-		{1,2},	// 001
-		{1,3},	// 010
-		{2,3},	// 011
-		{1,4},	// 100
-		{1,6},	// 101
-		{1,8},	// 110
-		{1,8}	// 111
-	};
-#endif
-#endif
-
-	rtc_gettimeofday(&xtime);
+	if (board_time_init)
+		board_time_init();
 
-	setup_irq(TIMER_IRQ, &irq0);
+	/* 
+	 * XXX: Hmm... when cpu/ is proposed, this looks like a good spot for
+	 * it, but we need a rtc to get the timer_freq so board_time_init()
+	 * must always come before a CPU time_(rtc?)_init().
+	 */
+	get_current_frequency_divisors(&ifc, &bfc, &pfc);
 
 	timer_freq = get_timer_frequency();
 
-	module_clock = timer_freq * 4;
-
-#if defined(__sh3__)
-	{
-		unsigned short tmp;
-
-		frqcr = ctrl_inw(FRQCR);
-		tmp  = (frqcr & 0x8000) >> 13;
-		tmp |= (frqcr & 0x0030) >>  4;
-		bfc = stc_table[tmp];
-		tmp  = (frqcr & 0x4000) >> 12;
-		tmp |= (frqcr & 0x000c) >> 2;
-		ifc  = ifc_table[tmp];
-		tmp  = (frqcr & 0x2000) >> 11;
-		tmp |= frqcr & 0x0003;
-		pfc = pfc_table[tmp];
-	}
-#elif defined(__SH4__)
-	{
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-		unsigned long pvr;
+	current_cpu_data.module_clock = timer_freq * 4;
 
-		/* This should probably be moved into the SH3 probing code, and then use the processor
-		 * structure to determine which CPU we are running on.
-		 */
-		pvr = ctrl_inl(CCN_PVR);
-		printk("PVR %08x\n", pvr);
-
-		if (((pvr >>CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) {
-			/* Unfortunatly the STB1 FRQCR values are different from the 7750 ones */
-			struct frqcr_data *d;
-			int a;
-			unsigned long memclkcr;
-			struct memclk_data *e;
-
-			for (a=0; a<ARRAY_SIZE(st40_frqcr_table); a++) {
-				d = &st40_frqcr_table[a];
-				if (d->frqcr == (frqcr & 0x1ff))
-					break;
-			}
-			if (a == ARRAY_SIZE(st40_frqcr_table)) {
-				d = st40_frqcr_table;
-				printk("ERROR: Unrecognised FRQCR value, using default multipliers\n");
-			}
+	rtc_get_time(&xtime);
 
-			memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
-			e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
+	if (board_timer_setup) {
+		board_timer_setup(&irq0);
+	} else {
+		setup_irq(TIMER_IRQ, &irq0);
+	}
 
-			printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n",
-			       d->factor[0].multiplier, d->factor[0].divisor,
-			       d->factor[1].multiplier, d->factor[1].divisor,
-			       e->multiplier,           e->divisor,
-			       d->factor[2].multiplier, d->factor[2].divisor);
-			
-			master_clock = module_clock * d->factor[2].divisor    / d->factor[2].multiplier;
-			bus_clock    = master_clock * d->factor[1].multiplier / d->factor[1].divisor;
-			memory_clock = master_clock * e->multiplier           / e->divisor;
-			cpu_clock    = master_clock * d->factor[0].multiplier / d->factor[0].divisor;
-			goto skip_calc;
-		} else
-#endif
-		{
-			frqcr = ctrl_inw(FRQCR);
+	if (!current_cpu_data.master_clock)
+		current_cpu_data.master_clock = current_cpu_data.module_clock * pfc;
+	if (!current_cpu_data.bus_clock)
+		current_cpu_data.bus_clock = current_cpu_data.master_clock / bfc;
+	if (!current_cpu_data.cpu_clock)
+		current_cpu_data.cpu_clock = current_cpu_data.master_clock / ifc;
 
-			ifc  = ifc_table[(frqcr>> 6) & 0x0007];
-			bfc  = bfc_table[(frqcr>> 3) & 0x0007];
-			pfc = pfc_table[frqcr & 0x0007];
-		}
-	}
-#endif
-	master_clock = module_clock * pfc;
-	bus_clock = master_clock / bfc;
-	cpu_clock = master_clock / ifc;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
- skip_calc:
-#endif
 	printk("CPU clock: %d.%02dMHz\n",
-	       (cpu_clock / 1000000), (cpu_clock % 1000000)/10000);
+	       (current_cpu_data.cpu_clock / 1000000),
+	       (current_cpu_data.cpu_clock % 1000000)/10000);
 	printk("Bus clock: %d.%02dMHz\n",
-	       (bus_clock/1000000), (bus_clock % 1000000)/10000);
+	       (current_cpu_data.bus_clock / 1000000),
+	       (current_cpu_data.bus_clock % 1000000)/10000);
 #ifdef CONFIG_CPU_SUBTYPE_ST40STB1
 	printk("Memory clock: %d.%02dMHz\n",
-	       (memory_clock/1000000), (memory_clock % 1000000)/10000);
+	       (current_cpu_data.memory_clock / 1000000),
+	       (current_cpu_data.memory_clock % 1000000)/10000);
 #endif
 	printk("Module clock: %d.%02dMHz\n",
-	       (module_clock/1000000), (module_clock % 1000000)/10000);
-	interval = (module_clock/4 + HZ/2) / HZ;
+	       (current_cpu_data.module_clock / 1000000),
+	       (current_cpu_data.module_clock % 1000000)/10000);
+	interval = (current_cpu_data.module_clock/4 + HZ/2) / HZ;
 
 	printk("Interval = %ld\n", interval);
 
-	current_cpu_data.cpu_clock    = cpu_clock;
-	current_cpu_data.master_clock = master_clock;
-	current_cpu_data.bus_clock    = bus_clock;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-	current_cpu_data.memory_clock = memory_clock;
-#endif
-	current_cpu_data.module_clock = module_clock;
-
 	/* Start TMU0 */
 	ctrl_outb(0, TMU_TSTR);
 	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
@@ -477,4 +456,12 @@
 	ctrl_outl(interval, TMU0_TCOR);
 	ctrl_outl(interval, TMU0_TCNT);
 	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+
+#if defined(CONFIG_SH_KGDB)
+	/*
+	 * Set up kgdb as requested. We do it here because the serial
+	 * init uses the timer vars we just set up for figuring baud.
+	 */
+	kgdb_init();
+#endif
 }
diff -urN linux-2.5.73-bk9/arch/sh/kernel/traps.c linux-2.5.73-bk10/arch/sh/kernel/traps.c
--- linux-2.5.73-bk9/arch/sh/kernel/traps.c	2003-06-22 11:32:31.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/kernel/traps.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,10 +1,11 @@
-/* $Id: traps.c,v 1.14 2001/07/24 08:07:10 gniibe Exp $
+/* $Id: traps.c,v 1.7 2003/05/04 19:29:53 lethal Exp $
  *
  *  linux/arch/sh/traps.c
  *
  *  SuperH version: Copyright (C) 1999 Niibe Yutaka
  *                  Copyright (C) 2000 Philipp Rumpf
  *                  Copyright (C) 2000 David Howells
+ *                  Copyright (C) 2002, 2003 Paul Mundt
  */
 
 /*
@@ -24,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -31,6 +33,19 @@
 #include <asm/atomic.h>
 #include <asm/processor.h>
 
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#define CHK_REMOTE_DEBUG(regs)                                               \
+{                                                                            \
+  if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \
+  {                                                                          \
+    (*kgdb_debug_hook)(regs);                                                \
+  }                                                                          \
+}
+#else
+#define CHK_REMOTE_DEBUG(regs)
+#endif
+
 #define DO_ERROR(trapnr, signr, str, name, tsk) \
 asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
 			  unsigned long r6, unsigned long r7, \
@@ -39,9 +54,10 @@
 	unsigned long error_code; \
  \
 	asm volatile("stc	r2_bank, %0": "=r" (error_code)); \
-	sti(); \
+	local_irq_enable(); \
 	tsk->thread.error_code = error_code; \
 	tsk->thread.trap_no = trapnr; \
+        CHK_REMOTE_DEBUG(&regs); \
 	force_sig(signr, tsk); \
 	die_if_no_fixup(str,&regs,error_code); \
 }
@@ -59,9 +75,11 @@
 void die(const char * str, struct pt_regs * regs, long err)
 {
 	static int die_counter;
+
 	console_verbose();
 	spin_lock_irq(&die_lock);
 	printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+	CHK_REMOTE_DEBUG(regs);
 	show_regs(regs);
 	spin_unlock_irq(&die_lock);
 	do_exit(SIGSEGV);
@@ -86,10 +104,10 @@
 {
 	if (!user_mode(regs))
 	{
-		unsigned long fixup;
-		fixup = search_exception_table(regs->pc);
+		const struct exception_table_entry *fixup;
+		fixup = search_exception_tables(regs->pc);
 		if (fixup) {
-			regs->pc = fixup;
+			regs->pc = fixup->fixup;
 			return 0;
 		}
 		die(str, regs, err);
@@ -403,7 +421,7 @@
 		case 0x0F00: /* bf/s lab */
 			ret = handle_unaligned_delayslot(regs);
 			if (ret==0) {
-#if defined(__SH4__)
+#if defined(CONFIG_CPU_SH4)
 				if ((regs->sr & 0x00000001) != 0)
 					regs->pc += 4; /* next after slot */
 				else
@@ -416,7 +434,7 @@
 		case 0x0D00: /* bt/s lab */
 			ret = handle_unaligned_delayslot(regs);
 			if (ret==0) {
-#if defined(__SH4__)
+#if defined(CONFIG_CPU_SH4)
 				if ((regs->sr & 0x00000001) == 0)
 					regs->pc += 4; /* next after slot */
 				else
@@ -468,7 +486,7 @@
 	oldfs = get_fs();
 
 	if (user_mode(regs)) {
-		sti();
+		local_irq_enable();
 		current->thread.error_code = error_code;
 		current->thread.trap_no = (writeaccess) ? 8 : 7;
 
@@ -526,17 +544,9 @@
 
 #if defined(CONFIG_SH_STANDARD_BIOS)
 void *gdb_vbr_vector;
-#endif
 
-void __init trap_init(void)
+static inline void __init gdb_vbr_init(void)
 {
-	extern void *vbr_base;
-	extern void *exception_handling_table[14];
-
-	exception_handling_table[12] = (void *)do_reserved_inst;
-	exception_handling_table[13] = (void *)do_illegal_slot_inst;
-
-#if defined(CONFIG_SH_STANDARD_BIOS)
     	/*
 	 * Read the old value of the VBR register to initialise
 	 * the vector through which debug and BIOS traps are
@@ -549,6 +559,15 @@
 	    printk("Setting GDB trap vector to 0x%08lx\n",
 	    	(unsigned long)gdb_vbr_vector);
 	}
+}
+#endif
+
+void __init per_cpu_trap_init(void)
+{
+	extern void *vbr_base;
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+	gdb_vbr_init();
 #endif
 
 	/* NOTE: The VBR value should be at P1
@@ -561,29 +580,70 @@
 		     : "memory");
 }
 
-void dump_stack(void)
+void __init trap_init(void)
 {
-	unsigned long *start;
-	unsigned long *end;
-	unsigned long *p;
-
-	asm("mov	r15, %0" : "=r" (start));
-	asm("stc	r7_bank, %0" : "=r" (end));
-	end += 8192/4;
-
-	printk("%08lx:%08lx\n", (unsigned long)start, (unsigned long)end);
-	for (p=start; p < end; p++) {
-		extern long _text, _etext;
-		unsigned long v=*p;
-
-		if ((v >= (unsigned long )&_text)
-		    && (v <= (unsigned long )&_etext)) {
-			printk("%08lx\n", v);
+	extern void *exception_handling_table[14];
+
+	exception_handling_table[12] = (void *)do_reserved_inst;
+	exception_handling_table[13] = (void *)do_illegal_slot_inst;
+
+	per_cpu_trap_init();
+}
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+	unsigned long *stack, addr;
+	unsigned long module_start = VMALLOC_START;
+	unsigned long module_end = VMALLOC_END;
+	extern long _text, _etext;
+	int i = 1;
+
+	if (!sp) {
+		__asm__ __volatile__ (
+			"mov r15, %0\n\t"
+			"stc r7_bank, %1\n\t"
+			: "=r" (module_start),
+			  "=r" (module_end)
+		);
+		
+		sp = (unsigned long *)module_start;
+	}
+
+	stack = sp;
+
+	printk("\nCall trace: ");
+
+	while (((long)stack & (THREAD_SIZE - 1))) {
+		addr = *stack++;
+		if (((addr >= (unsigned long)&_text) &&
+		     (addr <= (unsigned long)&_etext)) ||
+		    ((addr >= module_start) && (addr <= module_end))) {
+			/*
+			 * For 80-columns display, 6 entry is maximum.
+			 * NOTE: '[<8c00abcd>] ' consumes 13 columns .
+			 */
+			if (i && ((i % 6) == 0))
+				printk("\n       ");
+			printk("[<%08lx>] ", addr);
+			i++;
 		}
 	}
+
+	printk("\n");
+}
+
+void show_task(unsigned long *sp)
+{
+	show_stack(NULL, sp);
 }
 
 void show_trace_task(struct task_struct *tsk)
 {
-	printk("Backtrace not yet implemented for SH.\n");
+	show_task((unsigned long *)tsk->thread.sp);
 }
+
+void dump_stack(void)
+{
+	show_stack(NULL, NULL);
+}
+
diff -urN linux-2.5.73-bk9/arch/sh/lib/Makefile linux-2.5.73-bk10/arch/sh/lib/Makefile
--- linux-2.5.73-bk9/arch/sh/lib/Makefile	2003-06-22 11:32:45.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/lib/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -3,4 +3,4 @@
 #
 
 lib-y  = delay.o memcpy.o memset.o memmove.o memchr.o \
-	 checksum.o strcasecmp.o strlen.o
+	 checksum.o strcasecmp.o strlen.o div64.o udivdi3.o
diff -urN linux-2.5.73-bk9/arch/sh/lib/div64.S linux-2.5.73-bk10/arch/sh/lib/div64.S
--- linux-2.5.73-bk9/arch/sh/lib/div64.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/lib/div64.S	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,46 @@
+/*	
+ * unsigned long long __div64_32(unsigned long long n, unsigned long d); 
+ */
+
+#include <linux/linkage.h>
+
+.text
+ENTRY(__div64_32)
+#ifdef  __LITTLE_ENDIAN__
+	mov	r4, r0
+	mov	r5, r1
+#else
+	mov	r4, r1
+	mov	r5, r0
+#endif
+	cmp/hs	r6, r1
+	bf.s	1f
+	 mov	#0, r2
+
+	mov	r1, r2
+	mov	#0, r3
+	div0u
+	.rept	32
+	rotcl	r2
+	div1	r6, r3
+	.endr
+	rotcl	r2
+	mul.l	r6, r2
+	sts	macl, r3
+	sub	r3, r1
+1:
+	div0u
+	.rept	32
+	rotcl	r0
+	div1	r6, r1
+	.endr
+#ifdef  __LITTLE_ENDIAN__
+	mov	r2, r1
+	rts
+	 rotcl	r0
+#else
+	rotcl	r0
+	mov	r0, r1
+	rts
+	 mov	r2, r0
+#endif
diff -urN linux-2.5.73-bk9/arch/sh/lib/udivdi3.c linux-2.5.73-bk10/arch/sh/lib/udivdi3.c
--- linux-2.5.73-bk9/arch/sh/lib/udivdi3.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/lib/udivdi3.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,16 @@
+/*
+ * Simple __udivdi3 function which doesn't use FPU.
+ */
+
+#include <linux/types.h>
+
+extern u64 __div64_32(u64 n, u32 d);
+extern void panic(const char * fmt, ...);
+
+u64 __udivdi3(u64 n, u64 d)
+{
+	if (d & ~0xffffffff)
+		panic("Need true 64-bit/64-bit division");
+	return __div64_32(n, (u32)d);
+}
+
diff -urN linux-2.5.73-bk9/arch/sh/mm/Makefile linux-2.5.73-bk10/arch/sh/mm/Makefile
--- linux-2.5.73-bk9/arch/sh/mm/Makefile	2003-06-22 11:33:15.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/mm/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -2,7 +2,19 @@
 # Makefile for the Linux SuperH-specific parts of the memory manager.
 #
 
-obj-y	 := init.o fault.o extable.o clear_page.o copy_page.o
+obj-y			:= init.o extable.o clear_page.o copy_page.o
 
+obj-$(CONFIG_CPU_SH2)	+= cache-sh2.o
 obj-$(CONFIG_CPU_SH3) += cache-sh3.o
-obj-$(CONFIG_CPU_SH4) += cache-sh4.o __clear_user_page-sh4.o __copy_user_page-sh4.o ioremap.o
+obj-$(CONFIG_CPU_SH4)	+= cache-sh4.o pg-sh4.o
+
+mmu-y			:= fault-nommu.o tlb-nommu.o
+mmu-$(CONFIG_MMU)	:= fault.o
+
+obj-y			+= $(mmu-y)
+
+ifdef CONFIG_MMU
+obj-$(CONFIG_CPU_SH3)	+= tlb-sh3.o
+obj-$(CONFIG_CPU_SH4)	+= tlb-sh4.o ioremap.o
+endif
+
diff -urN linux-2.5.73-bk9/arch/sh/mm/cache-sh2.c linux-2.5.73-bk10/arch/sh/mm/cache-sh2.c
--- linux-2.5.73-bk9/arch/sh/mm/cache-sh2.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/mm/cache-sh2.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,72 @@
+/*
+ * arch/sh/mm/cache-sh2.c
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/cache.h>
+#include <asm/addrspace.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+
+/*
+ * Calculate the OC address and set the way bit on the SH-2.
+ *
+ * We must have already jump_to_P2()'ed prior to calling this
+ * function, since we rely on CCR manipulation to do the
+ * Right Thing(tm).
+ */
+unsigned long __get_oc_addr(unsigned long set, unsigned long way)
+{
+	unsigned long ccr;
+	
+	/*
+	 * On SH-2 the way bit isn't tracked in the address field
+	 * if we're doing address array access .. instead, we need
+	 * to manually switch out the way in the CCR.
+	 */
+	ccr = ctrl_inl(CCR);
+	ccr &= ~0x00c0;
+	ccr |= way << cpu_data->dcache.way_shift;
+
+	/*
+	 * Despite the number of sets being halved, we end up losing
+	 * the first 2 ways to OCRAM instead of the last 2 (if we're
+	 * 4-way). As a result, forcibly setting the W1 bit handily
+	 * bumps us up 2 ways.
+	 */
+	if (ccr & CCR_CACHE_ORA)
+		ccr |= 1 << (cpu_data->dcache.way_shift + 1);
+
+	ctrl_outl(ccr, CCR);
+
+	return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift);
+}
+
+int __init detect_cpu_and_cache_system(void)
+{
+	/*
+	 * For now, assume SH7604 .. fix this later.
+	 */
+	cpu_data->type			= CPU_SH7604;
+	cpu_data->dcache.ways		= 4;
+	cpu_data->dcache.way_shift	= 6;
+	cpu_data->dcache.sets		= 64;
+	cpu_data->dcache.entry_shift	= 4;
+	cpu_data->dcache.linesz		= L1_CACHE_BYTES;
+	cpu_data->dcache.flags		= 0;
+
+	/*
+	 * SH-2 doesn't have seperate caches
+	 */
+	cpu_data->dcache.flags |= SH_CACHE_COMBINED;
+	cpu_data->icache = cpu_data->dcache;
+
+	return 0;
+}
+
diff -urN linux-2.5.73-bk9/arch/sh/mm/cache-sh3.c linux-2.5.73-bk10/arch/sh/mm/cache-sh3.c
--- linux-2.5.73-bk9/arch/sh/mm/cache-sh3.c	2003-06-22 11:32:31.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/mm/cache-sh3.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,9 +1,9 @@
-/* $Id: cache-sh3.c,v 1.6 2001/09/10 08:59:59 dwmw2 Exp $
+/* $Id: cache-sh3.c,v 1.5 2003/05/06 23:28:48 lethal Exp $
  *
  *  linux/arch/sh/mm/cache-sh3.c
  *
  * Copyright (C) 1999, 2000  Niibe Yutaka
- *
+ * Copyright (C) 2002 Paul Mundt
  */
 
 #include <linux/init.h>
@@ -19,71 +19,9 @@
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
 
-
-#define CCR		0xffffffec	/* Address of Cache Control Register */
-
-#define CCR_CACHE_CE	0x01	/* Cache Enable */
-#define CCR_CACHE_WT	0x02	/* Write-Through (for P0,U0,P3) (else writeback) */
-#define CCR_CACHE_CB	0x04	/* Write-Back (for P1) (else writethrough) */
-#define CCR_CACHE_CF	0x08	/* Cache Flush */
-#define CCR_CACHE_RA	0x20	/* RAM mode */
-
-#define CCR_CACHE_VAL	(CCR_CACHE_CB|CCR_CACHE_CE)	/* 8k-byte cache, P1-wb, enable */
-#define CCR_CACHE_INIT	(CCR_CACHE_CF|CCR_CACHE_VAL)	/* 8k-byte cache, CF, P1-wb, enable */
-
-#define CACHE_OC_ADDRESS_ARRAY 0xf0000000
-#define CACHE_VALID	  1
-#define CACHE_UPDATED	  2
-#define CACHE_PHYSADDR_MASK 0x1ffffc00
-
-/* 7709A/7729 has 16K cache (256-entry), while 7702 has only 2K(direct)
-   7702 is not supported (yet) */
-struct _cache_system_info {
-	int way_shift;
-	int entry_mask;
-	int num_entries;
-};
-
-/* Data at BSS is cleared after setting this variable.
-   So, we Should not placed this variable at BSS section.
-   Initialize this, it is placed at data section. */
-static struct _cache_system_info cache_system_info = {0,};
-
-#define CACHE_OC_WAY_SHIFT	(cache_system_info.way_shift)
-#define CACHE_OC_ENTRY_SHIFT    4
-#define CACHE_OC_ENTRY_MASK	(cache_system_info.entry_mask)
-#define CACHE_OC_NUM_ENTRIES	(cache_system_info.num_entries)
-#define CACHE_OC_NUM_WAYS	4
-#define CACHE_OC_ASSOC_BIT    (1<<3)
-
-
-/*
- * Write back all the cache.
- *
- * For SH-4, we only need to flush (write back) Operand Cache,
- * as Instruction Cache doesn't have "updated" data.
- *
- * Assumes that this is called in interrupt disabled context, and P2.
- * Shuld be INLINE function.
- */
-static inline void cache_wback_all(void)
-{
-	unsigned long addr, data, i, j;
-
-	for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) {
-		for (j=0; j<CACHE_OC_NUM_WAYS; j++) {
-			addr = CACHE_OC_ADDRESS_ARRAY|(j<<CACHE_OC_WAY_SHIFT)|
-				(i<<CACHE_OC_ENTRY_SHIFT);
-			data = ctrl_inl(addr);
-			if ((data & (CACHE_UPDATED|CACHE_VALID))
-			    == (CACHE_UPDATED|CACHE_VALID))
-				ctrl_outl(data & ~CACHE_UPDATED, addr);
-		}
-	}
-}
-
-static void __init
+static int __init
 detect_cpu_and_cache_system(void)
 {
 	unsigned long addr0, addr1, data0, data1, data2, data3;
@@ -99,54 +37,53 @@
 
 	/* First, write back & invalidate */
 	data0  = ctrl_inl(addr0);
-	ctrl_outl(data0&~(CACHE_VALID|CACHE_UPDATED), addr0);
+	ctrl_outl(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0);
 	data1  = ctrl_inl(addr1);
-	ctrl_outl(data1&~(CACHE_VALID|CACHE_UPDATED), addr1);
+	ctrl_outl(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1);
 
 	/* Next, check if there's shadow or not */
 	data0 = ctrl_inl(addr0);
-	data0 ^= CACHE_VALID;
+	data0 ^= SH_CACHE_VALID;
 	ctrl_outl(data0, addr0);
 	data1 = ctrl_inl(addr1);
-	data2 = data1 ^ CACHE_VALID;
+	data2 = data1 ^ SH_CACHE_VALID;
 	ctrl_outl(data2, addr1);
 	data3 = ctrl_inl(addr0);
 
 	/* Lastly, invaliate them. */
-	ctrl_outl(data0&~CACHE_VALID, addr0);
-	ctrl_outl(data2&~CACHE_VALID, addr1);
+	ctrl_outl(data0&~SH_CACHE_VALID, addr0);
+	ctrl_outl(data2&~SH_CACHE_VALID, addr1);
+
 	back_to_P1();
 
+	cpu_data->dcache.ways		= 4;
+	cpu_data->dcache.entry_shift	= 4;
+	cpu_data->dcache.linesz		= L1_CACHE_BYTES;
+	cpu_data->dcache.flags		= 0;
+
+	/*
+	 * 7709A/7729 has 16K cache (256-entry), while 7702 has only
+	 * 2K(direct) 7702 is not supported (yet)
+	 */
 	if (data0 == data1 && data2 == data3) {	/* Shadow */
-		cache_system_info.way_shift = 11;
-		cache_system_info.entry_mask = 0x7f0;
-		cache_system_info.num_entries = 128;
+		cpu_data->dcache.way_shift	= 11;
+		cpu_data->dcache.entry_mask	= 0x7f0;
+		cpu_data->dcache.sets		= 128;
 		cpu_data->type = CPU_SH7708;
 	} else {				/* 7709A or 7729  */
-		cache_system_info.way_shift = 12;
-		cache_system_info.entry_mask = 0xff0;
-		cache_system_info.num_entries = 256;
+		cpu_data->dcache.way_shift	= 12;
+		cpu_data->dcache.entry_mask	= 0xff0;
+		cpu_data->dcache.sets		= 256;
 		cpu_data->type = CPU_SH7729;
 	}
-}
-
-void __init cache_init(void)
-{
-	unsigned long ccr;
 
-	detect_cpu_and_cache_system();
-
-	jump_to_P2();
-	ccr = ctrl_inl(CCR);
-	if (ccr & CCR_CACHE_CE)
 		/*
-		 * XXX: Should check RA here. 
-		 * If RA was 1, we only need to flush the half of the caches.
+	 * SH-3 doesn't have seperate caches
 		 */
-		cache_wback_all();
+	cpu_data->dcache.flags |= SH_CACHE_COMBINED;
+	cpu_data->icache = cpu_data->dcache;
 
-	ctrl_outl(CCR_CACHE_INIT, CCR);
-	back_to_P1();
+	return 0;
 }
 
 /*
@@ -170,23 +107,24 @@
 		& ~(L1_CACHE_BYTES-1);
 
 	for (v = begin; v < end; v+=L1_CACHE_BYTES) {
-		for (j=0; j<CACHE_OC_NUM_WAYS; j++) {
+		for (j = 0; j < cpu_data->dcache.ways; j++) {
 			unsigned long data, addr, p;
 
 			p = __pa(v);
-			addr = CACHE_OC_ADDRESS_ARRAY|(j<<CACHE_OC_WAY_SHIFT)|
-				(v&CACHE_OC_ENTRY_MASK);
-			save_and_cli(flags);
+			addr = CACHE_OC_ADDRESS_ARRAY |
+				(j << cpu_data->dcache.way_shift)|
+				(v & cpu_data->dcache.entry_mask);
+			local_irq_save(flags);
 			data = ctrl_inl(addr);
 			
 			if ((data & CACHE_PHYSADDR_MASK) ==
 			    (p & CACHE_PHYSADDR_MASK)) {
-				data &= ~CACHE_UPDATED;
+				data &= ~SH_CACHE_UPDATED;
 				ctrl_outl(data, addr);
-				restore_flags(flags);
+				local_irq_restore(flags);
 				break;
 			}
-			restore_flags(flags);
+			local_irq_restore(flags);
 		}
 	}
 }
@@ -210,8 +148,8 @@
 		unsigned long data, addr;
 
 		data = (v & 0xfffffc00); /* _Virtual_ address, ~U, ~V */
-		addr = CACHE_OC_ADDRESS_ARRAY | (v&CACHE_OC_ENTRY_MASK) | 
-			CACHE_OC_ASSOC_BIT;
+		addr = CACHE_OC_ADDRESS_ARRAY |
+			(v & cpu_data->dcache.entry_mask) | SH_CACHE_ASSOC;
 		ctrl_outl(data, addr);
 	}
 }
diff -urN linux-2.5.73-bk9/arch/sh/mm/cache-sh4.c linux-2.5.73-bk10/arch/sh/mm/cache-sh4.c
--- linux-2.5.73-bk9/arch/sh/mm/cache-sh4.c	2003-06-22 11:32:36.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/mm/cache-sh4.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,9 +1,9 @@
-/* $Id: cache-sh4.c,v 1.16 2001/09/10 11:06:35 dwmw2 Exp $
+/* $Id: cache-sh4.c,v 1.20 2003/05/10 03:22:05 sugioka Exp $
  *
- *  linux/arch/sh/mm/cache.c
- *
- * Copyright (C) 1999, 2000  Niibe Yutaka
+ *  linux/arch/sh/mm/cache-sh4.c
  *
+ * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
+ * Copyright (C) 2001, 2002, 2003  Paul Mundt
  */
 
 #include <linux/config.h>
@@ -20,96 +20,100 @@
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
 
-#define CCR		 0xff00001c	/* Address of Cache Control Register */
-
-#define CCR_CACHE_OCE	0x0001	/* Operand Cache Enable */
-#define CCR_CACHE_WT	0x0002	/* Write-Through (for P0,U0,P3) (else writeback)*/
-#define CCR_CACHE_CB	0x0004	/* Copy-Back (for P1) (else writethrough) */
-#define CCR_CACHE_OCI	0x0008	/* OC Invalidate */
-#define CCR_CACHE_ORA	0x0020	/* OC RAM Mode */
-#define CCR_CACHE_OIX	0x0080	/* OC Index Enable */
-#define CCR_CACHE_ICE	0x0100	/* Instruction Cache Enable */
-#define CCR_CACHE_ICI	0x0800	/* IC Invalidate */
-#define CCR_CACHE_IIX	0x8000	/* IC Index Enable */
-
-/* Default CCR setup: 8k+16k-byte cache,P1-wb,enable */
-#define CCR_CACHE_VAL	(CCR_CACHE_ICE|CCR_CACHE_CB|CCR_CACHE_OCE)
-#define CCR_CACHE_INIT	(CCR_CACHE_VAL|CCR_CACHE_OCI|CCR_CACHE_ICI)
-#define CCR_CACHE_ENABLE (CCR_CACHE_OCE|CCR_CACHE_ICE)
-
-#define CACHE_IC_ADDRESS_ARRAY 0xf0000000
-#define CACHE_OC_ADDRESS_ARRAY 0xf4000000
-#define CACHE_VALID	  1
-#define CACHE_UPDATED	  2
-
-#define CACHE_OC_WAY_SHIFT       13
-#define CACHE_IC_WAY_SHIFT       13
-#define CACHE_OC_ENTRY_SHIFT      5
-#define CACHE_IC_ENTRY_SHIFT      5
-#define CACHE_OC_ENTRY_MASK		0x3fe0
-#define CACHE_OC_ENTRY_PHYS_MASK	0x0fe0
-#define CACHE_IC_ENTRY_MASK		0x1fe0
-#define CACHE_IC_NUM_ENTRIES	256
-#define CACHE_OC_NUM_ENTRIES	512
-
-static void __init
-detect_cpu_and_cache_system(void)
-{
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-	cpu_data->type = CPU_ST40STB1;
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
-	cpu_data->type = CPU_SH7750;
-#else
-#error Unknown SH4 CPU type
-#endif
-}
-
-void __init cache_init(void)
+extern void __flush_cache_4096_all(unsigned long start);
+static void __flush_cache_4096_all_ex(unsigned long start);
+extern void __flush_dcache_all(void);
+static void __flush_dcache_all_ex(void);
+/*
+ * FIXME: Add ST40STB1 probe support (and clean up the manual overdrive stuff)
+ * seems to rely on some quirky PVR shifting .. stuart? ++paulm
+ */
+int __init detect_cpu_and_cache_system(void)
 {
-	unsigned long ccr;
+	unsigned long pvr, prr, ccr;
 
-	detect_cpu_and_cache_system();
+	pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff;
+	prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff;
 
-	jump_to_P2();
-	ccr = ctrl_inl(CCR);
-	if (ccr & CCR_CACHE_ENABLE) {
 		/*
-		 * XXX: Should check RA here. 
-		 * If RA was 1, we only need to flush the half of the caches.
+	 * Setup some sane SH-4 defaults for the icache
 		 */
-		unsigned long addr, data;
+	cpu_data->icache.way_shift	= 13;
+	cpu_data->icache.entry_shift	= 5;
+	cpu_data->icache.entry_mask	= 0x1fe0;
+	cpu_data->icache.sets		= 256;
+	cpu_data->icache.ways		= 1;
+	cpu_data->icache.linesz		= L1_CACHE_BYTES;
+
+	/*
+	 * And again for the dcache ..
+	 */
+	cpu_data->dcache.way_shift	= 14;
+	cpu_data->dcache.entry_shift	= 5;
+	cpu_data->dcache.entry_mask	= 0x3fe0;
+	cpu_data->dcache.sets		= 512;
+	cpu_data->dcache.ways		= 1;
+	cpu_data->dcache.linesz		= L1_CACHE_BYTES;
 
-		for (addr = CACHE_OC_ADDRESS_ARRAY;
-		     addr < (CACHE_OC_ADDRESS_ARRAY+
-			     (CACHE_OC_NUM_ENTRIES << CACHE_OC_ENTRY_SHIFT));
-		     addr += (1 << CACHE_OC_ENTRY_SHIFT)) {
-			data = ctrl_inl(addr);
-			if ((data & (CACHE_UPDATED|CACHE_VALID))
-			    == (CACHE_UPDATED|CACHE_VALID))
-				ctrl_outl(data & ~CACHE_UPDATED, addr);
+	/*
+	 * Probe the underlying processor version/revision and
+	 * adjust cpu_data setup accordingly.
+	 */
+	switch (pvr) {
+	case 0x205:
+		cpu_data->type = CPU_SH7750;
+		break;
+	case 0x206:
+		cpu_data->type = CPU_SH7750S;
+		break;
+	case 0x1100:
+		cpu_data->type = CPU_SH7751;
+		break;
+	case 0x8000:
+		cpu_data->type = CPU_ST40RA;
+		break;
+	case 0x8100:
+		cpu_data->type = CPU_ST40GX1;
+		break;
+	case 0x500:
+		if (prr == 0x10)
+			cpu_data->type = CPU_SH7750R;
+		else
+			cpu_data->type = CPU_SH7751R;
+		jump_to_P2();
+		ccr = ctrl_inl(CCR);
+		back_to_P1();
+		if(ccr & CCR_CACHE_EMODE) {
+			cpu_data->icache.ways = 2;
+			cpu_data->dcache.ways = 2;
 		}
+		break;
+	default:
+		cpu_data->type = CPU_SH_NONE;
+		break;
 	}
 
-	ctrl_outl(CCR_CACHE_INIT, CCR);
-	back_to_P1();
+	/*
+	 * For now, all SH-4's have an FPU ..
+	 */
+	cpu_data->flags |= CPU_HAS_FPU;
+
+	return 0;
 }
 
 /*
  * SH-4 has virtually indexed and physically tagged cache.
  */
 
-static struct semaphore p3map_sem[4];
+struct semaphore p3map_sem[4];
 
 void __init p3_cache_init(void)
 {
-	/* In ioremap.c */
-	extern int remap_area_pages(unsigned long address,
-				    unsigned long phys_addr,
-				    unsigned long size, unsigned long flags);
-
 	if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE))
-		panic("p3_cachie_init failed.");
+		panic("%s failed.", __FUNCTION__);
+
 	sema_init (&p3map_sem[0], 1);
 	sema_init (&p3map_sem[1], 1);
 	sema_init (&p3map_sem[2], 1);
@@ -177,6 +181,40 @@
 	}
 }
 
+static void __flush_dcache_all_ex(void)
+{
+	unsigned long addr, end_addr, entry_offset;
+
+	end_addr = CACHE_OC_ADDRESS_ARRAY + (cpu_data->dcache.sets << cpu_data->dcache.entry_shift) * cpu_data->dcache.ways;
+	entry_offset = 1 << cpu_data->dcache.entry_shift;
+	for (addr = CACHE_OC_ADDRESS_ARRAY; addr < end_addr; addr += entry_offset) {
+		ctrl_outl(0, addr);
+	}
+}
+
+static void __flush_cache_4096_all_ex(unsigned long start)
+{
+	unsigned long addr, entry_offset;
+	int i;
+
+	entry_offset = 1 << cpu_data->dcache.entry_shift;
+	for (i = 0; i < cpu_data->dcache.ways; i++, start += (1 << cpu_data->dcache.way_shift)) {
+		for (addr = CACHE_OC_ADDRESS_ARRAY + start;
+		     addr < CACHE_OC_ADDRESS_ARRAY + 4096 + start;
+		     addr += entry_offset) {
+			ctrl_outl(0, addr);
+		}
+	}
+}
+
+void flush_cache_4096_all(unsigned long start)
+{
+	if (cpu_data->dcache.ways == 1)
+		__flush_cache_4096_all(start);
+	else
+		__flush_cache_4096_all_ex(start);
+}
+
 /*
  * Write back the range of D-cache, and purge the I-cache.
  *
@@ -189,63 +227,51 @@
 
 /*
  * Write back the D-cache and purge the I-cache for signal trampoline. 
+ * .. which happens to be the same behavior as flush_icache_range().
+ * So, we simply flush out a line.
  */
 void flush_cache_sigtramp(unsigned long addr)
 {
 	unsigned long v, index;
 	unsigned long flags; 
+	int i;
 
 	v = addr & ~(L1_CACHE_BYTES-1);
 	asm volatile("ocbwb	%0"
 		     : /* no output */
 		     : "m" (__m(v)));
 
-	index = CACHE_IC_ADDRESS_ARRAY| (v&CACHE_IC_ENTRY_MASK);
-	save_and_cli(flags);
+	index = CACHE_IC_ADDRESS_ARRAY | (v & cpu_data->icache.entry_mask);
+
+	local_irq_save(flags);
 	jump_to_P2();
-	ctrl_outl(0, index);	/* Clear out Valid-bit */
+	for(i = 0; i < cpu_data->icache.ways; i++, index += (1 << cpu_data->icache.way_shift))
+		ctrl_outl(0, index);	/* Clear out Valid-bit */
 	back_to_P1();
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
-/*
- * Writeback&Invalidate the D-cache of the page
- */
-static void __flush_dcache_page(unsigned long phys)
+static inline void flush_cache_4096(unsigned long start,
+				    unsigned long phys)
 {
-	unsigned long addr, data;
-	unsigned long flags;
-
-	phys |= CACHE_VALID;
-
-	save_and_cli(flags);
-	jump_to_P2();
-
-	/* Loop all the D-cache */
-	for (addr = CACHE_OC_ADDRESS_ARRAY;
-	     addr < (CACHE_OC_ADDRESS_ARRAY
-		     +(CACHE_OC_NUM_ENTRIES<< CACHE_OC_ENTRY_SHIFT));
-	     addr += (1<<CACHE_OC_ENTRY_SHIFT)) {
-		data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-		if (data == phys)
-			ctrl_outl(0, addr);
-	}
+	unsigned long flags; 
+	extern void __flush_cache_4096(unsigned long addr, unsigned long phys, unsigned long exec_offset);
 
-#if 0 /* DEBUG DEBUG */
-	/* Loop all the I-cache */
-	for (addr = CACHE_IC_ADDRESS_ARRAY;
-	     addr < (CACHE_IC_ADDRESS_ARRAY
-		     +(CACHE_IC_NUM_ENTRIES<< CACHE_IC_ENTRY_SHIFT));
-	     addr += (1<<CACHE_IC_ENTRY_SHIFT)) {
-		data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-		if (data == phys) {
-			printk(KERN_INFO "__flush_cache_page: I-cache entry found\n");
-			ctrl_outl(0, addr);
-		}
+		/*
+	 * SH7751, SH7751R, and ST40 have no restriction to handle cache.
+		 * (While SH7750 must do that at P2 area.)
+		 */
+	if ((cpu_data->type == CPU_SH7751 ||
+	     cpu_data->type == CPU_SH7751R ||
+	     cpu_data->type == CPU_ST40RA ||
+	     cpu_data->type == CPU_ST40GX1) &&
+		(start >= CACHE_OC_ADDRESS_ARRAY)) {
+		__flush_cache_4096(start | SH_CACHE_ASSOC, phys | 0x80000000, 0);
+	} else {
+		local_irq_save(flags);
+		__flush_cache_4096(start | SH_CACHE_ASSOC, phys | 0x80000000, 0x20000000);
+		local_irq_restore(flags);
 	}
-#endif
-	back_to_P1();
-	restore_flags(flags);
 }
 
 /*
@@ -254,38 +280,82 @@
  */
 void flush_dcache_page(struct page *page)
 {
-	if (test_bit(PG_mapped, &page->flags))
-		__flush_dcache_page(PHYSADDR(page_address(page)));
+	if (test_bit(PG_mapped, &page->flags)) {
+		unsigned long phys = PHYSADDR(page_address(page));
+
+		/* Loop all the D-cache */
+		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY,          phys);
+		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys);
+		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys);
+		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys);
+	}
 }
 
-void flush_cache_all(void)
+static inline void flush_icache_all(void)
 {
-	extern unsigned long empty_zero_page[1024];
-	unsigned long flags;
-	unsigned long addr;
-
-	save_and_cli(flags);
-
-	/* Prefetch the data to write back D-cache */
-	for (addr = (unsigned long)empty_zero_page;
-	     addr < (unsigned long)empty_zero_page + 1024*16;
-	     addr += L1_CACHE_BYTES)
-		asm volatile("pref @%0"::"r" (addr));
+	unsigned long flags, ccr;
 
+	local_irq_save(flags);
 	jump_to_P2();
-	/* Flush D-cache/I-cache */
-	ctrl_outl(CCR_CACHE_INIT, CCR);
+
+	/* Flush I-cache */
+	ccr = ctrl_inl(CCR);
+	ccr |= CCR_CACHE_ICI;
+	ctrl_outl(ccr, CCR);
+
 	back_to_P1();
-	restore_flags(flags);
+	local_irq_restore(flags);
+}
+
+void flush_cache_all(void)
+{
+	if (cpu_data->dcache.ways == 1)
+		__flush_dcache_all();
+	else
+		__flush_dcache_all_ex();
+	flush_icache_all();
 }
 
 void flush_cache_mm(struct mm_struct *mm)
 {
 	/* Is there any good way? */
 	/* XXX: possibly call flush_cache_range for each vm area */
+	/* 
+	 * FIXME: Really, the optimal solution here would be able to flush out
+	 * individual lines created by the specified context, but this isn't
+	 * feasible for a number of architectures (such as MIPS, and some
+	 * SPARC) .. is this possible for SuperH?
+	 *
+	 * In the meantime, we'll just flush all of the caches.. this
+	 * seems to be the simplest way to avoid at least a few wasted
+	 * cache flushes. -Lethal
+	 */
 	flush_cache_all();
 }
 
+static void __flush_cache_page(struct vm_area_struct *vma,
+			       unsigned long address,
+			       unsigned long phys)
+{
+	/* We only need to flush D-cache when we have alias */
+	if ((address^phys) & CACHE_ALIAS) {
+		/* Loop 4K of the D-cache */
+		flush_cache_4096(
+			CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS),
+			phys);
+		/* Loop another 4K of the D-cache */
+		flush_cache_4096(
+			CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS),
+			phys);
+	}
+
+	if (vma->vm_flags & VM_EXEC)
+		/* Loop 4K (half) of the I-cache */
+		flush_cache_4096(
+			CACHE_IC_ADDRESS_ARRAY | (address & 0x1000),
+			phys);
+}
+
 /*
  * Write back and invalidate D-caches.
  *
@@ -298,14 +368,52 @@
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
 		       unsigned long end)
 {
-	/*
-	 * We could call flush_cache_page for the pages of these range,
-	 * but it's not efficient (scan the caches all the time...).
-	 *
-	 * We can't use A-bit magic, as there's the case we don't have
-	 * valid entry on TLB.
-	 */
-	flush_cache_all();
+	unsigned long p = start & PAGE_MASK;
+	pgd_t *dir;
+	pmd_t *pmd;
+	pte_t *pte;
+	pte_t entry;
+	unsigned long phys;
+	unsigned long d = 0;
+
+	dir = pgd_offset(vma->vm_mm, p);
+	pmd = pmd_offset(dir, p);
+
+	do {
+		if (pmd_none(*pmd) || pmd_bad(*pmd)) {
+			p &= ~((1 << PMD_SHIFT) -1);
+			p += (1 << PMD_SHIFT);
+			pmd++;
+			continue;
+		}
+		pte = pte_offset_kernel(pmd, p);
+		do {
+			entry = *pte;
+			if ((pte_val(entry) & _PAGE_PRESENT)) {
+				phys = pte_val(entry)&PTE_PHYS_MASK;
+				if ((p^phys) & CACHE_ALIAS) {
+					d |= 1 << ((p & CACHE_ALIAS)>>12); 
+					d |= 1 << ((phys & CACHE_ALIAS)>>12);
+					if (d == 0x0f)
+						goto loop_exit;
+				}
+			}
+			pte++;
+			p += PAGE_SIZE;
+		} while (p < end && (unsigned long)pte & PAGE_MASK);
+		pmd++;
+	} while (p < end);
+ loop_exit:
+	if (d & 1)
+		flush_cache_4096_all(0);
+	if (d & 2)
+		flush_cache_4096_all(0x1000);
+	if (d & 4)
+		flush_cache_4096_all(0x2000);
+	if (d & 8)
+		flush_cache_4096_all(0x3000);
+	if (vma->vm_flags & VM_EXEC)
+		flush_icache_all();
 }
 
 /*
@@ -319,133 +427,31 @@
 	pmd_t *pmd;
 	pte_t *pte;
 	pte_t entry;
-	unsigned long phys, addr, data;
-	unsigned long flags;
+	unsigned long phys;
 
 	dir = pgd_offset(vma->vm_mm, address);
 	pmd = pmd_offset(dir, address);
 	if (pmd_none(*pmd) || pmd_bad(*pmd))
 		return;
-	pte = pte_offset(pmd, address);
+	pte = pte_offset_kernel(pmd, address);
 	entry = *pte;
-	if (pte_none(entry) || !pte_present(entry))
+	if (!(pte_val(entry) & _PAGE_PRESENT))
 		return;
 
 	phys = pte_val(entry)&PTE_PHYS_MASK;
-
-	phys |= CACHE_VALID;
-	save_and_cli(flags);
-	jump_to_P2();
-
-	/* We only need to flush D-cache when we have alias */
-	if ((address^phys) & CACHE_ALIAS) {
-		/* Loop 4K of the D-cache */
-		for (addr = CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS);
-		     addr < (CACHE_OC_ADDRESS_ARRAY + (address & CACHE_ALIAS) 
-			     +(CACHE_OC_NUM_ENTRIES/4<<CACHE_OC_ENTRY_SHIFT));
-		     addr += (1<<CACHE_OC_ENTRY_SHIFT)) {
-			data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-			if (data == phys)
-				ctrl_outl(0, addr);
-		}
-		/* Loop another 4K of the D-cache */
-		for (addr = CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS);
-		     addr < (CACHE_OC_ADDRESS_ARRAY + (phys & CACHE_ALIAS) 
-			     +(CACHE_OC_NUM_ENTRIES/4<<CACHE_OC_ENTRY_SHIFT));
-		     addr += (1<<CACHE_OC_ENTRY_SHIFT)) {
-			data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-			if (data == phys)
-				ctrl_outl(0, addr);
-		}
-	}
-
-	if (vma->vm_flags & VM_EXEC)
-		/* Loop 4K of the I-cache */
-		for (addr = CACHE_IC_ADDRESS_ARRAY|(address&0x1000);
-		     addr < ((CACHE_IC_ADDRESS_ARRAY|(address&0x1000))
-			     +(CACHE_IC_NUM_ENTRIES/2<<CACHE_IC_ENTRY_SHIFT));
-		     addr += (1<<CACHE_IC_ENTRY_SHIFT)) {
-			data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-			if (data == phys)
-				ctrl_outl(0, addr);
-		}
-	back_to_P1();
-	restore_flags(flags);
+	__flush_cache_page(vma, address, phys);
 }
 
 /*
- * clear_user_page
- * @to: P1 address
- * @address: U0 address to be mapped
- */
-void clear_user_page(void *to, unsigned long address)
-{
-	struct page *page = virt_to_page(to);
-
-	__set_bit(PG_mapped, &page->flags);
-	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
-		clear_page(to);
-	else {
-		pgprot_t pgprot = __pgprot(_PAGE_PRESENT | 
-					   _PAGE_RW | _PAGE_CACHABLE |
-					   _PAGE_DIRTY | _PAGE_ACCESSED | 
-					   _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
-		unsigned long phys_addr = PHYSADDR(to);
-		unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
-		pgd_t *dir = pgd_offset_k(p3_addr);
-		pmd_t *pmd = pmd_offset(dir, p3_addr);
-		pte_t *pte = pte_offset(pmd, p3_addr);
-		pte_t entry;
-		unsigned long flags;
-
-		entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
-		down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
-		set_pte(pte, entry);
-		save_and_cli(flags);
-		__flush_tlb_page(get_asid(), p3_addr);
-		restore_flags(flags);
-		update_mmu_cache(NULL, p3_addr, entry);
-		__clear_user_page((void *)p3_addr, to);
-		pte_clear(pte);
-		up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
-	}
+ * flush_icache_user_range
+ * @vma: VMA of the process
+ * @page: page
+ * @addr: U0 address
+ * @len: length of the range (< page size)
+ */
+void flush_icache_user_range(struct vm_area_struct *vma,
+			     struct page *page, unsigned long addr, int len)
+{
+	__flush_cache_page(vma, addr, PHYSADDR(page_address(page)));
 }
 
-/*
- * copy_user_page
- * @to: P1 address
- * @from: P1 address
- * @address: U0 address to be mapped
- */
-void copy_user_page(void *to, void *from, unsigned long address)
-{
-	struct page *page = virt_to_page(to);
-
-	__set_bit(PG_mapped, &page->flags);
-	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
-		copy_page(to, from);
-	else {
-		pgprot_t pgprot = __pgprot(_PAGE_PRESENT | 
-					   _PAGE_RW | _PAGE_CACHABLE |
-					   _PAGE_DIRTY | _PAGE_ACCESSED | 
-					   _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
-		unsigned long phys_addr = PHYSADDR(to);
-		unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
-		pgd_t *dir = pgd_offset_k(p3_addr);
-		pmd_t *pmd = pmd_offset(dir, p3_addr);
-		pte_t *pte = pte_offset(pmd, p3_addr);
-		pte_t entry;
-		unsigned long flags;
-
-		entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
-		down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
-		set_pte(pte, entry);
-		save_and_cli(flags);
-		__flush_tlb_page(get_asid(), p3_addr);
-		restore_flags(flags);
-		update_mmu_cache(NULL, p3_addr, entry);
-		__copy_user_page((void *)p3_addr, from, to);
-		pte_clear(pte);
-		up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
-	}
-}
diff -urN linux-2.5.73-bk9/arch/sh/mm/clear_page.S linux-2.5.73-bk10/arch/sh/mm/clear_page.S
--- linux-2.5.73-bk9/arch/sh/mm/clear_page.S	2003-06-22 11:32:37.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/mm/clear_page.S	2003-07-02 04:57:23.000000000 -0700
@@ -1,10 +1,13 @@
-/* $Id: clear_page.S,v 1.1 2001/07/23 10:08:50 gniibe Exp $
+/* $Id: clear_page.S,v 1.12 2003/05/10 03:22:05 sugioka Exp $
  *
- * clear_page implementation of SuperH
+ * __clear_user_page, __clear_user, clear_page implementation of SuperH
  *
- * Copyright (C) 2001  Niibe Yutaka & Kaz Kojima
+ * Copyright (C) 2001  Kaz Kojima
+ * Copyright (C) 2001, 2002  Niibe Yutaka
  *
  */
+#include <linux/config.h>
+#include <linux/linkage.h>
 
 /*
  * clear_page
@@ -18,7 +21,6 @@
  * r4 --- to
  * r5 --- to + 4096
  */
-#include <linux/linkage.h>
 ENTRY(clear_page)
 	mov	r4,r5
 	mov.w	.Llimit,r0
@@ -26,9 +28,9 @@
 	mov	#0,r0
 	!
 1:
-#if defined(__sh3__)
+#if defined(CONFIG_CPU_SH3)
 	mov.l	r0,@r4
-#elif defined(__SH4__)
+#elif defined(CONFIG_CPU_SH4)
 	movca.l	r0,@r4
 	mov	r4,r1
 #endif
@@ -40,7 +42,7 @@
 	mov.l	r0,@-r4
 	mov.l	r0,@-r4
 	mov.l	r0,@-r4
-#if defined(__SH4__)
+#if defined(CONFIG_CPU_SH4)
 	ocbwb	@r1
 #endif
 	cmp/eq	r5,r4
@@ -50,3 +52,244 @@
 	rts
 	 nop
 .Llimit:	.word	(4096-28)
+
+ENTRY(__clear_user)
+	!
+	mov	#0, r0
+	mov	#0xe0, r1	! 0xffffffe0
+	!
+	! r4..(r4+31)&~32 	   -------- not aligned	[ Area 0 ]
+	! (r4+31)&~32..(r4+r5)&~32 -------- aligned	[ Area 1 ]
+	! (r4+r5)&~32..r4+r5       -------- not aligned	[ Area 2 ]
+	!
+	! Clear area 0
+	mov	r4, r2
+	!
+	tst	r1, r5		! length < 32
+	bt	.Larea2		! skip to remainder
+	!
+	add	#31, r2
+	and	r1, r2
+	cmp/eq	r4, r2
+	bt	.Larea1
+	mov	r2, r3
+	sub	r4, r3
+	mov	r3, r7
+	mov	r4, r2
+	!
+.L0:	dt	r3
+0:	mov.b	r0, @r2
+	bf/s	.L0
+	 add	#1, r2
+	!
+	sub	r7, r5
+	mov	r2, r4
+.Larea1:
+	mov	r4, r3
+	add	r5, r3
+	and	r1, r3
+	cmp/hi	r2, r3
+	bf	.Larea2
+	!
+	! Clear area 1
+#if defined(CONFIG_CPU_SH4)
+1:	movca.l	r0, @r2
+#else
+1:	mov.l	r0, @r2
+#endif
+	add	#4, r2
+2:	mov.l	r0, @r2
+	add	#4, r2
+3:	mov.l	r0, @r2
+	add	#4, r2
+4:	mov.l	r0, @r2
+	add	#4, r2
+5:	mov.l	r0, @r2
+	add	#4, r2
+6:	mov.l	r0, @r2
+	add	#4, r2
+7:	mov.l	r0, @r2
+	add	#4, r2
+8:	mov.l	r0, @r2
+	add	#4, r2
+	cmp/hi	r2, r3
+	bt/s	1b
+	 nop
+	!
+	! Clear area 2
+.Larea2:
+	mov	r4, r3
+	add	r5, r3
+	cmp/hs	r3, r2
+	bt/s	.Ldone
+	 sub	r2, r3
+.L2:	dt	r3
+9:	mov.b	r0, @r2
+	bf/s	.L2
+	 add	#1, r2
+	!
+.Ldone:	rts
+	 mov	#0, r0	! return 0 as normal return
+
+	! return the number of bytes remained
+.Lbad_clear_user:
+	mov	r4, r0
+	add	r5, r0
+	rts
+	 sub	r2, r0
+
+.section __ex_table,"a"
+	.align 2
+	.long	0b, .Lbad_clear_user
+	.long	1b, .Lbad_clear_user
+	.long	2b, .Lbad_clear_user
+	.long	3b, .Lbad_clear_user
+	.long	4b, .Lbad_clear_user
+	.long	5b, .Lbad_clear_user
+	.long	6b, .Lbad_clear_user
+	.long	7b, .Lbad_clear_user
+	.long	8b, .Lbad_clear_user
+	.long	9b, .Lbad_clear_user
+.previous
+
+#if defined(CONFIG_CPU_SH4)
+/*
+ * __clear_user_page
+ * @to: P3 address (with same color)
+ * @orig_to: P1 address
+ *
+ * void __clear_user_page(void *to, void *orig_to)
+ */
+
+/*
+ * r0 --- scratch 
+ * r4 --- to
+ * r5 --- orig_to
+ * r6 --- to + 4096
+ */
+ENTRY(__clear_user_page)
+	mov.w	.L4096,r0
+	mov	r4,r6
+	add	r0,r6
+	mov	#0,r0
+	!
+1:	ocbi	@r5
+	add	#32,r5
+	movca.l	r0,@r4
+	mov	r4,r1
+	add	#32,r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	add	#28,r4
+	cmp/eq	r6,r4
+	bf/s	1b
+	 ocbwb	@r1
+	!
+	rts
+	 nop
+.L4096:	.word	4096
+
+ENTRY(__flush_cache_4096)
+	mov.l	1f,r3
+	add	r6,r3
+	mov	r4,r0
+	mov	#64,r2
+	shll	r2
+	mov	#64,r6
+	jmp	@r3
+	 mov	#96,r7
+	.align	2
+1:	.long	2f
+2:
+	.rept	32
+	mov.l	r5,@r0
+	mov.l	r5,@(32,r0)
+	mov.l	r5,@(r0,r6)
+	mov.l	r5,@(r0,r7)
+	add	r2,r5
+	add	r2,r0
+	.endr
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	rts
+	 nop
+
+ENTRY(__flush_dcache_all)
+	mov.l	2f,r0
+	mov.l	3f,r4
+	and	r0,r4		! r4 = (unsigned long)&empty_zero_page[0] & ~0xffffc000
+	stc	sr,r1		! save SR
+	mov.l	4f,r2
+	or	r1,r2
+	mov	#32,r3
+	shll2	r3
+1:
+	ldc	r2,sr		! set BL bit
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	ldc	r1,sr		! restore SR
+	dt	r3
+	bf/s	1b
+	 add	#32,r4
+
+	rts
+	 nop
+	.align	2
+2:	.long	0xffffc000
+3:	.long	empty_zero_page
+4:	.long	0x10000000	! BL bit
+
+/* __flush_cache_4096_all(unsigned long addr) */
+ENTRY(__flush_cache_4096_all)
+	mov.l	2f,r0
+	mov.l	3f,r2
+	and	r0,r2
+	or	r2,r4		! r4 = addr | (unsigned long)&empty_zero_page[0] & ~0x3fff
+	stc	sr,r1		! save SR
+	mov.l	4f,r2
+	or	r1,r2
+	mov	#32,r3
+1:
+	ldc	r2,sr		! set BL bit
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	ldc	r1,sr		! restore SR
+	dt	r3
+	bf/s	1b
+	 add	#32,r4
+
+	rts
+	 nop
+	.align	2
+2:	.long	0xffffc000
+3:	.long	empty_zero_page
+4:	.long	0x10000000	! BL bit
+#endif
diff -urN linux-2.5.73-bk9/arch/sh/mm/copy_page.S linux-2.5.73-bk10/arch/sh/mm/copy_page.S
--- linux-2.5.73-bk9/arch/sh/mm/copy_page.S	2003-06-22 11:32:32.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/mm/copy_page.S	2003-07-02 04:57:23.000000000 -0700
@@ -1,10 +1,12 @@
-/* $Id: copy_page.S,v 1.2 2001/07/23 10:27:25 gniibe Exp $
+/* $Id: copy_page.S,v 1.7 2003/05/04 19:29:54 lethal Exp $
  *
- * copy_page implementation of SuperH
+ * copy_page, __copy_user_page, __copy_user implementation of SuperH
  *
  * Copyright (C) 2001  Niibe Yutaka & Kaz Kojima
+ * Copyright (C) 2002  Toshinobu Sugioka
  *
  */
+#include <linux/linkage.h>
 
 /*
  * copy_page
@@ -21,7 +23,6 @@
  * r10 --- to
  * r11 --- from
  */
-#include <linux/linkage.h>
 ENTRY(copy_page)
 	mov.l	r8,@-r15
 	mov.l	r10,@-r15
@@ -40,9 +41,9 @@
 	mov.l	@r11+,r5
 	mov.l	@r11+,r6
 	mov.l	@r11+,r7
-#if defined(__sh3__)
+#if defined(CONFIG_CPU_SH3)
 	mov.l	r0,@r10
-#elif defined(__SH4__)
+#elif defined(CONFIG_CPU_SH4)
 	movca.l	r0,@r10
 	mov	r10,r0
 #endif
@@ -54,7 +55,7 @@
 	mov.l	r3,@-r10
 	mov.l	r2,@-r10
 	mov.l	r1,@-r10
-#if defined(__SH4__)
+#if defined(CONFIG_CPU_SH4)
 	ocbwb	@r0
 #endif
 	cmp/eq	r11,r8
@@ -66,4 +67,331 @@
 	mov.l	@r15+,r8
 	rts
 	 nop
+
+#if defined(CONFIG_CPU_SH4)
+/*
+ * __copy_user_page
+ * @to: P1 address (with same color)
+ * @from: P1 address
+ * @orig_to: P1 address
+ *
+ * void __copy_user_page(void *to, void *from, void *orig_to)
+ */
+
+/*
+ * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch 
+ * r8 --- from + 4096
+ * r9 --- orig_to
+ * r10 --- to
+ * r11 --- from
+ */
+ENTRY(__copy_user_page)
+	mov.l	r8,@-r15
+	mov.l	r9,@-r15
+	mov.l	r10,@-r15
+	mov.l	r11,@-r15
+	mov	r4,r10
+	mov	r5,r11
+	mov	r6,r9
+	mov	r5,r8
+	mov.w	.L4096,r0
+	add	r0,r8
+	!
+1:	ocbi	@r9
+	add	#32,r9
+	mov.l	@r11+,r0
+	mov.l	@r11+,r1
+	mov.l	@r11+,r2
+	mov.l	@r11+,r3
+	mov.l	@r11+,r4
+	mov.l	@r11+,r5
+	mov.l	@r11+,r6
+	mov.l	@r11+,r7
+	movca.l	r0,@r10
+	mov	r10,r0
+	add	#32,r10
+	mov.l	r7,@-r10
+	mov.l	r6,@-r10
+	mov.l	r5,@-r10
+	mov.l	r4,@-r10
+	mov.l	r3,@-r10
+	mov.l	r2,@-r10
+	mov.l	r1,@-r10
+	ocbwb	@r0
+	cmp/eq	r11,r8
+	bf/s	1b
+	 add	#28,r10
+	!
+	mov.l	@r15+,r11
+	mov.l	@r15+,r10
+	mov.l	@r15+,r9
+	mov.l	@r15+,r8
+	rts
+	 nop
+#endif
 .L4096:	.word	4096
+/*
+ * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
+ * Return the number of bytes NOT copied
+ */
+#define EX(...)			\
+	9999: __VA_ARGS__ ;		\
+	.section __ex_table, "a";	\
+	.long 9999b, 6000f	;	\
+	.previous
+ENTRY(__copy_user)
+	tst	r6,r6		! Check explicitly for zero
+	bf	1f
+	rts
+	 mov	#0,r0		! normal return
+1:
+	mov.l	r10,@-r15
+	mov.l	r9,@-r15
+	mov.l	r8,@-r15
+	mov	r4,r3
+	add	r6,r3		! last destination address
+	mov	#12,r0		! Check if small number of bytes
+	cmp/gt	r0,r6
+	bt	2f
+	bra	.L_cleanup_loop
+	 nop
+2:
+	neg	r5,r0		! Calculate bytes needed to align source
+	add	#4,r0
+	and	#3,r0
+	tst	r0,r0
+	bt	.L_jump
+	mov	r0,r1
+
+.L_loop1:
+	! Copy bytes to align source
+EX(	mov.b	@r5+,r0		)
+	dt	r1
+EX(	mov.b	r0,@r4		)
+	add	#-1,r6
+	bf/s	.L_loop1
+	 add	#1,r4
+
+.L_jump:
+	mov	r6,r2		! Calculate number of longwords to copy
+	shlr2	r2
+	tst	r2,r2
+	bt	.L_cleanup
+
+	mov	r4,r0		! Jump to appropriate routine
+	and	#3,r0
+	mov	r0,r1
+	shll2	r1
+	mova	.L_jump_tbl,r0
+	mov.l	@(r0,r1),r1
+	jmp	@r1
+	 nop
+
+	.align 2
+.L_jump_tbl:
+	.long	.L_dest00
+	.long	.L_dest01
+	.long	.L_dest10
+	.long	.L_dest11
+
+! Destination = 00
+
+.L_dest00:
+	mov	r2,r7
+	shlr2	r7
+	shlr	r7
+	tst	r7,r7
+	mov	#7,r0
+	bt/s	1f
+	 and	r0,r2
+	.align 2
+2:
+EX(	mov.l	@r5+,r0		)
+EX(	mov.l	@r5+,r8		)
+EX(	mov.l	@r5+,r9		)
+EX(	mov.l	@r5+,r10	)
+EX(	mov.l	r0,@r4		)
+EX(	mov.l	r8,@(4,r4)	)
+EX(	mov.l	r9,@(8,r4)	)
+EX(	mov.l	r10,@(12,r4)	)
+EX(	mov.l	@r5+,r0		)
+EX(	mov.l	@r5+,r8		)
+EX(	mov.l	@r5+,r9		)
+EX(	mov.l	@r5+,r10	)
+	dt	r7
+EX(	mov.l	r0,@(16,r4)	)
+EX(	mov.l	r8,@(20,r4)	)
+EX(	mov.l	r9,@(24,r4)	)
+EX(	mov.l	r10,@(28,r4)	)
+	bf/s	2b
+	 add	#32,r4
+	tst	r2,r2
+	bt	.L_cleanup
+1:
+EX(	mov.l	@r5+,r0		)
+	dt	r2
+EX(	mov.l	r0,@r4		)
+	bf/s	1b
+	 add	#4,r4
+
+	bra	.L_cleanup
+	 nop
+
+! Destination = 10
+
+.L_dest10:
+	mov	r2,r7
+	shlr2	r7
+	shlr	r7
+	tst	r7,r7
+	mov	#7,r0
+	bt/s	1f
+	 and	r0,r2
+2:
+	dt	r7
+#ifdef __LITTLE_ENDIAN__
+EX(	mov.l	@r5+,r0		)
+EX(	mov.l	@r5+,r1		)
+EX(	mov.l	@r5+,r8		)
+EX(	mov.l	@r5+,r9		)
+EX(	mov.l	@r5+,r10	)
+EX(	mov.w	r0,@r4		)
+	add	#2,r4
+	xtrct	r1,r0
+	xtrct	r8,r1
+	xtrct	r9,r8
+	xtrct	r10,r9
+
+EX(	mov.l	r0,@r4		)
+EX(	mov.l	r1,@(4,r4)	)
+EX(	mov.l	r8,@(8,r4)	)
+EX(	mov.l	r9,@(12,r4)	)
+
+EX(	mov.l	@r5+,r1		)
+EX(	mov.l	@r5+,r8		)
+EX(	mov.l	@r5+,r0		)
+	xtrct	r1,r10
+	xtrct	r8,r1
+	xtrct	r0,r8
+	shlr16	r0
+EX(	mov.l	r10,@(16,r4)	)
+EX(	mov.l	r1,@(20,r4)	)
+EX(	mov.l	r8,@(24,r4)	)
+EX(	mov.w	r0,@(28,r4)	)
+	bf/s	2b
+	 add	#30,r4
+#else
+EX(	mov.l	@(28,r5),r0	)
+EX(	mov.l	@(24,r5),r8	)
+EX(	mov.l	@(20,r5),r9	)
+EX(	mov.l	@(16,r5),r10	)
+EX(	mov.w	r0,@(30,r4)	)
+	add	#-2,r4
+	xtrct	r8,r0
+	xtrct	r9,r8
+	xtrct	r10,r9
+EX(	mov.l	r0,@(28,r4)	)
+EX(	mov.l	r8,@(24,r4)	)
+EX(	mov.l	r9,@(20,r4)	)
+
+EX(	mov.l	@(12,r5),r0	)
+EX(	mov.l	@(8,r5),r8	)
+	xtrct	r0,r10
+EX(	mov.l	@(4,r5),r9	)
+	mov.l	r10,@(16,r4)
+EX(	mov.l	@r5,r10		)
+	xtrct	r8,r0
+	xtrct	r9,r8
+	xtrct	r10,r9
+EX(	mov.l	r0,@(12,r4)	)
+EX(	mov.l	r8,@(8,r4)	)
+	swap.w	r10,r0
+EX(	mov.l	r9,@(4,r4)	)
+EX(	mov.w	r0,@(2,r4)	)
+
+	add	#32,r5
+	bf/s	2b
+	 add	#34,r4
+#endif
+	tst	r2,r2
+	bt	.L_cleanup
+
+1:	! Read longword, write two words per iteration
+EX(	mov.l	@r5+,r0		)
+	dt	r2
+#ifdef __LITTLE_ENDIAN__
+EX(	mov.w	r0,@r4		)
+	shlr16	r0
+EX(	mov.w 	r0,@(2,r4)	)
+#else
+EX(	mov.w	r0,@(2,r4)	)
+	shlr16	r0
+EX(	mov.w	r0,@r4		)
+#endif
+	bf/s	1b
+	 add	#4,r4
+
+	bra	.L_cleanup
+	 nop
+
+! Destination = 01 or 11
+
+.L_dest01:
+.L_dest11:
+	! Read longword, write byte, word, byte per iteration
+EX(	mov.l	@r5+,r0		)
+	dt	r2
+#ifdef __LITTLE_ENDIAN__
+EX(	mov.b	r0,@r4		)
+	shlr8	r0
+	add	#1,r4
+EX(	mov.w	r0,@r4		)
+	shlr16	r0
+EX(	mov.b	r0,@(2,r4)	)
+	bf/s	.L_dest01
+	 add	#3,r4
+#else
+EX(	mov.b	r0,@(3,r4)	)
+	shlr8	r0
+	swap.w	r0,r7
+EX(	mov.b	r7,@r4		)
+	add	#1,r4
+EX(	mov.w	r0,@r4		)
+	bf/s	.L_dest01
+	 add	#3,r4
+#endif
+
+! Cleanup last few bytes
+.L_cleanup:
+	mov	r6,r0
+	and	#3,r0
+	tst	r0,r0
+	bt	.L_exit
+	mov	r0,r6
+
+.L_cleanup_loop:
+EX(	mov.b	@r5+,r0		)
+	dt	r6
+EX(	mov.b	r0,@r4		)
+	bf/s	.L_cleanup_loop
+	 add	#1,r4
+
+.L_exit:
+	mov	#0,r0		! normal return
+5000:
+
+# Exception handler:
+.section .fixup, "ax"
+6000:
+	mov.l	8000f,r1
+	mov	r3,r0
+	jmp	@r1
+	 sub	r4,r0
+	.align	2
+8000:	.long	5000b
+
+.previous
+	mov.l	@r15+,r8
+	mov.l	@r15+,r9
+	rts
+	 mov.l	@r15+,r10
diff -urN linux-2.5.73-bk9/arch/sh/mm/extable.c linux-2.5.73-bk10/arch/sh/mm/extable.c
--- linux-2.5.73-bk9/arch/sh/mm/extable.c	2003-06-22 11:32:31.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/mm/extable.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: extable.c,v 1.2 2001/03/31 10:43:18 gniibe Exp $
+/* $Id: extable.c,v 1.3 2003/05/06 23:28:50 lethal Exp $
  *
  * linux/arch/sh/mm/extable.c
  *  Taken from:
@@ -9,11 +9,9 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
-
-static inline unsigned long
-search_one_table(const struct exception_table_entry *first,
+/* Simple binary search */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
 		 const struct exception_table_entry *last,
 		 unsigned long value)
 {
@@ -24,35 +22,25 @@
 		mid = (last - first) / 2 + first;
 		diff = mid->insn - value;
                 if (diff == 0)
-                        return mid->fixup;
+                        return mid;
                 else if (diff < 0)
                         first = mid+1;
                 else
                         last = mid-1;
         }
-        return 0;
+
+        return NULL;
 }
 
-unsigned long
-search_exception_table(unsigned long addr)
+int fixup_exception(struct pt_regs *regs)
 {
-	unsigned long ret;
+	const struct exception_table_entry *fixup;
 
-#ifndef CONFIG_MODULES
-	/* There is only the kernel to search.  */
-	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-	if (ret) return ret;
-#else
-	/* The kernel is the last "module" -- no need to treat it special.  */
-	struct module *mp;
-	for (mp = module_list; mp != NULL; mp = mp->next) {
-		if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
-			continue;
-		ret = search_one_table(mp->ex_table_start,
-				       mp->ex_table_end - 1, addr);
-		if (ret) return ret;
+	fixup = search_exception_tables(regs->pc);
+	if (fixup) {
+		regs->pc = fixup->fixup;
+		return 1;
 	}
-#endif
 
 	return 0;
 }
diff -urN linux-2.5.73-bk9/arch/sh/mm/fault-nommu.c linux-2.5.73-bk10/arch/sh/mm/fault-nommu.c
--- linux-2.5.73-bk9/arch/sh/mm/fault-nommu.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/mm/fault-nommu.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,83 @@
+/* 
+ * arch/sh/mm/fault-nommu.c
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Based on linux/arch/sh/mm/fault.c:
+ *  Copyright (C) 1999  Niibe Yutaka
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+#if defined(CONFIG_SH_KGDB)
+#include <asm/kgdb.h>
+#endif
+
+extern void die(const char *,struct pt_regs *,long);
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+			      unsigned long address)
+{
+#if defined(CONFIG_SH_KGDB)
+	if (kgdb_nofault && kgdb_bus_err_hook)
+		kgdb_bus_err_hook();
+#endif
+
+	/*
+	 * Oops. The kernel tried to access some bad page. We'll have to
+	 * terminate things with extreme prejudice.
+	 *
+	 */
+	if (address < PAGE_SIZE) {
+		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+	} else {
+		printk(KERN_ALERT "Unable to handle kernel paging request");
+	}
+
+	printk(" at virtual address %08lx\n", address);
+	printk(KERN_ALERT "pc = %08lx\n", regs->pc);
+
+	die("Oops", regs, writeaccess);
+	do_exit(SIGKILL);
+}
+
+asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+			       unsigned long address)
+{
+#if defined(CONFIG_SH_KGDB)
+	if (kgdb_nofault && kgdb_bus_err_hook)
+		kgdb_bus_err_hook();
+#endif
+
+	if (address >= TASK_SIZE)
+		return 1;
+
+	return 0;
+}
+
diff -urN linux-2.5.73-bk9/arch/sh/mm/fault.c linux-2.5.73-bk10/arch/sh/mm/fault.c
--- linux-2.5.73-bk9/arch/sh/mm/fault.c	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/mm/fault.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.49 2001/10/06 19:46:00 lethal Exp $
+/* $Id: fault.c,v 1.10 2003/05/04 19:29:54 lethal Exp $
  *
  *  linux/arch/sh/mm/fault.c
  *  Copyright (C) 1999  Niibe Yutaka
@@ -19,6 +19,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -26,6 +27,11 @@
 #include <asm/pgalloc.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+#if defined(CONFIG_SH_KGDB)
+#include <asm/kgdb.h>
+#endif
 
 extern void die(const char *,struct pt_regs *,long);
 
@@ -41,7 +47,12 @@
 	struct mm_struct *mm;
 	struct vm_area_struct * vma;
 	unsigned long page;
-	unsigned long fixup;
+	const struct exception_table_entry *fixup;
+
+#if defined(CONFIG_SH_KGDB)
+	if (kgdb_nofault && kgdb_bus_err_hook)
+	  kgdb_bus_err_hook();
+#endif
 
 	tsk = current;
 	mm = tsk->mm;
@@ -115,9 +126,9 @@
 
 no_context:
 	/* Are we prepared to handle this kernel fault?  */
-	fixup = search_exception_table(regs->pc);
-	if (fixup != 0) {
-		regs->pc = fixup;
+	fixup = search_exception_tables(regs->pc);
+	if (fixup) {
+		regs->pc = fixup->fixup;
 		return;
 	}
 
@@ -192,6 +203,10 @@
 	pte_t *pte;
 	pte_t entry;
 
+#if defined(CONFIG_SH_KGDB)
+	if (kgdb_nofault && kgdb_bus_err_hook)
+	  kgdb_bus_err_hook();
+#endif
 	if (address >= P3SEG && address < P4SEG)
 		dir = pgd_offset_k(address);
 	else if (address >= TASK_SIZE)
@@ -209,7 +224,7 @@
 		pmd_clear(pmd);
 		return 1;
 	}
-	pte = pte_offset(pmd, address);
+	pte = pte_offset_kernel(pmd, address);
 	entry = *pte;
 	if (pte_none(entry) || pte_not_present(entry)
 	    || (writeaccess && !pte_write(entry)))
@@ -218,7 +233,7 @@
 	if (writeaccess)
 		entry = pte_mkdirty(entry);
 	entry = pte_mkyoung(entry);
-#if defined(__SH4__)
+#if defined(CONFIG_CPU_SH4)
 	/*
 	 * ITLB is not affected by "ldtlb" instruction.
 	 * So, we need to flush the entry by ourselves.
@@ -230,81 +245,6 @@
 	return 0;
 }
 
-void update_mmu_cache(struct vm_area_struct * vma,
-		      unsigned long address, pte_t pte)
-{
-	unsigned long flags;
-	unsigned long pteval;
-	unsigned long vpn;
-#if defined(__SH4__)
-	struct page *page;
-	unsigned long pfn;
-	unsigned long ptea;
-#endif
-
-	/* Ptrace may call this routine. */
-	if (vma && current->active_mm != vma->vm_mm)
-		return;
-
-#if defined(__SH4__)
-	pfn = pte_pfn(pte);
-	if (pfn_valid(pfn)) {
-		page = pfn_to_page(pfn);
-		if (!test_bit(PG_mapped, &page->flags)) {
-			unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-			__flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
-			__set_bit(PG_mapped, &page->flags);
-		}
-	}
-#endif
-
-	save_and_cli(flags);
-
-	/* Set PTEH register */
-	vpn = (address & MMU_VPN_MASK) | get_asid();
-	ctrl_outl(vpn, MMU_PTEH);
-
-	pteval = pte_val(pte);
-#if defined(__SH4__)
-	/* Set PTEA register */
-	/* TODO: make this look less hacky */
-	ptea = ((pteval >> 28) & 0xe) | (pteval & 0x1);
-	ctrl_outl(ptea, MMU_PTEA);
-#endif
-
-	/* Set PTEL register */
-	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
-	/* conveniently, we want all the software flags to be 0 anyway */
-	ctrl_outl(pteval, MMU_PTEL);
-
-	/* Load the TLB */
-	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
-	restore_flags(flags);
-}
-
-void __flush_tlb_page(unsigned long asid, unsigned long page)
-{
-	unsigned long addr, data;
-
-	/*
-	 * NOTE: PTEH.ASID should be set to this MM
-	 *       _AND_ we need to write ASID to the array.
-	 *
-	 * It would be simple if we didn't need to set PTEH.ASID...
-	 */
-#if defined(__sh3__)
-	addr = MMU_TLB_ADDRESS_ARRAY |(page & 0x1F000)| MMU_PAGE_ASSOC_BIT;
-	data = (page & 0xfffe0000) | asid; /* VALID bit is off */
-	ctrl_outl(data, addr);
-#elif defined(__SH4__)
-	addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT;
-	data = page | asid; /* VALID bit is off */
-	jump_to_P2();
-	ctrl_outl(data, addr);
-	back_to_P1();
-#endif
-}
-
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
 	if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) {
@@ -315,7 +255,7 @@
 		asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
 		page &= PAGE_MASK;
 
-		save_and_cli(flags);
+		local_irq_save(flags);
 		if (vma->vm_mm != current->mm) {
 			saved_asid = get_asid();
 			set_asid(asid);
@@ -323,7 +263,7 @@
 		__flush_tlb_page(asid, page);
 		if (saved_asid != MMU_NO_ASID)
 			set_asid(saved_asid);
-		restore_flags(flags);
+		local_irq_restore(flags);
 	}
 }
 
@@ -336,7 +276,7 @@
 		unsigned long flags;
 		int size;
 
-		save_and_cli(flags);
+		local_irq_save(flags);
 		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 		if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
 			mm->context = NO_CONTEXT;
@@ -360,8 +300,34 @@
 			if (saved_asid != MMU_NO_ASID)
 				set_asid(saved_asid);
 		}
-		restore_flags(flags);
+		local_irq_restore(flags);
+	}
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	unsigned long flags;
+	int size;
+
+	local_irq_save(flags);
+	size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+	if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
+		flush_tlb_all();
+	} else {
+		unsigned long asid = init_mm.context&MMU_CONTEXT_ASID_MASK;
+		unsigned long saved_asid = get_asid();
+
+		start &= PAGE_MASK;
+		end += (PAGE_SIZE - 1);
+		end &= PAGE_MASK;
+		set_asid(asid);
+		while (start < end) {
+			__flush_tlb_page(asid, start);
+			start += PAGE_SIZE;
+		}
+		set_asid(saved_asid);
 	}
+	local_irq_restore(flags);
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
@@ -371,11 +337,11 @@
 	if (mm->context != NO_CONTEXT) {
 		unsigned long flags;
 
-		save_and_cli(flags);
+		local_irq_save(flags);
 		mm->context = NO_CONTEXT;
 		if (mm == current->mm)
 			activate_context(mm);
-		restore_flags(flags);
+		local_irq_restore(flags);
 	}
 }
 
@@ -390,9 +356,9 @@
 	 * 	TF-bit for SH-3, TI-bit for SH-4.
 	 *      It's same position, bit #2.
 	 */
-	save_and_cli(flags);
+	local_irq_save(flags);
 	status = ctrl_inl(MMUCR);
 	status |= 0x04;		
 	ctrl_outl(status, MMUCR);
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
diff -urN linux-2.5.73-bk9/arch/sh/mm/init.c linux-2.5.73-bk10/arch/sh/mm/init.c
--- linux-2.5.73-bk9/arch/sh/mm/init.c	2003-06-22 11:33:08.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/mm/init.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,8 +1,9 @@
-/* $Id: init.c,v 1.19 2001/10/01 02:21:50 gniibe Exp $
+/* $Id: init.c,v 1.11 2003/05/27 16:21:23 lethal Exp $
  *
  *  linux/arch/sh/mm/init.c
  *
  *  Copyright (C) 1999  Niibe Yutaka
+ *  Copyright (C) 2002  Paul Mundt
  *
  *  Based on linux/arch/i386/mm/init.c:
  *   Copyright (C) 1995  Linus Torvalds
@@ -35,13 +36,22 @@
 #include <asm/mmu_context.h>
 #include <asm/io.h>
 #include <asm/tlb.h>
+#include <asm/cacheflush.h>
+#include <asm/cache.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 /*
  * Cache of MMU context last used.
  */
-unsigned long mmu_context_cache;
+unsigned long mmu_context_cache = NO_CONTEXT;
+
+#ifdef CONFIG_MMU
+/* It'd be good if these lines were in the standard header file. */
+#define START_PFN	(NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
+#define MAX_LOW_PFN	(NODE_DATA(0)->bdata->node_low_pfn)
+#endif
 
 #ifdef CONFIG_DISCONTIGMEM
 pg_data_t discontig_page_data[NR_NODES];
@@ -77,12 +87,6 @@
 extern char _text, _etext, _edata, __bss_start, _end;
 extern char __init_begin, __init_end;
 
-pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
-/* It'd be good if these lines were in the standard header file. */
-#define START_PFN	(NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
-#define MAX_LOW_PFN	(NODE_DATA(0)->bdata->node_low_pfn)
-
 /*
  * paging_init() sets up the page tables
  *
@@ -91,45 +95,75 @@
  */
 void __init paging_init(void)
 {
+	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+
+	/*
+	 * Setup some defaults for the zone sizes.. these should be safe
+	 * regardless of distcontiguous memory or MMU settings.
+	 */
+	zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
+	zones_size[ZONE_NORMAL] = __MEMORY_SIZE >> PAGE_SHIFT;
+#ifdef CONFIG_HIGHMEM
+	zones_size[ZONE_HIGHMEM] = 0 >> PAGE_SHIFT;
+#endif
+
+#ifdef CONFIG_MMU
+	/*
+	 * If we have an MMU, and want to be using it .. we need to adjust
+	 * the zone sizes accordingly, in addition to turning it on.
+	 */
+	{
+		unsigned long max_dma, low, start_pfn;
+		pgd_t *pg_dir;
 	int i;
-	pgd_t * pg_dir;
 
 	/* We don't need kernel mapping as hardware support that. */
 	pg_dir = swapper_pg_dir;
 
-	for (i=0; i < PTRS_PER_PGD; i++)
+		for (i = 0; i < PTRS_PER_PGD; i++)
 		pgd_val(pg_dir[i]) = 0;
 
-	/* Enable MMU */
-	ctrl_outl(MMU_CONTROL_INIT, MMUCR);
-
-	/* The manual suggests doing some nops after turning on the MMU */
-	asm volatile("nop;nop;nop;nop;nop;nop;");
-
-	mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
-	set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);
-
- 	{
-		unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
-		unsigned long max_dma, low, start_pfn;
+		/* Turn on the MMU */
+		enable_mmu();
 
+		/* Fixup the zone sizes */
 		start_pfn = START_PFN;
 		max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 		low = MAX_LOW_PFN;
 
-		if (low < max_dma)
+		if (low < max_dma) {
 			zones_size[ZONE_DMA] = low - start_pfn;
-		else {
+		} else {
 			zones_size[ZONE_DMA] = max_dma - start_pfn;
 			zones_size[ZONE_NORMAL] = low - max_dma;
 		}
+	}
+#elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
+	/*
+	 * If we don't have CONFIG_MMU set and the processor in question
+	 * still has an MMU, care needs to be taken to make sure it doesn't
+	 * stay on.. Since the boot loader could have potentially already
+	 * turned it on, and we clearly don't want it, we simply turn it off.
+	 *
+	 * We don't need to do anything special for the zone sizes, since the
+	 * default values that were already configured up above should be
+	 * satisfactory.
+	 */
+	disable_mmu();
+#endif
+
 		free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
+	/* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/
+		mem_map = NODE_DATA(0)->node_mem_map;
+
 #ifdef CONFIG_DISCONTIGMEM
+	/*
+	 * And for discontig, do some more fixups on the zone sizes..
+	 */
 		zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT;
 		zones_size[ZONE_NORMAL] = 0;
 		free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
 #endif
- 	}
 }
 
 void __init mem_init(void)
@@ -138,8 +172,15 @@
 	int codesize, reservedpages, datasize, initsize;
 	int tmp;
 
-	max_mapnr = num_physpages = MAX_LOW_PFN - START_PFN;
+#ifdef CONFIG_MMU
 	high_memory = (void *)__va(MAX_LOW_PFN * PAGE_SIZE);
+#else
+	extern unsigned long memory_end;
+
+	high_memory = (void *)(memory_end & PAGE_MASK);
+#endif
+
+	max_mapnr = num_physpages = MAP_NR(high_memory);
 
 	/* clear the zero-page */
 	memset(empty_zero_page, 0, PAGE_SIZE);
@@ -199,3 +240,76 @@
 	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 }
 #endif
+
+/*
+ * Generic first-level cache init
+ */
+void __init sh_cache_init(void)
+{
+	extern int detect_cpu_and_cache_system(void);
+	unsigned long ccr, flags = 0;
+
+	detect_cpu_and_cache_system();
+
+	if (cpu_data->type == CPU_SH_NONE)
+		panic("Unknown CPU");
+
+	jump_to_P2();
+	ccr = ctrl_inl(CCR);
+
+	/*
+	 * If the cache is already enabled .. flush it.
+	 */
+	if (ccr & CCR_CACHE_ENABLE) {
+		unsigned long entries, i, j;
+
+		entries = cpu_data->dcache.sets;
+
+		/*
+		 * If the OC is already in RAM mode, we only have
+		 * half of the entries to flush..
+		 */
+		if (ccr & CCR_CACHE_ORA)
+			entries >>= 1;
+
+		for (i = 0; i < entries; i++) {
+			for (j = 0; j < cpu_data->dcache.ways; j++) {
+				unsigned long data, addr;
+
+				addr = CACHE_OC_ADDRESS_ARRAY |
+					(j << cpu_data->dcache.way_shift) |
+					(i << cpu_data->dcache.entry_shift);
+
+				data = ctrl_inl(addr);
+
+				if ((data & (SH_CACHE_UPDATED | SH_CACHE_VALID))
+					== (SH_CACHE_UPDATED | SH_CACHE_VALID))
+					ctrl_outl(data & ~SH_CACHE_UPDATED, addr);
+		}
+		}
+	}
+
+	/* 
+	 * Default CCR values .. enable the caches
+	 * and flush them immediately..
+	 */
+	flags |= CCR_CACHE_ENABLE | CCR_CACHE_INVALIDATE | (ccr & CCR_CACHE_EMODE);
+
+#ifdef CONFIG_SH_WRITETHROUGH
+	/* Turn on Write-through caching */
+	flags |= CCR_CACHE_WT;
+#else
+	/* .. or default to Write-back */
+	flags |= CCR_CACHE_CB;
+#endif
+
+#ifdef CONFIG_SH_OCRAM
+	/* Turn on OCRAM -- halve the OC */
+	flags |= CCR_CACHE_ORA;
+	cpu_data->dcache.sets >>= 1;
+#endif
+
+	ctrl_outl(flags, CCR);
+	back_to_P1();
+}
+
diff -urN linux-2.5.73-bk9/arch/sh/mm/ioremap.c linux-2.5.73-bk10/arch/sh/mm/ioremap.c
--- linux-2.5.73-bk9/arch/sh/mm/ioremap.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk10/arch/sh/mm/ioremap.c	2003-07-02 04:57:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: ioremap.c,v 1.4 2001/06/30 09:18:39 gniibe Exp $
+/* $Id: ioremap.c,v 1.6 2003/05/04 19:29:55 lethal Exp $
  *
  * arch/sh/mm/ioremap.c
  *
@@ -10,8 +10,12 @@
  */
 
 #include <linux/vmalloc.h>
+#include <linux/mm.h>
 #include <asm/io.h>
+#include <asm/page.h>
 #include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
 
 static inline void remap_area_pte(pte_t * pte, unsigned long address,
 	unsigned long size, unsigned long phys_addr, unsigned long flags)
@@ -54,7 +58,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
diff -urN linux-2.5.73-bk9/arch/sh/mm/pg-sh4.c linux-2.5.73-bk10/arch/sh/mm/pg-sh4.c
--- linux-2.5.73-bk9/arch/sh/mm/pg-sh4.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/mm/pg-sh4.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,103 @@
+/* 
+ * $Id: pg-sh4.c,v 1.1.2.2 2002/11/17 17:56:18 lethal Exp $
+ *
+ *  arch/sh/mm/pg-sh4.c
+ *
+ * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
+ * Copyright (C) 2002  Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+extern struct semaphore p3map_sem[];
+
+/*
+ * clear_user_page
+ * @to: P1 address
+ * @address: U0 address to be mapped
+ * @page: page (virt_to_page(to))
+ */
+void clear_user_page(void *to, unsigned long address, struct page *page)
+{
+	__set_bit(PG_mapped, &page->flags);
+	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
+		clear_page(to);
+	else {
+		pgprot_t pgprot = __pgprot(_PAGE_PRESENT | 
+					   _PAGE_RW | _PAGE_CACHABLE |
+					   _PAGE_DIRTY | _PAGE_ACCESSED | 
+					   _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
+		unsigned long phys_addr = PHYSADDR(to);
+		unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
+		pgd_t *dir = pgd_offset_k(p3_addr);
+		pmd_t *pmd = pmd_offset(dir, p3_addr);
+		pte_t *pte = pte_offset_kernel(pmd, p3_addr);
+		pte_t entry;
+		unsigned long flags;
+
+		entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
+		down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+		set_pte(pte, entry);
+		local_irq_save(flags);
+		__flush_tlb_page(get_asid(), p3_addr);
+		local_irq_restore(flags);
+		update_mmu_cache(NULL, p3_addr, entry);
+		__clear_user_page((void *)p3_addr, to);
+		pte_clear(pte);
+		up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+	}
+}
+
+/*
+ * copy_user_page
+ * @to: P1 address
+ * @from: P1 address
+ * @address: U0 address to be mapped
+ * @page: page (virt_to_page(to))
+ */
+void copy_user_page(void *to, void *from, unsigned long address, 
+		    struct page *page)
+{
+	__set_bit(PG_mapped, &page->flags);
+	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
+		copy_page(to, from);
+	else {
+		pgprot_t pgprot = __pgprot(_PAGE_PRESENT | 
+					   _PAGE_RW | _PAGE_CACHABLE |
+					   _PAGE_DIRTY | _PAGE_ACCESSED | 
+					   _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
+		unsigned long phys_addr = PHYSADDR(to);
+		unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
+		pgd_t *dir = pgd_offset_k(p3_addr);
+		pmd_t *pmd = pmd_offset(dir, p3_addr);
+		pte_t *pte = pte_offset_kernel(pmd, p3_addr);
+		pte_t entry;
+		unsigned long flags;
+
+		entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
+		down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+		set_pte(pte, entry);
+		local_irq_save(flags);
+		__flush_tlb_page(get_asid(), p3_addr);
+		local_irq_restore(flags);
+		update_mmu_cache(NULL, p3_addr, entry);
+		__copy_user_page((void *)p3_addr, from, to);
+		pte_clear(pte);
+		up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+	}
+}
diff -urN linux-2.5.73-bk9/arch/sh/mm/tlb-nommu.c linux-2.5.73-bk10/arch/sh/mm/tlb-nommu.c
--- linux-2.5.73-bk9/arch/sh/mm/tlb-nommu.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/mm/tlb-nommu.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,58 @@
+/*
+ * arch/sh/mm/tlb-nommu.c
+ *
+ * TLB Operations for MMUless SH.
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+/*
+ * Nothing too terribly exciting here ..
+ */
+
+void flush_tlb(void)
+{
+	BUG();
+}
+
+void flush_tlb_all(void)
+{
+	BUG();
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	BUG();
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			    unsigned long end)
+{
+	BUG();
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	BUG();
+}
+
+void __flush_tlb_page(unsigned long asid, unsigned long page)
+{
+	BUG();
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	BUG();
+}
+
+void update_mmu_cache(struct vm_area_struct * vma,
+		      unsigned long address, pte_t pte)
+{
+	BUG();
+}
+
diff -urN linux-2.5.73-bk9/arch/sh/mm/tlb-sh3.c linux-2.5.73-bk10/arch/sh/mm/tlb-sh3.c
--- linux-2.5.73-bk9/arch/sh/mm/tlb-sh3.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/mm/tlb-sh3.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,75 @@
+/*
+ * arch/sh/mm/tlb-sh3.c
+ *
+ * SH-3 specific TLB operations
+ *
+ * Copyright (C) 1999  Niibe Yutaka
+ * Copyright (C) 2002  Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+void update_mmu_cache(struct vm_area_struct * vma,
+		      unsigned long address, pte_t pte)
+{
+	unsigned long flags;
+	unsigned long pteval;
+	unsigned long vpn;
+
+	/* Ptrace may call this routine. */
+	if (vma && current->active_mm != vma->vm_mm)
+		return;
+
+	local_irq_save(flags);
+
+	/* Set PTEH register */
+	vpn = (address & MMU_VPN_MASK) | get_asid();
+	ctrl_outl(vpn, MMU_PTEH);
+
+	pteval = pte_val(pte);
+
+	/* Set PTEL register */
+	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+	/* conveniently, we want all the software flags to be 0 anyway */
+	ctrl_outl(pteval, MMU_PTEL);
+
+	/* Load the TLB */
+	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+	local_irq_restore(flags);
+}
+
+void __flush_tlb_page(unsigned long asid, unsigned long page)
+{
+	unsigned long addr, data;
+
+	/*
+	 * NOTE: PTEH.ASID should be set to this MM
+	 *       _AND_ we need to write ASID to the array.
+	 *
+	 * It would be simple if we didn't need to set PTEH.ASID...
+	 */
+	addr = MMU_TLB_ADDRESS_ARRAY |(page & 0x1F000)| MMU_PAGE_ASSOC_BIT;
+	data = (page & 0xfffe0000) | asid; /* VALID bit is off */
+	ctrl_outl(data, addr);
+}
+
diff -urN linux-2.5.73-bk9/arch/sh/mm/tlb-sh4.c linux-2.5.73-bk10/arch/sh/mm/tlb-sh4.c
--- linux-2.5.73-bk9/arch/sh/mm/tlb-sh4.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/arch/sh/mm/tlb-sh4.c	2003-07-02 04:57:23.000000000 -0700
@@ -0,0 +1,97 @@
+/*
+ * arch/sh/mm/tlb-sh4.c
+ *
+ * SH-4 specific TLB operations
+ *
+ * Copyright (C) 1999  Niibe Yutaka
+ * Copyright (C) 2002  Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+void update_mmu_cache(struct vm_area_struct * vma,
+		      unsigned long address, pte_t pte)
+{
+	unsigned long flags;
+	unsigned long pteval;
+	unsigned long vpn;
+	struct page *page;
+	unsigned long pfn;
+	unsigned long ptea;
+
+	/* Ptrace may call this routine. */
+	if (vma && current->active_mm != vma->vm_mm)
+		return;
+
+	pfn = pte_pfn(pte);
+	if (pfn_valid(pfn)) {
+		page = pfn_to_page(pfn);
+		if (!test_bit(PG_mapped, &page->flags)) {
+			unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+			__flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
+			__set_bit(PG_mapped, &page->flags);
+		}
+	}
+
+	local_irq_save(flags);
+
+	/* Set PTEH register */
+	vpn = (address & MMU_VPN_MASK) | get_asid();
+	ctrl_outl(vpn, MMU_PTEH);
+
+	pteval = pte_val(pte);
+	/* Set PTEA register */
+	/* TODO: make this look less hacky */
+	ptea = ((pteval >> 28) & 0xe) | (pteval & 0x1);
+	ctrl_outl(ptea, MMU_PTEA);
+
+	/* Set PTEL register */
+	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+#ifdef CONFIG_SH_WRITETHROUGH
+	pteval |= 1;
+#endif
+	/* conveniently, we want all the software flags to be 0 anyway */
+	ctrl_outl(pteval, MMU_PTEL);
+
+	/* Load the TLB */
+	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+	local_irq_restore(flags);
+}
+
+void __flush_tlb_page(unsigned long asid, unsigned long page)
+{
+	unsigned long addr, data;
+
+	/*
+	 * NOTE: PTEH.ASID should be set to this MM
+	 *       _AND_ we need to write ASID to the array.
+	 *
+	 * It would be simple if we didn't need to set PTEH.ASID...
+	 */
+	addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT;
+	data = page | asid; /* VALID bit is off */
+	jump_to_P2();
+	ctrl_outl(data, addr);
+	back_to_P1();
+}
+
diff -urN linux-2.5.73-bk9/arch/x86_64/defconfig linux-2.5.73-bk10/arch/x86_64/defconfig
--- linux-2.5.73-bk9/arch/x86_64/defconfig	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk10/arch/x86_64/defconfig	2003-07-02 04:57:23.000000000 -0700
@@ -7,6 +7,7 @@
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_X86_CMPXCHG=y
 CONFIG_EARLY_PRINTK=y
+CONFIG_HPET_TIMER=y
 CONFIG_GENERIC_ISA_DMA=y
 
 #
@@ -64,7 +65,8 @@
 #
 # Power management options
 #
-# CONFIG_PM is not set
+CONFIG_PM=y
+CONFIG_SOFTWARE_SUSPEND=y
 
 #
 # ACPI Support
@@ -72,12 +74,15 @@
 CONFIG_ACPI=y
 # CONFIG_ACPI_HT_ONLY is not set
 CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
 CONFIG_ACPI_AC=y
 CONFIG_ACPI_BATTERY=y
 CONFIG_ACPI_BUTTON=y
 CONFIG_ACPI_FAN=y
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_THERMAL=y
+# CONFIG_ACPI_ASUS is not set
 CONFIG_ACPI_TOSHIBA=y
 CONFIG_ACPI_DEBUG=y
 CONFIG_ACPI_BUS=y
@@ -107,6 +112,11 @@
 CONFIG_UID16=y
 
 #
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -151,6 +161,7 @@
 # CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
 
 #
@@ -198,7 +209,58 @@
 #
 # SCSI device support
 #
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_SYM53C8XX is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -213,6 +275,11 @@
 #
 # Fusion MPT device support
 #
+CONFIG_FUSION=y
+CONFIG_FUSION_BOOT=y
+CONFIG_FUSION_MAX_SGE=40
+# CONFIG_FUSION_ISENSE is not set
+# CONFIG_FUSION_CTL is not set
 
 #
 # IEEE 1394 (FireWire) support (EXPERIMENTAL)
@@ -246,7 +313,12 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_TUNNEL is not set
 # CONFIG_XFRM_USER is not set
 
 #
@@ -307,6 +379,7 @@
 CONFIG_AMD8111_ETH=y
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
+# CONFIG_TC35815 is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
@@ -356,6 +429,7 @@
 #
 # Token Ring devices (depends on LLC=y)
 #
+# CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
 
@@ -405,6 +479,7 @@
 CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
 
 #
 # Input Device Drivers
@@ -434,6 +509,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -467,7 +543,11 @@
 #
 # IPMI
 #
-# CONFIG_IPMI_HANDLER is not set
+CONFIG_IPMI_HANDLER=y
+CONFIG_IPMI_PANIC_EVENT=y
+CONFIG_IPMI_DEVICE_INTERFACE=y
+CONFIG_IPMI_KCS=y
+CONFIG_IPMI_WATCHDOG=y
 
 #
 # Watchdog Cards
@@ -487,10 +567,15 @@
 # CONFIG_FTAPE is not set
 CONFIG_AGP=y
 CONFIG_AGP_AMD_8151=y
-# CONFIG_DRM is not set
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
+# CONFIG_DRM_R128 is not set
+CONFIG_DRM_RADEON=y
+# CONFIG_DRM_MGA is not set
 # CONFIG_MWAVE is not set
 CONFIG_RAW_DRIVER=y
-# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_HANGCHECK_TIMER=y
 
 #
 # Misc devices
@@ -613,7 +698,35 @@
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+CONFIG_SOUND_ICH=y
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
 
 #
 # USB support
@@ -629,7 +742,8 @@
 #
 # Profiling support
 #
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
 
 #
 # Kernel hacking
@@ -653,7 +767,21 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Library routines
diff -urN linux-2.5.73-bk9/arch/x86_64/ia32/Makefile linux-2.5.73-bk10/arch/x86_64/ia32/Makefile
--- linux-2.5.73-bk9/arch/x86_64/ia32/Makefile	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk10/arch/x86_64/ia32/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -10,7 +10,7 @@
 
 # The DSO images are built using a special linker script.
 $(obj)/vsyscall.so: $(src)/vsyscall.lds $(obj)/vsyscall.o
-	$(CC) -m32 -nostdlib -shared -s -Wl,-soname=linux-vsyscall.so.1 \
+	$(CC) -m32 -nostdlib -shared -s -Wl,-soname=linux-gate.so.1 \
 		-o $@ -Wl,-T,$^
 
 clean-files += vsyscall.so
diff -urN linux-2.5.73-bk9/arch/x86_64/ia32/ia32entry.S linux-2.5.73-bk10/arch/x86_64/ia32/ia32entry.S
--- linux-2.5.73-bk9/arch/x86_64/ia32/ia32entry.S	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk10/arch/x86_64/ia32/ia32entry.S	2003-07-02 04:57:23.000000000 -0700
@@ -47,7 +47,6 @@
 ENTRY(ia32_cstar_target)
 	swapgs
 	movl	%esp,%r8d
-	movq	%r8,%gs:pda_oldrsp
 	movq	%gs:pda_kernelstack,%rsp
 	sti
 	SAVE_ARGS 8,1
@@ -67,7 +66,6 @@
 	.section __ex_table,"a"
 	.quad 1b,cstar_badarg
 	.previous	
-	movq	%r9,R9-ARGOFFSET(%rsp)		
 	GET_THREAD_INFO(%r10)
 	bt  $TIF_SYSCALL_TRACE,threadinfo_flags(%r10)
 	jc  ia32_tracesys
diff -urN linux-2.5.73-bk9/arch/x86_64/kernel/acpi/wakeup.S linux-2.5.73-bk10/arch/x86_64/kernel/acpi/wakeup.S
--- linux-2.5.73-bk9/arch/x86_64/kernel/acpi/wakeup.S	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk10/arch/x86_64/kernel/acpi/wakeup.S	2003-07-02 04:57:23.000000000 -0700
@@ -209,7 +209,7 @@
 
 	movw	$0x0e00 + '!', %ds:(0xb801a)
 	movq	saved_eip, %rax
-	jmp	%rax
+	jmp	*%rax
 
 .code32
 
diff -urN linux-2.5.73-bk9/arch/x86_64/kernel/io_apic.c linux-2.5.73-bk10/arch/x86_64/kernel/io_apic.c
--- linux-2.5.73-bk9/arch/x86_64/kernel/io_apic.c	2003-06-22 11:32:46.000000000 -0700
+++ linux-2.5.73-bk10/arch/x86_64/kernel/io_apic.c	2003-07-02 04:57:23.000000000 -0700
@@ -712,9 +712,9 @@
 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;
+	union IO_APIC_reg_00 reg_00;
+	union IO_APIC_reg_01 reg_01;
+	union IO_APIC_reg_02 reg_02;
 	unsigned long flags;
 
  	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
@@ -731,49 +731,49 @@
 	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);
+	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);
 	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);
-	if (reg_00.__reserved_1 || reg_00.__reserved_2)
+	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+	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) &&
-		(reg_01.entries != 0x03) 
+	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) &&
+		(reg_01.bits.entries != 0x03) 
 	)
 		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 != 0x02) && /* 82801BA IO-APICs (ICH2) */
-		(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 != 0x02) && /* 82801BA IO-APICs (ICH2) */
+		(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();
 
-	if (reg_01.version >= 0x10) {
-		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) {
+		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();
 	}
 
@@ -782,7 +782,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);
@@ -963,7 +963,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;
 
@@ -980,9 +980,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;
 	}
 
 	/*
@@ -1013,7 +1013,7 @@
 
 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 = phys_cpu_present_map;
 	int apic;
 	int i;
@@ -1029,7 +1029,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;
@@ -1038,8 +1038,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;
 		}
 
 		/*
@@ -1083,18 +1083,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");
@@ -1637,7 +1637,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;
@@ -1655,13 +1655,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;
 	}
 
 	/*
@@ -1686,16 +1686,16 @@
 
 	apic_id_map |= (1 << 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);
 	}
 
@@ -1707,27 +1707,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-bk9/arch/x86_64/kernel/nmi.c linux-2.5.73-bk10/arch/x86_64/kernel/nmi.c
--- linux-2.5.73-bk9/arch/x86_64/kernel/nmi.c	2003-07-02 04:57:15.000000000 -0700
+++ linux-2.5.73-bk10/arch/x86_64/kernel/nmi.c	2003-07-02 04:57:23.000000000 -0700
@@ -23,6 +23,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/sysdev.h>
+#include <linux/nmi.h>
 
 #include <asm/smp.h>
 #include <asm/mtrr.h>
@@ -32,7 +33,13 @@
 #include <asm/proto.h>
 #include <asm/kdebug.h>
 
-extern void default_do_nmi(struct pt_regs *);
+/* nmi_active:
+ * +1: the lapic NMI watchdog is active, but can be disabled
+ *  0: the lapic NMI watchdog has not been set up, and cannot
+ *     be enabled
+ * -1: the lapic NMI watchdog is disabled, but can be enabled
+ */
+static int nmi_active;
 
 unsigned int nmi_watchdog = NMI_IO_APIC;
 static unsigned int nmi_hz = HZ;
@@ -90,6 +97,7 @@
 			printk("CPU#%d: NMI appears to be stuck (%d)!\n", 
 			       cpu,
 			       cpu_pda[cpu].__nmi_count);
+			nmi_active = 0;
 			return -1;
 		}
 	}
@@ -117,14 +125,6 @@
 
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
-/* nmi_active:
- * +1: the lapic NMI watchdog is active, but can be disabled
- *  0: the lapic NMI watchdog has not been set up, and cannot
- *     be enabled
- * -1: the lapic NMI watchdog is disabled, but can be enabled
- */
-static int nmi_active;
-
 void disable_lapic_nmi_watchdog(void)
 {
 	if (nmi_active <= 0)
@@ -149,6 +149,28 @@
 	}
   }
 
+
+void disable_timer_nmi_watchdog(void)
+{
+	if ((nmi_watchdog != NMI_IO_APIC) || (nmi_active <= 0))
+		return;
+
+	disable_irq(0);
+	unset_nmi_callback();
+	nmi_active = -1;
+	nmi_watchdog = NMI_NONE;
+}
+
+void enable_timer_nmi_watchdog(void)
+{
+	if (nmi_active < 0) {
+		nmi_watchdog = NMI_IO_APIC;
+		touch_nmi_watchdog();
+		nmi_active = 1;
+		enable_irq(0);
+	}
+}
+
 #ifdef CONFIG_PM
 
 #include <linux/device.h>
@@ -352,3 +374,5 @@
 EXPORT_SYMBOL(nmi_watchdog);
 EXPORT_SYMBOL(disable_lapic_nmi_watchdog);
 EXPORT_SYMBOL(enable_lapic_nmi_watchdog);
+EXPORT_SYMBOL(disable_timer_nmi_watchdog);
+EXPORT_SYMBOL(enable_timer_nmi_watchdog);
diff -urN linux-2.5.73-bk9/arch/x86_64/kernel/setup.c linux-2.5.73-bk10/arch/x86_64/kernel/setup.c
--- linux-2.5.73-bk9/arch/x86_64/kernel/setup.c	2003-06-22 11:32:31.000000000 -0700
+++ linux-2.5.73-bk10/arch/x86_64/kernel/setup.c	2003-07-02 04:57:23.000000000 -0700
@@ -93,11 +93,11 @@
 
 struct resource standard_io_resources[] = {
 	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
-	{ "pic1", 0x20, 0x3f, IORESOURCE_BUSY },
+	{ "pic1", 0x20, 0x21, IORESOURCE_BUSY },
 	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
 	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
 	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
-	{ "pic2", 0xa0, 0xbf, IORESOURCE_BUSY },
+	{ "pic2", 0xa0, 0xa1, IORESOURCE_BUSY },
 	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
 	{ "fpu", 0xf0, 0xff, IORESOURCE_BUSY }
 };
diff -urN linux-2.5.73-bk9/arch/x86_64/kernel/x8664_ksyms.c linux-2.5.73-bk10/arch/x86_64/kernel/x8664_ksyms.c
--- linux-2.5.73-bk9/arch/x86_64/kernel/x8664_ksyms.c	2003-06-22 11:32:34.000000000 -0700
+++ linux-2.5.73-bk10/arch/x86_64/kernel/x8664_ksyms.c	2003-07-02 04:57:23.000000000 -0700
@@ -30,6 +30,7 @@
 #include <asm/kdebug.h>
 #include <asm/unistd.h>
 #include <asm/delay.h>
+#include <asm/tlbflush.h>
 
 extern spinlock_t rtc_lock;
 
@@ -212,3 +213,6 @@
 #endif
 
 EXPORT_SYMBOL(clear_page);
+
+EXPORT_SYMBOL(flush_tlb_page);
+EXPORT_SYMBOL_GPL(flush_tlb_all);
diff -urN linux-2.5.73-bk9/arch/x86_64/oprofile/Makefile linux-2.5.73-bk10/arch/x86_64/oprofile/Makefile
--- linux-2.5.73-bk9/arch/x86_64/oprofile/Makefile	2003-06-22 11:32:37.000000000 -0700
+++ linux-2.5.73-bk10/arch/x86_64/oprofile/Makefile	2003-07-02 04:57:23.000000000 -0700
@@ -15,7 +15,7 @@
 oprofile-objs := $(DRIVER_OBJS) init.o
 
 oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o
- 
+oprofile-$(CONFIG_X86_IO_APIC)          += nmi_timer_int.o 
 INCL := $(obj)/op_counter.h $(obj)/op_x86_model.h
 
 $(obj)/nmi_int.c: ${INCL}
@@ -24,9 +24,11 @@
 	@ln -sf ../../i386/oprofile/op_model_athlon.c $(obj)/op_model_athlon.c
 $(obj)/init.c: ${INCL}
 	@ln -sf ../../i386/oprofile/init.c $(obj)/init.c
+$(obj)/nmi_timer_int.c: ${INCL}
+	@ln -sf ../../i386/oprofile/nmi_timer_int.c $(obj)/nmi_timer_int.c
 $(obj)/op_counter.h: 
 	@ln -sf ../../i386/oprofile/op_counter.h $(obj)/op_counter.h
 $(obj)/op_x86_model.h:
 	@ln -sf ../../i386/oprofile/op_x86_model.h $(obj)/op_x86_model.h	
 clean-files += op_x86_model.h op_counter.h init.c \
-	       op_model_athlon.c nmi_int.c
+	       op_model_athlon.c nmi_int.c nmi_timer_int.c
diff -urN linux-2.5.73-bk9/drivers/ide/Kconfig linux-2.5.73-bk10/drivers/ide/Kconfig
--- linux-2.5.73-bk9/drivers/ide/Kconfig	2003-06-22 11:32:44.000000000 -0700
+++ linux-2.5.73-bk10/drivers/ide/Kconfig	2003-07-02 04:57:24.000000000 -0700
@@ -277,9 +277,9 @@
 	  If you are unsure, say N here.
 
 config IDE_TASKFILE_IO
-	bool 'IDE Taskfile IO'
-	depends on BLK_DEV_IDE
-	default y
+	bool 'IDE Taskfile IO (EXPERIMENTAL)'
+	depends on BLK_DEV_IDE && EXPERIMENTAL
+	default n
 	---help---
 	  Use new taskfile IO code.
 
diff -urN linux-2.5.73-bk9/drivers/ide/ide-cd.c linux-2.5.73-bk10/drivers/ide/ide-cd.c
--- linux-2.5.73-bk9/drivers/ide/ide-cd.c	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk10/drivers/ide/ide-cd.c	2003-07-02 04:57:24.000000000 -0700
@@ -2805,7 +2805,7 @@
 				CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
 				CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R |
 				CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
-				CDC_GENERIC_PACKET,
+				CDC_GENERIC_PACKET | CDC_MO_DRIVE,
 	.generic_packet		= ide_cdrom_packet,
 };
 
@@ -2838,6 +2838,8 @@
 		devinfo->mask |= CDC_PLAY_AUDIO;
 	if (!CDROM_CONFIG_FLAGS(drive)->close_tray)
 		devinfo->mask |= CDC_CLOSE_TRAY;
+	if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
+		devinfo->mask |= CDC_MO_DRIVE;
 
 	return register_cdrom(devinfo);
 }
@@ -2884,6 +2886,7 @@
 	int nslots = 1;
 
 	if (drive->media == ide_optical) {
+		CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
 		printk("%s: ATAPI magneto-optical drive\n", drive->name);
 		return nslots;
 	}
diff -urN linux-2.5.73-bk9/drivers/ide/ide-cd.h linux-2.5.73-bk10/drivers/ide/ide-cd.h
--- linux-2.5.73-bk9/drivers/ide/ide-cd.h	2003-06-22 11:33:36.000000000 -0700
+++ linux-2.5.73-bk10/drivers/ide/ide-cd.h	2003-07-02 04:57:24.000000000 -0700
@@ -85,7 +85,8 @@
 	__u8 audio_play		: 1; /* can do audio related commands */
 	__u8 close_tray		: 1; /* can close the tray */
 	__u8 writing		: 1; /* pseudo write in progress */
-	__u8 reserved		: 3;
+	__u8 mo_drive		: 1; /* drive is an MO device */
+	__u8 reserved		: 2;
 	byte max_speed;		     /* Max speed of the drive */
 };
 #define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
diff -urN linux-2.5.73-bk9/drivers/net/e100/e100_main.c linux-2.5.73-bk10/drivers/net/e100/e100_main.c
--- linux-2.5.73-bk9/drivers/net/e100/e100_main.c	2003-07-02 04:57:15.000000000 -0700
+++ linux-2.5.73-bk10/drivers/net/e100/e100_main.c	2003-07-02 04:57:27.000000000 -0700
@@ -2068,13 +2068,14 @@
 			skb->ip_summed = CHECKSUM_NONE;
 		}
 
+		bdp->drv_stats.net_stats.rx_bytes += skb->len;
+
 		if(bdp->vlgrp && (rfd_status & CB_STATUS_VLAN)) {
 			vlan_hwaccel_rx(skb, bdp->vlgrp, be16_to_cpu(rfd->vlanid));
 		} else {
 			netif_rx(skb);
 		}
 		dev->last_rx = jiffies;
-		bdp->drv_stats.net_stats.rx_bytes += skb->len;
 		
 		rfd_cnt++;
 	}			/* end of rfd loop */
diff -urN linux-2.5.73-bk9/drivers/net/tulip/de2104x.c linux-2.5.73-bk10/drivers/net/tulip/de2104x.c
--- linux-2.5.73-bk9/drivers/net/tulip/de2104x.c	2003-06-22 11:33:08.000000000 -0700
+++ linux-2.5.73-bk10/drivers/net/tulip/de2104x.c	2003-07-02 04:57:28.000000000 -0700
@@ -77,7 +77,6 @@
 #define DE_DEF_MSG_ENABLE	(NETIF_MSG_DRV		| \
 				 NETIF_MSG_PROBE 	| \
 				 NETIF_MSG_LINK		| \
-				 NETIF_MSG_TIMER	| \
 				 NETIF_MSG_IFDOWN	| \
 				 NETIF_MSG_IFUP		| \
 				 NETIF_MSG_RX_ERR	| \
diff -urN linux-2.5.73-bk9/drivers/net/typhoon.c linux-2.5.73-bk10/drivers/net/typhoon.c
--- linux-2.5.73-bk9/drivers/net/typhoon.c	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk10/drivers/net/typhoon.c	2003-07-02 04:57:28.000000000 -0700
@@ -40,7 +40,7 @@
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
  * Setting to > 1518 effectively disables this feature.
  */
-static int rx_copybreak = 0;
+static int rx_copybreak = 200;
 
 /* end user-configurable values */
 
@@ -85,8 +85,8 @@
 #define PKT_BUF_SZ		1536
 
 #define DRV_MODULE_NAME		"typhoon"
-#define DRV_MODULE_VERSION 	"1.0"
-#define DRV_MODULE_RELDATE	"03/02/14"
+#define DRV_MODULE_VERSION 	"1.5.1"
+#define DRV_MODULE_RELDATE	"03/06/26"
 #define PFX			DRV_MODULE_NAME ": "
 #define ERR_PFX			KERN_ERR PFX
 
@@ -150,7 +150,7 @@
 #define TYPHOON_CRYPTO_DES		1
 #define TYPHOON_CRYPTO_3DES		2
 #define	TYPHOON_CRYPTO_VARIABLE		4
-#define TYPHOON_FIBER			5
+#define TYPHOON_FIBER			8
 
 enum typhoon_cards {
 	TYPHOON_TX = 0, TYPHOON_TX95, TYPHOON_TX97, TYPHOON_SVR,
@@ -1798,7 +1798,7 @@
 	u32 intr_status;
 
 	intr_status = readl(ioaddr + TYPHOON_REG_INTR_STATUS);
-	if(!intr_status)
+	if(!(intr_status & TYPHOON_INTR_HOST_INT))
 		return IRQ_NONE;
 
 	writel(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
diff -urN linux-2.5.73-bk9/drivers/net/wireless/airo.c linux-2.5.73-bk10/drivers/net/wireless/airo.c
--- linux-2.5.73-bk9/drivers/net/wireless/airo.c	2003-06-22 11:32:33.000000000 -0700
+++ linux-2.5.73-bk10/drivers/net/wireless/airo.c	2003-07-02 04:57:28.000000000 -0700
@@ -2901,6 +2901,7 @@
 					      airo_entry);
         apriv->proc_entry->uid = proc_uid;
         apriv->proc_entry->gid = proc_gid;
+        apriv->proc_entry->owner = THIS_MODULE;
 
 	/* Setup the StatsDelta */
 	entry = create_proc_entry("StatsDelta",
@@ -2909,6 +2910,7 @@
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+        entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_statsdelta_ops);
 
 	/* Setup the Stats */
@@ -2918,6 +2920,7 @@
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+        entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_stats_ops);
 
 	/* Setup the Status */
@@ -2927,6 +2930,7 @@
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+        entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_status_ops);
 
 	/* Setup the Config */
@@ -2936,6 +2940,7 @@
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+        entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_config_ops);
 
 	/* Setup the SSID */
@@ -2945,6 +2950,7 @@
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+        entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_SSID_ops);
 
 	/* Setup the APList */
@@ -2954,6 +2960,7 @@
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+        entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_APList_ops);
 
 	/* Setup the BSSList */
@@ -2963,6 +2970,7 @@
 	entry->uid = proc_uid;
 	entry->gid = proc_gid;
 	entry->data = dev;
+        entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_BSSList_ops);
 
 	/* Setup the WepKey */
@@ -2972,6 +2980,7 @@
         entry->uid = proc_uid;
         entry->gid = proc_gid;
 	entry->data = dev;
+        entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_wepkey_ops);
 
 	return 0;
@@ -3062,8 +3071,6 @@
 	StatusRid status_rid;
 	int i;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -3143,8 +3150,6 @@
 	StatsRid stats;
 	int i, j;
 	int *vals = stats.vals;
-	MOD_INC_USE_COUNT;
-
 
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
@@ -3421,8 +3426,6 @@
 	struct airo_info *ai = dev->priv;
 	int i;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -3692,8 +3695,6 @@
 	int j=0;
 	int rc;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -3742,8 +3743,6 @@
 	char *ptr;
 	SsidRid SSID_rid;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -3788,8 +3787,6 @@
 	char *ptr;
 	APListRid APList_rid;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -3840,8 +3837,6 @@
 	/* If doLoseSync is not 1, we won't do a Lose Sync */
 	int doLoseSync = -1;
 
-	MOD_INC_USE_COUNT;
-
 	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memset(file->private_data, 0, sizeof(struct proc_data));
@@ -3904,7 +3899,6 @@
 {
 	struct proc_data *data = (struct proc_data *)file->private_data;
 	if ( data->on_close != NULL ) data->on_close( inode, file );
-	MOD_DEC_USE_COUNT;
 	if ( data->rbuffer ) kfree( data->rbuffer );
 	if ( data->wbuffer ) kfree( data->wbuffer );
 	kfree( data );
diff -urN linux-2.5.73-bk9/drivers/net/wireless/netwave_cs.c linux-2.5.73-bk10/drivers/net/wireless/netwave_cs.c
--- linux-2.5.73-bk9/drivers/net/wireless/netwave_cs.c	2003-06-22 11:33:32.000000000 -0700
+++ linux-2.5.73-bk10/drivers/net/wireless/netwave_cs.c	2003-07-02 04:57:28.000000000 -0700
@@ -321,7 +321,6 @@
    
 typedef struct netwave_private {
     dev_link_t link;
-    struct net_device      dev;
     spinlock_t	spinlock;	/* Serialize access to the hardware (SMP) */
     dev_node_t node;
     u_char     *ramBase;
@@ -449,11 +448,13 @@
     netwave_flush_stale_links();
 
     /* Initialize the dev_link_t structure */
-    priv = kmalloc(sizeof(*priv), GFP_KERNEL);
-    if (!priv) return NULL;
-    memset(priv, 0, sizeof(*priv));
-    link = &priv->link; dev = &priv->dev;
-    link->priv = dev->priv = priv;
+    dev = alloc_etherdev(sizeof(netwave_private));
+    if (!dev)
+	return NULL;
+    priv = dev->priv;
+    link = &priv->link;
+    link->priv = dev;
+
     init_timer(&link->release);
     link->release.function = &netwave_release;
     link->release.data = (u_long)link;
@@ -504,7 +505,6 @@
     dev->tx_timeout = &netwave_watchdog;
     dev->watchdog_timeo = TX_TIMEOUT;
 
-    ether_setup(dev);
     dev->open = &netwave_open;
     dev->stop = &netwave_close;
     link->irq.Instance = dev;
@@ -541,7 +541,7 @@
  */
 static void netwave_detach(dev_link_t *link)
 {
-    netwave_private *priv = link->priv;
+    struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
     DEBUG(0, "netwave_detach(0x%p)\n", link);
@@ -580,8 +580,8 @@
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     if (link->dev)
-	unregister_netdev(&priv->dev);
-    kfree(priv);
+	unregister_netdev(dev);
+    kfree(dev);
     
 } /* netwave_detach */
 
@@ -1038,8 +1038,8 @@
 
 static void netwave_pcmcia_config(dev_link_t *link) {
     client_handle_t handle = link->handle;
-    netwave_private *priv = link->priv;
-    struct net_device *dev = &priv->dev;
+    struct net_device *dev = link->priv;
+    netwave_private *priv = dev->priv;
     tuple_t tuple;
     cisparse_t parse;
     int i, j, last_ret, last_fn;
@@ -1099,7 +1099,7 @@
      *  Allocate a 32K memory window.  Note that the dev_link_t
      *  structure provides space for one window handle -- if your
      *  device needs several windows, you'll need to keep track of
-     *  the handles in your private data structure, link->priv.
+     *  the handles in your private data structure, dev->priv.
      */
     DEBUG(1, "Setting mem speed of %d\n", mem_speed);
 
@@ -1161,7 +1161,8 @@
  */
 static void netwave_release(u_long arg) {
     dev_link_t *link = (dev_link_t *)arg;
-    netwave_private *priv = link->priv;
+    struct net_device *dev = link->priv;
+    netwave_private *priv = dev->priv;
 
     DEBUG(0, "netwave_release(0x%p)\n", link);
 
@@ -1206,8 +1207,7 @@
 static int netwave_event(event_t event, int priority,
 			 event_callback_args_t *args) {
     dev_link_t *link = args->client_data;
-    netwave_private *priv = link->priv;
-    struct net_device *dev = &priv->dev;
+    struct net_device *dev = link->priv;
 	
     DEBUG(1, "netwave_event(0x%06x)\n", event);
   
diff -urN linux-2.5.73-bk9/drivers/net/wireless/strip.c linux-2.5.73-bk10/drivers/net/wireless/strip.c
--- linux-2.5.73-bk9/drivers/net/wireless/strip.c	2003-06-22 11:32:59.000000000 -0700
+++ linux-2.5.73-bk10/drivers/net/wireless/strip.c	2003-07-02 04:57:28.000000000 -0700
@@ -284,7 +284,7 @@
 	 */
 
 	struct tty_struct *tty;		/* ptr to TTY structure         */
-	struct net_device dev;		/* Our device structure         */
+	struct net_device *dev;		/* Our device structure         */
 
 	/*
 	 * Neighbour radio records
@@ -509,7 +509,7 @@
 		*p++ = '\"';
 	*p++ = 0;
 
-	printk(KERN_INFO "%s: %-13s%s\n", strip_info->dev.name, msg, pkt_text);
+	printk(KERN_INFO "%s: %-13s%s\n", strip_info->dev->name, msg, pkt_text);
 }
 
 
@@ -846,7 +846,7 @@
 
 static int allocate_buffers(struct strip *strip_info)
 {
-	struct net_device *dev = &strip_info->dev;
+	struct net_device *dev = strip_info->dev;
 	int sx_size = MAX(STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096);
 	int tx_size = STRIP_ENCAP_SIZE(dev->mtu) + MaxCommandStringLength;
 	__u8 *r = kmalloc(MAX_RECV_MTU, GFP_ATOMIC);
@@ -881,7 +881,7 @@
 static void strip_changedmtu(struct strip *strip_info)
 {
 	int old_mtu = strip_info->mtu;
-	struct net_device *dev = &strip_info->dev;
+	struct net_device *dev = strip_info->dev;
 	unsigned char *orbuff = strip_info->rx_buff;
 	unsigned char *osbuff = strip_info->sx_buff;
 	unsigned char *otbuff = strip_info->tx_buff;
@@ -889,14 +889,14 @@
 	if (dev->mtu > MAX_SEND_MTU) {
 		printk(KERN_ERR
 		       "%s: MTU exceeds maximum allowable (%d), MTU change cancelled.\n",
-		       strip_info->dev.name, MAX_SEND_MTU);
+		       strip_info->dev->name, MAX_SEND_MTU);
 		dev->mtu = old_mtu;
 		return;
 	}
 
 	if (!allocate_buffers(strip_info)) {
 		printk(KERN_ERR "%s: unable to grow strip buffers, MTU change cancelled.\n",
-		       strip_info->dev.name);
+		       strip_info->dev->name);
 		dev->mtu = old_mtu;
 		return;
 	}
@@ -923,7 +923,7 @@
 	strip_info->tx_head = strip_info->tx_buff;
 
 	printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n",
-	       strip_info->dev.name, old_mtu, strip_info->mtu);
+	       strip_info->dev->name, old_mtu, strip_info->mtu);
 
 	if (orbuff)
 		kfree(orbuff);
@@ -940,7 +940,7 @@
 	 */
 	strip_info->idle_timer.expires = jiffies + 1 * HZ;
 	add_timer(&strip_info->idle_timer);
-	netif_wake_queue(&strip_info->dev);
+	netif_wake_queue(strip_info->dev);
 }
 
 
@@ -1087,10 +1087,10 @@
 	FirmwareVersion firmware_version = strip_info->firmware_version;
 	SerialNumber serial_number = strip_info->serial_number;
 	BatteryVoltage battery_voltage = strip_info->battery_voltage;
-	char *if_name = strip_info->dev.name;
+	char *if_name = strip_info->dev->name;
 	MetricomAddress true_dev_addr = strip_info->true_dev_addr;
 	MetricomAddress dev_dev_addr =
-	    *(MetricomAddress *) strip_info->dev.dev_addr;
+	    *(MetricomAddress *) strip_info->dev->dev_addr;
 	int manual_dev_addr = strip_info->manual_dev_addr;
 #ifdef EXT_COUNTERS
 	unsigned long rx_bytes = strip_info->rx_bytes;
@@ -1133,7 +1133,7 @@
 	p += sprintf(p, " Next gratuitous ARP:\t");
 
 	if (!memcmp
-	    (strip_info->dev.dev_addr, zero_address.c,
+	    (strip_info->dev->dev_addr, zero_address.c,
 	     sizeof(zero_address)))
 		p += sprintf(p, "Disabled\n");
 	else {
@@ -1210,7 +1210,7 @@
 	 */
 	if (strip_info->working) {
 		printk(KERN_INFO "%s: No response: Resetting radio.\n",
-		       strip_info->dev.name);
+		       strip_info->dev->name);
 		strip_info->firmware_version.c[0] = '\0';
 		strip_info->serial_number.c[0] = '\0';
 		strip_info->battery_voltage.c[0] = '\0';
@@ -1231,7 +1231,7 @@
 	/* Mark radio address as unknown */
 	*(MetricomAddress *) & strip_info->true_dev_addr = zero_address;
 	if (!strip_info->manual_dev_addr)
-		*(MetricomAddress *) strip_info->dev.dev_addr =
+		*(MetricomAddress *) strip_info->dev->dev_addr =
 		    zero_address;
 	strip_info->working = FALSE;
 	strip_info->firmware_level = NoStructure;
@@ -1285,7 +1285,7 @@
 
 	/* First make sure we're connected. */
 	if (!strip_info || strip_info->magic != STRIP_MAGIC ||
-	    !netif_running(&strip_info->dev))
+	    !netif_running(strip_info->dev))
 		return;
 
 	if (strip_info->tx_left > 0) {
@@ -1340,14 +1340,14 @@
 	else {
 		printk(KERN_ERR
 		       "%s: strip_make_packet: Unknown packet type 0x%04X\n",
-		       strip_info->dev.name, ntohs(header->protocol));
+		       strip_info->dev->name, ntohs(header->protocol));
 		return (NULL);
 	}
 
 	if (len > strip_info->mtu) {
 		printk(KERN_ERR
 		       "%s: Dropping oversized transmit packet: %d bytes\n",
-		       strip_info->dev.name, len);
+		       strip_info->dev->name, len);
 		return (NULL);
 	}
 
@@ -1357,7 +1357,7 @@
 	 */
 	if (!memcmp(haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) {
 		printk(KERN_ERR "%s: Dropping packet addressed to self\n",
-		       strip_info->dev.name);
+		       strip_info->dev->name);
 		return (NULL);
 	}
 
@@ -1367,7 +1367,7 @@
 	 */
 	if (haddr.c[0] == 0xFF) {
 		u32 brd = 0;
-		struct in_device *in_dev = in_dev_get(&strip_info->dev);
+		struct in_device *in_dev = in_dev_get(strip_info->dev);
 		if (in_dev == NULL)
 			return NULL;
 		read_lock(&in_dev->lock);
@@ -1377,10 +1377,10 @@
 		in_dev_put(in_dev);
 
 		/* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */
-		if (!arp_query(haddr.c, brd, &strip_info->dev)) {
+		if (!arp_query(haddr.c, brd, strip_info->dev)) {
 			printk(KERN_ERR
 			       "%s: Unable to send packet (no broadcast hub configured)\n",
-			       strip_info->dev.name);
+			       strip_info->dev->name);
 			return (NULL);
 		}
 		/*
@@ -1491,7 +1491,7 @@
 #endif
 		strip_info->watchdog_doprobe = jiffies + 10 * HZ;
 		strip_info->watchdog_doreset = jiffies + 1 * HZ;
-		/*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev.name); */
+		/*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev->name); */
 	}
 
 	/*
@@ -1506,7 +1506,7 @@
 	 */
 	if (strip_info->tx_size - strip_info->tx_left < 20)
 		printk(KERN_ERR "%s: Sending%5d bytes;%5d bytes free.\n",
-		       strip_info->dev.name, strip_info->tx_left,
+		       strip_info->dev->name, strip_info->tx_left,
 		       strip_info->tx_size - strip_info->tx_left);
 
 	/*
@@ -1519,7 +1519,7 @@
 	}
 
 	if (1) {
-		struct in_device *in_dev = in_dev_get(&strip_info->dev);
+		struct in_device *in_dev = in_dev_get(strip_info->dev);
 		brd = addr = 0;
 		if (in_dev) {
 			read_lock(&in_dev->lock);
@@ -1549,11 +1549,11 @@
 	 */
 	if (strip_info->working
 	    && (long) jiffies - strip_info->gratuitous_arp >= 0
-	    && memcmp(strip_info->dev.dev_addr, zero_address.c,
+	    && memcmp(strip_info->dev->dev_addr, zero_address.c,
 		      sizeof(zero_address))
-	    && arp_query(haddr.c, brd, &strip_info->dev)) {
+	    && arp_query(haddr.c, brd, strip_info->dev)) {
 		/*printk(KERN_INFO "%s: Sending gratuitous ARP with interval %ld\n",
-		   strip_info->dev.name, strip_info->arp_interval / HZ); */
+		   strip_info->dev->name, strip_info->arp_interval / HZ); */
 		strip_info->gratuitous_arp =
 		    jiffies + strip_info->arp_interval;
 		strip_info->arp_interval *= 2;
@@ -1561,11 +1561,11 @@
 			strip_info->arp_interval = MaxARPInterval;
 		if (addr)
 			arp_send(ARPOP_REPLY, ETH_P_ARP, addr,	/* Target address of ARP packet is our address */
-				 &strip_info->dev,	/* Device to send packet on */
+				 strip_info->dev,	/* Device to send packet on */
 				 addr,	/* Source IP address this ARP packet comes from */
 				 NULL,	/* Destination HW address is NULL (broadcast it) */
-				 strip_info->dev.dev_addr,	/* Source HW address is our HW address */
-				 strip_info->dev.dev_addr);	/* Target HW address is our HW address (redundant) */
+				 strip_info->dev->dev_addr,	/* Source HW address is our HW address */
+				 strip_info->dev->dev_addr);	/* Target HW address is our HW address (redundant) */
 	}
 
 	/*
@@ -1608,18 +1608,18 @@
 
 		if (rx_pps_count / 8 >= 10)
 			printk(KERN_INFO "%s: WARNING: Receiving %ld packets per second.\n",
-			       strip_info->dev.name, rx_pps_count / 8);
+			       strip_info->dev->name, rx_pps_count / 8);
 		if (tx_pps_count / 8 >= 10)
 			printk(KERN_INFO "%s: WARNING: Tx        %ld packets per second.\n",
-			       strip_info->dev.name, tx_pps_count / 8);
+			       strip_info->dev->name, tx_pps_count / 8);
 		if (sx_pps_count / 8 >= 10)
 			printk(KERN_INFO "%s: WARNING: Sending   %ld packets per second.\n",
-			       strip_info->dev.name, sx_pps_count / 8);
+			       strip_info->dev->name, sx_pps_count / 8);
 	}
 
 	spin_lock_irqsave(&strip_lock, flags);
 	/* See if someone has been ifconfigging */
-	if (strip_info->mtu != strip_info->dev.mtu)
+	if (strip_info->mtu != strip_info->dev->mtu)
 		strip_changedmtu(strip_info);
 
 	strip_send(strip_info, skb);
@@ -1735,7 +1735,7 @@
 	len = MIN(len, sizeof(FirmwareVersion) - 1);
 	if (strip_info->firmware_version.c[0] == 0)
 		printk(KERN_INFO "%s: Radio Firmware: %.*s\n",
-		       strip_info->dev.name, len, value_begin);
+		       strip_info->dev->name, len, value_begin);
 	sprintf(strip_info->firmware_version.c, "%.*s", len, value_begin);
 
 	/* Look for the first colon */
@@ -1806,10 +1806,10 @@
 		MetricomAddressString addr_string;
 		radio_address_to_string(&addr, &addr_string);
 		printk(KERN_INFO "%s: Radio address = %s\n",
-		       strip_info->dev.name, addr_string.c);
+		       strip_info->dev->name, addr_string.c);
 		strip_info->true_dev_addr = addr;
 		if (!strip_info->manual_dev_addr)
-			*(MetricomAddress *) strip_info->dev.dev_addr =
+			*(MetricomAddress *) strip_info->dev->dev_addr =
 			    addr;
 		/* Give the radio a few seconds to get its head straight, then send an arp */
 		strip_info->gratuitous_arp = jiffies + 15 * HZ;
@@ -1830,7 +1830,7 @@
 	if (sum == 0 && strip_info->firmware_level == StructuredMessages) {
 		strip_info->firmware_level = ChecksummedMessages;
 		printk(KERN_INFO "%s: Radio provides message checksums\n",
-		       strip_info->dev.name);
+		       strip_info->dev->name);
 	}
 	return (sum == 0);
 }
@@ -1849,7 +1849,7 @@
 	if (has_prefix(msg, len, "001")) {	/* Not in StarMode! */
 		RecvErr("Error Msg:", strip_info);
 		printk(KERN_INFO "%s: Radio %s is not in StarMode\n",
-		       strip_info->dev.name, sendername);
+		       strip_info->dev->name, sendername);
 	}
 
 	else if (has_prefix(msg, len, "002")) {	/* Remap handle */
@@ -1859,7 +1859,7 @@
 	else if (has_prefix(msg, len, "003")) {	/* Can't resolve name */
 		RecvErr("Error Msg:", strip_info);
 		printk(KERN_INFO "%s: Destination radio name is unknown\n",
-		       strip_info->dev.name);
+		       strip_info->dev->name);
 	}
 
 	else if (has_prefix(msg, len, "004")) {	/* Name too small or missing */
@@ -1876,7 +1876,7 @@
 		if (!strip_info->working) {
 			strip_info->working = TRUE;
 			printk(KERN_INFO "%s: Radio now in starmode\n",
-			       strip_info->dev.name);
+			       strip_info->dev->name);
 			/*
 			 * If the radio has just entered a working state, we should do our first
 			 * probe ASAP, so that we find out our radio address etc. without delay.
@@ -1888,7 +1888,7 @@
 			strip_info->next_command = 0;	/* Try to enable checksums ASAP */
 			printk(KERN_INFO
 			       "%s: Radio provides structured messages\n",
-			       strip_info->dev.name);
+			       strip_info->dev->name);
 		}
 		if (strip_info->firmware_level >= StructuredMessages) {
 			/*
@@ -1916,14 +1916,14 @@
 		RecvErr("Error Msg:", strip_info);
 		printk(KERN_ERR
 		       "%s: Error! Packet size too big for radio.\n",
-		       strip_info->dev.name);
+		       strip_info->dev->name);
 	}
 
 	else if (has_prefix(msg, len, "008")) {	/* Bad character in name */
 		RecvErr("Error Msg:", strip_info);
 		printk(KERN_ERR
 		       "%s: Radio name contains illegal character\n",
-		       strip_info->dev.name);
+		       strip_info->dev->name);
 	}
 
 	else if (has_prefix(msg, len, "009"))	/* No count or line terminator */
@@ -1994,7 +1994,7 @@
 	/* real radio hardware address, try to find another strip device that has been */
 	/* manually set to that address that we can 'transfer ownership' of this packet to  */
 	if (strip_info->manual_dev_addr &&
-	    !memcmp(strip_info->dev.dev_addr, zero_address.c,
+	    !memcmp(strip_info->dev->dev_addr, zero_address.c,
 		    sizeof(zero_address))
 	    && memcmp(&strip_info->true_dev_addr, zero_address.c,
 		      sizeof(zero_address))) {
@@ -2002,13 +2002,13 @@
 		read_lock_bh(&dev_base_lock);
 		dev = dev_base;
 		while (dev) {
-			if (dev->type == strip_info->dev.type &&
+			if (dev->type == strip_info->dev->type &&
 			    !memcmp(dev->dev_addr,
 				    &strip_info->true_dev_addr,
 				    sizeof(MetricomAddress))) {
 				printk(KERN_INFO
 				       "%s: Transferred packet ownership to %s.\n",
-				       strip_info->dev.name, dev->name);
+				       strip_info->dev->name, dev->name);
 				read_unlock_bh(&dev_base_lock);
 				return (dev);
 			}
@@ -2016,7 +2016,7 @@
 		}
 		read_unlock_bh(&dev_base_lock);
 	}
-	return (&strip_info->dev);
+	return (strip_info->dev);
 }
 
 /*
@@ -2029,7 +2029,7 @@
 	struct sk_buff *skb = dev_alloc_skb(sizeof(STRIP_Header) + packetlen);
 	if (!skb) {
 		printk(KERN_ERR "%s: memory squeeze, dropping packet.\n",
-		       strip_info->dev.name);
+		       strip_info->dev->name);
 		strip_info->rx_dropped++;
 	} else {
 		memcpy(skb_put(skb, sizeof(STRIP_Header)), header,
@@ -2073,12 +2073,12 @@
 
 	if (packetlen > MAX_RECV_MTU) {
 		printk(KERN_INFO "%s: Dropping oversized received IP packet: %d bytes\n",
-		       strip_info->dev.name, packetlen);
+		       strip_info->dev->name, packetlen);
 		strip_info->rx_dropped++;
 		return;
 	}
 
-	/*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev.name, packetlen); */
+	/*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev->name, packetlen); */
 
 	/* Decode remainder of the IP packet */
 	ptr =
@@ -2117,13 +2117,13 @@
 	if (packetlen > MAX_RECV_MTU) {
 		printk(KERN_INFO
 		       "%s: Dropping oversized received ARP packet: %d bytes\n",
-		       strip_info->dev.name, packetlen);
+		       strip_info->dev->name, packetlen);
 		strip_info->rx_dropped++;
 		return;
 	}
 
 	/*printk(KERN_INFO "%s: Got %d byte ARP %s\n",
-	   strip_info->dev.name, packetlen,
+	   strip_info->dev->name, packetlen,
 	   ntohs(arphdr->ar_op) == ARPOP_REQUEST ? "request" : "reply"); */
 
 	/* Decode remainder of the ARP packet */
@@ -2251,7 +2251,7 @@
 		}
 	}
 
-	/*printk(KERN_INFO "%s: Got packet from \"%s\".\n", strip_info->dev.name, sendername); */
+	/*printk(KERN_INFO "%s: Got packet from \"%s\".\n", strip_info->dev->name, sendername); */
 
 	/*
 	 * Fill in (pseudo) source and destination addresses in the packet.
@@ -2320,13 +2320,13 @@
 	unsigned long flags;
 
 	if (!strip_info || strip_info->magic != STRIP_MAGIC
-	    || !netif_running(&strip_info->dev))
+	    || !netif_running(strip_info->dev))
 		return;
 
 	spin_lock_irqsave(&strip_lock, flags);
 
 	/* Argh! mtu change time! - costs us the packet part received at the change */
-	if (strip_info->mtu != strip_info->dev.mtu)
+	if (strip_info->mtu != strip_info->dev->mtu)
 		strip_changedmtu(strip_info);
 
 #if 0
@@ -2347,7 +2347,7 @@
 	while (cp < end) {
 		if (fp && *fp)
 			printk(KERN_INFO "%s: %s on serial port\n",
-			       strip_info->dev.name, TTYERROR(*fp));
+			       strip_info->dev->name, TTYERROR(*fp));
 		if (fp && *fp++ && !strip_info->discard) {	/* If there's a serial error, record it */
 			/* If we have some characters in the buffer, discard them */
 			strip_info->discard = strip_info->sx_count;
@@ -2360,7 +2360,7 @@
 				if (strip_info->sx_count > 3000)
 					printk(KERN_INFO
 					       "%s: Cut a %d byte packet (%d bytes remaining)%s\n",
-					       strip_info->dev.name,
+					       strip_info->dev->name,
 					       strip_info->sx_count,
 					       end - cp - 1,
 					       strip_info->
@@ -2371,12 +2371,12 @@
 					strip_info->rx_over_errors++;
 					printk(KERN_INFO
 					       "%s: sx_buff overflow (%d bytes total)\n",
-					       strip_info->dev.name,
+					       strip_info->dev->name,
 					       strip_info->sx_count);
 				} else if (strip_info->discard)
 					printk(KERN_INFO
 					       "%s: Discarding bad packet (%d/%d)\n",
-					       strip_info->dev.name,
+					       strip_info->dev->name,
 					       strip_info->discard,
 					       strip_info->sx_count);
 				else
@@ -2415,9 +2415,9 @@
 	    memcmp(addr->c, broadcast_address.c,
 		   sizeof(broadcast_address));
 	if (strip_info->manual_dev_addr)
-		*(MetricomAddress *) strip_info->dev.dev_addr = *addr;
+		*(MetricomAddress *) strip_info->dev->dev_addr = *addr;
 	else
-		*(MetricomAddress *) strip_info->dev.dev_addr =
+		*(MetricomAddress *) strip_info->dev->dev_addr =
 		    strip_info->true_dev_addr;
 	return 0;
 }
@@ -2496,7 +2496,7 @@
 	strip_info->user_baud = get_baud(strip_info->tty);
 
 	printk(KERN_INFO "%s: Initializing Radio.\n",
-	       strip_info->dev.name);
+	       strip_info->dev->name);
 	ResetRadio(strip_info);
 	strip_info->idle_timer.expires = jiffies + 1 * HZ;
 	add_timer(&strip_info->idle_timer);
@@ -2589,6 +2589,8 @@
 	if (strip_info->next)
 		strip_info->next->referrer = strip_info->referrer;
 	strip_info->magic = 0;
+	if (strip_info->dev)
+		kfree(strip_info->dev);
 	kfree(strip_info);
 }
 
@@ -2600,6 +2602,7 @@
 {
 	int channel_id = 0;
 	struct strip **s = &struct_strip_list;
+	struct net_device *dev;
 	struct strip *strip_info = (struct strip *)
 	    kmalloc(sizeof(struct strip), GFP_KERNEL);
 
@@ -2612,13 +2615,22 @@
 
 	memset(strip_info, 0, sizeof(struct strip));
 
+	/* allocate the net_device */
+	dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	if (!dev) {
+		kfree(strip_info);
+		return NULL;
+	}
+	strip_info->dev = dev;
+	SET_MODULE_OWNER(dev);
+
 	/*
 	 * Search the list to find where to put our new entry
 	 * (and in the process decide what channel number it is
 	 * going to be)
 	 */
 
-	while (*s && (*s)->dev.base_addr == channel_id) {
+	while (*s && (*s)->dev->base_addr == channel_id) {
 		channel_id++;
 		s = &(*s)->next;
 	}
@@ -2639,15 +2651,15 @@
 	strip_info->gratuitous_arp = jiffies + LongTime;
 	strip_info->arp_interval = 0;
 	init_timer(&strip_info->idle_timer);
-	strip_info->idle_timer.data = (long) &strip_info->dev;
+	strip_info->idle_timer.data = (long) dev;
 	strip_info->idle_timer.function = strip_IdleTask;
 
 	/* Note: strip_info->if_name is currently 8 characters long */
-	sprintf(strip_info->dev.name, "st%d", channel_id);
-	strip_info->dev.base_addr = channel_id;
-	strip_info->dev.priv = (void *) strip_info;
-	strip_info->dev.next = NULL;
-	strip_info->dev.init = strip_dev_init;
+	sprintf(dev->name, "st%d", channel_id);
+	dev->base_addr = channel_id;
+	dev->priv = (void *) strip_info;
+	dev->next = NULL;
+	dev->init = strip_dev_init;
 
 	return strip_info;
 }
@@ -2682,7 +2694,7 @@
 	 * strip_dev_init() will be called as a side-effect
 	 */
 
-	if (register_netdev(&strip_info->dev) != 0) {
+	if (register_netdev(strip_info->dev) != 0) {
 		printk(KERN_ERR "strip: register_netdev() failed.\n");
 		strip_free(strip_info);
 		return -ENFILE;
@@ -2699,7 +2711,7 @@
 	 * Restore default settings
 	 */
 
-	strip_info->dev.type = ARPHRD_METRICOM;	/* dtang */
+	strip_info->dev->type = ARPHRD_METRICOM;	/* dtang */
 
 	/*
 	 * Set tty options
@@ -2709,15 +2721,13 @@
 	tty->termios->c_cflag |= CLOCAL;	/* Ignore modem control signals. */
 	tty->termios->c_cflag &= ~HUPCL;	/* Don't close on hup */
 
-	MOD_INC_USE_COUNT;
-
 	printk(KERN_INFO "STRIP: device \"%s\" activated\n",
-	       strip_info->dev.name);
+	       strip_info->dev->name);
 
 	/*
 	 * Done.  We have linked the TTY line to a channel.
 	 */
-	return (strip_info->dev.base_addr);
+	return (strip_info->dev->base_addr);
 }
 
 /*
@@ -2738,15 +2748,14 @@
 	if (!strip_info || strip_info->magic != STRIP_MAGIC)
 		return;
 
-	unregister_netdev(&strip_info->dev);
+	unregister_netdev(strip_info->dev);
 
 	tty->disc_data = 0;
 	strip_info->tty = NULL;
 	printk(KERN_INFO "STRIP: device \"%s\" closed down\n",
-	       strip_info->dev.name);
+	       strip_info->dev->name);
 	strip_free(strip_info);
 	tty->disc_data = NULL;
-	MOD_DEC_USE_COUNT;
 }
 
 
@@ -2767,13 +2776,13 @@
 
 	switch (cmd) {
 	case SIOCGIFNAME:
-		if(copy_to_user((void *) arg, strip_info->dev.name, strlen(strip_info->dev.name) + 1))
+		if(copy_to_user((void *) arg, strip_info->dev->name, strlen(strip_info->dev->name) + 1))
 			return -EFAULT;
 		break;
 	case SIOCSIFHWADDR:
 	{
 		MetricomAddress addr;
-		//printk(KERN_INFO "%s: SIOCSIFHWADDR\n", strip_info->dev.name);
+		//printk(KERN_INFO "%s: SIOCSIFHWADDR\n", strip_info->dev->name);
 		if(copy_from_user(&addr, (void *) arg, sizeof(MetricomAddress)))
 			return -EFAULT;
 		return set_mac_address(strip_info, &addr);
diff -urN linux-2.5.73-bk9/drivers/s390/cio/device.c linux-2.5.73-bk10/drivers/s390/cio/device.c
--- linux-2.5.73-bk9/drivers/s390/cio/device.c	2003-07-02 04:57:16.000000000 -0700
+++ linux-2.5.73-bk10/drivers/s390/cio/device.c	2003-07-02 04:57:29.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.57 $
+ *   $Revision: 1.58 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -305,9 +305,9 @@
 		return count;
 
 	i = simple_strtoul(buf, &tmp, 16);
-	if (i == 0 && cdev->drv->set_online)
+	if (i == 1 && cdev->drv->set_online)
 		ccw_device_set_online(cdev);
-	else if (i == 1 && cdev->drv->set_offline)
+	else if (i == 0 && cdev->drv->set_offline)
 		ccw_device_set_offline(cdev);
 	else
 		return -EINVAL;
diff -urN linux-2.5.73-bk9/drivers/s390/cio/qdio.c linux-2.5.73-bk10/drivers/s390/cio/qdio.c
--- linux-2.5.73-bk9/drivers/s390/cio/qdio.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk10/drivers/s390/cio/qdio.c	2003-07-02 04:57:30.000000000 -0700
@@ -55,7 +55,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.49 $"
+#define VERSION_QDIO_C "$Revision: 1.51 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -74,6 +74,8 @@
 static struct qdio_perf_stats perf_stats;
 #endif /* QDIO_PERFORMANCE_STATS */
 
+static int hydra_thinints;
+
 static int indicator_used[INDICATORS_PER_CACHELINE];
 static __u32 * volatile indicators;
 static __u32 volatile spare_indicator;
@@ -88,12 +90,12 @@
 #endif /* QDIO_DBF_LIKE_HELL */
 
 /* iQDIO stuff: */
-static volatile struct qdio_q *iq_list=NULL; /* volatile as it could change
-						  during a while loop */
-static spinlock_t iq_list_lock=SPIN_LOCK_UNLOCKED;
+static volatile struct qdio_q *tiq_list=NULL; /* volatile as it could change
+						 during a while loop */
+static spinlock_t ttiq_list_lock=SPIN_LOCK_UNLOCKED;
 static int register_thinint_result;
-static void iqdio_tl(unsigned long);
-static DECLARE_TASKLET(iqdio_tasklet,iqdio_tl,0);
+static void tiqdio_tl(unsigned long);
+static DECLARE_TASKLET(tiqdio_tasklet,tiqdio_tl,0);
 
 /* not a macro, as one of the arguments is atomic_read */
 static inline int 
@@ -173,7 +175,7 @@
 /* 
  * unfortunately, we can't just xchg the values; in do_QDIO we want to reserve
  * the q in any case, so that we'll not be interrupted when we are in
- * qdio_mark_iq... shouldn't have a really bad impact, as reserving almost
+ * qdio_mark_tiq... shouldn't have a really bad impact, as reserving almost
  * ever works (last famous words) 
  */
 static inline int 
@@ -195,7 +197,8 @@
 }
 
 static inline int 
-qdio_siga_sync(struct qdio_q *q)
+qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
+	       unsigned int gpr3)
 {
 	int cc;
 
@@ -206,17 +209,21 @@
 	perf_stats.siga_syncs++;
 #endif /* QDIO_PERFORMANCE_STATS */
 
-	if (q->is_input_q)
-		cc = do_siga_sync(q->irq, 0, q->mask);
-	else
-		cc = do_siga_sync(q->irq, q->mask, 0);
-
+	cc = do_siga_sync(q->irq, gpr2, gpr3);
 	if (cc)
 		QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
 
 	return cc;
 }
 
+static inline int
+qdio_siga_sync_q(struct qdio_q *q)
+{
+	if (q->is_input_q)
+		return qdio_siga_sync(q, 0, q->mask);
+	return qdio_siga_sync(q, q->mask, 0);
+}
+
 /* 
  * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns
  * an access exception 
@@ -304,7 +311,7 @@
 }
 
 static inline volatile void 
-iqdio_clear_summary_bit(__u32 *location)
+tiqdio_clear_summary_bit(__u32 *location)
 {
 	QDIO_DBF_TEXT5(0,trace,"clrsummb");
 	QDIO_DBF_HEX5(0,trace,&location,sizeof(void*));
@@ -313,7 +320,7 @@
 }
 
 static inline volatile void
-iqdio_set_summary_bit(__u32 *location)
+tiqdio_set_summary_bit(__u32 *location)
 {
 	QDIO_DBF_TEXT5(0,trace,"setsummb");
 	QDIO_DBF_HEX5(0,trace,&location,sizeof(void*));
@@ -322,21 +329,21 @@
 }
 
 static inline void 
-iqdio_sched_tl(void)
+tiqdio_sched_tl(void)
 {
-	tasklet_hi_schedule(&iqdio_tasklet);
+	tasklet_hi_schedule(&tiqdio_tasklet);
 }
 
 static inline void
-qdio_mark_iq(struct qdio_q *q)
+qdio_mark_tiq(struct qdio_q *q)
 {
 	unsigned long flags;
 
 	QDIO_DBF_TEXT4(0,trace,"mark iq");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
-	spin_lock_irqsave(&iq_list_lock,flags);
-	if (atomic_read(&q->is_in_shutdown)) 
+	spin_lock_irqsave(&ttiq_list_lock,flags);
+	if (unlikely(atomic_read(&q->is_in_shutdown)))
 		goto out_unlock;
 
 	if (!q->is_input_q)
@@ -345,23 +352,23 @@
 	if ((q->list_prev) || (q->list_next)) 
 		goto out_unlock;
 
-	if (!iq_list) {
-		iq_list=q;
+	if (!tiq_list) {
+		tiq_list=q;
 		q->list_prev=q;
 		q->list_next=q;
 	} else {
-		q->list_next=iq_list;
-		q->list_prev=iq_list->list_prev;
-		iq_list->list_prev->list_next=q;
-		iq_list->list_prev=q;
+		q->list_next=tiq_list;
+		q->list_prev=tiq_list->list_prev;
+		tiq_list->list_prev->list_next=q;
+		tiq_list->list_prev=q;
 	}
-	spin_unlock_irqrestore(&iq_list_lock,flags);
+	spin_unlock_irqrestore(&ttiq_list_lock,flags);
 
-	iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
-	iqdio_sched_tl();
+	tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+	tiqdio_sched_tl();
 	return;
 out_unlock:
-	spin_unlock_irqrestore(&iq_list_lock,flags);
+	spin_unlock_irqrestore(&ttiq_list_lock,flags);
 	return;
 }
 
@@ -371,7 +378,7 @@
 	QDIO_DBF_TEXT4(0,trace,"mark q");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
-	if (atomic_read(&q->is_in_shutdown))
+	if (unlikely(atomic_read(&q->is_in_shutdown)))
 		return;
 
 	tasklet_schedule(&q->tasklet);
@@ -410,7 +417,7 @@
 	 * checking for PRIMED state 
 	 */
 	if (q->is_iqdio_q)
-		iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+		tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
 	return 0;
 
 #else /* QDIO_USE_PROCESSING_STATE */
@@ -434,27 +441,27 @@
 	if ((!q->list_prev)||(!q->list_next))
 		return;
 
-	if ((q->is_iqdio_q)&&(q->is_input_q)) {
+	if ((q->is_thinint_q)&&(q->is_input_q)) {
 		/* iQDIO */
-		spin_lock_irqsave(&iq_list_lock,flags);
+		spin_lock_irqsave(&ttiq_list_lock,flags);
 		if (q->list_next==q) {
 			/* q was the only interesting q */
-			iq_list=NULL;
+			tiq_list=NULL;
 			q->list_next=NULL;
 			q->list_prev=NULL;
 		} else {
 			q->list_next->list_prev=q->list_prev;
 			q->list_prev->list_next=q->list_next;
-			iq_list=q->list_next;
+			tiq_list=q->list_next;
 			q->list_next=NULL;
 			q->list_prev=NULL;
 		}
-		spin_unlock_irqrestore(&iq_list_lock,flags);
+		spin_unlock_irqrestore(&ttiq_list_lock,flags);
 	}
 }
 
 static inline unsigned long 
-iqdio_clear_global_summary(void)
+tiqdio_clear_global_summary(void)
 {
 	unsigned long time;
 
@@ -467,6 +474,223 @@
 	return time;
 }
 
+
+/************************* OUTBOUND ROUTINES *******************************/
+
+inline static int
+qdio_get_outbound_buffer_frontier(struct qdio_q *q)
+{
+	int f,f_mod_no;
+	volatile char *slsb;
+	int first_not_to_check;
+	char dbf_text[15];
+
+	QDIO_DBF_TEXT4(0,trace,"getobfro");
+	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+
+	slsb=&q->slsb.acc.val[0];
+	f_mod_no=f=q->first_to_check;
+	/* 
+	 * f points to already processed elements, so f+no_used is correct...
+	 * ... but: we don't check 128 buffers, as otherwise
+	 * qdio_has_outbound_q_moved would return 0 
+	 */
+	first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used),
+				      (QDIO_MAX_BUFFERS_PER_Q-1));
+
+	if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis))
+		SYNC_MEMORY;
+
+check_next:
+	if (f==first_not_to_check) 
+		goto out;
+
+	switch(slsb[f_mod_no]) {
+
+        /* the hydra has not fetched the output yet */
+	case SLSB_CU_OUTPUT_PRIMED:
+		QDIO_DBF_TEXT5(0,trace,"outpprim");
+		break;
+
+	/* the hydra got it */
+	case SLSB_P_OUTPUT_EMPTY:
+		atomic_dec(&q->number_of_buffers_used);
+		f++;
+		f_mod_no=f&(QDIO_MAX_BUFFERS_PER_Q-1);
+		QDIO_DBF_TEXT5(0,trace,"outpempt");
+		goto check_next;
+
+	case SLSB_P_OUTPUT_ERROR:
+		QDIO_DBF_TEXT3(0,trace,"outperr");
+		sprintf(dbf_text,"%x-%x-%x",f_mod_no,
+			q->sbal[f_mod_no]->element[14].sbalf.value,
+			q->sbal[f_mod_no]->element[15].sbalf.value);
+		QDIO_DBF_TEXT3(1,trace,dbf_text);
+		QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
+
+		/* kind of process the buffer */
+		set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT);
+
+		/* 
+		 * we increment the frontier, as this buffer
+		 * was processed obviously 
+		 */
+		atomic_dec(&q->number_of_buffers_used);
+		f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
+
+		if (q->qdio_error)
+			q->error_status_flags|=
+				QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
+		q->qdio_error=SLSB_P_OUTPUT_ERROR;
+		q->error_status_flags|=QDIO_STATUS_LOOK_FOR_ERROR;
+
+		break;
+
+	/* no new buffers */
+	default:
+		QDIO_DBF_TEXT5(0,trace,"outpni");
+	}
+out:
+	return (q->first_to_check=f_mod_no);
+}
+
+/* all buffers are processed */
+inline static int
+qdio_is_outbound_q_done(struct qdio_q *q)
+{
+	int no_used;
+	char dbf_text[15];
+
+	no_used=atomic_read(&q->number_of_buffers_used);
+
+	if (no_used) {
+		sprintf(dbf_text,"oqisnt%02x",no_used);
+		QDIO_DBF_TEXT4(0,trace,dbf_text);
+	} else {
+		QDIO_DBF_TEXT4(0,trace,"oqisdone");
+	}
+	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+	return (no_used==0);
+}
+
+inline static int
+qdio_has_outbound_q_moved(struct qdio_q *q)
+{
+	int i;
+
+	i=qdio_get_outbound_buffer_frontier(q);
+
+	if ( (i!=GET_SAVED_FRONTIER(q)) ||
+	     (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
+		SAVE_FRONTIER(q,i);
+		SAVE_TIMESTAMP(q);
+		QDIO_DBF_TEXT4(0,trace,"oqhasmvd");
+		QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+		return 1;
+	} else {
+		QDIO_DBF_TEXT4(0,trace,"oqhsntmv");
+		QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+		return 0;
+	}
+}
+
+inline static void
+qdio_kick_outbound_q(struct qdio_q *q)
+{
+	int result;
+
+	QDIO_DBF_TEXT4(0,trace,"kickoutq");
+	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+
+	if (!q->siga_out)
+		return;
+
+	result=qdio_siga_output(q);
+
+	if (!result)
+		return;
+
+	if (q->siga_error)
+		q->error_status_flags|=QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
+	q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
+	q->siga_error=result;
+}
+
+inline static void
+qdio_kick_outbound_handler(struct qdio_q *q)
+{
+	int start, end, real_end, count;
+	char dbf_text[15];
+
+	start = q->first_element_to_kick;
+	/* last_move_ftc was just updated */
+	real_end = GET_SAVED_FRONTIER(q);
+	end = (real_end+QDIO_MAX_BUFFERS_PER_Q-1)&
+		(QDIO_MAX_BUFFERS_PER_Q-1);
+	count = (end+QDIO_MAX_BUFFERS_PER_Q+1-start)&
+		(QDIO_MAX_BUFFERS_PER_Q-1);
+
+	QDIO_DBF_TEXT4(0,trace,"kickouth");
+	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+
+	sprintf(dbf_text,"s=%2xc=%2x",start,count);
+	QDIO_DBF_TEXT4(0,trace,dbf_text);
+
+	if (q->state==QDIO_IRQ_STATE_ACTIVE)
+		q->handler(q->cdev,QDIO_STATUS_OUTBOUND_INT|
+			   q->error_status_flags,
+			   q->qdio_error,q->siga_error,q->q_no,start,count,
+			   q->int_parm);
+
+	/* for the next time: */
+	q->first_element_to_kick=real_end;
+	q->qdio_error=0;
+	q->siga_error=0;
+	q->error_status_flags=0;
+}
+
+static void
+qdio_outbound_processing(struct qdio_q *q)
+{
+	QDIO_DBF_TEXT4(0,trace,"qoutproc");
+	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+
+	if (unlikely(qdio_reserve_q(q))) {
+		qdio_release_q(q);
+#ifdef QDIO_PERFORMANCE_STATS
+		o_p_c++;
+#endif /* QDIO_PERFORMANCE_STATS */
+		/* as we're sissies, we'll check next time */
+		if (likely(!atomic_read(&q->is_in_shutdown))) {
+			qdio_mark_q(q);
+			QDIO_DBF_TEXT4(0,trace,"busy,agn");
+		}
+		return;
+	}
+#ifdef QDIO_PERFORMANCE_STATS
+	o_p_nc++;
+	perf_stats.tl_runs++;
+#endif /* QDIO_PERFORMANCE_STATS */
+
+	if (qdio_has_outbound_q_moved(q))
+		qdio_kick_outbound_handler(q);
+
+	if (q->is_iqdio_q) {
+		/* 
+		 * for asynchronous queues, we better check, if the fill
+		 * level is too high 
+		 */
+		if (atomic_read(&q->number_of_buffers_used)>
+		    IQDIO_FILL_LEVEL_TO_POLL)
+			qdio_mark_q(q);
+
+	} else if (!q->hydra_gives_outbound_pcis)
+		if (!qdio_is_outbound_q_done(q))
+			qdio_mark_q(q);
+
+	qdio_release_q(q);
+}
+
 /************************* INBOUND ROUTINES *******************************/
 
 
@@ -650,8 +874,8 @@
 	 * we will return 0 below, as there is nothing to do, except scheduling
 	 * ourselves for the next time. 
 	 */
-	iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
-	iqdio_sched_tl();
+	tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+	tiqdio_sched_tl();
 	return 0;
 }
 
@@ -725,14 +949,15 @@
 	count=0;
  	while (1) {
  		count++;
- 		if (i==end) break;
+ 		if (i==end)
+			break;
  		i=(i+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
  	}
 
 	sprintf(dbf_text,"s=%2xc=%2x",start,count);
 	QDIO_DBF_TEXT4(0,trace,dbf_text);
 
-	if (q->state==QDIO_IRQ_STATE_ACTIVE)
+	if (likely(q->state==QDIO_IRQ_STATE_ACTIVE))
 		q->handler(q->cdev,
 			   QDIO_STATUS_INBOUND_INT|q->error_status_flags,
 			   q->qdio_error,q->siga_error,q->q_no,start,count,
@@ -751,8 +976,12 @@
 }
 
 static inline void
-iqdio_inbound_processing(struct qdio_q *q)
+tiqdio_inbound_processing(struct qdio_q *q)
 {
+	struct qdio_irq *irq_ptr;
+	struct qdio_q *oq;
+	int i;
+
 	QDIO_DBF_TEXT4(0,trace,"iqinproc");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
@@ -761,7 +990,7 @@
 	 * interrupt ourselves and call qdio_unmark_q, as is_in_shutdown might
 	 * be set 
 	 */
-	if (qdio_reserve_q(q)) {
+	if (unlikely(qdio_reserve_q(q))) {
 		qdio_release_q(q);
 #ifdef QDIO_PERFORMANCE_STATS
 		ii_p_c++;
@@ -770,13 +999,13 @@
 		 * as we might just be about to stop polling, we make
 		 * sure that we check again at least once more 
 		 */
-		iqdio_sched_tl();
+		tiqdio_sched_tl();
 		return;
 	}
 #ifdef QDIO_PERFORMANCE_STATS
 	ii_p_nc++;
 #endif /* QDIO_PERFORMANCE_STATS */
-	if (atomic_read(&q->is_in_shutdown)) {
+	if (unlikely(atomic_read(&q->is_in_shutdown))) {
 		qdio_unmark_q(q);
 		goto out;
 	}
@@ -784,10 +1013,34 @@
 	if (!(*(q->dev_st_chg_ind)))
 		goto out;
 
-	iqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);
+	tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);
 
-	if (!q->siga_sync_done_on_thinints)
-			SYNC_MEMORY;
+	if (q->hydra_gives_outbound_pcis) {
+		if (!q->siga_sync_done_on_thinints) {
+			SYNC_MEMORY_ALL;
+		} else if ((!q->siga_sync_done_on_outb_tis)&&
+			 (q->hydra_gives_outbound_pcis)) {
+			SYNC_MEMORY_ALL_OUTB;
+		}
+	} else {
+		SYNC_MEMORY;
+	}
+	/*
+	 * maybe we have to do work on our outbound queues... at least
+	 * we have to check Hydra outbound-int-capable thinint-capable
+	 * queues
+	 */
+	if (q->hydra_gives_outbound_pcis) {
+		irq_ptr = (struct qdio_irq*)q->irq_ptr;
+		for (i=0;i<irq_ptr->no_output_qs;i++) {
+			oq = irq_ptr->output_qs[i];
+#ifdef QDIO_PERFORMANCE_STATS
+			perf_stats.tl_runs--;
+#endif /* QDIO_PERFORMANCE_STATS */
+			if (!qdio_is_outbound_q_done(oq))
+				qdio_outbound_processing(oq);
+		}
+	}
 
 	if (!qdio_has_inbound_q_moved(q))
 		goto out;
@@ -799,8 +1052,8 @@
 			 * we set the flags to get into the stuff next time,
 			 * see also comment in qdio_stop_polling 
 			 */
-			iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
-			iqdio_sched_tl();
+			tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+			tiqdio_sched_tl();
 		}
 out:
 	qdio_release_q(q);
@@ -814,13 +1067,13 @@
 	QDIO_DBF_TEXT4(0,trace,"qinproc");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
-	if (qdio_reserve_q(q)) {
+	if (unlikely(qdio_reserve_q(q))) {
 		qdio_release_q(q);
 #ifdef QDIO_PERFORMANCE_STATS
 		i_p_c++;
 #endif /* QDIO_PERFORMANCE_STATS */
 		/* as we're sissies, we'll check next time */
-		if (!atomic_read(&q->is_in_shutdown)) {
+		if (likely(!atomic_read(&q->is_in_shutdown))) {
 			qdio_mark_q(q);
 			QDIO_DBF_TEXT4(0,trace,"busy,agn");
 		}
@@ -849,229 +1102,14 @@
 	qdio_release_q(q);
 }
 
-/************************* OUTBOUND ROUTINES *******************************/
-
-inline static int
-qdio_get_outbound_buffer_frontier(struct qdio_q *q)
-{
-	int f,f_mod_no;
-	volatile char *slsb;
-	int first_not_to_check;
-	char dbf_text[15];
-
-	QDIO_DBF_TEXT4(0,trace,"getobfro");
-	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-
-	slsb=&q->slsb.acc.val[0];
-	f_mod_no=f=q->first_to_check;
-	/* 
-	 * f points to already processed elements, so f+no_used is correct...
-	 * ... but: we don't check 128 buffers, as otherwise
-	 * qdio_has_outbound_q_moved would return 0 
-	 */
-	first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used),
-				      (QDIO_MAX_BUFFERS_PER_Q-1));
-
-	if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis))
-		SYNC_MEMORY;
-
-check_next:
-	if (f==first_not_to_check) 
-		goto out;
-
-	switch(slsb[f_mod_no]) {
-
-        /* the hydra has not fetched the output yet */
-	case SLSB_CU_OUTPUT_PRIMED:
-		QDIO_DBF_TEXT5(0,trace,"outpprim");
-		break;
-
-	/* the hydra got it */
-	case SLSB_P_OUTPUT_EMPTY:
-		atomic_dec(&q->number_of_buffers_used);
-		f++;
-		f_mod_no=f&(QDIO_MAX_BUFFERS_PER_Q-1);
-		QDIO_DBF_TEXT5(0,trace,"outpempt");
-		goto check_next;
-
-	case SLSB_P_OUTPUT_ERROR:
-		QDIO_DBF_TEXT3(0,trace,"outperr");
-		sprintf(dbf_text,"%x-%x-%x",f_mod_no,
-			q->sbal[f_mod_no]->element[14].sbalf.value,
-			q->sbal[f_mod_no]->element[15].sbalf.value);
-		QDIO_DBF_TEXT3(1,trace,dbf_text);
-		QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
-
-		/* kind of process the buffer */
-		set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT);
-
-		/* 
-		 * we increment the frontier, as this buffer
-		 * was processed obviously 
-		 */
-		atomic_dec(&q->number_of_buffers_used);
-		f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
-
-		if (q->qdio_error)
-			q->error_status_flags|=
-				QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
-		q->qdio_error=SLSB_P_OUTPUT_ERROR;
-		q->error_status_flags|=QDIO_STATUS_LOOK_FOR_ERROR;
-
-		break;
-
-	/* no new buffers */
-	default:
-		QDIO_DBF_TEXT5(0,trace,"outpni");
-	}
-out:
-	return (q->first_to_check=f_mod_no);
-}
-
-/* all buffers are processed */
-inline static int
-qdio_is_outbound_q_done(struct qdio_q *q)
-{
-	int no_used;
-	char dbf_text[15];
-
-	no_used=atomic_read(&q->number_of_buffers_used);
-
-	if (no_used) {
-		sprintf(dbf_text,"oqisnt%02x",no_used);
-		QDIO_DBF_TEXT4(0,trace,dbf_text);
-	} else {
-		QDIO_DBF_TEXT4(0,trace,"oqisdone");
-	}
-	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-	return (no_used==0);
-}
-
-inline static int
-qdio_has_outbound_q_moved(struct qdio_q *q)
-{
-	int i;
-
-	i=qdio_get_outbound_buffer_frontier(q);
-
-	if ( (i!=GET_SAVED_FRONTIER(q)) ||
-	     (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
-		SAVE_FRONTIER(q,i);
-		SAVE_TIMESTAMP(q);
-		QDIO_DBF_TEXT4(0,trace,"oqhasmvd");
-		QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-		return 1;
-	} else {
-		QDIO_DBF_TEXT4(0,trace,"oqhsntmv");
-		QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-		return 0;
-	}
-}
-
-inline static void
-qdio_kick_outbound_q(struct qdio_q *q)
-{
-	int result;
-
-	QDIO_DBF_TEXT4(0,trace,"kickoutq");
-	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-
-	if (!q->siga_out)
-		return;
-
-	result=qdio_siga_output(q);
-
-	if (!result)
-		return;
-
-	if (q->siga_error)
-		q->error_status_flags|=QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
-	q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
-	q->siga_error=result;
-}
-
-inline static void
-qdio_kick_outbound_handler(struct qdio_q *q)
-{
-	int start, end, real_end, count;
-	char dbf_text[15];
-
-	start = q->first_element_to_kick;
-	/* last_move_ftc was just updated */
-	real_end = GET_SAVED_FRONTIER(q);
-	end = (real_end+QDIO_MAX_BUFFERS_PER_Q-1)&
-		(QDIO_MAX_BUFFERS_PER_Q-1);
-	count = (end+QDIO_MAX_BUFFERS_PER_Q+1-start)&
-		(QDIO_MAX_BUFFERS_PER_Q-1);
-
-	QDIO_DBF_TEXT4(0,trace,"kickouth");
-	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-
-	sprintf(dbf_text,"s=%2xc=%2x",start,count);
-	QDIO_DBF_TEXT4(0,trace,dbf_text);
-
-	if (q->state==QDIO_IRQ_STATE_ACTIVE)
-		q->handler(q->cdev,QDIO_STATUS_OUTBOUND_INT|
-			   q->error_status_flags,
-			   q->qdio_error,q->siga_error,q->q_no,start,count,
-			   q->int_parm);
-
-	/* for the next time: */
-	q->first_element_to_kick=real_end;
-	q->qdio_error=0;
-	q->siga_error=0;
-	q->error_status_flags=0;
-}
-
-static void qdio_outbound_processing(struct qdio_q *q)
-{
-	QDIO_DBF_TEXT4(0,trace,"qoutproc");
-	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-
-	if (qdio_reserve_q(q)) {
-		qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
-		o_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
-		/* as we're sissies, we'll check next time */
-		if (!atomic_read(&q->is_in_shutdown)) {
-			qdio_mark_q(q);
-			QDIO_DBF_TEXT4(0,trace,"busy,agn");
-		}
-		return;
-	}
-#ifdef QDIO_PERFORMANCE_STATS
-	o_p_nc++;
-	perf_stats.tl_runs++;
-#endif /* QDIO_PERFORMANCE_STATS */
-
-	if (qdio_has_outbound_q_moved(q))
-		qdio_kick_outbound_handler(q);
-
-	if (q->is_iqdio_q) {
-		/* 
-		 * for asynchronous queues, we better check, if the fill
-		 * level is too high 
-		 */
-		if (atomic_read(&q->number_of_buffers_used)>
-		    IQDIO_FILL_LEVEL_TO_POLL)
-			qdio_mark_q(q);
-
-	} else if (!q->hydra_gives_outbound_pcis)
-		if (!qdio_is_outbound_q_done(q))
-			qdio_mark_q(q);
-
-	qdio_release_q(q);
-}
-
 /************************* MAIN ROUTINES *******************************/
 
 #ifdef QDIO_USE_PROCESSING_STATE
 static inline int
-iqdio_do_inbound_checks(struct qdio_q *q, int q_laps)
+tiqdio_do_inbound_checks(struct qdio_q *q, int q_laps)
 {
 	if (!q) {
-		iqdio_sched_tl();
+		tiqdio_sched_tl();
 		return 0;
 	}
 
@@ -1082,7 +1120,7 @@
 	if (q->siga_sync)
 		return 2;
 
-	if (qdio_reserve_q(q)) {
+	if (unlikely(qdio_reserve_q(q))) {
 		qdio_release_q(q);
 #ifdef QDIO_PERFORMANCE_STATS
 		ii_p_c++;
@@ -1096,8 +1134,8 @@
 		 * sanity -- we'd get here without setting the
 		 * dev st chg ind 
 		 */
-		iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
-		iqdio_sched_tl();
+		tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+		tiqdio_sched_tl();
 		return 0;
 	}
 	if (qdio_stop_polling(q)) {
@@ -1112,8 +1150,8 @@
 	 * we set the flags to get into the stuff
 	 * next time, see also comment in qdio_stop_polling 
 	 */
-	iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
-	iqdio_sched_tl();
+	tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+	tiqdio_sched_tl();
 	qdio_release_q(q);
 	return 1;
 	
@@ -1121,7 +1159,7 @@
 #endif /* QDIO_USE_PROCESSING_STATE */
 
 static inline void
-iqdio_inbound_checks(void)
+tiqdio_inbound_checks(void)
 {
 	struct qdio_q *q;
 #ifdef QDIO_USE_PROCESSING_STATE
@@ -1135,20 +1173,20 @@
 again:
 #endif /* QDIO_USE_PROCESSING_STATE */
 
-	q=(struct qdio_q*)iq_list;
+	q=(struct qdio_q*)tiq_list;
 	do {
 		if (!q)
 			break;
-		iqdio_inbound_processing(q);
+		tiqdio_inbound_processing(q);
 		q=(struct qdio_q*)q->list_next;
-	} while (q!=(struct qdio_q*)iq_list);
+	} while (q!=(struct qdio_q*)tiq_list);
 
 #ifdef QDIO_USE_PROCESSING_STATE
-	q=(struct qdio_q*)iq_list;
+	q=(struct qdio_q*)tiq_list;
 	do {
 		int ret;
 
-		ret = iqdio_do_inbound_checks(q, q_laps);
+		ret = tiqdio_do_inbound_checks(q, q_laps);
 		switch (ret) {
 		case 0:
 			return;
@@ -1161,17 +1199,12 @@
 			q_laps++;
 			goto again;
 		}
-	} while (q!=(struct qdio_q*)iq_list);
+	} while (q!=(struct qdio_q*)tiq_list);
 #endif /* QDIO_USE_PROCESSING_STATE */
 }
 
 static void
-iqdio_check_for_polling(void)
-{
-}
-
-static void
-iqdio_tl(unsigned long data)
+tiqdio_tl(unsigned long data)
 {
 	QDIO_DBF_TEXT4(0,trace,"iqdio_tl");
 
@@ -1179,8 +1212,7 @@
 	perf_stats.tl_runs++;
 #endif /* QDIO_PERFORMANCE_STATS */
 
-	iqdio_inbound_checks();
-	iqdio_check_for_polling();
+	tiqdio_inbound_checks();
 }
 
 /********************* GENERAL HELPER_ROUTINES ***********************/
@@ -1298,6 +1330,7 @@
 		q->int_parm=int_parm;
 		irq_ptr->input_qs[i]=q;
 		q->irq=irq_ptr->irq;
+		q->irq_ptr = irq_ptr;
 		q->cdev = cdev;
 		q->mask=1<<(31-i);
 		q->q_no=i;
@@ -1308,10 +1341,11 @@
 		q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind;
 
 		q->tasklet.data=(unsigned long)q;
+		/* q->is_thinint_q isn't valid at this time, but
+		 * irq_ptr->is_thinint_irq is */
 		q->tasklet.func=(void(*)(unsigned long))
-			(
-			(q_format==QDIO_IQDIO_QFMT)?&iqdio_inbound_processing:
-			&qdio_inbound_processing);
+			((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing:
+			 &qdio_inbound_processing);
 
 /*		for (j=0;j<QDIO_STATS_NUMBER;j++)
 			q->timing.last_transfer_times[j]=(qdio_get_micros()/
@@ -1376,6 +1410,7 @@
 		q->is_input_q=0;
 		q->irq=irq_ptr->irq;
 		q->cdev = cdev;
+		q->irq_ptr = irq_ptr;
 		q->mask=1<<(31-i);
 		q->q_no=i;
 		q->first_to_check=0;
@@ -1454,7 +1489,7 @@
 }
 
 static int
-iqdio_thinint_handler(void)
+tiqdio_thinint_handler(void)
 {
 	QDIO_DBF_TEXT4(0,trace,"thin_int");
 
@@ -1464,10 +1499,9 @@
 #endif /* QDIO_PERFORMANCE_STATS */
 	/* VM will do the SVS for us */
 	if (!MACHINE_IS_VM)
-		iqdio_clear_global_summary();
+		tiqdio_clear_global_summary();
 
-	iqdio_inbound_checks();
-	iqdio_check_for_polling();
+	tiqdio_inbound_checks();
 	return 0;
 }
 
@@ -1814,9 +1848,10 @@
 }
 
 static unsigned int
-iqdio_check_chsc_availability(void)
+tiqdio_check_chsc_availability(void)
 {
 	int result;
+	char dbf_text[15];
 
 	struct {
 		struct chsc_header request;
@@ -1871,6 +1906,12 @@
 		result=-ENOENT;
 		goto exit;
 	}
+
+	/* Check for hydra thin interrupts. */
+	hydra_thinints = ((scsc_area->general_char[2] & 0x10000000)
+		== 0x10000000);
+	sprintf(dbf_text,"hydra_ti%1x", hydra_thinints);
+	QDIO_DBF_TEXT0(0,setup,dbf_text);
 exit:
 	free_page ((unsigned long) scsc_area);
 	return result;
@@ -1878,7 +1919,7 @@
 
 
 static unsigned int
-iqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
+tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
 {
 	unsigned long real_addr_local_summary_bit;
 	unsigned long real_addr_dev_st_chg_ind;
@@ -1907,7 +1948,7 @@
 		u32 reserved7;
 	} *scssc_area;
 
-	if (!irq_ptr->is_iqdio_irq)
+	if (!irq_ptr->is_thinint_irq)
 		return -ENODEV;
 
 	if (reset_to_zero) {
@@ -1936,7 +1977,7 @@
 	scssc_area->subchannel_indicator_addr = real_addr_dev_st_chg_ind;
 	scssc_area->ks = QDIO_STORAGE_KEY;
 	scssc_area->kc = QDIO_STORAGE_KEY;
-	scssc_area->isc = IQDIO_THININT_ISC;
+	scssc_area->isc = TIQDIO_THININT_ISC;
 	scssc_area->subsystem_id = (1<<16) + irq_ptr->irq;
 
 	result = chsc(scssc_area);
@@ -1972,7 +2013,7 @@
 }
 
 static unsigned int
-iqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
+tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
 {
 	unsigned int resp_code;
 	int result;
@@ -1992,7 +2033,7 @@
 		u32 reserved6;
 	} *scsscf_area;
 
-	if (!irq_ptr->is_iqdio_irq)
+	if (!irq_ptr->is_thinint_irq)
 		return -ENODEV;
 
 	scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -2082,7 +2123,7 @@
 	for (i=0;i<irq_ptr->no_output_qs;i++)
 		atomic_set(&irq_ptr->output_qs[i]->is_in_shutdown,1);
 
-	tasklet_kill(&iqdio_tasklet);
+	tasklet_kill(&tiqdio_tasklet);
 
 	for (i=0;i<irq_ptr->no_input_qs;i++) {
 		qdio_unmark_q(irq_ptr->input_qs[i]);
@@ -2145,9 +2186,9 @@
 static inline void
 qdio_cleanup_finish(struct ccw_device *cdev, struct qdio_irq *irq_ptr)
 {
-	if (irq_ptr->is_iqdio_irq) {
+	if (irq_ptr->is_thinint_irq) {
 		qdio_put_indicator((__u32*)irq_ptr->dev_st_chg_ind);
-		iqdio_set_subchannel_ind(irq_ptr,1); 
+		tiqdio_set_subchannel_ind(irq_ptr,1); 
                 /* reset adapter interrupt indicators */
 	}
 
@@ -2156,6 +2197,7 @@
  		cdev->handler=irq_ptr->original_int_handler;
 
 	qdio_set_state(irq_ptr,QDIO_IRQ_STATE_INACTIVE);
+
 }
 
 int
@@ -2228,13 +2270,14 @@
 qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt)
 {
 	irq_ptr->input_qs[i]->is_iqdio_q = iqfmt;
+	irq_ptr->input_qs[i]->is_thinint_q = irq_ptr->is_thinint_irq;
 
 	irq_ptr->qdr->qdf0[i].sliba=(unsigned long)(irq_ptr->input_qs[i]->slib);
 
 	irq_ptr->qdr->qdf0[i].sla=(unsigned long)(irq_ptr->input_qs[i]->sl);
 
 	irq_ptr->qdr->qdf0[i].slsba=
-			(unsigned long)(&irq_ptr->input_qs[i]->slsb.acc.val[0]);
+		(unsigned long)(&irq_ptr->input_qs[i]->slsb.acc.val[0]);
 
 	irq_ptr->qdr->qdf0[i].akey=QDIO_STORAGE_KEY;
 	irq_ptr->qdr->qdf0[i].bkey=QDIO_STORAGE_KEY;
@@ -2247,9 +2290,9 @@
 			       int j, int iqfmt)
 {
 	irq_ptr->output_qs[i]->is_iqdio_q = iqfmt;
+	irq_ptr->output_qs[i]->is_thinint_q = irq_ptr->is_thinint_irq;
 
-	irq_ptr->qdr->qdf0[i+j].sliba=
-		(unsigned long)(irq_ptr->output_qs[i]->slib);
+	irq_ptr->qdr->qdf0[i+j].sliba=(unsigned long)(irq_ptr->output_qs[i]->slib);
 
 	irq_ptr->qdr->qdf0[i+j].sla=(unsigned long)(irq_ptr->output_qs[i]->sl);
 
@@ -2279,6 +2322,13 @@
 			irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS;
 		irq_ptr->input_qs[i]->hydra_gives_outbound_pcis=
 			irq_ptr->hydra_gives_outbound_pcis;
+		irq_ptr->input_qs[i]->siga_sync_done_on_outb_tis=
+			((irq_ptr->qdioac&
+			  (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
+			   CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))==
+			 (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
+			  CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS));
+
 	}
 }
 
@@ -2298,6 +2348,13 @@
 			irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS;
 		irq_ptr->output_qs[i]->hydra_gives_outbound_pcis=
 			irq_ptr->hydra_gives_outbound_pcis;
+		irq_ptr->output_qs[i]->siga_sync_done_on_outb_tis=
+			((irq_ptr->qdioac&
+			  (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
+			   CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))==
+			 (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
+			  CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS));
+
 	}
 }
 
@@ -2414,6 +2471,7 @@
 	struct ciw *ciw;
 	int result;
 	int is_iqdio;
+	char dbf_text[15];
 
 	if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
 	     (init_data->no_output_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
@@ -2460,9 +2518,18 @@
 	irq_ptr->no_input_qs=init_data->no_input_qs;
 	irq_ptr->no_output_qs=init_data->no_output_qs;
 
-	irq_ptr->is_iqdio_irq=(init_data->q_format==QDIO_IQDIO_QFMT)?1:0;
+	if (init_data->q_format==QDIO_IQDIO_QFMT) {
+		irq_ptr->is_iqdio_irq=1;
+		irq_ptr->is_thinint_irq=1;
+	} else {
+		irq_ptr->is_iqdio_irq=0;
+		irq_ptr->is_thinint_irq=hydra_thinints;
+	}
+	sprintf(dbf_text,"is_i_t%1x%1x",
+		irq_ptr->is_iqdio_irq,irq_ptr->is_thinint_irq);
+	QDIO_DBF_TEXT2(0,setup,dbf_text);
 
-	if (irq_ptr->is_iqdio_irq) {
+	if (irq_ptr->is_thinint_irq) {
 		irq_ptr->dev_st_chg_ind=qdio_get_indicator();
 		QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*));
 		if (!irq_ptr->dev_st_chg_ind) {
@@ -2522,10 +2589,10 @@
 
 	/* fill in qib */
 	irq_ptr->qib.qfmt=init_data->q_format;
-	if (init_data->no_input_qs) irq_ptr->qib.isliba=
-				 (unsigned long)(irq_ptr->input_qs[0]->slib);
-	if (init_data->no_output_qs) irq_ptr->qib.osliba=(unsigned long)
-				  (irq_ptr->output_qs[0]->slib);
+	if (init_data->no_input_qs)
+		irq_ptr->qib.isliba=(unsigned long)(irq_ptr->input_qs[0]->slib);
+	if (init_data->no_output_qs)
+		irq_ptr->qib.osliba=(unsigned long)(irq_ptr->output_qs[0]->slib);
 	memcpy(irq_ptr->qib.ebcnam,init_data->adapter_name,8);
 
 	qdio_set_impl_params(irq_ptr,init_data->qib_param_field_format,
@@ -2567,21 +2634,16 @@
 	irq_ptr->original_int_handler = init_data->cdev->handler;
 	init_data->cdev->handler = qdio_handler;
 
-	/* the iqdio CHSC stuff */
-	if (irq_ptr->is_iqdio_irq) {
-/*		iqdio_enable_adapter_int_facility(irq_ptr);*/
-
-		if (iqdio_check_chsc_availability()) {
-			QDIO_PRINT_ERR("Not all CHSCs supported. " \
-				       "Continuing.\n");
-		}
-		result=iqdio_set_subchannel_ind(irq_ptr,0);
+	/* the thinint CHSC stuff */
+	if (irq_ptr->is_thinint_irq) {
+
+		result = tiqdio_set_subchannel_ind(irq_ptr,0);
 		if (result) {
 			up(&irq_ptr->setting_up_sema);
 			qdio_cleanup(init_data->cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
 			return result;
 		}
-		iqdio_set_delay_target(irq_ptr,IQDIO_DELAY_TARGET);
+		tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
 	}
 
 	up(&irq_ptr->setting_up_sema);
@@ -2620,7 +2682,7 @@
 
 	ccw_device_set_options(cdev, 0);
 	result=ccw_device_start_timeout(cdev,&irq_ptr->ccw,
-					QDIO_DOING_ESTABLISH,0,0,
+					QDIO_DOING_ESTABLISH,0, 0,
 					QDIO_ESTABLISH_TIMEOUT);
 	if (result) {
 		result2=ccw_device_start_timeout(cdev,&irq_ptr->ccw,
@@ -2721,14 +2783,14 @@
 		goto out;
 
 	for (i=0;i<irq_ptr->no_input_qs;i++) {
-		if (irq_ptr->is_iqdio_irq) {
+		if (irq_ptr->is_thinint_irq) {
 			/* 
 			 * that way we know, that, if we will get interrupted
-			 * by iqdio_inbound_processing, qdio_unmark_q will
+			 * by tiqdio_inbound_processing, qdio_unmark_q will
 			 * not be called 
 			 */
 			qdio_reserve_q(irq_ptr->input_qs[i]);
-			qdio_mark_iq(irq_ptr->input_qs[i]);
+			qdio_mark_tiq(irq_ptr->input_qs[i]);
 			qdio_release_q(irq_ptr->input_qs[i]);
 		}
 	}
@@ -2958,7 +3020,7 @@
 		 perf_stats.siga_ins);
 	_OUTP_IT("Number of SIGA out's issued                     : %u\n",
 		 perf_stats.siga_outs);
-	_OUTP_IT("Number of PCI's caught                          : %u\n",
+	_OUTP_IT("Number of PCIs caught                          : %u\n",
 		 perf_stats.pcis);
 	_OUTP_IT("Number of adapter interrupts caught             : %u\n",
 		 perf_stats.thinints);
@@ -3032,11 +3094,11 @@
 }
 
 static void
-iqdio_register_thinints(void)
+tiqdio_register_thinints(void)
 {
 	char dbf_text[20];
 	register_thinint_result=
-		s390_register_adapter_interrupt(&iqdio_thinint_handler);
+		s390_register_adapter_interrupt(&tiqdio_thinint_handler);
 	if (register_thinint_result) {
 		sprintf(dbf_text,"regthn%x",(register_thinint_result&0xff));
 		QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -3048,10 +3110,10 @@
 }
 
 static void
-iqdio_unregister_thinints(void)
+tiqdio_unregister_thinints(void)
 {
 	if (!register_thinint_result)
-		s390_unregister_adapter_interrupt(&iqdio_thinint_handler);
+		s390_unregister_adapter_interrupt(&tiqdio_thinint_handler);
 }
 
 static int
@@ -3191,7 +3253,11 @@
 #endif /* QDIO_PERFORMANCE_STATS */
 
 	qdio_add_procfs_entry();
-	iqdio_register_thinints();
+
+	if (tiqdio_check_chsc_availability())
+		QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n");
+
+	tiqdio_register_thinints();
 
 	return 0;
  }
@@ -3199,7 +3265,7 @@
 static void __exit
 cleanup_QDIO(void)
 {
-	iqdio_unregister_thinints();
+	tiqdio_unregister_thinints();
 	qdio_remove_procfs_entry();
 	qdio_release_qdio_memory();
 	qdio_unregister_dbf_views();
diff -urN linux-2.5.73-bk9/drivers/s390/cio/qdio.h linux-2.5.73-bk10/drivers/s390/cio/qdio.h
--- linux-2.5.73-bk9/drivers/s390/cio/qdio.h	2003-07-02 04:57:16.000000000 -0700
+++ linux-2.5.73-bk10/drivers/s390/cio/qdio.h	2003-07-02 04:57:30.000000000 -0700
@@ -1,7 +1,7 @@
 #ifndef _CIO_QDIO_H
 #define _CIO_QDIO_H
 
-#define VERSION_CIO_QDIO_H "$Revision: 1.17 $"
+#define VERSION_CIO_QDIO_H "$Revision: 1.18 $"
 
 //#define QDIO_DBF_LIKE_HELL
 
@@ -31,8 +31,8 @@
  */
 #define IQDIO_FILL_LEVEL_TO_POLL 4
 
-#define IQDIO_THININT_ISC 3
-#define IQDIO_DELAY_TARGET 0
+#define TIQDIO_THININT_ISC 3
+#define TIQDIO_DELAY_TARGET 0
 #define QDIO_BUSY_BIT_PATIENCE 2000 /* in microsecs */
 #define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */
 #define IQDIO_GLOBAL_LAPS_INT 1 /* don't global summary */
@@ -473,7 +473,13 @@
 
 #define atomic_swap(a,b) xchg((int*)a.counter,b)
 
-#define SYNC_MEMORY if (q->siga_sync) qdio_siga_sync(q)
+/* unlikely as the later the better */
+#define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q)
+#define SYNC_MEMORY_ALL if (unlikely(q->siga_sync)) \
+	qdio_siga_sync(q,~0U,~0U)
+#define SYNC_MEMORY_ALL_OUTB if (unlikely(q->siga_sync)) \
+	qdio_siga_sync(q,~0U,0)
+
 #define NOW qdio_get_micros()
 #define SAVE_TIMESTAMP(q) q->timing.last_transfer_time=NOW
 #define GET_SAVED_TIMESTAMP(q) (q->timing.last_transfer_time)
@@ -519,6 +525,7 @@
 	struct ccw_device *cdev;
 
 	unsigned int is_iqdio_q;
+	unsigned int is_thinint_q;
 
 	/* bit 0 means queue 0, bit 1 means queue 1, ... */
 	unsigned int mask;
@@ -540,6 +547,7 @@
 	unsigned int siga_out;
 	unsigned int siga_sync;
 	unsigned int siga_sync_done_on_thinints;
+	unsigned int siga_sync_done_on_outb_tis;
 	unsigned int hydra_gives_outbound_pcis;
 
 	/* used to save beginning position when calling dd_handlers */
@@ -548,6 +556,8 @@
 	atomic_t use_count;
 	atomic_t is_in_shutdown;
 
+	void *irq_ptr;
+
 #ifdef QDIO_USE_TIMERS_FOR_POLLING
 	struct timer_list timer;
 	atomic_t timer_already_set;
@@ -604,6 +614,7 @@
 	int irq;
 
 	unsigned int is_iqdio_irq;
+	unsigned int is_thinint_irq;
 	unsigned int hydra_gives_outbound_pcis;
 	unsigned int sync_done_on_outb_pcis;
 
diff -urN linux-2.5.73-bk9/drivers/s390/cio/requestirq.c linux-2.5.73-bk10/drivers/s390/cio/requestirq.c
--- linux-2.5.73-bk9/drivers/s390/cio/requestirq.c	2003-06-22 11:33:00.000000000 -0700
+++ linux-2.5.73-bk10/drivers/s390/cio/requestirq.c	2003-07-02 04:57:30.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/requestirq.c
  *   S/390 common I/O routines -- enabling and disabling of devices
- *   $Revision: 1.44 $
+ *   $Revision: 1.45 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -45,11 +45,15 @@
 	/*
 	 * Let's build our path group ID here.
 	 */
+	if (MACHINE_NEW_STIDP)
+		global_pgid.cpu_addr = 0x8000;
+	else {
 #ifdef CONFIG_SMP
-	global_pgid.cpu_addr = hard_smp_processor_id();
+		global_pgid.cpu_addr = hard_smp_processor_id();
 #else
-	global_pgid.cpu_addr = 0;
+		global_pgid.cpu_addr = 0;
 #endif
+	}
 	global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
 	global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
 	global_pgid.tod_high = (__u32) (get_clock() >> 32);
diff -urN linux-2.5.73-bk9/drivers/s390/net/Kconfig linux-2.5.73-bk10/drivers/s390/net/Kconfig
--- linux-2.5.73-bk9/drivers/s390/net/Kconfig	2003-06-22 11:33:16.000000000 -0700
+++ linux-2.5.73-bk10/drivers/s390/net/Kconfig	2003-07-02 04:57:30.000000000 -0700
@@ -30,9 +30,56 @@
 	  vehicle networking under VM or VIF.  This option is also available
 	  as a module which will be called iucv.ko. If unsure, say "Y".
 
+
+config QETH
+	tristate "Gigabit Ethernet device support"
+	depends on NETDEVICES && IP_MULTICAST && QDIO
+	help
+	  This driver supports the IBM S/390 and zSeries OSA Express adapters
+	  in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN
+	  interfaces in QDIO and HIPER mode.
+	
+	  For details please refer to the documentation provided by IBM at   
+	  <http://www10.software.ibm.com/developerworks/opensource/linux390>
+
+	  This driver is also available as a module (code which can be
+	  inserted in and removed from the running kernel whenever you
+	  want). If you want to compile it as a module, say 'M' here and
+	  read file Documentation/modules.txt.
+
+
+comment "Gigabit Ethernet default settings"
+	depends on QETH
+
+# FIXME IPV6=m && QETH=y
+config QETH_IPV6
+	bool "IPv6 support for gigabit ethernet"
+	depends on QETH && IPV6
+	help
+	  If CONFIG_QETH is switched on, this option will include IPv6
+	  support in the qeth device driver.
+
+# FIXME VLAN_8021Q=m && QETH=y
+config QETH_VLAN
+	bool "VLAN support for gigabit ethernet"
+	depends on QETH && VLAN_8021Q
+	help
+	  If CONFIG_QETH is switched on, this option will include IEEE
+	  802.1q VLAN support in the qeth device driver.
+
+config QETH_PERF_STATS
+	bool "Performance statistics in /proc"
+	depends on QETH
+	help
+	  When switched on, this option will add a file in the proc-fs
+	  (/proc/qeth_perf_stats) containing performance statistics. It
+	  may slightly impact performance, so this is only recommended for
+	  internal tuning of the device driver.
+
 config CCWGROUP
  	tristate
- 	depends on LCS || CTC
-	default m if LCS!=y && CTC!=y
-	default y if LCS=y || CTC=y
+ 	depends on LCS || CTC  || QETH
+	default m if LCS!=y && CTC!=y && QETH!=y
+	default y if LCS=y || CTC=y || QETH=y
+
 endmenu
diff -urN linux-2.5.73-bk9/drivers/s390/net/Makefile linux-2.5.73-bk10/drivers/s390/net/Makefile
--- linux-2.5.73-bk9/drivers/s390/net/Makefile	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk10/drivers/s390/net/Makefile	2003-07-02 04:57:30.000000000 -0700
@@ -8,3 +8,6 @@
 obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
 obj-$(CONFIG_IUCV) += netiucv.o
 obj-$(CONFIG_LCS) += lcs.o cu3088.o
+qeth_mod-objs := qeth.o qeth_mpc.o
+obj-$(CONFIG_QETH) += qeth_mod.o
+
diff -urN linux-2.5.73-bk9/drivers/s390/net/qeth.c linux-2.5.73-bk10/drivers/s390/net/qeth.c
--- linux-2.5.73-bk9/drivers/s390/net/qeth.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/drivers/s390/net/qeth.c	2003-07-02 04:57:30.000000000 -0700
@@ -0,0 +1,11182 @@
+/*
+ *
+ * linux/drivers/s390/net/qeth.c ($Revision: 1.118 $)
+ *
+ * Linux on zSeries OSA Express and HiperSockets support
+ *
+ * Copyright 2000,2003 IBM Corporation
+ *
+ * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
+ *            Cornelia Huck <cohuck@de.ibm.com> (2.5 integration,
+ *                                               numerous bugfixes)
+ *            Frank Pavlic <pavlic@de.ibm.com>  (query/purge ARP, SNMP, fixes)
+ *            Andreas Herrmann <aherrman@de.ibm.com> (bugfixes)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * The driver supports in general all QDIO driven network devices on the
+ * Hydra card.
+ *
+ * For all devices, three channels must be available to the driver. One
+ * channel is the read channel, one is the write channel and the third
+ * one is the channel used to control QDIO.
+ *
+ * There are several stages from the channel recognition to the running
+ * network device:
+ * - The channels are scanned and ordered due to the parameters (see
+ *   MODULE_PARM_DESC)
+ * - The card is hardsetup: this means, that the communication channels
+ *   are prepared
+ * - The card is softsetup: this means, that commands are issued
+ *   to activate the network parameters
+ * - After that, data can flow through the card (transported by QDIO)
+ *
+ *IPA Takeover:
+ * /proc/qeth_ipa_takeover provides the possibility to add and remove
+ * certain ranges of IP addresses to the driver. As soon as these
+ * addresses have to be set by the driver, the driver uses the OSA
+ * Address Takeover mechanism.
+ * reading out of the proc-file displays the registered addresses;
+ * writing into it changes the information. Only one command at one
+ * time must be written into the file. Subsequent commands are ignored.
+ * The following commands are available:
+ * inv4
+ * inv6
+ * add4 <ADDR>/<mask bits>[:<interface>]
+ * add6 <ADDR>/<mask bits>[:<interface>]
+ * del4 <ADDR>/<mask bits>[:<interface>]
+ * del6 <ADDR>/<mask bits>[:<interface>]
+ * inv4 and inv6 toggle the IPA takeover behaviour for all interfaces:
+ * when inv4 was input once, all addresses specified with add4 are not
+ * set using the takeover mechanism, but all other IPv4 addresses are set so.
+ *
+ * add# adds an address range, del# deletes an address range. # corresponds
+ * to the IP version (4 or 6).
+ * <ADDR> is a 8 or 32byte hexadecimal view of the IP address.
+ * <mask bits> specifies the number of bits which are set in the network mask.
+ * <interface> is optional and specifies the interface name to which the
+ * address range is bound.
+ * E. g.
+ *   add4 C0a80100/24
+ * activates all addresses in the 192.168.10 subnet for address takeover.
+ * Note, that the address is not taken over before an according ifconfig
+ * is executed.
+ *
+ *VIPA:
+ * add_vipa4 <ADDR>:<interface>
+ * add_vipa6 <ADDR>:<interface>
+ * del_vipa4 <ADDR>:<interface>
+ * del_vipa6 <ADDR>:<interface>
+ *
+ * the specified address is set/unset as VIPA on the specified interface.
+ * use the src_vipa package to exploit this out of arbitrary applications.
+ *
+ *Proxy ARP:
+ *
+ * add_rxip4 <ADDR>:<interface>
+ * add_rxip6 <ADDR>:<interface>
+ * del_rxip4 <ADDR>:<interface>
+ * del_rxip6 <ADDR>:<interface>
+ *
+ * the specified address is set/unset as "do not fail a gratuitous ARP"
+ * on the specified interface. this can be used to act as a proxy ARP.
+ */
+
+static void volatile
+qeth_eyecatcher(void)
+{
+	return;
+}
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+
+#include <linux/version.h>
+
+#include <asm/io.h>
+#include <asm/ebcdic.h>
+#include <linux/ctype.h>
+#include <asm/semaphore.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/ip.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/tcp.h>
+#include <linux/icmp.h>
+#include <linux/skbuff.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif /* CONFIG_PROC_FS */
+#include <net/route.h>
+#include <net/arp.h>
+#include <linux/in.h>
+#include <linux/igmp.h>
+#include <net/ip.h>
+#include <asm/uaccess.h>
+#include <linux/init.h>
+#include <net/ipv6.h>
+#include <linux/in6.h>
+#include <net/if_inet6.h>
+#include <net/addrconf.h>
+#include <linux/if_tr.h>
+#include <linux/trdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/reboot.h>
+
+#include <linux/if_vlan.h>
+
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
+#include <asm/debug.h>
+
+#include "qeth_mpc.h"
+#include "qeth.h"
+
+/****************** MODULE PARAMETER VARIABLES ********************/
+static int qeth_sparebufs = 0;
+MODULE_PARM(qeth_sparebufs, "i");
+MODULE_PARM_DESC(qeth_sparebufs, "the number of pre-allocated spare buffers "
+		 "reserved for low memory situations");
+
+/****************** MODULE STUFF **********************************/
+#define VERSION_QETH_C "$Revision: 1.118 $"
+static const char *version = "qeth S/390 OSA-Express driver ("
+    VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H
+    QETH_VERSION_IPV6 QETH_VERSION_VLAN ")";
+
+MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
+MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
+		   "Copyright 2000,2003 IBM Corporation\n");
+MODULE_LICENSE("GPL");
+
+/******************** HERE WE GO ***********************************/
+
+#define PROCFILE_SLEEP_SEM_MAX_VALUE 0
+#define PROCFILE_IOCTL_SEM_MAX_VALUE 3
+static struct semaphore qeth_procfile_ioctl_lock;
+static struct semaphore qeth_procfile_ioctl_sem;
+static struct qeth_card *firstcard = NULL;
+
+static struct sparebufs sparebufs[MAX_SPARE_BUFFERS];
+static int sparebuffer_count;
+
+static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
+
+static spinlock_t setup_lock = SPIN_LOCK_UNLOCKED;
+static rwlock_t list_lock = RW_LOCK_UNLOCKED;
+
+static debug_info_t *qeth_dbf_setup = NULL;
+static debug_info_t *qeth_dbf_data = NULL;
+static debug_info_t *qeth_dbf_misc = NULL;
+static debug_info_t *qeth_dbf_control = NULL;
+static debug_info_t *qeth_dbf_trace = NULL;
+static debug_info_t *qeth_dbf_sense = NULL;
+static debug_info_t *qeth_dbf_qerr = NULL;
+
+static int proc_file_registration;
+#ifdef QETH_PERFORMANCE_STATS
+static int proc_perf_file_registration;
+#define NOW qeth_get_micros()
+#endif /* QETH_PERFORMANCE_STATS */
+static int proc_ipato_file_registration;
+
+static int ipato_inv4 = 0, ipato_inv6 = 0;
+static struct ipato_entry *ipato_entries = NULL;
+static spinlock_t ipato_list_lock = SPIN_LOCK_UNLOCKED;
+
+struct tempinfo{
+	char *data;
+	int len;
+};
+
+/* thought I could get along without forward declarations...
+ * just lazyness here */
+static int qeth_reinit_thread(void *);
+static void qeth_schedule_recovery(struct qeth_card *card);
+
+inline static int
+QETH_IP_VERSION(struct sk_buff *skb)
+{
+	switch (skb->protocol) {
+	case ETH_P_IPV6:
+		return 6;
+	case ETH_P_IP:
+		return 4;
+	default:
+		return 0;
+	}
+}
+
+/* not a macro, as one of the arguments is atomic_read */
+static inline int
+qeth_min(int a, int b)
+{
+	if (a < b)
+		return a;
+	else
+		return b;
+}
+
+static inline unsigned int
+qeth_get_millis(void)
+{
+	__u64 time;
+
+	asm volatile ("STCK %0":"=m" (time));
+	return (int) (time >> 22);   /* time>>12 is microseconds, we divide it
+					by 1024 */
+}
+
+#ifdef QETH_PERFORMANCE_STATS
+static inline unsigned int
+qeth_get_micros(void)
+{
+	__u64 time;
+
+	asm volatile ("STCK %0":"=m" (time));
+	return (int) (time >> 12);
+}
+#endif /* QETH_PERFORMANCE_STATS */
+
+static void
+qeth_delay_millis(unsigned long msecs)
+{
+	unsigned int start;
+
+	start = qeth_get_millis();
+	while (qeth_get_millis() - start < msecs) ;
+}
+
+static void
+qeth_wait_nonbusy(unsigned int timeout)
+{
+	unsigned int start;
+	char dbf_text[15];
+
+	sprintf(dbf_text, "wtnb%4x", timeout);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+
+	start = qeth_get_millis();
+	for (;;) {
+		set_task_state(current, TASK_INTERRUPTIBLE);
+		if (qeth_get_millis() - start > timeout) {
+			goto out;
+		}
+		schedule_timeout(((start + timeout -
+				   qeth_get_millis()) >> 10) * HZ);
+	}
+out:
+	set_task_state(current, TASK_RUNNING);
+}
+
+static void
+qeth_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev)
+{
+	if (dev->type == ARPHRD_IEEE802_TR)
+		ip_tr_mc_map(ipm, mac);
+	else
+		ip_eth_mc_map(ipm, mac);
+}
+
+#define atomic_swap(a,b) xchg((int*)a.counter,b)
+
+static int inline
+my_spin_lock_nonbusy(struct qeth_card *card, spinlock_t * lock)
+{
+	for (;;) {
+		if (card) {
+			if (atomic_read(&card->shutdown_phase))
+				return -1;
+		}
+		if (spin_trylock(lock))
+			return 0;
+		qeth_wait_nonbusy(QETH_IDLE_WAIT_TIME);
+	}
+}
+
+#ifdef CONFIG_ARCH_S390X
+#define QETH_GET_ADDR(x) ((__u32)(unsigned long)x)
+#else /* CONFIG_ARCH_S390X */
+#define QETH_GET_ADDR(x) ((__u32)x)
+#endif /* CONFIG_ARCH_S390X */
+
+static int
+qeth_does_card_exist(struct qeth_card *card)
+{
+	struct qeth_card *c = firstcard;
+	int rc = 0;
+
+	read_lock(&list_lock);
+	while (c) {
+		if (c == card) {
+			rc = 1;
+			break;
+		}
+		c = c->next;
+	}
+	read_unlock(&list_lock);
+	return rc;
+}
+
+static int
+qeth_getxdigit(char c)
+{
+	if ((c >= '0') && (c <= '9'))
+		return c - '0';
+	if ((c >= 'a') && (c <= 'f'))
+		return c + 10 - 'a';
+	if ((c >= 'A') && (c <= 'F'))
+		return c + 10 - 'A';
+	return -1;
+}
+
+static struct qeth_card *
+qeth_get_card_by_name(char *name)
+{
+	struct qeth_card *card;
+
+	read_lock(&list_lock);
+	card = firstcard;
+	while (card) {
+		if (!strncmp(name, card->dev_name, DEV_NAME_LEN))
+			break;
+		card = card->next;
+	}
+	read_unlock(&list_lock);
+
+	return card;
+}
+
+static void
+qeth_convert_addr_to_text(int version, __u8 * addr, char *text)
+{
+	if (version == 4) {
+		sprintf(text, "%02x%02x%02x%02x",
+			addr[0], addr[1], addr[2], addr[3]);
+	} else {
+		sprintf(text, "%02x%02x%02x%02x%02x%02x%02x%02x"
+			"%02x%02x%02x%02x%02x%02x%02x%02x",
+			addr[0], addr[1], addr[2], addr[3],
+			addr[4], addr[5], addr[6], addr[7],
+			addr[8], addr[9], addr[10], addr[11],
+			addr[12], addr[13], addr[14], addr[15]);
+	}
+}
+
+static int
+qeth_convert_text_to_addr(int version, char *text, __u8 * addr)
+{
+	int olen = (version == 4) ? 4 : 16;
+
+	while (olen--) {
+		if ((!isxdigit(*text)) || (!isxdigit(*(text + 1))))
+			return -EINVAL;
+		*addr =
+		    (qeth_getxdigit(*text) << 4) + qeth_getxdigit(*(text + 1));
+		addr++;
+		text += 2;
+	}
+	return 0;
+}
+
+static void
+qeth_add_ipato_entry(int version, __u8 * addr, int mask_bits, char *dev_name)
+{
+	struct ipato_entry *entry, *e;
+	int len = (version == 4) ? 4 : 16;
+
+	entry =
+	    (struct ipato_entry *) kmalloc(sizeof (struct ipato_entry),
+					   GFP_KERNEL);
+	if (!entry) {
+		PRINT_ERR("not enough memory for ipato allocation\n");
+		return;
+	}
+	entry->version = version;
+	memcpy(entry->addr, addr, len);
+	if (dev_name) {
+		strncpy(entry->dev_name, dev_name, DEV_NAME_LEN);
+		if (qeth_get_card_by_name(dev_name)->options.ena_ipat !=
+		    ENABLE_TAKEOVER)
+			PRINT_WARN("IP takeover is not enabled on %s! "
+				   "Ignoring line\n", dev_name);
+	} else
+		memset(entry->dev_name, 0, DEV_NAME_LEN);
+	entry->mask_bits = mask_bits;
+	entry->next = NULL;
+
+	spin_lock(&ipato_list_lock);
+	if (ipato_entries) {
+		e = ipato_entries;
+		while (e) {
+			if ((e->version == version) &&
+			    (e->mask_bits == mask_bits) &&
+			    (((dev_name) && !strncmp(e->dev_name, dev_name,
+						     DEV_NAME_LEN)) ||
+			     (!dev_name)) && (!memcmp(e->addr, addr, len))) {
+				PRINT_INFO("ipato to be added does already "
+					   "exist\n");
+				kfree(entry);
+				goto out;
+			}
+			if (e->next)
+				e = e->next;
+			else
+				break;
+		}
+		e->next = entry;
+	} else
+		ipato_entries = entry;
+      out:
+	spin_unlock(&ipato_list_lock);
+}
+
+static void
+qeth_del_ipato_entry(int version, __u8 * addr, int mask_bits, char *dev_name)
+{
+	struct ipato_entry *e, *e_before;
+	int len = (version == 4) ? 4 : 16;
+	int found = 0;
+
+	spin_lock(&ipato_list_lock);
+	e = ipato_entries;
+	if ((e->version == version) &&
+	    (e->mask_bits == mask_bits) && (!memcmp(e->addr, addr, len))) {
+		ipato_entries = e->next;
+		kfree(e);
+	} else
+		while (e) {
+			e_before = e;
+			e = e->next;
+			if (!e)
+				break;
+			if ((e->version == version) &&
+			    (e->mask_bits == mask_bits) &&
+			    (((dev_name) && !strncmp(e->dev_name, dev_name,
+						     DEV_NAME_LEN)) ||
+			     (!dev_name)) && (!memcmp(e->addr, addr, len))) {
+				e_before->next = e->next;
+				kfree(e);
+				found = 1;
+				break;
+			}
+		}
+	if (!found)
+		PRINT_INFO("ipato to be deleted does not exist\n");
+	spin_unlock(&ipato_list_lock);
+}
+
+static void
+qeth_convert_addr_to_bits(__u8 * addr, char *bits, int len)
+{
+	int i, j;
+	__u8 octet;
+
+	for (i = 0; i < len; i++) {
+		octet = addr[i];
+		for (j = 7; j >= 0; j--) {
+			bits[i * 8 + j] = (octet & 1) ? 1 : 0;
+			octet >>= 1;
+		}
+	}
+}
+
+static int
+qeth_is_ipa_covered_by_ipato_entries(int version, __u8 * addr,
+				     struct qeth_card *card)
+{
+	char *memarea, *addr_bits, *entry_bits;
+	int len = (version == 4) ? 4 : 16;
+	int invert = (version == 4) ? ipato_inv4 : ipato_inv6;
+	int result = 0;
+	struct ipato_entry *e;
+
+	if (card->options.ena_ipat != ENABLE_TAKEOVER) {
+		return 0;
+	}
+
+	memarea = kmalloc(256, GFP_KERNEL);
+	if (!memarea) {
+		PRINT_ERR("not enough memory to check out whether to "
+			  "use ipato\n");
+		return 0;
+	}
+	addr_bits = memarea;
+	entry_bits = memarea + 128;
+	qeth_convert_addr_to_bits(addr, addr_bits, len);
+	e = ipato_entries;
+	while (e) {
+		qeth_convert_addr_to_bits(e->addr, entry_bits, len);
+		if ((!memcmp(addr_bits, entry_bits,
+			     __min(len * 8, e->mask_bits))) &&
+		    ((e->dev_name[0] &&
+		      (!strncmp(e->dev_name, card->dev_name, DEV_NAME_LEN))) ||
+		     (!e->dev_name[0]))) {
+			result = 1;
+			break;
+		}
+		e = e->next;
+	}
+
+	kfree(memarea);
+	if (invert)
+		return !result;
+	else
+		return result;
+}
+
+static void
+qeth_set_dev_flag_running(struct qeth_card *card)
+{
+	if (card) {
+		card->dev->flags |= IFF_RUNNING;
+	}
+}
+
+static void
+qeth_set_dev_flag_norunning(struct qeth_card *card)
+{
+	if (card) {
+		card->dev->flags &= ~IFF_RUNNING;
+	}
+}
+
+static void
+qeth_restore_dev_flag_state(struct qeth_card *card)
+{
+	if (card) {
+		if (card->saved_dev_flags & IFF_RUNNING)
+			card->dev->flags |= IFF_RUNNING;
+		else
+			card->dev->flags &= ~IFF_RUNNING;
+	}
+}
+
+static void
+qeth_save_dev_flag_state(struct qeth_card *card)
+{
+	if (card) {
+		card->saved_dev_flags = card->dev->flags & IFF_RUNNING;
+	}
+}
+
+static int
+qeth_open(struct net_device *dev)
+{
+	struct qeth_card *card;
+
+	card = (struct qeth_card *) dev->priv;
+	QETH_DBF_TEXT2(0, trace, "open");
+	QETH_DBF_TEXT2(0, setup, "open");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id);
+
+	qeth_save_dev_flag_state(card);
+
+	netif_start_queue(dev);
+	atomic_set(&((struct qeth_card *) dev->priv)->is_open, 1);
+
+	return 0;
+}
+
+static int
+qeth_set_config(struct net_device *dev, struct ifmap *map)
+{
+	QETH_DBF_TEXT3(0, trace, "nscf");
+	QETH_DBF_TEXT3(0, trace,
+		       ((struct qeth_card *)dev->priv)->rdev->dev.bus_id);
+
+	return -EOPNOTSUPP;
+}
+
+static int
+qeth_is_multicast_skb_at_all(struct sk_buff *skb, int version)
+{
+	int i;
+	if (skb->dst && skb->dst->neighbour) {
+		i = skb->dst->neighbour->type;
+		return ((i == RTN_BROADCAST) ||
+			(i == RTN_MULTICAST) || (i == RTN_ANYCAST)) ? i : 0;
+	}
+	/* ok, we've to try it somehow else */
+	if (version == 4) {
+		return ((skb->nh.raw[16] & 0xf0) == 0xe0) ? RTN_MULTICAST : 0;
+	} else if (version == 6) {
+		return (skb->nh.raw[24] == 0xff) ? RTN_MULTICAST : 0;
+	} else {
+		PRINT_STUPID("QETH_IP_VERSION is %x\n", version);
+		PRINT_STUPID("skb->protocol=x%x=%i\n",
+			     skb->protocol, skb->protocol);
+		HEXDUMP16(STUPID, "skb:", skb->data);
+	}
+	return 0;
+}
+
+static int
+qeth_get_prioqueue(struct qeth_card *card, struct sk_buff *skb,
+		   int multicast, int version)
+{
+	if (!version)
+		return QETH_DEFAULT_QUEUE;
+	switch (card->no_queues) {
+	case 1:
+		return 0;
+	case 4:
+		if ((card->can_do_async_iqd) &&
+		    (card->options.async_iqd == ASYNC_IQD)) {
+			return card->no_queues - 1;
+		}
+		if (card->is_multicast_different) {
+			if (multicast) {
+				return card->is_multicast_different &
+				    (card->no_queues - 1);
+			} else {
+				return 0;
+			}
+		}
+		if (card->options.do_prio_queueing) {
+			if (version == 4) {
+				if (card->options.do_prio_queueing ==
+				    PRIO_QUEUEING_TOS) {
+					if (skb->nh.iph->tos &
+					    IP_TOS_NOTIMPORTANT) {
+						return 3;
+					}
+					if (skb->nh.iph->tos & IP_TOS_LOWDELAY) {
+						return 0;
+					}
+					if (skb->nh.iph->tos &
+					    IP_TOS_HIGHTHROUGHPUT) {
+						return 1;
+					}
+					if (skb->nh.iph->tos &
+					    IP_TOS_HIGHRELIABILITY) {
+						return 2;
+					}
+					return QETH_DEFAULT_QUEUE;
+				}
+				if (card->options.do_prio_queueing ==
+				    PRIO_QUEUEING_PREC) {
+					return 3 - (skb->nh.iph->tos >> 6);
+				}
+			} else if (version == 6) {
+				/********************
+				 ********************
+				 *TODO: IPv6!!!
+				 ********************/
+			}
+			return card->options.default_queue;
+		} else
+			return card->options.default_queue;
+	default:
+		return 0;
+	}
+}
+
+static void
+qeth_wakeup(struct qeth_card *card)
+{
+	QETH_DBF_TEXT5(0, trace, "wkup");
+	QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+
+	atomic_set(&card->data_has_arrived, 1);
+	spin_lock(&card->wait_q_lock);
+	if (atomic_read(&card->wait_q_active)) {
+		wake_up(&card->wait_q);
+	}
+	spin_unlock(&card->wait_q_lock);
+}
+
+static int
+qeth_check_idx_response(unsigned char *buffer)
+{
+	if (!buffer)
+		return 0;
+	if ((buffer[2] & 0xc0) == 0xc0) {
+		return -EIO;
+	}
+	return 0;
+}
+
+static int
+qeth_get_cards_problem(struct ccw_device *cdev, unsigned char *buffer,
+		       int dstat, int cstat, int rqparam,
+		       char *irb, char *sense)
+{
+	char dbf_text[15];
+	int problem = 0;
+	struct qeth_card *card;
+
+	card = cdev->dev.driver_data;
+
+	if (atomic_read(&card->shutdown_phase))
+		return 0;
+	if (dstat & DEV_STAT_UNIT_CHECK) {
+		if (sense[SENSE_RESETTING_EVENT_BYTE] &
+		    SENSE_RESETTING_EVENT_FLAG) {
+			QETH_DBF_TEXT1(0, trace, "REVN");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			problem = PROBLEM_RESETTING_EVENT_INDICATOR;
+			goto out;
+		}
+		if (sense[SENSE_COMMAND_REJECT_BYTE] &
+		    SENSE_COMMAND_REJECT_FLAG) {
+			QETH_DBF_TEXT1(0, trace, "CREJ");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			problem = PROBLEM_COMMAND_REJECT;
+			goto out;
+		}
+		if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) {
+			QETH_DBF_TEXT1(0, trace, "AFFE");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			problem = PROBLEM_AFFE;
+			goto out;
+		}
+		if ((!sense[0]) && (!sense[1]) && (!sense[2]) && (!sense[3])) {
+			QETH_DBF_TEXT1(0, trace, "ZSNS");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			problem = PROBLEM_ZERO_SENSE_DATA;
+			goto out;
+		}
+		QETH_DBF_TEXT1(0, trace, "GCHK");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		problem = PROBLEM_GENERAL_CHECK;
+		goto out;
+	}
+	if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
+		     SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
+		     SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
+		QETH_DBF_TEXT1(0, trace, "GCHK");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		QETH_DBF_HEX1(0, misc, irb, __max(QETH_DBF_MISC_LEN, 64));
+		PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x, "
+			   "rqparam=x%x\n",
+			   cdev->dev.bus_id, dstat, cstat, rqparam);
+		HEXDUMP16(WARN, "irb: ", irb);
+		HEXDUMP16(WARN, "irb: ", ((char *) irb) + 32);
+		problem = PROBLEM_GENERAL_CHECK;
+		goto out;
+	}
+	if (qeth_check_idx_response(buffer)) {
+		PRINT_WARN("received an IDX TERMINATE on device %s "
+			   "with cause code 0x%02x%s\n",
+			   card->rdev->dev.bus_id, buffer[4],
+			   (buffer[4] ==
+			    0x22) ? " -- try another portname" : "");
+		QETH_DBF_TEXT1(0, trace, "RTRM");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		problem = PROBLEM_RECEIVED_IDX_TERMINATE;
+		goto out;
+	}
+	if (IS_IPA(buffer) && !IS_IPA_REPLY(buffer)) {
+		if (*(PDU_ENCAPSULATION(buffer)) == IPA_CMD_STOPLAN) {
+			atomic_set(&card->is_startlaned, 0);
+			/* we don't do a  netif_stop_queue(card->dev);
+			   we better discard all packets --
+			   the outage could take longer */
+			PRINT_WARN("Link failure on %s (CHPID 0x%X) -- "
+				   "there is a network problem or someone "
+				   "pulled the cable or disabled the port."
+				   "Discarding outgoing packets.\n",
+				   card->dev_name, card->chpid);
+			QETH_DBF_TEXT1(0, trace, "CBOT");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			qeth_set_dev_flag_norunning(card);
+			problem = 0;
+			goto out;
+		}
+		if (*(PDU_ENCAPSULATION(buffer)) == IPA_CMD_STARTLAN) {
+			if (!atomic_read(&card->is_startlaned)) {
+				atomic_set(&card->is_startlaned, 1);
+				problem = PROBLEM_CARD_HAS_STARTLANED;
+			}
+			goto out;
+		}
+		if (*(PDU_ENCAPSULATION(buffer)) == IPA_CMD_REGISTER_LOCAL_ADDR) {
+			QETH_DBF_TEXT3(0, trace, "irla");
+			QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+		}
+		if (*(PDU_ENCAPSULATION(buffer)) ==
+		    IPA_CMD_UNREGISTER_LOCAL_ADDR) {
+			QETH_DBF_TEXT3(0, trace, "irla");
+			QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+		}
+		PRINT_WARN("probably a problem on %s: received data is IPA, "
+			   "but not a reply: command=0x%x\n", card->dev_name,
+			   *(PDU_ENCAPSULATION(buffer) + 1));
+		QETH_DBF_TEXT1(0, trace, "INRP");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		goto out;
+	}
+	/* no probs */
+out:
+	if (problem) {
+		QETH_DBF_TEXT3(0, trace, "gcpr");
+		QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%2x%2x%4x", dstat, cstat, problem);
+		QETH_DBF_TEXT3(0, trace, dbf_text);
+		sprintf(dbf_text, "%8x", rqparam);
+		QETH_DBF_TEXT3(0, trace, dbf_text);
+		if (buffer)
+			QETH_DBF_HEX3(0, trace, &buffer, sizeof (void *));
+		QETH_DBF_HEX3(0, trace, &irb, sizeof (void *));
+		QETH_DBF_HEX3(0, trace, &sense, sizeof (void *));
+	}
+	atomic_set(&card->problem, problem);
+	return problem;
+}
+
+static void
+qeth_issue_next_read(struct qeth_card *card)
+{
+	int result, result2;
+	char dbf_text[15];
+
+	QETH_DBF_TEXT5(0, trace, "isnr");
+	QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+
+	/* set up next read ccw */
+	memcpy(&card->dma_stuff->read_ccw, READ_CCW, sizeof (struct ccw1));
+	card->dma_stuff->read_ccw.count = QETH_BUFSIZE;
+	/* recbuf is not yet used by read channel program */
+	card->dma_stuff->read_ccw.cda = QETH_GET_ADDR(card->dma_stuff->recbuf);
+
+	/* 
+	 * we don't spin_lock_irqsave(get_ccwdev_lock(card->rdev),flags), as
+	 * we are only called in the interrupt handler
+	 */
+	result = ccw_device_start(card->rdev, &card->dma_stuff->read_ccw,
+				  MPC_SETUP_STATE, 0, 0);
+	if (result) {
+		qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO);
+		result2 =
+		    ccw_device_start(card->rdev, &card->dma_stuff->read_ccw,
+				     MPC_SETUP_STATE, 0, 0);
+		PRINT_WARN("read handler on device %s, read: ccw_device_start "
+			   "returned %i, next try returns %i\n",
+			   card->rdev->dev.bus_id, result, result2);
+		QETH_DBF_TEXT1(0, trace, "IsNR");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%04x%04x", (__s16) result, (__s16) result2);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+	}
+}
+
+static int
+qeth_is_to_recover(struct qeth_card *card, int problem)
+{
+	switch (problem) {
+	case PROBLEM_CARD_HAS_STARTLANED:
+		return 1;
+	case PROBLEM_RECEIVED_IDX_TERMINATE:
+		if (atomic_read(&card->in_recovery)) {
+			return 1;
+		} else {
+			qeth_set_dev_flag_norunning(card);
+			return 0;
+		}
+	case PROBLEM_ACTIVATE_CHECK_CONDITION:
+		return 1;
+	case PROBLEM_RESETTING_EVENT_INDICATOR:
+		return 1;
+	case PROBLEM_COMMAND_REJECT:
+		return 0;
+	case PROBLEM_ZERO_SENSE_DATA:
+		return 0;
+	case PROBLEM_GENERAL_CHECK:
+		return 1;
+	case PROBLEM_BAD_SIGA_RESULT:
+		return 1;
+	case PROBLEM_USER_TRIGGERED_RECOVERY:
+		return 1;
+	case PROBLEM_AFFE:
+		return 1;
+	case PROBLEM_MACHINE_CHECK:
+		return 1;
+	case PROBLEM_TX_TIMEOUT:
+		return 1;
+	}
+	return 0;
+}
+
+static int
+qeth_get_spare_buf(void)
+{
+	int i = 0;
+	char dbf_text[15];
+
+	while (i < sparebuffer_count) {
+		if (!atomic_compare_and_swap(SPAREBUF_FREE, SPAREBUF_USED,
+					     &sparebufs[i].status)) {
+			sprintf(dbf_text, "gtspb%3x", i);
+			QETH_DBF_TEXT4(0, trace, dbf_text);
+			return i;
+		}
+		i++;
+	}
+	QETH_DBF_TEXT3(0, trace, "nospbuf");
+
+	return -1;
+}
+
+static void
+qeth_put_spare_buf(int no)
+{
+	char dbf_text[15];
+
+	sprintf(dbf_text, "ptspb%3x", no);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+	atomic_set(&sparebufs[no].status, SPAREBUF_FREE);
+}
+
+static inline void
+qeth_put_buffer_pool_entry(struct qeth_card *card, int entry_no)
+{
+	if (entry_no & SPAREBUF_MASK)
+		qeth_put_spare_buf(entry_no & (~SPAREBUF_MASK));
+	else
+		card->inbound_buffer_pool_entry_used[entry_no] = BUFFER_UNUSED;
+}
+
+static inline int
+qeth_get_empty_buffer_pool_entry(struct qeth_card *card)
+{
+	int i;
+	int max_buffers = card->options.inbound_buffer_count;
+
+	for (i = 0; i < max_buffers; i++) {
+		if (xchg((int *) &card->inbound_buffer_pool_entry_used[i],
+			 BUFFER_USED) == BUFFER_UNUSED)
+			return i;
+	}
+	return -1;
+}
+
+static inline void
+qeth_clear_input_buffer(struct qeth_card *card, int bufno)
+{
+	struct qdio_buffer *buffer;
+	int i;
+	int elements, el_m_1;
+	char dbf_text[15];
+
+	QETH_DBF_TEXT6(0, trace, "clib");
+	QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "bufno%3x", bufno);
+	QETH_DBF_TEXT6(0, trace, dbf_text);
+
+	buffer = &card->inbound_qdio_buffers[bufno];
+	elements = BUFFER_MAX_ELEMENTS;
+	el_m_1 = elements - 1;
+
+	for (i = 0; i < elements; i++) {
+		if (i == el_m_1)
+			buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY;
+		else
+			buffer->element[i].flags = 0;
+
+		buffer->element[i].length = PAGE_SIZE;
+		buffer->element[i].addr = INBOUND_BUFFER_POS(card, bufno, i);
+	}
+}
+
+static void
+qeth_queue_input_buffer(struct qeth_card *card, int bufno,
+			unsigned int under_int)
+{
+	int count = 0, start = 0, stop = 0, pos;
+	int result;
+	int cnt1, cnt2 = 0;
+	int wrapped = 0;
+	int i;
+	int requeue_counter;
+	char dbf_text[15];
+	int no;
+
+	QETH_DBF_TEXT5(0, trace, "qibf");
+	QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "%4x%4x", under_int, bufno);
+	QETH_DBF_TEXT5(0, trace, dbf_text);
+	atomic_inc(&card->requeue_counter);
+	if (atomic_read(&card->requeue_counter) <= QETH_REQUEUE_THRESHOLD)
+		return;
+
+	if (!spin_trylock(&card->requeue_input_lock)) {
+		QETH_DBF_TEXT5(0, trace, "qibl");
+		QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+		return;
+	}
+	requeue_counter = atomic_read(&card->requeue_counter);
+	pos = atomic_read(&card->requeue_position);
+	
+	start = pos;
+	/* 
+	 * omit the situation with 128 simultaneously
+	 * enqueued buffers, as then we can't benefit from PCI
+	 * avoidance anymore -- therefore we let count not grow as
+	 * big as requeue_counter
+	 */
+	while ((!atomic_read(&card->inbound_buffer_refcnt[pos])) &&
+	       (count < requeue_counter - 1)) {
+		no = qeth_get_empty_buffer_pool_entry(card);
+		if (no == -1) {
+			if (count)
+				break;
+			no = qeth_get_spare_buf();
+			if (no == -1) {
+				PRINT_ERR("%s: no more input buffers "
+					  "available! Inbound traffic could "
+					  "be lost! Try increasing the bufcnt "
+					  "parameter\n",
+					  card->dev_name);
+				QETH_DBF_TEXT2(1, trace, "QINB");
+				QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id);
+				goto out;
+			}
+			card->inbound_buffer_entry_no[pos] =
+				no | SPAREBUF_MASK;
+		}
+		card->inbound_buffer_entry_no[pos] = no;
+		atomic_set(&card->inbound_buffer_refcnt[pos], 1);
+		count++;
+		if (pos >= QDIO_MAX_BUFFERS_PER_Q - 1) {
+			pos = 0;
+			wrapped = 1;
+		} else
+			pos++;
+	}
+	/* stop points to the position after the last element */
+	stop = pos;
+
+	QETH_DBF_TEXT3(0, trace, "qibi");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "%4x", requeue_counter);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+	sprintf(dbf_text, "%4x%4x", start, stop);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+	
+	if (wrapped) {
+		cnt1 = QDIO_MAX_BUFFERS_PER_Q - start;
+		cnt2 = stop;
+	} else {
+		cnt1 = count;
+		/* cnt2 is already set to 0 */
+	}
+	
+	atomic_sub(count, &card->requeue_counter);
+	/* 
+	 * this is the only place where card->requeue_position is
+	 * written to, so that's ok (as it is in a lock)
+	 */
+	atomic_set(&card->requeue_position,
+		   (atomic_read(&card->requeue_position) + count)
+		   & (QDIO_MAX_BUFFERS_PER_Q - 1));
+	
+	if (cnt1) {
+		for (i = start; i < start + cnt1; i++) {
+			qeth_clear_input_buffer(card, i);
+		}
+		result = do_QDIO(card->ddev,
+				 QDIO_FLAG_SYNC_INPUT | under_int,
+				 0, start, cnt1, NULL);
+		if (result) {
+			PRINT_WARN("qeth_queue_input_buffer's "
+				   "do_QDIO returnd %i (device %s)\n",
+				   result, card->ddev->dev.bus_id);
+			QETH_DBF_TEXT1(0, trace, "QIDQ");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "%4x%4x", result, requeue_counter);
+			QETH_DBF_TEXT1(0, trace, dbf_text);
+			sprintf(dbf_text, "%4x%4x", start, cnt1);
+			QETH_DBF_TEXT1(1, trace, dbf_text);
+		}
+	}
+	if (cnt2) {
+		for (i = 0; i < cnt2; i++) {
+			qeth_clear_input_buffer(card, i);
+		}
+		result = do_QDIO(card->ddev,
+				 QDIO_FLAG_SYNC_INPUT | under_int, 0,
+				 0, cnt2, NULL);
+		if (result) {
+			PRINT_WARN("qeth_queue_input_buffer's "
+				   "do_QDIO returnd %i (device %s)\n",
+				   result, card->ddev->dev.bus_id);
+			QETH_DBF_TEXT1(0, trace, "QIDQ");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "%4x%4x", result, requeue_counter);
+			QETH_DBF_TEXT1(0, trace, dbf_text);
+			sprintf(dbf_text, "%4x%4x", 0, cnt2);
+			QETH_DBF_TEXT1(1, trace, dbf_text);
+		}
+	}
+out:
+	spin_unlock(&card->requeue_input_lock);
+
+}
+
+static inline struct sk_buff *
+qeth_get_skb(unsigned int len)
+{
+	struct sk_buff *skb;
+
+#ifdef QETH_VLAN
+	skb = dev_alloc_skb(len + VLAN_HLEN);
+	if (skb)
+		skb_reserve(skb, VLAN_HLEN);
+#else /* QETH_VLAN */
+	skb = dev_alloc_skb(len);
+#endif /* QETH_VLAN */
+	return skb;
+}
+
+static struct sk_buff *
+qeth_get_next_skb(struct qeth_card *card,
+		  int *element_ptr, int *pos_in_el_ptr,
+		  void **hdr_ptr, struct qdio_buffer *buffer)
+{
+	int length;
+	char *data_ptr;
+	int step, len_togo, element, pos_in_el;
+	int curr_len;
+	int max_elements;
+	struct sk_buff *skb;
+	char dbf_text[15];
+
+	max_elements = BUFFER_MAX_ELEMENTS;
+
+#define SBALE_LEN(x) ((x>=max_elements)?0:(buffer->element[x].length))
+#define SBALE_ADDR(x) (buffer->element[x].addr)
+
+	element = *element_ptr;
+
+	if (element >= max_elements) {
+		PRINT_WARN("device %s: error in interpreting buffer (data "
+			   "too long), %i elements.\n",
+			   card->rdev->dev.bus_id, element);
+		QETH_DBF_TEXT0(0, trace, "IEDL");
+		QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x%4x", *element_ptr, *pos_in_el_ptr);
+		QETH_DBF_TEXT0(1, trace, dbf_text);
+		QETH_DBF_HEX0(0, misc, buffer, QETH_DBF_MISC_LEN);
+		QETH_DBF_HEX0(0, misc, buffer + QETH_DBF_MISC_LEN,
+			      QETH_DBF_MISC_LEN);
+		return NULL;
+	}
+
+	pos_in_el = *pos_in_el_ptr;
+
+	curr_len = SBALE_LEN(element);
+	if (curr_len > PAGE_SIZE) {
+		PRINT_WARN("device %s: bad element length in element %i: "
+			   "0x%x\n", card->rdev->dev.bus_id, element, curr_len);
+		QETH_DBF_TEXT0(0, trace, "BELN");
+		QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x", curr_len);
+		QETH_DBF_TEXT0(0, trace, dbf_text);
+		sprintf(dbf_text, "%4x%4x", *element_ptr, *pos_in_el_ptr);
+		QETH_DBF_TEXT0(1, trace, dbf_text);
+		QETH_DBF_HEX0(0, misc, buffer, QETH_DBF_MISC_LEN);
+		QETH_DBF_HEX0(0, misc, buffer + QETH_DBF_MISC_LEN,
+			      QETH_DBF_MISC_LEN);
+		return NULL;
+	}
+	/* header fits in current element? */
+	if (curr_len < pos_in_el + QETH_HEADER_SIZE) {
+		if (!pos_in_el) {
+			QETH_DBF_TEXT6(0, trace, "gnmh");
+			QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id);
+			return NULL;	/* no more data in buffer */
+		}
+		/* set hdr to next element */
+		element++;
+		pos_in_el = 0;
+		curr_len = SBALE_LEN(element);
+		/* does it fit in there? */
+		if (curr_len < QETH_HEADER_SIZE) {
+			QETH_DBF_TEXT6(0, trace, "gdnf");
+			QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id);
+			return NULL;
+		}
+	}
+
+	*hdr_ptr = SBALE_ADDR(element) + pos_in_el;
+
+	length = *(__u16 *) ((char *) (*hdr_ptr) + QETH_HEADER_LEN_POS);
+
+	QETH_DBF_TEXT6(0, trace, "gdHd");
+	QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_HEX6(0, trace, hdr_ptr, sizeof (void *));
+
+	pos_in_el += QETH_HEADER_SIZE;
+	if (curr_len <= pos_in_el) {
+		/* switch to next element for data */
+		pos_in_el = 0;
+		element++;
+		curr_len = SBALE_LEN(element);
+		if (!curr_len) {
+			PRINT_WARN("device %s: inb. buffer with more headers "
+				   "than data areas (%i elements).\n",
+				   card->rdev->dev.bus_id, element);
+			QETH_DBF_TEXT0(0, trace, "IEMH");
+			QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "%2x%2x%4x", element, *element_ptr,
+				*pos_in_el_ptr);
+			QETH_DBF_TEXT0(1, trace, dbf_text);
+			QETH_DBF_HEX0(0, misc, buffer, QETH_DBF_MISC_LEN);
+			QETH_DBF_HEX0(0, misc, buffer + QETH_DBF_MISC_LEN,
+				      QETH_DBF_MISC_LEN);
+			return NULL;
+		}
+	}
+
+	data_ptr = SBALE_ADDR(element) + pos_in_el;
+
+	if (card->options.fake_ll == FAKE_LL) {
+		skb = qeth_get_skb(length + QETH_FAKE_LL_LEN);
+		if (!skb)
+			goto nomem;
+		skb_pull(skb, QETH_FAKE_LL_LEN);
+		if (!skb) {
+			dev_kfree_skb_irq(skb);
+			goto nomem;
+		}
+	} else {
+		skb = qeth_get_skb(length);
+		if (!skb)
+			goto nomem;
+	}
+
+	if (card->easy_copy_cap)
+		memcpy(skb_put(skb, length), data_ptr, length);
+
+	QETH_DBF_HEX6(0, trace, &data_ptr, sizeof (void *));
+	QETH_DBF_HEX6(0, trace, &skb, sizeof (void *));
+
+	len_togo = length;
+	while (1) {
+		step = qeth_min(len_togo, curr_len - pos_in_el);
+		if (!step) {
+			PRINT_WARN("device %s: unexpected end of buffer, "
+				   "length of element %i is 0. Discarding "
+				   "packet.\n",
+				   card->rdev->dev.bus_id, element);
+			QETH_DBF_TEXT0(0, trace, "IEUE");
+			QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "%2x%2x%4x", element, *element_ptr,
+				*pos_in_el_ptr);
+			QETH_DBF_TEXT0(0, trace, dbf_text);
+			sprintf(dbf_text, "%4x%4x", len_togo, step);
+			QETH_DBF_TEXT0(0, trace, dbf_text);
+			sprintf(dbf_text, "%4x%4x", curr_len, pos_in_el);
+			QETH_DBF_TEXT0(1, trace, dbf_text);
+			QETH_DBF_HEX0(0, misc, buffer, QETH_DBF_MISC_LEN);
+			QETH_DBF_HEX0(0, misc, buffer + QETH_DBF_MISC_LEN,
+				      QETH_DBF_MISC_LEN);
+			dev_kfree_skb_irq(skb);
+			return NULL;
+		}
+		if (!card->easy_copy_cap)
+			memcpy(skb_put(skb, step), data_ptr, step);
+		len_togo -= step;
+		if (len_togo) {
+			pos_in_el = 0;
+			element++;
+			curr_len = SBALE_LEN(element);
+			data_ptr = SBALE_ADDR(element);
+		} else {
+#ifdef QETH_INBOUND_PACKING_1_PACKET_PER_SBALE
+			element++;
+			/* we don't need to calculate curr_len */
+			pos_in_el = 0;
+#else /* QETH_INBOUND_PACKING_1_PACKET_PER_SBALE */
+			pos_in_el += step;
+#endif /* QETH_INBOUND_PACKING_1_PACKET_PER_SBALE */
+			break;
+		}
+	}
+
+	sprintf(dbf_text, "%4x%4x", element, pos_in_el);
+	QETH_DBF_TEXT6(0, trace, dbf_text);
+
+	*element_ptr = element;
+	*pos_in_el_ptr = pos_in_el;
+
+	return skb;
+
+nomem:
+	if (net_ratelimit()) {
+		PRINT_WARN("no memory for packet from %s\n", card->dev_name);
+	}
+	QETH_DBF_TEXT0(0, trace, "NOMM");
+	QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id);
+	return NULL;
+}
+
+static inline void
+__qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
+			   void *hdr_ptr)
+{
+	skb->mac.raw = skb->data - QETH_FAKE_LL_LEN;
+	switch (skb->pkt_type) {
+	case PACKET_MULTICAST:
+		switch (skb->protocol) {
+#ifdef QETH_IPV6
+		case __constant_htons(ETH_P_IPV6):
+			ndisc_mc_map((struct in6_addr *)
+				     skb->data + QETH_FAKE_LL_V6_ADDR_POS,
+				     skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS,
+				     card->dev, 0);
+				break;
+#endif /* QETH_IPV6 */
+		case __constant_htons(ETH_P_IP):
+			qeth_get_mac_for_ipm(*(__u32*)
+					     skb->data + QETH_FAKE_LL_V4_ADDR_POS,
+					     skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS,
+					     card->dev);
+			break;
+		default:
+			memcpy(skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS,
+			       card->dev->dev_addr, QETH_FAKE_LL_ADDR_LEN);
+		}
+		break;
+	case PACKET_BROADCAST:
+		memset(skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS,
+		       0xff, QETH_FAKE_LL_ADDR_LEN);
+		break;
+	default:
+		memcpy(skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS,
+		       card->dev->dev_addr, QETH_FAKE_LL_ADDR_LEN);
+	}
+
+	if (*(__u8 *) (hdr_ptr + 11) & QETH_EXT_HEADER_SRC_MAC_ADDRESS) {
+		memcpy(skb->mac.raw + QETH_FAKE_LL_SRC_MAC_POS,
+		       hdr_ptr + QETH_FAKE_LL_SRC_MAC_POS_IN_QDIO_HDR,
+		       QETH_FAKE_LL_ADDR_LEN);
+	} else {
+		/* clear source MAC for security reasons */
+		memset(skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS,
+		       0, QETH_FAKE_LL_ADDR_LEN);
+	}
+	memcpy(skb->mac.raw + QETH_FAKE_LL_PROT_POS,
+	       &skb->protocol, QETH_FAKE_LL_PROT_LEN);
+
+}
+
+static inline void
+__qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb,
+			void *hdr_ptr)
+{
+#ifdef QETH_VLAN
+	__u16 *vlan_tag;
+
+	if (*(__u8 *) (hdr_ptr + 11) & QETH_EXT_HEADER_VLAN_FRAME) {
+
+		vlan_tag = (__u16 *) skb_push(skb, VLAN_HLEN);
+		/*
+		  if (*(__u8*)(hdr_ptr+11) & 
+		  QETH_EXT_HEADER_INCLUDE_VLAN_TAG) {
+		  *vlan_tag = *(__u16*)(hdr_ptr+28);
+		  *(vlan_tag+1)= *(__u16*)(hdr_ptr+30);
+		  } else {
+		*/
+		*vlan_tag = *(__u16 *) (hdr_ptr + 12);
+		*(vlan_tag + 1) = skb->protocol;
+		/*
+		  }
+		*/
+		skb->protocol = __constant_htons(ETH_P_8021Q);
+	}
+#endif
+}
+
+static inline void
+__qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, void *hdr_ptr)
+{
+	char dbf_text[15];
+	int version;
+	unsigned short cast_type;
+	
+	version = ((*(__u16 *) (hdr_ptr)) & (QETH_HEADER_IPV6)) ? 6 : 4;
+	skb->protocol = htons((version == 4) ? ETH_P_IP : 
+			      (version == 6) ? ETH_P_IPV6 : ETH_P_ALL);
+	cast_type = (*(__u16 *) (hdr_ptr)) & (QETH_CAST_FLAGS);
+	switch (cast_type) {
+	case QETH_CAST_UNICAST:
+		skb->pkt_type = PACKET_HOST;
+		break;
+	case QETH_CAST_MULTICAST:
+		skb->pkt_type = PACKET_MULTICAST;
+		break;
+	case QETH_CAST_BROADCAST:
+		skb->pkt_type = PACKET_BROADCAST;
+		break;
+	case QETH_CAST_ANYCAST:
+	case QETH_CAST_NOCAST:
+		QETH_DBF_TEXT2(0, trace, "ribf");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "castan%2x", cast_type);
+		QETH_DBF_TEXT2(1, trace, dbf_text);
+		skb->pkt_type = PACKET_HOST;
+		break;
+	default:
+		PRINT_WARN("adapter is using an unknown casting value "
+			   "of 0x%x. Using unicasting instead.\n",
+			   cast_type);
+		skb->pkt_type = PACKET_HOST;
+		QETH_DBF_TEXT2(0, trace, "ribf");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "castun%2x", cast_type);
+		QETH_DBF_TEXT2(1, trace, dbf_text);
+	}
+
+	if (card->options.fake_ll == FAKE_LL)
+		__qeth_rebuild_skb_fake_ll(card, skb, hdr_ptr);
+	else
+		skb->mac.raw = skb->data;
+
+	skb->ip_summed = card->options.checksum_type;
+	if (card->options.checksum_type == HW_CHECKSUMMING) {
+		/* do we have a checksummed packet? */
+		if (*(__u8 *) (hdr_ptr + 11) & QETH_EXT_HEADER_CSUM_TRANSP_REQ) {
+			/* skb->ip_summed is set already */
+			
+			/* 
+			 * vlan is not an issue here, it's still in
+			 * the QDIO header, not pushed in the skb yet
+			 */
+			int ip_len = (skb->data[0] & 0x0f) << 2;
+
+			if (*(__u8 *) (hdr_ptr + 11) &
+			    QETH_EXT_HEADER_CSUM_TRANSP_FRAME_TYPE) {
+				/* get the UDP checksum */
+				skb->csum = *(__u16 *)
+					(&skb->data[ip_len + 
+						    QETH_UDP_CSUM_OFFSET]);
+			} else {
+				/* get the TCP checksum */
+				skb->csum = *(__u16 *)
+					(&skb->data[ip_len +
+						    QETH_TCP_CSUM_OFFSET]);
+			}
+		} else {
+			/* make the stack check it */
+			skb->ip_summed = SW_CHECKSUMMING;
+		}
+	}
+	__qeth_rebuild_skb_vlan(card, skb, hdr_ptr);
+}
+
+static void
+qeth_read_in_buffer(struct qeth_card *card, int buffer_no)
+{
+	struct sk_buff *skb;
+	void *hdr_ptr;
+	int element = 0, pos_in_el = 0;
+	struct qdio_buffer *buffer;
+	int i;
+	int max_elements;
+	char dbf_text[15];
+	struct net_device *dev;
+
+	dev = card->dev;
+	max_elements = BUFFER_MAX_ELEMENTS;
+
+	buffer = &card->inbound_qdio_buffers[buffer_no];
+
+	/* inform about errors */
+	if (buffer->element[15].flags & 0xff) {
+		PRINT_WARN("on device %s: incoming SBALF 15 on buffer "
+			   "0x%x are 0x%x\n",
+			   card->rdev->dev.bus_id, buffer_no,
+			   buffer->element[15].flags & 0xff);
+		sprintf(dbf_text, "SF%s%2x%2x",
+			card->rdev->dev.bus_id, buffer_no,
+			buffer->element[15].flags & 0xff);
+		QETH_DBF_HEX1(1, trace, dbf_text, QETH_DBF_TRACE_LEN);
+	}
+
+	for (i = 0; i < max_elements - 1; i++) {
+		if (buffer->element[i].flags & SBAL_FLAGS_LAST_ENTRY) {
+			buffer->element[i + 1].length = 0;
+			break;
+		}
+	}
+#ifdef QETH_PERFORMANCE_STATS
+	card->perf_stats.bufs_rec++;
+#endif /* QETH_PERFORMANCE_STATS */
+
+	sprintf(dbf_text, "ribX%s", card->rdev->dev.bus_id);
+	dbf_text[3] = buffer_no;
+	QETH_DBF_HEX6(0, trace, dbf_text, QETH_DBF_TRACE_LEN);
+
+	while ((skb = qeth_get_next_skb(card, &element, &pos_in_el,
+					&hdr_ptr, buffer))) {
+
+#ifdef QETH_PERFORMANCE_STATS
+		card->perf_stats.skbs_rec++;
+#endif /* QETH_PERFORMANCE_STATS */
+
+		if (skb) {
+			skb->dev = dev;
+
+#ifdef QETH_IPV6
+			if ((*(__u16 *) (hdr_ptr)) & (QETH_HEADER_PASSTHRU))
+				skb->protocol = card->type_trans(skb, dev);
+			else
+#endif /* QETH_IPV6 */
+				__qeth_rebuild_skb(card, skb, hdr_ptr);
+
+#ifdef QETH_PERFORMANCE_STATS
+			card->perf_stats.inbound_time +=
+			    NOW - card->perf_stats.inbound_start_time;
+			card->perf_stats.inbound_cnt++;
+#endif /* QETH_PERFORMANCE_STATS */
+
+			QETH_DBF_TEXT6(0, trace, "rxpk");
+			QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id);
+
+			netif_rx(skb);
+			dev->last_rx = jiffies;
+			card->stats->rx_packets++;
+			card->stats->rx_bytes += skb->len;
+		} else {
+			PRINT_WARN("%s: dropped packet, no buffers "
+				   "available.\n", card->dev_name);
+			QETH_DBF_TEXT2(1, trace, "DROP");
+			QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id);
+			card->stats->rx_dropped++;
+		}
+	}
+	atomic_set(&card->inbound_buffer_refcnt[buffer_no], 0);
+	qeth_put_buffer_pool_entry(card,
+				   card->inbound_buffer_entry_no[buffer_no]);
+}
+
+static inline void
+__qeth_fill_header_add_vlan(struct qeth_hdr *hdr, struct sk_buff *skb,
+			    int version)
+{
+#ifdef QETH_VLAN
+	struct qeth_card *card;
+
+	/* before we're going to overwrite this location with next hop ip */
+	card = (struct qeth_card *) skb->dev->priv;
+	if ((card->vlangrp != NULL) &&
+	    vlan_tx_tag_present(skb) && (version == 4)) {
+		hdr->ext_flags = QETH_EXT_HEADER_VLAN_FRAME;
+		hdr->vlan_id = vlan_tx_tag_get(skb);
+	}
+#endif
+}
+
+static __u8
+__qeth_get_flags_v4(int multicast)
+{
+	if (multicast == RTN_MULTICAST)
+		return QETH_CAST_MULTICAST;
+	if (multicast == RTN_BROADCAST)
+		return QETH_CAST_BROADCAST;
+	return QETH_CAST_UNICAST;
+}
+
+static __u8
+__qeth_get_flags_v6(int multicast)
+{
+	if (multicast == RTN_MULTICAST)
+		return QETH_CAST_MULTICAST |
+			QETH_HEADER_PASSTHRU | QETH_HEADER_IPV6;
+	if (multicast == RTN_ANYCAST)
+		return QETH_CAST_ANYCAST |
+			QETH_HEADER_PASSTHRU | QETH_HEADER_IPV6;
+	if (multicast == RTN_BROADCAST)
+		return QETH_CAST_BROADCAST |
+			QETH_HEADER_PASSTHRU | QETH_HEADER_IPV6;
+	return QETH_CAST_UNICAST |
+#ifdef QETH_IPV6
+		QETH_HEADER_PASSTHRU |
+#endif /* QETH_IPV6 */
+		QETH_HEADER_IPV6;
+}
+
+static void
+qeth_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb,
+		 int version, int multicast)
+{
+	char dbf_text[15];
+
+	hdr->id = 1;
+	hdr->ext_flags = 0;
+
+	__qeth_fill_header_add_vlan(hdr, skb, version);
+
+	hdr->length = skb->len - QETH_HEADER_SIZE;	/* as skb->len includes
+							   the header now */
+
+	/* yes, I know this is doubled code, but a small little bit
+	   faster maybe */
+	if (version == 4) {	/* IPv4 */
+		hdr->flags = __qeth_get_flags_v4(multicast);
+		*((__u32 *) (&hdr->dest_addr[0])) = 0;
+		*((__u32 *) (&hdr->dest_addr[4])) = 0;
+		*((__u32 *) (&hdr->dest_addr[8])) = 0;
+		if ((skb->dst) && (skb->dst->neighbour)) {
+			*((__u32 *) (&hdr->dest_addr[12])) =
+			    *((__u32 *) skb->dst->neighbour->primary_key);
+		} else {
+			/* fill in destination address used in ip header */
+			*((__u32 *) (&hdr->dest_addr[12])) = skb->nh.iph->daddr;
+		}
+	} else if (version == 6) {	/* IPv6 or passthru */
+		hdr->flags = __qeth_get_flags_v6(multicast);
+		if ((skb->dst) && (skb->dst->neighbour)) {
+			memcpy(hdr->dest_addr,
+			       skb->dst->neighbour->primary_key, 16);
+		} else {
+			/* fill in destination address used in ip header */
+			memcpy(hdr->dest_addr, &skb->nh.ipv6h->daddr, 16);
+		}
+	} else {		/* passthrough */
+		if (!memcmp(skb->data + QETH_HEADER_SIZE,
+			    skb->dev->broadcast, 6)) {   /* broadcast? */
+			hdr->flags = QETH_CAST_BROADCAST | QETH_HEADER_PASSTHRU;
+		} else {
+			hdr->flags = QETH_CAST_UNICAST | QETH_HEADER_PASSTHRU;
+		}
+	}
+	sprintf(dbf_text, "filhdr%2x", version);
+	QETH_DBF_TEXT6(0, trace, dbf_text);
+	sprintf(dbf_text, "%2x", multicast);
+	QETH_DBF_TEXT6(0, trace, dbf_text);
+	QETH_DBF_HEX6(0, trace, &skb, sizeof (void *));
+	QETH_DBF_HEX6(0, trace, &skb->data, sizeof (void *));
+	QETH_DBF_HEX6(0, misc, hdr, __max(QETH_HEADER_SIZE, QETH_DBF_MISC_LEN));
+	QETH_DBF_HEX6(0, data, skb->data,
+		      __max(QETH_DBF_DATA_LEN, QETH_DBF_DATA_LEN));
+}
+
+static int inline
+qeth_fill_buffer(struct qdio_buffer *buffer, char *dataptr,
+		 int length, int element)
+{
+	int length_here;
+	int first_lap = 1;
+	char dbf_text[15];
+	int first_element = element;
+
+	while (length > 0) {
+		/* length_here is the remaining amount of data in this page */
+		length_here =
+		    PAGE_SIZE - ((unsigned long) dataptr & (PAGE_SIZE - 1));
+		if (length < length_here)
+			length_here = length;
+
+		buffer->element[element].addr = dataptr;
+		buffer->element[element].length = length_here;
+		length -= length_here;
+		if (!length) {
+			if (first_lap) {
+				buffer->element[element].flags = 0;
+			} else {
+				buffer->element[element].flags =
+				    SBAL_FLAGS_LAST_FRAG;
+			}
+		} else {
+			if (first_lap) {
+				buffer->element[element].flags =
+				    SBAL_FLAGS_FIRST_FRAG;
+			} else {
+				buffer->element[element].flags =
+				    SBAL_FLAGS_MIDDLE_FRAG;
+			}
+		}
+		dataptr = dataptr + length_here;
+		element++;
+		if (element > QDIO_MAX_ELEMENTS_PER_BUFFER) {
+			PRINT_ERR("qeth_fill_buffer: IP packet too big!\n");
+			QETH_DBF_TEXT1(0, trace, "IPpktobg");
+			QETH_DBF_HEX1(1, trace, &dataptr, sizeof (void *));
+			buffer->element[first_element].length = 0;
+			break;
+		}
+		first_lap = 0;
+	}
+	sprintf(dbf_text, "filbuf%2x", element);
+	QETH_DBF_TEXT6(0, trace, dbf_text);
+	QETH_DBF_HEX3(0, misc, buffer, QETH_DBF_MISC_LEN);
+	QETH_DBF_HEX3(0, misc, buffer + QETH_DBF_MISC_LEN, QETH_DBF_MISC_LEN);
+
+	return element;
+}
+
+static void
+qeth_flush_packed_packets(struct qeth_card *card, int queue, int under_int)
+{
+	struct qdio_buffer *buffer;
+	int result;
+	int position;
+	int position_for_do_qdio;
+	char dbf_text[15];
+	int last_pci;
+
+	position = card->outbound_first_free_buffer[queue];
+	/* can happen, when in the time between deciding to pack and sending
+	   the next packet the lower mark was reached: */
+	if (!card->outbound_ringbuffer[queue]->ringbuf_element[position].
+	    next_element_to_fill)
+		return;
+
+	buffer = &card->outbound_ringbuffer[queue]->buffer[position];
+	buffer->element[card->outbound_ringbuffer[queue]->
+			ringbuf_element[position].
+			next_element_to_fill - 1].flags |=
+	    SBAL_FLAGS_LAST_ENTRY;
+
+	card->dev->trans_start = jiffies;
+
+#ifdef QETH_PERFORMANCE_STATS
+	if (card->outbound_buffer_send_state[queue][position] ==
+	    SEND_STATE_DONT_PACK) {
+		card->perf_stats.bufs_sent_dont_pack++;
+	} else if (card->outbound_buffer_send_state[queue][position] ==
+		   SEND_STATE_PACK) {
+		card->perf_stats.bufs_sent_pack++;
+	}
+	card->perf_stats.bufs_sent++;
+#endif /* QETH_PERFORMANCE_STATS */
+
+	position_for_do_qdio = position;
+
+	position = (position + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1);
+	card->outbound_first_free_buffer[queue] = position;
+
+	card->outbound_bytes_in_buffer[queue] = 0;
+	/* we can override that, as we have at most 127 buffers enqueued */
+	card->outbound_ringbuffer[queue]->ringbuf_element[position].
+	    next_element_to_fill = 0;
+
+	atomic_inc(&card->outbound_used_buffers[queue]);
+
+	QETH_DBF_TEXT5(0, trace, "flsp");
+	QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "%4x%2x%2x", position_for_do_qdio, under_int, queue);
+	QETH_DBF_TEXT5(0, trace, dbf_text);
+	QETH_DBF_HEX5(0, misc, buffer, QETH_DBF_MISC_LEN);
+	QETH_DBF_HEX5(0, misc, buffer + QETH_DBF_MISC_LEN, QETH_DBF_MISC_LEN);
+
+	/* 
+	 * we always set the outbound pci flag, don't care, whether the
+	 * adapter honors it or not
+	 */
+	switch (card->send_state[queue]) {
+	case SEND_STATE_DONT_PACK:
+		if (atomic_read(&card->outbound_used_buffers[queue])
+		    < HIGH_WATERMARK_PACK - WATERMARK_FUZZ)
+			break;
+		/* set the PCI bit */
+		card->outbound_ringbuffer[queue]->
+		    buffer[position_for_do_qdio].element[0].flags |= 0x40;
+		atomic_set(&card->last_pci_pos[queue], position_for_do_qdio);
+		break;
+	case SEND_STATE_PACK:
+		last_pci = atomic_read(&card->last_pci_pos[queue]);
+		if (position_for_do_qdio < last_pci)
+			last_pci -= QDIO_MAX_BUFFERS_PER_Q;
+		/* so:
+		 * last_pci is the position of the last pci we've set
+		 * position_for_do_qdio is the position we will send out now
+		 * outbound_used_buffers is the number of buffers used (means
+		 *   all buffers hydra has, inclusive position_for_do_qdio)
+		 *
+		 * we have to request a pci, if we have got the buffer of the
+		 * last_pci position back.
+		 *
+		 * position_for_do_qdio-outbound_used_buffers is the newest
+		 *   buffer that we got back from hydra
+		 *
+		 * if this is greater or equal than the last_pci position,
+		 * we should request a pci, as no pci request is
+		 * outstanding anymore
+		 */
+		if (position_for_do_qdio -
+		    atomic_read(&card->outbound_used_buffers[queue]) >=
+		    last_pci) {
+			/* set the PCI bit */
+			card->outbound_ringbuffer[queue]->
+			    buffer[position_for_do_qdio].
+			    element[0].flags |= 0x40;
+			atomic_set(&card->last_pci_pos[queue],
+				   position_for_do_qdio);
+		}
+	}
+
+	/* 
+	 * this has to be at the end, otherwise a buffer could be flushed
+	 * twice (see comment in qeth_do_send_packet)
+	 */
+	result = do_QDIO(card->ddev, QDIO_FLAG_SYNC_OUTPUT | under_int, queue,
+			 position_for_do_qdio, 1, NULL);
+
+	if (result) {
+		PRINT_WARN("Outbound do_QDIO returned %i "
+			   "(device %s)\n", result, card->ddev->dev.bus_id);
+		QETH_DBF_TEXT5(0, trace, "FLSP");
+		QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "odoQ%4x", result);
+		QETH_DBF_TEXT5(0, trace, dbf_text);
+		sprintf(dbf_text, "%4x%2x%2x", position_for_do_qdio,
+			under_int, queue);
+		QETH_DBF_TEXT5(0, trace, dbf_text);
+		QETH_DBF_HEX5(0, misc, buffer, QETH_DBF_MISC_LEN);
+		QETH_DBF_HEX5(0, misc, buffer + QETH_DBF_MISC_LEN,
+			      QETH_DBF_MISC_LEN);
+	}
+}
+
+#define ERROR_NONE 0
+#define ERROR_RETRY 1
+#define ERROR_LINK_FAILURE 2
+#define ERROR_KICK_THAT_PUPPY 3
+static inline int
+qeth_determine_send_error(int cc, int qdio_error, int sbalf15)
+{
+	char dbf_text[15];
+
+	switch (cc & 3) {
+	case 0:
+		if (qdio_error)
+			return ERROR_LINK_FAILURE;
+		return ERROR_NONE;
+	case 2:
+		if (cc & QDIO_SIGA_ERROR_B_BIT_SET) {
+			QETH_DBF_TEXT3(0, trace, "sigacc2b");
+			return ERROR_KICK_THAT_PUPPY;
+		}
+		if (qeth_sbalf15_in_retrieable_range(sbalf15))
+			return ERROR_RETRY;
+		return ERROR_LINK_FAILURE;
+		/* look at qdio_error and sbalf 15 */
+	case 1:
+		PRINT_WARN("siga returned cc 1! cc=0x%x, "
+			   "qdio_error=0x%x, sbalf15=0x%x\n",
+			   cc, qdio_error, sbalf15);
+
+		QETH_DBF_TEXT3(0, trace, "siga-cc1");
+		QETH_DBF_TEXT2(0, qerr, "siga-cc1");
+		sprintf(dbf_text, "%1x%2x%2x", cc, qdio_error, sbalf15);
+		QETH_DBF_TEXT3(0, trace, dbf_text);
+		QETH_DBF_TEXT2(0, qerr, dbf_text);
+		return ERROR_LINK_FAILURE;
+	case 3:
+		QETH_DBF_TEXT3(0, trace, "siga-cc3");
+		return ERROR_KICK_THAT_PUPPY;
+	}
+	return ERROR_LINK_FAILURE;	/* should never happen */
+}
+
+static void
+qeth_free_buffer(struct qeth_card *card, int queue, int bufno,
+		 int qdio_error, int siga_error)
+{
+	struct sk_buff *skb;
+	int error;
+	int retries;
+	int sbalf15;
+	char dbf_text[15];
+	struct qdio_buffer *buffer;
+
+	switch (card->outbound_buffer_send_state[queue][bufno]) {
+	case SEND_STATE_DONT_PACK:	/* fallthrough */
+	case SEND_STATE_PACK:
+		QETH_DBF_TEXT5(0, trace, "frbf");
+		QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%2x%2x%4x", queue, bufno,
+			card->outbound_buffer_send_state[queue][bufno]);
+		QETH_DBF_TEXT5(0, trace, dbf_text);
+
+		buffer = &card->outbound_ringbuffer[queue]->buffer[bufno];
+		sbalf15 = buffer->element[15].flags & 0xff;
+		error =
+		    qeth_determine_send_error(siga_error, qdio_error, sbalf15);
+		if (error == ERROR_KICK_THAT_PUPPY) {
+			sprintf(dbf_text, "KP%s%2x",
+				card->rdev->dev.bus_id, queue);
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+			QETH_DBF_TEXT2(0, qerr, dbf_text);
+			QETH_DBF_TEXT2(1, setup, dbf_text);
+			sprintf(dbf_text, "%2x%2x%2x%2x", bufno,
+				siga_error, qdio_error, sbalf15);
+			QETH_DBF_TEXT2(1, trace, dbf_text);
+			QETH_DBF_TEXT2(1, qerr, dbf_text);
+			PRINT_ERR("Outbound queue x%x on device %s (%s); "
+				  "errs: siga: x%x, qdio: x%x, flags15: "
+				  "x%x. The device will be taken down.\n",
+				  queue, card->rdev->dev.bus_id, card->dev_name,
+				  siga_error, qdio_error, sbalf15);
+			netif_stop_queue(card->dev);
+			qeth_set_dev_flag_norunning(card);
+			atomic_set(&card->problem, PROBLEM_BAD_SIGA_RESULT);
+			qeth_schedule_recovery(card);
+		} else if (error == ERROR_RETRY) {
+			/* analyze, how many retries we did so far */
+			retries = card->send_retries[queue][bufno];
+
+			sprintf(dbf_text, "Rt%s%2x",
+				card->rdev->dev.bus_id, queue);
+			QETH_DBF_TEXT4(0, trace, dbf_text);
+			sprintf(dbf_text, "b%2x:%2x%2x", bufno,
+				sbalf15, retries);
+			QETH_DBF_TEXT4(0, trace, dbf_text);
+
+			if (++retries > SEND_RETRIES_ALLOWED) {
+				error = ERROR_LINK_FAILURE;
+				QETH_DBF_TEXT4(1, trace, "ndegelnd");
+			}
+			/* else error stays RETRY for the switch statemnet */
+		} else if (error == ERROR_LINK_FAILURE) {
+			/* we don't want to log failures resulting from
+			 * too many retries */
+			QETH_DBF_TEXT3(1, trace, "Fail");
+			QETH_DBF_TEXT3(1, trace, card->rdev->dev.bus_id);
+			QETH_DBF_HEX3(0, misc, buffer, QETH_DBF_MISC_LEN);
+			QETH_DBF_HEX3(0, misc, buffer + QETH_DBF_MISC_LEN,
+				      QETH_DBF_MISC_LEN);
+		}
+
+		while ((skb = skb_dequeue(&card->outbound_ringbuffer[queue]->
+					  ringbuf_element[bufno].skb_list))) {
+			switch (error) {
+			case ERROR_NONE:
+				atomic_dec(&skb->users);
+				dev_kfree_skb_irq(skb);
+				break;
+			case ERROR_RETRY:
+				QETH_DBF_TEXT3(0, qerr, "RETRY!!!");
+				QETH_DBF_TEXT4(0, trace, "RETRY!!!");
+				atomic_dec(&skb->users);
+				/* retry packet async (quickly) ... */
+				atomic_dec(&skb->users);
+				dev_kfree_skb_irq(skb);
+				break;
+			case ERROR_LINK_FAILURE:
+			case ERROR_KICK_THAT_PUPPY:
+				QETH_DBF_TEXT4(0, trace, "endeglnd");
+				dst_link_failure(skb);
+				atomic_dec(&skb->users);
+				dev_kfree_skb_irq(skb);
+				break;
+			}
+		}
+		break;
+	default:
+		PRINT_WARN("oops... wrong send_state on %s. "
+			   "shouldn't happen "
+			   "(line %i). q=%i, bufno=x%x, state=%i\n",
+			   card->dev_name, __LINE__, queue, bufno,
+			   card->outbound_buffer_send_state[queue][bufno]);
+		QETH_DBF_TEXT0(1, trace, "UPSf");
+		QETH_DBF_TEXT0(1, qerr, "UPSf");
+		QETH_DBF_TEXT0(1, trace, card->rdev->dev.bus_id);
+		QETH_DBF_TEXT0(1, qerr, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%2x%2x%4x", queue, bufno,
+			card->outbound_buffer_send_state[queue][bufno]);
+		QETH_DBF_TEXT0(1, trace, dbf_text);
+		QETH_DBF_TEXT0(1, qerr, dbf_text);
+	}
+	card->outbound_buffer_send_state[queue][bufno] = SEND_STATE_INACTIVE;
+	card->send_retries[queue][bufno] = 0;
+}
+
+static void
+qeth_free_all_skbs(struct qeth_card *card)
+{
+	int q, b;
+
+	for (q = 0; q < card->no_queues; q++)
+		for (b = 0; b < QDIO_MAX_BUFFERS_PER_Q; b++)
+			if (card->outbound_buffer_send_state[q][b] !=
+			    SEND_STATE_INACTIVE)
+				qeth_free_buffer(card, q, b, 0, 0);
+}
+
+static inline void
+qeth_flush_buffer(struct qeth_card *card, int queue, int under_int)
+{
+	char dbf_text[15];
+	QETH_DBF_TEXT5(0, trace, "flsb");
+	QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "%2x%2x%2x", queue, under_int,
+		card->outbound_buffer_send_state[queue]
+		[card->outbound_first_free_buffer[queue]]);
+	QETH_DBF_TEXT5(0, trace, dbf_text);
+
+	switch (card->outbound_buffer_send_state[queue]
+		[card->outbound_first_free_buffer[queue]]) {
+	case SEND_STATE_DONT_PACK:
+		break;
+	case SEND_STATE_PACK:
+		qeth_flush_packed_packets(card, queue, under_int);
+		break;
+	default:
+		break;
+	}
+}
+
+#ifdef QETH_VLAN
+void
+qeth_insert_ipv6_vlan_tag(struct sk_buff *__skb)
+{
+
+	/* Move the mac addresses to the beginning of the new header.
+	 * We are using three memcpys instead of one memmove to save cycles.
+	 */
+#define TMP_CPYSIZE 4
+	__u16 *tag;
+	tag = (__u16 *) skb_push(__skb, VLAN_HLEN);
+	memcpy(__skb->data, __skb->data + TMP_CPYSIZE, TMP_CPYSIZE);
+	memcpy(__skb->data + TMP_CPYSIZE,
+	       __skb->data + (2 * TMP_CPYSIZE), TMP_CPYSIZE);
+	memcpy(__skb->data + (2 * TMP_CPYSIZE),
+	       __skb->data + (3 * TMP_CPYSIZE), TMP_CPYSIZE);
+	tag = (__u16 *) (__skb->data + (3 * TMP_CPYSIZE));
+
+	/*first two bytes  = ETH_P_8021Q (0x8100)
+	 *second two bytes = VLANID
+	 */
+
+	*tag = __constant_htons(ETH_P_8021Q);
+	*(tag + 1) = vlan_tx_tag_get(__skb);
+	*(tag + 1) = htons(*(tag + 1));
+#undef TMP_CPYSIZE
+}
+#endif
+
+static inline void
+__qeth_add_vlan_tag(struct qeth_card *card, struct sk_buff *skb, int version)
+{
+#ifdef QETH_VLAN
+	if ((card->vlangrp != NULL) &&
+	    vlan_tx_tag_present(skb) && (version == 6)) {
+		qeth_insert_ipv6_vlan_tag(skb);
+	}
+#endif
+}
+
+static void
+qeth_send_packet_fast(struct qeth_card *card, struct sk_buff *skb,
+		      struct net_device *dev,
+		      int queue, int version, int multicast)
+{
+	struct qeth_ringbuffer_element *mybuffer;
+	int position;
+	struct qeth_hdr *hdr;
+	char *dataptr;
+	char dbf_text[15];
+	struct sk_buff *nskb;
+
+	position = card->outbound_first_free_buffer[queue];
+
+	card->outbound_buffer_send_state[queue][position] =
+	    SEND_STATE_DONT_PACK;
+
+	mybuffer = &card->outbound_ringbuffer[queue]->ringbuf_element[position];
+	if (skb_headroom(skb) < QETH_HEADER_SIZE) {
+		if ((version) && (!card->realloc_message)) {
+			card->realloc_message = 1;
+			PRINT_WARN("%s: not enough headroom in skb. "
+ 				   "Increasing the "
+ 				   "add_hhlen parameter by %i may help.\n",
+				   card->dev_name,
+				   QETH_HEADER_SIZE - skb_headroom(skb));
+		}
+		PRINT_STUPID("%s: not enough headroom in skb (missing: %i)\n",
+			     card->dev_name,
+			     QETH_HEADER_SIZE - skb_headroom(skb));
+		QETH_DBF_TEXT3(0, trace, "NHRf");
+		QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%2x%2x%2x%2x", skb_headroom(skb),
+			version, multicast, queue);
+		QETH_DBF_TEXT3(0, trace, dbf_text);
+		QETH_DBF_HEX3(0, trace, &skb->head, sizeof (void *));
+		QETH_DBF_HEX3(0, trace, &skb->data, sizeof (void *));
+		nskb = skb_realloc_headroom(skb, QETH_HEADER_SIZE);
+		if (!nskb) {
+			PRINT_WARN("%s: could not realloc headroom\n",
+				   card->dev_name);
+			QETH_DBF_TEXT2(0, trace, "CNRf");
+			QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+			dev_kfree_skb_irq(skb);
+			return;
+		}
+		dev_kfree_skb_irq(skb);
+		skb = nskb;
+	}
+	__qeth_add_vlan_tag(card, skb, version);
+	hdr = (struct qeth_hdr *) (skb_push(skb, QETH_HEADER_SIZE));
+	/* 
+	 * sanity check, the Linux memory allocation scheme should
+	 * never present us cases like this one (the 32bytes header plus
+	 * the first 40 bytes of the paket cross a 4k boundary)
+	 */
+	dataptr = (char *) hdr;
+	if ((((unsigned long) dataptr) & (~(PAGE_SIZE - 1))) !=
+	    (((unsigned long) dataptr + QETH_HEADER_SIZE +
+	      QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
+		PRINT_ERR("%s: packet misaligned -- the first %i bytes "
+			  "are not in the same page. Discarding packet!\n",
+			  card->dev_name,
+			  QETH_HEADER_SIZE + QETH_IP_HEADER_SIZE);
+		PRINT_ERR("head=%p, data=%p\n", skb->head, skb->data);
+		QETH_DBF_TEXT1(0, trace, "PMAf");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%2x%2x%2x%2x", skb_headroom(skb),
+			version, multicast, queue);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_HEX1(0, trace, &skb->head, sizeof (void *));
+		QETH_DBF_HEX1(1, trace, &skb->data, sizeof (void *));
+		dev_kfree_skb_irq(skb);
+		return;
+	}
+
+	atomic_inc(&skb->users);
+	skb_queue_tail(&mybuffer->skb_list, skb);
+	qeth_fill_header(hdr, skb, version, multicast);
+	/* we need to write to next_element_to_fill as
+	   qeth_flush_packed_packets checks it */
+	card->outbound_ringbuffer[queue]->ringbuf_element[position].
+	    next_element_to_fill =
+	    qeth_fill_buffer(&card->outbound_ringbuffer[queue]->
+			     buffer[position], (char *) hdr, skb->len, 0);
+
+#ifdef QETH_PERFORMANCE_STATS
+	card->perf_stats.skbs_sent_dont_pack++;
+#endif /* QETH_PERFORMANCE_STATS */
+
+	qeth_flush_packed_packets(card, queue, 0);
+}
+
+/* no checks, if all elements are used, as then we would not be here (at most
+   127 buffers are enqueued) */
+static void
+qeth_send_packet_packed(struct qeth_card *card, struct sk_buff *skb,
+			struct net_device *dev,
+			int queue, int version, int multicast)
+{
+	struct qeth_ringbuffer_element *mybuffer;
+	int elements_needed;
+	int element_to_fill;
+	int buffer_no;
+	int length;
+	char *dataptr;
+	struct qeth_hdr *hdr;
+	char dbf_text[15];
+	struct sk_buff *nskb;
+
+	/* sanity check, dev->hard_header_len should prevent this */
+	if (skb_headroom(skb) < QETH_HEADER_SIZE) {
+		if ((version) && (!card->realloc_message)) {
+			card->realloc_message = 1;
+			PRINT_WARN("%s: not enough headroom in skb. "
+				   "Try increasing the "
+				   "add_hhlen parameter by %i.\n",
+				   card->dev_name,
+				   QETH_HEADER_SIZE - skb_headroom(skb));
+		}
+		PRINT_STUPID("%s: not enough headroom in skb (missing: %i)\n",
+			     card->dev_name,
+			     QETH_HEADER_SIZE - skb_headroom(skb));
+		QETH_DBF_TEXT3(0, trace, "NHRp");
+		QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%2x%2x%2x%2x", skb_headroom(skb),
+			version, multicast, queue);
+		QETH_DBF_TEXT3(0, trace, dbf_text);
+		QETH_DBF_HEX3(0, trace, &skb->head, sizeof (void *));
+		QETH_DBF_HEX3(0, trace, &skb->data, sizeof (void *));
+		nskb = skb_realloc_headroom(skb, QETH_HEADER_SIZE);
+		if (!nskb) {
+			PRINT_WARN("%s: could not realloc headroom\n",
+				   card->dev_name);
+			QETH_DBF_TEXT2(0, trace, "CNRp");
+			QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+			dev_kfree_skb_irq(skb);
+			return;
+		}
+		dev_kfree_skb_irq(skb);
+		skb = nskb;
+	}
+	__qeth_add_vlan_tag(card, skb, version);
+	hdr = (struct qeth_hdr *) (skb_push(skb, QETH_HEADER_SIZE));
+
+	length = skb->len;
+
+	/* 
+	 * sanity check, the Linux memory allocation scheme should
+	 * never present us cases like this one (the 32bytes header plus
+	 * the first 40 bytes of the paket cross a 4k boundary)
+	 */
+	dataptr = (char *) hdr;
+	if ((((unsigned long) dataptr) & (~(PAGE_SIZE - 1))) !=
+	    (((unsigned long) dataptr + QETH_HEADER_SIZE +
+	      QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
+		PRINT_ERR("%s: packet misaligned -- the first %i bytes "
+			  "are not in the same page. Discarding packet!\n",
+			  card->dev_name,
+			  QETH_HEADER_SIZE + QETH_IP_HEADER_SIZE);
+		QETH_DBF_TEXT1(0, trace, "PMAp");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%2x%2x%2x%2x", skb_headroom(skb),
+			version, multicast, queue);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_HEX1(0, trace, &skb->head, sizeof (void *));
+		QETH_DBF_HEX1(1, trace, &skb->data, sizeof (void *));
+		dev_kfree_skb_irq(skb);
+		return;
+	}
+
+	buffer_no = card->outbound_first_free_buffer[queue];
+
+	element_to_fill = card->outbound_ringbuffer[queue]->
+	    ringbuf_element[buffer_no].next_element_to_fill;
+
+	elements_needed = 1 + (((((unsigned long) dataptr) & (PAGE_SIZE - 1)) +
+				length) >> PAGE_SHIFT);
+	if ((elements_needed > (QDIO_MAX_ELEMENTS_PER_BUFFER - element_to_fill))
+	    ||
+	    ((elements_needed ==
+	      (QDIO_MAX_ELEMENTS_PER_BUFFER - element_to_fill))
+	     && ((element_to_fill >> PAGE_SHIFT) ==
+		 card->outbound_bytes_in_buffer[queue]))) {
+		qeth_flush_packed_packets(card, queue, 0);
+		element_to_fill = 0;
+		card->outbound_bytes_in_buffer[queue] = 0;
+		buffer_no = (buffer_no + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1);
+	}
+
+	if (!element_to_fill)
+		card->outbound_buffer_send_state[queue][buffer_no]
+		    = SEND_STATE_PACK;
+
+#ifdef QETH_PERFORMANCE_STATS
+	card->perf_stats.skbs_sent_pack++;
+#endif /* QETH_PERFORMANCE_STATS */
+
+	mybuffer =
+	    &card->outbound_ringbuffer[queue]->ringbuf_element[buffer_no];
+	atomic_inc(&skb->users);
+	skb_queue_tail(&mybuffer->skb_list, skb);
+	qeth_fill_header(hdr, skb, version, multicast);
+	card->outbound_bytes_in_buffer[queue] += length + QETH_HEADER_SIZE;
+	card->outbound_ringbuffer[queue]->ringbuf_element[buffer_no].
+	    next_element_to_fill =
+	    qeth_fill_buffer(&card->outbound_ringbuffer[queue]->
+			     buffer[buffer_no],
+			     dataptr, length, element_to_fill);
+}
+
+static void
+qeth_alloc_spare_bufs(void)
+{
+	int i;
+	int dont_alloc_more = 0;
+	char dbf_text[15];
+
+	sparebuffer_count = 0;
+	for (i = 0; i < qeth_sparebufs; i++) {
+		if (!dont_alloc_more) {
+			sparebufs[i].buf = (char *)
+			    kmalloc(DEFAULT_BUFFER_SIZE, GFP_KERNEL);
+			if (sparebufs[i].buf)
+				sparebuffer_count++;
+			else
+				dont_alloc_more = 1;
+		}
+		atomic_set(&sparebufs[i].status, (dont_alloc_more) ?
+			   SPAREBUF_UNAVAIL : SPAREBUF_FREE);
+	}
+	sprintf(dbf_text, "alspb%3x", sparebuffer_count);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+
+	PRINT_INFO("allocated %i spare buffers\n", sparebuffer_count);
+}
+
+static void
+qeth_free_all_spare_bufs(void)
+{
+	int i;
+
+	QETH_DBF_TEXT2(0, trace, "frealspb");
+
+	for (i = 0; i < qeth_sparebufs; i++)
+		if (atomic_read(&sparebufs[i].status) != SPAREBUF_UNAVAIL) {
+			kfree(sparebufs[i].buf);
+			atomic_set(&sparebufs[i].status, SPAREBUF_UNAVAIL);
+		}
+}
+
+static __inline__ int
+atomic_return_sub(int i, atomic_t * v)
+{
+	int old_val, new_val;
+	__CS_LOOP(old_val, new_val, v, i, "sr");
+	return old_val;
+}
+
+static inline void
+__qeth_dump_packet_info(struct qeth_card *card, int version, int multicast,
+			int queue)
+{
+	char dbf_text[15];
+
+	QETH_DBF_TEXT6(0, trace, "dsp:");
+	QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "%c %c%4x",
+		(version == 4) ? '4' : ((version == 6) ? '6' : '0'),
+		(multicast) ? 'm' : '_', queue);
+	QETH_DBF_TEXT6(0, trace, dbf_text);
+	sprintf(dbf_text, "%4x%4x",
+		card->outbound_first_free_buffer[queue],
+		atomic_read(&card->outbound_used_buffers[queue]));
+	QETH_DBF_TEXT6(0, trace, dbf_text);
+	if (qeth_sbal_packing_on_card(card->type)) {
+		switch (card->send_state[queue]) {
+		case SEND_STATE_DONT_PACK:
+			QETH_DBF_TEXT6(0, trace, "usngfast");
+			break;
+		case SEND_STATE_PACK:
+			QETH_DBF_TEXT6(0, trace, "usngpack");
+			break;
+		}
+	} else {
+		QETH_DBF_TEXT6(0, trace, "usngfast");
+	}
+}
+
+static inline void
+__qeth_switch_state_if_needed(struct qeth_card *card, int queue)
+{
+	if (atomic_read(&card->outbound_used_buffers[queue])
+	    >= HIGH_WATERMARK_PACK) {
+		card->send_state[queue] = SEND_STATE_PACK;
+		QETH_DBF_TEXT3(0, trace, "stchup");
+		QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+#ifdef QETH_PERFORMANCE_STATS
+		card->perf_stats.sc_dp_p++;
+#endif /* QETH_PERFORMANCE_STATS */
+	}
+}
+
+static int
+qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb,
+		    struct net_device *dev)
+{
+	int queue, result = 0;
+	int multicast, version;
+
+	version = QETH_IP_VERSION(skb);
+	multicast = qeth_is_multicast_skb_at_all(skb, version);
+	queue = qeth_get_prioqueue(card, skb, multicast, version);
+
+	__qeth_dump_packet_info(card, version, multicast, queue);
+
+	if (atomic_read(&card->outbound_used_buffers[queue])
+	    >= QDIO_MAX_BUFFERS_PER_Q - 1) {
+		QETH_DBF_TEXT2(1, trace, "cdbs");
+		QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id);
+		netif_stop_queue(dev);
+		return -EBUSY;
+	}
+
+	/* 
+	 * we are not called under int, so we just spin
+	 * happens around once a second under heavy traffic. takes a little
+	 * bit less than 10usec in avg. on a z900
+	 */
+	if (atomic_compare_and_swap(QETH_LOCK_UNLOCKED, QETH_LOCK_NORMAL,
+				    &card->outbound_ringbuffer_lock[queue])) {
+		QETH_DBF_TEXT2(0, trace, "SPIN");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		while (atomic_compare_and_swap
+		       (QETH_LOCK_UNLOCKED, QETH_LOCK_NORMAL,
+			&card->outbound_ringbuffer_lock[queue])) ;
+		QETH_DBF_TEXT2(0, trace, "spin");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	}
+#ifdef QETH_PERFORMANCE_STATS
+	card->perf_stats.skbs_sent++;
+#endif /* QETH_PERFORMANCE_STATS */
+
+	if (qeth_sbal_packing_on_card(card->type)) {
+		switch (card->send_state[queue]) {
+		case SEND_STATE_DONT_PACK:
+			qeth_send_packet_fast(card, skb, dev, queue,
+					      version, multicast);
+			__qeth_switch_state_if_needed(card, queue);
+			break;
+		case SEND_STATE_PACK:
+			qeth_send_packet_packed(card, skb, dev, queue,
+						version, multicast);
+			break;
+		default:
+			result = -EBUSY;
+			QETH_DBF_TEXT0(1, trace, "UPSs");
+			QETH_DBF_TEXT0(1, trace, card->rdev->dev.bus_id);
+			PRINT_ALL("oops... shouldn't happen (line %i:%i).\n",
+				  __LINE__, card->send_state[queue]);
+		}
+	} else {
+		qeth_send_packet_fast(card, skb, dev, queue,
+				      version, multicast);
+	}
+
+	/* ATOMIC: (NORMAL->UNLOCKED, FLUSH->NORMAL) */
+	while (atomic_dec_return(&card->outbound_ringbuffer_lock[queue])) {
+		qeth_flush_buffer(card, queue, 0);
+		card->send_state[queue] = SEND_STATE_DONT_PACK;
+	}
+#ifdef QETH_PERFORMANCE_STATS
+	card->perf_stats.outbound_time +=
+	    NOW - card->perf_stats.outbound_start_time;
+	card->perf_stats.outbound_cnt++;
+#endif /* QETH_PERFORMANCE_STATS */
+
+	card->stats->tx_packets++;
+	card->stats->tx_bytes += skb->len;
+
+	return result;
+}
+
+static int
+qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct qeth_card *card;
+	int result;
+
+	card = (struct qeth_card *) (dev->priv);
+
+	if (skb == NULL)
+		return 0;
+
+	QETH_DBF_HEX4(0, data, skb->data, __max(QETH_DBF_DATA_LEN, skb->len));
+
+	netif_stop_queue(dev);
+
+	if (!card) {
+		QETH_DBF_TEXT2(0, trace, "XMNSNOCD");
+		dst_link_failure(skb);
+		dev_kfree_skb_irq(skb);
+		return 0;
+	}
+#ifdef QETH_PERFORMANCE_STATS
+	card->perf_stats.outbound_start_time = NOW;
+#endif /* QETH_PERFORMANCE_STATS */
+
+	if (!atomic_read(&card->is_startlaned)) {
+		card->stats->tx_carrier_errors++;
+		QETH_DBF_TEXT2(0, trace, "XMNS");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		dst_link_failure(skb);
+		dev_kfree_skb_irq(skb);
+		return 0;
+	}
+
+	result = qeth_do_send_packet(card, skb, dev);
+
+	if (!result)
+		netif_wake_queue(card->dev);
+
+	return result;
+}
+
+static struct net_device_stats *
+qeth_get_stats(struct net_device *dev)
+{
+	struct qeth_card *card;
+
+	card = (struct qeth_card *) (dev->priv);
+
+	QETH_DBF_TEXT3(0, trace, "gtst");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	return card->stats;
+}
+
+static int
+qeth_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct qeth_card *card;
+	char dbf_text[15];
+
+	card = (struct qeth_card *) (dev->priv);
+
+	QETH_DBF_TEXT2(0, trace, "mtu");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "%8x", new_mtu);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+
+	if (new_mtu < 64)
+		return -EINVAL;
+	if (new_mtu > 65535)
+		return -EINVAL;
+	if ((!qeth_is_supported(IPA_IP_FRAGMENTATION)) &&
+	    (!qeth_mtu_is_valid(card, new_mtu)))
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+static void
+qeth_start_softsetup_thread(struct qeth_card *card)
+{
+	if (!atomic_read(&card->shutdown_phase)) {
+		QETH_DBF_TEXT2(0, trace, "stss");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		up(&card->softsetup_thread_sem);
+	}
+}
+
+static int
+qeth_sleepon(struct qeth_card *card, int timeout)
+{
+	unsigned long flags;
+	unsigned long start;
+	int retval;
+	char dbf_text[15];
+
+	DECLARE_WAITQUEUE(current_wait_q, current);
+
+	QETH_DBF_TEXT5(0, trace, "slpn");
+	QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "%08x", timeout);
+	QETH_DBF_TEXT5(0, trace, dbf_text);
+
+	add_wait_queue(&card->wait_q, &current_wait_q);
+	atomic_set(&card->wait_q_active, 1);
+	start = qeth_get_millis();
+	for (;;) {
+		set_task_state(current, TASK_INTERRUPTIBLE);
+		if (atomic_read(&card->data_has_arrived)) {
+			atomic_set(&card->data_has_arrived, 0);
+			retval = 0;
+			goto out;
+		}
+		if (qeth_get_millis() - start > timeout) {
+			retval = -ETIME;
+			goto out;
+		}
+		schedule_timeout(((start + timeout -
+				   qeth_get_millis()) >> 10) * HZ);
+	}
+out:
+	spin_lock_irqsave(&card->wait_q_lock, flags);
+	atomic_set(&card->wait_q_active, 0);
+	spin_unlock_irqrestore(&card->wait_q_lock, flags);
+
+	/* we've got to check once again to close the window */
+	if (atomic_read(&card->data_has_arrived)) {
+		atomic_set(&card->data_has_arrived, 0);
+		retval = 0;
+	}
+
+	set_task_state(current, TASK_RUNNING);
+	remove_wait_queue(&card->wait_q, &current_wait_q);
+
+	return retval;
+}
+
+static void
+qeth_wakeup_ioctl(struct qeth_card *card)
+{
+
+	QETH_DBF_TEXT5(0, trace, "wkup");
+	QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+
+	atomic_set(&card->ioctl_data_has_arrived, 1);
+	spin_lock(&card->ioctl_wait_q_lock);
+	if (atomic_read(&card->ioctl_wait_q_active)) {
+		wake_up(&card->ioctl_wait_q);
+	}
+	spin_unlock(&card->ioctl_wait_q_lock);
+}
+
+static int
+qeth_sleepon_ioctl(struct qeth_card *card, int timeout)
+{
+	unsigned long flags;
+	unsigned long start;
+	int retval;
+	char dbf_text[15];
+
+	DECLARE_WAITQUEUE(current_wait_q, current);
+
+	QETH_DBF_TEXT5(0, trace, "ioctlslpn");
+	QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "%08x", timeout);
+	QETH_DBF_TEXT5(0, trace, dbf_text);
+
+	add_wait_queue(&card->ioctl_wait_q, &current_wait_q);
+	atomic_set(&card->ioctl_wait_q_active, 1);
+	start = qeth_get_millis();
+	for (;;) {
+		set_task_state(current, TASK_INTERRUPTIBLE);
+		if (atomic_read(&card->ioctl_data_has_arrived)) {
+			atomic_set(&card->ioctl_data_has_arrived, 0);
+			retval = 0;
+			goto out;
+		}
+		if (qeth_get_millis() - start > timeout) {
+			retval = -ETIME;
+			goto out;
+		}
+		schedule_timeout(((start + timeout -
+				   qeth_get_millis()) >> 10) * HZ);
+	}
+out:
+	spin_lock_irqsave(&card->ioctl_wait_q_lock, flags);
+	atomic_set(&card->ioctl_wait_q_active, 0);
+	spin_unlock_irqrestore(&card->ioctl_wait_q_lock, flags);
+
+	/* we've got to check once again to close the window */
+	if (atomic_read(&card->ioctl_data_has_arrived)) {
+		atomic_set(&card->ioctl_data_has_arrived, 0);
+		retval = 0;
+	}
+
+	set_task_state(current, TASK_RUNNING);
+	remove_wait_queue(&card->ioctl_wait_q, &current_wait_q);
+
+	return retval;
+}
+
+/*SNMP IOCTL on Procfile */
+
+static void
+qeth_wakeup_procfile(void)
+{
+	QETH_DBF_TEXT5(0, trace, "procwkup");
+	if (atomic_read(&qeth_procfile_ioctl_sem.count) <
+	    PROCFILE_SLEEP_SEM_MAX_VALUE)
+		up(&qeth_procfile_ioctl_sem);
+}
+
+static int
+qeth_sleepon_procfile(void)
+{
+	QETH_DBF_TEXT5(0, trace, "procslp");
+	if (down_interruptible(&qeth_procfile_ioctl_sem)) {
+		up(&qeth_procfile_ioctl_sem);
+		return -ERESTARTSYS;
+	}
+	return 0;
+}
+
+/* SNMP END */
+
+static char *
+qeth_send_control_data(struct qeth_card *card, unsigned char *buffer,
+		       int len, unsigned long intparam)
+{
+	unsigned long flags;
+	int result, result2;
+	char dbf_text[15];
+	unsigned char *rec_buf;
+	int setip = (intparam & IPA_SETIP_FLAG) ? 1 : 0;
+
+again:
+	if (atomic_read(&card->shutdown_phase) == QETH_REMOVE_CARD_QUICK)
+		return NULL;
+	if (atomic_read(&card->escape_softsetup))
+		return NULL;
+
+	/* we lock very early to synchronize access to seqnos */
+	if (atomic_swap(&card->write_busy, 1)) {
+		qeth_wait_nonbusy(QETH_IDLE_WAIT_TIME);
+		QETH_DBF_TEXT2(0, trace, "LSCD");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		goto again;
+	}
+	memcpy(card->dma_stuff->sendbuf, card->send_buf, QETH_BUFSIZE);
+
+	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(buffer),
+	       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+	card->seqno.trans_hdr++;
+
+	memcpy(QETH_PDU_HEADER_SEQ_NO(buffer),
+	       &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+	card->seqno.pdu_hdr++;
+	memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(buffer),
+	       &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+
+	/* there is noone doing this except sleep and this function */
+	atomic_set(&card->data_has_arrived, 0);
+
+	memcpy(&card->dma_stuff->write_ccw, WRITE_CCW, sizeof (struct ccw1));
+	card->dma_stuff->write_ccw.count = len;
+	card->dma_stuff->write_ccw.cda =
+	    QETH_GET_ADDR(card->dma_stuff->sendbuf);
+
+	QETH_DBF_TEXT2(0, trace, "scdw");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "%8x", len);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+	QETH_DBF_HEX4(0, trace, &intparam, QETH_DBF_TRACE_LEN);
+	QETH_DBF_HEX2(0, control, buffer, QETH_DBF_CONTROL_LEN);
+
+	spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags);
+	result = ccw_device_start(card->wdev, &card->dma_stuff->write_ccw,
+				  intparam, 0, 0);
+	if (result) {
+		qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO);
+		result2 = ccw_device_start(card->wdev,
+					   &card->dma_stuff->write_ccw,
+					   intparam, 0, 0);
+		if (result2 != -ENODEV)
+			PRINT_WARN("qeth_send_control_data: do_IO "
+				   "returned %i, next try returns %i\n",
+				   result, result2);
+		result = result2;
+	}
+	spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags);
+
+	if (result) {
+		QETH_DBF_TEXT2(0, trace, "scd:doio");
+		sprintf(dbf_text, "%4x", (__s16) result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		return NULL;
+	}
+
+	if (intparam == IPA_IOCTL_STATE) {
+		if (qeth_sleepon_ioctl(card, QETH_IPA_TIMEOUT)) {
+			QETH_DBF_TEXT2(0, trace, "scd:ioctime");
+			/* re-enable qeth_send_control_data again */
+			atomic_set(&card->write_busy, 0);
+			return NULL;
+		}
+		rec_buf = card->ipa_buf;
+		QETH_DBF_TEXT2(0, trace, "scro");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	} else {
+		if (qeth_sleepon(card, (setip) ? QETH_IPA_TIMEOUT :
+				 QETH_MPC_TIMEOUT)) {
+			QETH_DBF_TEXT2(0, trace, "scd:time");
+			/* re-enable qeth_send_control_data again */
+			atomic_set(&card->write_busy, 0);
+			return NULL;
+		}
+		rec_buf = card->ipa_buf;
+		QETH_DBF_TEXT2(0, trace, "scri");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	}
+	QETH_DBF_HEX2(0, control, rec_buf, QETH_DBF_CONTROL_LEN);
+
+	memcpy(&card->seqno.pdu_hdr_ack,
+	       QETH_PDU_HEADER_SEQ_NO(rec_buf), QETH_SEQ_NO_LENGTH);
+
+	return rec_buf;
+}
+
+static int
+qeth_send_ipa_cmd(struct qeth_card *card, struct ipa_cmd *cmd, int update_cmd,
+		  int ipatype)
+{
+	unsigned char *buffer;
+	struct ipa_cmd *reply;
+	int ipa_cmd;
+	int result;
+
+	/* don't muck around with ipv6 if there's no use to do so */
+	if ((cmd->prot_version == 6) && (!qeth_is_supported(IPA_IPv6)))
+		return 0;
+
+	ipa_cmd = cmd->command;
+
+	memcpy(card->send_buf, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+
+	memcpy(QETH_IPA_CMD_DEST_ADDR(card->send_buf),
+	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+
+	memcpy(card->send_buf + IPA_PDU_HEADER_SIZE,
+	       cmd, sizeof (struct ipa_cmd));
+
+	buffer = qeth_send_control_data(card, card->send_buf,
+					IPA_PDU_HEADER_SIZE +
+					sizeof (struct ipa_cmd), ipatype);
+
+	if (!buffer) {
+		if (atomic_read(&card->escape_softsetup))
+			result = 0;
+		else
+			result = -1;
+	} else {
+		reply = (struct ipa_cmd *) PDU_ENCAPSULATION(buffer);
+		if ((update_cmd) && (reply))
+			memcpy(cmd, reply, sizeof (struct ipa_cmd));
+		result = reply->return_code;
+
+		/* some special sausages: */
+		if ((ipa_cmd == IPA_CMD_SETASSPARMS) && (result == 0)) {
+			result = reply->data.setassparms.return_code;
+		}
+		if ((ipa_cmd == IPA_CMD_SETADAPTERPARMS) && (result == 0)) {
+			result = reply->data.setadapterparms.return_code;
+		}
+	}
+	return result;
+}
+
+static void
+qeth_fill_ipa_cmd(struct qeth_card *card, struct ipa_cmd *cmd,
+		  __u8 command, int ip_vers)
+{
+	memset(cmd, 0, sizeof (struct ipa_cmd));
+	cmd->command = command;
+	cmd->initiator = INITIATOR_HOST;
+	cmd->seq_no = card->seqno.ipa++;
+	cmd->adapter_type = qeth_get_adapter_type_for_ipa(card->link_type);
+	cmd->rel_adapter_no = (__u8) card->options.portno;
+	cmd->prim_version_no = 1;
+	cmd->param_count = 1;
+	cmd->prot_version = ip_vers;
+	cmd->ipa_supported = 0;
+	cmd->ipa_enabled = 0;
+}
+
+static int
+qeth_send_startstoplan(struct qeth_card *card, __u8 ipacmd, __u16 ip_vers)
+{
+	struct ipa_cmd cmd;
+	int result;
+
+	qeth_fill_ipa_cmd(card, &cmd, ipacmd, 0);
+	cmd.param_count = 0;
+	cmd.prot_version = ip_vers;
+	cmd.ipa_supported = 0;
+	cmd.ipa_enabled = 0;
+
+	result = qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE);
+	return result;
+}
+
+static int
+qeth_send_startlan(struct qeth_card *card, __u16 ip_vers)
+{
+	int result;
+	char dbf_text[15];
+
+	QETH_DBF_TEXT4(0, trace, "stln");
+	QETH_DBF_TEXT4(0, trace, card->rdev->dev.bus_id);
+
+	result = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, ip_vers);
+	if (!result)
+		atomic_set(&card->is_startlaned, 1);
+
+	if (result) {
+		QETH_DBF_TEXT2(0, trace, "STRTLNFL");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+	}
+
+	return result;
+}
+
+static int
+qeth_send_stoplan(struct qeth_card *card)
+{
+#ifdef QETH_SEND_STOPLAN_ON_SHUTDOWN
+	int result;
+	char dbf_text[15];
+
+	atomic_set(&card->is_startlaned, 0);
+
+	QETH_DBF_TEXT4(0, trace, "spln");
+	QETH_DBF_TEXT4(0, trace, card->rdev->dev.bus_id);
+
+	result = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, 4);
+
+	if (result) {
+		QETH_DBF_TEXT2(0, trace, "STPLNFLD");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+	}
+
+	return result;
+#else /* QETH_SEND_STOPLAN_ON_SHUTDOWN */
+	return 0;
+#endif /* QETH_SEND_STOPLAN_ON_SHUTDOWN */
+}
+
+static int
+qeth_send_qipassist(struct qeth_card *card, short ip_vers)
+{
+	struct ipa_cmd cmd;
+	int result;
+
+	qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_QIPASSIST, ip_vers);
+
+	result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE);
+
+	if (!result) {
+		if (ip_vers == 4) {
+			card->ipa_supported = cmd.ipa_supported;
+			card->ipa_enabled = cmd.ipa_enabled;
+		} else {
+			card->ipa6_supported = cmd.ipa_supported;
+			card->ipa6_enabled = cmd.ipa_enabled;
+		}
+	}
+
+	return result;
+}
+
+/* QUERY ARP FUNCTIONS */
+
+static int
+qeth_send_ipa_arpcmd(struct qeth_card *card, struct arp_cmd *cmd,
+		     int update_cmd, int ipatype, __u32 req_size)
+{
+	unsigned char *buffer;
+	int ipa_cmd;
+	int result;
+	__u16 s1, s2;
+
+	/* don't muck around with ipv6 if there's no use to do so */
+	if ((cmd->prot_version == 6) && (!qeth_is_supported(IPA_IPv6)))
+		return 0;
+	result = 0;
+	ipa_cmd = cmd->command;
+
+	memcpy(card->send_buf, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+	memcpy(QETH_IPA_CMD_DEST_ADDR(card->send_buf),
+	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(card->send_buf + IPA_PDU_HEADER_SIZE,
+	       cmd, sizeof (struct arp_cmd));
+
+	if (req_size) {
+		/* adjust sizes for big requests */
+		s1 = (__u32) IPA_PDU_HEADER_SIZE + SNMP_BASE_CMDLENGTH +
+		    req_size;
+		s2 = (__u32) SNMP_BASE_CMDLENGTH + req_size;
+		memcpy(QETH_IPA_PDU_LEN_TOTAL(card->send_buf), &s1, 2);
+		memcpy(QETH_IPA_PDU_LEN_PDU1(card->send_buf), &s2, 2);
+		memcpy(QETH_IPA_PDU_LEN_PDU2(card->send_buf), &s2, 2);
+		memcpy(QETH_IPA_PDU_LEN_PDU3(card->send_buf), &s2, 2);
+	}
+
+	buffer = qeth_send_control_data(card, card->send_buf,
+					IPA_PDU_HEADER_SIZE +
+					sizeof (struct arp_cmd), ipatype);
+	if (!buffer)
+		result = -ENODATA;
+	else
+		result = card->ioctl_returncode;
+	return result;
+}
+
+static int
+qeth_ioctl_handle_snmp_data(struct qeth_card *card, struct arp_cmd *reply)
+{
+	__u16 data_len;
+
+#define SNMP_HEADER_SIZE_WITH_TOKEN 36
+
+ 	data_len = *((__u16*)QETH_IPA_PDU_LEN_PDU1(card->dma_stuff->recbuf));
+	if (reply->data.setadapterparms.frame_seq_no == 1)
+		data_len = data_len - 
+			(__u16)((char*)reply->data.setadapterparms.data.
+				snmp_subcommand.snmp_data - (char*)reply); 
+	else
+ 		data_len = data_len - 
+ 		 	(__u16)((char*)&reply->data.setadapterparms.data.
+				snmp_subcommand.snmp_request - (char*)reply);
+
+	if (reply->data.setadapterparms.frame_seq_no == 1) {
+
+		if (card->ioctl_buffersize <= (SNMP_HEADER_SIZE_WITH_TOKEN +
+					       reply->data.setadapterparms.
+					       frames_used_total *
+					       ARP_DATA_SIZE)) {
+
+			card->ioctl_returncode = ARP_RETURNCODE_ERROR;
+			reply->data.setadapterparms.data.snmp_subcommand.
+			    snmp_returncode = -ENOMEM;
+		} else {
+			card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
+			card->number_of_entries = 0;
+ 			memcpy(((char *)card->ioctl_data_buffer),
+			       reply->data.setadapterparms.snmp_token,
+			       SNMP_HEADER_SIZE_WITH_TOKEN);
+ 			card->ioctl_buffer_pointer = card->ioctl_data_buffer+
+				SNMP_HEADER_SIZE_WITH_TOKEN;
+		}
+	}
+
+	if (card->ioctl_returncode != ARP_RETURNCODE_ERROR &&
+	    reply->data.setadapterparms.frame_seq_no <=
+	    reply->data.setadapterparms.frames_used_total) {
+
+		if (reply->data.setadapterparms.return_code ==
+		    IPA_REPLY_SUCCESS) {
+
+ 			if (reply->data.setadapterparms.frame_seq_no == 1)
+ 				memcpy(card->ioctl_buffer_pointer,
+				       reply->data.setadapterparms.data.
+				       snmp_subcommand.snmp_data, data_len);
+			else
+ 				memcpy(card->ioctl_buffer_pointer,
+				       (char*)&reply->data.setadapterparms.
+				       data.snmp_subcommand.snmp_request,
+				       data_len);
+
+			card->ioctl_buffer_pointer =
+			    card->ioctl_buffer_pointer + data_len;
+			card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
+
+			if (reply->data.setadapterparms.frame_seq_no ==
+			    reply->data.setadapterparms.frames_used_total) {
+				card->ioctl_returncode =
+				    ARP_RETURNCODE_LASTREPLY;
+			}
+		} else {
+			card->ioctl_returncode = ARP_RETURNCODE_ERROR;
+			memset(card->ioctl_data_buffer, 0,
+			       card->ioctl_buffersize);
+			reply->data.setadapterparms.data.snmp_subcommand.
+			    snmp_returncode =
+			    reply->data.setadapterparms.return_code;
+		}
+	}
+#undef  SNMP_HEADER_SIZE_WITH_TOKEN
+
+	return card->ioctl_returncode;
+}
+
+static int
+qeth_ioctl_handle_arp_data(struct qeth_card *card, struct arp_cmd *reply)
+{
+
+	if (reply->data.setassparms.seq_no == 1) {
+		if (card->ioctl_buffersize <=
+		    (sizeof (__u16) + sizeof (int) +
+		     reply->data.setassparms.number_of_replies *
+		     ARP_DATA_SIZE)) {
+
+			card->ioctl_returncode = ARP_RETURNCODE_ERROR;
+
+		} else {
+			card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
+			card->number_of_entries = 0;
+			card->ioctl_buffer_pointer =
+			    card->ioctl_data_buffer + sizeof (__u16) +
+			    sizeof (int);
+		}
+	}
+
+	if (card->ioctl_returncode != ARP_RETURNCODE_ERROR &&
+	    reply->data.setassparms.seq_no <=
+	    reply->data.setassparms.number_of_replies) {
+
+		if (reply->data.setassparms.return_code == IPA_REPLY_SUCCESS) {
+
+			card->number_of_entries = card->number_of_entries +
+			    reply->data.setassparms.
+			    data.queryarp_data.number_of_entries;
+			memcpy(card->ioctl_buffer_pointer,
+			       reply->data.setassparms.data.queryarp_data.
+			       arp_data, ARP_DATA_SIZE);
+			card->ioctl_buffer_pointer = card->
+			    ioctl_buffer_pointer + ARP_DATA_SIZE;
+			card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
+			if (reply->data.setassparms.seq_no ==
+			    reply->data.setassparms.number_of_replies) {
+				memcpy(card->ioctl_data_buffer,
+				       &reply->data.setassparms.data.
+				       queryarp_data.osa_setbitmask,
+				       sizeof (__u16));
+				card->ioctl_returncode =
+				    ARP_RETURNCODE_LASTREPLY;
+			}
+		} else {
+
+			card->ioctl_returncode = ARP_RETURNCODE_ERROR;
+			memset(card->ioctl_data_buffer, 0,
+			       card->ioctl_buffersize);
+		}
+	}
+	return card->ioctl_returncode;
+}
+
+static int
+qeth_look_for_arp_data(struct qeth_card *card)
+{
+	struct arp_cmd *reply;
+	int result;
+
+	reply = (struct arp_cmd *) PDU_ENCAPSULATION(card->dma_stuff->recbuf);
+
+	if ((reply->command == IPA_CMD_SETASSPARMS) &&
+	    (reply->data.setassparms.assist_no == IPA_ARP_PROCESSING) &&
+	    (reply->data.setassparms.command_code ==
+	     IPA_CMD_ASS_ARP_FLUSH_CACHE)) {
+		result = ARP_FLUSH;
+	} else if ((reply->command == IPA_CMD_SETASSPARMS) &&
+		   (reply->data.setassparms.assist_no == IPA_ARP_PROCESSING) &&
+		   (reply->data.setassparms.command_code ==
+		    IPA_CMD_ASS_ARP_QUERY_INFO) &&
+		   (card->ioctl_returncode == ARP_RETURNCODE_SUCCESS)) {
+
+		result = qeth_ioctl_handle_arp_data(card, reply);
+
+	} else if ((reply->command == IPA_CMD_SETADAPTERPARMS) &&
+		   (reply->data.setadapterparms.command_code ==
+		    IPA_SETADP_SET_SNMP_CONTROL) &&
+		   (card->ioctl_returncode == ARP_RETURNCODE_SUCCESS)) {
+
+		result = qeth_ioctl_handle_snmp_data(card, reply);
+	} else
+		result = ARP_RETURNCODE_NOARPDATA;
+
+	return result;
+}
+
+static int
+qeth_queryarp(struct qeth_card *card, struct ifreq *req, int version,
+	      __u32 assist_no, __u16 command_code, char *c_data, __u16 len)
+{
+	int data_size;
+	struct arp_cmd *cmd;
+	int result;
+
+	cmd = (struct arp_cmd *) kmalloc(sizeof (struct arp_cmd), GFP_KERNEL);
+	if (!cmd) {
+		return IPA_REPLY_FAILED;
+	}
+
+	memcpy(&data_size, c_data, sizeof (int));
+
+	qeth_fill_ipa_cmd(card, (struct ipa_cmd *) cmd, IPA_CMD_SETASSPARMS,
+			  version);
+
+	cmd->data.setassparms.assist_no = assist_no;
+	cmd->data.setassparms.length = 8 + len;
+	cmd->data.setassparms.command_code = command_code;
+	cmd->data.setassparms.return_code = 0;
+	cmd->data.setassparms.seq_no = 0;
+
+	card->ioctl_buffersize = data_size;
+	card->ioctl_data_buffer = (char *) vmalloc(data_size);
+	if (!card->ioctl_data_buffer) {
+		kfree(cmd);
+		return IPA_REPLY_FAILED;
+	}
+
+	card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
+
+	result = qeth_send_ipa_arpcmd(card, cmd, 1, IPA_IOCTL_STATE, 0);
+
+	if ((result == ARP_RETURNCODE_ERROR) || (result == -ENODATA)) {
+		result = IPA_REPLY_FAILED;
+	} else {
+		result = IPA_REPLY_SUCCESS;
+		memcpy(((char *) (card->ioctl_data_buffer)) + sizeof (__u16),
+		       &(card->number_of_entries), sizeof (int));
+		copy_to_user(req->ifr_ifru.ifru_data,
+			     card->ioctl_data_buffer, data_size);
+	}
+	card->ioctl_buffer_pointer = NULL;
+	vfree(card->ioctl_data_buffer);
+	kfree(cmd);
+	card->number_of_entries = 0;
+	card->ioctl_buffersize = 0;
+
+	return result;
+}
+
+static int
+snmp_set_setadapterparms_command(struct qeth_card *card,
+				 struct arp_cmd *cmd, struct ifreq *req,
+				 char *data, __u16 len,
+				 __u16 command_code, int req_size)
+{
+	__u32 data_size;
+
+	memcpy(&data_size, data, sizeof (__u32));
+
+	card->ioctl_buffersize = data_size;
+	card->ioctl_data_buffer = (char *) vmalloc(data_size);
+	if (!card->ioctl_data_buffer) {
+		return -ENOMEM;
+	}
+	card->ioctl_returncode = ARP_RETURNCODE_SUCCESS;
+
+	memcpy(cmd->data.setadapterparms.snmp_token,
+	       data + SNMP_REQUEST_DATA_OFFSET, req_size);
+
+	cmd->data.setadapterparms.cmdlength = SNMP_SETADP_CMDLENGTH + req_size;
+	cmd->data.setadapterparms.command_code = command_code;
+	cmd->data.setadapterparms.frames_used_total = 1;
+	cmd->data.setadapterparms.frame_seq_no = 1;
+
+	return 0;
+}
+static int
+qeth_send_snmp_control(struct qeth_card *card, struct ifreq *req,
+		       __u32 command, __u16 command_code,
+		       char *c_data, __u16 len)
+{
+	struct arp_cmd *cmd;
+	__u32 result, req_size;
+
+	cmd = (struct arp_cmd *) kmalloc(sizeof (struct arp_cmd), GFP_KERNEL);
+	if (!cmd) {
+		return IPA_REPLY_FAILED;
+	}
+
+	qeth_fill_ipa_cmd(card, (struct ipa_cmd *) cmd, command, 4);
+
+	memcpy(&req_size, ((char *) c_data) + sizeof (__u32), sizeof (__u32));
+
+	if (snmp_set_setadapterparms_command(card, cmd, req, c_data,
+					     len, command_code, req_size)) {
+		kfree(cmd);
+		return IPA_REPLY_FAILED;
+	}
+
+	result = qeth_send_ipa_arpcmd(card, cmd, 1, IPA_IOCTL_STATE, req_size);
+
+	if (result == -ENODATA) {
+		result = IPA_REPLY_FAILED;
+		goto snmp_out;
+	}
+	if (result == ARP_RETURNCODE_ERROR) {
+		copy_to_user(req->ifr_ifru.ifru_data + SNMP_REQUEST_DATA_OFFSET,
+			     card->ioctl_data_buffer, card->ioctl_buffersize);
+		result = IPA_REPLY_FAILED;
+	} else {
+		copy_to_user(req->ifr_ifru.ifru_data + SNMP_REQUEST_DATA_OFFSET,
+			     card->ioctl_data_buffer, card->ioctl_buffersize);
+		result = IPA_REPLY_SUCCESS;
+	}
+snmp_out:
+	card->number_of_entries = 0;
+	card->ioctl_buffersize = 0;
+	card->ioctl_buffer_pointer = NULL;
+	vfree(card->ioctl_data_buffer);
+	kfree(cmd);
+
+	return result;
+}
+
+static int
+qeth_send_setassparms(struct qeth_card *card, int version, __u32 assist_no,
+		      __u16 command_code, long data, __u16 len)
+{
+	struct ipa_cmd cmd;
+	int result;
+
+	qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETASSPARMS, version);
+
+	cmd.data.setassparms.assist_no = assist_no;
+	cmd.data.setassparms.length = 8 + len;
+	cmd.data.setassparms.command_code = command_code;
+	cmd.data.setassparms.return_code = 0;
+	cmd.data.setassparms.seq_no = 0;
+
+	if (len <= sizeof (__u32))
+		cmd.data.setassparms.data.flags_32bit = (__u32) data;
+	else if (len > sizeof (__u32))
+		memcpy(&cmd.data.setassparms.data, (void *) data,
+		       qeth_min(len, PAGE_SIZE));
+	if (command_code != IPA_CMD_ASS_START) {
+		result = qeth_send_ipa_cmd(card, &cmd, 0,
+					   ((assist_no == IPA_ARP_PROCESSING) &&
+					    (command_code !=
+					     IPA_CMD_ASS_ARP_FLUSH_CACHE)) ?
+					   IPA_IOCTL_STATE : IPA_CMD_STATE);
+
+	} else
+		result = qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE);
+
+	return result;
+}
+
+static int
+qeth_send_setadapterparms_query(struct qeth_card *card)
+{
+	struct ipa_cmd cmd;
+	int result;
+
+	qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETADAPTERPARMS,
+			  IPA_SETADAPTERPARMS_IP_VERSION);
+	cmd.data.setadapterparms.cmdlength = sizeof (struct ipa_setadp_cmd);
+	cmd.data.setadapterparms.command_code =
+	    IPA_SETADP_QUERY_COMMANDS_SUPPORTED;
+	cmd.data.setadapterparms.frames_used_total = 1;
+	cmd.data.setadapterparms.frame_seq_no = 1;
+	result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE);
+
+	if (cmd.data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f)
+		card->link_type = cmd.data.setadapterparms.data.
+		    query_cmds_supp.lan_type;
+
+	card->adp_supported =
+	    cmd.data.setadapterparms.data.query_cmds_supp.supported_cmds;
+
+	return result;
+}
+
+static int
+qeth_send_setadapterparms_mode(struct qeth_card *card, __u32 command,
+			       __u32 mode)
+{
+
+	struct ipa_cmd cmd;
+	int result;
+
+	qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETADAPTERPARMS,
+			  IPA_SETADAPTERPARMS_IP_VERSION);
+	cmd.data.setadapterparms.cmdlength = sizeof (struct ipa_setadp_cmd);
+	cmd.data.setadapterparms.command_code = command;
+	cmd.data.setadapterparms.frames_used_total = 1;
+	cmd.data.setadapterparms.frame_seq_no = 1;
+	cmd.data.setadapterparms.data.mode = mode;
+	result = qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE);
+
+	return result;
+}
+
+static int
+qeth_send_setadapterparms_change_addr(struct qeth_card *card,
+				      __u32 command,
+				      __u32 subcmd, __u8 * mac_addr,
+				      int addr_len)
+{
+	struct ipa_cmd cmd;
+	int result;
+
+	qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETADAPTERPARMS,
+			  IPA_SETADAPTERPARMS_IP_VERSION);
+	cmd.data.setadapterparms.cmdlength = sizeof (struct ipa_setadp_cmd);
+	cmd.data.setadapterparms.command_code = command;
+	cmd.data.setadapterparms.frames_used_total = 1;
+	cmd.data.setadapterparms.frame_seq_no = 1;
+	cmd.data.setadapterparms.data.change_addr.cmd = subcmd;
+	cmd.data.setadapterparms.data.change_addr.addr_size = addr_len;
+	memcpy(&cmd.data.setadapterparms.data.change_addr.addr,
+	       mac_addr, addr_len);
+
+	result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE);
+
+	memcpy(mac_addr, &cmd.data.setadapterparms.data.change_addr.addr,
+	       addr_len);
+
+	return result;
+}
+
+static int
+qeth_send_setassparms_simple_with_data(struct qeth_card *card,
+				       __u32 assist_no,
+				       __u16 command_code, long data)
+{
+	return qeth_send_setassparms(card, 4, assist_no, command_code, data, 4);
+}
+
+static int
+qeth_send_setassparms_simple_without_data(struct qeth_card *card,
+					  __u32 assist_no, __u16 command_code)
+{
+	return qeth_send_setassparms(card, 4, assist_no, command_code, 0, 0);
+}
+
+static int
+qeth_send_setassparms_simple_without_data6(struct qeth_card *card,
+					   __u32 assist_no, __u16 command_code)
+{
+	return qeth_send_setassparms(card, 6, assist_no, command_code, 0, 0);
+}
+
+static int
+qeth_send_setdelip(struct qeth_card *card, __u8 * ip, __u8 * netmask,
+		   int ipacmd, short ip_vers, unsigned int flags)
+{
+	struct ipa_cmd cmd;
+	int ip_len = (ip_vers == 6) ? 16 : 4;
+
+	qeth_fill_ipa_cmd(card, &cmd, ipacmd, ip_vers);
+
+	if (ip_vers == 6) {
+		memcpy(&cmd.data.setdelip6.ip, ip, ip_len);
+		memcpy(&cmd.data.setdelip6.netmask, netmask, ip_len);
+		cmd.data.setdelip6.flags = flags;
+	} else {
+		memcpy(&cmd.data.setdelip4.ip, ip, ip_len);
+		memcpy(&cmd.data.setdelip4.netmask, netmask, ip_len);
+		cmd.data.setdelip4.flags = flags;
+	}
+
+	return qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE |
+				 ((ipacmd ==
+				   IPA_CMD_SETIP) ? IPA_SETIP_FLAG : 0));
+}
+
+static int
+qeth_send_setdelipm(struct qeth_card *card, __u8 * ip, __u8 * mac,
+		    int ipacmd, short ip_vers)
+{
+	struct ipa_cmd cmd;
+	int ip_len = (ip_vers == 6) ? 16 : 4;
+
+	qeth_fill_ipa_cmd(card, &cmd, ipacmd, ip_vers);
+	memcpy(&cmd.data.setdelipm.mac, mac, 6);
+	if (ip_vers == 6) {
+		memcpy(&cmd.data.setdelipm.ip6, ip, ip_len);
+	} else {
+		memcpy(&cmd.data.setdelipm.ip4_6, ip, ip_len);
+	}
+
+	return qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE |
+				 ((ipacmd ==
+				   IPA_CMD_SETIPM) ? IPA_SETIP_FLAG : 0));
+}
+
+#define PRINT_SETIP_ERROR(x) \
+	if (result) \
+		PRINT_ERR("setip%c: return code 0x%x (%s)\n",x,result, \
+			  (result==0xe002)?"invalid mtu size": \
+	       		  (result==0xe005)?"duplicate ip address": \
+	       		  (result==0xe0a5)?"duplicate ip address": \
+       			  (result==0xe006)?"ip table full": \
+			  (result==0xe008)?"startlan not received": \
+			  (result==0xe009)?"setip already received": \
+			  (result==0xe00a)?"dup network ip address": \
+			  (result==0xe00b)?"mblk no free main task entry": \
+			  (result==0xe00d)?"invalid ip version": \
+			  (result==0xe00e)?"unsupported arp assist cmd": \
+			  (result==0xe00f)?"arp assist not enabled": \
+			  (result==0xe080)?"startlan disabled": \
+			  (result==-1)?"IPA communication timeout": \
+			  "unknown return code")
+
+static inline int
+qeth_send_setip(struct qeth_card *card, __u8 * ip,
+		__u8 * netmask, short ip_vers, int use_retries)
+{
+	int result;
+	int retries;
+	char dbf_text[15];
+	int takeover = 0;
+
+	retries = (use_retries) ? QETH_SETIP_RETRIES : 1;
+	if (qeth_is_ipa_covered_by_ipato_entries(ip_vers, ip, card)) {
+		QETH_DBF_TEXT2(0, trace, "ipto");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		if (ip_vers == 4) {
+			*((__u32 *) (&dbf_text[0])) = *((__u32 *) ip);
+			*((__u32 *) (&dbf_text[4])) = *((__u32 *) netmask);
+			QETH_DBF_HEX2(0, trace, dbf_text, QETH_DBF_TRACE_LEN);
+		} else {
+			QETH_DBF_HEX2(0, trace, ip, QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX2(0, trace, ip + QETH_DBF_TRACE_LEN,
+				      QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX2(0, trace, netmask, QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX2(0, trace, netmask + QETH_DBF_TRACE_LEN,
+				      QETH_DBF_TRACE_LEN);
+		}
+		takeover = 1;
+	} else {
+	}
+retry:
+	result = qeth_send_setdelip(card, ip, netmask, IPA_CMD_SETIP, ip_vers,
+				    (takeover) ? IPA_SETIP_TAKEOVER_FLAGS :
+				    IPA_SETIP_FLAGS);
+	PRINT_SETIP_ERROR(' ');
+
+	if (result) {
+		QETH_DBF_TEXT2(0, trace, "SETIPFLD");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+	}
+
+	if (((result == -1) || (result == 0xe080)) && (retries--)) {
+		QETH_DBF_TEXT2(0, trace, "sipr");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		if (ip_vers == 4) {
+			*((__u32 *) (&dbf_text[0])) = *((__u32 *) ip);
+			*((__u32 *) (&dbf_text[4])) = *((__u32 *) netmask);
+			QETH_DBF_HEX2(0, trace, dbf_text, QETH_DBF_TRACE_LEN);
+		} else {
+			QETH_DBF_HEX2(0, trace, ip, QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX2(0, trace, ip + QETH_DBF_TRACE_LEN,
+				      QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX2(0, trace, netmask, QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX2(0, trace, netmask + QETH_DBF_TRACE_LEN,
+				      QETH_DBF_TRACE_LEN);
+		}
+		PRINT_WARN("trying again...\n");
+		goto retry;
+	}
+
+	return result;
+}
+
+static inline int
+qeth_send_delip(struct qeth_card *card, __u8 * ip,
+		__u8 * netmask, short ip_vers)
+{
+	return qeth_send_setdelip(card, ip, netmask, IPA_CMD_DELIP, ip_vers,
+				  IPA_DELIP_FLAGS);
+}
+
+static inline int
+qeth_send_setipm(struct qeth_card *card, __u8 * ip,
+		 __u8 * mac, short ip_vers, int use_retries)
+{
+	int result;
+	int retries;
+	char dbf_text[15];
+
+	retries = (use_retries) ? QETH_SETIP_RETRIES : 1;
+	if (qeth_is_ipa_covered_by_ipato_entries(ip_vers, ip, card)) {
+		QETH_DBF_TEXT2(0, trace, "imto");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		if (ip_vers == 4) {
+			*((__u32 *) (&dbf_text[0])) = *((__u32 *) ip);
+			QETH_DBF_HEX2(0, trace, dbf_text, QETH_DBF_TRACE_LEN);
+		} else {
+			QETH_DBF_HEX2(0, trace, ip, QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX2(0, trace, ip + QETH_DBF_TRACE_LEN,
+				      QETH_DBF_TRACE_LEN);
+		}
+	}
+
+retry:
+	result = qeth_send_setdelipm(card, ip, mac, IPA_CMD_SETIPM, ip_vers);
+	PRINT_SETIP_ERROR('m');
+
+	if (result) {
+		QETH_DBF_TEXT2(0, trace, "SETIMFLD");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+	}
+
+	if ((result == -1) && (retries--)) {
+		QETH_DBF_TEXT2(0, trace, "simr");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		if (ip_vers == 4) {
+			sprintf(dbf_text, "%08x", *((__u32 *) ip));
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+		} else {
+			QETH_DBF_HEX2(0, trace, ip, QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX2(0, trace, ip + QETH_DBF_TRACE_LEN,
+				      QETH_DBF_TRACE_LEN);
+		}
+		QETH_DBF_HEX2(0, trace, mac, OSA_ADDR_LEN);
+		PRINT_WARN("trying again...\n");
+		goto retry;
+	}
+
+	return result;
+}
+
+static inline int
+qeth_send_delipm(struct qeth_card *card, __u8 * ip, __u8 * mac, short ip_vers)
+{
+	return qeth_send_setdelipm(card, ip, mac, IPA_CMD_DELIPM, ip_vers);
+}
+
+static int
+qeth_add_vipa_entry(struct qeth_card *card, int version, __u8 * addr, int flag)
+{
+	struct qeth_vipa_entry *entry, *e;
+	int result = 0;
+
+	entry =
+	    (struct qeth_vipa_entry *) kmalloc(sizeof (struct qeth_vipa_entry),
+					       GFP_KERNEL);
+	if (!entry) {
+		PRINT_ERR("not enough memory for vipa handling\n");
+		return -ENOMEM;
+	}
+	entry->version = version;
+	entry->flag = flag;
+	memcpy(entry->ip, addr, 16);
+	entry->state = VIPA_2_B_ADDED;
+
+	write_lock(&card->vipa_list_lock);
+	e = card->vipa_list;
+	while (e) {
+		if (e->version != version)
+			goto next;
+		if (memcmp(e->ip, addr, (version == 4) ? 4 : 16))
+			goto next;
+		if (flag == IPA_SETIP_VIPA_FLAGS) {
+			PRINT_ERR("vipa already set\n");
+		} else {
+			PRINT_ERR("rxip already set\n");
+		}
+		kfree(entry);
+		result = -EALREADY;
+		goto out;
+	next:
+		e = e->next;
+	}
+	entry->next = card->vipa_list;
+	card->vipa_list = entry;
+out:
+	write_unlock(&card->vipa_list_lock);
+	return result;
+}
+
+static int
+qeth_del_vipa_entry(struct qeth_card *card, int version, __u8 * addr, int flag)
+{
+	struct qeth_vipa_entry *e;
+	int result = 0;
+
+	write_lock(&card->vipa_list_lock);
+	e = card->vipa_list;
+	while (e) {
+		if (e->version != version)
+			goto next;
+		if (e->flag != flag)
+			goto next;
+		if (memcmp(e->ip, addr, (version == 4) ? 4 : 16))
+			goto next;
+		e->state = VIPA_2_B_REMOVED;
+		goto out;
+	next:
+		e = e->next;
+	}
+	if (flag == IPA_SETIP_VIPA_FLAGS) {
+		PRINT_ERR("vipa not found\n");
+	} else {
+		PRINT_ERR("rxip not found\n");
+	}
+	result = -ENOENT;
+out:
+	write_unlock(&card->vipa_list_lock);
+	return result;
+}
+
+static void
+qeth_set_vipas(struct qeth_card *card, int set_only)
+{
+	struct qeth_vipa_entry *e, *le = NULL, *ne;	/* ne stands for new entry,
+							   le is last entry */
+	char dbf_text[15];
+	int result;
+	__u8 netmask[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	};
+	struct qeth_vipa_entry *priv_add_list = NULL;
+	struct qeth_vipa_entry *priv_del_list = NULL;
+
+	write_lock(&card->vipa_list_lock);
+	e = card->vipa_list;
+	while (e) {
+		switch (e->state) {
+		case VIPA_2_B_ADDED:
+			if (!set_only)
+				break;
+			if (!atomic_read(&card->is_open))
+				break;
+			/* we don't want to hold the lock for a long time...
+			 * so we clone the entry */
+			ne = (struct qeth_vipa_entry *)
+			    kmalloc(sizeof (struct qeth_vipa_entry),
+				    GFP_KERNEL);
+			if (ne) {
+				ne->version = e->version;
+				memcpy(ne->ip, e->ip, 16);
+				ne->next = priv_add_list;
+				priv_add_list = ne;
+
+				e->state = VIPA_ESTABLISHED;
+			} else {
+				PRINT_ERR("not enough for internal vipa "
+					  "handling... trying to set "
+					  "vipa next time.\n");
+				qeth_start_softsetup_thread(card);
+			}
+			break;
+		case VIPA_2_B_REMOVED:
+			if (set_only)
+				break;
+			if (le)
+				le->next = e->next;
+			else
+				card->vipa_list = e->next;
+			ne = e->next;
+			e->next = priv_del_list;
+			priv_del_list = e;
+			e = ne;
+			continue;
+		case VIPA_ESTABLISHED:
+			if (atomic_read(&card->is_open))
+				break;
+			/* we don't want to hold the lock for a long time...
+			 * so we clone the entry */
+			ne = (struct qeth_vipa_entry *)
+			    kmalloc(sizeof (struct qeth_vipa_entry),
+				    GFP_KERNEL);
+			if (ne) {
+				ne->version = e->version;
+				memcpy(ne->ip, e->ip, 16);
+				ne->next = priv_del_list;
+				priv_del_list = ne;
+
+				e->state = VIPA_2_B_ADDED;
+			} else {
+				PRINT_ERR("not enough for internal vipa "
+					  "handling... VIPA/RXIP remains set "
+					  "although device is stopped.\n");
+				qeth_start_softsetup_thread(card);
+			}
+			break;
+		default:
+			break;
+		}
+		le = e;
+		e = e->next;
+	}
+	write_unlock(&card->vipa_list_lock);
+
+	while (priv_add_list) {
+		result = qeth_send_setdelip(card, priv_add_list->ip, netmask,
+					    IPA_CMD_SETIP,
+					    priv_add_list->version,
+					    priv_add_list->flag);
+		PRINT_SETIP_ERROR('s');
+
+		if (result) {
+			QETH_DBF_TEXT2(0, trace, "SETSVFLD");
+			QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "%4x", result);
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+			if (priv_add_list->version == 4) {
+				PRINT_ERR("going to leave vipa/rxip %08x"
+					  "unset...\n",
+					  *((__u32 *) & priv_add_list->ip[0]));
+				sprintf(dbf_text, "%08x",
+					*((__u32 *) & priv_add_list->ip[0]));
+				QETH_DBF_TEXT2(0, trace, dbf_text);
+			} else {
+				PRINT_ERR("going to leave vipa/rxip "
+					  "%08x%08x%08x%08x unset...\n",
+					  *((__u32 *) & priv_add_list->ip[0]),
+					  *((__u32 *) & priv_add_list->ip[4]),
+					  *((__u32 *) & priv_add_list->ip[8]),
+					  *((__u32 *) & priv_add_list->ip[12]));
+				QETH_DBF_HEX2(0, trace, &priv_add_list->ip[0],
+					      QETH_DBF_TRACE_LEN);
+				QETH_DBF_HEX2(0, trace, &priv_add_list->ip[8],
+					      QETH_DBF_TRACE_LEN);
+			}
+		}
+		e = priv_add_list;
+		priv_add_list = priv_add_list->next;
+		kfree(e);
+	}
+
+	while (priv_del_list) {
+		result = qeth_send_setdelip(card, priv_del_list->ip, netmask,
+					    IPA_CMD_DELIP,
+					    priv_del_list->version,
+					    priv_del_list->flag);
+		if (result) {
+			QETH_DBF_TEXT2(0, trace, "DELSVFLD");
+			QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "%4x", result);
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+			if (priv_del_list->version == 4) {
+				PRINT_ERR("could not delete vipa/rxip "
+					  "%08x...\n",
+					  *((__u32 *) & priv_del_list->ip[0]));
+				sprintf(dbf_text, "%08x",
+					*((__u32 *) & priv_del_list->ip[0]));
+				QETH_DBF_TEXT2(0, trace, dbf_text);
+			} else {
+				PRINT_ERR("could not delete vipa/rxip "
+					  "%08x%08x%08x%08x...\n",
+					  *((__u32 *) & priv_del_list->ip[0]),
+					  *((__u32 *) & priv_del_list->ip[4]),
+					  *((__u32 *) & priv_del_list->ip[8]),
+					  *((__u32 *) & priv_del_list->ip[12]));
+				QETH_DBF_HEX2(0, trace, &priv_del_list->ip[0],
+					      QETH_DBF_TRACE_LEN);
+				QETH_DBF_HEX2(0, trace, &priv_del_list->ip[8],
+					      QETH_DBF_TRACE_LEN);
+			}
+/* in case of problems, it's better if we just display a message and
+ * don't requeue the entry back...
+			write_lock(&card->vipa_list_lock);
+			e=card->vipa_list;
+			card->vipa_list=priv_del_list;
+			priv_del_list=priv_del_list->next;
+			card->vipa_list->next=e;
+			card->vipa_list->state=VIPA_ESTABLISHED;
+			write_unlock(&card->vipa_list_lock);
+			continue;
+*/
+		}
+		e = priv_del_list;
+		priv_del_list = priv_del_list->next;
+		kfree(e);
+	}
+}
+
+static void
+qeth_refresh_vipa_states(struct qeth_card *card)
+{
+	struct qeth_vipa_entry *e;
+
+	write_lock(&card->vipa_list_lock);
+	e = card->vipa_list;
+	while (e) {
+		if (e->state == VIPA_ESTABLISHED)
+			e->state = VIPA_2_B_ADDED;
+		e = e->next;
+	}
+	write_unlock(&card->vipa_list_lock);
+}
+
+static inline int
+qeth_send_setrtg(struct qeth_card *card, int routing_type, short ip_vers)
+{
+	struct ipa_cmd cmd;
+
+	qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETRTG, ip_vers);
+	/* strip off RESET_ROUTING_FLAG */
+	cmd.data.setrtg.type = (routing_type) & (ROUTER_MASK);
+
+	return qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE);
+}
+
+static int
+qeth_is_ipa_in_list(struct in_ifaddr *ip, struct in_ifaddr *list)
+{
+	while (list) {
+		if (ip->ifa_address == list->ifa_address)
+			return 1;
+		list = list->ifa_next;
+	}
+	return 0;
+}
+
+#ifdef QETH_IPV6
+static int
+qeth_is_ipa_in_list6(struct inet6_ifaddr *ip, struct inet6_ifaddr *list)
+{
+	while (list) {
+		if (!memcmp(&ip->addr.s6_addr, &list->addr.s6_addr, 16))
+			return 1;
+		list = list->if_next;
+	}
+	return 0;
+}
+
+static int
+qeth_add_ifa6_to_list(struct inet6_ifaddr **list, struct inet6_ifaddr *ifa)
+{
+	struct inet6_ifaddr *i;
+
+	if (*list == NULL) {
+		*list = ifa;
+	} else {
+		if (qeth_is_ipa_in_list6(ifa, *list))
+			return -EALREADY;
+		i = *list;
+		while (i->if_next) {
+			i = i->if_next;
+		}
+		i->if_next = ifa;
+	}
+	ifa->if_next = NULL;
+	return 0;
+}
+#endif /* QETH_IPV6 */
+
+static int
+qeth_add_ifa_to_list(struct in_ifaddr **list, struct in_ifaddr *ifa)
+{
+	struct in_ifaddr *i;
+
+	if (*list == NULL) {
+		*list = ifa;
+	} else {
+		if (qeth_is_ipa_in_list(ifa, *list))
+			return -EALREADY;
+		i = *list;
+		while (i->ifa_next) {
+			i = i->ifa_next;
+		}
+		i->ifa_next = ifa;
+	}
+	ifa->ifa_next = NULL;
+	return 0;
+}
+
+static void
+__qeth_setips_ipv6(struct qeth_card *card, int use_setip_retries)
+{
+#ifdef QETH_IPV6
+	int result;
+	char dbf_text[15];
+	struct inet6_ifaddr *addr6;
+	__u8 netmask[16];
+
+#define FILL_NETMASK(len) { \
+	int i,j; \
+	for (i=0;i<16;i++) { \
+		j=(len)-(i*8); \
+		netmask[i]=(__u8)(0xFF00>>j); \
+	} \
+}
+	/* here we go with IPv6 */
+	addr6 = card->ip_current_state.ip6_ifa;
+	while (addr6) {
+		if (qeth_is_ipa_in_list6(addr6, card->ip_new_state.ip6_ifa)) {
+			addr6 = addr6->if_next;
+			continue;
+		}
+		QETH_DBF_TEXT3(0, trace, "setipdl6");
+		QETH_DBF_HEX3(0, trace, &addr6->addr.s6_addr,
+			      QETH_DBF_TRACE_LEN);
+		QETH_DBF_HEX3(0, trace,
+			      ((char *) (&addr6->addr.s6_addr)) +
+			      QETH_DBF_TRACE_LEN, QETH_DBF_TRACE_LEN);
+		sprintf(dbf_text, "nmsk%4u", addr6->prefix_len);
+		QETH_DBF_TEXT3(0, trace, dbf_text);
+		FILL_NETMASK(addr6->prefix_len);
+		result = qeth_send_delip(card,
+					 (__u8 *) & addr6->addr.s6_addr,
+					 (__u8 *) & netmask, 6);
+		if (result) {
+			PRINT_ERR("was not able to delete ip "
+				  "%04x:%04x:%04x:%04x:%04x:%04x:"
+				  "%04x:%04x/%u on device %s "
+				  "(result: 0x%x), "
+				  "trying to continue\n",
+				  addr6->addr.s6_addr16[0],
+				  addr6->addr.s6_addr16[1],
+				  addr6->addr.s6_addr16[2],
+				  addr6->addr.s6_addr16[3],
+				  addr6->addr.s6_addr16[4],
+				  addr6->addr.s6_addr16[5],
+				  addr6->addr.s6_addr16[6],
+				  addr6->addr.s6_addr16[7],
+				  addr6->prefix_len,
+				  card->rdev->dev.bus_id, result);
+ 			sprintf(dbf_text, "std6%4x", result);
+ 			QETH_DBF_TEXT3(0, trace, dbf_text);
+		}
+		addr6 = addr6->if_next;
+	}
+
+	addr6 = card->ip_new_state.ip6_ifa;
+	while (addr6) {
+		if (qeth_is_ipa_in_list6(addr6,
+					  card->ip_current_state.ip6_ifa)) {
+			addr6 = addr6->if_next;
+			continue;
+		}
+		QETH_DBF_TEXT3(0, trace, "setipst6");
+		QETH_DBF_HEX3(0, trace, &addr6->addr.s6_addr,
+			      QETH_DBF_TRACE_LEN);
+		QETH_DBF_HEX3(0, trace,
+			      ((char *) (&addr6->addr.s6_addr)) +
+			      QETH_DBF_TRACE_LEN, QETH_DBF_TRACE_LEN);
+		sprintf(dbf_text, "nmsk%4u", addr6->prefix_len);
+		QETH_DBF_TEXT3(0, trace, dbf_text);
+		FILL_NETMASK(addr6->prefix_len);
+		result = qeth_send_setip(card,
+					 (__u8 *) & addr6->addr.s6_addr,
+					 (__u8 *) & netmask, 6,
+					 use_setip_retries);
+		if (!result) {
+			addr6 = addr6->if_next;
+			continue;
+		}
+		PRINT_ERR("was not able to set ip "
+			  "%04x:%04x:%04x:%04x:%04x:%04x:"
+			  "%04x:%04x/%u on device %s "
+			  "(result: 0x%x), trying to continue\n",
+			  addr6->addr.s6_addr16[0],
+			  addr6->addr.s6_addr16[1],
+			  addr6->addr.s6_addr16[2],
+			  addr6->addr.s6_addr16[3],
+			  addr6->addr.s6_addr16[4],
+			  addr6->addr.s6_addr16[5],
+			  addr6->addr.s6_addr16[6],
+			  addr6->addr.s6_addr16[7],
+			  addr6->prefix_len,
+			  card->rdev->dev.bus_id, result);
+ 		sprintf(dbf_text, "sts6%4x", result);
+ 		QETH_DBF_TEXT3(0, trace, dbf_text);
+		addr6 = addr6->if_next;
+	}
+#endif /* QETH_IPV6 */
+}
+
+static int
+qeth_setips(struct qeth_card *card, int use_setip_retries)
+{
+	struct in_ifaddr *addr;
+	int result;
+	char dbf_text[15];
+
+	QETH_DBF_TEXT3(0, trace, "stip");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	addr = card->ip_current_state.ip_ifa;
+	while (addr) {
+		if (!qeth_is_ipa_in_list(addr, card->ip_new_state.ip_ifa)) {
+			QETH_DBF_TEXT3(0, trace, "setipdel");
+			*((__u32 *) (&dbf_text[0])) =
+			    *((__u32 *) & addr->ifa_address);
+			*((__u32 *) (&dbf_text[4])) =
+			    *((__u32 *) & addr->ifa_mask);
+			QETH_DBF_HEX3(0, trace, dbf_text, QETH_DBF_TRACE_LEN);
+			result =
+			    qeth_send_delip(card, (__u8 *) & addr->ifa_address,
+					    (__u8 *) & addr->ifa_mask, 4);
+			if (result) {
+				PRINT_ERR("was not able to delete ip "
+					  "%08x/%08x on device %s "
+					  "(result: 0x%x), "
+					  "trying to continue\n",
+					  addr->ifa_address, addr->ifa_mask,
+					  card->rdev->dev.bus_id, result);
+ 				sprintf(dbf_text, "stdl%4x", result);
+ 				QETH_DBF_TEXT3(0, trace, dbf_text);
+			}
+		}
+		addr = addr->ifa_next;
+	}
+
+	addr = card->ip_new_state.ip_ifa;
+	while (addr) {
+		if (qeth_is_ipa_in_list(addr, card->ip_current_state.ip_ifa)) {
+			addr = addr->ifa_next;
+			continue;
+		}
+		QETH_DBF_TEXT3(0, trace, "setipset");
+		*((__u32 *) (&dbf_text[0])) = *((__u32 *) & addr->ifa_address);
+		*((__u32 *) (&dbf_text[4])) = *((__u32 *) & addr->ifa_mask);
+		QETH_DBF_HEX3(0, trace, dbf_text, QETH_DBF_TRACE_LEN);
+		result = qeth_send_setip(card, (__u8 *) & addr->ifa_address,
+					 (__u8 *) & addr->ifa_mask, 4,
+					 use_setip_retries);
+		if (!result) {
+			addr = addr->ifa_next;
+			continue;
+		}
+		PRINT_ERR("was not able to set ip "
+			  "%08x/%08x on device %s, trying to continue\n",
+			  addr->ifa_address, addr->ifa_mask,
+			  card->rdev->dev.bus_id);
+ 		sprintf(dbf_text, "stst%4x", result);
+ 		QETH_DBF_TEXT3(0, trace, dbf_text);
+		addr = addr->ifa_next;
+	}
+
+	__qeth_setips_ipv6(card, use_setip_retries);
+
+	return 0;
+}
+
+static int
+qeth_is_ipma_in_list(struct qeth_ipm_mac *ipma, struct qeth_ipm_mac *list)
+{
+	while (list) {
+		if ((!memcmp(ipma->ip, list->ip, 16)) &&
+		    (!memcmp(ipma->mac, list->mac, 6)))
+			return 1;
+		list = list->next;
+	}
+	return 0;
+}
+
+static void
+qeth_remove_mc_ifa_from_list(struct qeth_ipm_mac **list,
+			     struct qeth_ipm_mac *ipma)
+{
+	struct qeth_ipm_mac *i, *li = NULL;
+
+	if ((!(*list)) || (!ipma))
+		return;
+
+	if (*list == ipma) {
+		*list = ipma->next;
+	} else {
+		i = *list;
+		while (i) {
+			if (i == ipma) {
+				li->next = i->next;
+			} else {
+				li = i;
+			}
+			i = i->next;
+		}
+	}
+}
+
+static int
+qeth_add_mc_ifa_to_list(struct qeth_ipm_mac **list, struct qeth_ipm_mac *ipma)
+{
+	struct qeth_ipm_mac *i;
+
+	if (qeth_is_ipma_in_list(ipma, *list))
+		return -EALREADY;
+
+	if (*list == NULL) {
+		*list = ipma;
+	} else {
+		i = *list;
+		while (i->next) {
+			i = i->next;
+		}
+		i->next = ipma;
+	}
+	ipma->next = NULL;
+	return 0;
+}
+
+static void
+__qeth_setipms_ipv6(struct qeth_card *card, int use_setipm_retries)
+{
+#ifdef QETH_IPV6
+	struct qeth_ipm_mac *addr;
+	int result;
+	char dbf_text[15];
+
+	/* here we go with IPv6 */
+	addr = card->ip_mc_current_state.ipm6_ifa;
+	while (addr) {
+		if (!qeth_is_ipma_in_list(addr,
+					  card->ip_mc_new_state.ipm6_ifa)) {
+			QETH_DBF_TEXT3(0, trace, "setimdl6");
+			QETH_DBF_HEX3(0, trace, &addr->ip[0],
+				      QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX3(0, trace,
+				      (&addr->ip[0]) + QETH_DBF_TRACE_LEN,
+				      QETH_DBF_TRACE_LEN);
+			QETH_DBF_HEX3(0, trace, &addr->mac,
+				      QETH_DBF_TRACE_LEN);
+			result = qeth_send_delipm(card,
+						  (__u8 *) & addr->ip[0],
+						  (__u8 *) addr->mac, 6);
+			if (result) {
+				PRINT_ERR("was not able to delete "
+					  "multicast ip %04x:%04x:"
+					  "%04x:%04x:%04x:%04x:%04x:%04x/"
+					  "%02x%02x%02x%02x%02x%02x "
+					  "on device %s (result: 0x%x), "
+					  "trying to continue\n",
+					  *((__u16 *) & addr->ip[0]),
+					  *((__u16 *) & addr->ip[2]),
+					  *((__u16 *) & addr->ip[4]),
+					  *((__u16 *) & addr->ip[6]),
+					  *((__u16 *) & addr->ip[8]),
+					  *((__u16 *) & addr->ip[10]),
+					  *((__u16 *) & addr->ip[12]),
+					  *((__u16 *) & addr->ip[14]),
+					  addr->mac[0], addr->mac[1],
+					  addr->mac[2], addr->mac[3],
+					  addr->mac[4], addr->mac[5],
+					  card->rdev->dev.bus_id, result);
+ 				sprintf(dbf_text, "smd6%4x", result);
+ 				QETH_DBF_TEXT3(0, trace, dbf_text);
+			}
+		}
+		addr = addr->next;
+	}
+
+	addr = card->ip_mc_new_state.ipm6_ifa;
+	while (addr) {
+		if (qeth_is_ipma_in_list(addr,
+					 card->ip_mc_current_state.ipm6_ifa)) {
+			addr = addr->next;
+			continue;
+		}
+		QETH_DBF_TEXT3(0, trace, "setimst6");
+		QETH_DBF_HEX3(0, trace, &addr->ip[0], QETH_DBF_TRACE_LEN);
+		QETH_DBF_HEX3(0, trace, (&addr->ip[0]) + QETH_DBF_TRACE_LEN,
+			      QETH_DBF_TRACE_LEN);
+		QETH_DBF_HEX3(0, trace, &addr->mac, QETH_DBF_TRACE_LEN);
+		result = qeth_send_setipm(card,
+					  (__u8 *) & addr->ip[0],
+					  (__u8 *) addr->mac, 6,
+					  use_setipm_retries);
+		if (result) {
+			PRINT_ERR("was not able to set "
+				  "multicast ip %04x:%04x:"
+				  "%04x:%04x:%04x:%04x:%04x:%04x/"
+				  "%02x%02x%02x%02x%02x%02x "
+				  "on device %s (result: 0x%x), "
+				  "trying to continue\n",
+				  *((__u16 *) & addr->ip[0]),
+				  *((__u16 *) & addr->ip[2]),
+				  *((__u16 *) & addr->ip[4]),
+				  *((__u16 *) & addr->ip[6]),
+				  *((__u16 *) & addr->ip[8]),
+				  *((__u16 *) & addr->ip[10]),
+				  *((__u16 *) & addr->ip[12]),
+				  *((__u16 *) & addr->ip[14]),
+				  addr->mac[0], addr->mac[1],
+				  addr->mac[2], addr->mac[3],
+				  addr->mac[4], addr->mac[5],
+				  card->rdev->dev.bus_id, result);
+ 			sprintf(dbf_text, "sms6%4x", result);
+ 			QETH_DBF_TEXT3(0, trace, dbf_text);
+			qeth_remove_mc_ifa_from_list
+				(&card->ip_mc_current_state.ipm6_ifa, addr);
+		}
+		addr = addr->next;
+	}
+#endif /* QETH_IPV6 */
+}
+
+static int
+qeth_setipms(struct qeth_card *card, int use_setipm_retries)
+{
+	struct qeth_ipm_mac *addr;
+	int result;
+	char dbf_text[15];
+
+	QETH_DBF_TEXT3(0, trace, "stim");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	if (!qeth_is_supported(IPA_MULTICASTING))
+		return 0;
+	addr = card->ip_mc_current_state.ipm_ifa;
+	while (addr) {
+		if (!qeth_is_ipma_in_list(addr,
+					  card->ip_mc_new_state.ipm_ifa)) {
+			QETH_DBF_TEXT3(0, trace, "setimdel");
+			sprintf(dbf_text, "%08x", *((__u32 *) & addr->ip[0]));
+			QETH_DBF_TEXT3(0, trace, dbf_text);
+			*((__u32 *) (&dbf_text[0])) = *((__u32 *) & addr->mac);
+			*((__u32 *) (&dbf_text[4])) = 
+				*(((__u32 *) & addr->mac) + 1);
+			QETH_DBF_HEX3(0, trace, dbf_text,
+				      QETH_DBF_TRACE_LEN);
+			result = qeth_send_delipm(card,
+						  (__u8 *) & addr->ip[0],
+						  (__u8 *) addr->mac, 4);
+			if (result) {
+				PRINT_ERR("was not able to delete "
+					  "multicast ip %08x/"
+					  "%02x%02x%02x%02x%02x%02x "
+					  "on device %s "
+					  "(result: 0x%x), "
+					  "trying to continue\n",
+					  *((__u32 *) & addr->ip[0]),
+					  addr->mac[0], addr->mac[1],
+					  addr->mac[2], addr->mac[3],
+					  addr->mac[4], addr->mac[5],
+					  card->rdev->dev.bus_id, result);
+				sprintf(dbf_text, "smdl%4x", result);
+				QETH_DBF_TEXT3(0, trace, dbf_text);
+			}
+		}
+		addr = addr->next;
+	}
+
+	addr = card->ip_mc_new_state.ipm_ifa;
+	while (addr) {
+		if (qeth_is_ipma_in_list(addr,
+					 card->ip_mc_current_state.ipm_ifa)) {
+			addr = addr->next;
+			continue;
+		}
+		QETH_DBF_TEXT3(0, trace, "setimset");
+		sprintf(dbf_text, "%08x", *((__u32 *) & addr->ip[0]));
+		QETH_DBF_TEXT3(0, trace, dbf_text);
+		*((__u32 *) (&dbf_text[0])) = *((__u32 *) & addr->mac);
+		*((__u32 *) (&dbf_text[4])) = *(((__u32 *) & addr->mac) + 1);
+		QETH_DBF_HEX3(0, trace, dbf_text, QETH_DBF_TRACE_LEN);
+		result = qeth_send_setipm(card, (__u8 *) & addr->ip[0],
+					  (__u8 *) addr->mac, 4,
+					  use_setipm_retries);
+		if (result) {
+			PRINT_ERR("was not able to set multicast ip %08x/"
+				  "%02x%02x%02x%02x%02x%02x "
+				  "on device %s (result: 0x%x), "
+				  "trying to continue\n",
+				  *((__u32 *) & addr->ip[0]),
+				  addr->mac[0], addr->mac[1],
+				  addr->mac[2], addr->mac[3],
+				  addr->mac[4], addr->mac[5],
+				  card->rdev->dev.bus_id, result);
+			sprintf(dbf_text, "smst%4x", result);
+			QETH_DBF_TEXT3(0, trace, dbf_text);
+			qeth_remove_mc_ifa_from_list
+				(&card->ip_mc_current_state.ipm_ifa, addr);
+		}
+		addr = addr->next;
+	}
+	__qeth_setipms_ipv6(card, use_setipm_retries);
+	return 0;
+}
+
+static void
+qeth_clone_ifa(struct in_ifaddr *src, struct in_ifaddr *dest)
+{
+	memcpy(dest, src, sizeof (struct in_ifaddr));
+	dest->ifa_next = NULL;
+}
+
+#ifdef QETH_IPV6
+static void
+qeth_clone_ifa6(struct inet6_ifaddr *src, struct inet6_ifaddr *dest)
+{
+	memcpy(dest, src, sizeof (struct inet6_ifaddr));
+	dest->if_next = NULL;
+}
+#endif /* QETH_IPV6 */
+
+#define QETH_STANDARD_RETVALS \
+		ret_val=-EIO; \
+		if (result==IPA_REPLY_SUCCESS) ret_val=0; \
+		if (result==IPA_REPLY_FAILED) ret_val=-EIO; \
+		if (result==IPA_REPLY_OPNOTSUPP) ret_val=-EOPNOTSUPP
+
+static int
+qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	char *data;
+	int result, i, ret_val;
+	int version = 4;
+	struct qeth_card *card;
+	char dbf_text[15];
+	char buff[100];
+
+	card = (struct qeth_card *) dev->priv;
+
+	PRINT_STUPID("CALL: qeth_do_ioctl called with cmd %i (=0x%x).\n", cmd,
+		     cmd);
+	QETH_DBF_TEXT2(0, trace, "ioct");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "cmd=%4x", cmd);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+	QETH_DBF_HEX2(0, trace, &rq, sizeof (void *));
+
+	if ((cmd < SIOCDEVPRIVATE) || (cmd > SIOCDEVPRIVATE + 5))
+		return -EOPNOTSUPP;
+	copy_from_user(buff, rq->ifr_ifru.ifru_data, sizeof (buff));
+	data = buff;
+
+	if ((!atomic_read(&card->is_registered)) ||
+	    (!atomic_read(&card->is_hardsetup)))
+		return -ENODEV;
+
+	if (atomic_read(&card->shutdown_phase))
+		return -ENODEV;
+
+	spin_lock(&card->ioctl_lock);
+
+	if (atomic_read(&card->shutdown_phase)) {
+		ret_val = -ENODEV;
+		goto out;
+	}
+	if ((!atomic_read(&card->is_registered)) ||
+	    (!atomic_read(&card->is_hardsetup))) {
+		ret_val = -ENODEV;
+		goto out;
+	}
+
+	switch (cmd) {
+	case SIOCDEVPRIVATE + 0:
+		if (!capable(CAP_NET_ADMIN)) {
+			ret_val = -EPERM;
+			break;
+		}
+		result =
+		    qeth_send_setassparms(card, version, IPA_ARP_PROCESSING,
+					  IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
+					  rq->ifr_ifru.ifru_ivalue, 4);
+		QETH_STANDARD_RETVALS;
+		if (result == 3)
+			ret_val = -EINVAL;
+		break;
+	case SIOCDEVPRIVATE + 1:
+		if (!capable(CAP_NET_ADMIN)) {
+			ret_val = -EPERM;
+			break;
+		}
+		result = qeth_queryarp(card, rq, version, IPA_ARP_PROCESSING,
+				       IPA_CMD_ASS_ARP_QUERY_INFO, data, 4);
+
+		QETH_STANDARD_RETVALS;
+		break;
+	case SIOCDEVPRIVATE + 2:
+		if (!capable(CAP_NET_ADMIN)) {
+			ret_val = -EPERM;
+			break;
+		}
+		for (i = 12; i < 24; i++)
+			if (data[i])
+				version = 6;
+		result =
+		    qeth_send_setassparms(card, version, IPA_ARP_PROCESSING,
+					  IPA_CMD_ASS_ARP_ADD_ENTRY,
+					  (long) data, 56);
+		QETH_STANDARD_RETVALS;
+		break;
+	case SIOCDEVPRIVATE + 3:
+		if (!capable(CAP_NET_ADMIN)) {
+			ret_val = -EPERM;
+			break;
+		}
+		for (i = 4; i < 12; i++)
+			if (data[i])
+				version = 6;
+		result =
+		    qeth_send_setassparms(card, version, IPA_ARP_PROCESSING,
+					  IPA_CMD_ASS_ARP_REMOVE_ENTRY,
+					  (long) data, 16);
+		QETH_STANDARD_RETVALS;
+		break;
+	case SIOCDEVPRIVATE + 4:
+		if (!capable(CAP_NET_ADMIN)) {
+			ret_val = -EPERM;
+			break;
+		}
+		result =
+		    qeth_send_setassparms(card, version, IPA_ARP_PROCESSING,
+					  IPA_CMD_ASS_ARP_FLUSH_CACHE, 0, 0);
+		QETH_STANDARD_RETVALS;
+		break;
+	case SIOCDEVPRIVATE + 5:
+
+		result =
+		    qeth_send_snmp_control(card, rq, IPA_CMD_SETADAPTERPARMS,
+					   IPA_SETADP_SET_SNMP_CONTROL, data,
+					   4);
+		QETH_STANDARD_RETVALS;
+		break;
+
+	default:
+		ret_val = -EOPNOTSUPP;
+		goto out;
+	}
+out:
+	spin_unlock(&card->ioctl_lock);
+
+	sprintf(dbf_text, "ret=%4x", ret_val);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+
+	return ret_val;
+}
+
+static void
+qeth_clear_ifamc_list(struct qeth_ipm_mac **ifa_list)
+{
+	struct qeth_ipm_mac *ifa;
+	while (*ifa_list) {
+		ifa = *ifa_list;
+		*ifa_list = ifa->next;
+		kfree(ifa);
+	}
+}
+
+#ifdef QETH_IPV6
+static void
+qeth_clear_ifa6_list(struct inet6_ifaddr **ifa_list)
+{
+	struct inet6_ifaddr *ifa;
+	while (*ifa_list) {
+		ifa = *ifa_list;
+		*ifa_list = ifa->if_next;
+		kfree(ifa);
+	}
+}
+
+static inline void
+__qeth_append_vlan_ipas_v6(struct qeth_card *card)
+{
+#ifdef QETH_VLAN
+	char dbf_text[15];
+	struct vlan_group *card_group;
+	int i;
+	int remove;
+	struct inet6_ifaddr *ifa, *ifanew;
+
+	/*
+	 * append all known VLAN IP Addresses corresponding to the real device
+	 * card->dev->ifindex
+	 */
+	QETH_DBF_TEXT4(0, trace, "to-vip6s");
+	if ((!qeth_is_supported(IPA_FULL_VLAN)) || (!atomic_read(&card->is_open)))
+		return;
+
+	card_group = (struct vlan_group *) card->vlangrp;
+	
+	if (!card_group)
+		return;
+	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		if (!card_group->vlan_devices[i] ||
+		    !(card_group->vlan_devices[i]->flags & IFF_UP) ||
+		    !(struct inet6_dev *) card_group->vlan_devices[i]->ip6_ptr)
+			continue;
+		ifa = ((struct inet6_dev *)
+		       card_group->vlan_devices[i]->ip6_ptr)->addr_list;
+		
+		while (ifa) {
+			ifanew = kmalloc(sizeof(struct inet6_ifaddr),
+					 GFP_KERNEL);
+			if (!ifanew) {
+				PRINT_WARN("No memory for IP address "
+					   "handling. Some of the IPs "
+					   "will not be set on %s.\n",
+					   card->dev_name);
+				QETH_DBF_TEXT2(0, trace, "TOIPNMEM");
+			} else {
+				qeth_clone_ifa6(ifa, ifanew);
+				remove = qeth_add_ifa6_to_list
+					(&card->ip_new_state.ip6_ifa, ifanew);
+				QETH_DBF_HEX4(0, trace,
+					      &ifanew->addr.s6_addr,
+					      QETH_DBF_TRACE_LEN);
+				QETH_DBF_HEX4(0, trace,
+					      &ifanew->addr.s6_addr +
+					      QETH_DBF_TRACE_LEN,
+					      QETH_DBF_TRACE_LEN);
+				sprintf(dbf_text, "pref%4u", ifanew->prefix_len);
+				QETH_DBF_TEXT4(0, trace, dbf_text);
+				if (remove) {
+					kfree(ifanew);
+					QETH_DBF_TEXT4(0, trace, "alrdv6rm");
+				}
+			}
+			ifa = ifa->if_next;
+		}
+	}
+#endif
+}
+
+static inline void
+__qeth_append_vlan_ipas_v6_mc(struct qeth_card *card)
+{
+#ifdef QETH_VLAN
+	struct vlan_group *card_group;
+	int i;
+	int remove;
+	struct inet6_dev *in6_vdev;
+	char buf[MAX_ADDR_LEN];
+	struct qeth_ipm_mac *ipmanew;
+	struct ifmcaddr6 *im6;
+	
+	QETH_DBF_TEXT4(0, trace, "tovipm6s");
+	if (!qeth_is_supported(IPA_FULL_VLAN) || !atomic_read(&card->is_open))
+		return;
+
+	card_group = (struct vlan_group *) card->vlangrp;
+	if (!card_group)
+		return;
+
+	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		if (!card_group->vlan_devices[i] ||
+		    !(card_group->vlan_devices[i]->flags & IFF_UP))
+			continue;
+		
+		in6_vdev = in6_dev_get(card_group->vlan_devices[i]);
+		if (!in6_vdev) {
+			QETH_DBF_TEXT2(0, trace, "id26");
+			QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+			continue;
+		}
+
+		read_lock(&in6_vdev->lock);
+		for (im6 = in6_vdev->mc_list; im6; im6 = im6->next) {
+			ndisc_mc_map(&im6->mca_addr, buf,
+				     card_group->vlan_devices[i], 0);
+			ipmanew = (struct qeth_ipm_mac *)
+				kmalloc(sizeof(struct qeth_ipm_mac), GFP_KERNEL);
+			if (!ipmanew) {
+				PRINT_WARN("No memory for IPM address "
+					   "handling. Multicast IP "
+					   "%04x:%04x:%04x:%04x:%04x:"
+					   "%04x:%04x:%04x"
+					   "will not be set on %s.\n",
+					   im6->mca_addr.s6_addr16[0],
+					   im6->mca_addr.s6_addr16[1],
+					   im6->mca_addr.s6_addr16[2],
+					   im6->mca_addr.s6_addr16[3],
+					   im6->mca_addr.s6_addr16[4],
+					   im6->mca_addr.s6_addr16[5],
+					   im6->mca_addr.s6_addr16[6],
+					   im6->mca_addr.s6_addr16[7],
+					   card->dev_name);
+				QETH_DBF_TEXT2(0, trace, "TOIPMNMM");
+			} else {
+				memset(ipmanew, 0, sizeof(struct qeth_ipm_mac));
+				memcpy(ipmanew->mac, buf,OSA_ADDR_LEN);
+				memcpy(ipmanew->ip, im6->mca_addr.s6_addr, 16);
+				ipmanew->next = NULL;
+				remove = qeth_add_mc_ifa_to_list
+					(&card->ip_mc_new_state.ipm6_ifa,
+						 ipmanew);
+				QETH_DBF_HEX4(0, trace, &ipmanew->ip,
+					      QETH_DBF_TRACE_LEN);
+				QETH_DBF_HEX4(0, trace, &ipmanew->ip +
+					      QETH_DBF_TRACE_LEN,
+					      QETH_DBF_TRACE_LEN);
+				QETH_DBF_HEX4(0, trace, &ipmanew->mac,
+					      QETH_DBF_TRACE_LEN);
+				
+				if (remove) {
+					QETH_DBF_TEXT4(0, trace, "mlrdv6rm");
+					kfree(ipmanew);
+				}
+			}
+		}
+		read_unlock(&in6_vdev->lock);
+		in6_dev_put(in6_vdev);
+	}
+#endif
+}
+
+static struct inet6_dev *
+__qeth_get_mc_lock_v6(struct qeth_card *card)
+{
+	struct inet6_dev *in6_dev;
+
+	in6_dev = in6_dev_get(card->dev);
+
+	if (!in6_dev) {
+		QETH_DBF_TEXT2(0, trace, "id16");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		return ERR_PTR(-ENODEV);
+	}
+	read_lock(&in6_dev->lock);
+	return in6_dev;
+}
+
+static void
+__qeth_takeover_ip_ipms6_mc(struct qeth_card *card, struct inet6_dev *in6_dev)
+{
+	int remove;
+	struct qeth_ipm_mac *ipmanew;
+	struct ifmcaddr6 *im6;
+	char buf[MAX_ADDR_LEN];
+
+	QETH_DBF_TEXT4(0, trace, "to-ipm6s");
+	if (atomic_read(&card->is_open))
+		for (im6 = in6_dev->mc_list; im6; im6 = im6->next) {
+			ndisc_mc_map(&im6->mca_addr, buf, card->dev, 0);
+			ipmanew =
+			    (struct qeth_ipm_mac *)
+			    kmalloc(sizeof (struct qeth_ipm_mac), GFP_KERNEL);
+			if (!ipmanew) {
+				PRINT_WARN("No memory for IPM address "
+					   "handling. Multicast IP "
+					   "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+					   "will not be set on %s.\n",
+					   im6->mca_addr.s6_addr16[0],
+					   im6->mca_addr.s6_addr16[1],
+					   im6->mca_addr.s6_addr16[2],
+					   im6->mca_addr.s6_addr16[3],
+					   im6->mca_addr.s6_addr16[4],
+					   im6->mca_addr.s6_addr16[5],
+					   im6->mca_addr.s6_addr16[6],
+					   im6->mca_addr.s6_addr16[7],
+					   card->dev_name);
+				QETH_DBF_TEXT2(0, trace, "TOIPMNMM");
+			} else {
+				memset(ipmanew, 0,
+				       sizeof (struct qeth_ipm_mac));
+				memcpy(ipmanew->mac, buf, OSA_ADDR_LEN);
+				memcpy(ipmanew->ip, im6->mca_addr.s6_addr, 16);
+				ipmanew->next = NULL;
+				remove =
+				    qeth_add_mc_ifa_to_list(&card->
+							    ip_mc_new_state.
+							    ipm6_ifa, ipmanew);
+				QETH_DBF_HEX4(0, trace, &ipmanew->ip,
+					      QETH_DBF_TRACE_LEN);
+				QETH_DBF_HEX4(0, trace,
+					      &ipmanew->ip + QETH_DBF_TRACE_LEN,
+					      QETH_DBF_TRACE_LEN);
+				QETH_DBF_HEX4(0, trace, &ipmanew->mac,
+					      QETH_DBF_TRACE_LEN);
+				if (remove) {
+					QETH_DBF_TEXT4(0, trace, "mlrdy6rm");
+					kfree(ipmanew);
+				}
+			}
+		}
+	__qeth_append_vlan_ipas_v6_mc(card);
+
+	read_unlock(&in6_dev->lock);
+	in6_dev_put(in6_dev);
+}
+#endif /* QETH_IPV6 */
+
+static void
+qeth_takeover_ip_ipms6(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	struct inet6_ifaddr *ifa, *ifanew;
+	char dbf_text[15];
+	int remove;
+	struct inet6_dev *in6_dev;
+
+	QETH_DBF_TEXT3(0, trace, "tip6");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+	/* unicast */
+	/* clear ip_current_state */
+	qeth_clear_ifa6_list(&card->ip_current_state.ip6_ifa);
+	/* take it over */
+	card->ip_current_state.ip6_ifa = card->ip_new_state.ip6_ifa;
+	card->ip_new_state.ip6_ifa = NULL;
+
+	in6_dev = __qeth_get_mc_lock_v6(card);
+	if (PTR_ERR(in6_dev) == -ENODEV)
+		return;
+	/* get new one, we try to have the same order as ifa_list in device
+	   structure, for what reason ever */
+	QETH_DBF_TEXT4(0, trace, "to-ip6s");
+	if ((atomic_read(&card->is_open)) && (card->dev->ip6_ptr) &&
+	    (((struct inet6_dev *) card->dev->ip6_ptr)->addr_list)) {
+		ifa = ((struct inet6_dev *) card->dev->ip6_ptr)->addr_list;
+
+		while (ifa) {
+			ifanew =
+			    kmalloc(sizeof (struct inet6_ifaddr), GFP_KERNEL);
+			if (!ifanew) {
+				PRINT_WARN("No memory for IP address "
+					   "handling. Some of the IPs "
+					   "will not be set on %s.\n",
+					   card->dev_name);
+				QETH_DBF_TEXT2(0, trace, "TOIPNMEM");
+			} else {
+				qeth_clone_ifa6(ifa, ifanew);
+				remove =
+				    qeth_add_ifa6_to_list(&card->ip_new_state.
+							  ip6_ifa, ifanew);
+				QETH_DBF_HEX4(0, trace, &ifanew->addr.s6_addr,
+					      QETH_DBF_TRACE_LEN);
+				QETH_DBF_HEX4(0, trace,
+					      &ifanew->addr.s6_addr +
+					      QETH_DBF_TRACE_LEN,
+					      QETH_DBF_TRACE_LEN);
+				sprintf(dbf_text, "pref%4u",
+					ifanew->prefix_len);
+				QETH_DBF_TEXT4(0, trace, dbf_text);
+				if (remove) {
+					kfree(ifanew);
+					QETH_DBF_TEXT4(0, trace, "alrdy6rm");
+				}
+			}
+			ifa = ifa->if_next;
+		}
+	}
+
+	__qeth_append_vlan_ipas_v6(card);
+	
+	__qeth_takeover_ip_ipms6_mc(card, in6_dev);
+#endif /* QETH_IPV6 */
+}
+
+static void
+qeth_clear_ifa4_list(struct in_ifaddr **ifa_list)
+{
+	struct in_ifaddr *ifa;
+	while (*ifa_list) {
+		ifa = *ifa_list;
+		*ifa_list = ifa->ifa_next;
+		kfree(ifa);
+	}
+}
+
+static inline void
+__qeth_append_vlan_ipas_v4(struct qeth_card *card)
+{
+#ifdef QETH_VLAN
+	struct in_ifaddr *ifa, *ifanew;
+	char dbf_text[15];
+	struct vlan_group *card_group;
+	int i;
+	int remove;
+	struct in_device *vin4_dev;
+
+	/*
+	 * append all known VLAN IP Addresses corresponding to the real device
+	 * card->dev->ifindex
+	 */
+	QETH_DBF_TEXT4(0, trace, "to-vips");
+	if (!qeth_is_supported(IPA_FULL_VLAN) || !atomic_read(&card->is_open))
+		return;
+
+	card_group = (struct vlan_group *) card->vlangrp;
+	if (!card_group)
+		return;
+
+	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		vin4_dev = in_dev_get(card->dev);
+		if (!vin4_dev) {
+			QETH_DBF_TEXT2(0, trace, "nodvhol2");
+			QETH_DBF_TEXT2(0, trace, card->dev_name);
+			continue;
+		}
+		read_lock(&vin4_dev->lock);
+
+		if ((card_group->vlan_devices[i]) &&
+		    (card_group->vlan_devices[i]->flags & IFF_UP)) {
+			ifa = ((struct in_device *)
+			       card_group->vlan_devices[i]->ip_ptr)->ifa_list;
+			while (ifa) {
+				ifanew = kmalloc(sizeof(struct in_ifaddr),
+						 GFP_KERNEL);
+				if (!ifanew) {
+					PRINT_WARN("No memory for IP address "
+						   "handling. Some of the IPs "
+						   "will not be set on %s.\n",
+						   card->dev_name);
+					QETH_DBF_TEXT2(0, trace, "TOIPNMEM");
+				} else {
+					qeth_clone_ifa(ifa, ifanew);
+					remove = qeth_add_ifa_to_list
+						(&card->ip_new_state.ip_ifa,
+						 ifanew);
+					*((__u32*) (&dbf_text[0])) =
+						*((__u32*) &ifanew->ifa_address);
+					*((__u32*) (&dbf_text[4])) =
+						*((__u32*) &ifanew->ifa_mask);
+					QETH_DBF_TEXT4(0, trace, dbf_text);
+					if (remove) {
+						kfree(ifanew);
+						QETH_DBF_TEXT4(0, trace,
+							       "alrdv4rm");
+					}
+				}
+				ifa = ifa->ifa_next;
+			}
+		}		
+
+		read_unlock(&vin4_dev->lock);
+		in_dev_put(vin4_dev);
+	}
+#endif /* QETH_VLAN */
+
+}
+
+static inline void
+__qeth_append_vlan_ipas_v4_mc(struct qeth_card *card)
+{
+#ifdef QETH_VLAN
+	char dbf_text[15];
+	int i;
+	int remove;
+	struct vlan_group *card_group;
+	struct in_device *vin4_dev;
+	struct qeth_ipm_mac *ipmanew;
+	struct ip_mc_list *im4;
+	char buf[MAX_ADDR_LEN];
+	__u32 maddr;
+	
+	QETH_DBF_TEXT4(0, trace, "to-vipms");
+	if (!qeth_is_supported(IPA_FULL_VLAN) || !atomic_read(&card->is_open))
+		return;
+
+	card_group = (struct vlan_group *) card->vlangrp;
+	if (!card_group)
+		return;
+
+	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		if (!card_group->vlan_devices[i] ||
+		    !(card_group->vlan_devices[i]->flags & IFF_UP))
+			continue;
+
+		vin4_dev = in_dev_get(card_group->vlan_devices[i]);
+		if (!vin4_dev) {
+			QETH_DBF_TEXT2(0, trace, "novdhol3");
+			QETH_DBF_TEXT2(0, trace, card->dev_name);
+			QETH_DBF_TEXT2(0, trace,
+				       card_group->vlan_devices[i]->name);
+			continue;
+		}
+		read_lock(&vin4_dev->lock);
+		for (im4 = vin4_dev->mc_list; im4; im4 = im4->next) {
+			qeth_get_mac_for_ipm(im4->multiaddr, buf, vin4_dev->dev);
+			ipmanew = (struct qeth_ipm_mac *)
+				kmalloc(sizeof(struct qeth_ipm_mac), GFP_KERNEL);
+			if (!ipmanew) {
+				PRINT_WARN("No memory for IPM address "
+					   "handling. Multicast VLAN IP %08x"
+					   "will not be set on %s.\n",
+					   (__u32) im4->multiaddr,
+					   card->dev_name);
+				QETH_DBF_TEXT2(0, trace, "TOIPMNMM");
+			} else {
+				memset(ipmanew, 0, sizeof(struct qeth_ipm_mac));
+				memcpy(ipmanew->mac, buf, OSA_ADDR_LEN);
+				maddr = im4->multiaddr;
+				memcpy(&(ipmanew->ip[0]), &maddr, 4);
+				memset(&(ipmanew->ip[4]), 0xff, 12);
+				ipmanew->next = NULL;
+				remove = qeth_add_mc_ifa_to_list
+					(&card->ip_mc_new_state.ipm_ifa,
+					 ipmanew);
+				sprintf(dbf_text, "%08x",
+					*((__u32 *) &ipmanew->ip));
+				QETH_DBF_TEXT4(0, trace, dbf_text);
+				QETH_DBF_HEX4(0, trace, &ipmanew->mac,
+					      QETH_DBF_TRACE_LEN);
+				if (remove) {
+					QETH_DBF_TEXT4(0, trace, "mlrdv4rm");
+					kfree(ipmanew);
+				}
+			}
+		}
+		read_unlock(&vin4_dev->lock);
+		in_dev_put(vin4_dev);
+	}
+#endif /* QETH_VLAN */
+
+}
+
+static struct in_device *
+__qeth_get_mc_lock(struct qeth_card *card)
+{
+	struct in_device *in4_dev;
+
+	/* multicast */
+	/* clear ip_mc_current_state */
+	qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm_ifa);
+	/* take it over */
+	card->ip_mc_current_state.ipm_ifa = card->ip_mc_new_state.ipm_ifa;
+	/* get new one, we try to have the same order as ifa_list in device
+	   structure, for what reason ever */
+	card->ip_mc_new_state.ipm_ifa = NULL;
+
+	in4_dev = in_dev_get(card->dev);
+	if (!in4_dev) {
+		QETH_DBF_TEXT2(0, trace, "nodvhol1");
+		QETH_DBF_TEXT2(0, trace, card->dev_name);
+		return ERR_PTR(-ENODEV);
+	}
+	read_lock(&in4_dev->lock);
+	return in4_dev;
+}
+
+static void
+__qeth_takeover_ip_ipms_mc(struct qeth_card *card, struct in_device *in4_dev)
+{
+	char dbf_text[15];
+	int remove;
+	struct qeth_ipm_mac *ipmanew;
+	struct ip_mc_list *im4;
+	char buf[MAX_ADDR_LEN];
+	__u32 maddr;
+
+	QETH_DBF_TEXT4(0, trace, "to-ipms");
+	if (atomic_read(&card->is_open))
+		for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
+			qeth_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev);
+			ipmanew =
+			    (struct qeth_ipm_mac *)
+			    kmalloc(sizeof (struct qeth_ipm_mac), GFP_KERNEL);
+			if (!ipmanew) {
+				PRINT_WARN("No memory for IPM address "
+					   "handling. Multicast IP %08x"
+					   "will not be set on %s.\n",
+					   (__u32) im4->multiaddr,
+					   card->dev_name);
+				QETH_DBF_TEXT2(0, trace, "TOIPMNMM");
+			} else {
+				memset(ipmanew, 0,
+				       sizeof (struct qeth_ipm_mac));
+				memcpy(ipmanew->mac, buf, OSA_ADDR_LEN);
+				maddr = im4->multiaddr;
+				memcpy(&(ipmanew->ip[0]), &maddr, 4);
+				memset(&(ipmanew->ip[4]), 0xff, 12);
+				ipmanew->next = NULL;
+				remove =
+				    qeth_add_mc_ifa_to_list(&card->
+							    ip_mc_new_state.
+							    ipm_ifa, ipmanew);
+				sprintf(dbf_text, "%08x",
+					*((__u32 *) & ipmanew->ip));
+				QETH_DBF_TEXT4(0, trace, dbf_text);
+				QETH_DBF_HEX4(0, trace, &ipmanew->mac,
+					      QETH_DBF_TRACE_LEN);
+				if (remove) {
+					QETH_DBF_TEXT4(0, trace, "mlrdy4rm");
+					kfree(ipmanew);
+				}
+			}
+		}
+	__qeth_append_vlan_ipas_v4(card);
+
+	read_unlock(&in4_dev->lock);
+	in_dev_put(in4_dev);
+
+}
+
+static void
+qeth_takeover_ip_ipms(struct qeth_card *card)
+{
+	struct in_ifaddr *ifa, *ifanew;
+	char dbf_text[15];
+	int remove;
+	struct in_device *in4_dev;
+
+	QETH_DBF_TEXT3(0, trace, "tips");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+	/* unicast */
+	/* clear ip_current_state */
+	qeth_clear_ifa4_list(&card->ip_current_state.ip_ifa);
+	/* take it over */
+	card->ip_current_state.ip_ifa = card->ip_new_state.ip_ifa;
+	card->ip_new_state.ip_ifa = NULL;
+
+	in4_dev = __qeth_get_mc_lock(card);
+	if (PTR_ERR(in4_dev) == -ENODEV)
+		return;
+
+	/* get new one, we try to have the same order as ifa_list in device
+	   structure, for what reason ever */
+	QETH_DBF_TEXT4(0, trace, "to-ips");
+	if ((atomic_read(&card->is_open)) && (card->dev->ip_ptr) &&
+	    (((struct in_device *) card->dev->ip_ptr)->ifa_list)) {
+		ifa = ((struct in_device *) card->dev->ip_ptr)->ifa_list;
+
+		while (ifa) {
+			ifanew = kmalloc(sizeof (struct in_ifaddr), GFP_KERNEL);
+			if (!ifanew) {
+				PRINT_WARN("No memory for IP address "
+					   "handling. Some of the IPs "
+					   "will not be set on %s.\n",
+					   card->dev_name);
+				QETH_DBF_TEXT2(0, trace, "TOIPNMEM");
+			} else {
+				qeth_clone_ifa(ifa, ifanew);
+				remove =
+				    qeth_add_ifa_to_list(&card->ip_new_state.
+							 ip_ifa, ifanew);
+				*((__u32 *) (&dbf_text[0])) =
+				    *((__u32 *) & ifanew->ifa_address);
+				*((__u32 *) (&dbf_text[4])) =
+				    *((__u32 *) & ifanew->ifa_mask);
+				QETH_DBF_TEXT4(0, trace, dbf_text);
+				if (remove) {
+					kfree(ifanew);
+					QETH_DBF_TEXT4(0, trace, "alrdy4rm");
+				}
+			}
+
+			ifa = ifa->ifa_next;
+		}
+	}
+	__qeth_append_vlan_ipas_v4(card);
+
+	__qeth_takeover_ip_ipms_mc(card, in4_dev);
+}
+
+static void
+qeth_get_unique_id(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	struct ipa_cmd cmd;
+	int result;
+	char dbf_text[15];
+
+	if (!qeth_is_supported(IPA_IPv6)) {
+		card->unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+		    UNIQUE_ID_NOT_BY_CARD;
+		return;
+	}
+	qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_CREATE_ADDR, 6);
+
+	*((__u16 *) & cmd.data.create_destroy_addr.unique_id[6]) =
+	    card->unique_id;
+
+	result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE);
+
+	if (result) {
+		card->unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+		    UNIQUE_ID_NOT_BY_CARD;
+		PRINT_WARN("couldn't get a unique id from the card on device "
+			   "%s (result=x%x), using default id. ipv6 "
+			   "autoconfig on other lpars may lead to duplicate "
+			   "ip addresses. please use manually "
+			   "configured ones.\n",
+			   card->rdev->dev.bus_id, result);
+		QETH_DBF_TEXT2(0, trace, "unid fld");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+	} else {
+		card->unique_id =
+		    *((__u16 *) & cmd.data.create_destroy_addr.unique_id[6]);
+		QETH_DBF_TEXT2(0, setup, "uniqueid");
+		QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x", card->unique_id);
+		QETH_DBF_TEXT2(0, setup, dbf_text);
+	}
+#else /* QETH_IPV6 */
+	card->unique_id =
+	    UNIQUE_ID_IF_CREATE_ADDR_FAILED | UNIQUE_ID_NOT_BY_CARD;
+#endif /* QETH_IPV6 */
+}
+
+static void
+qeth_put_unique_id(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	struct ipa_cmd cmd;
+	int result;
+	char dbf_text[15];
+
+	/* is also true, if ipv6 is not supported on the card */
+	if ((card->unique_id & UNIQUE_ID_NOT_BY_CARD) == UNIQUE_ID_NOT_BY_CARD)
+		return;
+
+	qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_DESTROY_ADDR, 6);
+	*((__u16 *) & cmd.data.create_destroy_addr.unique_id[6]) =
+	    card->unique_id;
+	memcpy(&cmd.data.create_destroy_addr.unique_id[0], card->dev->dev_addr,
+	       OSA_ADDR_LEN);
+
+	result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE);
+
+	if (result) {
+		QETH_DBF_TEXT2(0, trace, "unibkfld");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+	}
+#else /* QETH_IPV6 */
+	card->unique_id =
+	    UNIQUE_ID_IF_CREATE_ADDR_FAILED | UNIQUE_ID_NOT_BY_CARD;
+#endif /* QETH_IPV6 */
+}
+
+static inline void
+__qeth_setparms_hstr(struct qeth_card *card)
+{
+	char dbf_text[15];
+	int result;
+
+	if ((card->link_type != QETH_MPC_LINK_TYPE_HSTR) &&
+	    (card->link_type != QETH_MPC_LINK_TYPE_LANE_TR))
+		return;
+
+	QETH_DBF_TEXT3(0, trace, "hstr");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+	
+	if (qeth_is_adp_supported(IPA_SETADP_SET_BROADCAST_MODE)) {
+		result = qeth_send_setadapterparms_mode
+			(card, IPA_SETADP_SET_BROADCAST_MODE,
+			 card->options.broadcast_mode);
+		if (result) {
+			PRINT_WARN("couldn't set broadcast mode on "
+				   "device %s: x%x\n",
+				   card->rdev->dev.bus_id, result);
+			QETH_DBF_TEXT1(0, trace, "STBRDCST");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "%4x", result);
+			QETH_DBF_TEXT1(1, trace, dbf_text);
+		}
+	} else if (card->options.broadcast_mode) {
+		PRINT_WARN("set adapter parameters not available "
+			   "to set broadcast mode, using ALLRINGS "
+			   "on device %s:\n", card->rdev->dev.bus_id);
+		QETH_DBF_TEXT1(0, trace, "NOBC");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+	}
+	
+	if (qeth_is_adp_supported(IPA_SETADP_SET_BROADCAST_MODE)) {
+		result = qeth_send_setadapterparms_mode
+			(card, IPA_SETADP_ALTER_MAC_ADDRESS,
+			 card->options.macaddr_mode);
+		if (result) {
+			PRINT_WARN("couldn't set macaddr mode on "
+				   "device %s: x%x\n", card->rdev->dev.bus_id,
+				   result);
+			QETH_DBF_TEXT1(0, trace, "STMACMOD");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "%4x", result);
+			QETH_DBF_TEXT1(1, trace, dbf_text);
+		}
+	} else if (card->options.macaddr_mode) {
+		PRINT_WARN("set adapter parameters not available "
+			   "to set macaddr mode, using NONCANONICAL "
+			   "on device %s:\n", card->rdev->dev.bus_id);
+		QETH_DBF_TEXT1(0, trace, "NOMA");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+	}
+}
+
+static void
+qeth_do_setadapterparms_stuff(struct qeth_card *card)
+{
+	int result;
+	char dbf_text[15];
+
+	if (!qeth_is_supported(IPA_SETADAPTERPARMS)) {
+		return;
+	}
+
+	QETH_DBF_TEXT4(0, trace, "stap");
+	QETH_DBF_TEXT4(0, trace, card->rdev->dev.bus_id);
+
+	result = qeth_send_setadapterparms_query(card);
+
+	if (result) {
+		PRINT_WARN("couldn't set adapter parameters on device %s: "
+			   "x%x\n", card->rdev->dev.bus_id, result);
+		QETH_DBF_TEXT1(0, trace, "SETADPFL");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x", result);
+		QETH_DBF_TEXT1(1, trace, dbf_text);
+		return;
+	}
+
+	sprintf(dbf_text, "spap%4x", card->adp_supported);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+
+	if (qeth_is_adp_supported(IPA_SETADP_ALTER_MAC_ADDRESS)) {
+		QETH_DBF_TEXT3(0, trace, "rdmc");
+		QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+		QETH_DBF_TEXT2(0, setup, "rdmc");
+		QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id);
+
+		result = qeth_send_setadapterparms_change_addr(card,
+							       IPA_SETADP_ALTER_MAC_ADDRESS,
+							       CHANGE_ADDR_READ_MAC,
+							       card->dev->
+							       dev_addr,
+							       OSA_ADDR_LEN);
+		if (result) {
+			PRINT_WARN("couldn't get MAC address on "
+				   "device %s: x%x\n",
+				   card->rdev->dev.bus_id, result);
+			QETH_DBF_TEXT1(0, trace, "NOMACADD");
+			QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "%4x", result);
+			QETH_DBF_TEXT1(1, trace, dbf_text);
+		} else {
+			QETH_DBF_HEX2(0, setup, card->dev->dev_addr,
+				      __max(OSA_ADDR_LEN, QETH_DBF_SETUP_LEN));
+			QETH_DBF_HEX3(0, trace, card->dev->dev_addr,
+				      __max(OSA_ADDR_LEN, QETH_DBF_TRACE_LEN));
+		}
+	}
+	__qeth_setparms_hstr(card);
+}
+
+static inline void
+__qeth_start_vlan_assist(struct qeth_card *card)
+{
+#ifdef QETH_VLAN
+	char dbf_text[15];
+	int result;
+
+	if (!qeth_is_supported(IPA_FULL_VLAN)) {
+		PRINT_WARN("VLAN not supported on %s\n",
+			   card->dev_name);
+		QETH_DBF_TEXT2(0, trace, "vlnotsup");
+		return;
+	}
+	result = qeth_send_setassparms_simple_without_data(card,
+							   IPA_VLAN_PRIO,
+							   IPA_CMD_ASS_START);
+	QETH_DBF_TEXT2(0, trace, "enavlan");
+	if (result) {
+		PRINT_WARN("Could not start vlan "
+			   "assist on %s: 0x%x, continuing\n",
+			   card->dev_name, result);
+		sprintf(dbf_text, "VLAN%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		return;
+	}
+	card->dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+#endif /* QETH_VLAN */
+}
+
+static inline void
+__qeth_start_mc_assist(struct qeth_card *card)
+{
+	char dbf_text[15];
+	int result;
+
+	if (!qeth_is_supported(IPA_MULTICASTING)) {
+		PRINT_WARN("multicasting not supported on %s\n",
+			   card->dev_name);
+		QETH_DBF_TEXT2(0, trace, "mcnotsup");
+		return;
+	}
+	result = qeth_send_setassparms_simple_without_data(card,
+							   IPA_MULTICASTING,
+							   IPA_CMD_ASS_START);
+	QETH_DBF_TEXT2(0, trace, "enamcass");
+	if (result) {
+		PRINT_WARN("Could not start multicast "
+			   "assist on %s: 0x%x, continuing\n",
+			   card->dev_name, result);
+		sprintf(dbf_text, "MCAS%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		return;
+	}
+	card->dev->flags |= IFF_MULTICAST;
+}
+
+static int
+__qeth_softsetup_enable_ipv6(struct qeth_card *card, int do_a_startlan6)
+{
+	int result;
+	char dbf_text[15];
+
+	if (do_a_startlan6) {
+		QETH_DBF_TEXT2(0, trace, "startln6");
+		netif_stop_queue(card->dev);
+		result = qeth_send_startlan(card, 6);
+		if (result) {
+			sprintf(dbf_text, "stl6%4x", result);
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+			atomic_set(&card->is_softsetup, 0);
+			/* do not return an error */
+			if (result == 0xe080)
+				result = 0;
+			return result;
+		}
+	}
+	netif_wake_queue(card->dev);
+
+	QETH_DBF_TEXT2(0, trace, "qipassi6");
+	result = qeth_send_qipassist(card, 6);
+	if (result) {
+		PRINT_WARN("couldn't send QIPASSIST6 on %s: 0x%x\n",
+			   card->dev_name, result);
+		sprintf(dbf_text, "QIP6%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		atomic_set(&card->is_softsetup, 0);
+		return result;
+	}
+		
+	sprintf(dbf_text, "%4x%4x", card->ipa6_supported, card->ipa6_enabled);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+
+	QETH_DBF_TEXT2(0, trace, "enaipv46");
+	result = qeth_send_setassparms_simple_with_data(card, IPA_IPv6,
+							IPA_CMD_ASS_START, 3);
+	if (result) {
+		PRINT_WARN("Could not enable IPv4&6 assist "
+			   "on %s: 0x%x, continuing\n",
+			   card->dev_name, result);
+		sprintf(dbf_text, "I46A%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		/* go on */
+	}
+
+	QETH_DBF_TEXT2(0, trace, "enaipv6");
+	result = qeth_send_setassparms_simple_without_data6(card, IPA_IPv6,
+							    IPA_CMD_ASS_START);
+	if (result) {
+		PRINT_WARN("Could not start IPv6 assist "
+			   "on %s: 0x%x, continuing\n",
+			   card->dev_name, result);
+		sprintf(dbf_text, "I6AS%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		/* go on */
+	}
+
+	QETH_DBF_TEXT2(0, trace, "enapstr6");
+	result = qeth_send_setassparms_simple_without_data6(card, IPA_PASSTHRU,
+							    IPA_CMD_ASS_START);
+	if (result) {
+		PRINT_WARN("Could not enable passthrough "
+			   "on %s: 0x%x, continuing\n",
+			   card->dev_name, result);
+		sprintf(dbf_text, "PSTR%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		/* go on */
+	}
+	return 0;
+}
+
+static int
+__qeth_softsetup_start_assists(struct qeth_card *card)
+{
+	int result;
+	char dbf_text[15];
+	int do_a_startlan6 = 0;
+
+	if (atomic_read(&card->is_softsetup))
+		return 0;
+
+	atomic_set(&card->enable_routing_attempts4, QETH_ROUTING_ATTEMPTS);
+#ifdef QETH_IPV6
+	atomic_set(&card->enable_routing_attempts6, QETH_ROUTING_ATTEMPTS);
+#endif /* QETH_IPV6 */
+	if ((!atomic_read(&card->is_startlaned)) &&
+	    (atomic_read(&card->startlan_attempts))) {
+		atomic_dec(&card->startlan_attempts);
+		QETH_DBF_TEXT2(0, trace, "startlan");
+		netif_stop_queue(card->dev);
+		result = qeth_send_startlan(card, 4);
+		if (result) {
+			PRINT_WARN("couldn't send STARTLAN on %s "
+				   "(CHPID 0x%X): 0x%x (%s)\n",
+				   card->dev_name, card->chpid, result,
+				   (result == 0xe080) ?
+				   "startlan disabled (link "
+				   "failure -- please check the "
+				   "network, plug in the cable or "
+				   "enable the OSA port" :
+				   "unknown return code");
+			sprintf(dbf_text, "stln%4x", result);
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+			atomic_set(&card->is_softsetup, 0);
+			atomic_set(&card->is_startlaned, 0);
+			/* do not return an error */
+			if (result == 0xe080) {
+				result = 0;
+			}
+			return result;
+		}
+		do_a_startlan6 = 1;
+	}
+	netif_wake_queue(card->dev);
+	
+	qeth_do_setadapterparms_stuff(card);
+	
+	if (!qeth_is_supported(IPA_ARP_PROCESSING)) {
+		PRINT_WARN("oops... ARP processing not supported "
+			   "on %s!\n", card->dev_name);
+		QETH_DBF_TEXT1(0, trace, "NOarpPRC");
+	} else {
+		QETH_DBF_TEXT2(0, trace, "enaARPpr");
+		result = qeth_send_setassparms_simple_without_data
+			(card, IPA_ARP_PROCESSING, IPA_CMD_ASS_START);
+		if (result) {
+			PRINT_WARN("Could not start ARP processing "
+				   "assist on %s: 0x%x\n",
+				   card->dev_name, result);
+			sprintf(dbf_text, "ARPp%4x", result);
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+			atomic_set(&card->is_softsetup, 0);
+			return result;
+		}
+	}
+	
+	if (qeth_is_supported(IPA_IP_FRAGMENTATION)) {
+		PRINT_INFO("IP fragmentation supported on "
+			   "%s... :-)\n", card->dev_name);
+		/* start it */
+		QETH_DBF_TEXT2(0, trace, "enaipfrg");
+		result = qeth_send_setassparms_simple_without_data
+			(card, IPA_IP_FRAGMENTATION, IPA_CMD_ASS_START);
+		if (result) {
+			PRINT_WARN("Could not start IP fragmenting "
+				   "assist on %s: 0x%x, continuing\n",
+				   card->dev_name, result);
+			sprintf(dbf_text, "IFRG%4x", result);
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+			/* go on */
+		}
+	}
+	if (card->options.fake_ll == FAKE_LL) {
+		if (qeth_is_supported(IPA_SOURCE_MAC_AVAIL)) {
+			/* start it */
+			QETH_DBF_TEXT2(0, trace, "enainsrc");
+			result = qeth_send_setassparms_simple_without_data
+				(card, IPA_SOURCE_MAC_AVAIL, IPA_CMD_ASS_START);
+			if (result) {
+				PRINT_WARN
+					("Could not start inbound source "
+					 "assist on %s: 0x%x, continuing\n",
+					 card->dev_name, result);
+				sprintf(dbf_text, "INSR%4x", result);
+				QETH_DBF_TEXT2(0, trace, dbf_text);
+				/* go on */
+			}
+		} else {
+			PRINT_INFO("Inbound source addresses not "
+				   "supported on %s\n", card->dev_name);
+		}
+	}
+	__qeth_start_vlan_assist(card);
+	__qeth_start_mc_assist(card);
+	
+	if (!qeth_is_supported(IPA_IPv6)) {
+		QETH_DBF_TEXT2(0, trace, "ipv6ntsp");
+		PRINT_WARN("IPv6 not supported on %s\n", card->dev_name);
+	} else {
+		result = __qeth_softsetup_enable_ipv6(card, do_a_startlan6);
+		if (result != 0)
+			return result;
+	}
+	
+	card->broadcast_capable = 0;
+	if (!qeth_is_supported(IPA_FILTERING)) {
+		QETH_DBF_TEXT2(0, trace, "filtntsp");
+		PRINT_WARN("Broadcasting not supported on %s\n",
+			   card->dev_name);
+	} else {
+		QETH_DBF_TEXT2(0, trace, "enafiltr");
+		result = qeth_send_setassparms_simple_without_data
+			(card, IPA_FILTERING, IPA_CMD_ASS_START);
+		if (result) {
+			PRINT_WARN("Could not enable broadcast "
+				   "filtering on %s: "
+				   "0x%x, continuing\n",
+				   card->dev_name, result);
+			sprintf(dbf_text, "FLT1%4x", result);
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+			goto go_on_filt;
+		}
+		result = qeth_send_setassparms_simple_with_data
+			(card, IPA_FILTERING, IPA_CMD_ASS_CONFIGURE, 1);
+		if (result) {
+			PRINT_WARN("Could not set up broadcast "
+				   "filtering on %s: "
+				   "0x%x, continuing\n",
+				   card->dev_name, result);
+			sprintf(dbf_text, "FLT2%4x", result);
+			QETH_DBF_TEXT2(0, trace, dbf_text);
+			goto go_on_filt;
+		}
+		card->dev->flags |= IFF_BROADCAST;
+		card->broadcast_capable = 1;
+	}
+go_on_filt:
+	if (card->options.checksum_type == HW_CHECKSUMMING) {
+		if (!qeth_is_supported(IPA_INBOUND_CHECKSUM)) {
+			PRINT_WARN("Inbound HW checksumming not "
+				   "supported on %s, continuing "
+				   "using inbound sw checksumming\n",
+				   card->dev_name);
+			QETH_DBF_TEXT2(0, trace, "ibckntsp");
+			card->options.checksum_type = SW_CHECKSUMMING;
+		} else {
+			QETH_DBF_TEXT2(0, trace, "ibcksupp");
+			result = qeth_send_setassparms_simple_without_data
+				(card, IPA_INBOUND_CHECKSUM,
+				 IPA_CMD_ASS_START);
+			if (result) {
+				PRINT_WARN("Could not start inbound "
+					   "checksumming on %s: 0x%x, "
+					   "continuing using "
+					   "inbound sw checksumming\n",
+					   card->dev_name, result);
+				sprintf(dbf_text, "SIBC%4x", result);
+				QETH_DBF_TEXT2(0, trace, dbf_text);
+				card->options.checksum_type = SW_CHECKSUMMING;
+				goto go_on_checksum;
+			}
+			result=qeth_send_setassparms_simple_with_data
+				(card,IPA_INBOUND_CHECKSUM,
+				 IPA_CMD_ASS_ENABLE, IPA_CHECKSUM_ENABLE_MASK);
+			if (result) {
+				PRINT_WARN("Could not enable inbound " \
+					   "checksumming on %s: 0x%x, " \
+					   "continuing using " \
+					   "inbound sw checksumming\n",
+					   card->dev_name,result);
+				sprintf(dbf_text,"EIBC%4x",result);
+				QETH_DBF_TEXT2(0,trace,dbf_text);
+				card->options.checksum_type = SW_CHECKSUMMING;
+				goto go_on_checksum;
+
+			}
+		}
+	}
+go_on_checksum:	
+	atomic_set(&card->is_softsetup, 1);
+	return 0;
+}
+
+static inline void
+__qeth_softsetup_routingv4(struct qeth_card *card)
+{
+	int result;
+	char dbf_text[15];
+
+	if (!atomic_read(&card->enable_routing_attempts4))
+		return;
+
+	if (!card->options.routing_type4) {
+		atomic_set(&card->enable_routing_attempts4, 0);
+		atomic_set(&card->rt4fld, 0);
+		return;
+	}
+
+	sprintf(dbf_text, "strtg4%2x", card->options.routing_type4);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+	result = qeth_send_setrtg(card, card->options.routing_type4, 4);
+	if (!result) {	/* routing set correctly */
+		atomic_set(&card->enable_routing_attempts4, 0);
+		atomic_set(&card->rt4fld, 0);
+		return;
+	}
+	if (atomic_dec_return(&card->enable_routing_attempts4)) {
+		PRINT_WARN("couldn't set up v4 routing type "
+			   "on %s: 0x%x (%s).\nWill try "
+			   "next time again.\n",
+			   card->dev_name, result,
+			   ((result == 0xe010) || (result == 0xe008)) ?
+			   "primary already defined"
+			   : ((result == 0xe011) || (result == 0xe009)) ?
+			   "secondary already defined"
+			   : (result == 0xe012) ? "invalid indicator" :
+			   "unknown return code");
+		sprintf(dbf_text, "sRT4%4x", result);
+		atomic_set(&card->rt4fld, 1);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+	} else {
+		PRINT_WARN("couldn't set up v4 routing type "
+			   "on %s: 0x%x (%s).\nTrying to "
+			   "continue without routing.\n",
+			   card->dev_name, result,
+			   ((result == 0xe010) || (result == 0xe008)) ?
+			   "primary already defined"
+			   : ((result == 0xe011) || (result == 0xe009)) ?
+			   "secondary already defined"
+			   : (result == 0xe012) ? "invalid indicator" :
+			   "unknown return code");
+		sprintf(dbf_text, "SRT4%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		atomic_set(&card->rt4fld, 1);
+	}
+}
+
+static void
+__qeth_softsetup_routingv6(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	int result;
+	char dbf_text[15];
+
+	if (!atomic_read(&card->enable_routing_attempts6))
+		return;
+
+	if (!card->options.routing_type6) {
+		atomic_set(&card->enable_routing_attempts6, 0);
+		atomic_set(&card->rt6fld, 0);
+		return;
+	}
+	sprintf(dbf_text, "strtg6%2x", card->options.routing_type6);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+	result = qeth_send_setrtg(card, card->options.routing_type6, 6);
+	if (!result) {	/* routing set correctly */
+		atomic_set(&card->enable_routing_attempts6, 0);
+		atomic_set(&card->rt6fld, 0);
+		return;
+	}
+	if (atomic_dec_return(&card->enable_routing_attempts6)) {
+		PRINT_WARN("couldn't set up v6 routing type "
+			   "on %s: 0x%x (%s).\nWill try "
+			   "next time again.\n",
+			   card->dev_name, result,
+			   ((result == 0xe010) || (result == 0xe008)) ?
+			   "primary already defined"
+			   : ((result == 0xe011) || (result == 0xe009)) ?
+			   "secondary already defined"
+			   : (result == 0xe012) ? "invalid indicator" :
+			   "unknown return code");
+		sprintf(dbf_text, "sRT6%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		atomic_set(&card->rt6fld, 1);
+	} else {
+		PRINT_WARN("couldn't set up v6 routing type "
+			   "on %s: 0x%x (%s).\nTrying to "
+			   "continue without routing.\n",
+			   card->dev_name, result,
+			   ((result == 0xe010) || (result == 0xe008)) ?
+			   "primary already defined"
+			   : ((result == 0xe011) || (result == 0xe009)) ?
+			   "secondary already defined"
+			   : (result == 0xe012) ? "invalid indicator" :
+			   "unknown return code");
+		sprintf(dbf_text, "SRT6%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		atomic_set(&card->rt6fld, 1);
+	}
+#endif /* QETH_IPV6 */
+}
+
+static int
+qeth_softsetup_card(struct qeth_card *card, int wait_for_lock)
+{
+	int result;
+	char dbf_text[15];
+	int use_setip_retries = 1;
+
+	if (wait_for_lock == QETH_WAIT_FOR_LOCK) {
+		spin_lock(&card->softsetup_lock);
+	} else if (wait_for_lock == QETH_DONT_WAIT_FOR_LOCK) {
+		if (!spin_trylock(&card->softsetup_lock)) {
+			return -EAGAIN;
+		}
+	} else if (wait_for_lock == QETH_LOCK_ALREADY_HELD) {
+		use_setip_retries = 0;	/* we are in recovery and don't want
+					   to repeat setting ips on and on */
+	} else {
+		return -EINVAL;
+	}
+
+	qeth_save_dev_flag_state(card);
+
+	QETH_DBF_TEXT1(0, trace, wait_for_lock?"sscw":"sscn");
+	QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+
+	result = __qeth_softsetup_start_assists(card);
+	if (result)
+		goto out;
+
+	__qeth_softsetup_routingv4(card);
+	__qeth_softsetup_routingv6(card);
+
+	QETH_DBF_TEXT2(0, trace, "delvipa");
+	qeth_set_vipas(card, 0);
+	QETH_DBF_TEXT2(0, trace, "toip/ms");
+	qeth_takeover_ip_ipms(card);
+	qeth_takeover_ip_ipms6(card);
+	QETH_DBF_TEXT2(0, trace, "setvipa");
+	qeth_set_vipas(card, 1);
+
+	result = qeth_setips(card, use_setip_retries);
+	if (result) {		/* by now, qeth_setips does not return errors */
+		PRINT_WARN("couldn't set up IPs on %s: 0x%x\n",
+			   card->dev_name, result);
+		sprintf(dbf_text, "SSIP%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		atomic_set(&card->is_softsetup, 0);
+		goto out;
+	}
+	result = qeth_setipms(card, use_setip_retries);
+	if (result) {		/* by now, qeth_setipms does not return errors */
+		PRINT_WARN("couldn't set up multicast IPs on %s: 0x%x\n",
+			   card->dev_name, result);
+		sprintf(dbf_text, "ssim%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		atomic_set(&card->is_softsetup, 0);
+		goto out;
+	}
+out:
+	if (!result) {
+		netif_wake_queue(card->dev);
+	}
+	if (wait_for_lock != QETH_LOCK_ALREADY_HELD)
+		spin_unlock(&card->softsetup_lock);
+	return result;
+}
+
+static int
+qeth_softsetup_thread(void *param)
+{
+	char name[15];
+	struct qeth_card *card = (struct qeth_card *) param;
+
+	/* set a nice name ... */
+	sprintf(name, "qethsoftd%s", card->rdev->dev.bus_id);
+	daemonize(name);
+
+	QETH_DBF_TEXT2(0, trace, "ssth");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+	atomic_set(&card->softsetup_thread_is_running, 1);
+	for (;;) {
+		if (atomic_read(&card->shutdown_phase))
+			goto out;
+		down_interruptible(&card->softsetup_thread_sem);
+		QETH_DBF_TEXT2(0, trace, "ssst");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		if (atomic_read(&card->shutdown_phase))
+			goto out;
+		while (qeth_softsetup_card(card, QETH_DONT_WAIT_FOR_LOCK)
+		       == -EAGAIN) {
+			if (atomic_read(&card->shutdown_phase))
+				goto out;
+			qeth_wait_nonbusy(QETH_IDLE_WAIT_TIME);
+		}
+		QETH_DBF_TEXT2(0, trace, "sssd");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		netif_wake_queue(card->dev);
+	}
+out:
+	atomic_set(&card->softsetup_thread_is_running, 0);
+
+	QETH_DBF_TEXT2(0, trace, "lsst");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+	return 0;
+}
+
+static void
+qeth_softsetup_thread_starter(void *data)
+{
+	struct qeth_card *card = (struct qeth_card *) data;
+
+	QETH_DBF_TEXT4(0, trace, "ssts");
+	QETH_DBF_TEXT4(0, trace, card->rdev->dev.bus_id);
+	sema_init(&card->softsetup_thread_sem, 0);
+	kernel_thread(qeth_softsetup_thread, card, SIGCHLD);
+}
+
+static void
+qeth_start_reinit_thread(struct qeth_card *card)
+{
+	/* we allow max 2 reinit threads, one could be just about to
+	 * finish and the next would be waiting. another waiting
+	 * reinit_thread is not necessary. */
+	if (atomic_read(&card->reinit_counter) < 2) {
+		atomic_inc(&card->reinit_counter);
+		if (atomic_read(&card->shutdown_phase)) {
+			atomic_dec(&card->reinit_counter);
+			return;
+		}
+		QETH_DBF_TEXT2(0, trace, "stri");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		PRINT_STUPID("starting reinit-thread\n");
+		kernel_thread(qeth_reinit_thread, card, SIGCHLD);
+	}
+}
+
+static void
+qeth_recover(void *data)
+{
+	struct qeth_card *card;
+	int i;
+	char dbf_text[15];
+
+	card = (struct qeth_card *) data;
+
+	QETH_DBF_TEXT2(0, trace, "recv");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+	if (atomic_compare_and_swap(0, 1, &card->in_recovery))
+		return;
+
+	i = atomic_read(&card->problem);
+
+	sprintf(dbf_text, "PROB%4x", i);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+
+	if (i != PROBLEM_TX_TIMEOUT)
+		PRINT_WARN("recovery was scheduled on device %s (%s) with "
+			   "problem 0x%x\n",
+			   card->rdev->dev.bus_id, card->dev_name, i);
+	switch (i) {
+	case PROBLEM_RECEIVED_IDX_TERMINATE:
+		if (atomic_read(&card->in_recovery))
+			atomic_set(&card->break_out, QETH_BREAKOUT_AGAIN);
+		break;
+	case PROBLEM_CARD_HAS_STARTLANED:
+		PRINT_WARN("You are lucky! Somebody either fixed the "
+			   "network problem, plugged the cable back in "
+			   "or enabled the OSA port on %s (CHPID 0x%X). "
+			   "The link has come up.\n",
+			   card->dev_name, card->chpid);
+		sprintf(dbf_text, "CBIN%4x", i);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		atomic_set(&card->is_softsetup, 0);
+		qeth_set_dev_flag_running(card);
+		atomic_set(&card->enable_routing_attempts4,
+			   QETH_ROUTING_ATTEMPTS);
+		qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa);
+#ifdef QETH_IPV6
+		atomic_set(&card->enable_routing_attempts6,
+			   QETH_ROUTING_ATTEMPTS);
+		qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa);
+#endif /* QETH_IPV6 */
+		qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa);
+#ifdef QETH_IPV6
+		qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa);
+#endif /* QETH_IPV6 */
+		qeth_refresh_vipa_states(card);
+		qeth_start_softsetup_thread(card);
+		atomic_set(&card->in_recovery, 0);
+		break;
+	case PROBLEM_RESETTING_EVENT_INDICATOR:
+		/* we do nothing here */
+		break;
+	case PROBLEM_ACTIVATE_CHECK_CONDITION:
+	case PROBLEM_GENERAL_CHECK:
+	case PROBLEM_USER_TRIGGERED_RECOVERY:
+	case PROBLEM_AFFE:
+	case PROBLEM_MACHINE_CHECK:
+	case PROBLEM_BAD_SIGA_RESULT:
+	case PROBLEM_TX_TIMEOUT:
+		qeth_start_reinit_thread(card);
+		break;
+	}
+}
+
+static void
+qeth_schedule_recovery(struct qeth_card *card)
+{
+	if (card) {
+		INIT_WORK(&card->tqueue, qeth_recover, card);
+		schedule_work(&card->tqueue);
+	} else {
+		QETH_DBF_TEXT2(1, trace, "scdnocrd");
+		PRINT_WARN("recovery requested to be scheduled "
+			   "with no card!\n");
+	}
+}
+
+static void
+qeth_qdio_input_handler(struct ccw_device *cdev, unsigned int status,
+			unsigned int qdio_error, unsigned int siga_error,
+			unsigned int queue,
+			int first_element, int count, unsigned long card_ptr)
+{
+	struct net_device *dev;
+	struct qeth_card *card;
+	int problem;
+	int sbalf15;
+	char dbf_text[15];
+
+	sprintf(dbf_text, "qibhn%s", cdev->dev.bus_id);
+	QETH_DBF_HEX6(0, trace, dbf_text, QETH_DBF_TRACE_LEN);
+
+	card = (struct qeth_card *) card_ptr;
+
+#ifdef QETH_PERFORMANCE_STATS
+	card->perf_stats.inbound_start_time = NOW;
+#endif /* QETH_PERFORMANCE_STATS */
+	dev = card->dev;
+
+	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
+			problem = PROBLEM_ACTIVATE_CHECK_CONDITION;
+			atomic_set(&card->problem, problem);
+			QETH_DBF_TEXT1(0, trace, "IHACTQCK");
+			sprintf(dbf_text, "%4x%4x", first_element, count);
+			QETH_DBF_TEXT1(0, trace, dbf_text);
+			sprintf(dbf_text, "%4x%4x", queue, status);
+			QETH_DBF_TEXT1(0, trace, dbf_text);
+			QETH_DBF_TEXT1(1, trace, "qscd");
+			QETH_DBF_TEXT1(1, trace, card->rdev->dev.bus_id);
+			qeth_schedule_recovery(card);
+			return;
+		}
+		sbalf15 = (card->inbound_qdio_buffers[(first_element + count - 1)
+						      & QDIO_MAX_BUFFERS_PER_Q].
+			   element[15].flags) && 0xff;
+		PRINT_STUPID("inbound qdio transfer error on device %s. "
+			     "qdio_error=0x%x (more than one: %c), "
+			     "siga_error=0x%x (more than one: %c), "
+			     "sbalf15=x%x, bufno=x%x\n", cdev->dev.bus_id,
+			     qdio_error,
+			     (status & QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR) ?
+			     'y' : 'n', siga_error,
+			     (status & QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR) ?
+			     'y' : 'n', sbalf15, first_element);
+		QETH_DBF_TEXT1(0, trace, "IQTI");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		QETH_DBF_TEXT1(0, qerr, "IQTI");
+		QETH_DBF_TEXT1(0, qerr, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x%4x", first_element, count);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_TEXT1(0, qerr, dbf_text);
+		sprintf(dbf_text, "%2x%4x%2x", queue, status, sbalf15);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_TEXT1(0, qerr, dbf_text);
+		sprintf(dbf_text, "%4x%4x", qdio_error, siga_error);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_TEXT1(0, qerr, dbf_text);
+		/* we inform about error more detailed in
+		 * qeth_read_in_buffer() */
+	}
+
+	for (;;) {
+		qeth_read_in_buffer(card, first_element);
+		qeth_queue_input_buffer(card, first_element,
+					QDIO_FLAG_UNDER_INTERRUPT);
+		count--;
+		if (count)
+			first_element = (first_element + 1) &
+			    (QDIO_MAX_BUFFERS_PER_Q - 1);
+		else
+			break;
+	}
+}
+
+static void
+__qeth_try_to_flush_packets(struct qeth_card *card, int last_pci_hit,
+			    unsigned int queue)
+{
+	int switch_state;
+
+	switch_state = (atomic_read(&card->outbound_used_buffers[queue]) <=
+			LOW_WATERMARK_PACK);
+	/* first_element is the last buffer that we got back from hydra */
+	if (!switch_state && !last_pci_hit)
+		return;;
+	QETH_DBF_TEXT3(0, trace, "stchcw");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+	if (atomic_swap(&card->outbound_ringbuffer_lock[queue], QETH_LOCK_FLUSH)
+	    == QETH_LOCK_UNLOCKED) {
+		/* 
+		 * we stop the queue as we try to not run onto the 
+		 * outbound_ringbuffer_lock -- this will not prevent it totally,
+		 * but reduce it. in high traffic situations, it saves around
+		 * 20us per second, hopefully this is amortized by calling 
+		 * netif_...
+		 */
+		netif_stop_queue(card->dev);
+		qeth_flush_packed_packets(card, queue,
+					  QDIO_FLAG_UNDER_INTERRUPT);
+		/* 
+		 * only switch state to non-packing, if the amount of used
+		 * buffers decreased
+		 */
+		if (switch_state)
+			card->send_state[queue] = SEND_STATE_DONT_PACK;
+		netif_wake_queue(card->dev);
+		atomic_set(&card->outbound_ringbuffer_lock[queue],
+			   QETH_LOCK_UNLOCKED);
+	}
+	/* 
+	 * if the lock was UNLOCKED, we flush ourselves, otherwise this is done
+	 * in do_send_packet when the lock is released
+	 */
+#ifdef QETH_PERFORMANCE_STATS
+	card->perf_stats.sc_p_dp++;
+#endif /* QETH_PERFORMANCE_STATS */
+}
+
+static void
+qeth_qdio_output_handler(struct ccw_device *cdev,
+			 unsigned int status,
+			 unsigned int qdio_error,
+			 unsigned int siga_error,
+			 unsigned int queue,
+			 int first_element, int count, unsigned long card_ptr)
+{
+	struct qeth_card *card;
+	int mycnt, problem, buffers_used;
+	int sbalf15;
+	char dbf_text[15];
+	int last_pci_hit = 0;
+	int last_pci;
+
+	sprintf(dbf_text, "qouthn%s", cdev->dev.bus_id);
+	QETH_DBF_HEX6(0, trace, dbf_text, QETH_DBF_TRACE_LEN);
+
+	mycnt = count;
+	card = (struct qeth_card *) card_ptr;
+
+	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
+			problem = PROBLEM_ACTIVATE_CHECK_CONDITION;
+			atomic_set(&card->problem, problem);
+			QETH_DBF_TEXT1(0, trace, "OHACTQCK");
+			sprintf(dbf_text, "%4x%4x", first_element, count);
+			QETH_DBF_TEXT1(0, trace, dbf_text);
+			sprintf(dbf_text, "%4x%4x", queue, status);
+			QETH_DBF_TEXT1(0, trace, dbf_text);
+			QETH_DBF_TEXT1(1, trace, "qscd");
+			QETH_DBF_TEXT1(1, trace, card->rdev->dev.bus_id);
+			qeth_schedule_recovery(card);
+			goto out;
+		}
+		sbalf15 = (card->outbound_ringbuffer[queue]->
+			   buffer[(first_element + count - 1) & QDIO_MAX_BUFFERS_PER_Q].
+			   element[15].flags) & 0xff;
+		PRINT_STUPID("outbound qdio transfer error on device %s, "
+			     "queue=%i. qdio_error=0x%x (more than one: %c),"
+			     " siga_error=0x%x (more than one: %c), "
+			     "sbalf15=x%x, bufno=x%x\n",
+			     cdev->dev.bus_id, queue, qdio_error, status &
+			     QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR ? 'y' : 'n',
+			     siga_error, status &
+			     QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR ? 'y' : 'n',
+			     sbalf15, first_element);
+		QETH_DBF_TEXT1(0, trace, "IQTO");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		QETH_DBF_TEXT1(0, qerr, "IQTO");
+		QETH_DBF_TEXT1(0, qerr, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x%4x", first_element, count);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_TEXT1(0, qerr, dbf_text);
+		sprintf(dbf_text, "%2x%4x%2x", queue, status, sbalf15);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_TEXT1(0, qerr, dbf_text);
+		sprintf(dbf_text, "%4x%4x", qdio_error, siga_error);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_TEXT1(0, qerr, dbf_text);
+		/* we maybe do recovery or dst_link_failures
+		 * in qeth_free_buffer */
+	}
+
+	if (mycnt) {
+		last_pci = atomic_read(&card->last_pci_pos[queue]);
+		for (;;) {
+			qeth_free_buffer(card, queue, first_element,
+					 qdio_error, siga_error);
+			if (first_element == last_pci)
+				last_pci_hit = 1;
+			mycnt--;
+			if (mycnt > 0)
+				first_element = (first_element + 1) &
+				    (QDIO_MAX_BUFFERS_PER_Q - 1);
+			else
+				break;
+		}
+	}
+
+	buffers_used = atomic_return_sub(count,
+					 &card->outbound_used_buffers[queue]);
+
+	switch (card->send_state[queue]) {
+	case SEND_STATE_PACK:
+		__qeth_try_to_flush_packets(card, last_pci_hit, queue);
+		break;
+	default:
+		break;
+	}
+
+	/* we don't have to start the queue, if it was started already */
+	if (buffers_used < QDIO_MAX_BUFFERS_PER_Q - 1)
+		return;
+
+out:
+	netif_wake_queue(card->dev);
+}
+
+static long
+__qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb)
+{
+	if (!IS_ERR(irb))
+		return 0;
+
+	switch (PTR_ERR(irb)) {
+	case -EIO:
+		PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
+		break;
+	case -ETIMEDOUT:
+		PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
+		break;
+	default:
+		PRINT_WARN("unknown error %d on device %s\n", PTR_ERR(irb),
+			   cdev->dev.bus_id);
+	}
+	return PTR_ERR(irb);
+}
+
+static void
+qeth_interrupt_handler_read(struct ccw_device *cdev, unsigned long intparm,
+			    struct irb *irb)
+{
+	int cstat, dstat;
+	int problem;
+	struct qeth_card *card;
+	int rqparam;
+	char dbf_text[15];
+	int result;
+
+	if (__qeth_check_irb_error(cdev, irb))
+		return;
+
+	cstat = irb->scsw.cstat;
+	dstat = irb->scsw.dstat;
+	rqparam = intparm;
+
+	sprintf(dbf_text, "rint%s", cdev->dev.bus_id);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+	sprintf(dbf_text, "%4x%4x", cstat, dstat);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+	sprintf(dbf_text, "%4x", rqparam);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+
+	card = cdev->dev.driver_data;
+	if (!card)
+		return;
+
+	if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) {
+		atomic_set(&card->clear_succeeded0, 1);
+		wake_up(&card->wait_q);
+		return;
+	}
+
+	if (!rqparam) {
+		PRINT_STUPID("got unsolicited interrupt in read handler "
+			     "for %s\n", cdev->dev.bus_id);
+		return;
+	}
+
+	if ((dstat == 0) && (cstat == 0))
+		return;
+
+	if (irb->esw.esw0.erw.cons) {
+		PRINT_WARN("sense data available on read channel.\n");
+		HEXDUMP16(WARN, "irb: ", irb);
+		HEXDUMP16(WARN, "sense data: ", irb->ecw);
+		sprintf(dbf_text, "RSNS%s", cdev->dev.bus_id);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_HEX0(0, sense, irb, QETH_DBF_SENSE_LEN);
+	}
+
+	if (cstat != 0) {
+		PRINT_WARN("got nonzero-nonpci channel status in read_"
+			   "handler (device %s, devstat 0x%02x, schstat "
+			   "0x%02x, rqparam 0x%x)\n", cdev->dev.bus_id,
+			   dstat, cstat, rqparam);
+	}
+
+	problem = qeth_get_cards_problem(cdev, card->dma_stuff->recbuf,
+					 dstat, cstat, rqparam,
+					 (char *) irb, (char *) irb->ecw);
+
+	/* detect errors in dstat here */
+	if ((dstat & DEV_STAT_UNIT_EXCEP) || (dstat & DEV_STAT_UNIT_CHECK)) {
+		PRINT_WARN("unit check/exception in read_handler "
+			   "(device %s, devstat 0x%02x, schstat 0x%02x, "
+			   "rqparam 0x%x)\n",
+			   cdev->dev.bus_id, dstat, cstat, rqparam);
+
+		if (!atomic_read(&card->is_hardsetup)) {
+			if ((problem) && (qeth_is_to_recover(card, problem)))
+				atomic_set(&card->break_out,
+					   QETH_BREAKOUT_AGAIN);
+			else
+				atomic_set(&card->break_out,
+					   QETH_BREAKOUT_LEAVE);
+			goto wakeup_out;
+		} else
+			goto recover;
+	}
+
+	if (!(dstat & DEV_STAT_CHN_END)) {
+		PRINT_WARN("didn't get device end in read_handler "
+			   "(device %s, devstat 0x%02x, schstat 0x%02x, "
+			   "rqparam 0x%x)\n",
+			   cdev->dev.bus_id, dstat, cstat, rqparam);
+		goto wakeup_out;
+	}
+
+	if ((rqparam == IDX_ACTIVATE_WRITE_STATE) || (rqparam == NOP_STATE)) {
+		goto wakeup_out;
+	}
+
+	/* at this point, (maybe channel end and) device end has appeared */
+
+	/* we don't start the next read until we have examined the buffer. */
+	if ((rqparam != IDX_ACTIVATE_READ_STATE) &&
+	    (rqparam != IDX_ACTIVATE_WRITE_STATE))
+		qeth_issue_next_read(card);
+
+recover:
+	if (qeth_is_to_recover(card, problem)) {
+		QETH_DBF_TEXT2(1, trace, "rscd");
+		QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id);
+		qeth_schedule_recovery(card);
+		goto wakeup_out;
+	}
+
+	if (!IS_IPA(card->dma_stuff->recbuf) ||
+	    IS_IPA_REPLY(card->dma_stuff->recbuf)) {
+		/* setup or unknown data */
+		result = qeth_look_for_arp_data(card);
+		switch (result) {
+		case ARP_RETURNCODE_ERROR:
+		case ARP_RETURNCODE_LASTREPLY:
+			qeth_wakeup_ioctl(card);
+			return;
+		default:
+			break;
+		}
+	}
+
+wakeup_out:
+	memcpy(card->ipa_buf, card->dma_stuff->recbuf, QETH_BUFSIZE);
+	qeth_wakeup(card);
+}
+
+static void
+qeth_interrupt_handler_write(struct ccw_device *cdev, unsigned long intparm,
+			     struct irb *irb)
+{
+	int cstat, dstat, rqparam;
+	struct qeth_card *card;
+	int problem;
+	char dbf_text[15];
+
+	if (__qeth_check_irb_error(cdev, irb))
+		return;
+
+	cstat = irb->scsw.cstat;
+	dstat = irb->scsw.dstat;
+	rqparam = intparm;
+
+	sprintf(dbf_text, "wint%s", cdev->dev.bus_id);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+	sprintf(dbf_text, "%4x%4x", cstat, dstat);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+	sprintf(dbf_text, "%4x", rqparam);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+
+	card = cdev->dev.driver_data;
+	if (!card)
+		return;
+
+	if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) {
+		atomic_set(&card->clear_succeeded1, 1);
+		wake_up(&card->wait_q);
+		goto out;
+	}
+
+	if (!rqparam) {
+		PRINT_STUPID("got unsolicited interrupt in write handler "
+			     "for %s\n", cdev->dev.bus_id);
+		return;
+	}
+
+	if ((dstat == 0) && (cstat == 0))
+		goto out;
+
+	if (irb->esw.esw0.erw.cons) {
+		PRINT_WARN("sense data available on write channel.\n");
+		HEXDUMP16(WARN, "irb: ", irb);
+		HEXDUMP16(WARN, "sense data: ", irb->ecw);
+		sprintf(dbf_text, "WSNS%s", cdev->dev.bus_id);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_HEX0(0, sense, irb, QETH_DBF_SENSE_LEN);
+	}
+
+	if (cstat != 0) {
+		PRINT_WARN("got nonzero channel status in write_handler "
+			   "(device %s, devstat 0x%02x, schstat 0x%02x, "
+			   "rqparam 0x%x)\n",
+			   cdev->dev.bus_id, dstat, cstat, rqparam);
+	}
+
+	problem = qeth_get_cards_problem(cdev, NULL,
+					 dstat, cstat, rqparam,
+					 (char *) irb, (char *) irb->ecw);
+
+	/* detect errors in dstat here */
+	if ((dstat & DEV_STAT_UNIT_EXCEP) || (dstat & DEV_STAT_UNIT_CHECK)) {
+		PRINT_WARN("unit check/exception in write_handler "
+			   "(device %s, devstat 0x%02x, schstat 0x%02x, "
+			   "rqparam 0x%x)\n",
+			   cdev->dev.bus_id, dstat, cstat, rqparam);
+		if (!atomic_read(&card->is_hardsetup)) {
+			if (problem == PROBLEM_RESETTING_EVENT_INDICATOR) {
+				atomic_set(&card->break_out,
+					   QETH_BREAKOUT_AGAIN);
+				qeth_wakeup(card);
+				goto out;
+			}
+			atomic_set(&card->break_out, QETH_BREAKOUT_LEAVE);
+			goto out;
+		} else
+			goto recover;
+	}
+
+	if (dstat == DEV_STAT_DEV_END)
+		goto out;
+
+	if (!(dstat & DEV_STAT_CHN_END)) {
+		PRINT_WARN("didn't get device end in write_handler "
+			   "(device %s, devstat 0x%02x, schstat 0x%02x, "
+			   "rqparam 0x%x)\n",
+			   cdev->dev.bus_id, dstat, cstat, rqparam);
+		goto out;
+	}
+
+recover:
+	if (qeth_is_to_recover(card, problem)) {
+		QETH_DBF_TEXT2(1, trace, "wscd");
+		QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id);
+		qeth_schedule_recovery(card);
+		goto out;
+	}
+
+	/* at this point, (maybe channel end and) device end has appeared */
+	if ((rqparam == IDX_ACTIVATE_READ_STATE) ||
+	    (rqparam == IDX_ACTIVATE_WRITE_STATE) || (rqparam == NOP_STATE)) {
+		qeth_wakeup(card);
+		goto out;
+	}
+
+	/* well, a write has been done successfully. */
+
+out:
+	/* all statuses are final statuses on the write channel */
+	atomic_set(&card->write_busy, 0);
+}
+
+static void
+qeth_interrupt_handler_qdio(struct ccw_device *cdev, unsigned long intparm,
+			    struct irb *irb)
+{
+	int cstat, dstat, rqparam;
+	char dbf_text[15];
+	struct qeth_card *card;
+
+	if (__qeth_check_irb_error(cdev, irb))
+		return;
+
+	cstat = irb->scsw.cstat;
+	dstat = irb->scsw.dstat;
+	rqparam = intparm;
+
+	sprintf(dbf_text, "qint%s", cdev->dev.bus_id);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+	sprintf(dbf_text, "%4x%4x", cstat, dstat);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+	sprintf(dbf_text, "%4x", rqparam);
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+
+	card = cdev->dev.driver_data;
+	if (!card)
+		return;
+
+	if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) {
+		atomic_set(&card->clear_succeeded2, 1);
+		wake_up(&card->wait_q);
+		return;
+	}
+
+	if (!rqparam) {
+		PRINT_STUPID("got unsolicited interrupt in qdio handler, "
+			     "device%s\n", cdev->dev.bus_id);
+		return;
+	}
+
+	if ((dstat == 0) && (cstat == 0))
+		return;
+
+	if (irb->esw.esw0.erw.cons) {
+		PRINT_WARN("sense data available on qdio channel.\n");
+		HEXDUMP16(WARN, "irb: ", irb);
+		HEXDUMP16(WARN, "sense data: ", irb->ecw);
+		sprintf(dbf_text, "QSNS%s", cdev->dev.bus_id);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		QETH_DBF_HEX0(0, sense, irb, QETH_DBF_SENSE_LEN);
+	}
+
+	if ((rqparam == READ_CONF_DATA_STATE) || (rqparam == NOP_STATE)) {
+		qeth_wakeup(card);
+		return;
+	}
+
+	if (cstat != 0) {
+		sprintf(dbf_text, "qchk%s", cdev->dev.bus_id);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		sprintf(dbf_text, "%4x%4x", cstat, dstat);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		sprintf(dbf_text, "%4x", rqparam);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		PRINT_WARN("got nonzero channel status in qdio_handler "
+			   "(device %s, devstat 0x%02x, schstat 0x%02x)\n",
+			   cdev->dev.bus_id, dstat, cstat);
+	}
+
+	if (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) {
+		PRINT_WARN("got the following dstat on the qdio channel: "
+			   "device %s, dstat 0x%02x, cstat 0x%02x, "
+			   "rqparam=%i\n",
+			   cdev->dev.bus_id, dstat, cstat, rqparam);
+	}
+
+}
+
+static int
+qeth_register_netdev(struct qeth_card *card)
+{
+	int result;
+
+	QETH_DBF_TEXT3(0, trace, "rgnd");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	result = register_netdev(card->dev);
+
+	return result;
+}
+
+static void
+qeth_unregister_netdev(struct qeth_card *card)
+{
+	QETH_DBF_TEXT3(0, trace, "nrgn");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	unregister_netdev(card->dev);
+}
+
+static int
+qeth_stop(struct net_device *dev)
+{
+	struct qeth_card *card;
+
+	card = (struct qeth_card *) dev->priv;
+	QETH_DBF_TEXT2(0, trace, "stop");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_TEXT2(0, setup, "stop");
+	QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id);
+
+	qeth_save_dev_flag_state(card);
+
+	netif_stop_queue(dev);
+	atomic_set(&((struct qeth_card *) dev->priv)->is_open, 0);
+
+	return 0;
+}
+
+static void
+qeth_softshutdown(struct qeth_card *card)
+{
+	QETH_DBF_TEXT3(0, trace, "ssht");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	qeth_send_stoplan(card);
+}
+
+static void
+__qeth_clear_card_halt_clear(struct qeth_card *card, int halt)
+{
+	unsigned long flags0, flags1, flags2;
+	int ret0, ret1, ret2;
+
+	atomic_set(&card->clear_succeeded0, 0);
+	atomic_set(&card->clear_succeeded1, 0);
+	atomic_set(&card->clear_succeeded2, 0);
+	
+	spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags0);
+	if (halt)
+		ret0 = ccw_device_halt(card->rdev, CLEAR_STATE);
+	else
+		ret0 = ccw_device_clear(card->rdev, CLEAR_STATE);
+	spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags0);
+	
+	spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags1);
+	if (halt)
+		ret1 = ccw_device_halt(card->wdev, CLEAR_STATE);
+	else
+		ret1 = ccw_device_clear(card->wdev, CLEAR_STATE);
+	spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags1);
+	
+	spin_lock_irqsave(get_ccwdev_lock(card->ddev), flags2);
+	if (halt)
+		ret2 = ccw_device_halt(card->ddev, CLEAR_STATE);
+	else
+		ret2 = ccw_device_clear(card->ddev, CLEAR_STATE);
+	spin_unlock_irqrestore(get_ccwdev_lock(card->ddev), flags2);
+
+	/* The device owns us an interrupt. */
+	if ((ret0 == 0) && (atomic_read(&card->clear_succeeded0) == 0))
+		wait_event(card->wait_q,
+			   atomic_read(&card->clear_succeeded0) == 1);
+	if ((ret1 == 0) && (atomic_read(&card->clear_succeeded1) == 0))
+		wait_event(card->wait_q,
+			   atomic_read(&card->clear_succeeded1) == 1);
+	if ((ret2 == 0) && (atomic_read(&card->clear_succeeded2) == 0))
+		wait_event(card->wait_q,
+			   atomic_read(&card->clear_succeeded2) == 1);
+}
+
+static void
+qeth_clear_card(struct qeth_card *card, int qdio_clean, int use_halt)
+{
+	QETH_DBF_TEXT3(0, trace, qdio_clean?"clrq":"clr");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_TEXT1(0, setup, qdio_clean?"clrq":"clr");
+	QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id);
+
+	atomic_set(&card->write_busy, 0);
+	if (qdio_clean)
+		qdio_cleanup(card->ddev,
+			     (card->type == QETH_CARD_TYPE_IQD) ?
+			     QDIO_FLAG_CLEANUP_USING_HALT :
+			     QDIO_FLAG_CLEANUP_USING_CLEAR);
+
+	if (use_halt)
+		__qeth_clear_card_halt_clear(card, 1);
+
+	__qeth_clear_card_halt_clear(card, 0);
+}
+
+static void
+qeth_free_card(struct qeth_card *card)
+{
+	int i, j;
+	int element_count;
+	struct qeth_vipa_entry *e, *e2;
+
+	if (!card)
+		return;
+
+	QETH_DBF_TEXT3(0, trace, "free");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_TEXT1(0, setup, "free");
+	QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id);
+
+	write_lock(&card->vipa_list_lock);
+	e = card->vipa_list;
+	while (e) {
+		e2 = e->next;
+		kfree(e);
+		e = e2;
+	}
+	write_unlock(&card->vipa_list_lock);
+
+	element_count = (card->options.memusage == MEMUSAGE_DISCONTIG) ?
+	    BUFFER_MAX_ELEMENTS : 1;
+	for (i = 0; i < card->options.inbound_buffer_count; i++) {
+		for (j = 0; j < element_count; j++) {
+			if (card->inbound_buffer_pool_entry[i][j]) {
+				kfree(card->inbound_buffer_pool_entry[i][j]);
+				card->inbound_buffer_pool_entry[i][j] = NULL;
+			}
+		}
+	}
+	for (i = 0; i < card->no_queues; i++)
+		if (card->outbound_ringbuffer[i])
+			vfree(card->outbound_ringbuffer[i]);
+
+	if (card->stats)
+		kfree(card->stats);
+	if (card->dma_stuff)
+		kfree(card->dma_stuff);
+	if (card->dev)
+		kfree(card->dev);
+	vfree(card);		/* we checked against NULL already */
+}
+
+/* also locked from outside (setup_lock) */
+static void
+qeth_remove_card_from_list(struct qeth_card *card)
+{
+	struct qeth_card *cn;
+	unsigned long flags0, flags1, flags2;
+
+	write_lock(&list_lock);
+	if (!card) {
+		QETH_DBF_TEXT2(0, trace, "RMCWNOCD");
+		PRINT_WARN("qeth_remove_card_from_list call with no card!\n");
+		write_unlock(&list_lock);
+		return;
+	}
+
+	QETH_DBF_TEXT3(0, trace, "rmcl");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	/* check first, if card is in list */
+	if (!firstcard) {
+		QETH_DBF_TEXT2(0, trace, "NOCRDINL");
+		PRINT_WARN
+		    ("qeth_remove_card_from_list called on empty card list!!\n");
+		write_unlock(&list_lock);
+		return;
+	}
+
+	spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags0);
+	spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags1);
+	spin_lock_irqsave(get_ccwdev_lock(card->ddev), flags2);
+
+	if (firstcard == card)
+		firstcard = card->next;
+	else {
+		cn = firstcard;
+		while (cn->next) {
+			if (cn->next == card) {
+				cn->next = card->next;
+				card->next = NULL;
+				break;
+			}
+			cn = cn->next;
+		}
+	}
+
+	spin_unlock_irqrestore(get_ccwdev_lock(card->ddev), flags2);
+	spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags1);
+	spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags0);
+
+	write_unlock(&list_lock);
+
+}
+
+static void
+qeth_delete_all_ips(struct qeth_card *card)
+{
+	struct qeth_vipa_entry *e;
+
+	if (atomic_read(&card->is_softsetup)) {
+		qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa);
+		qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa);
+
+#ifdef QETH_IPV6
+		qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa);
+		qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa);
+#endif /* QETH_IPV6 */
+
+		write_lock(&card->vipa_list_lock);
+		e = card->vipa_list;
+		while (e) {
+			e->state = VIPA_2_B_REMOVED;
+			e = e->next;
+		}
+		write_unlock(&card->vipa_list_lock);
+		qeth_start_softsetup_thread(card);
+	}
+}
+
+static void
+qeth_remove_card(struct qeth_card *card, int method)
+{
+	if (!card)
+		return;
+
+	QETH_DBF_TEXT2(0, trace, "rmcd");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_TEXT1(0, setup, "rmcd");
+	QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id);
+
+	if (method == QETH_REMOVE_CARD_PROPER) {
+		atomic_set(&card->shutdown_phase, QETH_REMOVE_CARD_PROPER);
+		if (atomic_read(&card->is_open)) {
+			qeth_stop(card->dev);
+			qeth_wait_nonbusy(QETH_REMOVE_WAIT_TIME);
+		}
+		qeth_delete_all_ips(card);
+	} else {
+		atomic_set(&card->shutdown_phase, QETH_REMOVE_CARD_QUICK);
+	}
+	atomic_set(&card->write_busy, 0);
+
+	QETH_DBF_TEXT4(0, trace, "freeskbs");
+	qeth_free_all_skbs(card);
+
+	QETH_DBF_TEXT2(0, trace, "upthrsem");
+
+	up(&card->softsetup_thread_sem);
+	up(&card->reinit_thread_sem);
+	while ((atomic_read(&card->softsetup_thread_is_running)) ||
+	       (atomic_read(&card->reinit_counter))) {
+		qeth_wait_nonbusy(QETH_WAIT_FOR_THREAD_TIME);
+	}
+
+	if (method == QETH_REMOVE_CARD_PROPER) {
+		QETH_DBF_TEXT4(0, trace, "softshut");
+		qeth_softshutdown(card);
+		qeth_wait_nonbusy(QETH_REMOVE_WAIT_TIME);
+	}
+
+	atomic_set(&card->is_startlaned, 0);	/* paranoia, qeth_stop
+						   should prevent
+						   further calls of
+						   hard_start_xmit */
+
+	if (atomic_read(&card->is_registered)) {
+		QETH_DBF_TEXT2(0, trace, "unregdev");
+		qeth_unregister_netdev(card);
+		qeth_wait_nonbusy(QETH_REMOVE_WAIT_TIME);
+		atomic_set(&card->is_registered, 0);
+	}
+
+	qeth_put_unique_id(card);
+
+	QETH_DBF_TEXT2(0, trace, "clrcard");
+	if (atomic_read(&card->is_hardsetup)) {
+		PRINT_STUPID("clearing card %s\n", card->dev_name);
+		qeth_clear_card(card, 1, 0);
+	}
+
+	atomic_set(&card->is_hardsetup, 0);
+	atomic_set(&card->is_softsetup, 0);
+
+	QETH_DBF_TEXT2(0, trace, "cardrmvd");
+
+}
+
+static void
+qeth_destructor(struct net_device *dev)
+{
+	struct qeth_card *card;
+
+	card = (struct qeth_card *) (dev->priv);
+	QETH_DBF_TEXT2(0, trace, "dstr");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+}
+
+static void
+qeth_set_multicast_list(struct net_device *dev)
+{
+	struct qeth_card *card = dev->priv;
+
+	QETH_DBF_TEXT2(0, trace, "smcl");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+	qeth_start_softsetup_thread(card);
+}
+
+static int
+qeth_set_mac_address(struct net_device *dev, void *addr)
+{
+	struct qeth_card *card;
+
+	card = (struct qeth_card *) dev->priv;
+	QETH_DBF_TEXT2(0, trace, "stmc");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+	return -EOPNOTSUPP;
+}
+
+static int
+qeth_neigh_setup(struct net_device *dev, struct neigh_parms *np)
+{
+	struct qeth_card *card;
+
+	card = (struct qeth_card *) dev->priv;
+	QETH_DBF_TEXT2(0, trace, "ngst");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+	return 0;
+}
+
+static void
+qeth_generate_tokens(struct qeth_card *card)
+{
+	card->token.issuer_rm_w = 0x00010103UL;
+	card->token.cm_filter_w = 0x00010108UL;
+	card->token.cm_connection_w = 0x0001010aUL;
+	card->token.ulp_filter_w = 0x0001010bUL;
+	card->token.ulp_connection_w = 0x0001010dUL;
+}
+
+static int
+qeth_peer_func_level(int level)
+{
+	if ((level & 0xff) == 8)
+		return (level & 0xff) + 0x400;
+	if (((level >> 8) & 3) == 1)
+		return (level & 0xff) + 0x200;
+	return level;		/* hmmm... don't know what to do with that level. */
+}
+
+static int
+qeth_idx_activate_read(struct qeth_card *card)
+{
+	int result, result2;
+	__u16 temp;
+	unsigned long flags;
+	char dbf_text[15];
+
+	result = result2 = 0;
+
+	memcpy(&card->dma_stuff->write_ccw, WRITE_CCW, sizeof (struct ccw1));
+	card->dma_stuff->write_ccw.count = IDX_ACTIVATE_SIZE;
+	card->dma_stuff->write_ccw.cda =
+	    QETH_GET_ADDR(card->dma_stuff->sendbuf);
+
+	memcpy(card->dma_stuff->sendbuf, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE);
+	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(card->dma_stuff->sendbuf),
+	       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+
+	memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(card->dma_stuff->sendbuf),
+	       &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->sendbuf),
+	       &card->func_level, 2);
+
+	temp = _ccw_device_get_device_number(card->ddev);
+	memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(card->dma_stuff->sendbuf), &temp, 2);
+	temp = (card->cula << 8) + card->unit_addr2;
+	memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(card->dma_stuff->sendbuf),
+	       &temp, 2);
+
+	QETH_DBF_TEXT2(0, trace, "iarw");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_HEX2(0, control, card->dma_stuff->sendbuf,
+		      QETH_DBF_CONTROL_LEN);
+
+	spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags);
+	result = ccw_device_start(card->rdev, &card->dma_stuff->write_ccw,
+				  IDX_ACTIVATE_WRITE_STATE, 0, 0);
+	if (result) {
+		qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO);
+		result2 = ccw_device_start(card->rdev,
+					   &card->dma_stuff->write_ccw,
+					   IDX_ACTIVATE_WRITE_STATE, 0, 0);
+		sprintf(dbf_text, "IRW1%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		sprintf(dbf_text, "IRW2%4x", result2);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		PRINT_WARN("qeth_idx_activate_read (write): do_IO returned "
+			   "%i, next try returns %i\n", result, result2);
+	}
+	spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags);
+
+	if (atomic_read(&card->break_out)) {
+		QETH_DBF_TEXT3(0, trace, "IARWBRKO");
+		return -EIO;
+	}
+
+	if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) {
+		QETH_DBF_TEXT1(0, trace, "IRWT");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		PRINT_ERR("IDX_ACTIVATE(wr) on read channel device %s: "
+			  "timeout\n", card->rdev->dev.bus_id);
+		return -EIO;
+	}
+
+/* start reading on read channel, card->read_ccw is not yet used */
+	memcpy(&card->dma_stuff->read_ccw, READ_CCW, sizeof (struct ccw1));
+	card->dma_stuff->read_ccw.count = QETH_BUFSIZE;
+	card->dma_stuff->read_ccw.cda = QETH_GET_ADDR(card->dma_stuff->recbuf);
+
+	spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags);
+	result2 = 0;
+	result = ccw_device_start(card->rdev, &card->dma_stuff->read_ccw,
+				  IDX_ACTIVATE_READ_STATE, 0, 0);
+	if (result) {
+		qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO);
+		result2 = ccw_device_start(card->rdev,
+					   &card->dma_stuff->read_ccw,
+					   IDX_ACTIVATE_READ_STATE, 0, 0);
+		sprintf(dbf_text, "IRR1%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		sprintf(dbf_text, "IRR2%4x", result2);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		PRINT_WARN("qeth_idx_activate_read (read): do_IO "
+			   "returned %i, next try returns %i\n",
+			   result, result2);
+	}
+	spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags);
+
+	if (result2) {
+		result = result2;
+		if (result)
+			return result;
+	}
+
+	if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) {
+		QETH_DBF_TEXT1(0, trace, "IRRT");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		PRINT_ERR("IDX_ACTIVATE(rd) on read channel device %s: "
+			  "timeout\n", card->rdev->dev.bus_id);
+		return -EIO;
+	}
+	QETH_DBF_TEXT2(0, trace, "iarr");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_HEX2(0, control, card->dma_stuff->recbuf,
+		      QETH_DBF_CONTROL_LEN);
+
+	if (!(QETH_IS_IDX_ACT_POS_REPLY(card->dma_stuff->recbuf))) {
+		QETH_DBF_TEXT1(0, trace, "IRNR");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		PRINT_ERR("IDX_ACTIVATE on read channel device %s: negative "
+			  "reply\n", card->rdev->dev.bus_id);
+		return -EIO;
+	}
+
+	card->portname_required =
+	    ((!QETH_IDX_NO_PORTNAME_REQUIRED(card->dma_stuff->recbuf)) &&
+	     (card->type == QETH_CARD_TYPE_OSAE));;
+
+	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf), 2);
+	if (temp != qeth_peer_func_level(card->func_level)) {
+		QETH_DBF_TEXT1(0, trace, "IRFL");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x%4x", card->func_level, temp);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		PRINT_WARN("IDX_ACTIVATE on read channel device %s: function "
+			   "level mismatch (sent: 0x%x, received: 0x%x)\n",
+			   card->rdev->dev.bus_id, card->func_level, temp);
+		result = -EIO;
+	}
+
+	memcpy(&card->token.issuer_rm_r,
+	       QETH_IDX_ACT_ISSUER_RM_TOKEN(card->dma_stuff->recbuf),
+	       QETH_MPC_TOKEN_LENGTH);
+
+	memcpy(&card->level[0],
+	       QETH_IDX_REPLY_LEVEL(card->dma_stuff->recbuf), QETH_MCL_LENGTH);
+
+	return result;
+}
+
+static int
+qeth_idx_activate_write(struct qeth_card *card)
+{
+	int result, result2;
+	__u16 temp;
+	unsigned long flags;
+	char dbf_text[15];
+
+	result = result2 = 0;
+
+	memcpy(&card->dma_stuff->write_ccw, WRITE_CCW, sizeof (struct ccw1));
+	card->dma_stuff->write_ccw.count = IDX_ACTIVATE_SIZE;
+	card->dma_stuff->write_ccw.cda =
+	    QETH_GET_ADDR(card->dma_stuff->sendbuf);
+
+	memcpy(card->dma_stuff->sendbuf, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);
+	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(card->dma_stuff->sendbuf),
+	       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+	card->seqno.trans_hdr++;
+
+	memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(card->dma_stuff->sendbuf),
+	       &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->sendbuf),
+	       &card->func_level, 2);
+
+	temp = _ccw_device_get_device_number(card->ddev);
+	memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(card->dma_stuff->sendbuf), &temp, 2);
+	temp = (card->cula << 8) + card->unit_addr2;
+	memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(card->dma_stuff->sendbuf),
+	       &temp, 2);
+
+	QETH_DBF_TEXT2(0, trace, "iaww");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_HEX2(0, control, card->dma_stuff->sendbuf,
+		      QETH_DBF_CONTROL_LEN);
+
+	spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags);
+	result = ccw_device_start(card->wdev, &card->dma_stuff->write_ccw,
+				  IDX_ACTIVATE_WRITE_STATE, 0, 0);
+	if (result) {
+		qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO);
+		result2 = ccw_device_start(card->wdev,
+					   &card->dma_stuff->write_ccw,
+					   IDX_ACTIVATE_WRITE_STATE, 0, 0);
+		sprintf(dbf_text, "IWW1%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		sprintf(dbf_text, "IWW2%4x", result2);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		PRINT_WARN("qeth_idx_activate_write (write): do_IO "
+			   "returned %i, next try returns %i\n",
+			   result, result2);
+	}
+	spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags);
+
+	if (atomic_read(&card->break_out)) {
+		QETH_DBF_TEXT3(0, trace, "IAWWBRKO");
+		return -EIO;
+	}
+
+	if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) {
+		QETH_DBF_TEXT1(0, trace, "IWWT");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		PRINT_ERR("IDX_ACTIVATE(wr) on write channel device %s: "
+			  "timeout\n", card->wdev->dev.bus_id);
+		return -EIO;
+	}
+
+	QETH_DBF_TEXT3(0, trace, "idxawrrd");
+	/* start one read on write channel */
+	memcpy(&card->dma_stuff->read_ccw, READ_CCW, sizeof (struct ccw1));
+	card->dma_stuff->read_ccw.count = QETH_BUFSIZE;
+	/* recbuf and card->read_ccw is not yet used by any other
+	   read channel program */
+	card->dma_stuff->read_ccw.cda = QETH_GET_ADDR(card->dma_stuff->recbuf);
+
+	spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags);
+	result2 = 0;
+	result = ccw_device_start(card->wdev, &card->dma_stuff->read_ccw,
+				  IDX_ACTIVATE_READ_STATE, 0, 0);
+	if (result) {
+		qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO);
+		result2 = ccw_device_start(card->wdev,
+					   &card->dma_stuff->read_ccw,
+					   IDX_ACTIVATE_READ_STATE, 0, 0);
+		sprintf(dbf_text, "IWR1%4x", result);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		sprintf(dbf_text, "IWR2%4x", result2);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+		PRINT_WARN("qeth_idx_activate_write (read): do_IO returned "
+			   "%i, next try returns %i\n", result, result2);
+	}
+
+	spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags);
+
+	if (result2) {
+		result = result2;
+		if (result)
+			return result;
+	}
+
+	if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) {
+		QETH_DBF_TEXT1(0, trace, "IWRT");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		PRINT_ERR("IDX_ACTIVATE(rd) on write channel device %s: "
+			  "timeout\n", card->wdev->dev.bus_id);
+		return -EIO;
+	}
+	QETH_DBF_TEXT2(0, trace, "iawr");
+	QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+	QETH_DBF_HEX2(0, control, card->dma_stuff->recbuf,
+		      QETH_DBF_CONTROL_LEN);
+
+	if (!(QETH_IS_IDX_ACT_POS_REPLY(card->dma_stuff->recbuf))) {
+		QETH_DBF_TEXT1(0, trace, "IWNR");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		PRINT_ERR("IDX_ACTIVATE on write channel device %s: negative "
+			  "reply\n", card->wdev->dev.bus_id);
+		return -EIO;
+	}
+
+	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf), 2);
+	if ((temp & ~0x0100) != qeth_peer_func_level(card->func_level)) {
+		QETH_DBF_TEXT1(0, trace, "IWFM");
+		QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "%4x%4x", card->func_level, temp);
+		QETH_DBF_TEXT1(0, trace, dbf_text);
+		PRINT_WARN("IDX_ACTIVATE on write channel device %s: function "
+			   "level mismatch (sent: 0x%x, received: 0x%x)\n",
+			   card->wdev->dev.bus_id, card->func_level, temp);
+		result = -EIO;
+	}
+
+	return result;
+}
+
+static int
+qeth_cm_enable(struct qeth_card *card)
+{
+	unsigned char *buffer;
+	int result;
+	char dbf_text[15];
+
+	memcpy(card->send_buf, CM_ENABLE, CM_ENABLE_SIZE);
+
+	memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(card->send_buf),
+	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_CM_ENABLE_FILTER_TOKEN(card->send_buf),
+	       &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH);
+
+	buffer = qeth_send_control_data(card, card->send_buf,
+					CM_ENABLE_SIZE, MPC_SETUP_STATE);
+
+	if (!buffer) {
+		QETH_DBF_TEXT2(0, trace, "CME:NOBF");
+		return -EIO;
+	}
+
+	memcpy(&card->token.cm_filter_r,
+	       QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer), QETH_MPC_TOKEN_LENGTH);
+
+	result = qeth_check_idx_response(buffer);
+
+	sprintf(dbf_text, "cme=%4x", result);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+
+	return result;
+}
+
+static int
+qeth_cm_setup(struct qeth_card *card)
+{
+	unsigned char *buffer;
+	int result;
+	char dbf_text[15];
+
+	memcpy(card->send_buf, CM_SETUP, CM_SETUP_SIZE);
+
+	memcpy(QETH_CM_SETUP_DEST_ADDR(card->send_buf),
+	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(card->send_buf),
+	       &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_CM_SETUP_FILTER_TOKEN(card->send_buf),
+	       &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH);
+
+	buffer = qeth_send_control_data(card, card->send_buf,
+					CM_SETUP_SIZE, MPC_SETUP_STATE);
+
+	if (!buffer) {
+		QETH_DBF_TEXT2(0, trace, "CMS:NOBF");
+		return -EIO;
+	}
+
+	memcpy(&card->token.cm_connection_r,
+	       QETH_CM_SETUP_RESP_DEST_ADDR(buffer), QETH_MPC_TOKEN_LENGTH);
+
+	result = qeth_check_idx_response(buffer);
+
+	sprintf(dbf_text, "cms=%4x", result);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+
+	return result;
+}
+
+static int
+qeth_ulp_enable(struct qeth_card *card)
+{
+	unsigned char *buffer;
+	__u16 mtu, framesize;
+	__u16 len;
+	__u8 link_type;
+	int result;
+	char dbf_text[15];
+
+	memcpy(card->send_buf, ULP_ENABLE, ULP_ENABLE_SIZE);
+
+	*(QETH_ULP_ENABLE_LINKNUM(card->send_buf)) =
+	    (__u8) card->options.portno;
+
+	memcpy(QETH_ULP_ENABLE_DEST_ADDR(card->send_buf),
+	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(card->send_buf),
+	       &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
+
+	memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(card->send_buf),
+	       card->options.portname, 9);
+
+	buffer = qeth_send_control_data(card, card->send_buf,
+					ULP_ENABLE_SIZE, MPC_SETUP_STATE);
+
+	if (!buffer) {
+		QETH_DBF_TEXT2(0, trace, "ULE:NOBF");
+		return -EIO;
+	}
+
+	memcpy(&card->token.ulp_filter_r,
+	       QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer),
+	       QETH_MPC_TOKEN_LENGTH);
+
+	/* to be done before qeth_init_ringbuffers and qeth_init_dev */
+	if (qeth_get_mtu_out_of_mpc(card->type)) {
+		memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(buffer), 2);
+		mtu = qeth_get_mtu_outof_framesize(framesize);
+
+		QETH_DBF_TEXT2(0, trace, "ule");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		sprintf(dbf_text, "mtu=%4x", mtu);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+
+		if (!mtu)
+			return -EINVAL;
+
+		card->max_mtu = mtu;
+		card->initial_mtu = mtu;
+		card->inbound_buffer_size = mtu + 2 * PAGE_SIZE;
+	} else {
+		card->initial_mtu = qeth_get_initial_mtu_for_card(card);
+		card->max_mtu = qeth_get_max_mtu_for_card(card->type);
+		card->inbound_buffer_size = DEFAULT_BUFFER_SIZE;
+	}
+
+	memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer), 2);
+	if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
+		memcpy(&link_type, QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer), 1);
+		card->link_type = link_type;
+		sprintf(dbf_text, "link=%2x", link_type);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+	} else
+		card->link_type = 0;
+
+	result = qeth_check_idx_response(buffer);
+
+	sprintf(dbf_text, "ule=%4x", result);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+
+	return result;
+}
+
+static int
+qeth_ulp_setup(struct qeth_card *card)
+{
+	unsigned char *buffer;
+	__u16 temp;
+	int result;
+	char dbf_text[15];
+
+	memcpy(card->send_buf, ULP_SETUP, ULP_SETUP_SIZE);
+
+	memcpy(QETH_ULP_SETUP_DEST_ADDR(card->send_buf),
+	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(card->send_buf),
+	       &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_ULP_SETUP_FILTER_TOKEN(card->send_buf),
+	       &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
+
+	temp = _ccw_device_get_device_number(card->ddev);
+	memcpy(QETH_ULP_SETUP_CUA(card->send_buf), &temp, 2);
+	temp = (card->cula << 8) + card->unit_addr2;
+	memcpy(QETH_ULP_SETUP_REAL_DEVADDR(card->send_buf), &temp, 2);
+
+	buffer = qeth_send_control_data(card, card->send_buf,
+					ULP_SETUP_SIZE, MPC_SETUP_STATE);
+
+	if (!buffer) {
+		QETH_DBF_TEXT2(0, trace, "ULS:NOBF");
+		return -EIO;
+	}
+
+	memcpy(&card->token.ulp_connection_r,
+	       QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer),
+	       QETH_MPC_TOKEN_LENGTH);
+
+	result = qeth_check_idx_response(buffer);
+
+	sprintf(dbf_text, "uls=%4x", result);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+
+	return result;
+}
+
+static int
+qeth_qdio_establish(struct qeth_card *card)
+{
+	int result;
+	char *adapter_area;
+	char dbf_text[15];
+	void **input_array, **output_array, **ptr;
+	int i, j;
+	struct qdio_initialize init_data;
+
+ 	adapter_area = vmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char));
+ 	if (!adapter_area)
+		return -ENOMEM;
+ 
+ 	memset(adapter_area, 0, QDIO_MAX_BUFFERS_PER_Q * sizeof(char));
+
+	adapter_area[0] = _ascebc['P'];
+	adapter_area[1] = _ascebc['C'];
+	adapter_area[2] = _ascebc['I'];
+	adapter_area[3] = _ascebc['T'];
+	*((unsigned int *) (&adapter_area[4])) = PCI_THRESHOLD_A;
+	*((unsigned int *) (&adapter_area[8])) = PCI_THRESHOLD_B;
+	*((unsigned int *) (&adapter_area[12])) = PCI_TIMER_VALUE;
+
+	input_array = vmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof (void *));
+	if (!input_array) {
+		vfree(adapter_area);
+		return -ENOMEM;
+	}
+	ptr = input_array;
+	for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) {
+		*ptr = (void *) virt_to_phys(&card->inbound_qdio_buffers[j]);
+		ptr++;
+	}
+
+	output_array = vmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof (void *) *
+			       card->no_queues);
+	if (!output_array) {
+		vfree(input_array);
+		vfree(adapter_area);
+		return -ENOMEM;
+	}
+	ptr = output_array;
+	for (i = 0; i < card->no_queues; i++)
+		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) {
+			*ptr = (void *) virt_to_phys
+			    (&card->outbound_ringbuffer[i]->buffer[j]);
+			ptr++;
+		}
+
+	init_data.cdev = card->ddev;
+	init_data.q_format = qeth_get_q_format(card->type);
+	init_data.qib_param_field_format = 0;
+	init_data.qib_param_field = adapter_area;
+	init_data.input_slib_elements = NULL;
+	init_data.output_slib_elements = NULL;
+	init_data.min_input_threshold = card->options.polltime;
+	init_data.max_input_threshold = card->options.polltime;
+	init_data.min_output_threshold = QETH_MIN_OUTPUT_THRESHOLD;
+	init_data.max_output_threshold = QETH_MAX_OUTPUT_THRESHOLD;
+	init_data.no_input_qs = 1;
+	init_data.no_output_qs = card->no_queues;
+	init_data.input_handler = qeth_qdio_input_handler;
+	init_data.output_handler = qeth_qdio_output_handler;
+	init_data.int_parm = (unsigned long) card;
+	init_data.flags = QDIO_INBOUND_0COPY_SBALS |
+	    QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS;
+	init_data.input_sbal_addr_array = input_array;
+	init_data.output_sbal_addr_array = output_array;
+
+	result = qdio_initialize(&init_data);
+
+	vfree(input_array);
+	vfree(output_array);
+	vfree(adapter_area);
+
+	sprintf(dbf_text, "qde=%4i", result);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+
+	return result;
+}
+
+static int
+qeth_qdio_activate(struct qeth_card *card)
+{
+	int result;
+	char dbf_text[15];
+
+	result = qdio_activate(card->ddev, 0);
+
+	sprintf(dbf_text, "qda=%4x", result);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+
+	return result;
+}
+
+static int
+qeth_dm_act(struct qeth_card *card)
+{
+	unsigned char *buffer;
+	int result;
+	char dbf_text[15];
+
+	memcpy(card->send_buf, DM_ACT, DM_ACT_SIZE);
+
+	memcpy(QETH_DM_ACT_DEST_ADDR(card->send_buf),
+	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+	memcpy(QETH_DM_ACT_CONNECTION_TOKEN(card->send_buf),
+	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+
+	buffer = qeth_send_control_data(card, card->send_buf,
+					DM_ACT_SIZE, MPC_SETUP_STATE);
+
+	if (!buffer) {
+		QETH_DBF_TEXT2(0, trace, "DMA:NOBF");
+		return -EIO;
+	}
+
+	result = qeth_check_idx_response(buffer);
+
+	sprintf(dbf_text, "dma=%4x", result);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+
+	return result;
+}
+
+static inline int
+__qeth_verify_dev_vlan(struct net_device *dev,struct qeth_card *card)
+{
+#ifdef QETH_VLAN
+	struct vlan_group *vlan_grp;
+	int i;
+	int result = 0;
+
+	/* check all vlan devices */
+	vlan_grp = (struct vlan_group *) card->vlangrp;
+	if (vlan_grp) {
+		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+			if (vlan_grp->vlan_devices[i] == dev) {
+				result = QETH_VERIFY_IS_VLAN_DEV;
+			}
+		}
+	}
+	return result;
+#endif
+	return 0;
+}
+
+#if defined(QETH_VLAN)||defined(QETH_IPV6)
+static int
+qeth_verify_dev(struct net_device *dev)
+{
+	struct qeth_card *tmp;
+	int result = 0;
+
+	read_lock(&list_lock);
+	tmp = firstcard;
+	for (; tmp && (!result); tmp = tmp->next) {
+		if (atomic_read(&tmp->shutdown_phase))
+			continue;
+		if (dev == tmp->dev) {
+			result = QETH_VERIFY_IS_REAL_DEV;
+		}
+		result = __qeth_verify_dev_vlan(dev, tmp);
+	}
+	read_unlock(&list_lock);
+	return result;
+}
+#endif /* defined(QETH_VLAN)||defined(QETH_IPV6) */
+
+static int
+qeth_verify_card(struct qeth_card *card)
+{
+	struct qeth_card *tmp;
+	int result = 0;
+
+	read_lock(&list_lock);
+	tmp = firstcard;
+	while (tmp) {
+		if ((card == tmp) && (!atomic_read(&card->shutdown_phase))) {
+			result = 1;
+			break;
+		}
+		tmp = tmp->next;
+	}
+	read_unlock(&list_lock);
+	return result;
+}
+
+static inline struct qeth_card *
+__qeth_get_card_from_dev(struct net_device *dev)
+{
+#ifdef QETH_VLAN
+	if (qeth_verify_dev(dev) == QETH_VERIFY_IS_VLAN_DEV)
+		return (struct qeth_card *) VLAN_DEV_INFO(dev)->real_dev->priv;
+	else
+#endif
+		return (struct qeth_card *) dev->priv;
+}
+
+#ifdef QETH_IPV6
+/* FIXME: don't put extern declarations in a c file, use a header that's
+ * shared with the definition for this! */
+extern struct neigh_table arp_tbl;
+static int (*qeth_old_arp_constructor) (struct neighbour *);
+static struct neigh_ops arp_direct_ops_template = {
+	.family = AF_INET,
+	.destructor = NULL,
+	.solicit = NULL,
+	.error_report = NULL,
+	.output = dev_queue_xmit,
+	.connected_output = dev_queue_xmit,
+	.hh_output = dev_queue_xmit,
+	.queue_xmit = dev_queue_xmit
+};
+
+/*
+ * FIXME:
+ * as we have neighbour structures point to this structure, even
+ * after our life time, this will stay in memory as a leak 
+ */
+static struct neigh_ops *arp_direct_ops;
+
+
+static int
+qeth_arp_constructor(struct neighbour *neigh)
+{
+	char dbf_text[15];
+	struct net_device *dev = neigh->dev;
+	struct in_device *in_dev = in_dev_get(dev);
+
+	if (in_dev == NULL)
+		return -EINVAL;
+
+	QETH_DBF_TEXT4(0, trace, "arpconst");
+	if (!qeth_verify_dev(dev)) {
+
+		in_dev_put(in_dev);
+		return qeth_old_arp_constructor(neigh);
+	}
+
+	neigh->type = inet_addr_type(*(u32 *) neigh->primary_key);
+	if (in_dev->arp_parms)
+		neigh->parms = in_dev->arp_parms;
+
+	in_dev_put(in_dev);
+
+	sprintf(dbf_text, "%08x", ntohl(*((__u32 *) (neigh->primary_key))));
+	QETH_DBF_TEXT4(0, trace, dbf_text);
+	QETH_DBF_HEX4(0, trace, &neigh, sizeof (void *));
+
+	neigh->nud_state = NUD_NOARP;
+	neigh->ops = arp_direct_ops;
+	neigh->output = neigh->ops->queue_xmit;
+	return 0;
+}
+
+static int
+qeth_hard_header(struct sk_buff *skb, struct net_device *dev,
+		 unsigned short type, void *daddr, void *saddr, unsigned len)
+{
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT5(0, trace, "hardhdr");
+
+	card = __qeth_get_card_from_dev(dev);
+	return card->hard_header(skb, dev, type, daddr, saddr, len);
+}
+
+static void
+qeth_header_cache_update(struct hh_cache *hh,
+			 struct net_device *dev, unsigned char *haddr)
+{
+	struct qeth_card *card;
+
+	card = (struct qeth_card *) dev->priv;
+	QETH_DBF_TEXT5(0, trace, "hdrcheup");
+	return card->header_cache_update(hh, dev, haddr);
+}
+
+static int
+qeth_rebuild_header(struct sk_buff *skb)
+{
+	struct qeth_card *card;
+	QETH_DBF_TEXT5(0, trace, "rebldhdr");
+	if (skb->protocol == __constant_htons(ETH_P_IP))
+		return 0;
+
+	card = __qeth_get_card_from_dev(skb->dev);
+
+	return card->rebuild_header(skb);
+}
+
+int
+qeth_ipv6_generate_eui64(u8 * eui, struct net_device *dev)
+{
+	switch (dev->type) {
+	case ARPHRD_ETHER:
+	case ARPHRD_FDDI:
+	case ARPHRD_IEEE802_TR:
+		if (dev->addr_len != ETH_ALEN)
+			return -1;
+		memcpy(eui, dev->dev_addr, 3);
+		memcpy(eui + 5, dev->dev_addr + 3, 3);
+		eui[3] = (dev->dev_id >> 8) & 0xff;
+		eui[4] = dev->dev_id & 0xff;
+		return 0;
+	}
+	return -1;
+
+}
+#endif /* QETH_IPV6 */
+
+static void
+qeth_ipv6_init_card(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	card->hard_header = qeth_get_hard_header(card->link_type);
+	card->rebuild_header = qeth_get_rebuild_header(card->link_type);
+	card->hard_header_cache = qeth_get_hard_header_cache(card->link_type);
+	card->header_cache_update =
+	    qeth_get_header_cache_update(card->link_type);
+	card->type_trans = qeth_get_type_trans(card->link_type);
+	card->dev->dev_id = card->unique_id & 0xffff;
+	if (!(card->unique_id & UNIQUE_ID_NOT_BY_CARD))
+		card->dev->generate_eui64 = qeth_ipv6_generate_eui64;
+#endif /* QETH_IPV6 */
+}
+
+#ifdef QETH_VLAN
+static void
+qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+{
+	struct qeth_card *card;
+	card = (struct qeth_card *) dev->priv;
+	spin_lock_irq(&card->vlan_lock);
+	card->vlangrp = grp;
+	spin_unlock_irq(&card->vlan_lock);
+}
+static void
+qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+	struct qeth_card *card;
+	card = (struct qeth_card *) dev->priv;
+	spin_lock_irq(&card->vlan_lock);
+	if (card->vlangrp)
+		card->vlangrp->vlan_devices[vid] = NULL;
+	spin_unlock_irq(&card->vlan_lock);
+}
+#endif
+
+static void
+qeth_tx_timeout(struct net_device *dev)
+{
+	struct qeth_card *card;
+
+	card = (struct qeth_card *) dev->priv;
+	QETH_DBF_TEXT2(1, trace, "XMTO");
+	QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id);
+	card->stats->tx_errors++;
+	atomic_set(&card->problem, PROBLEM_TX_TIMEOUT);
+	qeth_schedule_recovery(card);
+}
+
+static void*
+__qeth_rebuild_header_func(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	return (!(qeth_get_additional_dev_flags(card->type) & IFF_NOARP)) ?
+		(qeth_get_rebuild_header(card->link_type) ?
+		 qeth_rebuild_header : NULL) : NULL;
+#endif /* QETH_IPV6 */
+	return NULL;
+}
+
+static void*
+__qeth_hard_header_func(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	return (!(qeth_get_additional_dev_flags(card->type) & IFF_NOARP)) ?
+		(qeth_get_hard_header(card->link_type) ?
+		 qeth_hard_header : NULL) : NULL;
+#endif /* QETH_IPV6 */
+	return NULL;
+}
+
+static void*
+__qeth_header_cache_update_func(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	return (!(qeth_get_additional_dev_flags(card->type) & IFF_NOARP)) ?
+		(qeth_get_header_cache_update(card->link_type) ?
+		 qeth_header_cache_update : NULL) : NULL;
+#endif /* QETH_IPV6 */
+	return NULL;
+}
+
+static void*
+__qeth_hard_header_cache_func(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	return (!(qeth_get_additional_dev_flags(card->type) & IFF_NOARP)) ?
+		qeth_get_hard_header_cache(card->link_type) : NULL;
+#endif /* QETH_IPV6 */
+	return NULL;
+}
+
+static int
+qeth_init_dev(struct net_device *dev)
+{
+	struct qeth_card *card;
+
+	card = (struct qeth_card *) dev->priv;
+
+	QETH_DBF_TEXT3(0, trace, "inid");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	dev->tx_timeout = &qeth_tx_timeout;
+	dev->watchdog_timeo = QETH_TX_TIMEOUT;
+	dev->open = qeth_open;
+	dev->stop = qeth_stop;
+	dev->set_config = qeth_set_config;
+	dev->hard_start_xmit = qeth_hard_start_xmit;
+	dev->do_ioctl = qeth_do_ioctl;
+	dev->get_stats = qeth_get_stats;
+	dev->change_mtu = qeth_change_mtu;
+#ifdef QETH_VLAN
+	dev->vlan_rx_register = qeth_vlan_rx_register;
+	dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
+#endif
+	dev->rebuild_header = __qeth_rebuild_header_func(card);
+	dev->hard_header = __qeth_hard_header_func(card);
+	dev->header_cache_update = __qeth_header_cache_update_func(card);
+	dev->hard_header_cache = __qeth_hard_header_cache_func(card);
+	dev->hard_header_parse = NULL;
+	dev->destructor = qeth_destructor;
+	dev->set_multicast_list = qeth_set_multicast_list;
+	dev->set_mac_address = qeth_set_mac_address;
+	dev->neigh_setup = qeth_neigh_setup;
+
+	dev->flags |= qeth_get_additional_dev_flags(card->type);
+
+	dev->flags |= ((card->options.fake_broadcast == FAKE_BROADCAST) ||
+		       (card->broadcast_capable)) ? IFF_BROADCAST : 0;
+
+	 /* is done in hardsetup_card... see comment below
+	 qeth_send_qipassist(card,4);*/
+
+	/* that was the old place. one id. we need to make sure, that
+	 * hydra knows about us going to use the same id again, so we
+	 * do that in hardsetup_card every time
+	 qeth_get_unique_id(card);*/
+
+	dev->tx_queue_len = qeth_get_device_tx_q_len(card->type);
+	dev->hard_header_len =
+		qeth_get_hlen(card->link_type) + card->options.add_hhlen;
+	dev->addr_len = OSA_ADDR_LEN;	/* is ok for eth, tr, atm lane */
+	SET_MODULE_OWNER(dev);
+	netif_start_queue(dev);
+
+	dev->mtu = card->initial_mtu;
+
+	qeth_ipv6_init_card(card);
+
+	return 0;
+}
+
+static int
+qeth_get_unitaddr(struct qeth_card *card)
+{
+	char *prcd;
+	int result = 0;
+	char dbf_text[15];
+	int length;
+
+	QETH_DBF_TEXT3(0, trace, "gtua");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	result = read_conf_data(card->ddev, (void **) &prcd, &length);
+	if (result) {
+		sprintf(dbf_text, "rcd%4x", result);
+		QETH_DBF_TEXT3(0, trace, dbf_text);
+		PRINT_ERR("read_conf_data for device %s returned %i\n",
+			  card->ddev->dev.bus_id, result);
+		return result;
+	}
+
+	card->chpid = prcd[30];
+	card->unit_addr2 = prcd[31];
+	card->cula = prcd[63];
+	card->is_guest_lan= ((prcd[0x10] == _ascebc['V']) &&
+			     (prcd[0x11] == _ascebc['M']));
+
+	sprintf(dbf_text, "chpid:%02x", card->chpid);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+	sprintf(dbf_text, "unad2:%02x", card->unit_addr2);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+	sprintf(dbf_text, "cula:%02x", card->cula);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+
+	return 0;
+}
+
+static int
+qeth_send_nops(struct qeth_card *card)
+{
+	int result, result2;
+	unsigned long saveflags;
+
+	card->dma_stuff->write_ccw.cmd_code = CCW_NOP_CMD;
+	card->dma_stuff->write_ccw.flags = CCW_FLAG_SLI;
+	card->dma_stuff->write_ccw.count = CCW_NOP_COUNT;
+	card->dma_stuff->write_ccw.cda = (unsigned long) NULL;
+
+#define DO_SEND_NOP(cdev) \
+do { \
+	QETH_DBF_TEXT3(0, trace, "snnp"); \
+	QETH_DBF_TEXT3(0, trace, cdev->dev.bus_id); \
+\
+	spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags); \
+	ccw_device_set_options(cdev, 0); \
+        result=ccw_device_start(cdev,&card->dma_stuff->write_ccw, \
+				NOP_STATE,0,0); \
+        if (result) { \
+		qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO); \
+                result2=ccw_device_start(cdev,&card->dma_stuff->write_ccw, \
+					 NOP_STATE,0,0); \
+                PRINT_WARN("qeth_send_nops on device %s: do_IO returned %i, " \
+                           "next try returns %i\n", \
+                           cdev->dev.bus_id,result,result2); \
+		result=result2; \
+        } \
+        spin_unlock_irqrestore(get_ccwdev_lock(cdev),saveflags); \
+\
+	if (result) goto exit; \
+\
+        if (qeth_sleepon(card,QETH_NOP_TIMEOUT)) { \
+		QETH_DBF_TEXT2(0,trace,"snnp:tme"); \
+		result=-EIO; \
+		goto exit; \
+        } \
+} while (0)
+
+	DO_SEND_NOP(card->rdev);
+	DO_SEND_NOP(card->wdev);
+	DO_SEND_NOP(card->ddev);
+
+exit:
+	return result;
+}
+
+static void
+qeth_clear_card_structures(struct qeth_card *card)
+{
+	int i, j;
+
+	if (!card) {
+		QETH_DBF_TEXT2(0, trace, "clrCRDnc");
+		return;
+	}
+
+	QETH_DBF_TEXT3(0, trace, "clcs");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	atomic_set(&card->is_startlaned, 0);
+
+	for (i = 0; i < QETH_MAX_QUEUES; i++) {
+		card->send_state[i] = SEND_STATE_DONT_PACK;
+		card->outbound_first_free_buffer[i] = 0;
+		atomic_set(&card->outbound_used_buffers[i], 0);
+		atomic_set(&card->outbound_ringbuffer_lock[i], 0);
+
+		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) {
+			card->outbound_buffer_send_state[i][j] =
+			    SEND_STATE_DONT_PACK;
+			card->send_retries[i][j] = 0;
+
+			if (i < card->no_queues) {
+				card->outbound_ringbuffer[i]->
+				    ringbuf_element[j].next_element_to_fill = 0;
+				card->outbound_bytes_in_buffer[i] = 0;
+				skb_queue_head_init(&card->
+						    outbound_ringbuffer[i]->
+						    ringbuf_element[j].
+						    skb_list);
+			}
+		}
+	}
+
+	for (i = 0; i < card->options.inbound_buffer_count; i++) {
+		xchg((int *) &card->inbound_buffer_pool_entry_used[i],
+		     BUFFER_UNUSED);
+	}
+
+	spin_lock_init(&card->requeue_input_lock);
+	atomic_set(&card->requeue_position, 0);
+	atomic_set(&card->requeue_counter, 0);
+
+	card->seqno.trans_hdr = 0;
+	card->seqno.pdu_hdr = 0;
+	card->seqno.pdu_hdr_ack = 0;
+	card->seqno.ipa = 0;
+
+	qeth_clear_ifa4_list(&card->ip_current_state.ip_ifa);
+	qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa);
+	qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm_ifa);
+	qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa);
+
+#ifdef QETH_IPV6
+	qeth_clear_ifa6_list(&card->ip_current_state.ip6_ifa);
+	qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa);
+	qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm6_ifa);
+	qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa);
+#endif /* QETH_IPV6 */
+}
+
+static void
+qeth_init_input_buffers(struct qeth_card *card)
+{
+	int i;
+
+	/* slowly, slowly (we don't want to enqueue all buffers
+	 * at one time) */
+	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
+		atomic_set(&card->inbound_buffer_refcnt[i], 1);
+	}
+	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
+		atomic_set(&card->inbound_buffer_refcnt[i], 0);
+ 		/* only try to queue as many buffers as we have at all */
+ 		if (i < card->options.inbound_buffer_count)
+ 			qeth_queue_input_buffer(card,i,0);
+	}
+	qdio_synchronize(card->ddev, QDIO_FLAG_SYNC_INPUT, 0);
+}
+
+/* initializes all the structures for a card */
+static int
+qeth_hardsetup_card(struct qeth_card *card, int in_recovery)
+{
+	int result, q, breakout;
+	unsigned long flags;
+	int laps = QETH_HARDSETUP_LAPS;
+	int clear_laps;
+	int cleanup_qdio;
+	char dbf_text[15];
+	int i, r;
+
+	/* setup name and so on */
+	atomic_set(&card->shutdown_phase, 0);
+
+	if (atomic_read(&card->is_hardsetup)) {
+		QETH_DBF_TEXT2(1, trace, "hscd");
+		QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id);
+		PRINT_ALL("card is already hardsetup.\n");
+		return 0;
+	}
+
+	cleanup_qdio = in_recovery;	/* if we are in recovery, we clean
+					   the qdio stuff up */
+
+	spin_lock(&card->hardsetup_lock);
+	atomic_set(&card->write_busy, 0);
+
+	do {
+		if (in_recovery) {
+			PRINT_STUPID("qeth: recovery: quiescing %s...\n",
+				     card->dev_name);
+			QETH_DBF_TEXT2(0, trace, "Rqsc");
+			QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+			qeth_wait_nonbusy(QETH_QUIESCE_WAIT_BEFORE_CLEAR);
+		}
+		clear_laps = QETH_HARDSETUP_CLEAR_LAPS;
+		do {
+			if (in_recovery)
+				PRINT_STUPID("clearing card %s\n",
+					     card->dev_name);
+			qeth_clear_card(card, cleanup_qdio,
+					(card->type == QETH_CARD_TYPE_OSAE));
+			result = qeth_send_nops(card);
+			breakout = atomic_read(&card->break_out);
+		} while ((--clear_laps) && (result));
+		if (result) {
+			goto exit;
+		}
+
+		if (in_recovery) {
+			PRINT_STUPID("qeth: recovery: still quiescing %s...\n",
+				     card->dev_name);
+			QETH_DBF_TEXT2(0, trace, "RQsc");
+			QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+			qeth_wait_nonbusy(QETH_QUIESCE_WAIT_AFTER_CLEAR);
+		} else {
+			atomic_set(&card->shutdown_phase, 0);
+		}
+
+		cleanup_qdio = 0;	/* qdio was cleaned now, if necessary */
+
+		result = qeth_get_unitaddr(card);
+		if (result)
+			goto exit;
+
+		qeth_generate_tokens(card);
+
+#define PRINT_TOKENS do { \
+		sprintf(dbf_text,"stra    "); \
+		memcpy(&dbf_text[4],&card->seqno.trans_hdr,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"spdu    "); \
+		memcpy(&dbf_text[4],&card->seqno.pdu_hdr,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"spda    "); \
+		memcpy(&dbf_text[4],&card->seqno.pdu_hdr_ack,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"sipa    "); \
+		memcpy(&dbf_text[4],&card->seqno.ipa,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tisw    "); \
+		memcpy(&dbf_text[4],&card->token.issuer_rm_w,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tisr    "); \
+		memcpy(&dbf_text[4],&card->token.issuer_rm_r,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tcfw    "); \
+		memcpy(&dbf_text[4],&card->token.cm_filter_w,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tcfr    "); \
+		memcpy(&dbf_text[4],&card->token.cm_filter_r,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tccw    "); \
+		memcpy(&dbf_text[4],&card->token.cm_connection_w,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tccr    "); \
+		memcpy(&dbf_text[4],&card->token.cm_connection_r,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tufw    "); \
+		memcpy(&dbf_text[4],&card->token.ulp_filter_w,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tufr    "); \
+		memcpy(&dbf_text[4],&card->token.ulp_filter_r,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tucw    "); \
+		memcpy(&dbf_text[4],&card->token.ulp_connection_w,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+		sprintf(dbf_text,"tucr    "); \
+		memcpy(&dbf_text[4],&card->token.ulp_connection_r,4); \
+		QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \
+	} while (0)
+
+		PRINT_TOKENS;
+
+		/* card->break_out and problem will be set here to 0
+		 * (in each lap) (there can't be a problem at this
+		 * early time) */
+		atomic_set(&card->problem, 0);
+		atomic_set(&card->break_out, 0);
+
+#define CHECK_ERRORS \
+		breakout=atomic_read(&card->break_out); \
+		if (breakout==QETH_BREAKOUT_AGAIN) \
+			continue; \
+		else if (breakout==QETH_BREAKOUT_LEAVE) { \
+			result=-EIO; \
+			goto exit; \
+		} \
+		if (result) goto exit
+
+		QETH_DBF_TEXT2(0, trace, "hsidxard");
+		result = qeth_idx_activate_read(card);
+		CHECK_ERRORS;
+
+		PRINT_TOKENS;
+		QETH_DBF_TEXT2(0, trace, "hsidxawr");
+		result = qeth_idx_activate_write(card);
+		CHECK_ERRORS;
+
+		QETH_DBF_TEXT2(0, trace, "hsissurd");
+		/* from here, there will always be an outstanding read */
+		spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags);
+		qeth_issue_next_read(card);
+		spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags);
+
+		PRINT_TOKENS;
+		QETH_DBF_TEXT2(0, trace, "hscmenab");
+		result = qeth_cm_enable(card);
+		CHECK_ERRORS;
+
+		PRINT_TOKENS;
+		QETH_DBF_TEXT2(0, trace, "hscmsetu");
+		result = qeth_cm_setup(card);
+		CHECK_ERRORS;
+
+		PRINT_TOKENS;
+		QETH_DBF_TEXT2(0, trace, "hsulpena");
+		result = qeth_ulp_enable(card);
+		CHECK_ERRORS;
+
+		PRINT_TOKENS;
+		QETH_DBF_TEXT2(0, trace, "hsulpset");
+		result = qeth_ulp_setup(card);
+		CHECK_ERRORS;
+
+		cleanup_qdio = 1;
+
+		QETH_DBF_TEXT2(0, trace, "hsqdioes");
+		result = qeth_qdio_establish(card);
+		CHECK_ERRORS;
+
+		PRINT_TOKENS;
+		QETH_DBF_TEXT2(0, trace, "hsqdioac");
+		result = qeth_qdio_activate(card);
+		CHECK_ERRORS;
+
+		PRINT_TOKENS;
+		QETH_DBF_TEXT2(0, trace, "hsdmact");
+		result = qeth_dm_act(card);
+		CHECK_ERRORS;
+	} while ((laps--) && (breakout == QETH_BREAKOUT_AGAIN));
+	if (breakout == QETH_BREAKOUT_AGAIN) {
+		QETH_DBF_TEXT2(0, trace, "hsnr");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		PRINT_ERR("qeth: recovery not successful on device "
+			  "%s/%s/%s; giving up.\n",
+			  card->rdev->dev.bus_id,
+			  card->wdev->dev.bus_id, card->ddev->dev.bus_id);
+		result = -EIO;
+		goto exit;
+	}
+
+	qeth_clear_ifa4_list(&card->ip_current_state.ip_ifa);
+	qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa);
+	qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm_ifa);
+	qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa);
+
+#ifdef QETH_IPV6
+	qeth_clear_ifa6_list(&card->ip_current_state.ip6_ifa);
+	qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa);
+	qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm6_ifa);
+	qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa);
+#endif /* QETH_IPV6 */
+
+	if (!atomic_read(&card->is_registered)) {
+		card->dev->dev_addr[0] = 0;	/* we don't know the mac addr yet */
+		card->dev->dev_addr[1] = 0;
+		card->dev->dev_addr[2] = 0;
+		card->dev->dev_addr[3] = 0;
+		card->dev->dev_addr[4] = 0;
+		card->dev->dev_addr[5] = 0;
+		card->dev->broadcast[0] = card->dev->broadcast[1] = 0xff;
+		card->dev->broadcast[2] = card->dev->broadcast[3] = 0xff;
+		card->dev->broadcast[4] = card->dev->broadcast[5] = 0xff;
+
+		card->dev->type = qeth_get_arphrd_type(card->type,
+						       card->link_type);
+
+		card->dev->init = qeth_init_dev;
+
+		if (card->options.memusage == MEMUSAGE_CONTIG) {
+			card->easy_copy_cap =
+			    qeth_determine_easy_copy_cap(card->type);
+		} else
+			card->easy_copy_cap = 0;
+		card->ipa_timeout = qeth_get_ipa_timeout(card->type);
+	}
+
+	atomic_set(&card->is_hardsetup, 1);
+	atomic_set(&card->is_softsetup, 0);
+	atomic_set(&card->startlan_attempts, 1);
+
+	for (q = 0; q < card->no_queues; q++)
+		card->send_state[q] = SEND_STATE_DONT_PACK;
+
+	/* we need to know first, whether we should include a value
+	 * into eui-64 address generation */
+	QETH_DBF_TEXT2(0, trace, "qipassi4");
+	r = qeth_send_qipassist(card, 4);
+	if (r) {
+		PRINT_WARN("couldn't send QIPASSIST4 on %s: "
+			   "0x%x\n", card->dev_name, r);
+		sprintf(dbf_text, "QIP4%4x", r);
+		QETH_DBF_TEXT2(0, trace, dbf_text);
+	}
+
+	sprintf(dbf_text, "%4x%4x", card->ipa_supported, card->ipa_enabled);
+	QETH_DBF_TEXT2(0, trace, dbf_text);
+
+	qeth_get_unique_id(card);
+
+	/* print out status */
+	if (in_recovery) {
+		qeth_clear_card_structures(card);
+		qeth_init_input_buffers(card);
+		QETH_DBF_TEXT1(0, trace, "RECOVSUC");
+		PRINT_INFO("qeth: recovered device %s/%s/%s (%s) "
+			   "successfully.\n",
+			   card->rdev->dev.bus_id,
+			   card->wdev->dev.bus_id,
+			   card->ddev->dev.bus_id, card->dev_name);
+	} else {
+		QETH_DBF_TEXT2(0, trace, "hrdsetok");
+
+		switch (card->type) {
+		case QETH_CARD_TYPE_OSAE:
+			/* 
+			 * VM will use a non-zero first character to indicate
+			 * a HiperSockets like reporting of the level
+			 * OSA sets the first character to zero
+			 */
+			if (!card->level[0]) {
+				sprintf(card->level, "%02x%02x", card->level[2],
+					card->level[3]);
+				card->level[QETH_MCL_LENGTH] = 0;
+				break;
+			}
+			/* fallthrough */
+		case QETH_CARD_TYPE_IQD:
+			card->level[0] = (char) _ebcasc[(__u8) card->level[0]];
+			card->level[1] = (char) _ebcasc[(__u8) card->level[1]];
+			card->level[2] = (char) _ebcasc[(__u8) card->level[2]];
+			card->level[3] = (char) _ebcasc[(__u8) card->level[3]];
+			card->level[QETH_MCL_LENGTH] = 0;
+			break;
+		default:
+			memset(&card->level[0], 0, QETH_MCL_LENGTH + 1);
+		}
+
+		sprintf(dbf_text, "lvl:%s", card->level);
+		QETH_DBF_TEXT2(0, setup, dbf_text);
+
+		if (card->portname_required) {
+			sprintf(dbf_text, "%s", card->options.portname + 1);
+			for (i = 0; i < 8; i++)
+				dbf_text[i] =
+				    (char) _ebcasc[(__u8) dbf_text[i]];
+			dbf_text[8] = 0;
+			printk("qeth: Device %s/%s/%s is a%s card%s%s%s\n"
+			       "with link type %s (portname: %s)\n",
+			       card->rdev->dev.bus_id,
+			       card->wdev->dev.bus_id,
+			       card->ddev->dev.bus_id,
+			       qeth_get_cardname(card->type,
+						 card->is_guest_lan),
+			       (card->level[0]) ? " (level: " : "",
+			       (card->level[0]) ? card->level : "",
+			       (card->level[0]) ? ")" : "",
+			       qeth_get_link_type_name(card->type,
+						       card->link_type),
+			       dbf_text);
+		} else {
+			if (card->options.portname[0])
+				printk("qeth: Device %s/%s/%s is a%s "
+				       "card%s%s%s\nwith link type %s "
+				       "(no portname needed by interface).\n",
+				       card->rdev->dev.bus_id,
+				       card->wdev->dev.bus_id,
+				       card->ddev->dev.bus_id,
+				       qeth_get_cardname(card->type,
+							 card->is_guest_lan),
+				       (card->level[0]) ? " (level: " : "",
+				       (card->level[0]) ? card->level : "",
+				       (card->level[0]) ? ")" : "",
+				       qeth_get_link_type_name(card->type,
+							       card->link_type));
+			else
+				printk("qeth: Device %s/%s/%s is a%s "
+				       "card%s%s%s\nwith link type %s.\n",
+				       card->rdev->dev.bus_id,
+				       card->wdev->dev.bus_id,
+				       card->ddev->dev.bus_id,
+				       qeth_get_cardname(card->type,
+							 card->is_guest_lan),
+				       (card->level[0]) ? " (level: " : "",
+				       (card->level[0]) ? card->level : "",
+				       (card->level[0]) ? ")" : "",
+				       qeth_get_link_type_name(card->type,
+							       card->link_type));
+		}
+	}
+
+exit:
+	spin_unlock(&card->hardsetup_lock);
+	return result;
+}
+
+static int
+qeth_reinit_thread(void *param)
+{
+	struct qeth_card *card = (struct qeth_card *) param;
+	int already_registered;
+	int already_hardsetup;
+	int retry = QETH_RECOVERY_HARDSETUP_RETRY;
+	int result;
+	char name[15];
+
+	QETH_DBF_TEXT1(0, trace, "RINI");
+	QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id);
+
+	/* set a nice name ... */
+	sprintf(name, "qethrinid%s", card->rdev->dev.bus_id);
+	daemonize(name);
+
+	if (atomic_read(&card->shutdown_phase))
+		goto out_wakeup;
+	down_interruptible(&card->reinit_thread_sem);
+	if (atomic_read(&card->shutdown_phase))
+		goto out_wakeup;
+
+	QETH_DBF_TEXT1(0, trace, "ri-gotin");
+	PRINT_STUPID("entering recovery (reinit) thread for device %s\n",
+		     card->dev_name);
+
+	atomic_set(&card->is_startlaned, 0);
+	atomic_set(&card->is_softsetup, 0);
+
+	read_lock(&list_lock);
+	if (!qeth_verify_card(card))
+		goto out;
+	QETH_DBF_TEXT1(0, trace, "ri-vrfd");
+
+	atomic_set(&card->write_busy, 0);
+	qeth_set_dev_flag_norunning(card);
+	already_hardsetup = atomic_read(&card->is_hardsetup);
+	already_registered = atomic_read(&card->is_registered);
+	if (already_hardsetup) {
+		atomic_set(&card->is_hardsetup, 0);
+
+		if (-1 == my_spin_lock_nonbusy(card, &setup_lock))
+			goto out;
+		if (atomic_read(&card->shutdown_phase))
+			goto out_wakeup;
+
+		atomic_set(&card->escape_softsetup, 1);
+
+		if (-1 == my_spin_lock_nonbusy(card, &card->softsetup_lock)) {
+			atomic_set(&card->escape_softsetup, 0);
+			goto out;
+		}
+		atomic_set(&card->escape_softsetup, 0);
+		if (atomic_read(&card->shutdown_phase)) {
+			spin_unlock(&card->softsetup_lock);
+			goto out_wakeup;
+		}
+		if (!qeth_verify_card(card))
+			goto out;
+
+		if (already_registered)
+			netif_stop_queue(card->dev);
+
+		qeth_wait_nonbusy(QETH_QUIESCE_NETDEV_TIME);
+
+		atomic_set(&card->is_startlaned, 0);
+
+		QETH_DBF_TEXT1(0, trace, "ri-frskb");
+		qeth_free_all_skbs(card);
+		do {
+			QETH_DBF_TEXT1(0, trace, "ri-hrdst");
+			result = qeth_hardsetup_card(card, 1);
+		} while (result && (retry--));
+
+		/* tries to remove old ips, that's paranoid, but ok */
+		qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa);
+		qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa);
+
+#ifdef QETH_IPV6
+		qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa);
+		qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa);
+#endif /* QETH_IPV6 */
+
+		if (result) {
+			QETH_DBF_TEXT1(0, trace, "ri-nosuc");
+			PRINT_ERR("qeth: RECOVERY WAS NOT SUCCESSFUL ON %s "
+				  "(%s/%s/%s), GIVING UP, "
+				  "OUTGOING PACKETS WILL BE DISCARDED!\n",
+				  card->dev_name,
+				  card->rdev->dev.bus_id,
+				  card->wdev->dev.bus_id,
+				  card->ddev->dev.bus_id);
+			/* early leave hard_start_xmit! */
+			atomic_set(&card->is_startlaned, 0);
+			qeth_wakeup_procfile();
+		} else {
+			QETH_DBF_TEXT1(0, trace, "ri-sftst");
+			qeth_softsetup_card(card, QETH_LOCK_ALREADY_HELD);
+			spin_unlock(&card->softsetup_lock);
+
+			if (!already_registered) {
+				QETH_DBF_TEXT1(0, trace, "ri-regcd");
+				qeth_register_netdev(card);
+			}
+			qeth_restore_dev_flag_state(card);
+			netif_wake_queue(card->dev);
+			qeth_wakeup_procfile();
+		}
+		spin_unlock(&setup_lock);
+	}
+out:
+	atomic_set(&card->in_recovery, 0);
+	read_unlock(&list_lock);
+	QETH_DBF_TEXT1(0, trace, "ri-leave");
+out_wakeup:
+	up(&card->reinit_thread_sem);
+	atomic_dec(&card->reinit_counter);
+
+	return 0;
+}
+
+static void
+qeth_fill_qeth_card_options(struct qeth_card *card)
+{
+	int i;
+
+	card->options.portname[0] = 0;
+	for (i = 1; i < 9; i++)
+		card->options.portname[i] = _ascebc[' '];
+	strcpy(card->options.devname, " ");
+	card->options.routing_type4 = NO_ROUTER;
+#ifdef QETH_IPV6
+	card->options.routing_type6 = NO_ROUTER;
+#endif /* QETH_IPV6 */
+	card->options.portno = 0;
+	card->options.checksum_type = QETH_CHECKSUM_DEFAULT;
+	card->options.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+	card->options.default_queue = QETH_DEFAULT_QUEUE;
+	card->options.inbound_buffer_count = DEFAULT_BUFFER_COUNT;
+	card->options.polltime = QETH_MAX_INPUT_THRESHOLD;
+	card->options.memusage = MEMUSAGE_DISCONTIG;
+	card->options.macaddr_mode = MACADDR_NONCANONICAL;
+	card->options.broadcast_mode = BROADCAST_ALLRINGS;
+	card->options.fake_broadcast = DONT_FAKE_BROADCAST;
+	card->options.ena_ipat = ENABLE_TAKEOVER;
+	card->options.add_hhlen = DEFAULT_ADD_HHLEN;
+	card->options.fake_ll = DONT_FAKE_LL;
+	card->options.async_iqd = SYNC_IQD;
+}
+
+static struct qeth_card *
+qeth_alloc_card(void)
+{
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT3(0, trace, "alloccrd");
+	card = (struct qeth_card *) vmalloc(sizeof (struct qeth_card));
+	if (!card)
+		goto exit_card;
+	memset(card, 0, sizeof (struct qeth_card));
+	init_waitqueue_head(&card->wait_q);
+	init_waitqueue_head(&card->ioctl_wait_q);
+
+	qeth_fill_qeth_card_options(card);
+
+	card->dma_stuff =
+	    (struct qeth_dma_stuff *) kmalloc(sizeof (struct qeth_dma_stuff),
+					      GFP_KERNEL | GFP_DMA);
+	if (!card->dma_stuff)
+		goto exit_dma;
+	memset(card->dma_stuff, 0, sizeof (struct qeth_dma_stuff));
+
+	card->dma_stuff->recbuf = (char *) kmalloc(QETH_BUFSIZE,
+						   GFP_KERNEL | GFP_DMA);
+	if (!card->dma_stuff->recbuf)
+		goto exit_dma1;
+	memset(card->dma_stuff->recbuf, 0, QETH_BUFSIZE);
+
+	card->dma_stuff->sendbuf = (char *) kmalloc(QETH_BUFSIZE,
+						    GFP_KERNEL | GFP_DMA);
+	if (!card->dma_stuff->sendbuf)
+		goto exit_dma2;
+	memset(card->dma_stuff->sendbuf, 0, QETH_BUFSIZE);
+
+	card->dev = (struct net_device *) kmalloc(sizeof (struct net_device),
+						  GFP_KERNEL);
+	if (!card->dev)
+		goto exit_dev;
+	memset(card->dev, 0, sizeof (struct net_device));
+
+	card->stats =
+	    (struct net_device_stats *)
+	    kmalloc(sizeof (struct net_device_stats), GFP_KERNEL);
+	if (!card->stats)
+		goto exit_stats;
+	memset(card->stats, 0, sizeof (struct net_device_stats));
+
+	spin_lock_init(&card->wait_q_lock);
+	spin_lock_init(&card->softsetup_lock);
+	spin_lock_init(&card->hardsetup_lock);
+	spin_lock_init(&card->ioctl_lock);
+#ifdef QETH_VLAN
+	spin_lock_init(&card->vlan_lock);
+	card->vlangrp = NULL;
+#endif
+	card->unique_id = 0;
+	sema_init(&card->reinit_thread_sem, 0);
+	up(&card->reinit_thread_sem);
+
+	/* setup card stuff */
+	card->ip_current_state.ip_ifa = NULL;
+	card->ip_new_state.ip_ifa = NULL;
+	card->ip_mc_current_state.ipm_ifa = NULL;
+	card->ip_mc_new_state.ipm_ifa = NULL;
+
+#ifdef QETH_IPV6
+	card->ip_current_state.ip6_ifa = NULL;
+	card->ip_new_state.ip6_ifa = NULL;
+	card->ip_mc_current_state.ipm6_ifa = NULL;
+	card->ip_mc_new_state.ipm6_ifa = NULL;
+#endif /* QETH_IPV6 */
+
+	/* setup net_device stuff */
+	card->dev->priv = card;
+
+	strncpy(card->dev->name, card->dev_name, IFNAMSIZ);
+
+	/* setup net_device_stats stuff */
+	/* =nothing yet */
+
+	/* and return to the sender */
+	return card;
+
+	/* these are quick exits in case of failures of the kmallocs */
+exit_stats:
+	kfree(card->dev);
+exit_dev:
+	kfree(card->dma_stuff->sendbuf);
+exit_dma2:
+	kfree(card->dma_stuff->recbuf);
+exit_dma1:
+	kfree(card->dma_stuff);
+exit_dma:
+	kfree(card);
+exit_card:
+	return NULL;
+}
+
+static int
+qeth_init_ringbuffers1(struct qeth_card *card)
+{
+	int i, j;
+
+	QETH_DBF_TEXT3(0, trace, "irb1");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	for (i = 0; i < card->no_queues; i++) {
+		card->outbound_ringbuffer[i] =
+		    vmalloc(sizeof (struct qeth_ringbuffer));
+		if (!card->outbound_ringbuffer[i]) {
+			for (j = i - 1; j >= 0; j--) {
+				vfree(card->outbound_ringbuffer[j]);
+				card->outbound_ringbuffer[j] = NULL;
+			}
+			return -ENOMEM;
+		}
+		memset(card->outbound_ringbuffer[i], 0,
+		       sizeof (struct qeth_ringbuffer));
+		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
+			skb_queue_head_init(&card->outbound_ringbuffer[i]->
+					    ringbuf_element[j].skb_list);
+	}
+
+	return 0;
+}
+
+static int
+qeth_init_ringbuffers2(struct qeth_card *card)
+{
+	int i, j;
+	int failed = 0;
+	int discont_mem, element_count;
+	long alloc_size;
+
+	QETH_DBF_TEXT3(0, trace, "irb2");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	discont_mem = (card->options.memusage == MEMUSAGE_DISCONTIG);
+	element_count = (discont_mem) ? BUFFER_MAX_ELEMENTS : 1;
+	alloc_size = (discont_mem) ? PAGE_SIZE : BUFFER_SIZE;
+	if (discont_mem) {
+		for (i = 0; i < card->options.inbound_buffer_count; i++) {
+			for (j = 0; j < element_count; j++) {
+				card->inbound_buffer_pool_entry[i][j] =
+				    kmalloc(alloc_size, GFP_KERNEL);
+				if (!card->inbound_buffer_pool_entry[i][j]) {
+					failed = 1;
+					goto out;
+				}
+			}
+			card->inbound_buffer_pool_entry_used[i] = BUFFER_UNUSED;
+		}
+	} else {
+		for (i = 0; i < card->options.inbound_buffer_count; i++) {
+			card->inbound_buffer_pool_entry[i][0] =
+			    kmalloc(alloc_size, GFP_KERNEL);
+			if (!card->inbound_buffer_pool_entry[i][0])
+				failed = 1;
+			for (j = 1; j < element_count; j++)
+				card->inbound_buffer_pool_entry[i][j] =
+				    card->inbound_buffer_pool_entry[i][0] +
+				    PAGE_SIZE * j;
+			card->inbound_buffer_pool_entry_used[i] = BUFFER_UNUSED;
+		}
+	}
+
+out:
+	if (failed) {
+		for (i = 0; i < card->options.inbound_buffer_count; i++) {
+			for (j = 0; j < QDIO_MAX_ELEMENTS_PER_BUFFER; j++) {
+				if (card->inbound_buffer_pool_entry[i][j]) {
+					if (j < element_count)
+						kfree(card->
+						      inbound_buffer_pool_entry
+						      [i][j]);
+					card->inbound_buffer_pool_entry
+					    [i][j] = NULL;
+				}
+			}
+		}
+		for (i = 0; i < card->no_queues; i++) {
+			vfree(card->outbound_ringbuffer[i]);
+			card->outbound_ringbuffer[i] = NULL;
+		}
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&card->requeue_input_lock);
+
+	return 0;
+}
+
+/* also locked from outside (setup_lock) */
+static void
+qeth_insert_card_into_list(struct qeth_card *card)
+{
+	QETH_DBF_TEXT3(0, trace, "icil");
+	QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
+
+	write_lock(&list_lock);
+	card->next = firstcard;
+	firstcard = card;
+	write_unlock(&list_lock);
+}
+
+static int
+qeth_determine_card_type(struct qeth_card *card)
+{
+	int i = 0;
+	char dbf_text[15];
+
+	while (known_devices[i][4]) {
+		if ((card->rdev->id.dev_type == known_devices[i][2]) &&
+		    (card->rdev->id.dev_model == known_devices[i][3])) {
+			card->type = known_devices[i][4];
+			if (card->options.ena_ipat == ENABLE_TAKEOVER)
+				card->func_level = known_devices[i][6];
+			else
+				card->func_level = known_devices[i][7];
+			card->no_queues = known_devices[i][8];
+			card->is_multicast_different = known_devices[i][9];
+			QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id);
+			sprintf(dbf_text, "ctyp%4x", card->type);
+			QETH_DBF_TEXT2(0, setup, dbf_text);
+			return 0;
+		}
+		i++;
+	}
+	card->type = QETH_CARD_TYPE_UNKNOWN;
+	QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id);
+	sprintf(dbf_text, "ctypUNKN");
+	QETH_DBF_TEXT2(0, setup, dbf_text);
+	PRINT_ERR("unknown card type on device %s\n", card->rdev->dev.bus_id);
+	return -ENOENT;
+}
+
+static int
+qeth_getint(char *s, int longint)
+{
+	int cnt;
+	int hex;
+	int result;
+	char c;
+
+	if (!s)
+		return -1;
+	hex = ((s[0] == '0') && ((s[1] == 'x') || (s[1] == 'X'))) ? 1 : 0;
+	cnt = (hex) ? 2 : 0;	/* start from the first real digit */
+	if (!(s[cnt]))
+		return -1;
+	result = 0;
+	while ((c = s[cnt++])) {
+		if (hex) {
+			if (isxdigit(c))
+				result = result * 16 + qeth_getxdigit(c);
+			else
+				return -1;
+		} else {
+			if (isdigit(c))
+				result = result * 10 + c - '0';
+			else
+				return -1;
+		}
+		/* prevent overflow, 0xffff is enough for us */
+		if (longint) {
+			if (result > 0xfffffff)
+				return -1;
+		} else {
+			if (result > 0xffff)
+				return -1;
+		}
+	}
+	return result;
+}
+
+static void
+__qeth_correct_routing_status_v4(struct qeth_card *card)
+{
+	if (card->options.routing_type4 == NO_ROUTER)
+		return;
+
+	if (card->type == QETH_CARD_TYPE_IQD) {
+		/* if it's not a mc router, it's no router */
+		if ((card->options.routing_type4 == PRIMARY_ROUTER) ||
+		    (card->options.routing_type4 == SECONDARY_ROUTER)) {
+			PRINT_WARN("routing not applicable, reset "
+				   "routing status for ipv4. \n");
+			card->options.routing_type4 = NO_ROUTER;
+		}
+		card->options.do_prio_queueing = NO_PRIO_QUEUEING;
+	} else {
+		/* if it's a mc router, it's no router */
+		if ((card->options.routing_type4 == MULTICAST_ROUTER) ||
+		    (card->options.routing_type4 == PRIMARY_CONNECTOR) ||
+		    (card->options.routing_type4 == SECONDARY_CONNECTOR)) {
+			PRINT_WARN("routing not applicable, reset "
+				   "routing status for ipv4. (Did you mean "
+				   "primary_router or secondary_router?)\n");
+			card->options.routing_type4 = NO_ROUTER;
+		}
+	}
+}
+
+static void
+__qeth_correct_routing_status_v6(struct qeth_card *card)
+{
+#ifdef QETH_IPV6
+	if (card->options.routing_type6 == NO_ROUTER)
+		return;
+	if (card->type == QETH_CARD_TYPE_IQD) {
+		/* if it's not a mc router, it's no router */
+		if ((card->options.routing_type6 == PRIMARY_ROUTER) ||
+		    (card->options.routing_type6 == SECONDARY_ROUTER)) {
+			PRINT_WARN("routing not applicable, reset "
+				   "routing status for ipv6. \n");
+			card->options.routing_type6 = NO_ROUTER;
+		}
+		card->options.do_prio_queueing = NO_PRIO_QUEUEING;
+	} else {
+		/* if it's a mc router, it's no router */
+		if ((card->options.routing_type6 == MULTICAST_ROUTER) ||
+		    (card->options.routing_type6 == PRIMARY_CONNECTOR) ||
+		    (card->options.routing_type6 == SECONDARY_CONNECTOR)) {
+			PRINT_WARN("routing not applicable, reset "
+				   "routing status for ipv6. (Did you mean "
+				   "primary_router or secondary_router?)\n");
+			card->options.routing_type6 = NO_ROUTER;
+		}
+	}
+#endif /* QETH_IPV6 */
+}
+
+static void
+qeth_correct_routing_status(struct qeth_card *card)
+{
+	__qeth_correct_routing_status_v4(card);
+	__qeth_correct_routing_status_v6(card);
+}
+
+static struct net_device *
+qeth_init_netdev(struct net_device *dev)
+{
+
+	struct qeth_card *card = NULL;
+	int result;
+	char dbf_text[15];
+
+	if (!dev) {
+		PRINT_ERR("qeth_init_netdev called with no device!\n");
+		goto out;
+	}
+
+	card = (struct qeth_card *) dev->priv;
+	strcpy(card->dev_name, dev->name);
+	result = qeth_register_netdev(card);
+	if (result) {
+		PRINT_ALL("         register_netdev %s -- rc=%i\n",
+			  ((struct qeth_card *) firstcard->dev->priv)->
+			  dev_name, result);
+		sprintf(dbf_text, "rgnd%4x", (__u16) result);
+		QETH_DBF_TEXT2(1, trace, dbf_text);
+		atomic_set(&card->is_registered, 0);
+		goto out;
+	}
+	strcpy(card->dev_name, dev->name);
+	atomic_set(&card->write_busy, 0);
+	atomic_set(&card->is_registered, 1);
+
+	result = qeth_softsetup_card(card, QETH_WAIT_FOR_LOCK);
+
+	if (!result) {
+		qeth_init_input_buffers(card);
+	} else {
+		QETH_DBF_TEXT2(0, trace, "SSFAILED");
+		PRINT_WARN("soft-setup of card failed!\n");
+	}
+
+	INIT_WORK(&card->tqueue, qeth_softsetup_thread_starter, card);
+	schedule_work(&card->tqueue);
+out:
+	qeth_wakeup_procfile();
+	return dev;
+
+}
+
+static int
+qeth_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct qeth_card *card;
+	struct net_device *dev = (struct net_device *) ptr;
+	char dbf_text[15];
+
+	sprintf(dbf_text, "devevent");
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+	QETH_DBF_HEX3(0, trace, &event, sizeof (unsigned long));
+	QETH_DBF_HEX3(0, trace, &dev, sizeof (void *));
+
+	card = __qeth_get_card_from_dev(dev);
+	if (qeth_does_card_exist(card)) {
+		qeth_save_dev_flag_state(card);
+		switch (event) {
+		default:
+			qeth_start_softsetup_thread(card);
+			break;
+		}
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int
+qeth_ip_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct qeth_card *card;
+	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
+	struct net_device *dev = ifa->ifa_dev->dev;
+	char dbf_text[15];
+
+	sprintf(dbf_text, "ipevent");
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+	QETH_DBF_HEX3(0, trace, &event, sizeof (unsigned long));
+	QETH_DBF_HEX3(0, trace, &dev, sizeof (void *));
+	sprintf(dbf_text, "%08x", ifa->ifa_address);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+	sprintf(dbf_text, "%08x", ifa->ifa_mask);
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+
+	card = __qeth_get_card_from_dev(dev);
+	if (qeth_does_card_exist(card)) {
+		QETH_DBF_HEX3(0, trace, &card, sizeof (void *));
+		qeth_save_dev_flag_state(card);
+		qeth_start_softsetup_thread(card);
+	}
+
+	return NOTIFY_DONE;
+}
+
+#ifdef QETH_IPV6
+static int
+qeth_ip6_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct qeth_card *card;
+	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *) ptr;
+	struct net_device *dev = ifa->idev->dev;
+	char dbf_text[15];
+
+	sprintf(dbf_text, "ip6event");
+	QETH_DBF_TEXT3(0, trace, dbf_text);
+	QETH_DBF_HEX3(0, trace, &event, sizeof (unsigned long));
+	QETH_DBF_HEX3(0, trace, &dev, sizeof (void *));
+	QETH_DBF_HEX3(0, trace, ifa->addr.s6_addr, QETH_DBF_TRACE_LEN);
+	QETH_DBF_HEX3(0, trace, ifa->addr.s6_addr + QETH_DBF_TRACE_LEN,
+		      QETH_DBF_TRACE_LEN);
+
+	card = __qeth_get_card_from_dev(dev);
+	if (qeth_does_card_exist(card)) {
+		QETH_DBF_HEX3(0, trace, &card, sizeof (void *));
+		qeth_save_dev_flag_state(card);
+		qeth_start_softsetup_thread(card);
+	}
+
+	return NOTIFY_DONE;
+}
+#endif /* QETH_IPV6 */
+
+static int
+qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct qeth_card *card;
+
+	read_lock(&list_lock);
+	if (firstcard) {
+		card = firstcard;
+	clear_another_one:
+		if (card->type == QETH_CARD_TYPE_IQD) {
+			ccw_device_halt(card->ddev, 0);
+			ccw_device_clear(card->rdev, 0);
+			ccw_device_clear(card->wdev, 0);
+			ccw_device_clear(card->ddev, 0);
+		} else {
+			ccw_device_clear(card->ddev, 0);
+			ccw_device_clear(card->rdev, 0);
+			ccw_device_clear(card->wdev, 0);
+		}
+		if (card->next) {
+			card = card->next;
+			goto clear_another_one;
+		}
+	}
+	read_unlock(&list_lock);
+
+	return 0;
+}
+
+static struct notifier_block qeth_dev_notifier = {
+	qeth_dev_event,
+	0
+};
+
+static struct notifier_block qeth_ip_notifier = {
+	qeth_ip_event,
+	0
+};
+
+#ifdef QETH_IPV6
+static struct notifier_block qeth_ip6_notifier = {
+	qeth_ip6_event,
+	0
+};
+#endif /* QETH_IPV6 */
+
+static struct notifier_block qeth_reboot_notifier = {
+	qeth_reboot_event,
+	0
+};
+
+static void
+qeth_register_notifiers(void)
+{
+	int r;
+
+	QETH_DBF_TEXT5(0, trace, "regnotif");
+	/* register to be notified on events */
+	r = register_netdevice_notifier(&qeth_dev_notifier);
+
+	r = register_inetaddr_notifier(&qeth_ip_notifier);
+#ifdef QETH_IPV6
+	r = register_inet6addr_notifier(&qeth_ip6_notifier);
+#endif /* QETH_IPV6 */
+	r = register_reboot_notifier(&qeth_reboot_notifier);
+}
+
+static void __exit
+qeth_unregister_notifiers(void)
+{
+	int r;
+
+	QETH_DBF_TEXT5(0, trace, "unregnot");
+	r = unregister_netdevice_notifier(&qeth_dev_notifier);
+	r = unregister_inetaddr_notifier(&qeth_ip_notifier);
+#ifdef QETH_IPV6
+	r = unregister_inet6addr_notifier(&qeth_ip6_notifier);
+#endif /* QETH_IPV6 */
+	r = unregister_reboot_notifier(&qeth_reboot_notifier);
+
+}
+
+static int
+qeth_procfile_open(struct inode *inode, struct file *file)
+{
+	int length = 0;
+	struct qeth_card *card;
+	char checksum_str[5], queueing_str[14], router_str[8], bufsize_str[4];
+	char *buffer;
+	int rc = 0;
+	int size;
+	struct tempinfo *info;
+
+	info = (struct tempinfo *) vmalloc(sizeof (struct tempinfo));
+	if (info == NULL) {
+		PRINT_WARN("No memory available for data\n");
+		return -ENOMEM;
+	} else {
+		file->private_data = (void *) info;
+	}
+
+	/* lock all the stuff */
+	read_lock(&list_lock);
+	card = firstcard;
+	size = 200;		/* 2 lines plus some sanity space */
+	while (card) {
+		size += 90;	/* if device name is > 10 chars, (should never
+				   happen...), we'll need that */
+		card = card->next;
+	}
+
+	buffer = info->data = (char *) vmalloc(size);
+	if (info->data == NULL) {
+		PRINT_WARN("No memory available for data\n");
+		vfree(info);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	QETH_DBF_TEXT2(0, trace, "procread");
+	length += sprintf(buffer + length,
+			  "devices            CHPID     "
+			  "device     cardtype port chksum prio-q'ing "
+			  "rtr fsz C cnt\n");
+	length += sprintf(buffer + length,
+			  "-------------------- --- ----"
+			  "------ -------------- --     -- ---------- "
+			  "--- --- - ---\n");
+	card = firstcard;
+	while (card) {
+		strcpy(checksum_str,
+		       (card->options.checksum_type == SW_CHECKSUMMING) ? "SW" :
+		       (card->options.checksum_type == HW_CHECKSUMMING) ? "HW" :
+		       "no");
+		if (card->options.do_prio_queueing == NO_PRIO_QUEUEING) {
+			sprintf(queueing_str, "always_q_%i",
+				card->options.default_queue);
+		} else {
+			strcpy(queueing_str, (card->options.do_prio_queueing
+					      ==
+					      PRIO_QUEUEING_PREC) ? "by_prec." :
+			       "by_ToS");
+		}
+
+		/* FIXME: this is really a mess... */
+
+#ifdef QETH_IPV6
+		if (atomic_read(&card->rt4fld) && atomic_read(&card->rt6fld))
+			strcpy(router_str, "no");
+		else if (atomic_read(&card->rt4fld)
+			 || atomic_read(&card->rt6fld))
+			strcpy(router_str, "mix");
+#else/* QETH_IPV6 */
+		if (atomic_read(&card->rt4fld))
+			strcpy(router_str, "no");
+#endif /* QETH_IPV6 */
+		else if (((card->options.routing_type4 & ROUTER_MASK) ==
+			  PRIMARY_ROUTER)
+#ifdef QETH_IPV6
+			 &&
+			 ((card->options.routing_type6 & ROUTER_MASK) ==
+			  PRIMARY_ROUTER)
+#endif /* QETH_IPV6 */
+		    ) {
+			strcpy(router_str, "pri");
+		} else
+		    if (((card->options.routing_type4 & ROUTER_MASK) ==
+			 SECONDARY_ROUTER)
+#ifdef QETH_IPV6
+			&&
+			((card->options.routing_type6 & ROUTER_MASK) ==
+			 SECONDARY_ROUTER)
+#endif /* QETH_IPV6 */
+		    ) {
+			strcpy(router_str, "sec");
+		} else
+		    if (((card->options.routing_type4 & ROUTER_MASK) ==
+			 MULTICAST_ROUTER)
+#ifdef QETH_IPV6
+			&&
+			((card->options.routing_type6 & ROUTER_MASK) ==
+			 MULTICAST_ROUTER)
+#endif /* QETH_IPV6 */
+		    ) {
+			strcpy(router_str, "mc");
+		} else
+		    if (((card->options.routing_type4 & ROUTER_MASK) ==
+			 PRIMARY_CONNECTOR)
+#ifdef QETH_IPV6
+			&&
+			((card->options.routing_type6 & ROUTER_MASK) ==
+			 PRIMARY_CONNECTOR)
+#endif /* QETH_IPV6 */
+		    ) {
+			strcpy(router_str, "p.c");
+		} else
+		    if (((card->options.routing_type4 & ROUTER_MASK) ==
+			 SECONDARY_CONNECTOR)
+#ifdef QETH_IPV6
+			&&
+			((card->options.routing_type6 & ROUTER_MASK) ==
+			 SECONDARY_CONNECTOR)
+#endif /* QETH_IPV6 */
+		    ) {
+			strcpy(router_str, "s.c");
+		} else
+		    if (((card->options.routing_type4 & ROUTER_MASK) ==
+			 NO_ROUTER)
+#ifdef QETH_IPV6
+			&&
+			((card->options.routing_type6 & ROUTER_MASK) ==
+			 NO_ROUTER)
+#endif /* QETH_IPV6 */
+		    ) {
+			strcpy(router_str, "no");
+		} else {
+			strcpy(router_str, "mix");
+		}
+		strcpy(bufsize_str,
+		       (BUFFER_SIZE == 16384) ? "16k" :
+		       (BUFFER_SIZE == 24576) ? "24k" :
+		       (BUFFER_SIZE == 32768) ? "32k" :
+		       (BUFFER_SIZE == 40960) ? "40k" : "64k");
+
+		if (!atomic_read(&card->is_startlaned)) {
+			length += sprintf(buffer + length,
+					  "%s/%s/%s x%02X %10s %14s %2i"
+					  "  +++ CABLE PULLED +++\n",
+					  card->rdev->dev.bus_id,
+					  card->wdev->dev.bus_id,
+					  card->ddev->dev.bus_id,
+					  card->chpid,
+					  card->dev_name,
+					  qeth_get_cardname_short
+					  (card->type, card->link_type,
+					   card->is_guest_lan),
+					  card->options.portno);
+		} else {
+			length += sprintf(buffer + length,
+					  "%s/%s/%s x%02X %10s %14s %2i"
+					  "     %2s %10s %3s %3s %c %3i\n",
+					  card->rdev->dev.bus_id,
+					  card->wdev->dev.bus_id,
+					  card->ddev->dev.bus_id,
+					  card->chpid, card->dev_name,
+					  qeth_get_cardname_short
+					  (card->type, card->link_type,
+					   card->is_guest_lan),
+					  card->options.portno, checksum_str,
+					  queueing_str, router_str, bufsize_str,
+					  (card->options.memusage ==
+					   MEMUSAGE_CONTIG) ? 'c' : ' ',
+					  card->options.inbound_buffer_count);
+		}
+		card = card->next;
+	}
+
+out:
+	info->len = length;
+	/* unlock all the stuff */
+	read_unlock(&list_lock);
+	return rc;
+}
+
+#define _OUTP_IT(x...) c+=sprintf(buffer+c,x)
+
+#ifdef QETH_PERFORMANCE_STATS
+static int
+qeth_perf_procfile_read(char *buffer, char **buffer_location,
+			off_t offset, int buffer_length, int *eof, void *data)
+{
+	int c = 0;
+	struct qeth_card *card;
+	/* we are always called with buffer_length=4k, so we all
+	   deliver on the first read */
+	if (offset > 0)
+		return 0;
+
+	QETH_DBF_TEXT2(0, trace, "perfpfrd");
+
+	card = firstcard;
+
+	while (card) {
+		_OUTP_IT("For card with devnos %s/%s/%s (%s):\n",
+			 card->rdev->dev.bus_id,
+			 card->wdev->dev.bus_id,
+			 card->ddev->dev.bus_id, card->dev_name);
+		_OUTP_IT("  Skb's/buffers received                 : %i/%i\n",
+			 card->perf_stats.skbs_rec, card->perf_stats.bufs_rec);
+		_OUTP_IT("  Skb's/buffers sent                     : %i/%i\n",
+			 card->perf_stats.skbs_sent,
+			 card->perf_stats.bufs_sent);
+		_OUTP_IT("\n");
+		_OUTP_IT("  Skb's/buffers sent without packing     : %i/%i\n",
+			 card->perf_stats.skbs_sent_dont_pack,
+			 card->perf_stats.bufs_sent_dont_pack);
+		_OUTP_IT("  Skb's/buffers sent with packing        : %i/%i\n",
+			 card->perf_stats.skbs_sent_pack,
+			 card->perf_stats.bufs_sent_pack);
+		_OUTP_IT("\n");
+		_OUTP_IT("  Packing state changes no pkg.->packing : %i/%i\n",
+			 card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp);
+		_OUTP_IT("  Current buffer usage (outbound q's)    : "
+			 "%i/%i/%i/%i\n",
+			 atomic_read(&card->outbound_used_buffers[0]),
+			 atomic_read(&card->outbound_used_buffers[1]),
+			 atomic_read(&card->outbound_used_buffers[2]),
+			 atomic_read(&card->outbound_used_buffers[3]));
+		_OUTP_IT("\n");
+		_OUTP_IT("  Inbound time (in us)                   : %i\n",
+			 card->perf_stats.inbound_time);
+		_OUTP_IT("  Inbound cnt                            : %i\n",
+			 card->perf_stats.inbound_cnt);
+		_OUTP_IT("  Outbound time (in us, incl QDIO)       : %i\n",
+			 card->perf_stats.outbound_time);
+		_OUTP_IT("  Outbound cnt                           : %i\n",
+			 card->perf_stats.outbound_cnt);
+		_OUTP_IT("  Watermarks: L/H=%i/%i\n",
+			 LOW_WATERMARK_PACK, HIGH_WATERMARK_PACK);
+		_OUTP_IT("\n");
+
+		card = card->next;
+	}
+
+	return c;
+}
+
+static struct proc_dir_entry *qeth_perf_proc_file;
+
+#endif /* QETH_PERFORMANCE_STATS */
+
+static int
+qeth_ipato_procfile_open(struct inode *inode, struct file *file)
+{
+	char text[33];
+	struct ipato_entry *ipato_entry;
+	struct qeth_card *card;
+	struct qeth_vipa_entry *vipa_entry;
+	int rc = 0;
+	struct tempinfo *info;
+	int size;
+	char entry_type[5];
+
+	info = (struct tempinfo *) vmalloc(sizeof (struct tempinfo));
+	if (info == NULL) {
+		PRINT_WARN("No memory available for data\n");
+		return -ENOMEM;
+	} else {
+		file->private_data = (void *) info;
+	}
+	info->len = 0;
+
+	QETH_DBF_TEXT2(0, trace, "ipatorea");
+	/* lock all the stuff */
+	spin_lock(&ipato_list_lock);
+	read_lock(&list_lock);
+
+	size = 64;		/* for inv4/6 etc. */
+
+	ipato_entry = ipato_entries;
+	while (ipato_entry) {
+		ipato_entry = ipato_entry->next;
+		size += 64;
+	}
+	card = firstcard;
+	while (card) {
+		read_lock(&card->vipa_list_lock);
+		vipa_entry = card->vipa_list;
+		while (vipa_entry) {
+			vipa_entry = vipa_entry->next;
+			size += 64;
+		}
+		/*read_unlock(&card->vipa_list_lock); don't unlock it here */
+		card = card->next;
+	}
+	info->data = (char *) vmalloc(size);
+	if (info->data == NULL) {
+		PRINT_WARN("No memory available for data\n");
+		vfree(info);
+		rc = -ENOMEM;
+		goto out;
+	}
+#define _IOUTP_IT(x...) info->len+=sprintf(info->data+info->len,x)
+	if (ipato_inv4)
+		_IOUTP_IT("inv4\n");
+	ipato_entry = ipato_entries;
+	text[8] = 0;
+	while (ipato_entry) {
+		if (ipato_entry->version == 4) {
+			qeth_convert_addr_to_text(4, ipato_entry->addr, text);
+			_IOUTP_IT("add4 %s/%i%s%s\n", text,
+				  ipato_entry->mask_bits,
+				  ipato_entry->dev_name[0] ? ":" : "",
+				  ipato_entry->dev_name[0] ?
+				  ipato_entry->dev_name : "");
+		}
+		ipato_entry = ipato_entry->next;
+	}
+
+	if (ipato_inv6)
+		_IOUTP_IT("inv6\n");
+	ipato_entry = ipato_entries;
+	text[32] = 0;
+	while (ipato_entry) {
+		if (ipato_entry->version == 6) {
+			qeth_convert_addr_to_text(6, ipato_entry->addr, text);
+			_IOUTP_IT("add6 %s/%i%s%s\n", text,
+				  ipato_entry->mask_bits,
+				  ipato_entry->dev_name[0] ? ":" : "",
+				  ipato_entry->dev_name[0] ?
+				  ipato_entry->dev_name : "");
+		}
+		ipato_entry = ipato_entry->next;
+	}
+	card = firstcard;
+	while (card) {
+		vipa_entry = card->vipa_list;
+		while (vipa_entry) {
+			strcpy(entry_type, (vipa_entry->flag ==
+					    IPA_SETIP_VIPA_FLAGS) ?
+			       "vipa" : "rxip");
+			if (vipa_entry->version == 4) {
+				_IOUTP_IT("add_%s4 %02x%02x%02x%02x:%s\n",
+					  entry_type,
+					  vipa_entry->ip[0],
+					  vipa_entry->ip[1],
+					  vipa_entry->ip[2],
+					  vipa_entry->ip[3], card->dev_name);
+			} else {
+				_IOUTP_IT("add_%s6 %02x%02x%02x%02x"
+					  "%02x%02x%02x%02x"
+					  "%02x%02x%02x%02x"
+					  "%02x%02x%02x%02x:%s\n",
+					  entry_type,
+					  vipa_entry->ip[0],
+					  vipa_entry->ip[1],
+					  vipa_entry->ip[2],
+					  vipa_entry->ip[3],
+					  vipa_entry->ip[4],
+					  vipa_entry->ip[5],
+					  vipa_entry->ip[6],
+					  vipa_entry->ip[7],
+					  vipa_entry->ip[8],
+					  vipa_entry->ip[9],
+					  vipa_entry->ip[10],
+					  vipa_entry->ip[11],
+					  vipa_entry->ip[12],
+					  vipa_entry->ip[13],
+					  vipa_entry->ip[14],
+					  vipa_entry->ip[15], card->dev_name);
+			}
+			vipa_entry = vipa_entry->next;
+		}
+		card = card->next;
+	}
+out:
+	/* unlock all the stuff */
+	card = firstcard;
+	while (card) {
+		/*read_lock(&card->vipa_list_lock); don't lock it here */
+		read_unlock(&card->vipa_list_lock);
+		card = card->next;
+	}
+	read_unlock(&list_lock);
+	spin_unlock(&ipato_list_lock);
+
+	return rc;
+}
+
+static ssize_t
+qeth_procfile_read(struct file *file, char *user_buf,
+		   size_t user_len, loff_t * offset)
+{
+	loff_t len;
+	struct tempinfo *p_info = (struct tempinfo *) file->private_data;
+
+	if (*offset >= p_info->len) {
+		return 0;
+	} else {
+		len = __min(user_len, (p_info->len - *offset));
+		if (copy_to_user(user_buf, &(p_info->data[*offset]), len))
+			return -EFAULT;
+		(*offset) += len;
+		return len;
+	}
+}
+
+/* ATT: this is also the procfile release function for the ipato
+ * procfs entry */
+static int
+qeth_procfile_release(struct inode *inode, struct file *file)
+{
+	struct tempinfo *p_info = (struct tempinfo *) file->private_data;
+
+	if (p_info) {
+		if (p_info->data)
+			vfree(p_info->data);
+		vfree(p_info);
+	}
+
+	return 0;
+}
+
+static ssize_t
+qeth_ipato_procfile_write(struct file *file,
+			  const char *user_buffer,
+			  size_t user_len, loff_t * offset)
+{
+	int add, version;
+	char text[33];
+	__u8 addr[16];
+	int len, i, flag;
+	int mask_bits;
+	char *buffer;
+	int dev_name_there;
+	char *dev_name_ptr;
+	struct qeth_card *card;
+#define BUFFER_LEN (10+32+1+5+1+DEV_NAME_LEN+1)
+
+	if (*offset > 0)
+		return user_len;
+	buffer =
+	    vmalloc(__max(__max(user_len + 1, BUFFER_LEN), QETH_DBF_MISC_LEN));
+
+	if (buffer == NULL)
+		return -ENOMEM;
+	/* BUFFER_LEN=command incl. blank+addr+slash+mask_bits+
+	 * colon+DEV_NAME_LEN+zero */
+	memset(buffer, 0, BUFFER_LEN);
+
+	if (copy_from_user(buffer, user_buffer, user_len)) {
+		vfree(buffer);
+		return -EFAULT;
+	}
+
+	QETH_DBF_TEXT2(0, trace, "ipatowri");
+	QETH_DBF_TEXT2(0, misc, buffer);
+	if (!strncmp(buffer, "inv4", 4)) {
+		ipato_inv4 = 1 - ipato_inv4;
+		goto out;
+	}
+	if (!strncmp(buffer, "inv6", 4)) {
+		ipato_inv6 = 1 - ipato_inv6;
+		goto out;
+	}
+	if ((!strncmp(buffer, "add4 ", 5)) ||
+	    (!strncmp(buffer, "add6 ", 5)) ||
+	    (!strncmp(buffer, "del4 ", 5)) || (!strncmp(buffer, "del6 ", 5))) {
+		text[8] = 0;
+		text[32] = 0;
+		add = !strncmp(buffer, "add", 3);
+		version = (buffer[3] == '4') ? 4 : 6;
+		len = (version == 4) ? 8 : 32;
+		strncpy(text, buffer + 5, len);
+		if (qeth_convert_text_to_addr(version, text, addr)) {
+			PRINT_ERR("error in parsing ipato information "
+				  "(addr)\n");
+			goto out;
+		}
+		strncpy(text, buffer + 5 + len + 1, 10);
+		/* we prepare mask_bits for qeth_getints */
+		dev_name_there = 0;
+		for (i = 5 + len + 1; i < BUFFER_LEN; i++) {
+			if (*(buffer + i) == '\n') {
+				*(buffer + i) = 0;
+				break;
+			}
+			if (*(buffer + i) == ':') {
+				*(buffer + i) = 0;	/* so that qeth_getint works */
+				dev_name_there = i;
+				break;
+			}
+			if (*(buffer + i) == 0)
+				break;
+		}
+		mask_bits = qeth_getint(buffer + 5 + len + 1, 0);
+		if ((mask_bits < 0)
+		    || (mask_bits > ((version == 4) ? 32 : 128))) {
+			PRINT_ERR("error in parsing ipato information "
+				  "(mask bits)\n");
+			goto out;
+		}
+		if (dev_name_there) {
+			dev_name_ptr = buffer + dev_name_there + 1;
+			/* wipe out the linefeed */
+			for (i = dev_name_there + 1;
+			     i < dev_name_there + 1 + DEV_NAME_LEN + 1; i++)
+				if (*(buffer + i) == '\n')
+					*(buffer + i) = 0;
+		} else
+			dev_name_ptr = NULL;
+
+		if (add)
+			qeth_add_ipato_entry(version, addr, mask_bits,
+					     dev_name_ptr);
+		else
+			qeth_del_ipato_entry(version, addr, mask_bits,
+					     dev_name_ptr);
+		goto out;
+	}
+	if ((!strncmp(buffer, "add_vipa4 ", 10)) ||
+	    (!strncmp(buffer, "add_rxip4 ", 10)) ||
+	    (!strncmp(buffer, "add_vipa6 ", 10)) ||
+	    (!strncmp(buffer, "add_rxip6 ", 10)) ||
+	    (!strncmp(buffer, "del_vipa4 ", 10)) ||
+	    (!strncmp(buffer, "del_rxip4 ", 10)) ||
+	    (!strncmp(buffer, "del_vipa6 ", 10)) ||
+	    (!strncmp(buffer, "del_rxip6 ", 10))) {
+		text[8] = 0;
+		text[32] = 0;
+		add = !strncmp(buffer, "add", 3);
+		flag =
+		    (!strncmp(buffer + 4, "vipa", 4)) ? IPA_SETIP_VIPA_FLAGS :
+		    IPA_SETIP_TAKEOVER_FLAGS;
+		version = (buffer[8] == '4') ? 4 : 6;
+		len = (version == 4) ? 8 : 32;
+		strncpy(text, buffer + 10, len);
+		if (qeth_convert_text_to_addr(version, text, addr)) {
+			PRINT_ERR("error in parsing vipa/rxip information "
+				  "(addr)\n");
+			goto out;
+		}
+		if (*(buffer + 10 + len) != ':') {
+			PRINT_ERR("error in parsing vipa/rxip information "
+				  "(no interface)\n");
+			goto out;
+		}
+		/* interface name is at buffer+10+len+1 */
+		/* wipe out the \n */
+		for (i = 10 + len + 1; i < 10 + len + 1 + DEV_NAME_LEN + 1; i++)
+			if (*(buffer + i) == '\n')
+				*(buffer + i) = 0;
+		card = qeth_get_card_by_name(buffer + 10 + len + 1);
+		if (!card) {
+			PRINT_ERR("error in parsing vipa/rxip information "
+				  "(unknown interface)\n");
+			goto out;
+		}
+		if (add)
+			i = qeth_add_vipa_entry(card, version, addr, flag);
+		else
+			i = qeth_del_vipa_entry(card, version, addr, flag);
+		if (!i)
+			qeth_start_softsetup_thread(card);
+		goto out;
+	}
+	PRINT_ERR("unknown ipato information command\n");
+out:
+	vfree(buffer);
+	*offset = *offset + user_len;
+#undef BUFFER_LEN
+	return user_len;
+}
+
+static int
+qeth_procfile_getinterfaces(unsigned long arg)
+{
+	struct qeth_card *card;
+
+	char parms[16];
+	char *buffer;
+	char *buffer_pointer;
+	__u32 version, valid_fields, qeth_version, number_of_devices, if_index;
+	__u32 data_size, data_len;
+	unsigned long ioctl_flags;
+	int result = 0;
+
+	/* the struct of version 0 is:
+	   typedef struct dev_list
+	   {
+	   char device_name[IFNAME_MAXLEN]; // OSA-Exp device name (e.g. eth0)
+	   __u32 if_index;                  // interface index from kernel
+	   __u32 flags;                    // device charateristics
+	   } __attribute__((packed)) DEV_LIST;
+
+	   typedef struct osaexp_dev_ver0
+	   {
+	   __u32 version;                // structure version
+	   __u32 valid_fields;           // bitmask of fields that are really filled
+	   __u32 qeth_version;           // qeth driver version
+	   __u32 number_of_devices;      // number of OSA Express devices
+	   struct dev_list devices[0]; // list of OSA Express devices
+	   } __attribute__((packed)) OSAEXP_DEV_VER0;
+	 */
+
+	version = 0;
+	valid_fields = 0;
+	qeth_version = 0;
+	number_of_devices = 0;
+
+	copy_from_user((void *) parms, (void *) arg, sizeof (parms));
+	memcpy(&data_size, parms, sizeof (__u32));
+
+	if (!(data_size > 0))
+		return -EFAULT;
+	if (data_size > IOCTL_MAX_TRANSFER_SIZE)
+		return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, (void *) arg, data_size))
+		return -EFAULT;
+
+	read_lock(&list_lock);
+	card = firstcard;
+#define IOCTL_USER_STRUCT_SIZE (DEV_NAME_LEN*sizeof(char)) + \
+	sizeof(__u32) + sizeof(__u32)
+	while (card) {
+		if (card->type == QETH_CARD_TYPE_OSAE)
+			number_of_devices =
+			    number_of_devices + IOCTL_USER_STRUCT_SIZE;
+		card = card->next;
+	}
+#undef IOCTL_USER_STRUCT_SIZE
+	if ((number_of_devices + 4 * sizeof (__u32)) >= data_size) {
+		result = -ENOMEM;
+		goto out;
+	}
+
+	number_of_devices = 0;
+	card = firstcard;
+	buffer = (char *) vmalloc(data_size);
+	if (!buffer) {
+		result = -EFAULT;
+		goto out;
+	}
+	buffer_pointer = ((char *) (buffer)) + (4 * sizeof (__u32));
+	while (card) {
+		if ((card->type == QETH_CARD_TYPE_OSAE) &&
+		    (atomic_read(&card->is_hardsetup)) &&
+		    (atomic_read(&card->is_registered))) {
+
+			memcpy(buffer_pointer, card->dev_name, DEV_NAME_LEN);
+			buffer_pointer = buffer_pointer + DEV_NAME_LEN;
+			if_index = card->dev->ifindex;
+			memcpy(buffer_pointer, &if_index, sizeof (__u32));
+			buffer_pointer = buffer_pointer + sizeof (__u32);
+			memcpy(buffer_pointer, &ioctl_flags, sizeof (__u32));
+			buffer_pointer = buffer_pointer + sizeof (__u32);
+			number_of_devices = number_of_devices + 1;
+		}
+		card = card->next;
+	}
+
+	/* we copy the real size */
+	data_len = buffer_pointer - buffer;
+
+	buffer_pointer = buffer; 
+	/* copy the header information at the beginning of the buffer */
+	memcpy(buffer_pointer, &version, sizeof (__u32));
+	memcpy(((char *) buffer_pointer) + sizeof (__u32), &valid_fields,
+	       sizeof (__u32));
+	memcpy(((char *) buffer_pointer) + (2 * sizeof (__u32)), &qeth_version,
+	       sizeof (__u32));
+	memcpy(((char *) buffer_pointer) + (3 * sizeof (__u32)),
+	       &number_of_devices, sizeof (__u32));
+	copy_to_user((char *) arg, buffer, data_len);
+	vfree(buffer);
+out:
+	read_unlock(&list_lock);
+	return result;
+
+#undef PARMS_BUFFERLENGTH
+
+};
+
+static int
+qeth_procfile_interfacechanges(unsigned long arg)
+{
+	return qeth_sleepon_procfile();
+
+}
+
+static int
+qeth_procfile_ioctl(struct inode *inode, struct file *file,
+		    unsigned int cmd, unsigned long arg)
+{
+
+	int result;
+	down_interruptible(&qeth_procfile_ioctl_lock);
+	switch (cmd) {
+
+	case QETH_IOCPROC_OSAEINTERFACES:
+		result = qeth_procfile_getinterfaces(arg);
+		break;
+	case QETH_IOCPROC_INTERFACECHANGES:
+		result = qeth_procfile_interfacechanges(arg);
+		break;
+	default:
+		result = -EOPNOTSUPP;
+	}
+	up(&qeth_procfile_ioctl_lock);
+	return result;
+};
+
+static struct file_operations qeth_procfile_fops = {
+	ioctl:qeth_procfile_ioctl,
+	read:qeth_procfile_read,
+	open:qeth_procfile_open,
+	release:qeth_procfile_release,
+};
+
+static struct proc_dir_entry *qeth_proc_file;
+
+static struct file_operations qeth_ipato_procfile_fops = {
+	read:qeth_procfile_read,	/* same as above! */
+	write:qeth_ipato_procfile_write,
+	open:qeth_ipato_procfile_open,
+	release:qeth_procfile_release	/* same as above! */
+};
+
+static struct proc_dir_entry *qeth_ipato_proc_file;
+
+static inline void
+__qeth_add_procfs_perf(void)
+{
+#ifdef QETH_PERFORMANCE_STATS
+	proc_perf_file_registration = 0;
+	qeth_perf_proc_file = create_proc_entry(QETH_PERF_PROCFILE_NAME,
+						S_IFREG | 0444, &proc_root);
+	if (qeth_perf_proc_file) {
+		qeth_perf_proc_file->read_proc = &qeth_perf_procfile_read;
+	} else
+		proc_perf_file_registration = -1;
+
+	if (proc_perf_file_registration)
+		PRINT_WARN("was not able to register perf. proc-file (%i).\n",
+			   proc_perf_file_registration);
+#endif /* QETH_PERFORMANCE_STATS */
+}
+
+static void
+qeth_add_procfs_entries(void)
+{
+	proc_file_registration = 0;
+	qeth_proc_file = create_proc_entry(QETH_PROCFILE_NAME,
+					   S_IFREG | 0444, &proc_root);
+	if (qeth_proc_file) {
+		qeth_proc_file->proc_fops = &qeth_procfile_fops;
+		sema_init(&qeth_procfile_ioctl_sem,
+			  PROCFILE_SLEEP_SEM_MAX_VALUE);
+		sema_init(&qeth_procfile_ioctl_lock,
+			  PROCFILE_IOCTL_SEM_MAX_VALUE);
+	} else
+		proc_file_registration = -1;
+
+	if (proc_file_registration)
+		PRINT_WARN("was not able to register proc-file (%i).\n",
+			   proc_file_registration);
+	proc_ipato_file_registration = 0;
+	qeth_ipato_proc_file = create_proc_entry(QETH_IPA_PROCFILE_NAME,
+						 S_IFREG | 0644, &proc_root);
+	if (qeth_ipato_proc_file) {
+		qeth_ipato_proc_file->proc_fops = &qeth_ipato_procfile_fops;
+	} else
+		proc_ipato_file_registration = -1;
+
+	if (proc_ipato_file_registration)
+		PRINT_WARN("was not able to register ipato-proc-file (%i).\n",
+			   proc_ipato_file_registration);
+	__qeth_add_procfs_perf();
+}
+
+static void __exit
+qeth_remove_procfs_entries(void)
+{
+	if (!proc_file_registration)	/* means if it went ok earlier */
+		remove_proc_entry(QETH_PROCFILE_NAME, &proc_root);
+
+	if (!proc_ipato_file_registration)	/* means if it went ok earlier */
+		remove_proc_entry(QETH_IPA_PROCFILE_NAME, &proc_root);
+
+#ifdef QETH_PERFORMANCE_STATS
+	if (!proc_perf_file_registration)	/* means if it went ok earlier */
+		remove_proc_entry(QETH_PERF_PROCFILE_NAME, &proc_root);
+#endif /* QETH_PERFORMANCE_STATS */
+}
+
+static int
+qeth_register_dbf_views(void)
+{
+	qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME,
+					QETH_DBF_SETUP_INDEX,
+					QETH_DBF_SETUP_NR_AREAS,
+					QETH_DBF_SETUP_LEN);
+	if (!qeth_dbf_setup)
+		return -ENOMEM;
+
+	debug_register_view(qeth_dbf_setup, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_setup, QETH_DBF_SETUP_LEVEL);
+
+	qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME,
+				       QETH_DBF_MISC_INDEX,
+				       QETH_DBF_MISC_NR_AREAS,
+				       QETH_DBF_MISC_LEN);
+	if (!qeth_dbf_misc)
+		return -ENOMEM;
+
+	debug_register_view(qeth_dbf_misc, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_misc, QETH_DBF_MISC_LEVEL);
+
+	qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME,
+				       QETH_DBF_DATA_INDEX,
+				       QETH_DBF_DATA_NR_AREAS,
+				       QETH_DBF_DATA_LEN);
+	if (!qeth_dbf_data)
+		return -ENOMEM;
+
+	debug_register_view(qeth_dbf_data, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_data, QETH_DBF_DATA_LEVEL);
+
+	qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME,
+					  QETH_DBF_CONTROL_INDEX,
+					  QETH_DBF_CONTROL_NR_AREAS,
+					  QETH_DBF_CONTROL_LEN);
+	if (!qeth_dbf_control)
+		return -ENOMEM;
+
+	debug_register_view(qeth_dbf_control, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_control, QETH_DBF_CONTROL_LEVEL);
+
+	qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME,
+					QETH_DBF_SENSE_INDEX,
+					QETH_DBF_SENSE_NR_AREAS,
+					QETH_DBF_SENSE_LEN);
+	if (!qeth_dbf_sense)
+		return -ENOMEM;
+
+	debug_register_view(qeth_dbf_sense, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_sense, QETH_DBF_SENSE_LEVEL);
+
+	qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME,
+				       QETH_DBF_QERR_INDEX,
+				       QETH_DBF_QERR_NR_AREAS,
+				       QETH_DBF_QERR_LEN);
+	if (!qeth_dbf_qerr)
+		return -ENOMEM;
+
+	debug_register_view(qeth_dbf_qerr, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_qerr, QETH_DBF_QERR_LEVEL);
+
+	qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME,
+					QETH_DBF_TRACE_INDEX,
+					QETH_DBF_TRACE_NR_AREAS,
+					QETH_DBF_TRACE_LEN);
+	if (!qeth_dbf_trace)
+		return -ENOMEM;
+
+	debug_register_view(qeth_dbf_trace, &debug_hex_ascii_view);
+	debug_set_level(qeth_dbf_trace, QETH_DBF_TRACE_LEVEL);
+
+	return 0;
+}
+
+static void
+qeth_unregister_dbf_views(void)
+{
+	if (qeth_dbf_setup)
+		debug_unregister(qeth_dbf_setup);
+	if (qeth_dbf_qerr)
+		debug_unregister(qeth_dbf_qerr);
+	if (qeth_dbf_sense)
+		debug_unregister(qeth_dbf_sense);
+	if (qeth_dbf_misc)
+		debug_unregister(qeth_dbf_misc);
+	if (qeth_dbf_data)
+		debug_unregister(qeth_dbf_data);
+	if (qeth_dbf_control)
+		debug_unregister(qeth_dbf_control);
+	if (qeth_dbf_trace)
+		debug_unregister(qeth_dbf_trace);
+}
+
+#ifdef QETH_IPV6
+static int
+qeth_ipv6_init(void)
+{
+	qeth_old_arp_constructor = arp_tbl.constructor;
+	write_lock(&arp_tbl.lock);
+	arp_tbl.constructor = qeth_arp_constructor;
+	write_unlock(&arp_tbl.lock);
+
+ 	/* generate the memory leak here - FIXME*/
+ 	arp_direct_ops = (struct neigh_ops*)
+ 		kmalloc(sizeof(struct neigh_ops), GFP_KERNEL);
+ 	if (!arp_direct_ops)
+ 		return -ENOMEM;
+
+ 	memcpy(arp_direct_ops, &arp_direct_ops_template,
+ 	       sizeof(struct neigh_ops));
+ 	return 0;
+
+}
+
+static void
+qeth_ipv6_uninit(void)
+{
+	write_lock(&arp_tbl.lock);
+	arp_tbl.constructor = qeth_old_arp_constructor;
+	write_unlock(&arp_tbl.lock);
+}
+#endif /* QETH_IPV6 */
+
+static int
+qeth_get_internal_functions(void)
+{
+	struct net_device *dev;
+
+	dev = (struct net_device *) kmalloc(sizeof (struct net_device),
+					    GFP_KERNEL);
+	if (!dev) {
+		PRINT_ERR("Not enough memory for internal functions.\n");
+		return -ENOMEM;
+	}
+#ifdef CONFIG_NET_ETHERNET
+	ether_setup(dev);
+	qeth_my_eth_header = dev->hard_header;
+	qeth_my_eth_rebuild_header = dev->rebuild_header;
+	qeth_my_eth_header_cache = dev->hard_header_cache;
+	qeth_my_eth_header_cache_update = dev->header_cache_update;
+#endif
+#ifdef CONFIG_TR
+	tr_setup(dev);
+	qeth_my_tr_header = dev->hard_header;
+	qeth_my_tr_rebuild_header = dev->rebuild_header;
+#endif
+
+	kfree(dev);
+
+	return 0;
+}
+
+static struct ccw_device_id qeth_ids[] = {
+      {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
+      {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
+	{},
+};
+
+MODULE_DEVICE_TABLE(ccw, qeth_ids);
+
+static struct ccw_driver qeth_ccw_driver = {
+	.name = "qeth",
+	.ids = qeth_ids,
+	.probe = ccwgroup_probe_ccwdev,
+	.remove = ccwgroup_remove_ccwdev,
+};
+
+static struct device qeth_root_dev = {
+	.name = "QETH Devices",
+	.bus_id = "qeth",
+};
+
+static struct ccwgroup_driver qeth_ccwgroup_driver;
+static ssize_t
+qeth_group_store(struct device_driver *drv, const char *buf, size_t count)
+{
+	const char *start, *end;
+	char bus_ids[3][BUS_ID_SIZE], *argv[3];
+	int i;
+
+	pr_debug("group_store %s\n", buf);
+	start = buf;
+	for (i = 0; i < 3; i++) {
+		static const char delim[] = { ',', ',', '\n' };
+		int len;
+
+		if (!(end = strchr(start, delim[i])))
+			return count;
+		len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
+		strncpy(bus_ids[i], start, len);
+		bus_ids[i][len] = '\0';
+		start = end + 1;
+		argv[i] = bus_ids[i];
+	}
+	pr_debug("creating qeth group device from '%s', '%s' and '%s'\n",
+		 bus_ids[0], bus_ids[1], bus_ids[2]);
+	ccwgroup_create(&qeth_root_dev, qeth_ccwgroup_driver.driver_id,
+			&qeth_ccw_driver, 3, argv);
+	return count;
+}
+
+static DRIVER_ATTR(group, 0200, 0, qeth_group_store);
+
+static ssize_t
+qeth_bufcnt_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->options.inbound_buffer_count);
+}
+
+static ssize_t
+qeth_bufcnt_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	unsigned long cnt;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_softsetup))
+		return -EPERM;
+
+	cnt = simple_strtoul(buf, &tmp, 16);
+	cnt = (cnt < BUFCNT_MIN) ? BUFCNT_MIN :
+		((cnt > BUFCNT_MAX) ? BUFCNT_MAX : cnt);
+	card->options.inbound_buffer_count = cnt;
+
+	return count;
+}
+
+static DEVICE_ATTR(bufcnt, 0644, qeth_bufcnt_show, qeth_bufcnt_store);
+
+static ssize_t
+qeth_portname_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+	char tmp[9];
+	int i;
+
+	if (!card)
+		return -EINVAL;
+
+	if (card->portname_required) {
+		sprintf(tmp, "%s", card->options.portname + 1);
+		for (i = 0; i < 8; i++)
+			tmp[i] = (char) _ebcasc[(__u8) tmp[i]];
+		tmp[8] = 0;
+		return sprintf(buf, "%s\n", tmp);
+	} else
+		return sprintf(buf, "%s\n", "no portname required");
+}
+
+static ssize_t
+qeth_portname_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	char *tmp;
+	int i;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	/* Remove trailing '\n'. */
+	tmp = strsep((char **) &buf, "\n");
+	if ((strlen(tmp) > 8) || (strlen(tmp) < 2))
+		return -EINVAL;
+
+	card->options.portname[0] = strlen(tmp);
+	/* for beauty reasons: */
+	for (i = 1; i < 9; i++)
+		card->options.portname[i] = ' ';
+	strcpy(card->options.portname + 1, tmp);
+	for (i = 1; i < 9; i++)
+		card->options.portname[i] =
+			_ascebc[(unsigned char)card->options.portname[i]];
+
+	return count;
+}
+
+static DEVICE_ATTR(portname, 0644, qeth_portname_show, qeth_portname_store);
+
+static ssize_t
+qeth_route4_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	if (atomic_read(&card->rt4fld))
+		return sprintf(buf, "%s\n", "no");
+
+	switch (card->options.routing_type4 & ROUTER_MASK) {
+	case PRIMARY_ROUTER:
+		return sprintf(buf, "%s\n", "primary router");
+	case SECONDARY_ROUTER:
+		return sprintf(buf, "%s\n", "secondary router");
+	case MULTICAST_ROUTER:
+		return sprintf(buf, "%s\n", "multicast router");
+	case PRIMARY_CONNECTOR:
+		return sprintf(buf, "%s\n", "primary connector");
+	case SECONDARY_CONNECTOR:
+		return sprintf(buf, "%s\n", "secondary connector");
+	default:
+		return sprintf(buf, "%s\n", "no");
+	}
+}
+
+static ssize_t
+qeth_route4_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	int cnt;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	/* Remove trailing '\n'. */
+	tmp = strsep((char **) &buf, "\n");
+	cnt = strlen(tmp);
+	if (!strncmp(tmp, "primary_router", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "pri4");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		card->options.routing_type4 =
+			PRIMARY_ROUTER | RESET_ROUTING_FLAG;
+	} else if (!strncmp(tmp, "secondary_router", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "sec4");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		card->options.routing_type4 =
+			SECONDARY_ROUTER | RESET_ROUTING_FLAG;
+	}  else if (!strncmp(tmp, "multicast_router", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "mcr4");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+		card->options.routing_type4 =
+			MULTICAST_ROUTER | RESET_ROUTING_FLAG;
+	} else if (!strncmp(tmp, "primary_connector", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "prc4");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+		card->options.routing_type4 =
+			PRIMARY_CONNECTOR | RESET_ROUTING_FLAG;
+	} else if (!strncmp(tmp, "secondary_connector", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "scc4");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+		card->options.routing_type4 =
+			SECONDARY_CONNECTOR | RESET_ROUTING_FLAG;
+	} else if (!strncmp(tmp, "no_router", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "nor4");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		
+		card->options.routing_type4 = NO_ROUTER | RESET_ROUTING_FLAG;
+	} else {
+		PRINT_WARN("unknown command input in route4 attribute\n");
+		return -EINVAL;
+	}
+	__qeth_correct_routing_status_v4(card);
+	atomic_set(&card->enable_routing_attempts4, QETH_ROUTING_ATTEMPTS);
+	if (atomic_read(&card->is_softsetup))
+		qeth_start_softsetup_thread(card);
+	return count;
+}
+
+static DEVICE_ATTR(route4, 0644, qeth_route4_show, qeth_route4_store);
+
+static ssize_t
+qeth_route6_show(struct device *dev, char *buf)
+{
+#ifdef QETH_IPV6
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	if (atomic_read(&card->rt6fld))
+		return sprintf(buf, "%s\n", "no");
+
+	switch (card->options.routing_type6 & ROUTER_MASK) {
+	case PRIMARY_ROUTER:
+		return sprintf(buf, "%s\n", "primary router");
+	case SECONDARY_ROUTER:
+		return sprintf(buf, "%s\n", "secondary router");
+	case MULTICAST_ROUTER:
+		return sprintf(buf, "%s\n", "multicast router");
+	case PRIMARY_CONNECTOR:
+		return sprintf(buf, "%s\n", "primary connector");
+	case SECONDARY_CONNECTOR:
+		return sprintf(buf, "%s\n", "secondary connector");
+	default:
+		return sprintf(buf, "%s\n", "no");
+	}
+#endif /* QETH_IPV6 */
+	return sprintf(buf, "%s\n", "n/a");
+}
+
+static ssize_t
+qeth_route6_store(struct device *dev, const char *buf, size_t count)
+{
+#ifdef QETH_IPV6
+	struct qeth_card *card = dev->driver_data;
+	int cnt;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	/* Remove trailing '\n'. */
+	tmp = strsep((char **) &buf, "\n");
+	cnt = strlen(tmp);
+	if (!strncmp(tmp, "primary_router", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "pri6");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		card->options.routing_type6 =
+			PRIMARY_ROUTER | RESET_ROUTING_FLAG;
+	} else if (!strncmp(tmp, "secondary_router", cnt)) {
+				QETH_DBF_TEXT2(0, trace, "sec6");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		card->options.routing_type6 =
+			SECONDARY_ROUTER | RESET_ROUTING_FLAG;
+	}  else if (!strncmp(tmp, "multicast_router", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "mcr6");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+		card->options.routing_type6 =
+			MULTICAST_ROUTER | RESET_ROUTING_FLAG;
+	} else if (!strncmp(tmp, "primary_connector", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "prc6");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+		card->options.routing_type6 =
+			PRIMARY_CONNECTOR | RESET_ROUTING_FLAG;
+	} else if (!strncmp(tmp, "secondary_connector", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "scc6");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+
+		card->options.routing_type6 =
+			SECONDARY_CONNECTOR | RESET_ROUTING_FLAG;
+	} else if (!strncmp(tmp, "no_router", cnt)) {
+		QETH_DBF_TEXT2(0, trace, "nor6");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		
+		card->options.routing_type6 = NO_ROUTER | RESET_ROUTING_FLAG;
+	} else {
+		PRINT_WARN("unknown command input in route6 attribute\n");
+		return -EINVAL;
+	}
+	__qeth_correct_routing_status_v6(card);
+	atomic_set(&card->enable_routing_attempts6, QETH_ROUTING_ATTEMPTS);
+	if (atomic_read(&card->is_softsetup))
+		qeth_start_softsetup_thread(card);
+	return count;
+#endif /* QETH_IPV6 */
+	return -EINVAL;
+}
+
+static DEVICE_ATTR(route6, 0644, qeth_route6_show, qeth_route6_store);
+
+
+static ssize_t
+qeth_checksum_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	switch (card->options.checksum_type) {
+	case SW_CHECKSUMMING:
+		return sprintf(buf, "%s\n", "sw");
+	case HW_CHECKSUMMING:
+		return sprintf(buf, "%s\n", "hw");
+	default:
+		return sprintf(buf, "%s\n", "no");
+	}
+}
+
+static ssize_t
+qeth_checksum_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	char *tmp;
+	int cnt;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	/* Remove trailing '\n'. */
+	tmp = strsep((char **) &buf, "\n");
+	cnt = strlen(tmp);
+	if (!strncmp(tmp, "sw_checksumming", cnt))
+		card->options.checksum_type = SW_CHECKSUMMING;
+	else if (!strncmp(tmp, "hw_checksumming", cnt))
+		card->options.checksum_type = HW_CHECKSUMMING;
+	else if (!strncmp(tmp, "no_checksumming", cnt))
+		card->options.checksum_type = NO_CHECKSUMMING;
+	else
+		PRINT_WARN("unknown checksumming type '%s'\n", tmp);
+
+	return count;
+}
+
+static DEVICE_ATTR(checksumming, 0644, qeth_checksum_show, qeth_checksum_store);
+
+static ssize_t
+qeth_prioq_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	switch (card->options.do_prio_queueing) {
+	case PRIO_QUEUEING_PREC:
+		return sprintf(buf, "%s\n", "by precedence");
+	case PRIO_QUEUEING_TOS:
+		return sprintf(buf, "%s\n", "by type of service");
+	default:
+		return sprintf(buf, "always queue %i\n",
+			       card->options.default_queue);
+	}
+}
+
+static ssize_t
+qeth_prioq_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	char *tmp;
+	int cnt;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	/* Remove trailing '\n'. */
+	tmp = strsep((char **) &buf, "\n");
+	cnt = strlen(tmp);
+	if (!strncmp(tmp, "prio_queueing_prec", cnt))
+		card->options.do_prio_queueing = PRIO_QUEUEING_PREC;
+	else if (!strncmp(tmp, "prio_queueing_tos", cnt))
+		card->options.do_prio_queueing = PRIO_QUEUEING_TOS;
+	else if (!strncmp(tmp, "no_prio_queueing:0", cnt)) {
+		card->options.do_prio_queueing = NO_PRIO_QUEUEING;
+		card->options.default_queue = 0;
+	} else if (!strncmp(tmp, "no_prio_queueing:1", cnt)) {
+		card->options.do_prio_queueing = NO_PRIO_QUEUEING;
+		card->options.default_queue = 1;
+	} else if (!strncmp(tmp, "no_prio_queueing:2", cnt)) {
+		card->options.do_prio_queueing = NO_PRIO_QUEUEING;
+		card->options.default_queue = 2;
+	} else if (!strncmp(tmp, "no_prio_queueing:3", cnt)) {
+		card->options.do_prio_queueing = NO_PRIO_QUEUEING;
+		card->options.default_queue = 3;
+	} else if (!strncmp(tmp, "no_prio_queueing", cnt)) {
+		card->options.do_prio_queueing = NO_PRIO_QUEUEING;
+		card->options.default_queue = QETH_DEFAULT_QUEUE;
+	} else
+		PRINT_WARN("unknown queueing type '%s'\n", tmp);
+
+	return count;
+}
+
+static DEVICE_ATTR(priority_queueing, 0644, qeth_prioq_show, qeth_prioq_store);
+
+static ssize_t
+qeth_portno_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->options.portno);
+}
+
+static ssize_t
+qeth_portno_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	char *tmp;
+	int i;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if ((i < 0) || (i > MAX_PORTNO)) {
+		PRINT_ERR("portno %i out of range\n", i);
+		return -EINVAL;
+	}
+	card->options.portno = i;
+
+	return count;
+}
+
+static DEVICE_ATTR(portno, 0644, qeth_portno_show, qeth_portno_store);
+
+static ssize_t
+qeth_contig_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s\n",
+		       (card->options.memusage == MEMUSAGE_CONTIG)?"yes":"no");
+}
+
+static ssize_t
+qeth_contig_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	int i;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i == 0)
+		card->options.memusage = MEMUSAGE_DISCONTIG;
+	else if (i == 1)
+		card->options.memusage = MEMUSAGE_CONTIG;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(contig, 0644, qeth_contig_show, qeth_contig_store);
+
+static ssize_t
+qeth_polltime_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->options.polltime);
+}
+
+static ssize_t
+qeth_polltime_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	char *tmp;
+	int i;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i < 0) {
+		PRINT_ERR("polltime %i invalid\n", i);
+		return -EINVAL;
+	}
+	card->options.polltime = i;
+
+	return count;
+}
+
+static DEVICE_ATTR(polltime, 0644, qeth_polltime_show, qeth_polltime_store);
+
+static ssize_t
+qeth_hhlen_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%i\n", card->options.add_hhlen);
+}
+
+static ssize_t
+qeth_hhlen_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	char *tmp;
+	int i;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if ((i < 0) || (i > MAX_ADD_HHLEN)) {
+		PRINT_ERR("add_hhlen out of range\n");
+		return -EINVAL;
+	}
+	card->options.add_hhlen = i;
+
+	return count;
+}
+
+static DEVICE_ATTR(add_hhlen, 0644, qeth_hhlen_show, qeth_hhlen_store);
+
+static ssize_t
+qeth_takeover_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s\n",
+		       (card->options.ena_ipat == ENABLE_TAKEOVER)?"yes":"no");
+}
+
+static ssize_t
+qeth_takeover_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	int i;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i == 0)
+		card->options.ena_ipat = ENABLE_TAKEOVER;
+	else if (i == 1)
+		card->options.ena_ipat = DISABLE_TAKEOVER;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(enable_takeover, 0644, qeth_takeover_show, qeth_takeover_store);
+
+static ssize_t
+qeth_macaddr_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s\n",
+		       (card->options.macaddr_mode == MACADDR_CANONICAL)?"yes":"no");
+}
+
+static ssize_t
+qeth_macaddr_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	int i;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i == 0)
+		card->options.macaddr_mode = MACADDR_NONCANONICAL;
+	else if (i == 1)
+		card->options.macaddr_mode = MACADDR_CANONICAL;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(canonical_macaddr, 0644, qeth_macaddr_show, qeth_macaddr_store);
+
+static ssize_t
+qeth_fakebr_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s\n",
+		       (card->options.fake_broadcast == FAKE_BROADCAST)?"yes":"no");
+}
+
+static ssize_t
+qeth_fakebr_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	int i;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i == 0)
+		card->options.fake_broadcast = DONT_FAKE_BROADCAST;
+	else if (i == 1)
+		card->options.fake_broadcast = FAKE_BROADCAST;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(fake_broadcast, 0644, qeth_fakebr_show, qeth_fakebr_store);
+
+static ssize_t
+qeth_fakell_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s\n",
+		       (card->options.fake_ll == FAKE_LL)?"yes":"no");
+}
+
+static ssize_t
+qeth_fakell_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	int i;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i == 0)
+		card->options.fake_ll = DONT_FAKE_LL;
+	else if (i == 1)
+		card->options.fake_ll = FAKE_LL;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(fake_ll, 0644, qeth_fakell_show, qeth_fakell_store);
+
+static ssize_t
+qeth_hsi_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s\n",
+		       (card->options.async_iqd == ASYNC_IQD)?"async":"sync");
+}
+
+static ssize_t
+qeth_hsi_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	int i;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i == 0)
+		card->options.async_iqd = SYNC_IQD;
+	else if (i == 1)
+		card->options.async_iqd = ASYNC_IQD;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(async_hsi, 0644, qeth_hsi_show, qeth_hsi_store);
+
+static ssize_t
+qeth_broadcast_show(struct device *dev, char *buf)
+{
+	struct qeth_card *card = dev->driver_data;
+
+	if (!card)
+		return -EINVAL;
+
+	return sprintf(buf, "%s\n",
+		       (card->options.broadcast_mode == BROADCAST_ALLRINGS)
+		       ?"allrings":"local");
+}
+
+static ssize_t
+qeth_broadcast_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	char *tmp;
+	int cnt;
+
+	if (!card)
+		return count;
+
+	if (atomic_read(&card->is_hardsetup))
+		return -EPERM;
+
+	/* Remove trailing '\n'. */
+	tmp = strsep((char **) &buf, "\n");
+	cnt = strlen(tmp);
+	if (!strncmp(tmp, "broadcast_allrings", cnt))
+		card->options.broadcast_mode = BROADCAST_ALLRINGS;
+	else if (!strncmp(tmp, "broadcast_local", cnt))
+		card->options.broadcast_mode = BROADCAST_LOCAL;
+	else
+		PRINT_WARN("unknown broadcast type '%s'\n", tmp);
+
+	return count;
+}
+
+static DEVICE_ATTR(broadcast_mode, 0644, qeth_broadcast_show, qeth_broadcast_store);
+
+static ssize_t
+qeth_recover_store(struct device *dev, const char *buf, size_t count)
+{
+	struct qeth_card *card = dev->driver_data;
+	int i;
+	char *tmp;
+
+	if (!card)
+		return count;
+
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i == 1) {
+		QETH_DBF_TEXT2(0, trace, "UTRC");
+		QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id);
+		atomic_set(&card->problem, PROBLEM_USER_TRIGGERED_RECOVERY);
+		qeth_schedule_recovery(card);
+		return count;
+	} else
+		return -EINVAL;
+}
+
+static DEVICE_ATTR(recover, 0200, 0, qeth_recover_store);
+
+static inline int
+__qeth_create_attributes(struct device *dev)
+{
+	int ret;
+
+	ret = device_create_file(dev, &dev_attr_bufcnt);
+	if (ret != 0)
+		goto out_nobufcnt;
+
+	ret = device_create_file(dev, &dev_attr_portname);
+	if (ret != 0)
+		goto out_noportname;
+
+	ret = device_create_file(dev, &dev_attr_route4);
+	if (ret != 0)
+		goto out_noroute4;
+
+	ret = device_create_file(dev, &dev_attr_route6);
+	if (ret != 0)
+		goto out_noroute6;
+
+	ret = device_create_file(dev, &dev_attr_checksumming);
+	if (ret != 0)
+		goto out_nochecksum;
+
+	ret = device_create_file(dev, &dev_attr_priority_queueing);
+	if (ret != 0)
+		goto out_noprioq;
+
+	ret = device_create_file(dev, &dev_attr_portno);
+	if (ret != 0)
+		goto out_noportno;
+
+	ret = device_create_file(dev, &dev_attr_contig);
+	if (ret != 0)
+		goto out_nocontig;
+
+	ret = device_create_file(dev, &dev_attr_polltime);
+	if (ret != 0)
+		goto out_nopolltime;
+
+	ret = device_create_file(dev, &dev_attr_add_hhlen);
+	if (ret != 0)
+		goto out_nohhlen;
+
+	ret = device_create_file(dev, &dev_attr_enable_takeover);
+	if (ret != 0)
+		goto out_noipat;
+
+	ret = device_create_file(dev, &dev_attr_canonical_macaddr);
+	if (ret != 0)
+		goto out_nomac;
+	
+	ret = device_create_file(dev, &dev_attr_fake_broadcast);
+	if (ret != 0)
+		goto out_nofakebr;
+
+	ret = device_create_file(dev, &dev_attr_fake_ll);
+	if (ret != 0)
+		goto out_nofakell;
+
+	ret = device_create_file(dev, &dev_attr_async_hsi);
+	if (ret != 0)
+		goto out_nohsi;
+
+	ret = device_create_file(dev, &dev_attr_broadcast_mode);
+	if (ret != 0)
+		goto out_nobrmode;
+
+	ret = device_create_file(dev, &dev_attr_recover);
+	if (ret != 0)
+		goto out_norecover;
+
+	return 0;
+
+out_norecover:
+	device_remove_file(dev, &dev_attr_broadcast_mode);
+out_nobrmode:
+	device_remove_file(dev, &dev_attr_async_hsi);
+out_nohsi:
+	device_remove_file(dev, &dev_attr_fake_ll);
+out_nofakell:
+	device_remove_file(dev, &dev_attr_fake_broadcast);
+out_nofakebr:
+	device_remove_file(dev, &dev_attr_canonical_macaddr);
+out_nomac:
+	device_remove_file(dev, &dev_attr_enable_takeover);
+out_noipat:
+	device_remove_file(dev, &dev_attr_add_hhlen);
+out_nohhlen:
+	device_remove_file(dev, &dev_attr_polltime);
+out_nopolltime:
+	device_remove_file(dev, &dev_attr_contig);
+out_nocontig:
+	device_remove_file(dev, &dev_attr_portno);
+out_noportno:
+	device_remove_file(dev, &dev_attr_priority_queueing);
+out_noprioq:
+	device_remove_file(dev, &dev_attr_checksumming);
+out_nochecksum:
+	device_remove_file(dev, &dev_attr_route6);
+out_noroute6:
+	device_remove_file(dev, &dev_attr_route4);
+out_noroute4:
+	device_remove_file(dev, &dev_attr_portname);
+out_noportname:
+	device_remove_file(dev, &dev_attr_bufcnt);
+out_nobufcnt:
+	return ret;
+}
+
+static int
+qeth_probe_device(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card;
+	int ret;
+
+	if (!get_device(&gdev->dev))
+		return -ENODEV;
+
+	card = qeth_alloc_card();
+	if (!card) {
+		put_device(&gdev->dev);
+		return -ENOMEM;
+	}
+
+	gdev->dev.driver_data = card;
+
+	card->rdev = gdev->cdev[0];
+	gdev->cdev[0]->handler = qeth_interrupt_handler_read;
+	gdev->cdev[0]->dev.driver_data = card;
+
+	card->wdev = gdev->cdev[1];
+	gdev->cdev[1]->handler = qeth_interrupt_handler_write;
+	gdev->cdev[1]->dev.driver_data = card;
+
+	card->ddev = gdev->cdev[2];
+	gdev->cdev[2]->handler = qeth_interrupt_handler_qdio;
+	gdev->cdev[2]->dev.driver_data = card;
+
+	ret = __qeth_create_attributes(&gdev->dev);
+	if (ret != 0)
+		goto out;
+
+	snprintf(gdev->dev.name, DEVICE_NAME_SIZE, "qeth device");
+	return 0;
+out:
+	put_device(&gdev->dev);
+	qeth_free_card(card);
+	return ret;
+}
+
+/* 
+ * Replaces qeth_probe and qeth_attach_handler. 
+ * This is called after piping to the 'online' attribute,
+ * when all parameters are ready.
+ */
+static int
+qeth_activate(struct qeth_card *card)
+{
+	int result;
+
+	PRINT_STUPID("%s: got devices %s, %s, %s\n",
+		     __func__,
+		     rdev->dev.bus_id, wdev->dev.bus_id, ddev->dev.bus_id);
+
+	ccw_device_set_online(card->rdev);
+	ccw_device_set_online(card->wdev);
+	ccw_device_set_online(card->ddev);
+
+	QETH_DBF_TEXT1(0, setup, "activ");
+	QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id);
+	QETH_DBF_HEX1(0, setup, &card, sizeof (void *));
+	QETH_DBF_HEX1(0, setup, &card->dev, sizeof (void *));
+	QETH_DBF_HEX1(0, setup, &card->stats, sizeof (void *));
+
+	QETH_DBF_HEX2(0, misc, &card->options, QETH_DBF_MISC_LEN);
+
+	if (qeth_determine_card_type(card)) {
+		PRINT_WARN("%s: not a valid card type\n", __func__);
+		goto out;
+	}
+
+	qeth_insert_card_into_list(card);
+
+	qeth_correct_routing_status(card);
+
+	result = qeth_init_ringbuffers1(card);
+	if (result) {
+		PRINT_WARN("%s: could not init ringbuffers1\n", __func__);
+		goto out_remove;
+	}
+
+	result = qeth_hardsetup_card(card, 0);
+	if (result) {
+		goto out_remove;
+	}
+
+	result = qeth_init_ringbuffers2(card);
+	if (result) {
+		PRINT_WARN("%s: could not init ringbuffers2\n", __func__);
+		goto out_remove;
+	}
+
+	/* this was previously done in chandev_initnetdevice */
+	snprintf(card->dev->name, 8, "%s%%d",
+		 qeth_get_dev_basename(card->type, card->link_type));
+	qeth_init_netdev(card->dev);
+
+	return 0;		/* success */
+
+out_remove:
+	qeth_remove_card(card, QETH_REMOVE_CARD_QUICK);
+	qeth_remove_card_from_list(card);
+
+out:
+	QETH_DBF_TEXT4(0, trace, "freecard");
+
+	ccw_device_set_offline(card->ddev);
+	ccw_device_set_offline(card->wdev);
+	ccw_device_set_offline(card->rdev);
+
+	return -ENODEV;
+}
+
+static int
+qeth_remove_device(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = gdev->dev.driver_data;
+
+	gdev->dev.driver_data = NULL;
+	if (card)
+		kfree(card);
+	put_device(&gdev->dev);
+	return 0;
+}
+
+static int
+qeth_set_online(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = gdev->dev.driver_data;
+	int ret;
+
+	BUG_ON(!card);
+
+	ret = qeth_activate(card);
+	if (ret == 0)
+		snprintf(gdev->dev.name, DEVICE_NAME_SIZE, "%s",
+			 qeth_get_cardname_short(card->type, card->link_type,
+						 card->is_guest_lan));
+	return ret;
+}
+
+static int
+qeth_set_offline(struct ccwgroup_device *gdev)
+{
+	struct qeth_card *card = gdev->dev.driver_data;
+
+	if (!card)
+		return -ENODEV;
+
+	qeth_remove_card(card, QETH_REMOVE_CARD_PROPER);
+	qeth_remove_card_from_list(card);
+
+	QETH_DBF_TEXT4(0, trace, "freecard");
+
+	ccw_device_set_offline(card->ddev);
+	ccw_device_set_offline(card->wdev);
+	ccw_device_set_offline(card->rdev);
+
+	return 0;
+}
+
+static struct ccwgroup_driver qeth_ccwgroup_driver = {
+	.name = "qeth",
+	.driver_id = 0xD8C5E3C8,
+	.probe = qeth_probe_device,
+	.remove = qeth_remove_device,
+	.set_online = qeth_set_online,
+	.set_offline = qeth_set_offline,
+};
+
+static int __init
+qeth_init(void)
+{
+	int result;
+
+	qeth_eyecatcher();
+
+	printk(KERN_INFO "qeth: loading %s\n", version);
+
+	result = qeth_get_internal_functions();
+	if (result)
+		goto out;
+
+	qeth_alloc_spare_bufs();
+
+#ifdef QETH_IPV6
+	if (qeth_ipv6_init()) {
+		PRINT_ERR("Out of memory during ipv6 init.\n");
+		goto out_sparebufs;
+	}
+#endif /* QETH_IPV6 */
+
+	result = qeth_register_dbf_views();
+	if (result) {
+		PRINT_ERR("not enough memory for dbf. Will not load module.\n");
+		goto out_ipv6;
+	}
+
+	result = ccwgroup_driver_register(&qeth_ccwgroup_driver);
+	if (result)
+		goto out_dbf;
+
+	result = ccw_driver_register(&qeth_ccw_driver);
+	if (result)
+		goto out_gdrv;
+
+	result = driver_create_file(&qeth_ccwgroup_driver.driver,
+				    &driver_attr_group);
+	if (result)
+		goto out_cdrv;
+
+	result = device_register(&qeth_root_dev);
+	if (result)
+		goto out_file;
+
+	qeth_register_notifiers();
+	qeth_add_procfs_entries();
+
+	return 0;
+
+out_file:
+	driver_remove_file(&qeth_ccwgroup_driver.driver, &driver_attr_group);
+out_cdrv:
+	ccw_driver_unregister(&qeth_ccw_driver);
+out_gdrv:
+	ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
+out_dbf:
+	qeth_unregister_dbf_views();
+out_ipv6:
+#ifdef QETH_IPV6
+	qeth_ipv6_uninit();
+out_sparebufs:
+#endif /* QETH_IPV6 */
+	qeth_free_all_spare_bufs();
+out:
+	return result;
+}
+
+static void __exit
+qeth_exit(void)
+{
+#ifdef QETH_IPV6
+	qeth_ipv6_uninit();
+#endif /* QETH_IPV6 */
+	qeth_unregister_notifiers();
+
+	qeth_remove_procfs_entries();
+
+	QETH_DBF_TEXT1(0, trace, "cleanup.");
+
+	driver_remove_file(&qeth_ccwgroup_driver.driver, &driver_attr_group);
+	ccw_driver_unregister(&qeth_ccw_driver);
+	ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
+	device_unregister(&qeth_root_dev);
+
+	while (firstcard) {
+		struct qeth_card *card = firstcard;
+		qeth_remove_card(card, QETH_REMOVE_CARD_QUICK);
+		qeth_remove_card_from_list(card);
+		qeth_free_card(card);
+	}
+
+	qeth_free_all_spare_bufs();
+
+	qeth_unregister_dbf_views();
+
+	printk("qeth: %s: module removed\n", version);
+}
+
+EXPORT_SYMBOL(qeth_eyecatcher);
+
+module_init(qeth_init);
+module_exit(qeth_exit);
diff -urN linux-2.5.73-bk9/drivers/s390/net/qeth.h linux-2.5.73-bk10/drivers/s390/net/qeth.h
--- linux-2.5.73-bk9/drivers/s390/net/qeth.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/drivers/s390/net/qeth.h	2003-07-02 04:57:30.000000000 -0700
@@ -0,0 +1,1341 @@
+/*
+ * linux/drivers/s390/net/qeth.h
+ *
+ * Linux on zSeries OSA Express and HiperSockets support
+ *
+ * Copyright 2000,2003 IBM Corporation
+ * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
+ *
+ */
+#ifndef __QETH_H__
+#define __QETH_H__
+
+#include <asm/qdio.h>
+
+#define QETH_NAME " qeth"
+
+#define VERSION_QETH_H "$Revision: 1.47 $"
+
+/******************** CONFIG STUFF ***********************/
+//#define QETH_DBF_LIKE_HELL
+
+#ifdef CONFIG_QETH_IPV6
+#define QETH_IPV6
+#define QETH_VERSION_IPV6 ":IPv6"
+#else
+#define QETH_VERSION_IPV6 ""
+#endif	/* CONFIG_QETH_IPV6 */
+
+#ifdef CONFIG_QETH_VLAN
+#define QETH_VLAN
+#define QETH_VERSION_VLAN ":VLAN"
+#else
+#define QETH_VERSION_VLAN ""
+#endif	/* CONFIG_QETH_VLAN */
+
+/* these values match CHECKSUM_* in include/linux/skbuff.h */
+#define SW_CHECKSUMMING 0
+#define HW_CHECKSUMMING 1
+#define NO_CHECKSUMMING 2
+
+#define QETH_CHECKSUM_DEFAULT NO_CHECKSUMMING
+
+#define QETH_PRIOQ_DEFAULT NO_PRIO_QUEUEING
+#define QETH_DEFAULT_QUEUE 2
+
+/******************** CONFIG STUFF END ***********************/
+/********************* TUNING STUFF **************************/
+#define HIGH_WATERMARK_PACK		5
+#define LOW_WATERMARK_PACK		2
+#define WATERMARK_FUZZ			2
+
+#define QETH_MAX_INPUT_THRESHOLD 500
+#define QETH_MAX_OUTPUT_THRESHOLD 300	/* ? */
+
+/* only the MAX values are used */
+#define QETH_MIN_INPUT_THRESHOLD 1
+#define QETH_MIN_OUTPUT_THRESHOLD 1
+
+#define QETH_REQUEUE_THRESHOLD (card->options.inbound_buffer_count/4)
+
+#ifdef CONFIG_QETH_PERF_STATS
+#define QETH_PERFORMANCE_STATS
+#endif	/* CONFIG_QETH_PERF_STATS */
+
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_VERBOSE_LEVEL 8
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_VERBOSE_LEVEL 5
+#endif /* QETH_DBF_LIKE_HELL */
+
+#define PCI_THRESHOLD_A (card->options.inbound_buffer_count+1)	
+/* buffers we have to be behind before we get a PCI */
+#define PCI_THRESHOLD_B 0	/* enqueued free buffers left before we get a PCI */
+#define PCI_TIMER_VALUE 3	/* not used, unless the microcode gets patched */
+
+#define DEFAULT_SPARE_BUFFERS 0
+#define MAX_SPARE_BUFFERS 1024
+#define SPAREBUF_MASK 65536
+#define MAX_PORTNO 15
+
+#define QETH_PROCFILE_NAME "qeth"
+#define QETH_PERF_PROCFILE_NAME "qeth_perf"
+#define QETH_IPA_PROCFILE_NAME "qeth_ipa_takeover"
+
+#define SEND_RETRIES_ALLOWED 5
+#define QETH_ROUTING_ATTEMPTS 2
+
+#define QETH_HARDSETUP_LAPS 5
+#define QETH_HARDSETUP_CLEAR_LAPS 3
+#define QETH_RECOVERY_HARDSETUP_RETRY 2
+
+/************************* DEBUG FACILITY STUFF *********************/
+
+#define QETH_DBF_HEX(ex,name,level,addr,len) \
+        do { \
+        if (ex) \
+                debug_exception(qeth_dbf_##name,level,(void*)addr,len); \
+        else \
+                debug_event(qeth_dbf_##name,level,(void*)addr,len); \
+        } while (0)
+#define QETH_DBF_TEXT(ex,name,level,text) \
+        do { \
+        if (ex) \
+                debug_text_exception(qeth_dbf_##name,level,text); \
+        else \
+                debug_text_event(qeth_dbf_##name,level,text); \
+        } while (0)
+
+#define QETH_DBF_HEX0(ex,name,addr,len) QETH_DBF_HEX(ex,name,0,addr,len)
+#define QETH_DBF_HEX1(ex,name,addr,len) QETH_DBF_HEX(ex,name,1,addr,len)
+#define QETH_DBF_HEX2(ex,name,addr,len) QETH_DBF_HEX(ex,name,2,addr,len)
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_HEX3(ex,name,addr,len) QETH_DBF_HEX(ex,name,3,addr,len)
+#define QETH_DBF_HEX4(ex,name,addr,len) QETH_DBF_HEX(ex,name,4,addr,len)
+#define QETH_DBF_HEX5(ex,name,addr,len) QETH_DBF_HEX(ex,name,5,addr,len)
+#define QETH_DBF_HEX6(ex,name,addr,len) QETH_DBF_HEX(ex,name,6,addr,len)
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_HEX3(ex,name,addr,len) do {} while (0)
+#define QETH_DBF_HEX4(ex,name,addr,len) do {} while (0)
+#define QETH_DBF_HEX5(ex,name,addr,len) do {} while (0)
+#define QETH_DBF_HEX6(ex,name,addr,len) do {} while (0)
+#endif /* QETH_DBF_LIKE_HELL */
+
+#define QETH_DBF_TEXT0(ex,name,text) QETH_DBF_TEXT(ex,name,0,text)
+#define QETH_DBF_TEXT1(ex,name,text) QETH_DBF_TEXT(ex,name,1,text)
+#define QETH_DBF_TEXT2(ex,name,text) QETH_DBF_TEXT(ex,name,2,text)
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_TEXT3(ex,name,text) QETH_DBF_TEXT(ex,name,3,text)
+#define QETH_DBF_TEXT4(ex,name,text) QETH_DBF_TEXT(ex,name,4,text)
+#define QETH_DBF_TEXT5(ex,name,text) QETH_DBF_TEXT(ex,name,5,text)
+#define QETH_DBF_TEXT6(ex,name,text) QETH_DBF_TEXT(ex,name,6,text)
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_TEXT3(ex,name,text) do {} while (0)
+#define QETH_DBF_TEXT4(ex,name,text) do {} while (0)
+#define QETH_DBF_TEXT5(ex,name,text) do {} while (0)
+#define QETH_DBF_TEXT6(ex,name,text) do {} while (0)
+#endif /* QETH_DBF_LIKE_HELL */
+
+#define QETH_DBF_SETUP_NAME "qeth_setup"
+#define QETH_DBF_SETUP_LEN 8
+#define QETH_DBF_SETUP_INDEX 3
+#define QETH_DBF_SETUP_NR_AREAS 1
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_SETUP_LEVEL 6
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_SETUP_LEVEL 3
+#endif /* QETH_DBF_LIKE_HELL */
+
+#define QETH_DBF_MISC_NAME "qeth_misc"
+#define QETH_DBF_MISC_LEN 128
+#define QETH_DBF_MISC_INDEX 1
+#define QETH_DBF_MISC_NR_AREAS 1
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_MISC_LEVEL 6
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_MISC_LEVEL 2
+#endif /* QETH_DBF_LIKE_HELL */
+
+#define QETH_DBF_DATA_NAME "qeth_data"
+#define QETH_DBF_DATA_LEN 96
+#define QETH_DBF_DATA_INDEX 3
+#define QETH_DBF_DATA_NR_AREAS 1
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_DATA_LEVEL 6
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_DATA_LEVEL 2
+#endif /* QETH_DBF_LIKE_HELL */
+
+#define QETH_DBF_CONTROL_NAME "qeth_control"
+/* buffers are 255 bytes long, but no prob */
+#define QETH_DBF_CONTROL_LEN 256
+#define QETH_DBF_CONTROL_INDEX 3
+#define QETH_DBF_CONTROL_NR_AREAS 2
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_CONTROL_LEVEL 6
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_CONTROL_LEVEL 2
+#endif /* QETH_DBF_LIKE_HELL */
+
+#define QETH_DBF_TRACE_NAME "qeth_trace"
+#define QETH_DBF_TRACE_LEN 8
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_TRACE_INDEX 3
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_TRACE_INDEX 2
+#endif /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_TRACE_NR_AREAS 2
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_TRACE_LEVEL 6
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_TRACE_LEVEL 2
+#endif /* QETH_DBF_LIKE_HELL */
+
+#define QETH_DBF_SENSE_NAME "qeth_sense"
+#define QETH_DBF_SENSE_LEN 64
+#define QETH_DBF_SENSE_INDEX 1
+#define QETH_DBF_SENSE_NR_AREAS 1
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_SENSE_LEVEL 6
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_SENSE_LEVEL 2
+#endif /* QETH_DBF_LIKE_HELL */
+
+#define QETH_DBF_QERR_NAME "qeth_qerr"
+#define QETH_DBF_QERR_LEN 8
+#define QETH_DBF_QERR_INDEX 1
+#define QETH_DBF_QERR_NR_AREAS 2
+#ifdef QETH_DBF_LIKE_HELL
+#define QETH_DBF_QERR_LEVEL 6
+#else /* QETH_DBF_LIKE_HELL */
+#define QETH_DBF_QERR_LEVEL 2
+#endif /* QETH_DBF_LIKE_HELL */
+/****************** END OF DEBUG FACILITY STUFF *********************/
+
+/********************* CARD DATA STUFF **************************/
+
+#define QETH_MAX_PARAMS 150
+
+#define QETH_CARD_TYPE_UNKNOWN	0
+#define QETH_CARD_TYPE_OSAE	10
+#define QETH_CARD_TYPE_IQD	1234
+
+#define QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT 0x0101
+#define QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT 0x0101
+#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108
+#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108
+
+#define QETH_MAX_QUEUES 4
+
+#define UNIQUE_ID_IF_CREATE_ADDR_FAILED 0xfffe
+#define UNIQUE_ID_NOT_BY_CARD 0x10000
+
+/* 
+ * CU type & model, Dev type & model, card_type, odd_even_restriction,
+ * func level, no of queues, multicast is different (multicast-queue_no + 0x100)
+ */
+#define QETH_MODELLIST_ARRAY \
+	{{0x1731,0x01,0x1732,0x01,QETH_CARD_TYPE_OSAE,1, \
+	  QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+	  QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+	  QETH_MAX_QUEUES,0}, \
+	 {0x1731,0x05,0x1732,0x05,QETH_CARD_TYPE_IQD,0, \
+	  QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
+	  QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
+	  QETH_MAX_QUEUES,0x103}, \
+	 {0,0,0,0,0,0,0,0,0}}
+
+#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
+ /* only the first two bytes are looked at in qeth_get_cardname_short */
+#define QETH_MPC_LINK_TYPE_FAST_ETHERNET 0x01
+#define QETH_MPC_LINK_TYPE_HSTR 0x02
+#define QETH_MPC_LINK_TYPE_GIGABIT_ETHERNET 0x03
+#define QETH_MPC_LINK_TYPE_10GIGABIT_ETHERNET 0x10
+#define QETH_MPC_LINK_TYPE_LANE_ETH100 0x81
+#define QETH_MPC_LINK_TYPE_LANE_TR 0x82
+#define QETH_MPC_LINK_TYPE_LANE_ETH1000 0x83
+#define QETH_MPC_LINK_TYPE_LANE 0x88
+#define QETH_MPC_LINK_TYPE_ATM_NATIVE 0x90
+
+#define DEFAULT_ADD_HHLEN 0
+#define MAX_ADD_HHLEN 1024
+
+#define QETH_HEADER_SIZE	32
+#define QETH_IP_HEADER_SIZE	40
+#define QETH_HEADER_LEN_POS	8
+/* flags for the header: */
+#define QETH_HEADER_PASSTHRU	0x10
+#define QETH_HEADER_IPV6	0x80
+
+#define QETH_CAST_FLAGS		0x07
+#define QETH_CAST_UNICAST	6
+#define QETH_CAST_MULTICAST	4
+#define QETH_CAST_BROADCAST	5
+#define QETH_CAST_ANYCAST	7
+#define QETH_CAST_NOCAST	0
+
+/* VLAN defines */
+#define QETH_EXT_HEADER_VLAN_FRAME	  0x01
+#define QETH_EXT_HEADER_TOKEN_ID	  0x02
+#define QETH_EXT_HEADER_INCLUDE_VLAN_TAG  0x04
+
+#define QETH_EXT_HEADER_SRC_MAC_ADDRESS   0x08
+#define QETH_EXT_HEADER_CSUM_HDR_REQ      0x10
+#define QETH_EXT_HEADER_CSUM_TRANSP_REQ   0x20
+#define QETH_EXT_HEADER_CSUM_TRANSP_FRAME_TYPE   0x40
+
+#define QETH_UDP_CSUM_OFFSET	6
+#define QETH_TCP_CSUM_OFFSET	16
+
+#define QETH_VERIFY_IS_REAL_DEV               1
+#define QETH_VERIFY_IS_VLAN_DEV               2
+
+inline static unsigned int
+qeth_get_ipa_timeout(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_IQD:
+		return 2000;
+	default:
+		return 20000;
+	}
+}
+
+inline static unsigned short
+qeth_get_additional_dev_flags(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_IQD:
+		return IFF_NOARP;
+#ifdef QETH_IPV6
+	default:
+		return 0;
+#else /* QETH_IPV6 */
+	default:
+		return IFF_NOARP;
+#endif /* QETH_IPV6 */
+	}
+}
+
+inline static int
+qeth_get_hlen(__u8 link_type)
+{
+#ifdef QETH_IPV6
+	switch (link_type) {
+	case QETH_MPC_LINK_TYPE_HSTR:
+	case QETH_MPC_LINK_TYPE_LANE_TR:
+		return QETH_HEADER_SIZE + TR_HLEN;
+	default:
+#ifdef QETH_VLAN
+		return QETH_HEADER_SIZE + VLAN_ETH_HLEN;
+#else
+		return QETH_HEADER_SIZE + ETH_HLEN;
+#endif
+	}
+#else /* QETH_IPV6 */
+#ifdef QETH_VLAN
+	return QETH_HEADER_SIZE + VLAN_HLEN;
+#else
+	return QETH_HEADER_SIZE;
+#endif
+
+#endif /* QETH_IPV6 */
+}
+
+static int (*qeth_my_eth_header) (struct sk_buff *, struct net_device *,
+				  unsigned short, void *, void *, unsigned);
+#ifdef CONFIG_TR
+static int (*qeth_my_tr_header) (struct sk_buff *, struct net_device *,
+				 unsigned short, void *, void *, unsigned);
+#endif /* CONFIG_TR */
+static int (*qeth_my_eth_rebuild_header) (struct sk_buff *);
+#ifdef CONFIG_TR
+static int (*qeth_my_tr_rebuild_header) (struct sk_buff *);
+#endif /* CONFIG_TR */
+static int (*qeth_my_eth_header_cache) (struct neighbour *, struct hh_cache *);
+static void (*qeth_my_eth_header_cache_update) (struct hh_cache *,
+						struct net_device *,
+						unsigned char *);
+
+#ifdef QETH_IPV6
+typedef int (*__qeth_temp1) (struct sk_buff *, struct net_device *,
+			     unsigned short, void *, void *, unsigned);
+inline static __qeth_temp1
+qeth_get_hard_header(__u8 link_type)
+{
+	switch (link_type) {
+#ifdef CONFIG_TR
+	case QETH_MPC_LINK_TYPE_HSTR:
+	case QETH_MPC_LINK_TYPE_LANE_TR:
+		return qeth_my_tr_header;
+#endif /* CONFIG_TR */
+	default:
+		return qeth_my_eth_header;
+	}
+}
+
+typedef int (*__qeth_temp2) (struct sk_buff *);
+inline static __qeth_temp2
+qeth_get_rebuild_header(__u8 link_type)
+{
+	switch (link_type) {
+#ifdef CONFIG_TR
+	case QETH_MPC_LINK_TYPE_HSTR:
+	case QETH_MPC_LINK_TYPE_LANE_TR:
+		return qeth_my_tr_rebuild_header;
+#endif /* CONFIG_TR */
+	default:
+		return qeth_my_eth_rebuild_header;
+	}
+}
+
+typedef int (*__qeth_temp3) (struct neighbour *, struct hh_cache *);
+inline static __qeth_temp3
+qeth_get_hard_header_cache(__u8 link_type)
+{
+	switch (link_type) {
+	case QETH_MPC_LINK_TYPE_HSTR:
+	case QETH_MPC_LINK_TYPE_LANE_TR:
+		return NULL;
+	default:
+		return qeth_my_eth_header_cache;
+	}
+}
+
+typedef void (*__qeth_temp4) (struct hh_cache *, struct net_device *,
+			      unsigned char *);
+inline static __qeth_temp4
+qeth_get_header_cache_update(__u8 link_type)
+{
+	switch (link_type) {
+	case QETH_MPC_LINK_TYPE_HSTR:
+	case QETH_MPC_LINK_TYPE_LANE_TR:
+		return NULL;
+	default:
+		return qeth_my_eth_header_cache_update;
+	}
+}
+
+static unsigned short
+qeth_eth_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+	struct ethhdr *eth;
+
+	skb->mac.raw = skb->data;
+	skb_pull(skb, ETH_ALEN * 2 + sizeof (short));
+	eth = skb->mac.ethernet;
+
+	if (*eth->h_dest & 1) {
+		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+			skb->pkt_type = PACKET_BROADCAST;
+		else
+			skb->pkt_type = PACKET_MULTICAST;
+	} else {
+		skb->pkt_type = PACKET_OTHERHOST;
+	}
+	if (ntohs(eth->h_proto) >= 1536)
+		return eth->h_proto;
+	if (*(unsigned short *) (skb->data) == 0xFFFF)
+		return htons(ETH_P_802_3);
+	return htons(ETH_P_802_2);
+}
+
+typedef unsigned short (*__qeth_temp5) (struct sk_buff *, struct net_device *);
+inline static __qeth_temp5
+qeth_get_type_trans(__u8 link_type)
+{
+	switch (link_type) {
+#ifdef CONFIG_TR
+	case QETH_MPC_LINK_TYPE_HSTR:
+	case QETH_MPC_LINK_TYPE_LANE_TR:
+		return tr_type_trans;
+#endif
+	default:
+		return qeth_eth_type_trans;
+	}
+}
+#endif /* QETH_IPV6 */
+
+inline static const char *
+qeth_get_link_type_name(int cardtype, __u8 linktype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return "unknown";
+	case QETH_CARD_TYPE_OSAE:
+		switch (linktype) {
+		case QETH_MPC_LINK_TYPE_FAST_ETHERNET:
+			return "Fast Eth";
+		case QETH_MPC_LINK_TYPE_HSTR:
+			return "HSTR";
+		case QETH_MPC_LINK_TYPE_GIGABIT_ETHERNET:
+			return "Gigabit Eth";
+		case QETH_MPC_LINK_TYPE_LANE_ETH100:
+			return "LANE Eth100";
+		case QETH_MPC_LINK_TYPE_LANE_TR:
+			return "LANE TR";
+		case QETH_MPC_LINK_TYPE_LANE_ETH1000:
+			return "LANE Eth1000";
+		default:
+			return "unknown";
+		}
+	case QETH_CARD_TYPE_IQD:
+		return "magic";
+	default:
+		return "unknown";
+	}
+}
+
+inline static const char *
+qeth_get_dev_basename(int cardtype, __u8 link_type)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return "eth";
+	case QETH_CARD_TYPE_OSAE:
+		switch (link_type) {
+		case QETH_MPC_LINK_TYPE_LANE_TR:
+			/* fallthrough */
+		case QETH_MPC_LINK_TYPE_HSTR:
+			return "tr";
+		default:
+			return "eth";
+		}
+	case QETH_CARD_TYPE_IQD:
+		return "hsi";
+	default:
+		return "eth";
+	}
+}
+
+/* inbound: */
+#define DEFAULT_BUFFER_SIZE 65536
+#define DEFAULT_BUFFER_COUNT 128
+#define BUFCNT_MIN 8
+#define BUFCNT_MAX 128
+#define BUFFER_SIZE (card->inbound_buffer_size)
+#define BUFFER_MAX_ELEMENTS (BUFFER_SIZE>>12)
+	/* 8k for each pair header-buffer: */
+
+inline static int
+qeth_sbal_packing_on_card(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_IQD:
+		return 0;
+	default:
+		return 1;
+	}
+}
+
+/* 
+ * do it this way round -> __MODULE_STRING needs with
+ * QETH_PRIO_NICE_LEVELS a single number
+ */
+#define QETH_MAX_PRIO_QUEUES QETH_PRIO_NICE_LEVELS+1
+
+static inline int
+qeth_sbalf15_in_retrieable_range(int sbalf15)
+{
+	return ((sbalf15 >= 15) && (sbalf15 <= 31));
+}
+
+#define INBOUND_BUFFER_POS(card,bufno,sbale) \
+	( (bufno&SPAREBUF_MASK)? \
+	  ( \
+	    (sparebufs[bufno&(~SPAREBUF_MASK)].buf+ \
+	     PAGE_SIZE*sbale) \
+	  ):( \
+	      (card->inbound_buffer_pool_entry[card-> \
+	       inbound_buffer_entry_no[bufno]][sbale]) \
+	    ) )
+
+#define SPAREBUF_UNAVAIL 0
+#define SPAREBUF_FREE 1
+#define SPAREBUF_USED 2
+
+struct sparebufs {
+	char *buf;
+	atomic_t status;
+};
+
+#define SEND_STATE_INACTIVE		0
+#define SEND_STATE_DONT_PACK		1
+#define SEND_STATE_PACK			2
+
+#define QETH_LOCK_UNLOCKED 0
+#define QETH_LOCK_NORMAL 1
+#define QETH_LOCK_FLUSH 2
+
+#define QETH_MAX_DEVICES 16
+	/* DEPENDENCY ON QETH_MAX_DEVICES.
+	 *__MOUDLE_STRING expects simple literals */
+#define QETH_MAX_DEVICES_TIMES_4 64
+#define QETH_MAX_DEVNAMES 16
+#define QETH_DEVNAME "eth"
+
+#define QETH_TX_TIMEOUT 100*HZ	/* 100 seconds */
+
+#define QETH_REMOVE_WAIT_TIME 200
+#define QETH_WAIT_FOR_THREAD_TIME 20
+#define QETH_IDLE_WAIT_TIME 10
+#define QETH_WAIT_BEFORE_2ND_DOIO 1000
+
+#define QETH_MAX_PARM_LEN 128
+
+#define QETH_FAKE_LL_LEN ETH_HLEN	/* 14 */
+#define QETH_FAKE_LL_PROT_LEN 2
+#define QETH_FAKE_LL_ADDR_LEN ETH_ALEN	/* 6 */
+#define QETH_FAKE_LL_DEST_MAC_POS 0
+#define QETH_FAKE_LL_SRC_MAC_POS 6
+#define QETH_FAKE_LL_SRC_MAC_POS_IN_QDIO_HDR 6
+#define QETH_FAKE_LL_PROT_POS 12
+#define QETH_FAKE_LL_V4_ADDR_POS 16
+#define QETH_FAKE_LL_V6_ADDR_POS 24
+
+#define DEV_NAME_LEN 16
+#define IOCTL_MAX_TRANSFER_SIZE 65535
+
+#define IP_TOS_LOWDELAY 0x10
+#define IP_TOS_HIGHTHROUGHPUT 0x08
+#define IP_TOS_HIGHRELIABILITY 0x04
+#define IP_TOS_NOTIMPORTANT 0x02
+
+#define QETH_RCD_LENGTH 128
+
+#define __max(a,b) ( ((a)>(b))?(a):(b) )
+#define __min(a,b) ( ((a)<(b))?(a):(b) )
+#define QETH_BUFSIZE __max(__max(IPA_PDU_HEADER_SIZE+sizeof(struct arp_cmd), \
+				 IPA_PDU_HEADER_SIZE+sizeof(struct ipa_cmd)), \
+			   QETH_RCD_LENGTH)
+
+#define QETH_FINAL_STATUS_TIMEOUT 1500
+#define QETH_CLEAR_TIMEOUT 1500
+#define QETH_RCD_TIMEOUT 1500
+#define QETH_NOP_TIMEOUT 1500
+#define QETH_QUIESCE_NETDEV_TIME 300
+#define QETH_QUIESCE_WAIT_BEFORE_CLEAR 4000
+#define QETH_QUIESCE_WAIT_AFTER_CLEAR 4000
+
+#define NOP_STATE 0x1001
+#define READ_CONF_DATA_STATE 0x1002
+#define IDX_ACTIVATE_READ_STATE 0x1003
+#define IDX_ACTIVATE_WRITE_STATE 0x1004
+#define MPC_SETUP_STATE 0x1005
+#define CLEAR_STATE 0x1006
+#define IPA_CMD_STATE 0x1007
+#define IPA_IOCTL_STATE 0x1009
+#define IPA_SETIP_FLAG 0x100000
+
+#define QETH_REMOVE_CARD_PROPER 1
+#define QETH_REMOVE_CARD_QUICK 2
+
+#define NO_PRIO_QUEUEING 0
+#define PRIO_QUEUEING_PREC 1
+#define PRIO_QUEUEING_TOS 2
+#define NO_ROUTER 0
+#define PRIMARY_ROUTER 1
+#define SECONDARY_ROUTER 2
+#define MULTICAST_ROUTER 3
+#define PRIMARY_CONNECTOR 4
+#define SECONDARY_CONNECTOR 5
+#define ROUTER_MASK 0xf		/* used to remove SET_ROUTING_FLAG
+				   from routing_type */
+#define RESET_ROUTING_FLAG 0x10	/* used to indicate, that setting
+				   the routing type is desired */
+#define BROADCAST_ALLRINGS 0
+#define BROADCAST_LOCAL 1
+#define MACADDR_NONCANONICAL 0
+#define MACADDR_CANONICAL 1
+#define MEMUSAGE_DISCONTIG 0
+#define MEMUSAGE_CONTIG 1
+#define ENABLE_TAKEOVER 0
+#define DISABLE_TAKEOVER 1
+#define FAKE_BROADCAST 0
+#define DONT_FAKE_BROADCAST 1
+
+#define FAKE_LL 0
+#define DONT_FAKE_LL 1
+#define SYNC_IQD 0
+#define ASYNC_IQD 1
+
+#define QETH_BREAKOUT_LEAVE 1
+#define QETH_BREAKOUT_AGAIN 2
+
+#define QETH_WAIT_FOR_LOCK 0
+#define QETH_DONT_WAIT_FOR_LOCK 1
+#define QETH_LOCK_ALREADY_HELD 2
+
+#define PROBLEM_CARD_HAS_STARTLANED 1
+#define PROBLEM_RECEIVED_IDX_TERMINATE 2
+#define PROBLEM_ACTIVATE_CHECK_CONDITION 3
+#define PROBLEM_RESETTING_EVENT_INDICATOR 4
+#define PROBLEM_COMMAND_REJECT 5
+#define PROBLEM_ZERO_SENSE_DATA 6
+#define PROBLEM_GENERAL_CHECK 7
+#define PROBLEM_BAD_SIGA_RESULT 8
+#define PROBLEM_USER_TRIGGERED_RECOVERY 9
+#define PROBLEM_AFFE 10
+#define PROBLEM_MACHINE_CHECK 11
+#define PROBLEM_TX_TIMEOUT 12
+
+#define SENSE_COMMAND_REJECT_BYTE 0
+#define SENSE_COMMAND_REJECT_FLAG 0x80
+#define SENSE_RESETTING_EVENT_BYTE 1
+#define SENSE_RESETTING_EVENT_FLAG 0x80
+
+#define DEFAULT_RCD_CMD 0x72
+#define DEFAULT_RCD_COUNT 0x80
+
+#define BUFFER_USED 1
+#define BUFFER_UNUSED -1
+
+typedef int (*reg_notifier_t) (struct notifier_block *);
+
+struct ipato_entry {
+	int version;
+	__u8 addr[16];
+	int mask_bits;
+	char dev_name[DEV_NAME_LEN];
+	struct ipato_entry *next;
+};
+
+struct qeth_vipa_entry {
+	int version;
+	__u8 ip[16];
+	int flag;
+	volatile int state;
+	struct qeth_vipa_entry *next;
+};
+
+struct ip_state {
+	struct in_ifaddr *ip_ifa;	/* pointer to IPv4 adresses */
+	struct inet6_ifaddr *ip6_ifa;
+};
+
+struct qeth_ipm_mac {
+	__u8 mac[ETH_ALEN];
+	__u8 ip[16];
+	struct qeth_ipm_mac *next;
+};
+
+struct ip_mc_state {
+	struct qeth_ipm_mac *ipm_ifa;
+	struct qeth_ipm_mac *ipm6_ifa;
+};
+
+struct addr_request {
+	struct addr_request *next;
+	int request_type;
+	__u8 mac[ETH_ALEN];
+	__u8 ip[16];
+};
+
+struct qeth_card_options {
+	char devname[DEV_NAME_LEN];
+	volatile int routing_type4;
+#ifdef QETH_IPV6
+	volatile int routing_type6;
+#endif /* QETH_IPV6 */
+	int checksum_type;
+	int do_prio_queueing;
+	int default_queue;
+	int inbound_buffer_count;
+	int polltime;
+	char portname[9];
+	int portno;
+	int memusage;
+	int broadcast_mode;
+	int macaddr_mode;
+	int ena_ipat;
+	int fake_broadcast;
+	int add_hhlen;
+	int fake_ll;
+	int async_iqd;
+};
+
+struct qeth_hdr {
+	__u8 id;
+	__u8 flags;
+	__u16 inbound_checksum;
+	__u32 token;
+	__u16 length;
+	__u8 vlan_prio;
+	__u8 ext_flags;
+	__u16 vlan_id;
+	__u16 frame_offset;
+	__u8 dest_addr[16];
+};
+
+struct qeth_ringbuffer_element {
+	struct sk_buff_head skb_list;
+	int next_element_to_fill;
+} __attribute__ ((packed));
+
+struct qeth_ringbuffer {
+	struct qdio_buffer buffer[QDIO_MAX_BUFFERS_PER_Q];
+	struct qeth_ringbuffer_element ringbuf_element[QDIO_MAX_BUFFERS_PER_Q];
+}__attribute__ ((packed, aligned(PAGE_SIZE)));
+
+struct qeth_dma_stuff {
+	unsigned char *sendbuf;
+	unsigned char *recbuf;
+	struct ccw1 read_ccw;
+	struct ccw1 write_ccw;
+}__attribute__ ((packed, aligned(PAGE_SIZE)));
+
+struct qeth_perf_stats {
+	unsigned int skbs_rec;
+	unsigned int bufs_rec;
+
+	unsigned int skbs_sent;
+	unsigned int bufs_sent;
+
+	unsigned int skbs_sent_dont_pack;
+	unsigned int bufs_sent_dont_pack;
+	unsigned int skbs_sent_pack;
+	unsigned int bufs_sent_pack;
+	unsigned int skbs_sent_pack_better;
+	unsigned int bufs_sent_pack_better;
+
+	unsigned int sc_dp_p;
+	unsigned int sc_p_dp;
+
+	__u64 inbound_start_time;
+	unsigned int inbound_cnt;
+	unsigned int inbound_time;
+	__u64 outbound_start_time;
+	unsigned int outbound_cnt;
+	unsigned int outbound_time;
+};
+
+/* ugly. I know. */
+struct qeth_card {	/* pointed to by dev->priv */
+	int easy_copy_cap;
+
+	/* pointer to options (defaults + parameters) */
+	struct qeth_card_options options;
+
+	atomic_t is_startlaned;	/* card did not get a stoplan */
+	                        /* also 0 when card is gone after a
+	                         * machine check */
+
+	__u8 link_type;
+
+	int is_guest_lan;
+
+	/* inbound buffer management */
+	atomic_t inbound_buffer_refcnt[QDIO_MAX_BUFFERS_PER_Q];
+	struct qdio_buffer inbound_qdio_buffers[QDIO_MAX_BUFFERS_PER_Q];
+	/* inbound data area */
+	void *inbound_buffer_pool_entry[QDIO_MAX_BUFFERS_PER_Q]
+	    [QDIO_MAX_ELEMENTS_PER_BUFFER];
+	volatile int inbound_buffer_pool_entry_used[QDIO_MAX_BUFFERS_PER_Q];
+	int inbound_buffer_entry_no[QDIO_MAX_BUFFERS_PER_Q];
+
+	/* for requeueing of buffers */
+	spinlock_t requeue_input_lock;
+	atomic_t requeue_position;
+	atomic_t requeue_counter;
+
+	/* outbound QDIO stuff */
+	volatile int send_state[QETH_MAX_QUEUES];
+	volatile int outbound_first_free_buffer[QETH_MAX_QUEUES];
+	atomic_t outbound_used_buffers[QETH_MAX_QUEUES];
+	int outbound_buffer_send_state[QETH_MAX_QUEUES]
+	    [QDIO_MAX_BUFFERS_PER_Q];
+	int send_retries[QETH_MAX_QUEUES][QDIO_MAX_BUFFERS_PER_Q];
+	volatile int outbound_bytes_in_buffer[QETH_MAX_QUEUES];
+	struct qeth_ringbuffer *outbound_ringbuffer[QETH_MAX_QUEUES];
+	atomic_t outbound_ringbuffer_lock[QETH_MAX_QUEUES];
+	atomic_t last_pci_pos[QETH_MAX_QUEUES];
+
+#ifdef QETH_IPV6
+	int (*hard_header) (struct sk_buff *, struct net_device *,
+			    unsigned short, void *, void *, unsigned);
+	int (*rebuild_header) (struct sk_buff *);
+	int (*hard_header_cache) (struct neighbour *, struct hh_cache *);
+	void (*header_cache_update) (struct hh_cache *, struct net_device *,
+				     unsigned char *);
+	unsigned short (*type_trans) (struct sk_buff *, struct net_device *);
+#endif /* QETH_IPV6 */
+
+#ifdef QETH_VLAN
+	struct vlan_group *vlangrp;
+	spinlock_t vlan_lock;
+#endif
+
+	char dev_name[DEV_NAME_LEN];	/* pointed to by dev->name */
+	struct net_device *dev;
+	struct net_device_stats *stats;
+
+	int no_queues;
+
+#ifdef QETH_PERFORMANCE_STATS
+	struct qeth_perf_stats perf_stats;
+#endif /* QETH_PERFORMANCE_STATS */
+
+	/* our state */
+	atomic_t is_registered;	/* card registered as netdev? */
+	atomic_t is_hardsetup;	/* card has gone through hardsetup */
+	atomic_t is_softsetup;	/* card is setup by softsetup */
+	atomic_t is_open;	/* card is in use */
+
+	/* prevents deadlocks :-O */
+	spinlock_t softsetup_lock;
+	spinlock_t hardsetup_lock;
+	spinlock_t ioctl_lock;
+	atomic_t softsetup_thread_is_running;
+	struct semaphore softsetup_thread_sem;
+	struct work_struct tqueue_sst;
+
+	atomic_t escape_softsetup;	/* active, when recovery has to
+					   wait for softsetup */
+	struct semaphore reinit_thread_sem;
+	atomic_t in_recovery;
+	atomic_t reinit_counter;
+
+	/* problem management */
+	atomic_t break_out;
+	atomic_t problem;
+	struct work_struct tqueue;
+
+	struct {
+		__u32 trans_hdr;
+		__u32 pdu_hdr;
+		__u32 pdu_hdr_ack;
+		__u32 ipa;
+	} seqno;
+
+	struct {
+		__u32 issuer_rm_w;
+		__u32 issuer_rm_r;
+		__u32 cm_filter_w;
+		__u32 cm_filter_r;
+		__u32 cm_connection_w;
+		__u32 cm_connection_r;
+		__u32 ulp_filter_w;
+		__u32 ulp_filter_r;
+		__u32 ulp_connection_w;
+		__u32 ulp_connection_r;
+	} token;
+
+	/* this is card-related */
+	int type;
+	__u16 func_level;
+	int initial_mtu;
+	int max_mtu;
+	int inbound_buffer_size;
+
+	int is_multicast_different;	/* if multicast traffic is to be sent
+					   on a different queue, this is the
+					   queue+no_queues */
+	int can_do_async_iqd;	/* 1 only on IQD that provides async
+				   unicast sigas */
+	__u32 ipa_supported;
+	__u32 ipa_enabled;
+	__u32 ipa6_supported;
+	__u32 ipa6_enabled;
+	__u32 adp_supported;
+
+	atomic_t startlan_attempts;
+	atomic_t enable_routing_attempts4;
+	atomic_t rt4fld;
+#ifdef QETH_IPV6
+	atomic_t enable_routing_attempts6;
+	atomic_t rt6fld;
+#endif /* QETH_IPV6 */
+	int unique_id;
+
+	/* device and I/O data */
+	struct ccw_device *rdev;
+	struct ccw_device *wdev;
+	struct ccw_device *ddev;
+	unsigned short unit_addr2;
+	unsigned short cula;
+	unsigned short chpid;
+
+	unsigned char ipa_buf[QETH_BUFSIZE];
+	unsigned char send_buf[QETH_BUFSIZE];
+
+/* IOCTL Stuff */
+	unsigned char *ioctl_data_buffer;
+	unsigned char *ioctl_buffer_pointer;
+	int ioctl_returncode;
+	int ioctl_buffersize;
+	int number_of_entries;
+
+	atomic_t ioctl_data_has_arrived;
+	wait_queue_head_t ioctl_wait_q;
+	atomic_t ioctl_wait_q_active;
+	spinlock_t ioctl_wait_q_lock;
+
+/* stuff under 2 gb */
+	struct qeth_dma_stuff *dma_stuff;
+
+	unsigned int ipa_timeout;
+
+	atomic_t write_busy;
+
+	/* vipa stuff */
+	rwlock_t vipa_list_lock;
+	struct qeth_vipa_entry *vipa_list;
+
+	/* state information when doing I/O */
+	atomic_t shutdown_phase;
+	atomic_t data_has_arrived;
+	wait_queue_head_t wait_q;
+	atomic_t wait_q_active;
+	spinlock_t wait_q_lock;	/* for wait_q_active and wait_q */
+
+	atomic_t clear_succeeded0;
+	atomic_t clear_succeeded1;
+	atomic_t clear_succeeded2;
+
+	/* bookkeeping of IP and multicast addresses */
+	struct ip_state ip_current_state;
+	struct ip_state ip_new_state;
+
+	struct ip_mc_state ip_mc_current_state;
+	struct ip_mc_state ip_mc_new_state;
+
+	int broadcast_capable;
+	int portname_required;
+
+	int realloc_message;
+
+	char level[QETH_MCL_LENGTH + 1];
+
+	volatile int saved_dev_flags;
+
+	/* for our linked list */
+	struct qeth_card *next;
+};
+
+inline static int
+qeth_get_arphrd_type(int cardtype, int linktype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_OSAE:
+		switch (linktype) {
+		case QETH_MPC_LINK_TYPE_LANE_TR:
+			/* fallthrough */
+		case QETH_MPC_LINK_TYPE_HSTR:
+			return ARPHRD_IEEE802;
+		default:
+			return ARPHRD_ETHER;
+		}
+	case QETH_CARD_TYPE_IQD:
+		return ARPHRD_ETHER;
+	default:
+		return ARPHRD_ETHER;
+	}
+}
+
+inline static int
+qeth_determine_easy_copy_cap(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return 0;	/* better be cautious */
+	case QETH_CARD_TYPE_OSAE:
+		return 1;
+	case QETH_CARD_TYPE_IQD:
+		return 0;
+	default:
+		return 0;	/* ?? */
+	}
+}
+
+inline static __u8
+qeth_get_adapter_type_for_ipa(int link_type)
+{
+	switch (link_type) {
+	case QETH_MPC_LINK_TYPE_HSTR:
+		return 2;
+	default:
+		return 1;
+	}
+}
+
+inline static const char *
+qeth_get_cardname(int cardtype, int is_guest_lan)
+{
+
+ 	if (is_guest_lan) {
+ 		switch (cardtype) {
+ 		case QETH_CARD_TYPE_UNKNOWN:
+			return "n unknown";
+ 		case QETH_CARD_TYPE_OSAE:
+			return " Guest LAN QDIO";
+ 		case QETH_CARD_TYPE_IQD:
+			return " Guest LAN Hiper";
+ 		default: return
+				 " strange";
+ 		}
+	} else {
+		switch (cardtype) {
+		case QETH_CARD_TYPE_UNKNOWN:
+			return "n unknown";
+		case QETH_CARD_TYPE_OSAE:
+			return "n OSD Express";
+		case QETH_CARD_TYPE_IQD:
+			return " HiperSockets";
+		default:
+			return " strange";
+		}
+	}
+}
+
+/* max length to be returned: 14 */
+inline static const char *
+qeth_get_cardname_short(int cardtype, __u8 link_type, int is_guest_lan)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return "unknown";
+	case QETH_CARD_TYPE_OSAE:
+		if (is_guest_lan)
+			return "GuestLAN QDIO";
+		switch (link_type) {
+		case QETH_MPC_LINK_TYPE_FAST_ETHERNET:
+			return "OSD_100";
+		case QETH_MPC_LINK_TYPE_HSTR:
+			return "HSTR";
+		case QETH_MPC_LINK_TYPE_GIGABIT_ETHERNET:
+			return "OSD_1000";
+		case QETH_MPC_LINK_TYPE_LANE_ETH100:
+			return "OSD_FE_LANE";
+		case QETH_MPC_LINK_TYPE_LANE_TR:
+			return "OSD_TR_LANE";
+		case QETH_MPC_LINK_TYPE_LANE_ETH1000:
+			return "OSD_GbE_LANE";
+		case QETH_MPC_LINK_TYPE_LANE:
+			return "OSD_ATM_LANE";
+		default:
+			return "OSD_Express";
+		}
+	case QETH_CARD_TYPE_IQD:
+		return is_guest_lan ? "GuestLAN Hiper" : "HiperSockets";
+	default:
+		return " strange";
+	}
+}
+
+inline static int
+qeth_mtu_is_valid(struct qeth_card * card, int mtu)
+{
+	switch (card->type) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return 1;
+	case QETH_CARD_TYPE_OSAE:
+		return ((mtu >= 576) && (mtu <= 61440));
+	case QETH_CARD_TYPE_IQD:
+		return ((mtu >= 576) && (mtu <= card->max_mtu + 4096 - 32));
+	default:
+		return 1;
+	}
+}
+
+inline static int
+qeth_get_initial_mtu_for_card(struct qeth_card * card)
+{
+	switch (card->type) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return 1500;
+	case QETH_CARD_TYPE_IQD:
+		return card->max_mtu;
+	case QETH_CARD_TYPE_OSAE:
+		switch (card->link_type) {
+		case QETH_MPC_LINK_TYPE_HSTR:
+		case QETH_MPC_LINK_TYPE_LANE_TR:
+			return 2000;
+		default:
+			return 1492;
+		}
+	default:
+		return 1500;
+	}
+}
+
+inline static int
+qeth_get_max_mtu_for_card(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return 61440;
+	case QETH_CARD_TYPE_OSAE:
+		return 61440;
+	case QETH_CARD_TYPE_IQD:
+		return 57344;
+	default:
+		return 1500;
+	}
+}
+
+inline static int
+qeth_get_mtu_out_of_mpc(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_IQD:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+inline static int
+qeth_get_mtu_outof_framesize(int framesize)
+{
+	switch (framesize) {
+	case 0x4000:
+		return 8192;
+	case 0x6000:
+		return 16384;
+	case 0xa000:
+		return 32768;
+	case 0xffff:
+		return 57344;
+	default:
+		return 0;
+	}
+}
+
+inline static int
+qeth_get_buffersize_for_card(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return 65536;
+	case QETH_CARD_TYPE_OSAE:
+		return 65536;
+	case QETH_CARD_TYPE_IQD:
+		return 16384;
+	default:
+		return 65536;
+	}
+}
+
+inline static int
+qeth_get_min_number_of_buffers(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_UNKNOWN:
+		return 32;
+	case QETH_CARD_TYPE_OSAE:
+		return 32;
+	case QETH_CARD_TYPE_IQD:
+		return 64;
+	default:
+		return 64;
+	}
+}
+
+inline static int
+qeth_get_q_format(int cardtype)
+{
+	switch (cardtype) {
+	case QETH_CARD_TYPE_IQD:
+		return 2;
+	default:
+		return 0;
+	}
+}
+
+inline static int
+qeth_get_device_tx_q_len(int cardtype)
+{
+	return 100;
+}
+
+inline static int
+qeth_get_max_number_of_buffers(int cardtype)
+{
+	return 127;
+}
+
+/******************** OUTPUT FACILITIES **************************/
+
+#ifdef PRINT_INFO
+#undef PRINTK_HEADER
+#undef PRINT_STUPID
+#undef PRINT_ALL
+#undef PRINT_INFO
+#undef PRINT_WARN
+#undef PRINT_ERR
+#undef PRINT_CRIT
+#undef PRINT_ALERT
+#undef PRINT_EMERG
+#endif				/* PRINT_INFO */
+
+#define PRINTK_HEADER QETH_NAME ": "
+
+#if QETH_VERBOSE_LEVEL>8
+#define PRINT_STUPID(x...) printk( KERN_DEBUG PRINTK_HEADER x)
+#else
+#define PRINT_STUPID(x...)
+#endif
+
+#if QETH_VERBOSE_LEVEL>7
+#define PRINT_ALL(x...) printk( KERN_DEBUG PRINTK_HEADER x)
+#else
+#define PRINT_ALL(x...)
+#endif
+
+#if QETH_VERBOSE_LEVEL>6
+#define PRINT_INFO(x...) printk( KERN_INFO PRINTK_HEADER x)
+#else
+#define PRINT_INFO(x...)
+#endif
+
+#if QETH_VERBOSE_LEVEL>5
+#define PRINT_WARN(x...) printk( KERN_WARNING PRINTK_HEADER x)
+#else
+#define PRINT_WARN(x...)
+#endif
+
+#if QETH_VERBOSE_LEVEL>4
+#define PRINT_ERR(x...) printk( KERN_ERR PRINTK_HEADER x)
+#else
+#define PRINT_ERR(x...)
+#endif
+
+#if QETH_VERBOSE_LEVEL>3
+#define PRINT_CRIT(x...) printk( KERN_CRIT PRINTK_HEADER x)
+#else
+#define PRINT_CRIT(x...)
+#endif
+
+#if QETH_VERBOSE_LEVEL>2
+#define PRINT_ALERT(x...) printk( KERN_ALERT PRINTK_HEADER x)
+#else
+#define PRINT_ALERT(x...)
+#endif
+
+#if QETH_VERBOSE_LEVEL>1
+#define PRINT_EMERG(x...) printk( KERN_EMERG PRINTK_HEADER x)
+#else
+#define PRINT_EMERG(x...)
+#endif
+
+#define HEXDUMP16(importance,header,ptr) \
+PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+		   *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
+		   *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
+		   *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
+		   *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
+		   *(((char*)ptr)+12),*(((char*)ptr)+13), \
+		   *(((char*)ptr)+14),*(((char*)ptr)+15)); \
+PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+		   *(((char*)ptr)+16),*(((char*)ptr)+17), \
+		   *(((char*)ptr)+18),*(((char*)ptr)+19), \
+		   *(((char*)ptr)+20),*(((char*)ptr)+21), \
+		   *(((char*)ptr)+22),*(((char*)ptr)+23), \
+		   *(((char*)ptr)+24),*(((char*)ptr)+25), \
+		   *(((char*)ptr)+26),*(((char*)ptr)+27), \
+		   *(((char*)ptr)+28),*(((char*)ptr)+29), \
+		   *(((char*)ptr)+30),*(((char*)ptr)+31));
+
+#endif /* __QETH_H__ */
diff -urN linux-2.5.73-bk9/drivers/s390/net/qeth_mpc.c linux-2.5.73-bk10/drivers/s390/net/qeth_mpc.c
--- linux-2.5.73-bk9/drivers/s390/net/qeth_mpc.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/drivers/s390/net/qeth_mpc.c	2003-07-02 04:57:30.000000000 -0700
@@ -0,0 +1,161 @@
+/*
+ * linux/drivers/s390/net/qeth_mpc.c
+ *
+ * Linux on zSeries OSA Express and HiperSockets support
+ *
+ * Copyright 2000,2003 IBM Corporation
+ * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
+ *
+ */
+#include <asm/cio.h>
+#include "qeth_mpc.h"
+
+unsigned char IDX_ACTIVATE_READ[]={
+	0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
+	0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00, 0x00,0x00,0xc8,0xc1,
+	0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00,
+	0x00,0x00
+};
+
+unsigned char IDX_ACTIVATE_WRITE[]={
+	0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
+	0x15,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
+	0xff,0xff,0x00,0x00, 0x00,0x00,0xc8,0xc1,
+	0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00,
+	0x00,0x00
+};
+
+unsigned char CM_ENABLE[]={
+	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x01,
+	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x63,
+	0x10,0x00,0x00,0x01,
+	0x00,0x00,0x00,0x00,
+	0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x23,
+	0x00,0x00,0x23,0x05, 0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+	0x01,0x00,0x00,0x23, 0x00,0x00,0x00,0x40,
+	0x00,0x0c,0x41,0x02, 0x00,0x17,0x00,0x00,
+	0x00,0x00,0x00,0x00,
+	0x00,0x0b,0x04,0x01,
+	0x7e,0x04,0x05,0x00, 0x01,0x01,0x0f,
+	0x00,
+	0x0c,0x04,0x02,0xff, 0xff,0xff,0xff,0xff,
+	0xff,0xff,0xff
+};
+
+unsigned char CM_SETUP[]={
+	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x02,
+	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x64,
+	0x10,0x00,0x00,0x01,
+	0x00,0x00,0x00,0x00,
+	0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x24,
+	0x00,0x00,0x24,0x05, 0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+	0x01,0x00,0x00,0x24, 0x00,0x00,0x00,0x40,
+	0x00,0x0c,0x41,0x04, 0x00,0x18,0x00,0x00,
+	0x00,0x00,0x00,0x00,
+	0x00,0x09,0x04,0x04,
+	0x05,0x00,0x01,0x01, 0x11,
+	0x00,0x09,0x04,
+	0x05,0x05,0x00,0x00, 0x00,0x00,
+	0x00,0x06,
+	0x04,0x06,0xc8,0x00
+};
+
+unsigned char ULP_ENABLE[]={
+	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x03,
+	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6b,
+	0x10,0x00,0x00,0x01,
+	0x00,0x00,0x00,0x00,
+	0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x01,
+	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x2b,
+	0x00,0x00,0x2b,0x05, 0x20,0x01,0x00,0x00,
+	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+	0x01,0x00,0x00,0x2b, 0x00,0x00,0x00,0x40,
+	0x00,0x0c,0x41,0x02, 0x00,0x1f,0x00,0x00,
+	0x00,0x00,0x00,0x00,
+	0x00,0x0b,0x04,0x01,
+	0x03,0x04,0x05,0x00, 0x01,0x01,0x12,
+	0x00,
+	0x14,0x04,0x0a,0x00, 0x20,0x00,0x00,0xff,
+	0xff,0x00,0x08,0xc8, 0xe8,0xc4,0xf1,0xc7,
+	0xf1,0x00,0x00
+};
+
+unsigned char ULP_SETUP[]={
+	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x04,
+	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6c,
+	0x10,0x00,0x00,0x01,
+	0x00,0x00,0x00,0x00,
+	0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x02,
+	0x00,0x00,0x00,0x01, 0x00,0x24,0x00,0x2c,
+	0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00,
+	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+	0x01,0x00,0x00,0x2c, 0x00,0x00,0x00,0x40,
+	0x00,0x0c,0x41,0x04, 0x00,0x20,0x00,0x00,
+	0x00,0x00,0x00,0x00,
+	0x00,0x09,0x04,0x04,
+	0x05,0x00,0x01,0x01, 0x14,
+	0x00,0x09,0x04,
+	0x05,0x05,0x30,0x01, 0x00,0x00,
+	0x00,0x06,
+	0x04,0x06,0x40,0x00,
+	0x00,0x08,0x04,0x0b,
+	0x00,0x00,0x00,0x00
+};
+
+unsigned char DM_ACT[]={
+	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x05,
+	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x55,
+	0x10,0x00,0x00,0x01,
+	0x00,0x00,0x00,0x00,
+	0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x03,
+	0x00,0x00,0x00,0x02, 0x00,0x24,0x00,0x15,
+	0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00,
+	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+	0x01,0x00,0x00,0x15, 0x00,0x00,0x00,0x40,
+	0x00,0x0c,0x43,0x60, 0x00,0x09,0x00,0x00,
+	0x00,0x00,0x00,0x00,
+	0x00,0x09,0x04,0x04,
+	0x05,0x40,0x01,0x01, 0x00
+};
+
+unsigned char IPA_PDU_HEADER[]={
+	0x00,0xe0,0x00,0x00, 0x77,0x77,0x77,0x77,
+	0x00,0x00,0x00,0x14, 0x00,0x00,
+		(IPA_PDU_HEADER_SIZE+sizeof(struct ipa_cmd))/256,
+		(IPA_PDU_HEADER_SIZE+sizeof(struct ipa_cmd))%256,
+	0x10,0x00,0x00,0x01,
+	0x00,0x00,0x00,0x00,
+	0xc1,0x03,0x00,0x01, 0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,sizeof(struct ipa_cmd),
+	0x00,0x00,sizeof(struct ipa_cmd),0x05, 0x77,0x77,0x77,0x77,
+	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+	0x01,0x00,sizeof(struct ipa_cmd)/256,sizeof(struct ipa_cmd)%256,
+				0x00,0x00,0x00,0x40,
+};
+
+unsigned char WRITE_CCW[]={
+	0x01,CCW_FLAG_SLI,0,0,
+	0,0,0,0
+};
+
+unsigned char READ_CCW[]={
+	0x02,CCW_FLAG_SLI,0,0,
+	0,0,0,0
+};
+
+
+
+
+
+
+
+
+
+
+
+
diff -urN linux-2.5.73-bk9/drivers/s390/net/qeth_mpc.h linux-2.5.73-bk10/drivers/s390/net/qeth_mpc.h
--- linux-2.5.73-bk9/drivers/s390/net/qeth_mpc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/drivers/s390/net/qeth_mpc.h	2003-07-02 04:57:30.000000000 -0700
@@ -0,0 +1,442 @@
+/*
+ * linux/drivers/s390/net/qeth_mpc.h
+ *
+ * Linux on zSeries OSA Express and HiperSockets support
+ *
+ * Copyright 2000,2003 IBM Corporation
+ * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
+ *
+ */
+#ifndef __QETH_MPC_H__
+#define __QETH_MPC_H__
+
+#define VERSION_QETH_MPC_H "$Revision: 1.15 $"
+
+#define QETH_IPA_TIMEOUT (card->ipa_timeout)
+#define QETH_MPC_TIMEOUT 2000
+#define QETH_ADDR_TIMEOUT 1000
+
+#define QETH_SETIP_RETRIES 2
+
+#define IDX_ACTIVATE_SIZE 0x22
+#define CM_ENABLE_SIZE 0x63
+#define CM_SETUP_SIZE 0x64
+#define ULP_ENABLE_SIZE 0x6b
+#define ULP_SETUP_SIZE 0x6c
+#define DM_ACT_SIZE 0x55
+
+#define QETH_MPC_TOKEN_LENGTH 4
+#define QETH_SEQ_NO_LENGTH 4
+#define QETH_IPA_SEQ_NO_LENGTH 2
+
+#define QETH_TRANSPORT_HEADER_SEQ_NO(buffer) (buffer+4)
+#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer+0x1c)
+#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer+0x20)
+
+extern unsigned char IDX_ACTIVATE_READ[];
+
+extern unsigned char IDX_ACTIVATE_WRITE[];
+
+#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer+0x0c)
+#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b]&0x80)
+#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer+0x10)
+#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer+0x16)
+#define QETH_IDX_ACT_QDIO_DEV_CUA(buffer) (buffer+0x1e)
+#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer+0x20)
+
+#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08]&3)==2)
+
+#define QETH_IDX_REPLY_LEVEL(buffer) (buffer+0x12)
+#define QETH_MCL_LENGTH 4
+
+extern unsigned char CM_ENABLE[];
+
+#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer+0x2c)
+#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53)
+#define QETH_CM_ENABLE_USER_DATA(buffer) (buffer+0x5b)
+
+#define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) (PDU_ENCAPSULATION(buffer)+ \
+						  0x13)
+
+extern unsigned char CM_SETUP[];
+
+#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer+0x2c)
+#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51)
+#define QETH_CM_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a)
+
+#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) (PDU_ENCAPSULATION(buffer)+ \
+					      0x1a)
+
+extern unsigned char ULP_ENABLE[];
+
+#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer+0x61)
+#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer+0x2c)
+#define QETH_ULP_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53)
+#define QETH_ULP_ENABLE_PORTNAME_AND_LL(buffer) (buffer+0x62)
+
+#define QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer) (PDU_ENCAPSULATION(buffer)+ \
+						   0x13)
+#define QETH_ULP_ENABLE_RESP_MAX_MTU(buffer) (PDU_ENCAPSULATION(buffer)+ 0x1f)
+#define QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer) (PDU_ENCAPSULATION(buffer)+ \
+					  	  0x17)
+#define QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer) (PDU_ENCAPSULATION(buffer)+ \
+						0x2b)
+
+extern unsigned char ULP_SETUP[];
+
+#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer+0x2c)
+#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51)
+#define QETH_ULP_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a)
+#define QETH_ULP_SETUP_CUA(buffer) (buffer+0x68)
+#define QETH_ULP_SETUP_REAL_DEVADDR(buffer) (buffer+0x6a)
+
+#define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) (PDU_ENCAPSULATION \
+						      (buffer)+0x1a)
+
+extern unsigned char DM_ACT[];
+
+#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer+0x2c)
+#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer+0x51)
+
+#define IPA_CMD_STARTLAN 0x01
+#define IPA_CMD_STOPLAN 0x02
+#define IPA_CMD_SETIP 0xb1
+#define IPA_CMD_DELIP 0xb7
+#define IPA_CMD_QIPASSIST 0xb2
+#define IPA_CMD_SETASSPARMS 0xb3
+#define IPA_CMD_SETIPM 0xb4
+#define IPA_CMD_DELIPM 0xb5
+#define IPA_CMD_SETRTG 0xb6
+#define IPA_CMD_SETADAPTERPARMS 0xb8
+#define IPA_CMD_ADD_ADDR_ENTRY 0xc1
+#define IPA_CMD_DELETE_ADDR_ENTRY 0xc2
+#define IPA_CMD_CREATE_ADDR 0xc3
+#define IPA_CMD_DESTROY_ADDR 0xc4
+#define IPA_CMD_REGISTER_LOCAL_ADDR 0xd1
+#define IPA_CMD_UNREGISTER_LOCAL_ADDR 0xd2
+
+#define INITIATOR_HOST 0
+#define INITIATOR_HYDRA 1
+
+#define PRIM_VERSION_IPA 1
+
+#define PROT_VERSION_SNA 1 /* hahaha */
+#define PROT_VERSION_IPv4 4
+#define PROT_VERSION_IPv6 6
+
+#define OSA_ADDR_LEN 6
+#define IPA_SETADAPTERPARMS_IP_VERSION PROT_VERSION_IPv4
+#define SR_INFO_LEN 16
+
+#define IPA_ARP_PROCESSING 0x00000001L
+#define IPA_INBOUND_CHECKSUM 0x00000002L
+#define IPA_OUTBOUND_CHECKSUM 0x00000004L
+#define IPA_IP_FRAGMENTATION 0x00000008L
+#define IPA_FILTERING 0x00000010L
+#define IPA_IPv6 0x00000020L
+#define IPA_MULTICASTING 0x00000040L
+#define IPA_IP_REASSEMBLY 0x00000080L
+#define IPA_QUERY_ARP_COUNTERS 0x00000100L
+#define IPA_QUERY_ARP_ADDR_INFO 0x00000200L
+#define IPA_SETADAPTERPARMS 0x00000400L
+#define IPA_VLAN_PRIO 0x00000800L
+#define IPA_PASSTHRU 0x00001000L
+#define IPA_FULL_VLAN 0x00004000L
+#define IPA_SOURCE_MAC_AVAIL 0x00010000L
+
+#define IPA_SETADP_QUERY_COMMANDS_SUPPORTED 0x01
+#define IPA_SETADP_ALTER_MAC_ADDRESS 0x02
+#define IPA_SETADP_ADD_DELETE_GROUP_ADDRESS 0x04
+#define IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR 0x08
+#define IPA_SETADP_SET_ADDRESSING_MODE 0x10
+#define IPA_SETADP_SET_CONFIG_PARMS 0x20
+#define IPA_SETADP_SET_CONFIG_PARMS_EXTENDED 0x40
+#define IPA_SETADP_SET_BROADCAST_MODE 0x80
+#define IPA_SETADP_SEND_OSA_MESSAGE 0x0100
+#define IPA_SETADP_SET_SNMP_CONTROL 0x0200
+#define IPA_SETADP_READ_SNMP_PARMS 0x0400
+#define IPA_SETADP_WRITE_SNMP_PARMS 0x0800
+#define IPA_SETADP_QUERY_CARD_INFO 0x1000
+
+#define CHANGE_ADDR_READ_MAC 0
+#define CHANGE_ADDR_REPLACE_MAC 1
+#define CHANGE_ADDR_ADD_MAC 2
+#define CHANGE_ADDR_DEL_MAC 4
+#define CHANGE_ADDR_RESET_MAC 8
+#define CHANGE_ADDR_READ_ADDR 0
+#define CHANGE_ADDR_ADD_ADDR 1
+#define CHANGE_ADDR_DEL_ADDR 2
+#define CHANGE_ADDR_FLUSH_ADDR_TABLE 4
+ 
+/* we assumed, that the card is named card */
+#define qeth_is_supported(str) (card->ipa_supported&str)
+#define qeth_is_supported6(str) (card->ipa6_supported&str)
+#define qeth_is_adp_supported(str) (card->adp_supported&str)
+
+/* the same for all assist parms: */
+#define IPA_CMD_ASS_START 0x0001
+#define IPA_CMD_ASS_STOP 0x0002
+
+#define IPA_CMD_ASS_CONFIGURE 0x0003
+#define IPA_CMD_ASS_ENABLE 0x0004
+
+#define IPA_CMD_ASS_ARP_SET_NO_ENTRIES 0x0003
+#define IPA_CMD_ASS_ARP_QUERY_CACHE 0x0004
+#define IPA_CMD_ASS_ARP_ADD_ENTRY 0x0005
+#define IPA_CMD_ASS_ARP_REMOVE_ENTRY 0x0006
+#define IPA_CMD_ASS_ARP_FLUSH_CACHE 0x0007
+#define IPA_CMD_ASS_ARP_QUERY_INFO 0x0104
+#define IPA_CMD_ASS_ARP_QUERY_STATS 0x0204
+
+#define IPA_CHECKSUM_ENABLE_MASK 0x001a
+
+#define IPA_CMD_ASS_FILTER_SET_TYPES 0x0003
+
+#define IPA_CMD_ASS_IPv6_SET_FUNCTIONS 0x0003
+
+#define IPA_REPLY_SUCCESS 0
+#define IPA_REPLY_FAILED 1
+#define IPA_REPLY_OPNOTSUPP 2
+#define IPA_REPLY_OPNOTSUPP2 4
+#define IPA_REPLY_NOINFO 8
+
+#define IPA_SETIP_FLAGS 0
+#define IPA_SETIP_VIPA_FLAGS 1
+#define IPA_SETIP_TAKEOVER_FLAGS 2
+
+#define VIPA_2_B_ADDED 0
+#define VIPA_ESTABLISHED 1
+#define VIPA_2_B_REMOVED 2
+
+#define IPA_DELIP_FLAGS 0
+
+#define IPA_SETADP_CMDSIZE 40
+
+struct ipa_setadp_cmd {
+	__u32 supp_hw_cmds;
+	__u32 reserved1;
+	__u16 cmdlength;
+	__u16 reserved2;
+	__u32 command_code;
+	__u16 return_code;
+	__u8 frames_used_total;
+	__u8 frame_seq_no;
+	__u32 reserved3;
+	union {
+		struct {
+			__u32 no_lantypes_supp;
+			__u8 lan_type;
+			__u8 reserved1[3];
+			__u32 supported_cmds;
+			__u8 reserved2[8];
+		} query_cmds_supp;
+		struct {
+			__u32 cmd;
+			__u32 addr_size;
+			__u32 no_macs;
+			__u8 addr[OSA_ADDR_LEN];
+		} change_addr;
+		__u32 mode;
+	} data;
+};
+
+struct ipa_cmd{
+	__u8 command;
+	__u8 initiator;
+	__u16 seq_no;
+	__u16 return_code;
+	__u8 adapter_type;
+	__u8 rel_adapter_no;
+	__u8 prim_version_no;
+	__u8 param_count;
+	__u16 prot_version;
+	__u32 ipa_supported;
+	__u32 ipa_enabled;
+	union {
+		struct {
+			__u8 ip[4];
+			__u8 netmask[4];
+			__u32 flags;
+		} setdelip4;
+		struct {
+			__u8 ip[16];
+			__u8 netmask[16];
+			__u32 flags;
+		} setdelip6;
+		struct {
+			__u32 assist_no;
+			__u16 length;
+			__u16 command_code;
+			__u16 return_code;
+			__u8 number_of_replies;
+			__u8 seq_no;
+			union {
+				__u32 flags_32bit;
+				struct {
+					__u8 mac[6];
+					__u8 reserved[2];
+					__u8 ip[16];
+					__u8 reserved2[32];
+				} add_arp_entry;
+				__u8 ip[16];
+			} data;
+		} setassparms;
+		struct {
+			__u8 mac[6];
+			__u8 padding[2];
+			__u8 ip6[12];
+			__u8 ip4_6[4];
+		} setdelipm;
+		struct {
+			__u8 type;
+		} setrtg;
+		struct ipa_setadp_cmd setadapterparms;
+		struct {
+			__u32 command;
+#define ADDR_FRAME_TYPE_DIX 1
+#define ADDR_FRAME_TYPE_802_3 2
+#define ADDR_FRAME_TYPE_TR_WITHOUT_SR 0x10
+#define ADDR_FRAME_TYPE_TR_WITH_SR 0x20
+			__u32 frame_type;
+			__u32 cmd_flags;
+			__u8 ip_addr[16];
+			__u32 tag_field;
+			__u8 mac_addr[6];
+			__u8 reserved[10];
+			__u32 sr_len;
+			__u8 sr_info[SR_INFO_LEN];
+		} add_addr_entry;
+		struct {
+			__u32 command;
+			__u32 cmd_flags;
+			__u8 ip_addr[16];
+			__u32 tag_field;
+		} delete_addr_entry;
+		struct {
+			__u8 unique_id[8];
+		} create_destroy_addr;
+	} data;
+}__attribute__ ((packed));
+
+#define QETH_IOC_MAGIC 0x22
+#define QETH_IOCPROC_OSAEINTERFACES _IOWR(QETH_IOC_MAGIC, 1, arg)
+#define QETH_IOCPROC_INTERFACECHANGES _IOWR(QETH_IOC_MAGIC, 2, arg)
+
+#define SNMP_QUERY_CARD_INFO 0x00000002L
+#define SNMP_REGISETER_MIB   0x00000004L
+#define SNMP_GET_OID         0x00000010L
+#define SNMP_SET_OID         0x00000011L
+#define SNMP_GET_NEXT_OID    0x00000012L
+#define SNMP_QUERY_ALERTS    0x00000020L
+#define SNMP_SET_TRAP        0x00000021L
+
+
+#define ARP_DATA_SIZE 3968
+#define ARP_FLUSH -3
+#define ARP_RETURNCODE_NOARPDATA -2
+#define ARP_RETURNCODE_ERROR -1
+#define ARP_RETURNCODE_SUCCESS 0
+#define ARP_RETURNCODE_LASTREPLY 1
+
+#define SNMP_BASE_CMDLENGTH 44
+#define SNMP_SETADP_CMDLENGTH 16
+#define SNMP_REQUEST_DATA_OFFSET 16
+
+struct snmp_ipa_setadp_cmd {
+	__u32 supp_hw_cmds;
+	__u32 reserved1;
+	__u16 cmdlength;
+	__u16 reserved2;
+	__u32 command_code;
+	__u16 return_code;
+	__u8 frames_used_total;
+	__u8 frame_seq_no;
+	__u32 reserved3;
+	__u8 snmp_token[16];
+	union {
+		struct {
+			__u32 snmp_request;
+			__u32 snmp_interface;
+			__u32 snmp_returncode;
+			__u32 snmp_firmwarelevel;
+			__u32 snmp_seqno;
+			__u8 snmp_data[ARP_DATA_SIZE];
+		} snmp_subcommand;
+	} data;
+}__attribute__ ((packed));
+
+
+struct arp_cmd {
+	__u8 command;
+	__u8 initiator;
+	__u16 seq_no;
+	__u16 return_code;
+	__u8 adapter_type;
+	__u8 rel_adapter_no;
+	__u8 prim_version_no;
+	__u8 param_count;
+	__u16 prot_version;
+	__u32 ipa_supported;
+	__u32 ipa_enabled;
+	union {
+		struct {
+			__u32 assist_no;
+			__u16 length;
+			__u16 command_code;
+			__u16 return_code;
+			__u8 number_of_replies;
+			__u8 seq_no;
+			union {
+				struct {
+					__u16 tcpip_requestbitmask;
+					__u16 osa_setbitmask;
+					__u32 number_of_entries;
+					__u8 arp_data[ARP_DATA_SIZE];
+				} queryarp_data;
+			} data;
+		} setassparms;
+                struct snmp_ipa_setadp_cmd setadapterparms; 
+	} data;
+}__attribute__ ((packed));
+
+
+
+#define IPA_PDU_HEADER_SIZE 0x40
+#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e)
+#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26)
+#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer+0x2a)
+#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer+0x3a)
+
+extern unsigned char IPA_PDU_HEADER[];
+
+#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer+0x2c)
+
+#define PDU_ENCAPSULATION(buffer) \
+	(buffer+ \
+	 *(buffer+ (*(buffer+0x0b))+ *(buffer+*(buffer+0x0b)+0x11) +0x07))
+
+#define IS_IPA(buffer) ((buffer) && ( *(buffer+ ((*(buffer+0x0b))+4) )==0xc1) )
+
+#define IS_IPA_REPLY(buffer) ( (buffer) && ( (*(PDU_ENCAPSULATION(buffer)+1))==INITIATOR_HOST ) )
+
+#define CCW_NOP_CMD 0x03
+#define CCW_NOP_COUNT 1
+
+extern unsigned char WRITE_CCW[];
+
+extern unsigned char READ_CCW[];
+
+#endif /* __QETH_MPC_H__ */
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -urN linux-2.5.73-bk9/drivers/usb/core/hcd-pci.c linux-2.5.73-bk10/drivers/usb/core/hcd-pci.c
--- linux-2.5.73-bk9/drivers/usb/core/hcd-pci.c	2003-06-22 11:32:45.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/core/hcd-pci.c	2003-07-02 04:57:32.000000000 -0700
@@ -38,6 +38,14 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void hcd_pci_release(struct usb_bus *bus)
+{
+	struct usb_hcd *hcd = bus->hcpriv;
+
+	if (hcd)
+		hcd->driver->hcd_free(hcd);
+}
+
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -172,6 +180,7 @@
 	usb_bus_init (&hcd->self);
 	hcd->self.op = &usb_hcd_operations;
 	hcd->self.hcpriv = (void *) hcd;
+	hcd->self.release = &hcd_pci_release;
 
 	INIT_LIST_HEAD (&hcd->dev_list);
 
@@ -234,13 +243,6 @@
 	}
 
 	usb_deregister_bus (&hcd->self);
-	if (atomic_read (&hcd->self.refcnt) != 1) {
-		dev_warn (hcd->controller,
-			"dangling refs (%d) to bus %d!\n",
-			atomic_read (&hcd->self.refcnt) - 1,
-			hcd->self.busnum);
-	}
-	hcd->driver->hcd_free (hcd);
 }
 EXPORT_SYMBOL (usb_hcd_pci_remove);
 
diff -urN linux-2.5.73-bk9/drivers/usb/core/hcd.c linux-2.5.73-bk10/drivers/usb/core/hcd.c
--- linux-2.5.73-bk9/drivers/usb/core/hcd.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/core/hcd.c	2003-07-02 04:57:32.000000000 -0700
@@ -557,20 +557,52 @@
 /*-------------------------------------------------------------------------*/
 
 /* exported only within usbcore */
-void usb_bus_get (struct usb_bus *bus)
+struct usb_bus *usb_bus_get (struct usb_bus *bus)
 {
-	atomic_inc (&bus->refcnt);
+	struct class_device *tmp;
+
+	if (!bus)
+		return NULL;
+
+	tmp = class_device_get(&bus->class_dev);
+	if (tmp)        
+		return to_usb_bus(tmp);
+	else
+		return NULL;
 }
 
 /* exported only within usbcore */
 void usb_bus_put (struct usb_bus *bus)
 {
-	if (atomic_dec_and_test (&bus->refcnt))
-		kfree (bus);
+	if (bus)
+		class_device_put(&bus->class_dev);
 }
 
 /*-------------------------------------------------------------------------*/
 
+static void usb_host_release(struct class_device *class_dev)
+{
+	struct usb_bus *bus = to_usb_bus(class_dev);
+
+	if (bus->release)
+		bus->release(bus);
+}
+
+static struct class usb_host_class = {
+	.name		= "usb_host",
+	.release	= &usb_host_release,
+};
+
+void usb_host_init(void)
+{
+	class_register(&usb_host_class);
+}
+
+void usb_host_cleanup(void)
+{
+	class_unregister(&usb_host_class);
+}
+
 /**
  * usb_bus_init - shared initialization code
  * @bus: the bus structure being initialized
@@ -592,8 +624,6 @@
 	bus->bandwidth_isoc_reqs = 0;
 
 	INIT_LIST_HEAD (&bus->bus_list);
-
-	atomic_set (&bus->refcnt, 1);
 }
 EXPORT_SYMBOL (usb_bus_init);
 
@@ -607,7 +637,7 @@
  *
  * If no memory is available, NULL is returned.
  *
- * The caller should call usb_free_bus() when it is finished with the structure.
+ * The caller should call usb_put_bus() when it is finished with the structure.
  */
 struct usb_bus *usb_alloc_bus (struct usb_operations *op)
 {
@@ -616,32 +646,13 @@
 	bus = kmalloc (sizeof *bus, GFP_KERNEL);
 	if (!bus)
 		return NULL;
+	memset(bus, 0, sizeof(struct usb_bus));
 	usb_bus_init (bus);
 	bus->op = op;
 	return bus;
 }
 EXPORT_SYMBOL (usb_alloc_bus);
 
-/**
- * usb_free_bus - frees the memory used by a bus structure
- * @bus: pointer to the bus to free
- *
- * To be invoked by a HCD, only as the last step of decoupling from
- * hardware.  It is an error to call this if the reference count is
- * anything but one.  That would indicate that some system component
- * did not correctly shut down, and thought the hardware was still
- * accessible.
- */
-void usb_free_bus (struct usb_bus *bus)
-{
-	if (!bus)
-		return;
-	if (atomic_read (&bus->refcnt) != 1)
-		err ("usb_free_bus #%d, count != 1", bus->busnum);
-	usb_bus_put (bus);
-}
-EXPORT_SYMBOL (usb_free_bus);
-
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -652,9 +663,10 @@
  * Assigns a bus number, and links the controller into usbcore data
  * structures so that it can be seen by scanning the bus list.
  */
-void usb_register_bus(struct usb_bus *bus)
+int usb_register_bus(struct usb_bus *bus)
 {
 	int busnum;
+	int retval;
 
 	down (&usb_bus_list_lock);
 	busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
@@ -664,15 +676,24 @@
 	} else
 		warn ("too many buses");
 
-	usb_bus_get (bus);
+	snprintf(bus->class_dev.class_id, BUS_ID_SIZE, "usb%d", busnum);
+	bus->class_dev.class = &usb_host_class;
+	bus->class_dev.dev = bus->controller;
+	retval = class_device_register(&bus->class_dev);
+	if (retval) {
+		clear_bit(busnum, busmap.busmap);
+		up(&usb_bus_list_lock);
+		return retval;
+	}
 
-	/* Add it to the list of buses */
+	/* Add it to the local list of buses */
 	list_add (&bus->bus_list, &usb_bus_list);
 	up (&usb_bus_list_lock);
 
 	usbfs_add_bus (bus);
 
 	dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
+	return 0;
 }
 EXPORT_SYMBOL (usb_register_bus);
 
@@ -701,7 +722,7 @@
 
 	clear_bit (bus->busnum, busmap.busmap);
 
-	usb_bus_put (bus);
+	class_device_unregister(&bus->class_dev);
 }
 EXPORT_SYMBOL (usb_deregister_bus);
 
diff -urN linux-2.5.73-bk9/drivers/usb/core/hcd.h linux-2.5.73-bk10/drivers/usb/core/hcd.h
--- linux-2.5.73-bk9/drivers/usb/core/hcd.h	2003-06-22 11:32:40.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/core/hcd.h	2003-07-02 04:57:32.000000000 -0700
@@ -347,9 +347,8 @@
 /*-------------------------------------------------------------------------*/
 
 extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
-extern void usb_free_bus (struct usb_bus *);
 
-extern void usb_register_bus (struct usb_bus *);
+extern int usb_register_bus (struct usb_bus *);
 extern void usb_deregister_bus (struct usb_bus *);
 
 extern int usb_register_root_hub (struct usb_device *usb_dev,
@@ -369,7 +368,7 @@
 extern struct list_head usb_bus_list;
 extern struct semaphore usb_bus_list_lock;
 
-extern void usb_bus_get (struct usb_bus *bus);
+extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
 extern void usb_bus_put (struct usb_bus *bus);
 
 extern int usb_find_interface_driver (struct usb_device *dev,
diff -urN linux-2.5.73-bk9/drivers/usb/core/usb.c linux-2.5.73-bk10/drivers/usb/core/usb.c
--- linux-2.5.73-bk9/drivers/usb/core/usb.c	2003-06-22 11:32:46.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/core/usb.c	2003-07-02 04:57:32.000000000 -0700
@@ -54,6 +54,8 @@
 extern void usb_hub_cleanup(void);
 extern int usb_major_init(void);
 extern void usb_major_cleanup(void);
+extern int usb_host_init(void);
+extern void usb_host_cleanup(void);
 
 
 int nousb;		/* Disable USB when built into kernel image */
@@ -652,11 +654,15 @@
 
 	memset(dev, 0, sizeof(*dev));
 
+	bus = usb_bus_get(bus);
+	if (!bus) {
+		kfree(dev);
+		return NULL;
+	}
+
 	device_initialize(&dev->dev);
 	dev->state = USB_STATE_ATTACHED;
 
-	usb_bus_get(bus);
-
 	if (!parent)
 		dev->devpath [0] = '0';
 	dev->bus = bus;
@@ -1531,6 +1537,7 @@
 	}
 
 	bus_register(&usb_bus_type);
+	usb_host_init();
 	usb_major_init();
 	usbfs_init();
 	usb_hub_init();
@@ -1553,6 +1560,7 @@
 	usb_major_cleanup();
 	usbfs_cleanup();
 	usb_hub_cleanup();
+	usb_host_cleanup();
 	bus_unregister(&usb_bus_type);
 }
 
diff -urN linux-2.5.73-bk9/drivers/usb/host/ehci-dbg.c linux-2.5.73-bk10/drivers/usb/host/ehci-dbg.c
--- linux-2.5.73-bk9/drivers/usb/host/ehci-dbg.c	2003-06-22 11:33:08.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/host/ehci-dbg.c	2003-07-02 04:57:32.000000000 -0700
@@ -392,9 +392,10 @@
 }
 
 static ssize_t
-show_async (struct device *dev, char *buf)
+show_async (struct class_device *class_dev, char *buf)
 {
-	struct pci_dev		*pdev;
+	struct usb_bus		*bus;
+	struct usb_hcd		*hcd;
 	struct ehci_hcd		*ehci;
 	unsigned long		flags;
 	unsigned		temp, size;
@@ -403,8 +404,9 @@
 
 	*buf = 0;
 
-	pdev = container_of (dev, struct pci_dev, dev);
-	ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
+	bus = to_usb_bus(class_dev);
+	hcd = bus->hcpriv;
+	ehci = hcd_to_ehci (hcd);
 	next = buf;
 	size = PAGE_SIZE;
 
@@ -427,14 +429,15 @@
 
 	return strlen (buf);
 }
-static DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
+static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
 
 #define DBG_SCHED_LIMIT 64
 
 static ssize_t
-show_periodic (struct device *dev, char *buf)
+show_periodic (struct class_device *class_dev, char *buf)
 {
-	struct pci_dev		*pdev;
+	struct usb_bus		*bus;
+	struct usb_hcd		*hcd;
 	struct ehci_hcd		*ehci;
 	unsigned long		flags;
 	union ehci_shadow	p, *seen;
@@ -446,8 +449,9 @@
 		return 0;
 	seen_count = 0;
 
-	pdev = container_of (dev, struct pci_dev, dev);
-	ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
+	bus = to_usb_bus(class_dev);
+	hcd = bus->hcpriv;
+	ehci = hcd_to_ehci (hcd);
 	next = buf;
 	size = PAGE_SIZE;
 
@@ -535,14 +539,15 @@
 
 	return PAGE_SIZE - size;
 }
-static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
+static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
 
 #undef DBG_SCHED_LIMIT
 
 static ssize_t
-show_registers (struct device *dev, char *buf)
+show_registers (struct class_device *class_dev, char *buf)
 {
-	struct pci_dev		*pdev;
+	struct usb_bus		*bus;
+	struct usb_hcd		*hcd;
 	struct ehci_hcd		*ehci;
 	unsigned long		flags;
 	unsigned		temp, size, i;
@@ -550,9 +555,9 @@
 	static char		fmt [] = "%*s\n";
 	static char		label [] = "";
 
-	pdev = container_of (dev, struct pci_dev, dev);
-	ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
-
+	bus = to_usb_bus(class_dev);
+	hcd = bus->hcpriv;
+	ehci = hcd_to_ehci (hcd);
 	next = buf;
 	size = PAGE_SIZE;
 
@@ -562,7 +567,7 @@
 	i = readw (&ehci->caps->hci_version);
 	temp = snprintf (next, size,
 		"%s\nEHCI %x.%02x, hcd state %d (driver " DRIVER_VERSION ")\n",
-		pdev->dev.name,
+		hcd->pdev->dev.name,
 		i >> 8, i & 0x0ff, ehci->hcd.state);
 	size -= temp;
 	next += temp;
@@ -636,20 +641,20 @@
 
 	return PAGE_SIZE - size;
 }
-static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
+static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 
 static inline void create_debug_files (struct ehci_hcd *bus)
 {
-	device_create_file (&bus->hcd.pdev->dev, &dev_attr_async);
-	device_create_file (&bus->hcd.pdev->dev, &dev_attr_periodic);
-	device_create_file (&bus->hcd.pdev->dev, &dev_attr_registers);
+	class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_async);
+	class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
+	class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
 }
 
 static inline void remove_debug_files (struct ehci_hcd *bus)
 {
-	device_remove_file (&bus->hcd.pdev->dev, &dev_attr_async);
-	device_remove_file (&bus->hcd.pdev->dev, &dev_attr_periodic);
-	device_remove_file (&bus->hcd.pdev->dev, &dev_attr_registers);
+	class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_async);
+	class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
+	class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
 }
 
 #endif /* STUB_DEBUG_FILES */
diff -urN linux-2.5.73-bk9/drivers/usb/host/hc_sl811.c linux-2.5.73-bk10/drivers/usb/host/hc_sl811.c
--- linux-2.5.73-bk9/drivers/usb/host/hc_sl811.c	2003-06-22 11:33:03.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/host/hc_sl811.c	2003-07-02 04:57:32.000000000 -0700
@@ -1205,7 +1205,7 @@
 	}
 
 	usb_deregister_bus (hci->bus);
-	usb_free_bus (hci->bus);
+	usb_put_bus (hci->bus);
 
 	list_del_init (&hci->hci_hcd_list);
 
diff -urN linux-2.5.73-bk9/drivers/usb/host/ohci-dbg.c linux-2.5.73-bk10/drivers/usb/host/ohci-dbg.c
--- linux-2.5.73-bk9/drivers/usb/host/ohci-dbg.c	2003-06-22 11:33:15.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/host/ohci-dbg.c	2003-07-02 04:57:32.000000000 -0700
@@ -466,13 +466,17 @@
 }
 
 static ssize_t
-show_async (struct device *dev, char *buf)
+show_async (struct class_device *class_dev, char *buf)
 {
+	struct usb_bus		*bus;
+	struct usb_hcd		*hcd;
 	struct ohci_hcd		*ohci;
 	size_t			temp;
 	unsigned long		flags;
 
-	ohci = dev_to_ohci(dev);
+	bus = to_usb_bus(class_dev);
+	hcd = bus->hcpriv;
+	ohci = hcd_to_ohci(hcd);
 
 	/* display control and bulk lists together, for simplicity */
 	spin_lock_irqsave (&ohci->lock, flags);
@@ -482,14 +486,16 @@
 
 	return temp;
 }
-static DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
+static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
 
 
 #define DBG_SCHED_LIMIT 64
 
 static ssize_t
-show_periodic (struct device *dev, char *buf)
+show_periodic (struct class_device *class_dev, char *buf)
 {
+	struct usb_bus		*bus;
+	struct usb_hcd		*hcd;
 	struct ohci_hcd		*ohci;
 	struct ed		**seen, *ed;
 	unsigned long		flags;
@@ -501,7 +507,9 @@
 		return 0;
 	seen_count = 0;
 
-	ohci = dev_to_ohci(dev);
+	bus = to_usb_bus(class_dev);
+	hcd = bus->hcpriv;
+	ohci = hcd_to_ohci(hcd);
 	next = buf;
 	size = PAGE_SIZE;
 
@@ -573,14 +581,16 @@
 
 	return PAGE_SIZE - size;
 }
-static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
+static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
 
 
 #undef DBG_SCHED_LIMIT
 
 static ssize_t
-show_registers (struct device *dev, char *buf)
+show_registers (struct class_device *class_dev, char *buf)
 {
+	struct usb_bus		*bus;
+	struct usb_hcd		*hcd;
 	struct ohci_hcd		*ohci;
 	struct ohci_regs	*regs;
 	unsigned long		flags;
@@ -588,7 +598,9 @@
 	char			*next;
 	u32			rdata;
 
-	ohci = dev_to_ohci(dev);
+	bus = to_usb_bus(class_dev);
+	hcd = bus->hcpriv;
+	ohci = hcd_to_ohci(hcd);
 	regs = ohci->regs;
 	next = buf;
 	size = PAGE_SIZE;
@@ -642,22 +654,22 @@
 
 	return PAGE_SIZE - size;
 }
-static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
+static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 
 
 static inline void create_debug_files (struct ohci_hcd *bus)
 {
-	device_create_file (bus->hcd.controller, &dev_attr_async);
-	device_create_file (bus->hcd.controller, &dev_attr_periodic);
-	device_create_file (bus->hcd.controller, &dev_attr_registers);
+	class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_async);
+	class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
+	class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
 	ohci_dbg (bus, "created debug files\n");
 }
 
 static inline void remove_debug_files (struct ohci_hcd *bus)
 {
-	device_remove_file (bus->hcd.controller, &dev_attr_async);
-	device_remove_file (bus->hcd.controller, &dev_attr_periodic);
-	device_remove_file (bus->hcd.controller, &dev_attr_registers);
+	class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_async);
+	class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
+	class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
 }
 
 #endif
diff -urN linux-2.5.73-bk9/drivers/usb/host/uhci-hcd.c linux-2.5.73-bk10/drivers/usb/host/uhci-hcd.c
--- linux-2.5.73-bk9/drivers/usb/host/uhci-hcd.c	2003-06-22 11:33:16.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/host/uhci-hcd.c	2003-07-02 04:57:32.000000000 -0700
@@ -1208,6 +1208,13 @@
 	    			uhci_packetout(td_token(td)));
 
 err:
+	/* 
+	 * Enable this chunk of code if you want to see some more debugging.
+	 * But be careful, it has the tendancy to starve out khubd and prevent
+	 * disconnects from happening successfully if you have a slow debug
+	 * log interface (like a serial console.
+	 */
+#if 0
 	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
 		/* Some debugging code */
 		dbg("uhci_result_common() failed with status %x", status);
@@ -1219,7 +1226,7 @@
 			lprintk(errbuf);
 		}
 	}
-
+#endif
 	return ret;
 }
 
diff -urN linux-2.5.73-bk9/drivers/usb/net/usbnet.c linux-2.5.73-bk10/drivers/usb/net/usbnet.c
--- linux-2.5.73-bk9/drivers/usb/net/usbnet.c	2003-06-22 11:32:55.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/net/usbnet.c	2003-07-02 04:57:33.000000000 -0700
@@ -1701,6 +1701,15 @@
 
 	.in = 1, .out = 2,
 };
+static const struct driver_info zaurus_slc700_info = {
+    .description =  "Sharp Zaurus SL-C700",
+    .flags =    FLAG_FRAMING_Z,
+    .check_connect = always_connected,
+    .tx_fixup =     zaurus_tx_fixup,
+
+    .in = 1, .out = 2,
+};
+
 
 // SL-5600 and C-700 are PXA based; should resemble A300
 
@@ -2751,6 +2760,15 @@
 	.bInterfaceSubClass	= 0x0a,
 	.bInterfaceProtocol	= 0x00,
 	.driver_info =  (unsigned long) &zaurus_slb500_info,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+	          | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor       = 0x04DD,
+	.idProduct      = 0x8007,
+	.bInterfaceClass    = 0x02,
+	.bInterfaceSubClass = 0x0a,
+	.bInterfaceProtocol = 0x00,
+	.driver_info =  (unsigned long) &zaurus_slc700_info,
 },
 #endif
 
diff -urN linux-2.5.73-bk9/drivers/usb/storage/scsiglue.c linux-2.5.73-bk10/drivers/usb/storage/scsiglue.c
--- linux-2.5.73-bk9/drivers/usb/storage/scsiglue.c	2003-06-22 11:32:45.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/storage/scsiglue.c	2003-07-02 04:57:33.000000000 -0700
@@ -166,7 +166,11 @@
 
 	/* lock the device pointers and do the reset */
 	down(&(us->dev_semaphore));
-	result = us->transport_reset(us);
+	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+		result = FAILED;
+		US_DEBUGP("No reset during disconnect\n");
+	} else
+		result = us->transport_reset(us);
 	up(&(us->dev_semaphore));
 
 	/* lock access to the state and clear it */
@@ -202,7 +206,7 @@
 	down(&(us->dev_semaphore));
 	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
 		result = -EIO;
-		US_DEBUGP("Attempt to reset during disconnect\n");
+		US_DEBUGP("No reset during disconnect\n");
 	} else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {
 		result = -EBUSY;
 		US_DEBUGP("Refusing to reset a multi-interface device\n");
diff -urN linux-2.5.73-bk9/drivers/usb/storage/transport.c linux-2.5.73-bk10/drivers/usb/storage/transport.c
--- linux-2.5.73-bk9/drivers/usb/storage/transport.c	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/storage/transport.c	2003-07-02 04:57:33.000000000 -0700
@@ -147,9 +147,19 @@
 	us->current_urb->context = &urb_done;
 	us->current_urb->actual_length = 0;
 	us->current_urb->error_count = 0;
-	us->current_urb->transfer_flags = URB_ASYNC_UNLINK;
 	us->current_urb->status = 0;
 
+	/* we assume that if transfer_buffer isn't us->iobuf then it
+	 * hasn't been mapped for DMA.  Yes, this is clunky, but it's
+	 * easier than always having the caller tell us whether the
+	 * transfer buffer has already been mapped. */
+	us->current_urb->transfer_flags =
+			URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP;
+	if (us->current_urb->transfer_buffer == us->iobuf)
+		us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	us->current_urb->transfer_dma = us->iobuf_dma;
+	us->current_urb->setup_dma = us->cr_dma;
+
 	/* submit the URB */
 	status = usb_submit_urb(us->current_urb, GFP_NOIO);
 	if (status) {
@@ -207,15 +217,15 @@
 			value, index, size);
 
 	/* fill in the devrequest structure */
-	us->dr->bRequestType = requesttype;
-	us->dr->bRequest = request;
-	us->dr->wValue = cpu_to_le16(value);
-	us->dr->wIndex = cpu_to_le16(index);
-	us->dr->wLength = cpu_to_le16(size);
+	us->cr->bRequestType = requesttype;
+	us->cr->bRequest = request;
+	us->cr->wValue = cpu_to_le16(value);
+	us->cr->wIndex = cpu_to_le16(index);
+	us->cr->wLength = cpu_to_le16(size);
 
 	/* fill and submit the URB */
 	usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, 
-			 (unsigned char*) us->dr, data, size, 
+			 (unsigned char*) us->cr, data, size, 
 			 usb_stor_blocking_completion, NULL);
 	status = usb_stor_msg_common(us, timeout);
 
@@ -346,15 +356,15 @@
 			value, index, size);
 
 	/* fill in the devrequest structure */
-	us->dr->bRequestType = requesttype;
-	us->dr->bRequest = request;
-	us->dr->wValue = cpu_to_le16(value);
-	us->dr->wIndex = cpu_to_le16(index);
-	us->dr->wLength = cpu_to_le16(size);
+	us->cr->bRequestType = requesttype;
+	us->cr->bRequest = request;
+	us->cr->wValue = cpu_to_le16(value);
+	us->cr->wIndex = cpu_to_le16(index);
+	us->cr->wLength = cpu_to_le16(size);
 
 	/* fill and submit the URB */
 	usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, 
-			 (unsigned char*) us->dr, data, size, 
+			 (unsigned char*) us->cr, data, size, 
 			 usb_stor_blocking_completion, NULL);
 	result = usb_stor_msg_common(us, 0);
 
@@ -786,9 +796,9 @@
 	}
 
 	/* STATUS STAGE */
-	result = usb_stor_intr_transfer(us, us->irqdata, sizeof(us->irqdata));
+	result = usb_stor_intr_transfer(us, us->iobuf, 2);
 	US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", 
-			us->irqdata[0], us->irqdata[1]);
+			us->iobuf[0], us->iobuf[1]);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
@@ -804,7 +814,7 @@
 		    srb->cmnd[0] == INQUIRY)
 			return USB_STOR_TRANSPORT_GOOD;
 		else {
-			if (us->irqdata[0])
+			if (us->iobuf[0])
 				return USB_STOR_TRANSPORT_FAILED;
 			else
 				return USB_STOR_TRANSPORT_GOOD;
@@ -815,13 +825,13 @@
 	 * The first byte should always be a 0x0
 	 * The second byte & 0x0F should be 0x0 for good, otherwise error 
 	 */
-	if (us->irqdata[0]) {
+	if (us->iobuf[0]) {
 		US_DEBUGP("CBI IRQ data showed reserved bType %d\n",
-				us->irqdata[0]);
+				us->iobuf[0]);
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
-	switch (us->irqdata[1] & 0x0F) {
+	switch (us->iobuf[1] & 0x0F) {
 		case 0x00: 
 			return USB_STOR_TRANSPORT_GOOD;
 		case 0x01: 
@@ -889,7 +899,6 @@
 /* Determine what the maximum LUN supported is */
 int usb_stor_Bulk_max_lun(struct us_data *us)
 {
-	unsigned char data;
 	int result;
 
 	/* issue the command */
@@ -897,14 +906,14 @@
 				 US_BULK_GET_MAX_LUN, 
 				 USB_DIR_IN | USB_TYPE_CLASS | 
 				 USB_RECIP_INTERFACE,
-				 0, us->ifnum, &data, sizeof(data), HZ);
+				 0, us->ifnum, us->iobuf, 1, HZ);
 
 	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
-		  result, data);
+		  result, us->iobuf[0]);
 
 	/* if we have a successful request, return the result */
 	if (result == 1)
-		return data;
+		return us->iobuf[0];
 
 	/* return the default -- no LUNs */
 	return 0;
@@ -912,33 +921,34 @@
 
 int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
 {
-	struct bulk_cb_wrap bcb;
-	struct bulk_cs_wrap bcs;
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
 	unsigned int transfer_length = srb->request_bufflen;
 	int result;
 	int fake_sense = 0;
 
 	/* set up the command wrapper */
-	bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb.DataTransferLength = cpu_to_le32(transfer_length);
-	bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
-	bcb.Tag = srb->serial_number;
-	bcb.Lun = srb->device->lun;
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = cpu_to_le32(transfer_length);
+	bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
+	bcb->Tag = srb->serial_number;
+	bcb->Lun = srb->device->lun;
 	if (us->flags & US_FL_SCM_MULT_TARG)
-		bcb.Lun |= srb->device->id << 4;
-	bcb.Length = srb->cmd_len;
+		bcb->Lun |= srb->device->id << 4;
+	bcb->Length = srb->cmd_len;
 
 	/* copy the command payload */
-	memset(bcb.CDB, 0, sizeof(bcb.CDB));
-	memcpy(bcb.CDB, srb->cmnd, bcb.Length);
+	memset(bcb->CDB, 0, sizeof(bcb->CDB));
+	memcpy(bcb->CDB, srb->cmnd, bcb->Length);
 
 	/* send it to out endpoint */
 	US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
-		  le32_to_cpu(bcb.Signature), bcb.Tag,
-		  (bcb.Lun >> 4), (bcb.Lun & 0x0F), 
-		  le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
+			le32_to_cpu(bcb->Signature), bcb->Tag,
+			(bcb->Lun >> 4), (bcb->Lun & 0x0F), 
+			le32_to_cpu(bcb->DataTransferLength),
+			bcb->Flags, bcb->Length);
 	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-				&bcb, US_BULK_CB_WRAP_LEN, NULL);
+				bcb, US_BULK_CB_WRAP_LEN, NULL);
 	US_DEBUGP("Bulk command transfer result=%d\n", result);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
@@ -972,7 +982,7 @@
 	/* get CSW for device status */
 	US_DEBUGP("Attempting to get CSW...\n");
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-				&bcs, US_BULK_CS_WRAP_LEN, NULL);
+				bcs, US_BULK_CS_WRAP_LEN, NULL);
 
 	/* did the attempt to read the CSW fail? */
 	if (result == USB_STOR_XFER_STALLED) {
@@ -980,7 +990,7 @@
 		/* get the status again */
 		US_DEBUGP("Attempting to get CSW (2nd try)...\n");
 		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-				&bcs, US_BULK_CS_WRAP_LEN, NULL);
+				bcs, US_BULK_CS_WRAP_LEN, NULL);
 	}
 
 	/* if we still have a failure at this point, we're in trouble */
@@ -990,17 +1000,18 @@
 
 	/* check bulk status */
 	US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
-		  le32_to_cpu(bcs.Signature), bcs.Tag, 
-		  bcs.Residue, bcs.Status);
-	if ((bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs.Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || 
-	    bcs.Tag != bcb.Tag || 
-	    bcs.Status > US_BULK_STAT_PHASE) {
+			le32_to_cpu(bcs->Signature), bcs->Tag, 
+			bcs->Residue, bcs->Status);
+	if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
+		    bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
+			bcs->Tag != srb->serial_number || 
+			bcs->Status > US_BULK_STAT_PHASE) {
 		US_DEBUGP("Bulk logical error\n");
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
 	/* based on the status code, we report good or bad */
-	switch (bcs.Status) {
+	switch (bcs->Status) {
 		case US_BULK_STAT_OK:
 			/* device babbled -- return fake sense data */
 			if (fake_sense) {
@@ -1065,6 +1076,10 @@
 	schedule_timeout(HZ*6);
 	set_current_state(TASK_RUNNING);
 	down(&us->dev_semaphore);
+	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+		US_DEBUGP("Reset interrupted by disconnect\n");
+		return FAILED;
+	}
 
 	US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
 	result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
@@ -1083,18 +1098,18 @@
 
 /* This issues a CB[I] Reset to the device in question
  */
+#define CB_RESET_CMD_SIZE	12
+
 int usb_stor_CB_reset(struct us_data *us)
 {
-	unsigned char cmd[12];
-
-	US_DEBUGP("CB_reset() called\n");
+	US_DEBUGP("%s called\n", __FUNCTION__);
 
-	memset(cmd, 0xFF, sizeof(cmd));
-	cmd[0] = SEND_DIAGNOSTIC;
-	cmd[1] = 4;
+	memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
+	us->iobuf[0] = SEND_DIAGNOSTIC;
+	us->iobuf[1] = 4;
 	return usb_stor_reset_common(us, US_CBI_ADSC, 
 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-				 0, us->ifnum, cmd, sizeof(cmd));
+				 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE);
 }
 
 /* This issues a Bulk-only Reset to the device in question, including
@@ -1102,7 +1117,7 @@
  */
 int usb_stor_Bulk_reset(struct us_data *us)
 {
-	US_DEBUGP("Bulk reset requested\n");
+	US_DEBUGP("%s called\n", __FUNCTION__);
 
 	return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, 
 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
diff -urN linux-2.5.73-bk9/drivers/usb/storage/unusual_devs.h linux-2.5.73-bk10/drivers/usb/storage/unusual_devs.h
--- linux-2.5.73-bk9/drivers/usb/storage/unusual_devs.h	2003-07-02 04:57:16.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/storage/unusual_devs.h	2003-07-02 04:57:33.000000000 -0700
@@ -252,6 +252,14 @@
 		US_SC_UFI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
+#ifdef CONFIG_USB_STORAGE_ISD200
+UNUSUAL_DEV(  0x054c, 0x002b, 0x0100, 0x0110,
+		"Sony",
+		"Portable USB Harddrive V2",
+		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		0 ),
+#endif
+
 UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100, 
 		"Sony",
 		"Memorystick MSAC-US1",
@@ -271,6 +279,12 @@
 		US_SC_UFI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 		
+UNUSUAL_DEV(  0x054c, 0x0069, 0x0000, 0x9999,
+		"Sony",
+		"Memorystick MSC-U03",
+		US_SC_UFI, US_PR_CB, NULL,
+		US_FL_SINGLE_LUN ),
+
 /* Submitted by Nathan Babb <nathan@lexi.com> */
 UNUSUAL_DEV(  0x054c, 0x006d, 0x0000, 0x9999,
 		"Sony",
@@ -295,26 +309,6 @@
 		"USB Hard Disk",
 		US_SC_RBC, US_PR_CB, NULL, 0 ), 
 
-/* This Pentax still camera is not conformant
- * to the USB storage specification: -
- * - It does not like the INQUIRY command. So we must handle this command
- *   of the SCSI layer ourselves.
- * Tested on Rev. 10.00 (0x1000)
- * Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
- */
-UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
-                "Pentax",
-                "Optio 2/3/400",
-                US_SC_DEVICE, US_PR_DEVICE, NULL,
-                US_FL_FIX_INQUIRY ),
-
-/* Submitted by Per Winkvist <per.winkvist@uk.com> */
-UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
-                "Pentax",
-                "Optio S",
-                US_SC_8070, US_PR_CBI, NULL,
-                US_FL_FIX_INQUIRY ),
-
 #ifdef CONFIG_USB_STORAGE_ISD200
 UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
 		"In-System",
@@ -339,12 +333,6 @@
 		"USB Storage Adapter V2",
 		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
 		0 ),
-
-UNUSUAL_DEV(  0x054c, 0x002b, 0x0100, 0x0110,
-		"Sony",
-		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
-		0 ),
 #endif
 
 #ifdef CONFIG_USB_STORAGE_JUMPSHOT
@@ -385,12 +373,6 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
-UNUSUAL_DEV(  0x05e3, 0x0700, 0x0000, 0x9999,
-		"Unknown",
-		"GL641USB based CF Card reader",
-		US_SC_SCSI, US_PR_BULK, NULL,
-		US_FL_FIX_INQUIRY | US_FL_MODE_XLATE),
-
 /* Reported by Hanno Boeck <hanno@gmx.de>
  * Taken from the Lycoris Kernel */
 UNUSUAL_DEV(  0x0636, 0x0003, 0x0000, 0x9999,
@@ -431,7 +413,8 @@
 UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009, 
 		"Sandisk",
 		"ImageMate SDDR-31",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_IGNORE_SER ),
 
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
 		"Sandisk",
@@ -520,13 +503,6 @@
 		"Simple Tech/Datafab CF+SM Reader",
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
 		US_FL_MODE_XLATE ),
-
-/* Submitted by Olaf Hering <olh@suse.de> */
-UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
-		"Datafab Systems, Inc.",
-		"USB to CF + SM Combo (LC1)",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_MODE_XLATE ),
 #endif
 		
 #ifdef CONFIG_USB_STORAGE_SDDR55
@@ -538,6 +514,15 @@
 		US_FL_FIX_INQUIRY ),
 #endif
 
+#ifdef CONFIG_USB_STORAGE_DATAFAB
+/* Submitted by Olaf Hering <olh@suse.de> */
+UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
+		"Datafab Systems, Inc.",
+		"USB to CF + SM Combo (LC1)",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		US_FL_MODE_XLATE ),
+#endif
+
 /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100
  * Only revision 1.13 tested (same for all of the above devices,
  * based on the Datafab DF-UG-07 chip).  Needed for US_FL_FIX_INQUIRY.
@@ -563,6 +548,22 @@
 		US_SC_8070, US_PR_CB, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
+UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
+		"Samsung",
+		"Digimax 410",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY),
+
+/* Aiptek PocketCAM 3Mega
+ * Nicolas DUPEUX <nicolas@dupeux.net> 
+ */
+UNUSUAL_DEV(  0x08ca, 0x2011, 0x0000, 0x9999,
+		"AIPTEK",
+		"PocketCAM 3Mega",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_MODE_XLATE ),
+
 /* aeb */
 UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
 		"Feiya",
@@ -570,13 +571,6 @@
 		US_SC_SCSI, US_PR_BULK, NULL,
 		US_FL_FIX_CAPACITY ),
 
-/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
-UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
-        "Samsung",
-        "Digimax 410",
-        US_SC_SCSI, US_PR_BULK, NULL,
-        US_FL_FIX_INQUIRY),
-                
 UNUSUAL_DEV(  0x097a, 0x0001, 0x0000, 0x0001,
 		"Minds@Work",
 		"Digital Wallet",
@@ -589,22 +583,26 @@
 		US_SC_SCSI, US_PR_BULK, NULL,
 		US_FL_FIX_INQUIRY ),
 
-UNUSUAL_DEV(  0x0a16, 0x8888, 0x0100, 0x0100,
-		"IBM",
-		"IBM USB Memory Key",
-		US_SC_SCSI, US_PR_BULK, NULL,
-		US_FL_FIX_INQUIRY ),
-		
-/* Pentax Optio S digital camera
- * adapted from http://www2.goldfisch.at/knowledge/233
- * (Peter Pilsl <pilsl@goldfisch.at>)
- * by Christoph Weidemann <cweidema@indiana.edu> */
-UNUSUAL_DEV(  0x0a17, 0x0006, 0x0000, 0xffff,
-		"Pentax",
-		"Optio S",
-		US_SC_8070, US_PR_CB, NULL,
-		US_FL_MODE_XLATE|US_FL_FIX_INQUIRY),
+/* This Pentax still camera is not conformant
+ * to the USB storage specification: -
+ * - It does not like the INQUIRY command. So we must handle this command
+ *   of the SCSI layer ourselves.
+ * Tested on Rev. 10.00 (0x1000)
+ * Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
+ */
+UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
+                "Pentax",
+                "Optio 2/3/400",
+                US_SC_DEVICE, US_PR_DEVICE, NULL,
+                US_FL_FIX_INQUIRY ),
 
+/* Submitted by Per Winkvist <per.winkvist@uk.com> */
+UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
+                "Pentax",
+                "Optio S",
+                US_SC_8070, US_PR_CBI, NULL,
+                US_FL_FIX_INQUIRY ),
+		
 #ifdef CONFIG_USB_STORAGE_ISD200
 UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
 		"ATI",
@@ -613,13 +611,6 @@
 		0 ),
 #endif
 
-/* EasyDisk support. Submitted by Stanislav Karchebny <berk@madfire.net> */
-UNUSUAL_DEV(  0x1065, 0x2136, 0x0000, 0x0001,
-		"Global Channel Solutions",
-		"EasyDisk EDxxxx",
-		US_SC_SCSI, US_PR_BULK, NULL,
-		US_FL_MODE_XLATE | US_FL_FIX_INQUIRY ),
-
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
  * Tested on hardware version 1.10.
  * Entry is needed only for the initializer function override.
@@ -648,13 +639,3 @@
 		US_SC_SCSI, US_PR_SDDR55, NULL,
 		US_FL_SINGLE_LUN),
 #endif
-
-/* Aiptek PocketCAM 3Mega
- * Nicolas DUPEUX <nicolas@dupeux.net> 
- */
-UNUSUAL_DEV(  0x08ca, 0x2011, 0x0000, 0x9999,
-	"AIPTEK",
-	"PocketCAM 3Mega",
-	US_SC_SCSI, US_PR_BULK, NULL,
-	US_FL_MODE_XLATE ),
-
diff -urN linux-2.5.73-bk9/drivers/usb/storage/usb.c linux-2.5.73-bk10/drivers/usb/storage/usb.c
--- linux-2.5.73-bk9/drivers/usb/storage/usb.c	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/storage/usb.c	2003-07-02 04:57:33.000000000 -0700
@@ -338,10 +338,16 @@
 		/* lock the device pointers */
 		down(&(us->dev_semaphore));
 
+		/* don't do anything if we are disconnecting */
+		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+			US_DEBUGP("No command during disconnect\n");
+			us->srb->result = DID_BAD_TARGET << 16;
+		}
+
 		/* reject the command if the direction indicator 
 		 * is UNKNOWN
 		 */
-		if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
+		else if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
 			US_DEBUGP("UNKNOWN data direction\n");
 			us->srb->result = DID_ERROR << 16;
 		}
@@ -421,12 +427,44 @@
  * Device probing and disconnecting
  ***********************************************************************/
 
+/* Associate our private data with the USB device */
+static int associate_dev(struct us_data *us, struct usb_interface *intf)
+{
+	US_DEBUGP("-- %s\n", __FUNCTION__);
+
+	/* Fill in the device-related fields */
+	us->pusb_dev = interface_to_usbdev(intf);
+	us->pusb_intf = intf;
+	us->ifnum = intf->altsetting->desc.bInterfaceNumber;
+
+	/* Store our private data in the interface and increment the
+	 * device's reference count */
+	usb_set_intfdata(intf, us);
+	usb_get_dev(us->pusb_dev);
+
+	/* Allocate the device-related DMA-mapped buffers */
+	us->cr = usb_buffer_alloc(us->pusb_dev, sizeof(*us->cr),
+			GFP_KERNEL, &us->cr_dma);
+	if (!us->cr) {
+		US_DEBUGP("usb_ctrlrequest allocation failed\n");
+		return -ENOMEM;
+	}
+
+	us->iobuf = usb_buffer_alloc(us->pusb_dev, US_IOBUF_SIZE,
+			GFP_KERNEL, &us->iobuf_dma);
+	if (!us->iobuf) {
+		US_DEBUGP("I/O buffer allocation failed\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
 /* Get the unusual_devs entries and the string descriptors */
 static void get_device_info(struct us_data *us, int id_index)
 {
 	struct usb_device *dev = us->pusb_dev;
-	struct usb_host_interface *altsetting =
-		&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting];
+	struct usb_interface_descriptor *idesc =
+		&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting].desc;
 	struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
 	struct usb_device_id *id = &storage_usb_ids[id_index];
 
@@ -438,10 +476,10 @@
 	/* Store the entries */
 	us->unusual_dev = unusual_dev;
 	us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
-			altsetting->desc.bInterfaceSubClass :
+			idesc->bInterfaceSubClass :
 			unusual_dev->useProtocol;
 	us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
-			altsetting->desc.bInterfaceProtocol :
+			idesc->bInterfaceProtocol :
 			unusual_dev->useTransport;
 	us->flags = unusual_dev->flags;
 
@@ -455,20 +493,26 @@
 			"an unneeded SubClass entry",
 			"an unneeded Protocol entry",
 			"unneeded SubClass and Protocol entries"};
+		struct usb_device_descriptor *ddesc = &dev->descriptor;
 		int msg = -1;
 
 		if (unusual_dev->useProtocol != US_SC_DEVICE &&
-			us->subclass == altsetting->desc.bInterfaceSubClass)
+			us->subclass == idesc->bInterfaceSubClass)
 			msg += 1;
 		if (unusual_dev->useTransport != US_PR_DEVICE &&
-			us->protocol == altsetting->desc.bInterfaceProtocol)
+			us->protocol == idesc->bInterfaceProtocol)
 			msg += 2;
 		if (msg >= 0)
 			printk(KERN_NOTICE USB_STORAGE "This device "
-				"(%04x,%04x) has %s in unusual_devs.h\n"
+				"(%04x,%04x,%04x S %02x P %02x)"
+				" has %s in unusual_devs.h\n"
 				"   Please send a copy of this message to "
 				"<linux-usb-devel@lists.sourceforge.net>\n",
-				id->idVendor, id->idProduct, msgs[msg]);
+				ddesc->idVendor, ddesc->idProduct,
+				ddesc->bcdDevice,
+				idesc->bInterfaceSubClass,
+				idesc->bInterfaceProtocol,
+				msgs[msg]);
 	}
 
 	/* Read the device's string descriptors */
@@ -485,15 +529,15 @@
 	/* Use the unusual_dev strings if the device didn't provide them */
 	if (strlen(us->vendor) == 0) {
 		if (unusual_dev->vendorName)
-			strncpy(us->vendor, unusual_dev->vendorName,
-				sizeof(us->vendor) - 1);
+			strlcpy(us->vendor, unusual_dev->vendorName,
+				sizeof(us->vendor));
 		else
 			strcpy(us->vendor, "Unknown");
 	}
 	if (strlen(us->product) == 0) {
 		if (unusual_dev->productName)
-			strncpy(us->product, unusual_dev->productName,
-				sizeof(us->product) - 1);
+			strlcpy(us->product, unusual_dev->productName,
+				sizeof(us->product));
 		else
 			strcpy(us->product, "Unknown");
 	}
@@ -714,18 +758,9 @@
 {
 	int p;
 
-	/* Allocate the USB control blocks */
-	US_DEBUGP("Allocating usb_ctrlrequest\n");
-	us->dr = kmalloc(sizeof(*us->dr), GFP_KERNEL);
-	if (!us->dr) {
-		US_DEBUGP("allocation failed\n");
-		return -ENOMEM;
-	}
-
-	US_DEBUGP("Allocating URB\n");
 	us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!us->current_urb) {
-		US_DEBUGP("allocation failed\n");
+		US_DEBUGP("URB allocation failed\n");
 		return -ENOMEM;
 	}
 
@@ -778,8 +813,24 @@
 {
 	US_DEBUGP("-- %s\n", __FUNCTION__);
 	down(&us->dev_semaphore);
+
+	/* Free the device-related DMA-mapped buffers */
+	if (us->cr) {
+		usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
+				us->cr_dma);
+		us->cr = NULL;
+	}
+	if (us->iobuf) {
+		usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf,
+				us->iobuf_dma);
+		us->iobuf = NULL;
+	}
+
+	/* Remove our private data from the interface and decrement the
+	 * device's reference count */
 	usb_set_intfdata(us->pusb_intf, NULL);
 	usb_put_dev(us->pusb_dev);
+
 	us->pusb_dev = NULL;
 	us->pusb_intf = NULL;
 	up(&us->dev_semaphore);
@@ -818,16 +869,11 @@
 		us->extra_destructor(us->extra);
 	}
 
-	/* Destroy the extra data */
-	if (us->extra) {
+	/* Free the extra data and the URB */
+	if (us->extra)
 		kfree(us->extra);
-	}
-
-	/* Free the USB control blocks */
 	if (us->current_urb)
 		usb_free_urb(us->current_urb);
-	if (us->dr)
-		kfree(us->dr);
 
 	/* Free the structure itself */
 	kfree(us);
@@ -857,15 +903,10 @@
 	init_MUTEX_LOCKED(&(us->sema));
 	init_completion(&(us->notify));
 
-	/* Fill in the device-related fields */
-	us->pusb_dev = interface_to_usbdev(intf);
-	us->pusb_intf = intf;
-	us->ifnum = intf->altsetting->desc.bInterfaceNumber;
-
-	/* Store our private data in the interface and increment the
-	 * device's reference count */
-	usb_set_intfdata(intf, us);
-	usb_get_dev(us->pusb_dev);
+	/* Associate the us_data structure with the USB device */
+	result = associate_dev(us, intf);
+	if (result)
+		goto BadDevice;
 
 	/*
 	 * Get the unusual_devs entries and the descriptors
diff -urN linux-2.5.73-bk9/drivers/usb/storage/usb.h linux-2.5.73-bk10/drivers/usb/storage/usb.h
--- linux-2.5.73-bk9/drivers/usb/storage/usb.h	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/storage/usb.h	2003-07-02 04:57:33.000000000 -0700
@@ -71,6 +71,7 @@
 #define US_FL_SINGLE_LUN      0x00000001 /* allow access to only LUN 0	    */
 #define US_FL_MODE_XLATE      0x00000002 /* translate _6 to _10 commands for
 						    Win/MacOS compatibility */
+#define US_FL_IGNORE_SER      0		 /* [no longer used]		    */
 #define US_FL_SCM_MULT_TARG   0x00000020 /* supports multiple targets	    */
 #define US_FL_FIX_INQUIRY     0x00000040 /* INQUIRY response needs fixing   */
 #define US_FL_FIX_CAPACITY    0x00000080 /* READ CAPACITY response too big  */
@@ -92,6 +93,15 @@
 
 #define USB_STOR_STRING_LEN 32
 
+/*
+ * We provide a DMA-mapped I/O buffer for use with small USB transfers.
+ * It turns out that CB[I] needs a 12-byte buffer and Bulk-only needs a
+ * 31-byte buffer.  But Freecom needs a 64-byte buffer, so that's the
+ * size we'll allocate.
+ */
+
+#define US_IOBUF_SIZE		64	/* Size of the DMA-mapped I/O buffer */
+
 typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
 typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
@@ -106,6 +116,7 @@
 	struct semaphore	dev_semaphore;	 /* protect pusb_dev */
 	struct usb_device	*pusb_dev;	 /* this usb_device */
 	struct usb_interface	*pusb_intf;	 /* this interface */
+	struct us_unusual_dev   *unusual_dev;	 /* device-filter entry     */
 	unsigned long		flags;		 /* from filter initially */
 	unsigned int		send_bulk_pipe;	 /* cached pipe values */
 	unsigned int		recv_bulk_pipe;
@@ -139,20 +150,19 @@
 	int			pid;		 /* control thread	 */
 	int			sm_state;	 /* what we are doing	 */
 
-	/* interrupt communications data */
-	unsigned char		irqdata[2];	 /* data from USB IRQ	 */
-
 	/* control and bulk communications data */
-	struct urb		*current_urb;	 /* non-int USB requests */
-	struct usb_ctrlrequest	*dr;		 /* control requests	 */
-	struct usb_sg_request	current_sg;	 /* scatter-gather USB   */
-
-	/* the semaphore for sleeping the control thread */
-	struct semaphore	sema;		 /* to sleep thread on   */
+	struct urb		*current_urb;	 /* USB requests	 */
+	struct usb_ctrlrequest	*cr;		 /* control requests	 */
+	struct usb_sg_request	current_sg;	 /* scatter-gather req.  */
+	unsigned char		*iobuf;		 /* I/O buffer		 */
+	dma_addr_t		cr_dma;		 /* buffer DMA addresses */
+	dma_addr_t		iobuf_dma;
 
 	/* mutual exclusion structures */
+	struct semaphore	sema;		 /* to sleep thread on   */
 	struct completion	notify;		 /* thread begin/end	    */
-	struct us_unusual_dev   *unusual_dev;	 /* If unusual device       */
+
+	/* subdriver information */
 	void			*extra;		 /* Any extra data          */
 	extra_data_destructor	extra_destructor;/* extra data destructor   */
 };
diff -urN linux-2.5.73-bk9/drivers/usb/usb-skeleton.c linux-2.5.73-bk10/drivers/usb/usb-skeleton.c
--- linux-2.5.73-bk9/drivers/usb/usb-skeleton.c	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk10/drivers/usb/usb-skeleton.c	2003-07-02 04:57:33.000000000 -0700
@@ -112,6 +112,7 @@
 	struct completion	write_finished;		/* wait for the write to finish */
 
 	int			open;			/* if the port is open or not */
+	int			present;		/* if the device is not disconnected */
 	struct semaphore	sem;			/* locks this structure */
 };
 
@@ -296,7 +297,7 @@
 
 	dev->open = 0;
 
-	if (dev->udev == NULL) {
+	if (!dev->present) {
 		/* the device was unplugged before the file was released */
 		up (&dev->sem);
 		skel_delete (dev);
@@ -326,7 +327,7 @@
 	down (&dev->sem);
 
 	/* verify that the device wasn't unplugged */
-	if (dev->udev == NULL) {
+	if (!dev->present) {
 		up (&dev->sem);
 		return -ENODEV;
 	}
@@ -382,7 +383,7 @@
 	down (&dev->sem);
 
 	/* verify that the device wasn't unplugged */
-	if (dev->udev == NULL) {
+	if (!dev->present) {
 		retval = -ENODEV;
 		goto exit;
 	}
@@ -452,7 +453,7 @@
 	down (&dev->sem);
 
 	/* verify that the device wasn't unplugged */
-	if (dev->udev == NULL) {
+	if (!dev->present) {
 		up (&dev->sem);
 		return -ENODEV;
 	}
@@ -507,8 +508,6 @@
 	size_t buffer_size;
 	int i;
 	int retval;
-	char name[14];
-
 
 	/* See if the device offered us matches what we can accept */
 	if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) ||
@@ -580,7 +579,7 @@
 			 */
 			buffer_size = endpoint->wMaxPacketSize;
 			dev->bulk_out_size = buffer_size;
-			dev->write_urb->transfer_flags = (URB_NO_DMA_MAP |
+			dev->write_urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP |
 					URB_ASYNC_UNLINK);
 			dev->bulk_out_buffer = usb_buffer_alloc (udev,
 					buffer_size, GFP_KERNEL,
@@ -601,6 +600,9 @@
 		goto error;
 	}
 
+	/* allow device read, write and ioctl */
+	dev->present = 1;
+
 	/* let the user know what node this device is now attached to */
 	info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
 
@@ -663,10 +665,12 @@
 		wait_for_completion (&dev->write_finished);
 	}
 
-	dev->udev = NULL;
+	/* prevent device read, write and ioctl */
+	dev->present = 0;
+
 	up (&dev->sem);
 
-	/* if the device is not opened, then we clean up right now */
+	/* if the device is opened, skel_release will clean this up */
 	if (!dev->open)
 		skel_delete (dev);
 
diff -urN linux-2.5.73-bk9/fs/Kconfig.binfmt linux-2.5.73-bk10/fs/Kconfig.binfmt
--- linux-2.5.73-bk9/fs/Kconfig.binfmt	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk10/fs/Kconfig.binfmt	2003-07-02 04:57:33.000000000 -0700
@@ -43,7 +43,7 @@
 
 config BINFMT_AOUT
 	tristate "Kernel support for a.out and ECOFF binaries"
-	depends on X86 || ALPHA || ARM || M68K || MIPS || SPARC
+	depends on (X86 && !X86_64) || ALPHA || ARM || M68K || MIPS || SPARC
 	---help---
 	  A.out (Assembler.OUTput) is a set of formats for libraries and
 	  executables used in the earliest versions of UNIX.  Linux used
diff -urN linux-2.5.73-bk9/include/asm-m68knommu/bitops.h linux-2.5.73-bk10/include/asm-m68knommu/bitops.h
--- linux-2.5.73-bk9/include/asm-m68knommu/bitops.h	2003-06-22 11:32:33.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-m68knommu/bitops.h	2003-07-02 04:57:36.000000000 -0700
@@ -11,31 +11,6 @@
 #include <asm/system.h>		/* save_flags */
 
 #ifdef __KERNEL__
-/*
- * Function prototypes to keep gcc -Wall happy
- */
-
-/*
- * The __ functions are not atomic
- */
-
-extern void set_bit(int nr, volatile void * addr);
-extern void __set_bit(int nr, volatile void * addr);
-extern void clear_bit(int nr, volatile void * addr);
-extern void __clear_bit(int nr, volatile void * addr);
-extern void change_bit(int nr, volatile void * addr);
-extern void __change_bit(int nr, volatile void * addr);
-extern int test_and_set_bit(int nr, volatile void * addr);
-extern int __test_and_set_bit(int nr, volatile void * addr);
-extern int test_and_clear_bit(int nr, volatile void * addr);
-extern int __test_and_clear_bit(int nr, volatile void * addr);
-extern int test_and_change_bit(int nr, volatile void * addr);
-extern int __test_and_change_bit(int nr, volatile void * addr);
-extern int __constant_test_bit(int nr, const volatile void * addr);
-extern int __test_bit(int nr, volatile void * addr);
-extern int find_first_zero_bit(void * addr, unsigned size);
-extern int find_next_zero_bit (void * addr, int size, int offset);
-
 
 /*
  *	Generic ffs().
@@ -130,7 +105,7 @@
  * ffz = Find First Zero in word. Undefined if no zero exists,
  * so code should check against ~0UL first..
  */
-extern __inline__ unsigned long ffz(unsigned long word)
+static __inline__ unsigned long ffz(unsigned long word)
 {
 	unsigned long result = 0;
 
@@ -142,7 +117,7 @@
 }
 
 
-extern __inline__ void set_bit(int nr, volatile void * addr)
+static __inline__ void set_bit(int nr, volatile unsigned long * addr)
 {
 	int 	* a = (int *) addr;
 	int	mask;
@@ -155,7 +130,7 @@
 	local_irq_restore(flags);
 }
 
-extern __inline__ void __set_bit(int nr, volatile void * addr)
+static __inline__ void __set_bit(int nr, volatile unsigned long * addr)
 {
 	int 	* a = (int *) addr;
 	int	mask;
@@ -171,7 +146,7 @@
 #define smp_mb__before_clear_bit()	barrier()
 #define smp_mb__after_clear_bit()	barrier()
 
-extern __inline__ void clear_bit(int nr, volatile void * addr)
+static __inline__ void clear_bit(int nr, volatile unsigned long * addr)
 {
 	int 	* a = (int *) addr;
 	int	mask;
@@ -184,7 +159,7 @@
 	local_irq_restore(flags);
 }
 
-extern __inline__ void __clear_bit(int nr, volatile void * addr)
+static __inline__ void __clear_bit(int nr, volatile unsigned long * addr)
 {
 	int 	* a = (int *) addr;
 	int	mask;
@@ -194,7 +169,7 @@
 	*a &= ~mask;
 }
 
-extern __inline__ void change_bit(int nr, volatile void * addr)
+static __inline__ void change_bit(int nr, volatile unsigned long * addr)
 {
 	int mask, flags;
 	unsigned long *ADDR = (unsigned long *) addr;
@@ -206,7 +181,7 @@
 	local_irq_restore(flags);
 }
 
-extern __inline__ void __change_bit(int nr, volatile void * addr)
+static __inline__ void __change_bit(int nr, volatile unsigned long * addr)
 {
 	int mask;
 	unsigned long *ADDR = (unsigned long *) addr;
@@ -216,7 +191,7 @@
 	*ADDR ^= mask;
 }
 
-extern __inline__ int test_and_set_bit(int nr, volatile void * addr)
+static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
 {
 	int	mask, retval;
 	volatile unsigned int *a = (volatile unsigned int *) addr;
@@ -232,7 +207,7 @@
 	return retval;
 }
 
-extern __inline__ int __test_and_set_bit(int nr, volatile void * addr)
+static __inline__ int __test_and_set_bit(int nr, volatile unsigned long * addr)
 {
 	int	mask, retval;
 	volatile unsigned int *a = (volatile unsigned int *) addr;
@@ -244,7 +219,7 @@
 	return retval;
 }
 
-extern __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
 {
 	int	mask, retval;
 	volatile unsigned int *a = (volatile unsigned int *) addr;
@@ -260,7 +235,7 @@
 	return retval;
 }
 
-extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
+static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long * addr)
 {
 	int	mask, retval;
 	volatile unsigned int *a = (volatile unsigned int *) addr;
@@ -272,7 +247,7 @@
 	return retval;
 }
 
-extern __inline__ int test_and_change_bit(int nr, volatile void * addr)
+static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
 {
 	int	mask, retval;
 	volatile unsigned int *a = (volatile unsigned int *) addr;
@@ -288,7 +263,7 @@
 	return retval;
 }
 
-extern __inline__ int __test_and_change_bit(int nr, volatile void * addr)
+static __inline__ int __test_and_change_bit(int nr, volatile unsigned long * addr)
 {
 	int	mask, retval;
 	volatile unsigned int *a = (volatile unsigned int *) addr;
@@ -303,12 +278,12 @@
 /*
  * This routine doesn't need to be atomic.
  */
-extern __inline__ int __constant_test_bit(int nr, const volatile void * addr)
+static __inline__ int __constant_test_bit(int nr, const volatile unsigned long * addr)
 {
 	return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
 }
 
-extern __inline__ int __test_bit(int nr, volatile void * addr)
+static __inline__ int __test_bit(int nr, const unsigned long * addr)
 {
 	int 	* a = (int *) addr;
 	int	mask;
@@ -326,7 +301,7 @@
 #define find_first_zero_bit(addr, size) \
         find_next_zero_bit((addr), (size), 0)
 
-extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
 {
 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 	unsigned long result = offset & ~31UL;
@@ -372,7 +347,7 @@
 #define hweight8(x) generic_hweight8(x)
 
 
-extern __inline__ int ext2_set_bit(int nr, volatile void * addr)
+static __inline__ int ext2_set_bit(int nr, volatile void * addr)
 {
 	int		mask, retval;
 	unsigned long	flags;
@@ -387,7 +362,7 @@
 	return retval;
 }
 
-extern __inline__ int ext2_clear_bit(int nr, volatile void * addr)
+static __inline__ int ext2_clear_bit(int nr, volatile void * addr)
 {
 	int		mask, retval;
 	unsigned long	flags;
@@ -420,7 +395,7 @@
 		ret;					\
 	})
 
-extern __inline__ int ext2_test_bit(int nr, const volatile void * addr)
+static __inline__ int ext2_test_bit(int nr, const volatile void * addr)
 {
 	int	mask;
 	const volatile unsigned char	*ADDR = (const unsigned char *) addr;
@@ -433,7 +408,7 @@
 #define ext2_find_first_zero_bit(addr, size) \
         ext2_find_next_zero_bit((addr), (size), 0)
 
-extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
 {
 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 	unsigned long result = offset & ~31UL;
diff -urN linux-2.5.73-bk9/include/asm-m68knommu/dma.h linux-2.5.73-bk10/include/asm-m68knommu/dma.h
--- linux-2.5.73-bk9/include/asm-m68knommu/dma.h	2003-06-22 11:33:12.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-m68knommu/dma.h	2003-07-02 04:57:36.000000000 -0700
@@ -36,7 +36,7 @@
 /*
  * Set number of channels of DMA on ColdFire for different implementations.
  */
-#if defined(CONFIG_M5307) || defined(CONFIG_M5407)
+#if defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
 #define MAX_M68K_DMA_CHANNELS 4
 #elif defined(CONFIG_M5272)
 #define MAX_M68K_DMA_CHANNELS 1
diff -urN linux-2.5.73-bk9/include/asm-m68knommu/mcfuart.h linux-2.5.73-bk10/include/asm-m68knommu/mcfuart.h
--- linux-2.5.73-bk9/include/asm-m68knommu/mcfuart.h	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-m68knommu/mcfuart.h	2003-07-02 04:57:36.000000000 -0700
@@ -84,7 +84,7 @@
 #define	MCFUART_MR1_PARITYEVEN	0x00		/* Even parity */
 #define	MCFUART_MR1_PARITYODD	0x04		/* Odd parity */
 #define	MCFUART_MR1_PARITYSPACE	0x08		/* Space parity */
-#define	MCFUART_MR1_PARITYMARK	0x06		/* Mark parity */
+#define	MCFUART_MR1_PARITYMARK	0x0c		/* Mark parity */
 
 #define	MCFUART_MR1_CS5		0x00		/* 5 bits per char */
 #define	MCFUART_MR1_CS6		0x01		/* 6 bits per char */
diff -urN linux-2.5.73-bk9/include/asm-ppc64/bitops.h linux-2.5.73-bk10/include/asm-ppc64/bitops.h
--- linux-2.5.73-bk9/include/asm-ppc64/bitops.h	2003-06-22 11:33:07.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-ppc64/bitops.h	2003-07-02 04:57:38.000000000 -0700
@@ -269,6 +269,7 @@
  * hweightN: returns the hamming weight (i.e. the number
  * of bits set) of a N-bit word
  */
+#define hweight64(x) generic_hweight64(x)
 #define hweight32(x) generic_hweight32(x)
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
diff -urN linux-2.5.73-bk9/include/asm-ppc64/cputable.h linux-2.5.73-bk10/include/asm-ppc64/cputable.h
--- linux-2.5.73-bk9/include/asm-ppc64/cputable.h	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-ppc64/cputable.h	2003-07-02 04:57:38.000000000 -0700
@@ -113,6 +113,8 @@
 #define CPU_FTR_TLBIEL         		0x0000000400000000
 #define CPU_FTR_NOEXECUTE     		0x0000000800000000
 #define CPU_FTR_NODSISRALIGN  		0x0000001000000000
+#define CPU_FTR_DABR  			0x0000002000000000
+#define CPU_FTR_IABR  			0x0000004000000000
 
 /* Platform firmware features */
 #define FW_FTR_                         0x0000000000000001
diff -urN linux-2.5.73-bk9/include/asm-ppc64/eeh.h linux-2.5.73-bk10/include/asm-ppc64/eeh.h
--- linux-2.5.73-bk9/include/asm-ppc64/eeh.h	2003-06-22 11:33:16.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-ppc64/eeh.h	2003-07-02 04:57:38.000000000 -0700
@@ -25,6 +25,8 @@
 #ifndef _EEH_H
 #define _EEH_H
 
+#include <linux/string.h>
+
 struct pci_dev;
 
 /* I/O addresses are converted to EEH "tokens" such that a driver will cause
@@ -65,9 +67,6 @@
  */
 unsigned long eeh_token_to_phys(unsigned long token);
 
-extern void *memcpy(void *, const void *, unsigned long);
-extern void *memset(void *,int, unsigned long);
-
 /* EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
  *
  * Order this macro for performance.
diff -urN linux-2.5.73-bk9/include/asm-ppc64/pci.h linux-2.5.73-bk10/include/asm-ppc64/pci.h
--- linux-2.5.73-bk9/include/asm-ppc64/pci.h	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-ppc64/pci.h	2003-07-02 04:57:38.000000000 -0700
@@ -89,11 +89,7 @@
 extern int pci_domain_nr(struct pci_bus *bus);
 
 /* Set the name of the bus as it appears in /proc/bus/pci */
-static inline int pci_name_bus(char *name, struct pci_bus *bus)
-{
-	sprintf(name, "%02x", bus->number);
-	return 0;
-}
+extern int pci_name_bus(char *name, struct pci_bus *bus);
 
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
diff -urN linux-2.5.73-bk9/include/asm-ppc64/processor.h linux-2.5.73-bk10/include/asm-ppc64/processor.h
--- linux-2.5.73-bk9/include/asm-ppc64/processor.h	2003-06-22 11:32:32.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-ppc64/processor.h	2003-07-02 04:57:38.000000000 -0700
@@ -730,15 +730,6 @@
 
 #define spin_lock_prefetch(x)	prefetchw(x)
 
-/* XXX we have to call HV to set when in LPAR */
-#define cpu_has_dabr()		(1)
-
-#define cpu_has_iabr()		(processor_type() != PV_POWER4 && \
-				 processor_type() != PV_POWER4p)
-
-#define cpu_alignexc_sets_dsisr() (processor_type() != PV_POWER4 && \
-				 processor_type() != PV_POWER4p)
-
 #endif /* ASSEMBLY */
 
 #endif /* __ASM_PPC64_PROCESSOR_H */
diff -urN linux-2.5.73-bk9/include/asm-ppc64/prom.h linux-2.5.73-bk10/include/asm-ppc64/prom.h
--- linux-2.5.73-bk9/include/asm-ppc64/prom.h	2003-06-22 11:33:35.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-ppc64/prom.h	2003-07-02 04:57:38.000000000 -0700
@@ -194,5 +194,6 @@
 extern int prom_n_addr_cells(struct device_node* np);
 extern int prom_n_size_cells(struct device_node* np);
 extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
+extern void prom_add_property(struct device_node* np, struct property* prop);
 
 #endif /* _PPC64_PROM_H */
diff -urN linux-2.5.73-bk9/include/asm-ppc64/smp.h linux-2.5.73-bk10/include/asm-ppc64/smp.h
--- linux-2.5.73-bk9/include/asm-ppc64/smp.h	2003-06-22 11:32:27.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-ppc64/smp.h	2003-07-02 04:57:38.000000000 -0700
@@ -35,24 +35,23 @@
 struct pt_regs;
 extern void smp_message_recv(int, struct pt_regs *);
 
-#define NO_PROC_ID		0xFF            /* No processor magic marker */
-
 #define cpu_online(cpu)	test_bit((cpu), &cpu_online_map)
 
 #define cpu_possible(cpu)	paca[cpu].active
 
-static inline int num_online_cpus(void)
+static inline unsigned int num_online_cpus(void)
 {
-	int i, nr = 0;
+	return hweight64(cpu_online_map);
+}
 
-	for (i = 0; i < NR_CPUS; i++)
-		nr += test_bit(i, &cpu_online_map);
+static inline unsigned int any_online_cpu(unsigned int mask)
+{
+	if (mask & cpu_online_map)
+		return __ffs(mask & cpu_online_map);
 
-	return nr;
+	return NR_CPUS;
 }
 
-extern volatile unsigned int cpu_callin_map[NR_CPUS];
-
 #define smp_processor_id() (get_paca()->xPacaIndex)
 
 /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
diff -urN linux-2.5.73-bk9/include/asm-ppc64/system.h linux-2.5.73-bk10/include/asm-ppc64/system.h
--- linux-2.5.73-bk9/include/asm-ppc64/system.h	2003-06-22 11:33:35.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-ppc64/system.h	2003-07-02 04:57:38.000000000 -0700
@@ -115,13 +115,6 @@
 	return(PVR_VER(pvr) == pv);
 }
 
-static inline int processor_type(void)
-{
-	unsigned long pvr;
-	asm ("mfspr %0, 0x11F" : "=r" (pvr)); 
-	return(PVR_VER(pvr));
-}
-
 /*
  * Atomic exchange
  *
diff -urN linux-2.5.73-bk9/include/asm-ppc64/uaccess.h linux-2.5.73-bk10/include/asm-ppc64/uaccess.h
--- linux-2.5.73-bk9/include/asm-ppc64/uaccess.h	2003-06-22 11:32:55.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-ppc64/uaccess.h	2003-07-02 04:57:38.000000000 -0700
@@ -44,11 +44,14 @@
  * Address valid if:
  *  - "addr" doesn't have any high-bits set
  *  - AND "size" doesn't have any high-bits set
- *  - AND "addr+size" doesn't have any high-bits set
  *  - OR we are in kernel mode.
+ *
+ * We dont have to check for high bits in (addr+size) because the first
+ * two checks force the maximum result to be below the start of the
+ * kernel region.
  */
 #define __access_ok(addr,size,segment) \
-	(((segment).seg & (addr | size | (addr+size))) == 0)
+	(((segment).seg & (addr | size )) == 0)
 
 #define access_ok(type,addr,size) \
 	__access_ok(((unsigned long)(addr)),(size),get_fs())
@@ -270,6 +273,8 @@
 {
 	if (likely(access_ok(VERIFY_READ, from, n)))
 		n = __copy_from_user(to, from, n);
+	else
+		memset(to, 0, n);
 	return n;
 }
 
diff -urN linux-2.5.73-bk9/include/asm-s390/elf.h linux-2.5.73-bk10/include/asm-s390/elf.h
--- linux-2.5.73-bk9/include/asm-s390/elf.h	2003-06-22 11:33:16.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-s390/elf.h	2003-07-02 04:57:38.000000000 -0700
@@ -84,8 +84,13 @@
 #define R_390_TLS_DTPOFF	55	/* Offset in TLS block.  */
 #define R_390_TLS_TPOFF		56	/* Negate offset in static TLS
                                            block.  */
+#define R_390_20		57	/* Direct 20 bit.  */
+#define R_390_GOT20		58	/* 20 bit GOT offset.  */
+#define R_390_GOTPLT20		59	/* 20 bit offset to jump slot.  */
+#define R_390_TLS_GOTIE20	60	/* 20 bit GOT offset for static TLS
+					   block offset.  */
 /* Keep this the last entry.  */
-#define R_390_NUM	57
+#define R_390_NUM	61
 
 /*
  * ELF register definitions..
diff -urN linux-2.5.73-bk9/include/asm-s390/setup.h linux-2.5.73-bk10/include/asm-s390/setup.h
--- linux-2.5.73-bk9/include/asm-s390/setup.h	2003-06-22 11:33:16.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-s390/setup.h	2003-07-02 04:57:38.000000000 -0700
@@ -35,6 +35,7 @@
 #define MACHINE_IS_P390		(machine_flags & 4)
 #define MACHINE_HAS_MVPG	(machine_flags & 16)
 #define MACHINE_HAS_DIAG44	(machine_flags & 32)
+#define MACHINE_NEW_STIDP	(machine_flags & 64)
 
 #ifndef __s390x__
 #define MACHINE_HAS_IEEE	(machine_flags & 2)
diff -urN linux-2.5.73-bk9/include/asm-sh/addrspace.h linux-2.5.73-bk10/include/asm-sh/addrspace.h
--- linux-2.5.73-bk9/include/asm-sh/addrspace.h	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/addrspace.h	2003-07-02 04:57:38.000000000 -0700
@@ -10,6 +10,8 @@
 #ifndef __ASM_SH_ADDRSPACE_H
 #define __ASM_SH_ADDRSPACE_H
 
+#include <asm/cpu/addrspace.h>
+
 /* Memory segments (32bit Priviledged mode addresses)  */
 #define P0SEG		0x00000000
 #define P1SEG		0x80000000
@@ -17,22 +19,6 @@
 #define P3SEG		0xc0000000
 #define P4SEG		0xe0000000
 
-#if defined(__sh3__)
-/* Should fill here */
-#elif defined(__SH4__)
-/* Detailed P4SEG  */
-#define P4SEG_STORE_QUE	(P4SEG)
-#define P4SEG_IC_ADDR	0xf0000000
-#define P4SEG_IC_DATA	0xf1000000
-#define P4SEG_ITLB_ADDR	0xf2000000
-#define P4SEG_ITLB_DATA	0xf3000000
-#define P4SEG_OC_ADDR	0xf4000000
-#define P4SEG_OC_DATA	0xf5000000
-#define P4SEG_TLB_ADDR	0xf6000000
-#define P4SEG_TLB_DATA	0xf7000000
-#define P4SEG_REG_BASE	0xff000000
-#endif
-
 /* Returns the privileged segment base of a given address  */
 #define PXSEG(a)	(((unsigned long)(a)) & 0xe0000000)
 
diff -urN linux-2.5.73-bk9/include/asm-sh/adx/io.h linux-2.5.73-bk10/include/asm-sh/adx/io.h
--- linux-2.5.73-bk9/include/asm-sh/adx/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/adx/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,86 @@
+/*
+ * include/asm-sh/io_adx.h
+ *
+ * Copyright (C) 2001 A&D Co., Ltd.
+ *
+ * This file may be copied or modified under the terms of the GNU
+ * General Public License.  See linux/COPYING for more information.
+ *
+ * IO functions for an A&D ADX Board
+ */
+
+#ifndef _ASM_SH_IO_ADX_H
+#define _ASM_SH_IO_ADX_H
+
+#include <asm/io_generic.h>
+
+extern unsigned char adx_inb(unsigned long port);
+extern unsigned short adx_inw(unsigned long port);
+extern unsigned int adx_inl(unsigned long port);
+
+extern void adx_outb(unsigned char value, unsigned long port);
+extern void adx_outw(unsigned short value, unsigned long port);
+extern void adx_outl(unsigned int value, unsigned long port);
+
+extern unsigned char adx_inb_p(unsigned long port);
+extern void adx_outb_p(unsigned char value, unsigned long port);
+
+extern void adx_insb(unsigned long port, void *addr, unsigned long count);
+extern void adx_insw(unsigned long port, void *addr, unsigned long count);
+extern void adx_insl(unsigned long port, void *addr, unsigned long count);
+extern void adx_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void adx_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void adx_outsl(unsigned long port, const void *addr, unsigned long count);
+
+extern unsigned char adx_readb(unsigned long addr);
+extern unsigned short adx_readw(unsigned long addr);
+extern unsigned int adx_readl(unsigned long addr);
+extern void adx_writeb(unsigned char b, unsigned long addr);
+extern void adx_writew(unsigned short b, unsigned long addr);
+extern void adx_writel(unsigned int b, unsigned long addr);
+
+extern void * adx_ioremap(unsigned long offset, unsigned long size);
+extern void adx_iounmap(void *addr);
+
+extern unsigned long adx_isa_port2addr(unsigned long offset);
+
+extern void setup_adx(void);
+extern void init_adx_IRQ(void);
+
+#ifdef __WANT_IO_DEF
+
+#define __inb		adx_inb
+#define __inw		adx_inw
+#define __inl		adx_inl
+#define __outb		adx_outb
+#define __outw		adx_outw
+#define __outl		adx_outl
+
+#define __inb_p		adx_inb_p
+#define __inw_p		adx_inw
+#define __inl_p		adx_inl
+#define __outb_p	adx_outb_p
+#define __outw_p	adx_outw
+#define __outl_p	adx_outl
+
+#define __insb		adx_insb
+#define __insw		adx_insw
+#define __insl		adx_insl
+#define __outsb		adx_outsb
+#define __outsw		adx_outsw
+#define __outsl		adx_outsl
+
+#define __readb		adx_readb
+#define __readw		adx_readw
+#define __readl		adx_readl
+#define __writeb	adx_writeb
+#define __writew	adx_writew
+#define __writel	adx_writel
+
+#define __isa_port2addr	adx_isa_port2addr
+#define __ioremap	adx_ioremap
+#define __iounmap	adx_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_AANDD_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/atomic.h linux-2.5.73-bk10/include/asm-sh/atomic.h
--- linux-2.5.73-bk9/include/asm-sh/atomic.h	2003-06-22 11:33:08.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/atomic.h	2003-07-02 04:57:38.000000000 -0700
@@ -26,29 +26,29 @@
 {
 	unsigned long flags;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	*(long *)v += i;
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 static __inline__ void atomic_sub(int i, atomic_t *v)
 {
 	unsigned long flags;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	*(long *)v -= i;
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 static __inline__ int atomic_add_return(int i, atomic_t * v)
 {
 	unsigned long temp, flags;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	temp = *(long *)v;
 	temp += i;
 	*(long *)v = temp;
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 	return temp;
 }
@@ -57,11 +57,11 @@
 {
 	unsigned long temp, flags;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	temp = *(long *)v;
 	temp -= i;
 	*(long *)v = temp;
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 	return temp;
 }
@@ -79,18 +79,18 @@
 {
 	unsigned long flags;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	*(long *)v &= ~mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
 {
 	unsigned long flags;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	*(long *)v |= mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 /* Atomic operations are already serializing on SH */
diff -urN linux-2.5.73-bk9/include/asm-sh/bigsur/bigsur.h linux-2.5.73-bk10/include/asm-sh/bigsur/bigsur.h
--- linux-2.5.73-bk9/include/asm-sh/bigsur/bigsur.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/bigsur/bigsur.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,80 @@
+/*
+ *
+ * Hitachi Big Sur Eval Board support
+ *
+ * Dustin McIntire (dustin@sensoria.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Derived from Hitachi SH7751 reference manual
+ * 
+ */
+
+#ifndef _ASM_BIGSUR_H_
+#define _ASM_BIGSUR_H_
+
+#include <asm/irq.h>
+#include <asm/hd64465/hd64465.h>
+
+/* 7751 Internal IRQ's used by external CPLD controller */
+#define BIGSUR_IRQ_LOW	0
+#define BIGSUR_IRQ_NUM  14         /* External CPLD level 1 IRQs */
+#define BIGSUR_IRQ_HIGH (BIGSUR_IRQ_LOW + BIGSUR_IRQ_NUM)
+#define BIGSUR_2NDLVL_IRQ_LOW   (HD64465_IRQ_BASE+HD64465_IRQ_NUM)  
+#define BIGSUR_2NDLVL_IRQ_NUM   32 /* Level 2 IRQs = 4 regs * 8 bits */
+#define BIGSUR_2NDLVL_IRQ_HIGH  (BIGSUR_2NDLVL_IRQ_LOW + \
+                                 BIGSUR_2NDLVL_IRQ_NUM)
+
+/* PCI interrupt base number (A_INTA-A_INTD) */
+#define BIGSUR_SH7751_PCI_IRQ_BASE  (BIGSUR_2NDLVL_IRQ_LOW+10)  
+
+/* CPLD registers and external chip addresses */
+#define BIGSUR_HD64464_ADDR	0xB2000000
+#define BIGSUR_DGDR	0xB1FFFE00
+#define BIGSUR_BIDR	0xB1FFFD00
+#define BIGSUR_CSLR	0xB1FFFC00
+#define BIGSUR_SW1R	0xB1FFFB00
+#define BIGSUR_DBGR	0xB1FFFA00
+#define BIGSUR_BDTR	0xB1FFF900
+#define BIGSUR_BDRR	0xB1FFF800
+#define BIGSUR_PPR1	0xB1FFF700
+#define BIGSUR_PPR2	0xB1FFF600
+#define BIGSUR_IDE2	0xB1FFF500
+#define BIGSUR_IDE3	0xB1FFF400
+#define BIGSUR_SPCR	0xB1FFF300
+#define BIGSUR_ETHR	0xB1FE0000
+#define BIGSUR_PPDR	0xB1FDFF00
+#define BIGSUR_ICTL	0xB1FDFE00
+#define BIGSUR_ICMD	0xB1FDFD00
+#define BIGSUR_DMA0	0xB1FDFC00
+#define BIGSUR_DMA1	0xB1FDFB00
+#define BIGSUR_IRQ0	0xB1FDFA00
+#define BIGSUR_IRQ1	0xB1FDF900
+#define BIGSUR_IRQ2	0xB1FDF800
+#define BIGSUR_IRQ3	0xB1FDF700
+#define BIGSUR_IMR0	0xB1FDF600
+#define BIGSUR_IMR1	0xB1FDF500
+#define BIGSUR_IMR2	0xB1FDF400
+#define BIGSUR_IMR3	0xB1FDF300
+#define BIGSUR_IRLMR0	0xB1FDF200
+#define BIGSUR_IRLMR1	0xB1FDF100
+#define BIGSUR_V320USC_ADDR  0xB1000000
+#define BIGSUR_HD64465_ADDR  0xB0000000
+#define BIGSUR_INTERNAL_BASE 0xB0000000
+
+/* SMC ethernet card parameters */
+#define BIGSUR_ETHER_IOPORT		0x220
+
+/* IDE register paramters */
+#define BIGSUR_IDECMD_IOPORT	0x1f0
+#define BIGSUR_IDECTL_IOPORT	0x1f8
+
+/* LED bit position in BIGSUR_CSLR */
+#define BIGSUR_LED  (1<<4)
+
+/* PCI: default LOCAL memory window sizes (seen from PCI bus) */
+#define BIGSUR_LSR0_SIZE    (64*(1<<20)) //64MB
+#define BIGSUR_LSR1_SIZE    (64*(1<<20)) //64MB
+
+#endif /* _ASM_BIGSUR_H_ */
diff -urN linux-2.5.73-bk9/include/asm-sh/bigsur/io.h linux-2.5.73-bk10/include/asm-sh/bigsur/io.h
--- linux-2.5.73-bk9/include/asm-sh/bigsur/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/bigsur/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,89 @@
+/*
+ * include/asm-sh/io_bigsur.h
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ * Derived from io_hd64465.h, which bore the message:
+ * By Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc. 
+ * and from io_hd64461.h, which bore the message:
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for a Hitachi Big Sur Evaluation Board.
+ */
+
+#ifndef _ASM_SH_IO_BIGSUR_H
+#define _ASM_SH_IO_BIGSUR_H
+
+#include <linux/types.h>
+#include <asm/io_generic.h>
+
+extern unsigned char bigsur_inb(unsigned long port);
+extern unsigned short bigsur_inw(unsigned long port);
+extern unsigned int bigsur_inl(unsigned long port);
+
+extern void bigsur_outb(unsigned char value, unsigned long port);
+extern void bigsur_outw(unsigned short value, unsigned long port);
+extern void bigsur_outl(unsigned int value, unsigned long port);
+
+extern unsigned char bigsur_inb_p(unsigned long port);
+extern void bigsur_outb_p(unsigned char value, unsigned long port);
+
+extern void bigsur_insb(unsigned long port, void *addr, unsigned long count);
+extern void bigsur_insw(unsigned long port, void *addr, unsigned long count);
+extern void bigsur_insl(unsigned long port, void *addr, unsigned long count);
+extern void bigsur_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void bigsur_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void bigsur_outsl(unsigned long port, const void *addr, unsigned long count);
+extern unsigned long bigsur_isa_port2addr(unsigned long offset);
+extern int bigsur_irq_demux(int irq);
+extern void bigsur_init_pci(void);
+/* Provision for generic secondary demux step -- used by PCMCIA code */
+extern void bigsur_register_irq_demux(int irq,
+		int (*demux)(int irq, void *dev), void *dev);
+extern void bigsur_unregister_irq_demux(int irq);
+/* Set this variable to 1 to see port traffic */
+extern int bigsur_io_debug;
+/* Map a range of ports to a range of kernel virtual memory. */
+extern void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift);
+extern void bigsur_port_unmap(u32 baseport, u32 nports);
+
+#endif /* _ASM_SH_IO_BIGSUR_H */
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			bigsur_inb
+# define __inw			bigsur_inw
+# define __inl			bigsur_inl
+# define __outb			bigsur_outb
+# define __outw			bigsur_outw
+# define __outl			bigsur_outl
+
+# define __inb_p		bigsur_inb_p
+# define __inw_p		bigsur_inw
+# define __inl_p		bigsur_inl
+# define __outb_p		bigsur_outb_p
+# define __outw_p		bigsur_outw
+# define __outl_p		bigsur_outl
+
+# define __insb			bigsur_insb
+# define __insw			bigsur_insw
+# define __insl			bigsur_insl
+# define __outsb		bigsur_outsb
+# define __outsw		bigsur_outsw
+# define __outsl		bigsur_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	bigsur_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/bigsur/serial.h linux-2.5.73-bk10/include/asm-sh/bigsur/serial.h
--- linux-2.5.73-bk9/include/asm-sh/bigsur/serial.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/bigsur/serial.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,30 @@
+/*
+ * include/asm-sh/serial-bigsur.h
+ *
+ * Configuration details for Big Sur 16550 based serial ports 
+ * i.e. HD64465, PCMCIA, etc.
+ */
+
+#ifndef _ASM_SERIAL_BIGSUR_H
+#define _ASM_SERIAL_BIGSUR_H
+#include <asm/hd64465.h>
+
+#define BASE_BAUD (3379200 / 16)
+
+/* Leave 2 spare for possible PCMCIA serial cards */
+#define RS_TABLE_SIZE  3
+
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+
+#define STD_SERIAL_PORT_DEFNS                   \
+        /* UART CLK   PORT IRQ     FLAGS        */                      \
+        { 0, BASE_BAUD, 0x3F8, HD64465_IRQ_UART, STD_COM_FLAGS } /* ttyS0 */ 
+
+
+#define SERIAL_PORT_DFNS STD_SERIAL_PORT_DEFNS
+
+/* XXX: This should be moved ino irq.h */
+#define irq_cannonicalize(x) (x)
+
+#endif /* _ASM_SERIAL_BIGSUR_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/bitops.h linux-2.5.73-bk10/include/asm-sh/bitops.h
--- linux-2.5.73-bk9/include/asm-sh/bitops.h	2003-06-22 11:32:30.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/bitops.h	2003-07-02 04:57:38.000000000 -0700
@@ -14,9 +14,9 @@
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	*a |= mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 static __inline__ void __set_bit(int nr, volatile void * addr)
@@ -42,9 +42,9 @@
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	*a &= ~mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 static __inline__ void __clear_bit(int nr, volatile void * addr)
@@ -65,9 +65,9 @@
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	*a ^= mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 static __inline__ void __change_bit(int nr, volatile void * addr)
@@ -88,10 +88,10 @@
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	retval = (mask & *a) != 0;
 	*a |= mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 	return retval;
 }
@@ -117,10 +117,10 @@
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	retval = (mask & *a) != 0;
 	*a &= ~mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 	return retval;
 }
@@ -146,10 +146,10 @@
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	retval = (mask & *a) != 0;
 	*a ^= mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 	return retval;
 }
@@ -186,6 +186,82 @@
 	return result;
 }
 
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __inline__ unsigned long __ffs(unsigned long word)
+{
+	unsigned long result;
+
+	__asm__("1:\n\t"
+		"shlr	%1\n\t"
+		"bf/s	1b\n\t"
+		" add	#1, %0"
+		: "=r" (result), "=r" (word)
+		: "0" (~0L), "1" (word)
+		: "t");
+	return result;
+}
+
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+static __inline__ unsigned long find_next_bit(unsigned long *addr,
+	unsigned long size, unsigned long offset)
+{
+	unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
+	unsigned int result = offset & ~31UL;
+	unsigned int tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = *p++;
+		tmp &= ~0UL << offset;
+		if (size < 32)
+			goto found_first;
+		if (tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size >= 32) {
+		if ((tmp = *p++) != 0)
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp &= ~0UL >> (32 - size);
+	if (tmp == 0UL)        /* Are any bits set? */
+		return result + size; /* Nope. */
+found_middle:
+	return result + __ffs(tmp);
+}
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first set bit, not the number of the byte
+ * containing a bit.
+ */
+#define find_first_bit(addr, size) \
+	find_next_bit((addr), (size), 0)
+
 static __inline__ int find_next_zero_bit(void *addr, int size, int offset)
 {
 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
@@ -242,6 +318,26 @@
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
 
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 140-bit bitmap where the first 100 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 140
+ * bits is cleared.
+ */
+
+static inline int sched_find_first_bit(unsigned long *b)
+{
+	if (unlikely(b[0]))
+		return __ffs(b[0]);
+	if (unlikely(b[1]))
+		return __ffs(b[1]) + 32;
+	if (unlikely(b[2]))
+		return __ffs(b[2]) + 64;
+	if (b[3])
+		return __ffs(b[3]) + 96;
+	return __ffs(b[4]) + 128;
+}
+
 #ifdef __LITTLE_ENDIAN__
 #define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr))
 #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr))
@@ -258,10 +354,10 @@
 
 	ADDR += nr >> 3;
 	mask = 1 << (nr & 0x07);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	retval = (mask & *ADDR) != 0;
 	*ADDR |= mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 	return retval;
 }
 
@@ -273,10 +369,10 @@
 
 	ADDR += nr >> 3;
 	mask = 1 << (nr & 0x07);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	retval = (mask & *ADDR) != 0;
 	*ADDR &= ~mask;
-	restore_flags(flags);
+	local_irq_restore(flags);
 	return retval;
 }
 
@@ -369,6 +465,12 @@
 #define minix_test_bit(nr,addr) test_bit(nr,addr)
 #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
 
+/*
+ * fls: find last bit set.
+ */
+
+#define fls(x) generic_fls(x)
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_SH_BITOPS_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/bug.h linux-2.5.73-bk10/include/asm-sh/bug.h
--- linux-2.5.73-bk9/include/asm-sh/bug.h	2003-06-22 11:33:16.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/bug.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_BUG_H
 #define __ASM_SH_BUG_H
 
+#include <linux/config.h>
+
 /*
  * Tell the user there is some problem.
  */
diff -urN linux-2.5.73-bk9/include/asm-sh/bugs.h linux-2.5.73-bk10/include/asm-sh/bugs.h
--- linux-2.5.73-bk9/include/asm-sh/bugs.h	2003-06-22 11:32:39.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/bugs.h	2003-07-02 04:57:38.000000000 -0700
@@ -16,33 +16,30 @@
 
 static void __init check_bugs(void)
 {
+	extern char *get_cpu_subtype(void);
 	extern unsigned long loops_per_jiffy;
 	char *p= &system_utsname.machine[2]; /* "sh" */
 
 	cpu_data->loops_per_jiffy = loops_per_jiffy;
 	
 	switch (cpu_data->type) {
-	case CPU_SH7708:
-		*p++ = '3';
-		printk("CPU: SH7707/SH7708/SH7709\n");
+	case CPU_SH7604:
+		*p++ = '2';
 		break;
-	case CPU_SH7729:
+	case CPU_SH7708 ... CPU_SH7729:
 		*p++ = '3';
-		printk("CPU: SH7709A/SH7729\n");
-		break;
-	case CPU_SH7750:
-		*p++ = '4';
-		printk("CPU: SH7750/SH7751\n");
 		break;
-	case CPU_ST40STB1:
+	case CPU_SH7750 ... CPU_ST40GX1:
 		*p++ = '4';
-		printk("CPU: ST40STB1\n");
 		break;
 	default:
-		printk("CPU: ??????\n");
+		*p++ = '?';
+		*p++ = '!';
 		break;
 	}
 
+	printk("CPU: %s\n", get_cpu_subtype());
+
 #ifndef __LITTLE_ENDIAN__
 	/* 'eb' means 'Endian Big' */
 	*p++ = 'e';
diff -urN linux-2.5.73-bk9/include/asm-sh/byteorder.h linux-2.5.73-bk10/include/asm-sh/byteorder.h
--- linux-2.5.73-bk9/include/asm-sh/byteorder.h	2003-06-22 11:32:28.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/byteorder.h	2003-07-02 04:57:38.000000000 -0700
@@ -25,6 +25,19 @@
 	return x;
 }
 
+static inline __u64 ___arch__swab64(__u64 val) 
+{ 
+	union { 
+		struct { __u32 a,b; } s;
+		__u64 u;
+	} v, w;
+	v.u = val;
+	w.s.b = ___arch__swab32(v.s.a); 
+	w.s.a = ___arch__swab32(v.s.b); 
+	return w.u;	
+} 
+
+#define __arch__swab64(x) ___arch__swab64(x)
 #define __arch__swab32(x) ___arch__swab32(x)
 #define __arch__swab16(x) ___arch__swab16(x)
 
diff -urN linux-2.5.73-bk9/include/asm-sh/cache.h linux-2.5.73-bk10/include/asm-sh/cache.h
--- linux-2.5.73-bk9/include/asm-sh/cache.h	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/cache.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,19 +1,53 @@
-/* $Id: cache.h,v 1.3 2000/07/04 06:24:49 gniibe Exp $
+/* $Id: cache.h,v 1.4 2003/05/06 23:28:50 lethal Exp $
  *
  * include/asm-sh/cache.h
  *
  * Copyright 1999 (C) Niibe Yutaka
+ * Copyright 2002, 2003 (C) Paul Mundt
  */
 #ifndef __ASM_SH_CACHE_H
 #define __ASM_SH_CACHE_H
 
-/* bytes per L1 cache line */
-#if defined(__sh3__)
-#define        L1_CACHE_BYTES  16
-#elif defined(__SH4__)
-#define        L1_CACHE_BYTES  32
+#include <asm/cpu/cache.h>
+#include <asm/cpu/cacheflush.h>
+
+#define SH_CACHE_VALID		1
+#define SH_CACHE_UPDATED	2
+#define SH_CACHE_COMBINED	4
+#define SH_CACHE_ASSOC		8
+
+#define SMP_CACHE_BYTES L1_CACHE_BYTES
+
+#define L1_CACHE_ALIGN(x)	(((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
+
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+#else
+#define __cacheline_aligned					\
+  __attribute__((__aligned__(L1_CACHE_BYTES),			\
+		 __section__(".data.cacheline_aligned")))
 #endif
 
 #define L1_CACHE_SHIFT_MAX 5	/* largest L1 which this arch supports */
 
+struct cache_info {
+	unsigned int ways;
+	unsigned int sets;
+	unsigned int linesz;
+
+	unsigned int way_shift;
+	unsigned int entry_shift;
+	unsigned int entry_mask;
+
+	unsigned long flags;
+};
+
+/* Flush (write-back only) a region (smaller than a page) */
+extern void __flush_wback_region(void *start, int size);
+/* Flush (write-back & invalidate) a region (smaller than a page) */
+extern void __flush_purge_region(void *start, int size);
+/* Flush (invalidate only) a region (smaller than a page) */
+extern void __flush_invalidate_region(void *start, int size);
+
 #endif /* __ASM_SH_CACHE_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cacheflush.h linux-2.5.73-bk10/include/asm-sh/cacheflush.h
--- linux-2.5.73-bk9/include/asm-sh/cacheflush.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cacheflush.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,13 @@
+#ifndef __ASM_SH_CACHEFLUSH_H
+#define __ASM_SH_CACHEFLUSH_H
+
+#include <asm/cpu/cacheflush.h>
+
+/* Flush (write-back only) a region (smaller than a page) */
+extern void __flush_wback_region(void *start, int size);
+/* Flush (write-back & invalidate) a region (smaller than a page) */
+extern void __flush_purge_region(void *start, int size);
+/* Flush (invalidate only) a region (smaller than a page) */
+extern void __flush_invalidate_region(void *start, int size);
+
+#endif /* __ASM_SH_CACHEFLUSH_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/cat68701/io.h linux-2.5.73-bk10/include/asm-sh/cat68701/io.h
--- linux-2.5.73-bk9/include/asm-sh/cat68701/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cat68701/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,89 @@
+/*
+ * include/asm-sh/io_cat68701.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *           2001 Yutarou Ebihar (ebihara@si-linux.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an AONE Corp. CAT-68701 SH7708 Borad
+ */
+
+#ifndef _ASM_SH_IO_CAT68701_H
+#define _ASM_SH_IO_CAT68701_H
+
+#include <asm/io_generic.h>
+
+extern unsigned char cat68701_inb(unsigned long port);
+extern unsigned short cat68701_inw(unsigned long port);
+extern unsigned int cat68701_inl(unsigned long port);
+
+extern void cat68701_outb(unsigned char value, unsigned long port);
+extern void cat68701_outw(unsigned short value, unsigned long port);
+extern void cat68701_outl(unsigned int value, unsigned long port);
+
+extern unsigned char cat68701_inb_p(unsigned long port);
+extern void cat68701_outb_p(unsigned char value, unsigned long port);
+
+extern void cat68701_insb(unsigned long port, void *addr, unsigned long count);
+extern void cat68701_insw(unsigned long port, void *addr, unsigned long count);
+extern void cat68701_insl(unsigned long port, void *addr, unsigned long count);
+extern void cat68701_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void cat68701_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void cat68701_outsl(unsigned long port, const void *addr, unsigned long count);
+
+extern unsigned char cat68701_readb(unsigned long addr);
+extern unsigned short cat68701_readw(unsigned long addr);
+extern unsigned int cat68701_readl(unsigned long addr);
+extern void cat68701_writeb(unsigned char b, unsigned long addr);
+extern void cat68701_writew(unsigned short b, unsigned long addr);
+extern void cat68701_writel(unsigned int b, unsigned long addr);
+
+extern void * cat68701_ioremap(unsigned long offset, unsigned long size);
+extern void cat68701_iounmap(void *addr);
+
+extern unsigned long cat68701_isa_port2addr(unsigned long offset);
+extern int cat68701_irq_demux(int irq);
+
+extern void setup_cat68701(void);
+extern void init_cat68701_IRQ(void);
+extern void heartbeat_cat68701(void);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			cat68701_inb
+# define __inw			cat68701_inw
+# define __inl			cat68701_inl
+# define __outb			cat68701_outb
+# define __outw			cat68701_outw
+# define __outl			cat68701_outl
+
+# define __inb_p		cat68701_inb_p
+# define __inw_p		cat68701_inw
+# define __inl_p		cat68701_inl
+# define __outb_p		cat68701_outb_p
+# define __outw_p		cat68701_outw
+# define __outl_p		cat68701_outl
+
+# define __insb			cat68701_insb
+# define __insw			cat68701_insw
+# define __insl			cat68701_insl
+# define __outsb		cat68701_outsb
+# define __outsw		cat68701_outsw
+# define __outsl		cat68701_outsl
+
+# define __readb		cat68701_readb
+# define __readw		cat68701_readw
+# define __readl		cat68701_readl
+# define __writeb		cat68701_writeb
+# define __writew		cat68701_writew
+# define __writel		cat68701_writel
+
+# define __isa_port2addr	cat68701_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_CAT68701_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh2/cache.h linux-2.5.73-bk10/include/asm-sh/cpu-sh2/cache.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh2/cache.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh2/cache.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,31 @@
+/*
+ * include/asm-sh/cpu-sh2/cache.h
+ *
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH2_CACHE_H
+#define __ASM_CPU_SH2_CACHE_H
+
+#define	L1_CACHE_BYTES	16
+
+#define CCR		0xfffffe92	/* Address of Cache Control Register */
+
+#define CCR_CACHE_CE	0x01	/* Cache enable */
+#define CCR_CACHE_ID	0x02	/* Instruction Replacement disable */
+#define CCR_CACHE_OD	0x04	/* Data Replacement disable */
+#define CCR_CACHE_TW	0x08	/* Two-way mode */
+#define CCR_CACHE_CP	0x10	/* Cache purge */
+
+#define CACHE_OC_ADDRESS_ARRAY	0x60000000
+
+#define CCR_CACHE_ENABLE	CCR_CACHE_CE
+#define CCR_CACHE_INVALIDATE	CCR_CACHE_CP
+#define CCR_CACHE_ORA		CCR_CACHE_TW
+#define CCR_CACHE_WT		0x00	/* SH-2 is _always_ write-through */
+
+#endif /* __ASM_CPU_SH2_CACHE_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh2/cacheflush.h linux-2.5.73-bk10/include/asm-sh/cpu-sh2/cacheflush.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh2/cacheflush.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh2/cacheflush.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,40 @@
+/*
+ * include/asm-sh/cpu-sh2/cacheflush.h
+ *
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH2_CACHEFLUSH_H
+#define __ASM_CPU_SH2_CACHEFLUSH_H
+
+/* 
+ * Cache flushing:
+ *
+ *  - flush_cache_all() flushes entire cache
+ *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_page(mm, vmaddr) flushes a single page
+ *  - flush_cache_range(vma, start, end) flushes a range of pages
+ *
+ *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
+ *  - flush_icache_range(start, end) flushes(invalidates) a range for icache
+ *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
+ *
+ *  Caches are indexed (effectively) by physical address on SH-2, so
+ *  we don't need them.
+ */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(vma, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_dcache_page(page)			do { } while (0)
+#define flush_icache_range(start, end)		do { } while (0)
+#define flush_icache_page(vma,pg)		do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
+#define flush_cache_sigtramp(vaddr)		do { } while (0)
+
+#define p3_cache_init()				do { } while (0)
+#endif /* __ASM_CPU_SH2_CACHEFLUSH_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh2/watchdog.h linux-2.5.73-bk10/include/asm-sh/cpu-sh2/watchdog.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh2/watchdog.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh2/watchdog.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,69 @@
+/*
+ * include/asm-sh/cpu-sh2/watchdog.h
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH2_WATCHDOG_H
+#define __ASM_CPU_SH2_WATCHDOG_H
+
+/*
+ * More SH-2 brilliance .. its not good enough that we can't read
+ * and write the same sizes to WTCNT, now we have to read and write
+ * with different sizes at different addresses for WTCNT _and_ RSTCSR.
+ *
+ * At least on the bright side no one has managed to screw over WTCSR
+ * in this fashion .. yet.
+ */
+/* Register definitions */
+#define WTCNT		0xfffffe80
+#define WTCSR		0xfffffe80
+#define RSTCSR		0xfffffe82
+
+#define WTCNT_R		(WTCNT + 1)
+#define RSTCSR_R	(RSTCSR + 1)
+
+/* Bit definitions */
+#define WTCSR_IOVF	0x80
+#define WTCSR_WT	0x40
+#define WTCSR_TME	0x20
+#define WTCSR_RSTS	0x00
+
+#define RSTCSR_RSTS	0x20
+
+/**
+ * 	sh_wdt_read_rstcsr - Read from Reset Control/Status Register
+ *
+ *	Reads back the RSTCSR value.
+ */
+static inline __u8 sh_wdt_read_rstcsr(void)
+{
+	/*
+	 * Same read/write brain-damage as for WTCNT here..
+	 */
+	return ctrl_inb(RSTCSR_R);
+}
+
+/**
+ * 	sh_wdt_write_csr - Write to Reset Control/Status Register
+ *
+ * 	@val: Value to write
+ *
+ * 	Writes the given value @val to the lower byte of the control/status
+ * 	register. The upper byte is set manually on each write.
+ */
+static inline void sh_wdt_write_rstcsr(__u8 val)
+{
+	/*
+	 * Note: Due to the brain-damaged nature of this register,
+	 * we can't presently touch the WOVF bit, since the upper byte
+	 * has to be swapped for this. So just leave it alone..
+	 */
+	ctrl_outw((WTCNT_HIGH << 8) | (__u16)val, RSTCSR);
+}
+
+#endif /* __ASM_CPU_SH2_WATCHDOG_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/addrspace.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/addrspace.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/addrspace.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/addrspace.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 by Kaz Kojima
+ *
+ * Defitions for the address spaces of the SH-3 CPUs.
+ */
+#ifndef __ASM_CPU_SH3_ADDRSPACE_H
+#define __ASM_CPU_SH3_ADDRSPACE_H
+
+/* Should fill here */
+
+#endif /* __ASM_CPU_SH3_ADDRSPACE_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/cache.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/cache.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/cache.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/cache.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,30 @@
+/*
+ * include/asm-sh/cpu-sh3/cache.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH3_CACHE_H
+#define __ASM_CPU_SH3_CACHE_H
+
+#define        L1_CACHE_BYTES  16
+
+#define CCR		0xffffffec	/* Address of Cache Control Register */
+
+#define CCR_CACHE_CE	0x01	/* Cache Enable */
+#define CCR_CACHE_WT	0x02	/* Write-Through (for P0,U0,P3) (else writeback) */
+#define CCR_CACHE_CB	0x04	/* Write-Back (for P1) (else writethrough) */
+#define CCR_CACHE_CF	0x08	/* Cache Flush */
+#define CCR_CACHE_ORA	0x20	/* RAM mode */
+
+#define CACHE_OC_ADDRESS_ARRAY	0xf0000000
+#define CACHE_PHYSADDR_MASK	0x1ffffc00
+
+#define CCR_CACHE_ENABLE	CCR_CACHE_CE
+#define CCR_CACHE_INVALIDATE	CCR_CACHE_CF
+
+#endif /* __ASM_CPU_SH3_CACHE_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/cacheflush.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/cacheflush.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/cacheflush.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/cacheflush.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,41 @@
+/*
+ * include/asm-sh/cpu-sh3/cacheflush.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH3_CACHEFLUSH_H
+#define __ASM_CPU_SH3_CACHEFLUSH_H
+
+/* 
+ * Cache flushing:
+ *
+ *  - flush_cache_all() flushes entire cache
+ *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_page(mm, vmaddr) flushes a single page
+ *  - flush_cache_range(vma, start, end) flushes a range of pages
+ *
+ *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
+ *  - flush_icache_range(start, end) flushes(invalidates) a range for icache
+ *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
+ *
+ *  Caches are indexed (effectively) by physical address on SH-3, so
+ *  we don't need them.
+ */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(vma, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_dcache_page(page)			do { } while (0)
+#define flush_icache_range(start, end)		do { } while (0)
+#define flush_icache_page(vma,pg)		do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
+#define flush_cache_sigtramp(vaddr)		do { } while (0)
+
+#define p3_cache_init()				do { } while (0)
+
+#endif /* __ASM_CPU_SH3_CACHEFLUSH_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/dma.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/dma.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/dma.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/dma.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,11 @@
+#ifndef __ASM_CPU_SH3_DMA_H
+#define __ASM_CPU_SH3_DMA_H
+
+#define SAR ((unsigned long[]){0xa4000020,0xa4000030,0xa4000040,0xa4000050})
+#define DAR ((unsigned long[]){0xa4000024,0xa4000034,0xa4000044,0xa4000054})
+#define DMATCR ((unsigned long[]){0xa4000028,0xa4000038,0xa4000048,0xa4000058})
+#define CHCR ((unsigned long[]){0xa400002c,0xa400003c,0xa400004c,0xa400005c})
+#define DMAOR 0xa4000060UL
+
+#endif /* __ASM_CPU_SH3_DMA_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/freq.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/freq.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/freq.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/freq.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,18 @@
+/*
+ * include/asm-sh/cpu-sh3/freq.h
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH3_FREQ_H
+#define __ASM_CPU_SH3_FREQ_H
+
+#define FRQCR			0xffffff80
+#define MIN_DIVISOR_NR		0
+#define MAX_DIVISOR_NR		4
+
+#endif /* __ASM_CPU_SH3_FREQ_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/mmu_context.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/mmu_context.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/mmu_context.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/mmu_context.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,27 @@
+/*
+ * include/asm-sh/cpu-sh3/mmu_context.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH3_MMU_CONTEXT_H
+#define __ASM_CPU_SH3_MMU_CONTEXT_H
+
+#define MMU_PTEH	0xFFFFFFF0	/* Page table entry register HIGH */
+#define MMU_PTEL	0xFFFFFFF4	/* Page table entry register LOW */
+#define MMU_TTB		0xFFFFFFF8	/* Translation table base register */
+#define MMU_TEA		0xFFFFFFFC	/* TLB Exception Address */
+
+#define MMUCR		0xFFFFFFE0	/* MMU Control Register */
+
+#define MMU_TLB_ADDRESS_ARRAY	0xF2000000
+#define MMU_PAGE_ASSOC_BIT	0x80
+
+#define MMU_NTLB_ENTRIES	128	/* for 7708 */
+#define MMU_CONTROL_INIT	0x007	/* SV=0, TF=1, IX=1, AT=1 */
+
+#endif /* __ASM_CPU_SH3_MMU_CONTEXT_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/rtc.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/rtc.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/rtc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/rtc.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,25 @@
+#ifndef __ASM_CPU_SH3_RTC_H
+#define __ASM_CPU_SH3_RTC_H
+
+/* SH-3 RTC */
+#define R64CNT  	0xfffffec0
+#define RSECCNT 	0xfffffec2
+#define RMINCNT 	0xfffffec4
+#define RHRCNT  	0xfffffec6
+#define RWKCNT  	0xfffffec8
+#define RDAYCNT 	0xfffffeca
+#define RMONCNT 	0xfffffecc
+#define RYRCNT  	0xfffffece
+#define RSECAR  	0xfffffed0
+#define RMINAR  	0xfffffed2
+#define RHRAR   	0xfffffed4
+#define RWKAR   	0xfffffed6
+#define RDAYAR  	0xfffffed8
+#define RMONAR  	0xfffffeda
+#define RCR1    	0xfffffedc
+#define RCR2    	0xfffffede
+
+#define RTC_BIT_INVERTED	0	/* No bug on SH7708, SH7709A */
+
+#endif /* __ASM_CPU_SH3_RTC_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/shmparam.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/shmparam.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/shmparam.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/shmparam.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,16 @@
+/*
+ * include/asm-sh/cpu-sh3/shmparam.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH3_SHMPARAM_H
+#define __ASM_CPU_SH3_SHMPARAM_H
+
+#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
+
+#endif /* __ASM_CPU_SH3_SHMPARAM_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/ubc.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/ubc.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/ubc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/ubc.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,27 @@
+/*
+ * include/asm-sh/cpu-sh3/ubc.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH3_UBC_H
+#define __ASM_CPU_SH3_UBC_H
+
+#define UBC_BARA                0xffffffb0
+#define UBC_BAMRA               0xffffffb4
+#define UBC_BBRA                0xffffffb8
+#define UBC_BASRA               0xffffffe4
+#define UBC_BARB                0xffffffa0
+#define UBC_BAMRB               0xffffffa4
+#define UBC_BBRB                0xffffffa8
+#define UBC_BASRB               0xffffffe8
+#define UBC_BDRB                0xffffff90
+#define UBC_BDMRB               0xffffff94
+#define UBC_BRCR                0xffffff98
+
+#endif /* __ASM_CPU_SH3_UBC_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh3/watchdog.h linux-2.5.73-bk10/include/asm-sh/cpu-sh3/watchdog.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh3/watchdog.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh3/watchdog.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,25 @@
+/*
+ * include/asm-sh/cpu-sh3/watchdog.h
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH3_WATCHDOG_H
+#define __ASM_CPU_SH3_WATCHDOG_H
+
+/* Register definitions */
+#define WTCNT		0xffffff84
+#define WTCSR		0xffffff86
+
+/* Bit definitions */
+#define WTCSR_TME	0x80
+#define WTCSR_WT	0x40
+#define WTCSR_RSTS	0x20
+#define WTCSR_WOVF	0x10
+#define WTCSR_IOVF	0x08
+
+#endif /* __ASM_CPU_SH3_WATCHDOG_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/addrspace.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/addrspace.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/addrspace.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/addrspace.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,26 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 by Kaz Kojima
+ *
+ * Defitions for the address spaces of the SH-4 CPUs.
+ */
+#ifndef __ASM_CPU_SH4_ADDRSPACE_H
+#define __ASM_CPU_SH4_ADDRSPACE_H
+
+/* Detailed P4SEG  */
+#define P4SEG_STORE_QUE	(P4SEG)
+#define P4SEG_IC_ADDR	0xf0000000
+#define P4SEG_IC_DATA	0xf1000000
+#define P4SEG_ITLB_ADDR	0xf2000000
+#define P4SEG_ITLB_DATA	0xf3000000
+#define P4SEG_OC_ADDR	0xf4000000
+#define P4SEG_OC_DATA	0xf5000000
+#define P4SEG_TLB_ADDR	0xf6000000
+#define P4SEG_TLB_DATA	0xf7000000
+#define P4SEG_REG_BASE	0xff000000
+
+#endif /* __ASM_CPU_SH4_ADDRSPACE_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/cache.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/cache.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/cache.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/cache.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,35 @@
+/*
+ * include/asm-sh/cpu-sh4/cache.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH4_CACHE_H
+#define __ASM_CPU_SH4_CACHE_H
+
+#define        L1_CACHE_BYTES  32
+
+#define CCR		0xff00001c	/* Address of Cache Control Register */
+#define CCR_CACHE_OCE	0x0001	/* Operand Cache Enable */
+#define CCR_CACHE_WT	0x0002	/* Write-Through (for P0,U0,P3) (else writeback)*/
+#define CCR_CACHE_CB	0x0004	/* Copy-Back (for P1) (else writethrough) */
+#define CCR_CACHE_OCI	0x0008	/* OC Invalidate */
+#define CCR_CACHE_ORA	0x0020	/* OC RAM Mode */
+#define CCR_CACHE_OIX	0x0080	/* OC Index Enable */
+#define CCR_CACHE_ICE	0x0100	/* Instruction Cache Enable */
+#define CCR_CACHE_ICI	0x0800	/* IC Invalidate */
+#define CCR_CACHE_IIX	0x8000	/* IC Index Enable */
+#define CCR_CACHE_EMODE	0x80000000	/* EMODE Enable */
+
+/* Default CCR setup: 8k+16k-byte cache,P1-wb,enable */
+#define CCR_CACHE_ENABLE	(CCR_CACHE_OCE|CCR_CACHE_ICE)
+#define CCR_CACHE_INVALIDATE	(CCR_CACHE_OCI|CCR_CACHE_ICI)
+
+#define CACHE_IC_ADDRESS_ARRAY	0xf0000000
+#define CACHE_OC_ADDRESS_ARRAY	0xf4000000
+
+#endif /* __ASM_CPU_SH4_CACHE_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/cacheflush.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/cacheflush.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/cacheflush.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/cacheflush.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,60 @@
+/*
+ * include/asm-sh/cpu-sh4/cacheflush.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH4_CACHEFLUSH_H
+#define __ASM_CPU_SH4_CACHEFLUSH_H
+
+/*
+ *  Caches are broken on SH-4 (unless we use write-through
+ *  caching; in which case they're only semi-broken),
+ *  so we need them.
+ */
+
+/* Page is 4K, OC size is 16K, there are four lines. */
+#define CACHE_ALIAS 0x00003000
+
+struct page;
+struct mm_struct;
+struct vm_area_struct;
+
+extern void flush_cache_all(void);
+extern void flush_cache_mm(struct mm_struct *mm);
+extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+			      unsigned long end);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_dcache_page(struct page *pg);
+extern void flush_icache_range(unsigned long start, unsigned long end);
+extern void flush_cache_sigtramp(unsigned long addr);
+extern void flush_icache_user_range(struct vm_area_struct *vma,
+				    struct page *page, unsigned long addr,
+				    int len);
+
+#define flush_icache_page(vma,pg)		do { } while (0)
+
+/* Initialization of P3 area for copy_user_page */
+extern void p3_cache_init(void);
+
+#define PG_mapped	PG_arch_1
+
+/* We provide our own get_unmapped_area to avoid cache alias issue */
+#define HAVE_ARCH_UNMAPPED_AREA
+
+#ifdef CONFIG_MMU
+extern int remap_area_pages(unsigned long addr, unsigned long phys_addr,
+			    unsigned long size, unsigned long flags);
+#else /* CONFIG_MMU */
+static inline int remap_area_pages(unsigned long addr, unsigned long phys_addr,
+				   unsigned long size, unsigned long flags)
+{
+	return 0;
+}
+#endif /* CONFIG_MMU */
+#endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/dma.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/dma.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/dma.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/dma.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,11 @@
+#ifndef __ASM_CPU_SH4_DMA_H
+#define __ASM_CPU_SH4_DMA_H
+
+#define SAR ((unsigned long[]){0xbfa00000,0xbfa00010,0xbfa00020,0xbfa00030})
+#define DAR ((unsigned long[]){0xbfa00004,0xbfa00014,0xbfa00024,0xbfa00034})
+#define DMATCR ((unsigned long[]){0xbfa00008,0xbfa00018,0xbfa00028,0xbfa00038})
+#define CHCR ((unsigned long[]){0xbfa0000c,0xbfa0001c,0xbfa0002c,0xbfa0003c})
+#define DMAOR 0xbfa00040UL
+
+#endif /* __ASM_CPU_SH4_DMA_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/freq.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/freq.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/freq.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/freq.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,18 @@
+/*
+ * include/asm-sh/cpu-sh4/freq.h
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH4_FREQ_H
+#define __ASM_CPU_SH4_FREQ_H
+
+#define FRQCR			0xffc00000
+#define MIN_DIVISOR_NR		0
+#define MAX_DIVISOR_NR		3
+
+#endif /* __ASM_CPU_SH4_FREQ_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/mmu_context.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/mmu_context.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/mmu_context.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/mmu_context.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,39 @@
+/*
+ * include/asm-sh/cpu-sh4/mmu_context.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH4_MMU_CONTEXT_H
+#define __ASM_CPU_SH4_MMU_CONTEXT_H
+
+#define MMU_PTEH	0xFF000000	/* Page table entry register HIGH */
+#define MMU_PTEL	0xFF000004	/* Page table entry register LOW */
+#define MMU_TTB		0xFF000008	/* Translation table base register */
+#define MMU_TEA		0xFF00000C	/* TLB Exception Address */
+#define MMU_PTEA	0xFF000034	/* Page table entry assistance register */
+
+#define MMUCR		0xFF000010	/* MMU Control Register */
+
+#define MMU_ITLB_ADDRESS_ARRAY	0xF2000000
+#define MMU_UTLB_ADDRESS_ARRAY	0xF6000000
+#define MMU_PAGE_ASSOC_BIT	0x80
+
+#define MMU_NTLB_ENTRIES	64	/* for 7750 */
+#define MMU_CONTROL_INIT	0x205	/* SQMD=1, SV=0, TI=1, AT=1 */
+
+#define MMU_ITLB_DATA_ARRAY	0xF3000000
+#define MMU_UTLB_DATA_ARRAY	0xF7000000
+
+#define MMU_UTLB_ENTRIES	   64
+#define MMU_U_ENTRY_SHIFT	    8
+#define MMU_UTLB_VALID		0x100
+#define MMU_ITLB_ENTRIES	    4
+#define MMU_I_ENTRY_SHIFT	    8
+#define MMU_ITLB_VALID		0x100
+
+#endif /* __ASM_CPU_SH4_MMU_CONTEXT_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/rtc.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/rtc.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/rtc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/rtc.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,25 @@
+#ifndef __ASM_CPU_SH4_RTC_H
+#define __ASM_CPU_SH4_RTC_H
+
+/* SH-4 RTC */
+#define R64CNT  	0xffc80000
+#define RSECCNT 	0xffc80004
+#define RMINCNT 	0xffc80008
+#define RHRCNT  	0xffc8000c
+#define RWKCNT  	0xffc80010
+#define RDAYCNT 	0xffc80014
+#define RMONCNT 	0xffc80018
+#define RYRCNT  	0xffc8001c  /* 16bit */
+#define RSECAR  	0xffc80020
+#define RMINAR  	0xffc80024
+#define RHRAR   	0xffc80028
+#define RWKAR   	0xffc8002c
+#define RDAYAR  	0xffc80030
+#define RMONAR  	0xffc80034
+#define RCR1    	0xffc80038
+#define RCR2    	0xffc8003c
+
+#define RTC_BIT_INVERTED	0x40	/* bug on SH7750, SH7750S */
+
+#endif /* __ASM_CPU_SH4_RTC_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/shmparam.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/shmparam.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/shmparam.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/shmparam.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,19 @@
+/*
+ * include/asm-sh/cpu-sh4/shmparam.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH4_SHMPARAM_H
+#define __ASM_CPU_SH4_SHMPARAM_H
+
+/*
+ * SH-4 has D-cache alias issue
+ */
+#define	SHMLBA (PAGE_SIZE*4)		 /* attach addr a multiple of this */
+
+#endif /* __ASM_CPU_SH4_SHMPARAM_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/ubc.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/ubc.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/ubc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/ubc.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,27 @@
+/*
+ * include/asm-sh/cpu-sh4/ubc.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH4_UBC_H
+#define __ASM_CPU_SH4_UBC_H
+
+#define UBC_BARA		0xff200000
+#define UBC_BAMRA		0xff200004
+#define UBC_BBRA		0xff200008
+#define UBC_BASRA		0xff000014
+#define UBC_BARB		0xff20000c
+#define UBC_BAMRB		0xff200010
+#define UBC_BBRB		0xff200014
+#define UBC_BASRB		0xff000018
+#define UBC_BDRB		0xff200018
+#define UBC_BDMRB		0xff20001c
+#define UBC_BRCR		0xff200020
+
+#endif /* __ASM_CPU_SH4_UBC_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cpu-sh4/watchdog.h linux-2.5.73-bk10/include/asm-sh/cpu-sh4/watchdog.h
--- linux-2.5.73-bk9/include/asm-sh/cpu-sh4/watchdog.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cpu-sh4/watchdog.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,25 @@
+/*
+ * include/asm-sh/cpu-sh4/watchdog.h
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH4_WATCHDOG_H
+#define __ASM_CPU_SH4_WATCHDOG_H
+
+/* Register definitions */
+#define WTCNT		0xffc00008
+#define WTCSR		0xffc0000c
+
+/* Bit definitions */
+#define WTCSR_TME	0x80
+#define WTCSR_WT	0x40
+#define WTCSR_RSTS	0x20
+#define WTCSR_WOVF	0x10
+#define WTCSR_IOVF	0x08
+
+#endif /* __ASM_CPU_SH4_WATCHDOG_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/cqreek/cqreek.h linux-2.5.73-bk10/include/asm-sh/cqreek/cqreek.h
--- linux-2.5.73-bk9/include/asm-sh/cqreek/cqreek.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/cqreek/cqreek.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,27 @@
+#ifndef __ASM_SH_CQREEK_CQREEK_H
+#define __ASM_SH_CQREEK_CQREEK_H
+
+#define BRIDGE_FEATURE		0x0002
+
+#define BRIDGE_IDE_CTRL		0x0018
+#define BRIDGE_IDE_INTR_LVL    	0x001A
+#define BRIDGE_IDE_INTR_MASK	0x001C
+#define BRIDGE_IDE_INTR_STAT	0x001E
+
+#define BRIDGE_ISA_CTRL		0x0028
+#define BRIDGE_ISA_INTR_LVL    	0x002A
+#define BRIDGE_ISA_INTR_MASK	0x002C
+#define BRIDGE_ISA_INTR_STAT	0x002E
+
+/* arch/sh/boards/cqreek/setup.c */
+extern void setup_cqreek(void);
+
+/* arch/sh/boards/cqreek/irq.c */
+extern int cqreek_has_ide, cqreek_has_isa;
+extern void init_cqreek_IRQ(void);
+
+/* arch/sh/boards/cqreek/io.c */
+extern unsigned long cqreek_port2addr(unsigned long port);
+
+#endif /* __ASM_SH_CQREEK_CQREEK_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/current.h linux-2.5.73-bk10/include/asm-sh/current.h
--- linux-2.5.73-bk9/include/asm-sh/current.h	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/current.h	2003-07-02 04:57:38.000000000 -0700
@@ -6,16 +6,13 @@
  *
  */
 
+#include <linux/thread_info.h>
+
 struct task_struct;
 
 static __inline__ struct task_struct * get_current(void)
 {
-	struct task_struct *current;
-
-	__asm__("stc	r7_bank, %0"
-		:"=r" (current));
-
-	return current;
+	return current_thread_info()->task;
 }
 
 #define current get_current()
diff -urN linux-2.5.73-bk9/include/asm-sh/delay.h linux-2.5.73-bk10/include/asm-sh/delay.h
--- linux-2.5.73-bk9/include/asm-sh/delay.h	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/delay.h	2003-07-02 04:57:38.000000000 -0700
@@ -8,8 +8,10 @@
  */
  
 extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
 
 extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
 extern void __const_udelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
 
@@ -17,4 +19,9 @@
 	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
 	__udelay(n))
 
+
+#define ndelay(n) (__builtin_constant_p(n) ? \
+	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+	__ndelay(n))
+
 #endif /* __ASM_SH_DELAY_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/div64.h linux-2.5.73-bk10/include/asm-sh/div64.h
--- linux-2.5.73-bk9/include/asm-sh/div64.h	2003-06-22 11:32:28.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/div64.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,10 +1,20 @@
 #ifndef __ASM_SH_DIV64
 #define __ASM_SH_DIV64
 
+extern u64 __div64_32(u64 n, u32 d);
+
 #define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
+u64 __n = (n), __q; \
+u32 __base = (base); \
+u32 __res; \
+if ((__n >> 32) == 0) { \
+	__res = ((unsigned long) __n) % (unsigned) __base; \
+	(n) = ((unsigned long) __n) / (unsigned) __base; \
+} else { \
+	__q = __div64_32(__n, __base); \
+	__res = __n - __q * __base; \
+	(n) = __q; \
+} \
 __res; })
 
 #endif /* __ASM_SH_DIV64 */
diff -urN linux-2.5.73-bk9/include/asm-sh/dma.h linux-2.5.73-bk10/include/asm-sh/dma.h
--- linux-2.5.73-bk9/include/asm-sh/dma.h	2003-06-22 11:32:32.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/dma.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,7 +1,12 @@
 #ifndef __ASM_SH_DMA_H
 #define __ASM_SH_DMA_H
 
+#ifdef CONFIG_SH_MPC1211
+#include <asm/mpc1211/dma.h>
+#else
+
 #include <linux/config.h>
+#include <asm/cpu/dma.h>
 #include <asm/io.h>		/* need byte IO */
 
 #define MAX_DMA_CHANNELS 8
@@ -14,20 +19,6 @@
 /* XXX: This is not applicable to SuperH, just needed for alloc_bootmem */
 #define MAX_DMA_ADDRESS      (PAGE_OFFSET+0x10000000)
 
-#if defined(__sh3__)
-#define SAR ((unsigned long[]){0xa4000020,0xa4000030,0xa4000040,0xa4000050})
-#define DAR ((unsigned long[]){0xa4000024,0xa4000034,0xa4000044,0xa4000054})
-#define DMATCR ((unsigned long[]){0xa4000028,0xa4000038,0xa4000048,0xa4000058})
-#define CHCR ((unsigned long[]){0xa400002c,0xa400003c,0xa400004c,0xa400005c})
-#define DMAOR 0xa4000060UL
-#elif defined(__SH4__)
-#define SAR ((unsigned long[]){0xbfa00000,0xbfa00010,0xbfa00020,0xbfa00030})
-#define DAR ((unsigned long[]){0xbfa00004,0xbfa00014,0xbfa00024,0xbfa00034})
-#define DMATCR ((unsigned long[]){0xbfa00008,0xbfa00018,0xbfa00028,0xbfa00038})
-#define CHCR ((unsigned long[]){0xbfa0000c,0xbfa0001c,0xbfa0002c,0xbfa0003c})
-#define DMAOR 0xbfa00040UL
-#endif
-
 #define DMTE_IRQ ((int[]){DMTE0_IRQ,DMTE1_IRQ,DMTE2_IRQ,DMTE3_IRQ})
 
 #define DMA_MODE_READ	0x00	/* I/O to memory, no autoinit, increment, single mode */
@@ -66,8 +57,6 @@
 
 struct dma_info_t {
 	unsigned int chan;
-	unsigned int mode_read;
-	unsigned int mode_write;
 	unsigned long dev_addr;
 	unsigned int mode;
 	unsigned long mem_addr;
@@ -93,5 +82,6 @@
 #define isa_dma_bridge_buggy 	(0)
 #endif
 
+#endif /* CONFIG_SH_MPC1211 */
 
 #endif /* __ASM_SH_DMA_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/dmida/io.h linux-2.5.73-bk10/include/asm-sh/dmida/io.h
--- linux-2.5.73-bk9/include/asm-sh/dmida/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/dmida/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,10 @@
+#ifndef __ASM_SH_DMIDA_IO_H
+#define __ASM_SH_DMIDA_IO_H
+
+/*
+ * Nothing special here.. just use the generic cchip io routines.
+ */
+#include <asm/hd64465/io.h>
+
+#endif /* __ASM_SH_DMIDA_IO_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/dreamcast/io.h linux-2.5.73-bk10/include/asm-sh/dreamcast/io.h
--- linux-2.5.73-bk9/include/asm-sh/dreamcast/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/dreamcast/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,49 @@
+/*
+ *	$Id: io.h,v 1.3 2003/05/04 19:30:14 lethal Exp $
+ *	IO functions for SEGA Dreamcast
+ */
+
+#ifndef _ASM_SH_IO_DREAMCAST_H
+#define _ASM_SH_IO_DREAMCAST_H
+
+#include <asm/io_generic.h>
+
+unsigned long dreamcast_isa_port2addr(unsigned long offset);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			generic_inb
+# define __inw			generic_inw
+# define __inl			generic_inl
+# define __outb			generic_outb
+# define __outw			generic_outw
+# define __outl			generic_outl
+
+# define __inb_p		generic_inb_p
+# define __inw_p		generic_inw
+# define __inl_p		generic_inl
+# define __outb_p		generic_outb_p
+# define __outw_p		generic_outw
+# define __outl_p		generic_outl
+
+# define __insb			generic_insb
+# define __insw			generic_insw
+# define __insl			generic_insl
+# define __outsb		generic_outsb
+# define __outsw		generic_outsw
+# define __outsl		generic_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	dreamcast_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_DREAMCAST_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/dreamcast/sysasic.h linux-2.5.73-bk10/include/asm-sh/dreamcast/sysasic.h
--- linux-2.5.73-bk9/include/asm-sh/dreamcast/sysasic.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/dreamcast/sysasic.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,35 @@
+/* include/asm-sh/dc_sysasic.h
+ *
+ * Definitions for the Dreamcast System ASIC and related peripherals.
+ *
+ * Copyright (c) 2001 M. R. Brown <mrbrown@linuxdc.org>
+ *
+ * This file is part of the LinuxDC project (www.linuxdc.org)
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ */
+
+#include <asm/irq.h>
+
+/* Hardware events -
+
+   Each of these events correspond to a bit within the Event Mask Registers/
+   Event Status Registers.  Because of the virtual IRQ numbering scheme, a
+   base offset must be used when calculating the virtual IRQ that each event
+   takes.
+*/
+
+#define HW_EVENT_IRQ_BASE  OFFCHIP_IRQ_BASE /* 48 */
+
+/* IRQ 13 */
+#define HW_EVENT_VSYNC     (HW_EVENT_IRQ_BASE +  5) /* VSync */
+#define HW_EVENT_MAPLE_DMA (HW_EVENT_IRQ_BASE + 12) /* Maple DMA complete */
+#define HW_EVENT_GDROM_DMA (HW_EVENT_IRQ_BASE + 14) /* GD-ROM DMA complete */
+
+/* IRQ 11 */
+#define HW_EVENT_GDROM_CMD (HW_EVENT_IRQ_BASE + 32) /* GD-ROM cmd. complete */
+#define HW_EVENT_AICA_SYS  (HW_EVENT_IRQ_BASE + 33) /* AICA-related */
+#define HW_EVENT_EXTERNAL  (HW_EVENT_IRQ_BASE + 35) /* Ext. (expansion) */
+
+#define HW_EVENT_IRQ_MAX (HW_EVENT_IRQ_BASE + 95)
diff -urN linux-2.5.73-bk9/include/asm-sh/ec3104/ec3104.h linux-2.5.73-bk10/include/asm-sh/ec3104/ec3104.h
--- linux-2.5.73-bk9/include/asm-sh/ec3104/ec3104.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/ec3104/ec3104.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,43 @@
+#ifndef __ASM_EC3104_H
+#define __ASM_EC3104_H
+
+
+/*
+ * Most of the register set is at 0xb0ec0000 - 0xb0ecffff.
+ *
+ * as far as I've figured it out the register map is:
+ * 0xb0ec0000 - id string
+ * 0xb0ec0XXX - power management
+ * 0xb0ec1XXX - interrupt control
+ * 0xb0ec3XXX - ps2 port (touch pad on aero 8000)
+ * 0xb0ec6XXX - i2c
+ * 0xb0ec7000 - first serial port (proprietary connector on aero 8000)
+ * 0xb0ec8000 - second serial port
+ * 0xb0ec9000 - third serial port
+ * 0xb0eca000 - fourth serial port (keyboard controller on aero 8000)
+ * 0xb0eccXXX - GPIO
+ * 0xb0ecdXXX - GPIO
+ */
+
+#define EC3104_BASE	0xb0ec0000
+
+#define EC3104_SER4_DATA	(EC3104_BASE+0xa000)
+#define EC3104_SER4_IIR		(EC3104_BASE+0xa008)
+#define EC3104_SER4_MCR		(EC3104_BASE+0xa010)
+#define EC3104_SER4_LSR		(EC3104_BASE+0xa014)
+#define EC3104_SER4_MSR		(EC3104_BASE+0xa018)
+
+/*
+ * our ISA bus.  this seems to be real ISA.
+ */
+#define EC3104_ISA_BASE	0xa5000000
+
+#define EC3104_IRQ	11
+#define EC3104_IRQBASE	64
+
+#define EC3104_IRQ_SER1	EC3104_IRQBASE + 7
+#define EC3104_IRQ_SER2	EC3104_IRQBASE + 8
+#define EC3104_IRQ_SER3	EC3104_IRQBASE + 9
+#define EC3104_IRQ_SER4	EC3104_IRQBASE + 10
+
+#endif /* __ASM_EC3104_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/ec3104/io.h linux-2.5.73-bk10/include/asm-sh/ec3104/io.h
--- linux-2.5.73-bk9/include/asm-sh/ec3104/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/ec3104/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,54 @@
+#ifndef _ASM_SH_IO_EC3104_H
+#define _ASM_SH_IO_EC3104_H
+
+#include <asm/io_generic.h>
+#include <linux/types.h>
+
+extern unsigned char ec3104_inb(unsigned long port);
+extern unsigned short ec3104_inw(unsigned long port);
+extern unsigned long ec3104_inl(unsigned long port);
+
+extern void ec3104_outb(unsigned char value, unsigned long port);
+extern void ec3104_outw(unsigned short value, unsigned long port);
+extern void ec3104_outl(unsigned long value, unsigned long port);
+
+extern int ec3104_irq_demux(int irq);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			ec3104_inb
+# define __inw			ec3104_inw
+# define __inl			ec3104_inl
+# define __outb			ec3104_outb
+# define __outw			ec3104_outw
+# define __outl			ec3104_outl
+
+# define __inb_p		ec3104_inb
+# define __inw_p		ec3104_inw
+# define __inl_p		ec3104_inl
+# define __outb_p		ec3104_outb
+# define __outw_p		ec3104_outw
+# define __outl_p		ec3104_outl
+
+# define __insb			generic_insb
+# define __insw			generic_insw
+# define __insl			generic_insl
+# define __outsb		generic_outsb
+# define __outsw		generic_outsw
+# define __outsl		generic_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	generic_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __ioremap_nocache	generic_ioremap_nocache
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_EC3104_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/ec3104/keyboard.h linux-2.5.73-bk10/include/asm-sh/ec3104/keyboard.h
--- linux-2.5.73-bk9/include/asm-sh/ec3104/keyboard.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/ec3104/keyboard.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,17 @@
+extern unsigned char ec3104_kbd_sysrq_xlate[];
+extern int ec3104_kbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int ec3104_kbd_getkeycode(unsigned int scancode);
+extern int ec3104_kbd_translate(unsigned char, unsigned char *, char);
+extern char ec3104_kbd_unexpected_up(unsigned char);
+extern void ec3104_kbd_leds(unsigned char);
+extern void ec3104_kbd_init_hw(void);
+
+#define SYSRQ_KEY 0x54
+
+#define kbd_sysrq_xlate ec3104_kbd_sysrq_xlate
+#define kbd_setkeycode ec3104_kbd_setkeycode
+#define kbd_getkeycode ec3104_kbd_getkeycode
+#define kbd_translate ec3104_kbd_translate
+#define kbd_unexpected_up ec3104_kbd_unexpected_up
+#define kbd_leds ec3104_kbd_leds
+#define kbd_init_hw ec3104_kbd_init_hw
diff -urN linux-2.5.73-bk9/include/asm-sh/ec3104/serial.h linux-2.5.73-bk10/include/asm-sh/ec3104/serial.h
--- linux-2.5.73-bk9/include/asm-sh/ec3104/serial.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/ec3104/serial.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,24 @@
+#include <asm/ec3104.h>
+/* Naturally we don't know the exact value but 115200 baud has a divisor
+ * of 9 and 19200 baud has a divisor of 52, so this seems like a good
+ * guess.  */
+#define BASE_BAUD (16800000 / 16)
+
+#define RS_TABLE_SIZE  3
+
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+/* there is a fourth serial port with the expected values as well, but
+ * it's got the keyboard controller behind it so we can't really use it
+ * (without moving the keyboard driver to userspace, which doesn't sound
+ * like a very good idea) */
+#define STD_SERIAL_PORT_DEFNS			\
+	/* UART CLK   PORT IRQ     FLAGS        */			\
+	{ 0, BASE_BAUD, 0x11C00, EC3104_IRQBASE+7, STD_COM_FLAGS }, /* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x12000, EC3104_IRQBASE+8, STD_COM_FLAGS }, /* ttyS1 */	\
+	{ 0, BASE_BAUD, 0x12400, EC3104_IRQBASE+9, STD_COM_FLAGS }, /* ttyS2 */
+
+#define SERIAL_PORT_DFNS STD_SERIAL_PORT_DEFNS
+
+/* XXX: This should be moved ino irq.h */
+#define irq_cannonicalize(x) (x)
diff -urN linux-2.5.73-bk9/include/asm-sh/elf.h linux-2.5.73-bk10/include/asm-sh/elf.h
--- linux-2.5.73-bk9/include/asm-sh/elf.h	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/elf.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,6 +1,47 @@
 #ifndef __ASM_SH_ELF_H
 #define __ASM_SH_ELF_H
 
+/* SH relocation types  */
+#define	R_SH_NONE		0
+#define	R_SH_DIR32		1
+#define	R_SH_REL32		2
+#define	R_SH_DIR8WPN		3
+#define	R_SH_IND12W		4
+#define	R_SH_DIR8WPL		5
+#define	R_SH_DIR8WPZ		6
+#define	R_SH_DIR8BP		7
+#define	R_SH_DIR8W		8
+#define	R_SH_DIR8L		9
+#define	R_SH_SWITCH16		25
+#define	R_SH_SWITCH32		26
+#define	R_SH_USES		27
+#define	R_SH_COUNT		28
+#define	R_SH_ALIGN		29
+#define	R_SH_CODE		30
+#define	R_SH_DATA		31
+#define	R_SH_LABEL		32
+#define	R_SH_SWITCH8		33
+#define	R_SH_GNU_VTINHERIT	34
+#define	R_SH_GNU_VTENTRY	35
+#define	R_SH_TLS_GD_32		144
+#define	R_SH_TLS_LD_32		145
+#define	R_SH_TLS_LDO_32		146
+#define	R_SH_TLS_IE_32		147
+#define	R_SH_TLS_LE_32		148
+#define	R_SH_TLS_DTPMOD32	149
+#define	R_SH_TLS_DTPOFF32	150
+#define	R_SH_TLS_TPOFF32	151
+#define	R_SH_GOT32		160
+#define	R_SH_PLT32		161
+#define	R_SH_COPY		162
+#define	R_SH_GLOB_DAT		163
+#define	R_SH_JMP_SLOT		164
+#define	R_SH_RELATIVE		165
+#define	R_SH_GOTOFF		166
+#define	R_SH_GOTPC		167
+/* Keep this the last entry.  */
+#define	R_SH_NUM		256
+
 /*
  * ELF register definitions..
  */
@@ -70,6 +111,11 @@
 
 #ifdef __KERNEL__
 #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
+extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
+
+#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
+#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
 #endif
 
 #endif /* __ASM_SH_ELF_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/floppy.h linux-2.5.73-bk10/include/asm-sh/floppy.h
--- linux-2.5.73-bk9/include/asm-sh/floppy.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/floppy.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,274 @@
+/*
+ * Architecture specific parts of the Floppy driver
+ *   include/asm-i386/floppy.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995
+ */
+#ifndef __ASM_SH_FLOPPY_H
+#define __ASM_SH_FLOPPY_H
+
+#include <linux/vmalloc.h>
+
+
+/*
+ * The DMA channel used by the floppy controller cannot access data at
+ * addresses >= 16MB
+ *
+ * Went back to the 1MB limit, as some people had problems with the floppy
+ * driver otherwise. It doesn't matter much for performance anyway, as most
+ * floppy accesses go through the track buffer.
+ */
+#define _CROSS_64KB(a,s,vdma) \
+(!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
+
+#define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
+
+
+#define SW fd_routine[use_virtual_dma&1]
+#define CSW fd_routine[can_use_virtual_dma & 1]
+
+
+#define fd_inb(port)			inb_p(port)
+#define fd_outb(port,value)		outb_p(port,value)
+
+#define fd_request_dma()        CSW._request_dma(FLOPPY_DMA,"floppy")
+#define fd_free_dma()           CSW._free_dma(FLOPPY_DMA)
+#define fd_enable_irq()         enable_irq(FLOPPY_IRQ)
+#define fd_disable_irq()        disable_irq(FLOPPY_IRQ)
+#define fd_free_irq()		free_irq(FLOPPY_IRQ, NULL)
+#define fd_get_dma_residue()    SW._get_dma_residue(FLOPPY_DMA)
+#define fd_dma_mem_alloc(size)	SW._dma_mem_alloc(size)
+#define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io)
+
+#define FLOPPY_CAN_FALLBACK_ON_NODMA
+
+static int virtual_dma_count;
+static int virtual_dma_residue;
+static char *virtual_dma_addr;
+static int virtual_dma_mode;
+static int doing_pdma;
+
+static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
+{
+	register unsigned char st;
+
+#undef TRACE_FLPY_INT
+
+#ifdef TRACE_FLPY_INT
+	static int calls=0;
+	static int bytes=0;
+	static int dma_wait=0;
+#endif
+	if(!doing_pdma) {
+		floppy_interrupt(irq, dev_id, regs);
+		return;
+	}
+
+#ifdef TRACE_FLPY_INT
+	if(!calls)
+		bytes = virtual_dma_count;
+#endif
+
+	{
+		register int lcount;
+		register char *lptr;
+
+		st = 1;
+		for(lcount=virtual_dma_count, lptr=virtual_dma_addr; 
+		    lcount; lcount--, lptr++) {
+			st=inb(virtual_dma_port+4) & 0xa0 ;
+			if(st != 0xa0) 
+				break;
+			if(virtual_dma_mode)
+				outb_p(*lptr, virtual_dma_port+5);
+			else
+				*lptr = inb_p(virtual_dma_port+5);
+		}
+		virtual_dma_count = lcount;
+		virtual_dma_addr = lptr;
+		st = inb(virtual_dma_port+4);
+	}
+
+#ifdef TRACE_FLPY_INT
+	calls++;
+#endif
+	if(st == 0x20)
+		return;
+	if(!(st & 0x20)) {
+		virtual_dma_residue += virtual_dma_count;
+		virtual_dma_count=0;
+#ifdef TRACE_FLPY_INT
+		printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", 
+		       virtual_dma_count, virtual_dma_residue, calls, bytes,
+		       dma_wait);
+		calls = 0;
+		dma_wait=0;
+#endif
+		doing_pdma = 0;
+		floppy_interrupt(irq, dev_id, regs);
+		return;
+	}
+#ifdef TRACE_FLPY_INT
+	if(!virtual_dma_count)
+		dma_wait++;
+#endif
+}
+
+static void fd_disable_dma(void)
+{
+	if(! (can_use_virtual_dma & 1))
+		disable_dma(FLOPPY_DMA);
+	doing_pdma = 0;
+	virtual_dma_residue += virtual_dma_count;
+	virtual_dma_count=0;
+}
+
+static int vdma_request_dma(unsigned int dmanr, const char * device_id)
+{
+	return 0;
+}
+
+static void vdma_nop(unsigned int dummy)
+{
+}
+
+
+static int vdma_get_dma_residue(unsigned int dummy)
+{
+	return virtual_dma_count + virtual_dma_residue;
+}
+
+
+static int fd_request_irq(void)
+{
+	if(can_use_virtual_dma)
+		return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT,
+						   "floppy", NULL);
+	else
+		return request_irq(FLOPPY_IRQ, floppy_interrupt,
+						   SA_INTERRUPT|SA_SAMPLE_RANDOM,
+						   "floppy", NULL);	
+
+}
+
+static unsigned long dma_mem_alloc(unsigned long size)
+{
+	return __get_dma_pages(GFP_KERNEL,get_order(size));
+}
+
+
+static unsigned long vdma_mem_alloc(unsigned long size)
+{
+	return (unsigned long) vmalloc(size);
+
+}
+
+#define nodma_mem_alloc(size) vdma_mem_alloc(size)
+
+static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
+{
+	if((unsigned int) addr >= (unsigned int) high_memory)
+		return vfree((void *)addr);
+	else
+		free_pages(addr, get_order(size));		
+}
+
+#define fd_dma_mem_free(addr, size)  _fd_dma_mem_free(addr, size) 
+
+static void _fd_chose_dma_mode(char *addr, unsigned long size)
+{
+	if(can_use_virtual_dma == 2) {
+		if((unsigned int) addr >= (unsigned int) high_memory ||
+		   virt_to_bus(addr) >= 0x10000000)
+			use_virtual_dma = 1;
+		else
+			use_virtual_dma = 0;
+	} else {
+		use_virtual_dma = can_use_virtual_dma & 1;
+	}
+}
+
+#define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size)
+
+
+static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
+{
+	doing_pdma = 1;
+	virtual_dma_port = io;
+	virtual_dma_mode = (mode  == DMA_MODE_WRITE);
+	virtual_dma_addr = addr;
+	virtual_dma_count = size;
+	virtual_dma_residue = 0;
+	return 0;
+}
+
+static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
+{
+#ifdef FLOPPY_SANITY_CHECK
+	if (CROSS_64KB(addr, size)) {
+		printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size);
+		return -1;
+	}
+#endif
+
+	dma_cache_wback_inv(addr, size);
+
+	/* actual, physical DMA */
+	doing_pdma = 0;
+	clear_dma_ff(FLOPPY_DMA);
+	set_dma_mode(FLOPPY_DMA,mode);
+	set_dma_addr(FLOPPY_DMA,virt_to_bus(addr));
+	set_dma_count(FLOPPY_DMA,size);
+	enable_dma(FLOPPY_DMA);
+	return 0;
+}
+
+struct fd_routine_l {
+	int (*_request_dma)(unsigned int dmanr, const char * device_id);
+	void (*_free_dma)(unsigned int dmanr);
+	int (*_get_dma_residue)(unsigned int dummy);
+	unsigned long (*_dma_mem_alloc) (unsigned long size);
+	int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
+} fd_routine[] = {
+	{
+		request_dma,
+		free_dma,
+		get_dma_residue,
+		dma_mem_alloc,
+		hard_dma_setup
+	},
+	{
+		vdma_request_dma,
+		vdma_nop,
+		vdma_get_dma_residue,
+		vdma_mem_alloc,
+		vdma_dma_setup
+	}
+};
+
+
+static int FDC1 = 0x3f0;
+static int FDC2 = -1;
+
+/*
+ * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock
+ * is needed to prevent corrupted CMOS RAM in case "insmod floppy"
+ * coincides with another rtc CMOS user.		Paul G.
+ */
+#define FLOPPY0_TYPE	(4)
+#define FLOPPY1_TYPE	(0)
+
+#define N_FDC 2
+#define N_DRIVE 8
+
+#define FLOPPY_MOTOR_MASK 0xf0
+
+#define AUTO_DMA
+
+#define EXTRA_FLOPPY_PARAMS
+
+#endif /* __ASM_SH_FLOPPY_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/freq.h linux-2.5.73-bk10/include/asm-sh/freq.h
--- linux-2.5.73-bk9/include/asm-sh/freq.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/freq.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,28 @@
+/*
+ * include/asm-sh/freq.h
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * 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.
+ */
+#ifndef __ASM_SH_FREQ_H
+#define __ASM_SH_FREQ_H
+
+#include <asm/cpu/freq.h>
+
+/* arch/sh/kernel/time.c */
+extern void get_current_frequency_divisors(unsigned int *ifc, unsigned int *pfc, unsigned int *bfc);
+
+extern unsigned int get_ifc_divisor(unsigned int value);
+extern unsigned int get_ifc_divisor(unsigned int value);
+extern unsigned int get_ifc_divisor(unsigned int value);
+
+extern unsigned int get_ifc_value(unsigned int divisor);
+extern unsigned int get_pfc_value(unsigned int divisor);
+extern unsigned int get_bfc_value(unsigned int divisor);
+
+#endif /* __ASM_SH_FREQ_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/hardirq.h linux-2.5.73-bk10/include/asm-sh/hardirq.h
--- linux-2.5.73-bk9/include/asm-sh/hardirq.h	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/hardirq.h	2003-07-02 04:57:38.000000000 -0700
@@ -3,12 +3,11 @@
 
 #include <linux/config.h>
 #include <linux/threads.h>
+#include <linux/irq.h>
 
 /* entry.S is sensitive to the offsets of these fields */
 typedef struct {
 	unsigned int __softirq_pending;
-	unsigned int __local_irq_count;
-	unsigned int __local_bh_count;
 	unsigned int __syscall_count;
 	struct task_struct * __ksoftirqd_task;
 } ____cacheline_aligned irq_cpustat_t;
@@ -16,9 +15,89 @@
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
 
 /*
+ * We put the hardirq and softirq counter into the preemption
+ * counter. The bitmask has the following meaning:
+ *
+ * - bits 0-7 are the preemption count (max preemption depth: 256)
+ * - bits 8-15 are the softirq count (max # of softirqs: 256)
+ * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
+ *
+ * - ( bit 26 is the PREEMPT_ACTIVE flag. )
+ *
+ * PREEMPT_MASK: 0x000000ff
+ * SOFTIRQ_MASK: 0x0000ff00
+ * HARDIRQ_MASK: 0x00ff0000
+ */
+
+#define PREEMPT_BITS	8
+#define SOFTIRQ_BITS	8
+#define HARDIRQ_BITS	8
+
+#define PREEMPT_SHIFT	0
+#define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
+#define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
+
+#define __MASK(x)	((1UL << (x))-1)
+
+#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
+#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
+#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
+
+#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
+#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
+#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
+
+#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
+#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
+#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
+
+/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+/*
  * Are we in an interrupt context? Either doing bottom half
  * or hardware interrupt processing?
  */
+#define in_irq()		(hardirq_count())
+#define in_softirq()		(softirq_count())
+#define in_interrupt()		(irq_count())
+
+
+#define hardirq_trylock()	(!in_interrupt())
+#define hardirq_endlock()	do { } while (0)
+
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
+#define nmi_enter()		(irq_enter())
+#define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
+
+#if CONFIG_PREEMPT
+# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
+# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
+#else
+# define in_atomic()	(preempt_count() != 0)
+# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#endif
+#define irq_exit()							\
+do {									\
+		preempt_count() -= IRQ_EXIT_OFFSET;			\
+		if (!in_interrupt() && softirq_pending(smp_processor_id())) \
+			do_softirq();					\
+		preempt_enable_no_resched();				\
+} while (0)
+
+#ifndef CONFIG_SMP
+# define synchronize_irq(irq)	barrier()
+#else
+extern void synchronize_irq(unsigned int irq);
+#endif /* CONFIG_SMP */
+
+/* XXX: MRB-remove
 #define in_interrupt() ({ int __cpu = smp_processor_id(); \
 	(local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
 
@@ -38,5 +117,7 @@
 
 #error Super-H SMP is not available
 
-#endif /* CONFIG_SMP */
+#endif
+*/
+
 #endif /* __ASM_SH_HARDIRQ_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/harp/harp.h linux-2.5.73-bk10/include/asm-sh/harp/harp.h
--- linux-2.5.73-bk9/include/asm-sh/harp/harp.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/harp/harp.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,43 @@
+/* 
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Defintions applicable to the STMicroelectronics ST40STB1 HARP and
+ * compatible boards.
+ */
+
+#if defined(CONFIG_SH_STB1_HARP)
+
+#define EPLD_BASE     0xa0800000
+
+#define EPLD_LED      (EPLD_BASE+0x000c0000)
+#define EPLD_INTSTAT0 (EPLD_BASE+0x00200000)
+#define EPLD_INTSTAT1 (EPLD_BASE+0x00240000)
+#define EPLD_INTMASK0 (EPLD_BASE+0x00280000)
+#define EPLD_INTMASK1 (EPLD_BASE+0x002c0000)
+#define EPLD_PAGEADDR (EPLD_BASE+0x00300000)
+#define EPLD_REVID1   (EPLD_BASE+0x00380000)
+#define EPLD_REVID2   (EPLD_BASE+0x003c0000)
+
+#define EPLD_LED_ON  1
+#define EPLD_LED_OFF 0
+
+#elif defined(CONFIG_SH_STB1_OVERDRIVE)
+
+#define EPLD_BASE     0xa7000000
+
+#define EPLD_REVID    (EPLD_BASE+0x00000000)
+#define EPLD_LED      (EPLD_BASE+0x00040000)
+#define EPLD_INTMASK0 (EPLD_BASE+0x001c0000)
+#define EPLD_INTMASK1 (EPLD_BASE+0x00200000)
+#define EPLD_INTSTAT0 (EPLD_BASE+0x00240000)
+#define EPLD_INTSTAT1 (EPLD_BASE+0x00280000)
+
+#define EPLD_LED_ON  0
+#define EPLD_LED_OFF 1
+
+#else
+#error Unknown board
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/harp/io.h linux-2.5.73-bk10/include/asm-sh/harp/io.h
--- linux-2.5.73-bk9/include/asm-sh/harp/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/harp/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,10 @@
+#ifndef __ASM_SH_HARP_IO_H
+#define __ASM_SH_HARP_IO_H
+
+/*
+ * Nothing special here.. just use the generic cchip io routines.
+ */
+#include <asm/hd64465/io.h>
+
+#endif /* __ASM_SH_HARP_IO_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/hd64461/hd64461.h linux-2.5.73-bk10/include/asm-sh/hd64461/hd64461.h
--- linux-2.5.73-bk9/include/asm-sh/hd64461/hd64461.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/hd64461/hd64461.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,75 @@
+#ifndef __ASM_SH_HD64461
+#define __ASM_SH_HD64461
+/*
+ *	$Id: hd64461.h,v 1.3 2003/05/04 19:30:14 lethal Exp $
+ *	Copyright (C) 2000 YAEGASHI Takeshi
+ *	Hitachi HD64461 companion chip support
+ */
+#include <linux/config.h>
+
+#define HD64461_STBCR	0x10000
+#define HD64461_SYSCR	0x10002
+#define HD64461_SCPUCR	0x10004
+
+#define HD64461_LCDCBAR		0x11000
+#define HD64461_LCDCLOR		0x11002
+#define HD64461_LCDCCRR		0x11004
+#define	HD64461_LDR1		0x11010
+#define	HD64461_LDR2		0x11012
+#define	HD64461_LDHNCR		0x11014
+#define	HD64461_LDHNSR		0x11016
+#define HD64461_LDVNTR		0x11018
+#define HD64461_LDVNDR		0x1101a
+#define HD64461_LDVSPR		0x1101c
+#define HD64461_LDR3		0x1101e
+
+#define HD64461_CPTWAR		0x11030	
+#define HD64461_CPTWDR		0x11032
+#define HD64461_CPTRAR		0x11034	
+#define HD64461_CPTRDR		0x11036
+
+#define HD64461_PCC0ISR         0x12000
+#define HD64461_PCC0GCR         0x12002
+#define HD64461_PCC0CSCR        0x12004
+#define HD64461_PCC0CSCIER      0x12006
+#define HD64461_PCC0SCR         0x12008
+#define HD64461_PCC1ISR         0x12010
+#define HD64461_PCC1GCR         0x12012
+#define HD64461_PCC1CSCR        0x12014
+#define HD64461_PCC1CSCIER      0x12016
+#define HD64461_PCC1SCR         0x12018
+#define HD64461_P0OCR           0x1202a
+#define HD64461_P1OCR           0x1202c
+#define HD64461_PGCR            0x1202e
+
+#define HD64461_GPACR		0x14000
+#define HD64461_GPBCR		0x14002
+#define HD64461_GPCCR		0x14004
+#define HD64461_GPDCR		0x14006
+#define HD64461_GPADR		0x14010
+#define HD64461_GPBDR		0x14012
+#define HD64461_GPCDR		0x14014
+#define HD64461_GPDDR		0x14016
+#define HD64461_GPAICR		0x14020
+#define HD64461_GPBICR		0x14022
+#define HD64461_GPCICR		0x14024
+#define HD64461_GPDICR		0x14026
+#define HD64461_GPAISR		0x14040
+#define HD64461_GPBISR		0x14042
+#define HD64461_GPCISR		0x14044
+#define HD64461_GPDISR		0x14046
+
+#define HD64461_NIRR		0x15000
+#define HD64461_NIMR		0x15002
+
+#ifndef CONFIG_HD64461_IOBASE
+#define CONFIG_HD64461_IOBASE	0xb0000000
+#endif
+#ifndef CONFIG_HD64461_IRQ
+#define CONFIG_HD64461_IRQ	36
+#endif
+
+#define HD64461_IRQBASE		OFFCHIP_IRQ_BASE
+#define HD64461_IRQ_NUM 	16
+
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/hd64461/io.h linux-2.5.73-bk10/include/asm-sh/hd64461/io.h
--- linux-2.5.73-bk9/include/asm-sh/hd64461/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/hd64461/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,73 @@
+/*
+ * include/asm-sh/io_hd64461.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an HD64461
+ */
+
+#ifndef _ASM_SH_IO_HD64461_H
+#define _ASM_SH_IO_HD64461_H
+
+#include <asm/io_generic.h>
+
+extern unsigned char hd64461_inb(unsigned long port);
+extern unsigned short hd64461_inw(unsigned long port);
+extern unsigned int hd64461_inl(unsigned long port);
+
+extern void hd64461_outb(unsigned char value, unsigned long port);
+extern void hd64461_outw(unsigned short value, unsigned long port);
+extern void hd64461_outl(unsigned int value, unsigned long port);
+
+extern unsigned char hd64461_inb_p(unsigned long port);
+extern void hd64461_outb_p(unsigned char value, unsigned long port);
+
+extern void hd64461_insb(unsigned long port, void *addr, unsigned long count);
+extern void hd64461_insw(unsigned long port, void *addr, unsigned long count);
+extern void hd64461_insl(unsigned long port, void *addr, unsigned long count);
+extern void hd64461_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void hd64461_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void hd64461_outsl(unsigned long port, const void *addr, unsigned long count);
+extern int hd64461_irq_demux(int irq);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			hd64461_inb
+# define __inw			hd64461_inw
+# define __inl			hd64461_inl
+# define __outb			hd64461_outb
+# define __outw			hd64461_outw
+# define __outl			hd64461_outl
+
+# define __inb_p		hd64461_inb_p
+# define __inw_p		hd64461_inw
+# define __inl_p		hd64461_inl
+# define __outb_p		hd64461_outb_p
+# define __outw_p		hd64461_outw
+# define __outl_p		hd64461_outl
+
+# define __insb			hd64461_insb
+# define __insw			hd64461_insw
+# define __insl			hd64461_insl
+# define __outsb		hd64461_outsb
+# define __outsw		hd64461_outsw
+# define __outsl		hd64461_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	generic_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __ioremap_nocache	generic_ioremap_nocache
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_HD64461_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/hd64465/gpio.h linux-2.5.73-bk10/include/asm-sh/hd64465/gpio.h
--- linux-2.5.73-bk9/include/asm-sh/hd64465/gpio.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/hd64465/gpio.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,46 @@
+#ifndef _ASM_SH_HD64465_GPIO_
+#define _ASM_SH_HD64465_GPIO_ 1
+/*
+ * $Id: gpio.h,v 1.3 2003/05/04 19:30:14 lethal Exp $
+ *
+ * Hitachi HD64465 companion chip: General Purpose IO pins support.
+ * This layer enables other device drivers to configure GPIO
+ * pins, get and set their values, and register an interrupt
+ * routine for when input pins change in hardware.
+ *
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc.
+ */
+#include <asm/hd64465.h>
+
+/* Macro to construct a portpin number (used in all
+ * subsequent functions) from a port letter and a pin
+ * number, e.g. HD64465_GPIO_PORTPIN('A', 5).
+ */
+#define HD64465_GPIO_PORTPIN(port,pin)	(((port)-'A')<<3|(pin))
+
+/* Pin configuration constants for _configure() */
+#define HD64465_GPIO_FUNCTION2	0	/* use the pin's *other* function */
+#define HD64465_GPIO_OUT	1	/* output */
+#define HD64465_GPIO_IN_PULLUP	2	/* input, pull-up MOS on */
+#define HD64465_GPIO_IN		3	/* input */
+
+/* Configure a pin's direction */
+extern void hd64465_gpio_configure(int portpin, int direction);
+
+/* Get, set value */
+extern void hd64465_gpio_set_pin(int portpin, unsigned int value);
+extern unsigned int hd64465_gpio_get_pin(int portpin);
+extern void hd64465_gpio_set_port(int port, unsigned int value);
+extern unsigned int hd64465_gpio_get_port(int port);
+
+/* mode constants for _register_irq() */
+#define HD64465_GPIO_FALLING	0
+#define HD64465_GPIO_RISING	1
+
+/* Interrupt on external value change */
+extern void hd64465_gpio_register_irq(int portpin, int mode,
+	void (*handler)(int portpin, void *dev), void *dev);
+extern void hd64465_gpio_unregister_irq(int portpin);
+
+#endif /* _ASM_SH_HD64465_GPIO_  */
diff -urN linux-2.5.73-bk9/include/asm-sh/hd64465/hd64465.h linux-2.5.73-bk10/include/asm-sh/hd64465/hd64465.h
--- linux-2.5.73-bk9/include/asm-sh/hd64465/hd64465.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/hd64465/hd64465.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,257 @@
+#ifndef _ASM_SH_HD64465_
+#define _ASM_SH_HD64465_ 1
+/*
+ * $Id: hd64465.h,v 1.3 2003/05/04 19:30:15 lethal Exp $
+ *
+ * Hitachi HD64465 companion chip support
+ *
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc.
+ *
+ * Derived from <asm/hd64461.h> which bore the message:
+ * Copyright (C) 2000 YAEGASHI Takeshi
+ */
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+/*
+ * Note that registers are defined here as virtual port numbers,
+ * which have no meaning except to get translated by hd64465_isa_port2addr()
+ * to an address in the range 0xb0000000-0xb3ffffff.  Note that
+ * this translation happens to consist of adding the lower 16 bits
+ * of the virtual port number to 0xb0000000.  Note also that the manual
+ * shows addresses as absolute physical addresses starting at 0x10000000,
+ * so e.g. the NIRR register is listed as 0x15000 here, 0x10005000 in the
+ * manual, and accessed using address 0xb0005000 - Greg.
+ */
+
+/* System registers */
+#define HD64465_REG_SRR     0x1000c 	/* System Revision Register */
+#define HD64465_REG_SDID    0x10010 	/* System Device ID Reg */
+#define     HD64465_SDID            0x8122  /* 64465 device ID */
+
+/* Power Management registers */
+#define HD64465_REG_SMSCR   0x10000 	/* System Module Standby Control Reg */
+#define	    HD64465_SMSCR_PS2ST     0x4000  /* PS/2 Standby */
+#define	    HD64465_SMSCR_ADCST     0x1000  /* ADC Standby */
+#define	    HD64465_SMSCR_UARTST    0x0800  /* UART Standby */
+#define	    HD64465_SMSCR_SCDIST    0x0200  /* Serial Codec Standby */
+#define	    HD64465_SMSCR_PPST	    0x0100  /* Parallel Port Standby */
+#define	    HD64465_SMSCR_PC0ST     0x0040  /* PCMCIA0 Standby */
+#define	    HD64465_SMSCR_PC1ST     0x0020  /* PCMCIA1 Standby */
+#define	    HD64465_SMSCR_AFEST     0x0010  /* AFE Standby */
+#define	    HD64465_SMSCR_TM0ST     0x0008  /* Timer0 Standby */
+#define	    HD64465_SMSCR_TM1ST     0x0004  /* Timer1 Standby */
+#define	    HD64465_SMSCR_IRDAST    0x0002  /* IRDA Standby */
+#define	    HD64465_SMSCR_KBCST     0x0001  /* Keyboard Controller Standby */
+ 
+/* Interrupt Controller registers */
+#define HD64465_REG_NIRR    0x15000  	/* Interrupt Request Register */
+#define HD64465_REG_NIMR    0x15002  	/* Interrupt Mask Register */
+#define HD64465_REG_NITR    0x15004  	/* Interrupt Trigger Mode Register */
+
+/* Timer registers */
+#define HD64465_REG_TCVR1   0x16000  	/* Timer 1 constant value register  */
+#define HD64465_REG_TCVR0   0x16002	/* Timer 0 constant value register  */
+#define HD64465_REG_TRVR1   0x16004	/* Timer 1 read value register  */
+#define HD64465_REG_TRVR0   0x16006	/* Timer 0 read value register  */
+#define HD64465_REG_TCR1    0x16008	/* Timer 1 control register  */
+#define HD64465_REG_TCR0    0x1600A	/* Timer 0 control register  */
+#define	    HD64465_TCR_EADT 	0x10	    /* Enable ADTRIG# signal */
+#define	    HD64465_TCR_ETMO 	0x08	    /* Enable TMO signal */
+#define	    HD64465_TCR_PST_MASK 0x06	    /* Clock Prescale */
+#define	    HD64465_TCR_PST_1 	0x06	    /* 1:1 */
+#define	    HD64465_TCR_PST_4 	0x04	    /* 1:4 */
+#define	    HD64465_TCR_PST_8 	0x02	    /* 1:8 */
+#define	    HD64465_TCR_PST_16 	0x00	    /* 1:16 */
+#define	    HD64465_TCR_TSTP 	0x01	    /* Start/Stop timer */
+#define HD64465_REG_TIRR    0x1600C	/* Timer interrupt request register  */
+#define HD64465_REG_TIDR    0x1600E	/* Timer interrupt disable register  */
+#define HD64465_REG_PWM1CS  0x16010	/* PWM 1 clock scale register  */
+#define HD64465_REG_PWM1LPC 0x16012	/* PWM 1 low pulse width counter register  */
+#define HD64465_REG_PWM1HPC 0x16014	/* PWM 1 high pulse width counter register  */
+#define HD64465_REG_PWM0CS  0x16018	/* PWM 0 clock scale register  */
+#define HD64465_REG_PWM0LPC 0x1601A	/* PWM 0 low pulse width counter register  */
+#define HD64465_REG_PWM0HPC 0x1601C	/* PWM 0 high pulse width counter register  */
+
+/* Analog/Digital Converter registers */
+#define HD64465_REG_ADDRA   0x1E000	/* A/D data register A */
+#define HD64465_REG_ADDRB   0x1E002	/* A/D data register B */
+#define HD64465_REG_ADDRC   0x1E004	/* A/D data register C */
+#define HD64465_REG_ADDRD   0x1E006	/* A/D data register D */
+#define HD64465_REG_ADCSR   0x1E008	/* A/D control/status register */
+#define     HD64465_ADCSR_ADF	    0x80    /* A/D End Flag */
+#define     HD64465_ADCSR_ADST	    0x40    /* A/D Start Flag */
+#define     HD64465_ADCSR_ADIS	    0x20    /* A/D Interrupt Status */
+#define     HD64465_ADCSR_TRGE	    0x10    /* A/D Trigger Enable */
+#define     HD64465_ADCSR_ADIE	    0x08    /* A/D Interrupt Enable */
+#define     HD64465_ADCSR_SCAN	    0x04    /* A/D Scan Mode */
+#define     HD64465_ADCSR_CH_MASK   0x03    /* A/D Channel */
+#define HD64465_REG_ADCALCR 0x1E00A  	/* A/D calibration sample control */
+#define HD64465_REG_ADCAL   0x1E00C  	/* A/D calibration data register */
+
+
+/* General Purpose I/O ports registers */
+#define HD64465_REG_GPACR   0x14000  	/* Port A Control Register */
+#define HD64465_REG_GPBCR   0x14002  	/* Port B Control Register */
+#define HD64465_REG_GPCCR   0x14004  	/* Port C Control Register */
+#define HD64465_REG_GPDCR   0x14006  	/* Port D Control Register */
+#define HD64465_REG_GPECR   0x14008  	/* Port E Control Register */
+#define HD64465_REG_GPADR   0x14010  	/* Port A Data Register */
+#define HD64465_REG_GPBDR   0x14012  	/* Port B Data Register */
+#define HD64465_REG_GPCDR   0x14014  	/* Port C Data Register */
+#define HD64465_REG_GPDDR   0x14016  	/* Port D Data Register */
+#define HD64465_REG_GPEDR   0x14018  	/* Port E Data Register */
+#define HD64465_REG_GPAICR  0x14020  	/* Port A Interrupt Control Register */
+#define HD64465_REG_GPBICR  0x14022  	/* Port B Interrupt Control Register */
+#define HD64465_REG_GPCICR  0x14024  	/* Port C Interrupt Control Register */
+#define HD64465_REG_GPDICR  0x14026  	/* Port D Interrupt Control Register */
+#define HD64465_REG_GPEICR  0x14028  	/* Port E Interrupt Control Register */
+#define HD64465_REG_GPAISR  0x14040  	/* Port A Interrupt Status Register */
+#define HD64465_REG_GPBISR  0x14042  	/* Port B Interrupt Status Register */
+#define HD64465_REG_GPCISR  0x14044  	/* Port C Interrupt Status Register */
+#define HD64465_REG_GPDISR  0x14046  	/* Port D Interrupt Status Register */
+#define HD64465_REG_GPEISR  0x14048  	/* Port E Interrupt Status Register */
+
+/* PCMCIA bridge interface */
+#define HD64465_REG_PCC0ISR	0x12000	/* socket 0 interface status */ 
+#define     HD64465_PCCISR_PREADY   	 0x80    /* mem card ready / io card IREQ */
+#define     HD64465_PCCISR_PIREQ    	 0x80
+#define     HD64465_PCCISR_PMWP     	 0x40    /* mem card write-protected */
+#define     HD64465_PCCISR_PVS2 	 0x20    /* voltage select pin 2 */
+#define     HD64465_PCCISR_PVS1 	 0x10    /* voltage select pin 1 */
+#define     HD64465_PCCISR_PCD_MASK 	 0x0c    /* card detect */
+#define     HD64465_PCCISR_PBVD_MASK     0x03    /* battery voltage */
+#define     HD64465_PCCISR_PBVD_BATGOOD  0x03    /* battery good */
+#define     HD64465_PCCISR_PBVD_BATWARN  0x01    /* battery low warning */
+#define     HD64465_PCCISR_PBVD_BATDEAD1 0x02    /* battery dead */
+#define     HD64465_PCCISR_PBVD_BATDEAD2 0x00    /* battery dead */
+#define HD64465_REG_PCC0GCR	0x12002	/* socket 0 general control */ 
+#define     HD64465_PCCGCR_PDRV   	 0x80    /* output drive */
+#define     HD64465_PCCGCR_PCCR   	 0x40    /* PC card reset */
+#define     HD64465_PCCGCR_PCCT   	 0x20    /* PC card type, 1=IO&mem, 0=mem */
+#define     HD64465_PCCGCR_PVCC0   	 0x10    /* voltage control pin VCC0SEL0 */
+#define     HD64465_PCCGCR_PMMOD   	 0x08    /* memory mode */
+#define     HD64465_PCCGCR_PPA25   	 0x04    /* pin A25 */
+#define     HD64465_PCCGCR_PPA24   	 0x02    /* pin A24 */
+#define     HD64465_PCCGCR_PREG   	 0x01    /* ping PCC0REG# */
+#define HD64465_REG_PCC0CSCR	0x12004	/* socket 0 card status change */ 
+#define     HD64465_PCCCSCR_PSCDI   	 0x80    /* sw card detect intr */
+#define     HD64465_PCCCSCR_PSWSEL   	 0x40    /* power select */
+#define     HD64465_PCCCSCR_PIREQ   	 0x20    /* IREQ intr req */
+#define     HD64465_PCCCSCR_PSC   	 0x10    /* STSCHG (status change) pin */
+#define     HD64465_PCCCSCR_PCDC   	 0x08    /* CD (card detect) change */
+#define     HD64465_PCCCSCR_PRC   	 0x04    /* ready change */
+#define     HD64465_PCCCSCR_PBW   	 0x02    /* battery warning change */
+#define     HD64465_PCCCSCR_PBD   	 0x01    /* battery dead change */
+#define HD64465_REG_PCC0CSCIER	0x12006	/* socket 0 card status change interrupt enable */ 
+#define     HD64465_PCCCSCIER_PCRE   	 0x80    /* change reset enable */
+#define     HD64465_PCCCSCIER_PIREQE_MASK   	0x60   /* IREQ enable */
+#define     HD64465_PCCCSCIER_PIREQE_DISABLED	0x00   /* IREQ disabled */
+#define     HD64465_PCCCSCIER_PIREQE_LEVEL  	0x20   /* IREQ level-triggered */
+#define     HD64465_PCCCSCIER_PIREQE_FALLING	0x40   /* IREQ falling-edge-trig */
+#define     HD64465_PCCCSCIER_PIREQE_RISING 	0x60   /* IREQ rising-edge-trig */
+#define     HD64465_PCCCSCIER_PSCE   	 0x10    /* status change enable */
+#define     HD64465_PCCCSCIER_PCDE   	 0x08    /* card detect change enable */
+#define     HD64465_PCCCSCIER_PRE   	 0x04    /* ready change enable */
+#define     HD64465_PCCCSCIER_PBWE   	 0x02    /* battery warn change enable */
+#define     HD64465_PCCCSCIER_PBDE   	 0x01    /* battery dead change enable*/
+#define HD64465_REG_PCC0SCR	0x12008	/* socket 0 software control */ 
+#define     HD64465_PCCSCR_SHDN   	 0x10    /* TPS2206 SHutDowN pin */
+#define     HD64465_PCCSCR_SWP   	 0x01    /* write protect */
+#define HD64465_REG_PCCPSR	0x1200A	/* serial power switch control */ 
+#define HD64465_REG_PCC1ISR	0x12010	/* socket 1 interface status */ 
+#define HD64465_REG_PCC1GCR	0x12012	/* socket 1 general control */ 
+#define HD64465_REG_PCC1CSCR	0x12014	/* socket 1 card status change */ 
+#define HD64465_REG_PCC1CSCIER	0x12016	/* socket 1 card status change interrupt enable */ 
+#define HD64465_REG_PCC1SCR	0x12018	/* socket 1 software control */ 
+
+
+/* PS/2 Keyboard and mouse controller -- *not* register compatible */
+#define HD64465_REG_KBCSR   	0x1dc00 /* Keyboard Control/Status reg */
+#define     HD64465_KBCSR_KBCIE   	 0x8000    /* KBCK Input Enable */
+#define     HD64465_KBCSR_KBCOE   	 0x4000    /* KBCK Output Enable */
+#define     HD64465_KBCSR_KBDOE   	 0x2000    /* KB DATA Output Enable */
+#define     HD64465_KBCSR_KBCD   	 0x1000    /* KBCK Driven */
+#define     HD64465_KBCSR_KBDD   	 0x0800    /* KB DATA Driven */
+#define     HD64465_KBCSR_KBCS   	 0x0400    /* KBCK pin Status */
+#define     HD64465_KBCSR_KBDS   	 0x0200    /* KB DATA pin Status */
+#define     HD64465_KBCSR_KBDP   	 0x0100    /* KB DATA Parity bit */
+#define     HD64465_KBCSR_KBD_MASK   	 0x00ff    /* KD DATA shift reg */
+#define HD64465_REG_KBISR   	0x1dc04 /* Keyboard Interrupt Status reg */
+#define     HD64465_KBISR_KBRDF   	 0x0001    /* KB Received Data Full */
+#define HD64465_REG_MSCSR   	0x1dc10 /* Mouse Control/Status reg */
+#define HD64465_REG_MSISR   	0x1dc14 /* Mouse Interrupt Status reg */
+
+
+/*
+ * Logical address at which the HD64465 is mapped.  Note that this
+ * should always be in the P2 segment (uncached and untranslated).
+ */
+#ifndef CONFIG_HD64465_IOBASE
+#define CONFIG_HD64465_IOBASE	0xb0000000
+#endif
+/*
+ * The HD64465 multiplexes all its modules' interrupts onto
+ * this single interrupt.
+ */
+#ifndef CONFIG_HD64465_IRQ
+#define CONFIG_HD64465_IRQ	5
+#endif
+
+
+#define _HD64465_IO_MASK	0xf8000000
+#define is_hd64465_addr(addr) \
+	((addr & _HD64465_IO_MASK) == (CONFIG_HD64465_IOBASE & _HD64465_IO_MASK))
+
+/*
+ * A range of 16 virtual interrupts generated by
+ * demuxing the HD64465 muxed interrupt.
+ */
+#define HD64465_IRQ_BASE	OFFCHIP_IRQ_BASE
+#define HD64465_IRQ_NUM 	16
+#define HD64465_IRQ_ADC     	(HD64465_IRQ_BASE+0)
+#define HD64465_IRQ_USB     	(HD64465_IRQ_BASE+1)
+#define HD64465_IRQ_SCDI    	(HD64465_IRQ_BASE+2)
+#define HD64465_IRQ_PARALLEL	(HD64465_IRQ_BASE+3)
+/* bit 4 is reserved */
+#define HD64465_IRQ_UART    	(HD64465_IRQ_BASE+5)
+#define HD64465_IRQ_IRDA    	(HD64465_IRQ_BASE+6)
+#define HD64465_IRQ_PS2MOUSE	(HD64465_IRQ_BASE+7)
+#define HD64465_IRQ_KBC     	(HD64465_IRQ_BASE+8)
+#define HD64465_IRQ_TIMER1   	(HD64465_IRQ_BASE+9)
+#define HD64465_IRQ_TIMER0  	(HD64465_IRQ_BASE+10)
+#define HD64465_IRQ_GPIO    	(HD64465_IRQ_BASE+11)
+#define HD64465_IRQ_AFE     	(HD64465_IRQ_BASE+12)
+#define HD64465_IRQ_PCMCIA1 	(HD64465_IRQ_BASE+13)
+#define HD64465_IRQ_PCMCIA0 	(HD64465_IRQ_BASE+14)
+#define HD64465_IRQ_PS2KBD     	(HD64465_IRQ_BASE+15)
+
+/* Constants for PCMCIA mappings */
+#define HD64465_PCC_WINDOW	0x01000000
+
+#define HD64465_PCC0_BASE	0xb8000000	/* area 6 */
+#define HD64465_PCC0_ATTR	(HD64465_PCC0_BASE)
+#define HD64465_PCC0_COMM	(HD64465_PCC0_BASE+HD64465_PCC_WINDOW)
+#define HD64465_PCC0_IO		(HD64465_PCC0_BASE+2*HD64465_PCC_WINDOW)
+
+#define HD64465_PCC1_BASE	0xb4000000	/* area 5 */
+#define HD64465_PCC1_ATTR	(HD64465_PCC1_BASE)
+#define HD64465_PCC1_COMM	(HD64465_PCC1_BASE+HD64465_PCC_WINDOW)
+#define HD64465_PCC1_IO		(HD64465_PCC1_BASE+2*HD64465_PCC_WINDOW)
+
+/*
+ * Base of USB controller interface (as memory)
+ */
+#define HD64465_USB_BASE    	(CONFIG_HD64465_IOBASE+0xb000)
+#define HD64465_USB_LEN    	0x1000
+/*
+ * Base of embedded SRAM, used for USB controller.
+ */
+#define HD64465_SRAM_BASE    	(CONFIG_HD64465_IOBASE+0x9000)
+#define HD64465_SRAM_LEN    	0x1000
+
+
+
+#endif /* _ASM_SH_HD64465_  */
diff -urN linux-2.5.73-bk9/include/asm-sh/hd64465/io.h linux-2.5.73-bk10/include/asm-sh/hd64465/io.h
--- linux-2.5.73-bk9/include/asm-sh/hd64465/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/hd64465/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,90 @@
+/*
+ * include/asm-sh/io_hd64465.h
+ *
+ * By Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc.
+ *
+ * Derived from io_hd64461.h, which bore the message:
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an HD64465 "Windows CE Intelligent Peripheral Controller".
+ */
+
+#ifndef _ASM_SH_IO_HD64465_H
+#define _ASM_SH_IO_HD64465_H
+
+#include <asm/io_generic.h>
+
+extern unsigned char hd64465_inb(unsigned long port);
+extern unsigned short hd64465_inw(unsigned long port);
+extern unsigned int hd64465_inl(unsigned long port);
+
+extern void hd64465_outb(unsigned char value, unsigned long port);
+extern void hd64465_outw(unsigned short value, unsigned long port);
+extern void hd64465_outl(unsigned int value, unsigned long port);
+
+extern unsigned char hd64465_inb_p(unsigned long port);
+extern void hd64465_outb_p(unsigned char value, unsigned long port);
+
+extern void hd64465_insb(unsigned long port, void *addr, unsigned long count);
+extern void hd64465_insw(unsigned long port, void *addr, unsigned long count);
+extern void hd64465_insl(unsigned long port, void *addr, unsigned long count);
+extern void hd64465_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void hd64465_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void hd64465_outsl(unsigned long port, const void *addr, unsigned long count);
+extern unsigned long hd64465_isa_port2addr(unsigned long offset);
+extern int hd64465_irq_demux(int irq);
+/* Provision for generic secondary demux step -- used by PCMCIA code */
+extern void hd64465_register_irq_demux(int irq,
+		int (*demux)(int irq, void *dev), void *dev);
+extern void hd64465_unregister_irq_demux(int irq);
+/* Set this variable to 1 to see port traffic */
+extern int hd64465_io_debug;
+/* Map a range of ports to a range of kernel virtual memory.
+ */
+extern void hd64465_port_map(unsigned short baseport, unsigned int nports,
+			     unsigned long addr, unsigned char shift);
+extern void hd64465_port_unmap(unsigned short baseport, unsigned int nports);
+
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			hd64465_inb
+# define __inw			hd64465_inw
+# define __inl			hd64465_inl
+# define __outb			hd64465_outb
+# define __outw			hd64465_outw
+# define __outl			hd64465_outl
+
+# define __inb_p		hd64465_inb_p
+# define __inw_p		hd64465_inw
+# define __inl_p		hd64465_inl
+# define __outb_p		hd64465_outb_p
+# define __outw_p		hd64465_outw
+# define __outl_p		hd64465_outl
+
+# define __insb			hd64465_insb
+# define __insw			hd64465_insw
+# define __insl			hd64465_insl
+# define __outsb		hd64465_outsb
+# define __outsw		hd64465_outsw
+# define __outsl		hd64465_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	hd64465_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+
+#endif
+
+#endif /* _ASM_SH_IO_HD64465_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/hp6xx/io.h linux-2.5.73-bk10/include/asm-sh/hp6xx/io.h
--- linux-2.5.73-bk9/include/asm-sh/hp6xx/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/hp6xx/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,10 @@
+#ifndef __ASM_SH_HP6XX_IO_H
+#define __ASM_SH_HP6XX_IO_H
+
+/*
+ * Nothing special here.. just use the generic cchip io routines.
+ */
+#include <asm/hd64461/io.h>
+
+#endif /* __ASM_SH_HP6XX_IO_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/hw_irq.h linux-2.5.73-bk10/include/asm-sh/hw_irq.h
--- linux-2.5.73-bk9/include/asm-sh/hw_irq.h	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/hw_irq.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,6 +1,9 @@
 #ifndef __ASM_SH_HW_IRQ_H
 #define __ASM_SH_HW_IRQ_H
-static __inline__ void sh_do_profile (unsigned long pc) {/*Not implemented yet*/}
 
-static __inline__ void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { /* Nothing to do */ }
+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
+{
+	/* Nothing to do */
+}
+
 #endif /* __ASM_SH_HW_IRQ_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/ide.h linux-2.5.73-bk10/include/asm-sh/ide.h
--- linux-2.5.73-bk9/include/asm-sh/ide.h	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/ide.h	2003-07-02 04:57:38.000000000 -0700
@@ -98,13 +98,16 @@
 	int index;
 
 	for(index = 0; index < MAX_HWIFS; index++) {
+		memset(&hw, 0, sizeof hw);
 		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
 		hw.irq = ide_default_irq(ide_default_io_base(index));
-		ide_register_hw(&hw);
+		ide_register_hw(&hw, NULL);
 	}
-#endif
+#endif /* CONFIG_PCI */
 }
 
+#include <asm-generic/ide_iops.h>
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_SH_IDE_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/io.h linux-2.5.73-bk10/include/asm-sh/io.h
--- linux-2.5.73-bk9/include/asm-sh/io.h	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -107,33 +107,7 @@
 /* Control operations through platform specific headers */
 # define __WANT_IO_DEF
 
-# if defined(CONFIG_SH_HP600)
-#  include <asm/io_hd64461.h>
-# elif defined(CONFIG_SH_SOLUTION_ENGINE)
-#  include <asm/io_se.h>
-# elif defined(CONFIG_SH_SH2000)
-#  include <asm/io_sh2000.h>
-# elif defined(CONFIG_SH_DMIDA) || \
-       defined(CONFIG_SH_STB1_HARP) || \
-       defined(CONFIG_SH_STB1_OVERDRIVE)
-#  include <asm/io_hd64465.h>
-# elif defined(CONFIG_SH_EC3104)
-#  include <asm/io_ec3104.h>
-# elif defined(CONFIG_SH_DREAMCAST)
-#  include <asm/io_dc.h>
-# elif defined(CONFIG_SH_CAT68701)
-#  include <asm/io_cat68701.h>
-# elif defined(CONFIG_SH_BIGSUR)
-#  include <asm/io_bigsur.h>
-# elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
-#  include <asm/io_7751se.h>
-# elif defined(CONFIG_SH_ADX)
-#  include <asm/io_adx.h>
-# elif defined(CONFIG_SH_UNKNOWN)
-#  include <asm/io_unknown.h>
-# else
-#  error "What system is this?"
-#endif
+# include <asm/mach/io.h>
 
 #undef __WANT_IO_DEF
 
diff -urN linux-2.5.73-bk9/include/asm-sh/ioctl.h linux-2.5.73-bk10/include/asm-sh/ioctl.h
--- linux-2.5.73-bk9/include/asm-sh/ioctl.h	2003-06-22 11:32:33.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/ioctl.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: ioctl.h,v 1.1 2000/04/14 16:48:21 mjd Exp $
+/* $Id: ioctl.h,v 1.1.1.1 2001/10/15 20:45:09 mrbrown Exp $
  *
  * linux/ioctl.h for Linux by H.H. Bergman.
  */
diff -urN linux-2.5.73-bk9/include/asm-sh/ipc.h linux-2.5.73-bk10/include/asm-sh/ipc.h
--- linux-2.5.73-bk9/include/asm-sh/ipc.h	2003-06-22 11:33:18.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/ipc.h	2003-07-02 04:57:38.000000000 -0700
@@ -14,6 +14,7 @@
 #define SEMOP		 1
 #define SEMGET		 2
 #define SEMCTL		 3
+#define SEMTIMEDOP	 4
 #define MSGSND		11
 #define MSGRCV		12
 #define MSGGET		13
diff -urN linux-2.5.73-bk9/include/asm-sh/irq.h linux-2.5.73-bk10/include/asm-sh/irq.h
--- linux-2.5.73-bk9/include/asm-sh/irq.h	2003-06-22 11:32:32.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/irq.h	2003-07-02 04:57:38.000000000 -0700
@@ -14,10 +14,10 @@
 #include <asm/machvec.h>
 #include <asm/ptrace.h>		/* for pt_regs */
 
-#if defined(__sh3__)
+#if defined(CONFIG_CPU_SH3)
 #define INTC_IPRA  	0xfffffee2UL
 #define INTC_IPRB  	0xfffffee4UL
-#elif defined(__SH4__)
+#elif defined(CONFIG_CPU_SH4)
 #define INTC_IPRA	0xffd00004UL
 #define INTC_IPRB	0xffd00008UL
 #define INTC_IPRC	0xffd0000cUL
@@ -33,7 +33,7 @@
 #define RTC_IPR_POS	 0
 #define RTC_PRIORITY	TIMER_PRIORITY
 
-#if defined(__sh3__)
+#if defined(CONFIG_CPU_SH3)
 #define DMTE0_IRQ	48
 #define DMTE1_IRQ	49
 #define DMTE2_IRQ	50
@@ -41,7 +41,7 @@
 #define DMA_IPR_ADDR	INTC_IPRE
 #define DMA_IPR_POS	3
 #define DMA_PRIORITY	7
-#elif defined(__SH4__)
+#elif defined(CONFIG_CPU_SH4)
 #define DMTE0_IRQ	34
 #define DMTE1_IRQ	35
 #define DMTE2_IRQ	36
@@ -109,7 +109,9 @@
 #ifdef CONFIG_SH_GENERIC
 # define ONCHIP_NR_IRQS 144
 #else
-# if defined(CONFIG_CPU_SUBTYPE_SH7707)
+# if defined(CONFIG_CPU_SUBTYPE_SH7604)
+#  define ONCHIP_NR_IRQS 24	// Actually 21
+# elif defined(CONFIG_CPU_SUBTYPE_SH7707)
 #  define ONCHIP_NR_IRQS 64
 #  define PINT_NR_IRQS   16
 # elif defined(CONFIG_CPU_SUBTYPE_SH7708)
@@ -331,12 +333,21 @@
 extern int systemasic_irq_demux(int irq);
 #define irq_demux systemasic_irq_demux
 
+#elif defined(CONFIG_SH_MPC1211)
+
+extern int mpc1211_irq_demux(int irq);
+#define irq_demux mpc1211_irq_demux
+
 #else
 
 #define irq_demux(irq) __irq_demux(irq)
 
 #endif
 
+static __inline__ int irq_canonicalize(int irq)
+{
+	return irq;
+}
 
 
 #endif /* __ASM_SH_IRQ_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/keyboard.h linux-2.5.73-bk10/include/asm-sh/keyboard.h
--- linux-2.5.73-bk9/include/asm-sh/keyboard.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/keyboard.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,14 @@
+#ifndef	__ASM_SH_KEYBOARD_H
+#define	__ASM_SH_KEYBOARD_H
+/*
+ *	$Id: keyboard.h,v 1.1.1.1 2001/10/15 20:45:09 mrbrown Exp $
+ */
+
+#include <linux/kd.h>
+#include <linux/config.h>
+#include <asm/machvec.h>
+
+#ifdef CONFIG_SH_MPC1211
+#include <asm/mpc1211/keyboard-mpc1211.h>
+#endif
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/kgdb.h linux-2.5.73-bk10/include/asm-sh/kgdb.h
--- linux-2.5.73-bk9/include/asm-sh/kgdb.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/kgdb.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,117 @@
+/*
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Based on original code by Glenn Engel, Jim Kingdon,
+ * David Grothe <dave@gcom.com>, Tigran Aivazian, <tigran@sco.com> and
+ * Amit S. Kale <akale@veritas.com>
+ * 
+ * Super-H port based on sh-stub.c (Ben Lee and Steve Chamberlain) by
+ * Henry Bell <henry.bell@st.com>
+ * 
+ * Header file for low-level support for remote debug using GDB. 
+ *
+ */
+
+#ifndef __KGDB_H
+#define __KGDB_H
+
+#include <asm/ptrace.h>
+
+/* Same as pt_regs but has vbr in place of syscall_nr */
+struct kgdb_regs {
+        unsigned long regs[16];
+        unsigned long pc;
+        unsigned long pr;
+        unsigned long sr;
+        unsigned long gbr;
+        unsigned long mach;
+        unsigned long macl;
+        unsigned long vbr;
+};
+
+/* State info */
+extern char kgdb_in_gdb_mode;
+extern int kgdb_done_init;
+extern int kgdb_enabled;
+extern int kgdb_nofault;	/* Ignore bus errors (in gdb mem access) */
+extern int kgdb_halt;		/* Execute initial breakpoint at startup */
+extern char in_nmi;		/* Debounce flag to prevent NMI reentry*/
+
+/* SCI */
+extern int kgdb_portnum;
+extern int kgdb_baud;
+extern char kgdb_parity;
+extern char kgdb_bits;
+extern int kgdb_console_setup(struct console *, char *);
+
+/* Init and interface stuff */
+extern int kgdb_init(void);
+extern int (*kgdb_serial_setup)(void);
+extern int (*kgdb_getchar)(void);
+extern void (*kgdb_putchar)(int);
+
+struct kgdb_sermap {
+	char *name;
+	int namelen;
+	int (*setup_fn)(struct console *, char *);
+	struct kgdb_sermap *next;
+};
+extern void kgdb_register_sermap(struct kgdb_sermap *map);
+extern struct kgdb_sermap *kgdb_porttype;
+
+/* Trap functions */
+typedef void (kgdb_debug_hook_t)(struct pt_regs *regs); 
+typedef void (kgdb_bus_error_hook_t)(void);
+extern kgdb_debug_hook_t  *kgdb_debug_hook;
+extern kgdb_bus_error_hook_t *kgdb_bus_err_hook;
+
+extern void breakpoint(void);
+
+/* Console */
+struct console;
+void kgdb_console_write(struct console *co, const char *s, unsigned count);
+void kgdb_console_init(void);
+
+/* Prototypes for jmp fns */
+#define _JBLEN 9
+typedef        int jmp_buf[_JBLEN];
+extern void    longjmp(jmp_buf __jmpb, int __retval);
+extern int     setjmp(jmp_buf __jmpb);
+
+/* Variadic macro to print our own message to the console */
+#define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__)
+
+/* Forced breakpoint */
+#define BREAKPOINT() do {                                     \
+  if (kgdb_enabled) {                                         \
+    asm volatile("trapa   #0xff");                            \
+  }                                                           \
+} while (0)
+
+/* Kernel assert macros */
+#ifdef CONFIG_KGDB_KERNEL_ASSERTS
+
+/* Predefined conditions */
+#define KA_VALID_ERRNO(errno) ((errno) > 0 && (errno) <= EMEDIUMTYPE)
+#define KA_VALID_PTR_ERR(ptr) KA_VALID_ERRNO(-PTR_ERR(ptr))
+#define KA_VALID_KPTR(ptr)  (!(ptr) || \
+              ((void *)(ptr) >= (void *)PAGE_OFFSET &&  \
+               (void *)(ptr) < ERR_PTR(-EMEDIUMTYPE)))
+#define KA_VALID_PTRORERR(errptr) \
+               (KA_VALID_KPTR(errptr) || KA_VALID_PTR_ERR(errptr))
+#define KA_HELD_GKL()  (current->lock_depth >= 0)
+
+/* The actual assert */
+#define KGDB_ASSERT(condition, message) do {                   \
+       if (!(condition) && (kgdb_enabled)) {                   \
+               KGDB_PRINTK("Assertion failed at %s:%d: %s\n",  \
+                                  __FILE__, __LINE__, message);\
+               BREAKPOINT();                                   \
+       }                                                       \
+} while (0)
+#else
+#define KGDB_ASSERT(condition, message)
+#endif
+
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/kmap_types.h linux-2.5.73-bk10/include/asm-sh/kmap_types.h
--- linux-2.5.73-bk9/include/asm-sh/kmap_types.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/kmap_types.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,33 @@
+#ifndef __SH_KMAP_TYPES_H
+#define __SH_KMAP_TYPES_H
+
+/* Dummy header just to define km_type. */
+
+#include <linux/config.h>
+
+#if CONFIG_DEBUG_HIGHMEM
+# define D(n) __KM_FENCE_##n ,
+#else
+# define D(n)
+#endif
+
+enum km_type {
+D(0)	KM_BOUNCE_READ,
+D(1)	KM_SKB_SUNRPC_DATA,
+D(2)	KM_SKB_DATA_SOFTIRQ,
+D(3)	KM_USER0,
+D(4)	KM_USER1,
+D(5)	KM_BIO_SRC_IRQ,
+D(6)	KM_BIO_DST_IRQ,
+D(7)	KM_PTE0,
+D(8)	KM_PTE1,
+D(9)	KM_IRQ0,
+D(10)	KM_IRQ1,
+D(11)	KM_SOFTIRQ0,
+D(12)	KM_SOFTIRQ1,
+D(13)	KM_TYPE_NR
+};
+
+#undef D
+
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/machvec.h linux-2.5.73-bk10/include/asm-sh/machvec.h
--- linux-2.5.73-bk9/include/asm-sh/machvec.h	2003-06-22 11:32:31.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/machvec.h	2003-07-02 04:57:38.000000000 -0700
@@ -12,6 +12,9 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
+#include <linux/time.h>
+
+#include <asm/machtypes.h>
 
 struct timeval;
 
@@ -63,105 +66,10 @@
 
 	void (*mv_heartbeat)(void);
 
-	void (*mv_rtc_gettimeofday)(struct timeval *tv);
-	int (*mv_rtc_settimeofday)(const struct timeval *tv);
-
-	unsigned int mv_hw_se : 1;
-	unsigned int mv_hw_hp600 : 1;
-	unsigned int mv_hw_hp620 : 1;
-	unsigned int mv_hw_hp680 : 1;
-	unsigned int mv_hw_hp690 : 1;
-	unsigned int mv_hw_hd64461 : 1;
-	unsigned int mv_hw_sh2000 : 1;
-	unsigned int mv_hw_hd64465 : 1;
-	unsigned int mv_hw_dreamcast : 1;
-	unsigned int mv_hw_bigsur : 1;
-	unsigned int mv_hw_7751se: 1;
-	unsigned int mv_hw_adx : 1;
+	void (*mv_rtc_gettimeofday)(struct timespec *ts);
+	int (*mv_rtc_settimeofday)(const time_t secs);
 };
 
 extern struct sh_machine_vector sh_mv;
 
-/* Machine check macros */
-#ifdef CONFIG_SH_GENERIC
-#define MACH_SE		(sh_mv.mv_hw_se)
-#define MACH_HP600	(sh_mv.mv_hw_hp600)
-#define MACH_HP620	(sh_mv.mv_hw_hp620)
-#define MACH_HP680	(sh_mv.mv_hw_hp680)
-#define MACH_HP690	(sh_mv.mv_hw_hp690)
-#define MACH_HD64461	(sh_mv.mv_hw_hd64461)
-#define MACH_HD64465	(sh_mv.mv_hw_hd64465)
-#define MACH_SH2000	(sh_mv.mv_hw_sh2000)
-#define MACH_DREAMCAST	(sh_mv.mv_hw_dreamcast)
-#define MACH_BIGSUR	(sh_mv.mv_hw_bigsur)
-#define MACH_7751SE	(sh_mv.mv_hw_7751se)
-#define MACH_ADX	(sh_mv.mv_hw_adx)
-#else
-# ifdef CONFIG_SH_SOLUTION_ENGINE
-#  define MACH_SE		1
-# else
-#  define MACH_SE		0
-# endif
-# ifdef CONFIG_SH_7751_SOLUTION_ENGINE
-#  define MACH_7751SE		1
-# else
-#  define MACH_7751SE		0
-# endif
-# ifdef CONFIG_SH_HP600
-#  define MACH_HP600		1
-# else
-#  define MACH_HP600		0
-# endif
-# ifdef CONFIG_SH_HP620
-#  define MACH_HP620		1
-# else
-#  define MACH_HP620		0
-# endif
-# ifdef CONFIG_SH_HP680
-#  define MACH_HP680		1
-# else
-#  define MACH_HP680		0
-# endif
-# ifdef CONFIG_SH_HP690
-#  define MACH_HP690		1
-# else
-#  define MACH_HP690		0
-# endif
-# ifdef CONFIG_HD64461
-#  define MACH_HD64461		1
-# else
-#  define MACH_HD64461		0
-# endif
-# ifdef CONFIG_HD64465
-#  define MACH_HD64465		1
-# else
-#  define MACH_HD64465		0
-# endif
-# ifdef CONFIG_SH_SH2000
-#  define MACH_SH2000		1
-# else
-#  define MACH_SH2000		0
-# endif
-# ifdef CONFIG_SH_EC3104
-#  define MACH_EC3104		1
-# else
-#  define MACH_EC3104		0
-# endif
-# ifdef CONFIG_SH_DREAMCAST
-#  define MACH_DREAMCAST	1
-# else
-#  define MACH_DREAMCAST	0
-# endif
-# ifdef CONFIG_SH_BIGSUR
-#  define MACH_BIGSUR		1
-# else
-#  define MACH_BIGSUR		0
-# endif
-# ifdef CONFIG_SH_ADX
-#  define MACH_ADX		1
-# else
-#  define MACH_ADX		0
-# endif
-#endif
-
 #endif /* _ASM_SH_MACHVEC_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/mc146818rtc.h linux-2.5.73-bk10/include/asm-sh/mc146818rtc.h
--- linux-2.5.73-bk9/include/asm-sh/mc146818rtc.h	2003-06-22 11:33:18.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/mc146818rtc.h	2003-07-02 04:57:38.000000000 -0700
@@ -4,6 +4,12 @@
 #ifndef _ASM_MC146818RTC_H
 #define _ASM_MC146818RTC_H
 
+#ifdef CONFIG_SH_MPC1211
+#undef  _ASM_MC146818RTC_H
+#undef  RTC_IRQ
+#include <asm/mpc1211/mc146818rtc.h>
+#else
+
 #include <asm/rtc.h>
 
 #define RTC_ALWAYS_BCD	1
@@ -12,12 +18,12 @@
 #undef  RTC_IRQ
 #define RTC_IRQ		0
 
-#if defined(__sh3__)
+#if defined(CONFIG_CPU_SH3)
 #define RTC_PORT(n)		(R64CNT+(n)*2)
 #define CMOS_READ(addr)		__CMOS_READ(addr,b)
 #define CMOS_WRITE(val,addr)	__CMOS_WRITE(val,addr,b)
 
-#elif defined(__SH4__)
+#elif defined(CONFIG_CPU_SH4)
 #define RTC_PORT(n)		(R64CNT+(n)*4)
 #define CMOS_READ(addr)		__CMOS_READ(addr,w)
 #define CMOS_WRITE(val,addr)	__CMOS_WRITE(val,addr,w)
@@ -156,4 +162,6 @@
 			break;						\
 	}								\
 })
+
+#endif /* CONFIG_SH_MPC1211 */
 #endif /* _ASM_MC146818RTC_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/mman.h linux-2.5.73-bk10/include/asm-sh/mman.h
--- linux-2.5.73-bk9/include/asm-sh/mman.h	2003-06-22 11:33:12.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/mman.h	2003-07-02 04:57:38.000000000 -0700
@@ -4,6 +4,7 @@
 #define PROT_READ	0x1		/* page can be read */
 #define PROT_WRITE	0x2		/* page can be written */
 #define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_SEM	0x8		/* page may be used for atomic ops */
 #define PROT_NONE	0x0		/* page can not be accessed */
 
 #define MAP_SHARED	0x01		/* Share changes */
@@ -17,6 +18,8 @@
 #define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
 #define MAP_LOCKED	0x2000		/* pages are locked */
 #define MAP_NORESERVE	0x4000		/* don't check for reservations */
+#define MAP_POPULATE	0x8000		/* populate (prefault) page tables */
+#define MAP_NONBLOCK	0x10000		/* do not block on IO */
 
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_INVALIDATE	2		/* invalidate the caches */
diff -urN linux-2.5.73-bk9/include/asm-sh/mmu.h linux-2.5.73-bk10/include/asm-sh/mmu.h
--- linux-2.5.73-bk9/include/asm-sh/mmu.h	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/mmu.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,7 +1,29 @@
 #ifndef __MMU_H
 #define __MMU_H
 
+#if !defined(CONFIG_MMU)
+
+struct mm_rblock_struct {
+	int	size;
+	int	refcount;
+	void	*kblock;
+};
+
+struct mm_tblock_struct {
+	struct mm_rblock_struct *rblock;
+	struct mm_tblock_struct *next;
+};
+
+typedef struct {
+	struct mm_tblock_struct tblock;
+	unsigned long		end_brk;
+} mm_context_t;
+
+#else
+
 /* Default "unsigned long" context */
 typedef unsigned long mm_context_t;
 
-#endif
+#endif /* CONFIG_MMU */
+#endif /* __MMH_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/mmu_context.h linux-2.5.73-bk10/include/asm-sh/mmu_context.h
--- linux-2.5.73-bk9/include/asm-sh/mmu_context.h	2003-06-22 11:33:06.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/mmu_context.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,14 +1,22 @@
 /*
  * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2003 Paul Mundt
  *
  * ASID handling idea taken from MIPS implementation.
  */
 #ifndef __ASM_SH_MMU_CONTEXT_H
 #define __ASM_SH_MMU_CONTEXT_H
 
-/* The MMU "context" consists of two things:
-     (a) TLB cache version (or round, cycle whatever expression you like)
-     (b) ASID (Address Space IDentifier)
+#include <asm/cpu/mmu_context.h>
+#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/*
+ * The MMU "context" consists of two things:
+ *    (a) TLB cache version (or round, cycle whatever expression you like)
+ *    (b) ASID (Address Space IDentifier)
  */
 
 /*
@@ -29,19 +37,33 @@
  */
 #define MMU_VPN_MASK	0xfffff000
 
+#ifdef CONFIG_MMU
+/*
+ * Get MMU context if needed.
+ */
 static __inline__ void
-get_new_mmu_context(struct mm_struct *mm)
+get_mmu_context(struct mm_struct *mm)
 {
 	extern void flush_tlb_all(void);
+	unsigned long mc = mmu_context_cache;
 
-	unsigned long mc = ++mmu_context_cache;
+	/* Check if we have old version of context. */
+	if (((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
+		/* It's up to date, do nothing */
+		return;
 
+	/* It's old, we need to get new context with new version. */
+	mc = ++mmu_context_cache;
 	if (!(mc & MMU_CONTEXT_ASID_MASK)) {
-		/* We exhaust ASID of this version.
-		   Flush all TLB and start new cycle. */
+		/*
+		 * We exhaust ASID of this version.
+		 * Flush all TLB and start new cycle.
+		 */
 		flush_tlb_all();
-		/* Fix version if needed.
-		   Note that we avoid version #0 to distingush NO_CONTEXT. */
+		/*
+		 * Fix version; Note that we avoid version #0
+		 * to distingush NO_CONTEXT.
+		 */
 		if (!mc)
 			mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
 	}
@@ -49,21 +71,6 @@
 }
 
 /*
- * Get MMU context if needed.
- */
-static __inline__ void
-get_mmu_context(struct mm_struct *mm)
-{
-	if (mm) {
-		unsigned long mc = mmu_context_cache;
-		/* Check if we have old version of context.
-		   If it's old, we need to get new context with new version. */
-		if ((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK)
-			get_new_mmu_context(mm);
-	}
-}
-
-/*
  * Initialize the context related info for a new mm_struct
  * instance.
  */
@@ -71,6 +78,7 @@
 				       struct mm_struct *mm)
 {
 	mm->context = NO_CONTEXT;
+
 	return 0;
 }
 
@@ -83,49 +91,6 @@
 	/* Do nothing */
 }
 
-/* Other MMU related constants. */
-
-#if defined(__sh3__)
-#define MMU_PTEH	0xFFFFFFF0	/* Page table entry register HIGH */
-#define MMU_PTEL	0xFFFFFFF4	/* Page table entry register LOW */
-#define MMU_TTB		0xFFFFFFF8	/* Translation table base register */
-#define MMU_TEA		0xFFFFFFFC	/* TLB Exception Address */
-
-#define MMUCR		0xFFFFFFE0	/* MMU Control Register */
-
-#define MMU_TLB_ADDRESS_ARRAY	0xF2000000
-#define MMU_PAGE_ASSOC_BIT	0x80
-
-#define MMU_NTLB_ENTRIES	128	/* for 7708 */
-#define MMU_CONTROL_INIT	0x007	/* SV=0, TF=1, IX=1, AT=1 */
-
-#elif defined(__SH4__)
-#define MMU_PTEH	0xFF000000	/* Page table entry register HIGH */
-#define MMU_PTEL	0xFF000004	/* Page table entry register LOW */
-#define MMU_TTB		0xFF000008	/* Translation table base register */
-#define MMU_TEA		0xFF00000C	/* TLB Exception Address */
-#define MMU_PTEA	0xFF000034	/* Page table entry assistance register */
-
-#define MMUCR		0xFF000010	/* MMU Control Register */
-
-#define MMU_ITLB_ADDRESS_ARRAY	0xF2000000
-#define MMU_UTLB_ADDRESS_ARRAY	0xF6000000
-#define MMU_PAGE_ASSOC_BIT	0x80
-
-#define MMU_NTLB_ENTRIES	64	/* for 7750 */
-#define MMU_CONTROL_INIT	0x205	/* SQMD=1, SV=0, TI=1, AT=1 */
-
-#define MMU_ITLB_DATA_ARRAY	0xF3000000
-#define MMU_UTLB_DATA_ARRAY	0xF7000000
-
-#define MMU_UTLB_ENTRIES	   64
-#define MMU_U_ENTRY_SHIFT	    8
-#define MMU_UTLB_VALID		0x100
-#define MMU_ITLB_ENTRIES	    4
-#define MMU_I_ENTRY_SHIFT	    8
-#define MMU_ITLB_VALID		0x100
-#endif
-
 static __inline__ void set_asid(unsigned long asid)
 {
 	unsigned long __dummy;
@@ -166,11 +131,9 @@
 				 struct mm_struct *next,
 				 struct task_struct *tsk, unsigned int cpu)
 {
-	if (prev != next) {
+	if (likely(prev != next)) {
 		unsigned long __pgdir = (unsigned long)next->pgd;
 
-		clear_bit(cpu, &prev->cpu_vm_mask);
-		set_bit(cpu, &next->cpu_vm_mask);
 		__asm__ __volatile__("mov.l	%0, %1"
 				     : /* no output */
 				     : "r" (__pgdir), "m" (__m(MMU_TTB)));
@@ -187,28 +150,55 @@
 enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
 {
 }
+#else /* !CONFIG_MMU */
+#define get_mmu_context(mm)		do { } while (0)
+#define init_new_context(tsk,mm)	(0)
+#define destroy_context(mm)		do { } while (0)
+#define set_asid(asid)			do { } while (0)
+#define get_asid()			(0)
+#define activate_context(mm)		do { } while (0)
+#define switch_mm(prev,next,tsk,cpu)	do { } while (0)
+#define deactivate_mm(tsk,mm)		do { } while (0)
+#define activate_mm(prev,next)		do { } while (0)
+#define enter_lazy_tlb(mm,tsk,cpu)	do { } while (0)
+#endif /* CONFIG_MMU */
 
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
 /*
- * Every architecture must define this function. It's the fastest
- * way of searching a 168-bit bitmap where the first 128 bits are
- * unlikely to be set. It's guaranteed that at least one of the 168
- * bits is cleared.
+ * If this processor has an MMU, we need methods to turn it off/on ..
+ * paging_init() will also have to be updated for the processor in
+ * question.
  */
-#if MAX_RT_PRIO != 128 || MAX_PRIO != 168
-# error update this function.
-#endif
-
-static inline int sched_find_first_zero_bit(unsigned long *b)
+static inline void enable_mmu(void)
 {
-	unsigned int rt;
+	/* Enable MMU */
+	ctrl_outl(MMU_CONTROL_INIT, MMUCR);
+
+	/* The manual suggests doing some nops after turning on the MMU */
+	__asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop\n\t");
 
-	rt = b[0] & b[1] & b[2] & b[3];
-	if (unlikely(rt != 0xffffffff))
-		return find_first_zero_bit(b, MAX_RT_PRIO);
+	if (mmu_context_cache == NO_CONTEXT)
+		mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
 
-	if (b[4] != ~0)
-		return ffz(b[4]) + MAX_RT_PRIO;
-	return ffz(b[5]) + 32 + MAX_RT_PRIO;
+	set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);
 }
 
+static inline void disable_mmu(void)
+{
+	unsigned long cr;
+
+	cr = ctrl_inl(MMUCR);
+	cr &= ~MMU_CONTROL_INIT;
+	ctrl_outl(cr, MMUCR);
+	__asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop\n\t");
+}
+#else
+/*
+ * MMU control handlers for processors lacking memory
+ * management hardware.
+ */
+#define enable_mmu()	do { BUG(); } while (0)
+#define disable_mmu()	do { BUG(); } while (0)
+#endif
+
 #endif /* __ASM_SH_MMU_CONTEXT_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/mmzone.h linux-2.5.73-bk10/include/asm-sh/mmzone.h
--- linux-2.5.73-bk9/include/asm-sh/mmzone.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/mmzone.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,61 @@
+/*
+ *  linux/include/asm-sh/mmzone.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_SH_MMZONE_H
+#define __ASM_SH_MMZONE_H
+
+#include <linux/config.h>
+
+/* Currently, just for HP690 */
+#define PHYSADDR_TO_NID(phys)	((((phys) - __MEMORY_START) >= 0x01000000)?1:0)
+#define NR_NODES 2
+
+extern pg_data_t discontig_page_data[NR_NODES];
+extern bootmem_data_t discontig_node_bdata[NR_NODES];
+
+#ifdef CONFIG_DISCONTIGMEM
+/*
+ * Following are macros that each numa implmentation must define.
+ */
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(kaddr)	PHYSADDR_TO_NID(__pa(kaddr))
+
+/*
+ * Return a pointer to the node data for node n.
+ */
+#define NODE_DATA(nid)		(&discontig_page_data[nid])
+
+/*
+ * NODE_MEM_MAP gives the kaddr for the mem_map of the node.
+ */
+#define NODE_MEM_MAP(nid)	(NODE_DATA(nid)->node_mem_map)
+
+#define phys_to_page(phys)						\
+({ unsigned int node = PHYSADDR_TO_NID(phys); 		      		\
+   NODE_MEM_MAP(node)				 		 	\
+     + (((phys) - NODE_DATA(node)->node_start_paddr) >> PAGE_SHIFT); })
+
+static inline int is_valid_page(struct page *page)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_NODES; i++) {
+		if (page >= NODE_MEM_MAP(i) &&
+		    page < NODE_MEM_MAP(i) + NODE_DATA(i)->node_size)
+			return 1;
+	}
+	return 0;
+}
+
+#define VALID_PAGE(page)	is_valid_page(page)
+#define page_to_phys(page)	PHYSADDR(page_address(page))
+
+#endif /* CONFIG_DISCONTIGMEM */
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/module.h linux-2.5.73-bk10/include/asm-sh/module.h
--- linux-2.5.73-bk9/include/asm-sh/module.h	2003-06-22 11:32:55.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/module.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,12 +1,36 @@
 #ifndef _ASM_SH_MODULE_H
 #define _ASM_SH_MODULE_H
+
 /*
  * This file contains the SH architecture specific module code.
  */
 
-#define module_map(x)		vmalloc(x)
-#define module_unmap(x)		vfree(x)
-#define module_arch_init(x)	(0)
-#define arch_init_modules(x)	do { } while (0)
+struct mod_arch_specific {
+	/* Nothing to see here .. */
+};
+
+#define Elf_Shdr		Elf32_Shdr
+#define Elf_Sym			Elf32_Sym
+#define Elf_Ehdr		Elf32_Ehdr
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# ifdef CONFIG_CPU_SH3
+#  define MODULE_PROC_FAMILY "SH3LE "
+# elif defined  CONFIG_CPU_SH4
+#  define MODULE_PROC_FAMILY "SH4LE "
+# else
+#  error unknown processor family
+# endif
+#else
+# ifdef CONFIG_CPU_SH3
+#  define MODULE_PROC_FAMILY "SH3BE "
+# elif defined  CONFIG_CPU_SH4
+#  define MODULE_PROC_FAMILY "SH4BE "
+# else
+#  error unknown processor family
+# endif
+#endif
+
+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
 
 #endif /* _ASM_SH_MODULE_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/mpc1211/dma.h linux-2.5.73-bk10/include/asm-sh/mpc1211/dma.h
--- linux-2.5.73-bk9/include/asm-sh/mpc1211/dma.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/mpc1211/dma.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,304 @@
+/* $Id: dma.h,v 1.7 1992/12/14 00:29:34 root Exp root $
+ * linux/include/asm/dma.h: Defines for using and allocating dma channels.
+ * Written by Hennus Bergman, 1992.
+ * High DMA channel support & info by Hannu Savolainen
+ * and John Boyd, Nov. 1992.
+ */
+
+#ifndef _ASM_MPC1211_DMA_H
+#define _ASM_MPC1211_DMA_H
+
+#include <linux/config.h>
+#include <linux/spinlock.h>	/* And spinlocks */
+#include <asm/io.h>		/* need byte IO */
+#include <linux/delay.h>
+
+
+#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
+#define dma_outb	outb_p
+#else
+#define dma_outb	outb
+#endif
+
+#define dma_inb		inb
+
+/*
+ * NOTES about DMA transfers:
+ *
+ *  controller 1: channels 0-3, byte operations, ports 00-1F
+ *  controller 2: channels 4-7, word operations, ports C0-DF
+ *
+ *  - ALL registers are 8 bits only, regardless of transfer size
+ *  - channel 4 is not used - cascades 1 into 2.
+ *  - channels 0-3 are byte - addresses/counts are for physical bytes
+ *  - channels 5-7 are word - addresses/counts are for physical words
+ *  - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries
+ *  - transfer count loaded to registers is 1 less than actual count
+ *  - controller 2 offsets are all even (2x offsets for controller 1)
+ *  - page registers for 5-7 don't use data bit 0, represent 128K pages
+ *  - page registers for 0-3 use bit 0, represent 64K pages
+ *
+ * DMA transfers are limited to the lower 16MB of _physical_ memory.  
+ * Note that addresses loaded into registers must be _physical_ addresses,
+ * not logical addresses (which may differ if paging is active).
+ *
+ *  Address mapping for channels 0-3:
+ *
+ *   A23 ... A16 A15 ... A8  A7 ... A0    (Physical addresses)
+ *    |  ...  |   |  ... |   |  ... |
+ *    |  ...  |   |  ... |   |  ... |
+ *    |  ...  |   |  ... |   |  ... |
+ *   P7  ...  P0  A7 ... A0  A7 ... A0   
+ * |    Page    | Addr MSB | Addr LSB |   (DMA registers)
+ *
+ *  Address mapping for channels 5-7:
+ *
+ *   A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0    (Physical addresses)
+ *    |  ...  |   \   \   ... \  \  \  ... \  \
+ *    |  ...  |    \   \   ... \  \  \  ... \  (not used)
+ *    |  ...  |     \   \   ... \  \  \  ... \
+ *   P7  ...  P1 (0) A7 A6  ... A0 A7 A6 ... A0   
+ * |      Page      |  Addr MSB   |  Addr LSB  |   (DMA registers)
+ *
+ * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses
+ * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at
+ * the hardware level, so odd-byte transfers aren't possible).
+ *
+ * Transfer count (_not # bytes_) is limited to 64K, represented as actual
+ * count - 1 : 64K => 0xFFFF, 1 => 0x0000.  Thus, count is always 1 or more,
+ * and up to 128K bytes may be transferred on channels 5-7 in one operation. 
+ *
+ */
+
+#define MAX_DMA_CHANNELS	8
+
+/* The maximum address that we can perform a DMA transfer to on this platform */
+#define MAX_DMA_ADDRESS      (PAGE_OFFSET+0x10000000)
+
+/* 8237 DMA controllers */
+#define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
+#define IO_DMA2_BASE	0xC0	/* 16 bit master DMA, ch 4(=slave input)..7 */
+
+/* DMA controller registers */
+#define DMA1_CMD_REG		0x08	/* command register (w) */
+#define DMA1_STAT_REG		0x08	/* status register (r) */
+#define DMA1_REQ_REG            0x09    /* request register (w) */
+#define DMA1_MASK_REG		0x0A	/* single-channel mask (w) */
+#define DMA1_MODE_REG		0x0B	/* mode register (w) */
+#define DMA1_CLEAR_FF_REG	0x0C	/* clear pointer flip-flop (w) */
+#define DMA1_TEMP_REG           0x0D    /* Temporary Register (r) */
+#define DMA1_RESET_REG		0x0D	/* Master Clear (w) */
+#define DMA1_CLR_MASK_REG       0x0E    /* Clear Mask */
+#define DMA1_MASK_ALL_REG       0x0F    /* all-channels mask (w) */
+
+#define DMA2_CMD_REG		0xD0	/* command register (w) */
+#define DMA2_STAT_REG		0xD0	/* status register (r) */
+#define DMA2_REQ_REG            0xD2    /* request register (w) */
+#define DMA2_MASK_REG		0xD4	/* single-channel mask (w) */
+#define DMA2_MODE_REG		0xD6	/* mode register (w) */
+#define DMA2_CLEAR_FF_REG	0xD8	/* clear pointer flip-flop (w) */
+#define DMA2_TEMP_REG           0xDA    /* Temporary Register (r) */
+#define DMA2_RESET_REG		0xDA	/* Master Clear (w) */
+#define DMA2_CLR_MASK_REG       0xDC    /* Clear Mask */
+#define DMA2_MASK_ALL_REG       0xDE    /* all-channels mask (w) */
+
+#define DMA_ADDR_0              0x00    /* DMA address registers */
+#define DMA_ADDR_1              0x02
+#define DMA_ADDR_2              0x04
+#define DMA_ADDR_3              0x06
+#define DMA_ADDR_4              0xC0
+#define DMA_ADDR_5              0xC4
+#define DMA_ADDR_6              0xC8
+#define DMA_ADDR_7              0xCC
+
+#define DMA_CNT_0               0x01    /* DMA count registers */
+#define DMA_CNT_1               0x03
+#define DMA_CNT_2               0x05
+#define DMA_CNT_3               0x07
+#define DMA_CNT_4               0xC2
+#define DMA_CNT_5               0xC6
+#define DMA_CNT_6               0xCA
+#define DMA_CNT_7               0xCE
+
+#define DMA_PAGE_0              0x87    /* DMA page registers */
+#define DMA_PAGE_1              0x83
+#define DMA_PAGE_2              0x81
+#define DMA_PAGE_3              0x82
+#define DMA_PAGE_5              0x8B
+#define DMA_PAGE_6              0x89
+#define DMA_PAGE_7              0x8A
+
+#define DMA_MODE_READ	0x44	/* I/O to memory, no autoinit, increment, single mode */
+#define DMA_MODE_WRITE	0x48	/* memory to I/O, no autoinit, increment, single mode */
+#define DMA_MODE_CASCADE 0xC0   /* pass thru DREQ->HRQ, DACK<-HLDA only */
+
+#define DMA_AUTOINIT	0x10
+
+
+extern spinlock_t  dma_spin_lock;
+
+static __inline__ unsigned long claim_dma_lock(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dma_spin_lock, flags);
+	return flags;
+}
+
+static __inline__ void release_dma_lock(unsigned long flags)
+{
+	spin_unlock_irqrestore(&dma_spin_lock, flags);
+}
+
+/* enable/disable a specific DMA channel */
+static __inline__ void enable_dma(unsigned int dmanr)
+{
+	if (dmanr<=3)
+		dma_outb(dmanr,  DMA1_MASK_REG);
+	else
+		dma_outb(dmanr & 3,  DMA2_MASK_REG);
+}
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+	if (dmanr<=3)
+		dma_outb(dmanr | 4,  DMA1_MASK_REG);
+	else
+		dma_outb((dmanr & 3) | 4,  DMA2_MASK_REG);
+}
+
+/* Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while holding the DMA lock ! ---
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+	if (dmanr<=3)
+		dma_outb(0,  DMA1_CLEAR_FF_REG);
+	else
+		dma_outb(0,  DMA2_CLEAR_FF_REG);
+}
+
+/* set mode (above) for a specific DMA channel */
+static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+{
+	if (dmanr<=3)
+		dma_outb(mode | dmanr,  DMA1_MODE_REG);
+	else
+		dma_outb(mode | (dmanr&3),  DMA2_MODE_REG);
+}
+
+/* Set only the page register bits of the transfer address.
+ * This is used for successive transfers when we know the contents of
+ * the lower 16 bits of the DMA current address register, but a 64k boundary
+ * may have been crossed.
+ */
+static __inline__ void set_dma_page(unsigned int dmanr, unsigned int pagenr)
+{
+	switch(dmanr) {
+		case 0:
+			dma_outb( pagenr       & 0xff, DMA_PAGE_0);
+			dma_outb((pagenr >> 8) & 0xff, DMA_PAGE_0 + 0x400);
+			break;
+		case 1:
+			dma_outb( pagenr       & 0xff, DMA_PAGE_1);
+			dma_outb((pagenr >> 8) & 0xff, DMA_PAGE_1 + 0x400);
+			break;
+		case 2:
+			dma_outb( pagenr       & 0xff, DMA_PAGE_2);
+			dma_outb((pagenr >> 8) & 0xff, DMA_PAGE_2 + 0x400);
+			break;
+		case 3:
+			dma_outb( pagenr       & 0xff, DMA_PAGE_3);
+			dma_outb((pagenr >> 8) & 0xff, DMA_PAGE_3 + 0x400);
+			break;
+		case 5:
+			dma_outb( pagenr       & 0xfe, DMA_PAGE_5);
+			dma_outb((pagenr >> 8) & 0xff, DMA_PAGE_5 + 0x400);
+			break;
+		case 6:
+			dma_outb( pagenr       & 0xfe, DMA_PAGE_6);
+			dma_outb((pagenr >> 8) & 0xff, DMA_PAGE_6 + 0x400);
+			break;
+		case 7:
+			dma_outb( pagenr       & 0xfe, DMA_PAGE_7);
+			dma_outb((pagenr >> 8) & 0xff, DMA_PAGE_7 + 0x400);
+			break;
+       	}
+}
+
+
+/* Set transfer address & page bits for specific DMA channel.
+ * Assumes dma flipflop is clear.
+ */
+static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+	set_dma_page(dmanr, a>>16);
+	if (dmanr <= 3)  {
+	    dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+            dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+	}  else  {
+	    dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
+	    dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
+	}
+}
+
+
+/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
+ * a specific DMA channel.
+ * You must ensure the parameters are valid.
+ * NOTE: from a manual: "the number of transfers is one more
+ * than the initial word count"! This is taken into account.
+ * Assumes dma flip-flop is clear.
+ * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
+ */
+static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+        count--;
+	if (dmanr <= 3)  {
+	    dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+	    dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+        } else {
+	    dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
+	    dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
+        }
+}
+
+
+/* Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * If called before the channel has been used, it may return 1.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ *
+ * Assumes DMA flip-flop is clear.
+ */
+static __inline__ int get_dma_residue(unsigned int dmanr)
+{
+	unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
+					 : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE;
+
+	/* using short to get 16-bit wrap around */
+	unsigned short count;
+
+	count = 1 + dma_inb(io_port);
+	count += dma_inb(io_port) << 8;
+	return (dmanr<=3)? count : (count<<1);
+}
+
+
+/* These are in kernel/dma.c: */
+extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
+extern void free_dma(unsigned int dmanr);	/* release it again */
+
+/* From PCI */
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy 	(0)
+#endif
+
+#endif /* _ASM_MPC1211_DMA_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/mpc1211/io.h linux-2.5.73-bk10/include/asm-sh/mpc1211/io.h
--- linux-2.5.73-bk9/include/asm-sh/mpc1211/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/mpc1211/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,86 @@
+/*
+ * include/asm-sh/io_mpc1211.h
+ *
+ * Copyright 2001 Saito.K & Jeanne
+ *
+ * IO functions for an Interface MPC-1211
+ */
+
+#ifndef _ASM_SH_IO_MPC1211_H
+#define _ASM_SH_IO_MPC1211_H
+
+#include <linux/time.h>
+#include <asm/io_generic.h>
+
+extern unsigned char mpc1211_inb(unsigned long port);
+extern unsigned short mpc1211_inw(unsigned long port);
+extern unsigned int mpc1211_inl(unsigned long port);
+
+extern void mpc1211_outb(unsigned char value, unsigned long port);
+extern void mpc1211_outw(unsigned short value, unsigned long port);
+extern void mpc1211_outl(unsigned int value, unsigned long port);
+
+extern unsigned char mpc1211_inb_p(unsigned long port);
+extern void mpc1211_outb_p(unsigned char value, unsigned long port);
+
+extern void mpc1211_insb(unsigned long port, void *addr, unsigned long count);
+extern void mpc1211_insw(unsigned long port, void *addr, unsigned long count);
+extern void mpc1211_insl(unsigned long port, void *addr, unsigned long count);
+extern void mpc1211_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void mpc1211_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void mpc1211_outsl(unsigned long port, const void *addr, unsigned long count);
+
+extern unsigned char mpc1211_readb(unsigned long addr);
+extern unsigned short mpc1211_readw(unsigned long addr);
+extern unsigned int mpc1211_readl(unsigned long addr);
+extern void mpc1211_writeb(unsigned char b, unsigned long addr);
+extern void mpc1211_writew(unsigned short b, unsigned long addr);
+extern void mpc1211_writel(unsigned int b, unsigned long addr);
+
+extern unsigned long mpc1211_isa_port2addr(unsigned long offset);
+extern int mpc1211_irq_demux(int irq);
+
+extern void setup_mpc1211(void);
+extern void init_mpc1211_IRQ(void);
+extern void heartbeat_mpc1211(void);
+
+extern void mpc1211_rtc_gettimeofday(struct timeval *tv);
+extern int mpc1211_rtc_settimeofday(const struct timeval *tv);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			mpc1211_inb
+# define __inw			mpc1211_inw
+# define __inl			mpc1211_inl
+# define __outb			mpc1211_outb
+# define __outw			mpc1211_outw
+# define __outl			mpc1211_outl
+
+# define __inb_p		mpc1211_inb_p
+# define __inw_p		mpc1211_inw
+# define __inl_p		mpc1211_inl
+# define __outb_p		mpc1211_outb_p
+# define __outw_p		mpc1211_outw
+# define __outl_p		mpc1211_outl
+
+# define __insb			mpc1211_insb
+# define __insw			mpc1211_insw
+# define __insl			mpc1211_insl
+# define __outsb		mpc1211_outsb
+# define __outsw		mpc1211_outsw
+# define __outsl		mpc1211_outsl
+
+# define __readb		mpc1211_readb
+# define __readw		mpc1211_readw
+# define __readl		mpc1211_readl
+# define __writeb		mpc1211_writeb
+# define __writew		mpc1211_writew
+# define __writel		mpc1211_writel
+
+# define __isa_port2addr	mpc1211_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_MPC1211_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/mpc1211/keyboard.h linux-2.5.73-bk10/include/asm-sh/mpc1211/keyboard.h
--- linux-2.5.73-bk9/include/asm-sh/mpc1211/keyboard.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/mpc1211/keyboard.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,64 @@
+/*
+ *  MPC1211 specific keybord definitions
+ *  Taken from the old asm-i386/keybord.h for PC/AT-style definitions
+ *  created 3 Nov 1996 by Geert Uytterhoeven.
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/kd.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+
+#define KEYBOARD_IRQ			1
+#define DISABLE_KBD_DURING_INTERRUPTS	0
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern int pckbd_pm_resume(struct pm_dev *, pm_request_t, void *);
+extern pm_callback pm_kbd_request_override;
+extern unsigned char pckbd_sysrq_xlate[128];
+
+#define kbd_setkeycode		pckbd_setkeycode
+#define kbd_getkeycode		pckbd_getkeycode
+#define kbd_translate		pckbd_translate
+#define kbd_unexpected_up	pckbd_unexpected_up
+#define kbd_leds		pckbd_leds
+#define kbd_init_hw		pckbd_init_hw
+#define kbd_sysrq_xlate		pckbd_sysrq_xlate
+
+#define SYSRQ_KEY 0x54
+
+/* resource allocation */
+#define kbd_request_region()
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+                                             "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
+
+#endif /* __KERNEL__ */
diff -urN linux-2.5.73-bk9/include/asm-sh/mpc1211/m1543c.h linux-2.5.73-bk10/include/asm-sh/mpc1211/m1543c.h
--- linux-2.5.73-bk9/include/asm-sh/mpc1211/m1543c.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/mpc1211/m1543c.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,200 @@
+#ifndef __ASM_SH_M1543C_H
+#define __ASM_SH_M1543C_H
+
+/*
+ * linux/include/asm-sh/m1543c.h
+ * Copyright (C) 2001  Nobuhiro Sakawa
+ * M1543C:PCI-ISA Bus Bridge with Super IO Chip support
+ *
+ * from
+ *
+ * linux/include/asm-sh/smc37c93x.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * SMSC 37C93x Super IO Chip support
+ */
+
+/* Default base I/O address */
+#define FDC_PRIMARY_BASE	0x3f0
+#define IDE1_PRIMARY_BASE	0x1f0
+#define IDE1_SECONDARY_BASE	0x170
+#define PARPORT_PRIMARY_BASE	0x378
+#define COM1_PRIMARY_BASE	0x2f8
+#define COM2_PRIMARY_BASE	0x3f8
+#define COM3_PRIMARY_BASE	0x3e8
+#define RTC_PRIMARY_BASE	0x070
+#define KBC_PRIMARY_BASE	0x060
+#define AUXIO_PRIMARY_BASE	0x000	/* XXX */
+#define I8259_M_CR		0x20
+#define I8259_M_MR		0x21
+#define I8259_S_CR		0xa0
+#define I8259_S_MR		0xa1
+
+/* Logical device number */
+#define LDN_FDC			0
+#define LDN_IDE1		1
+#define LDN_IDE2		2
+#define LDN_PARPORT		3
+#define LDN_COM1		4
+#define LDN_COM2		5
+#define LDN_COM3		11
+#define LDN_RTC			6
+#define LDN_KBC			7
+
+/* Configuration port and key */
+#define CONFIG_PORT		0x3f0
+#define INDEX_PORT		CONFIG_PORT
+#define DATA_PORT		0x3f1
+#define CONFIG_ENTER1		0x51
+#define CONFIG_ENTER2		0x23
+#define CONFIG_EXIT		0xbb
+
+/* Configuration index */
+#define CURRENT_LDN_INDEX	0x07
+#define POWER_CONTROL_INDEX	0x22
+#define ACTIVATE_INDEX		0x30
+#define IO_BASE_HI_INDEX	0x60
+#define IO_BASE_LO_INDEX	0x61
+#define IRQ_SELECT_INDEX	0x70
+#define PS2_IRQ_INDEX		0x72
+#define DMA_SELECT_INDEX	0x74
+
+/* UART stuff. Only for debugging.  */
+/* UART Register */
+
+#define UART_RBR	0x0	/* Receiver Buffer Register (Read Only) */
+#define UART_THR	0x0	/* Transmitter Holding Register (Write Only) */
+#define UART_IER	0x2	/* Interrupt Enable Register */
+#define UART_IIR	0x4	/* Interrupt Ident Register (Read Only) */
+#define UART_FCR	0x4	/* FIFO Control Register (Write Only) */
+#define UART_LCR	0x6	/* Line Control Register */
+#define UART_MCR	0x8	/* MODEM Control Register */
+#define UART_LSR	0xa	/* Line Status Register */
+#define UART_MSR	0xc	/* MODEM Status Register */
+#define UART_SCR	0xe	/* Scratch Register */
+#define UART_DLL	0x0	/* Divisor Latch (LS) */
+#define UART_DLM	0x2	/* Divisor Latch (MS) */
+
+#ifndef __ASSEMBLY__
+typedef struct uart_reg {
+	volatile __u16 rbr;
+	volatile __u16 ier;
+	volatile __u16 iir;
+	volatile __u16 lcr;
+	volatile __u16 mcr;
+	volatile __u16 lsr;
+	volatile __u16 msr;
+	volatile __u16 scr;
+} uart_reg;
+#endif /* ! __ASSEMBLY__ */
+
+/* Alias for Write Only Register */
+
+#define thr	rbr
+#define tcr	iir
+
+/* Alias for Divisor Latch Register */
+
+#define dll	rbr
+#define dlm	ier
+#define fcr	iir
+
+/* Interrupt Enable Register */
+
+#define IER_ERDAI	0x0100	/* Enable Received Data Available Interrupt */
+#define IER_ETHREI	0x0200	/* Enable Transmitter Holding Register Empty Interrupt */
+#define IER_ELSI	0x0400	/* Enable Receiver Line Status Interrupt */
+#define IER_EMSI	0x0800	/* Enable MODEM Status Interrupt */
+
+/* Interrupt Ident Register */
+
+#define IIR_IP		0x0100	/* "0" if Interrupt Pending */
+#define IIR_IIB0	0x0200	/* Interrupt ID Bit 0 */
+#define IIR_IIB1	0x0400	/* Interrupt ID Bit 1 */
+#define IIR_IIB2	0x0800	/* Interrupt ID Bit 2 */
+#define IIR_FIFO	0xc000	/* FIFOs enabled */
+
+/* FIFO Control Register */
+
+#define FCR_FEN		0x0100	/* FIFO enable */
+#define FCR_RFRES	0x0200	/* Receiver FIFO reset */
+#define FCR_TFRES	0x0400	/* Transmitter FIFO reset */
+#define FCR_DMA		0x0800	/* DMA mode select */
+#define FCR_RTL		0x4000	/* Receiver triger (LSB) */
+#define FCR_RTM		0x8000	/* Receiver triger (MSB) */
+
+/* Line Control Register */
+
+#define LCR_WLS0	0x0100	/* Word Length Select Bit 0 */
+#define LCR_WLS1	0x0200	/* Word Length Select Bit 1 */
+#define LCR_STB		0x0400	/* Number of Stop Bits */
+#define LCR_PEN		0x0800	/* Parity Enable */
+#define LCR_EPS		0x1000	/* Even Parity Select */
+#define LCR_SP		0x2000	/* Stick Parity */
+#define LCR_SB		0x4000	/* Set Break */
+#define LCR_DLAB	0x8000	/* Divisor Latch Access Bit */
+
+/* MODEM Control Register */
+
+#define MCR_DTR		0x0100	/* Data Terminal Ready */
+#define MCR_RTS		0x0200	/* Request to Send */
+#define MCR_OUT1	0x0400	/* Out 1 */
+#define MCR_IRQEN	0x0800	/* IRQ Enable */
+#define MCR_LOOP	0x1000	/* Loop */
+
+/* Line Status Register */
+
+#define LSR_DR		0x0100	/* Data Ready */
+#define LSR_OE		0x0200	/* Overrun Error */
+#define LSR_PE		0x0400	/* Parity Error */
+#define LSR_FE		0x0800	/* Framing Error */
+#define LSR_BI		0x1000	/* Break Interrupt */
+#define LSR_THRE	0x2000	/* Transmitter Holding Register Empty */
+#define LSR_TEMT	0x4000	/* Transmitter Empty */
+#define LSR_FIFOE	0x8000	/* Receiver FIFO error */
+
+/* MODEM Status Register */
+
+#define MSR_DCTS	0x0100	/* Delta Clear to Send */
+#define MSR_DDSR	0x0200	/* Delta Data Set Ready */
+#define MSR_TERI	0x0400	/* Trailing Edge Ring Indicator */
+#define MSR_DDCD	0x0800	/* Delta Data Carrier Detect */
+#define MSR_CTS		0x1000	/* Clear to Send */
+#define MSR_DSR		0x2000	/* Data Set Ready */
+#define MSR_RI		0x4000	/* Ring Indicator */
+#define MSR_DCD		0x8000	/* Data Carrier Detect */
+
+/* Baud Rate Divisor */
+
+#define UART_CLK	(1843200)	/* 1.8432 MHz */
+#define UART_BAUD(x)	(UART_CLK / (16 * (x)))
+
+/* RTC register definition */
+#define RTC_SECONDS             0
+#define RTC_SECONDS_ALARM       1
+#define RTC_MINUTES             2
+#define RTC_MINUTES_ALARM       3
+#define RTC_HOURS               4
+#define RTC_HOURS_ALARM         5
+#define RTC_DAY_OF_WEEK         6
+#define RTC_DAY_OF_MONTH        7
+#define RTC_MONTH               8
+#define RTC_YEAR                9
+#define RTC_FREQ_SELECT		10
+# define RTC_UIP 0x80
+# define RTC_DIV_CTL 0x70
+/* This RTC can work under 32.768KHz clock only.  */
+# define RTC_OSC_ENABLE 0x20
+# define RTC_OSC_DISABLE 0x00
+#define RTC_CONTROL     	11
+# define RTC_SET 0x80
+# define RTC_PIE 0x40
+# define RTC_AIE 0x20
+# define RTC_UIE 0x10
+# define RTC_SQWE 0x08
+# define RTC_DM_BINARY 0x04
+# define RTC_24H 0x02
+# define RTC_DST_EN 0x01
+
+#endif  /* __ASM_SH_M1543C_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/mpc1211/mc146818rtc.h linux-2.5.73-bk10/include/asm-sh/mpc1211/mc146818rtc.h
--- linux-2.5.73-bk9/include/asm-sh/mpc1211/mc146818rtc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/mpc1211/mc146818rtc.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,6 @@
+/*
+ * MPC1211 uses PC/AT style RTC definitions.
+ */
+#include <asm-i386/mc146818rtc.h>
+
+
diff -urN linux-2.5.73-bk9/include/asm-sh/mpc1211/mpc1211.h linux-2.5.73-bk10/include/asm-sh/mpc1211/mpc1211.h
--- linux-2.5.73-bk9/include/asm-sh/mpc1211/mpc1211.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/mpc1211/mpc1211.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,18 @@
+#ifndef __ASM_SH_MPC1211_H
+#define __ASM_SH_MPC1211_H
+
+/*
+ * linux/include/asm-sh/mpc1211.h
+ *
+ * Copyright (C) 2001  Saito.K & Jeanne
+ *
+ * Interface MPC-1211 support
+ */
+
+#define PA_PCI_IO       (0xa4000000)    /* PCI I/O space */
+#define PA_PCI_MEM      (0xb0000000)    /* PCI MEM space */
+
+#define PCIPAR          (0xa4000cf8)    /* PCI Config address */
+#define PCIPDR          (0xa4000cfc)    /* PCI Config data    */
+
+#endif  /* __ASM_SH_MPC1211_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/mpc1211/pci.h linux-2.5.73-bk10/include/asm-sh/mpc1211/pci.h
--- linux-2.5.73-bk9/include/asm-sh/mpc1211/pci.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/mpc1211/pci.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,40 @@
+/*
+ *	Low-Level PCI Support for MPC-1211
+ *
+ *      (c) 2002 Saito.K & Jeanne
+ *
+ */
+
+#ifndef _PCI_MPC1211_H_
+#define _PCI_MPC1211_H_
+
+#include <linux/pci.h>
+
+/* set debug level 4=verbose...1=terse */
+//#define DEBUG_PCI 3
+#undef DEBUG_PCI
+
+#ifdef DEBUG_PCI
+#define PCIDBG(n, x...) { if(DEBUG_PCI>=n) printk(x); }
+#else
+#define PCIDBG(n, x...)
+#endif
+
+/* startup values */
+#define PCI_PROBE_BIOS    1
+#define PCI_PROBE_CONF1   2
+#define PCI_PROBE_CONF2   4
+#define PCI_NO_SORT       0x100
+#define PCI_BIOS_SORT     0x200
+#define PCI_NO_CHECKS     0x400
+#define PCI_ASSIGN_ROMS   0x1000
+#define PCI_BIOS_IRQ_SCAN 0x2000
+
+/* MPC-1211 Specific Values */
+#define PCIPAR            (0xa4000cf8)    /* PCI Config address */
+#define PCIPDR            (0xa4000cfc)    /* PCI Config data    */
+
+#define PA_PCI_IO         (0xa4000000)    /* PCI I/O space */
+#define PA_PCI_MEM        (0xb0000000)    /* PCI MEM space */
+
+#endif /* _PCI_MPC1211_H_ */
diff -urN linux-2.5.73-bk9/include/asm-sh/overdrive/fpga.h linux-2.5.73-bk10/include/asm-sh/overdrive/fpga.h
--- linux-2.5.73-bk9/include/asm-sh/overdrive/fpga.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/overdrive/fpga.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,15 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ */
+
+#ifndef __FPGA_OD_H__
+#define __FPGA_OD_H__
+
+/* This routine will program up the fpga which interfaces to the galileo */
+int init_overdrive_fpga(void);
+
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/overdrive/gt64111.h linux-2.5.73-bk10/include/asm-sh/overdrive/gt64111.h
--- linux-2.5.73-bk9/include/asm-sh/overdrive/gt64111.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/overdrive/gt64111.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,109 @@
+#ifndef _GT64111_H_
+#define _GT64111_H_
+
+#define MASTER_INTERFACE         0x0
+#define RAS10_LO_DEC_ADR         0x8        
+#define RAS10_HI_DEC_ADR         0x10
+#define RAS32_LO_DEC_ADR         0x18
+#define RAS32_HI_DEC_ADR         0x20
+#define CS20_LO_DEC_ADR          0x28
+#define CS20_HI_DEC_ADR          0x30
+#define CS3_LO_DEC_ADR           0x38
+#define CS3_HI_DEC_ADR           0x40
+#define PCI_IO_LO_DEC_ADR        0x48
+#define PCI_IO_HI_DEC_ADR        0x50
+#define PCI_MEM0_LO_DEC_ADR      0x58
+#define PCI_MEM0_HI_DEC_ADR      0x60
+#define INTERNAL_SPACE_DEC       0x68
+#define BUS_ERR_ADR_LO_CPU       0x70
+#define READONLY0                0x78
+#define PCI_MEM1_LO_DEC_ADR      0x80
+#define PCI_MEM1_HI_DEC_ADR      0x88
+#define RAS0_LO_DEC_ADR          0x400   
+#define RAS0_HI_DEC_ADR          0x404
+#define RAS1_LO_DEC_ADR          0x408
+#define RAS1_HI_DEC_ADR          0x40c
+#define RAS2_LO_DEC_ADR          0x410
+#define RAS2_HI_DEC_ADR          0x414
+#define RAS3_LO_DEC_ADR          0x418
+#define RAS3_HI_DEC_ADR          0x41c
+#define DEV_CS0_LO_DEC_ADR       0x420
+#define DEV_CS0_HI_DEC_ADR       0x424
+#define DEV_CS1_LO_DEC_ADR       0x428
+#define DEV_CS1_HI_DEC_ADR       0x42c
+#define DEV_CS2_LO_DEC_ADR       0x430
+#define DEV_CS2_HI_DEC_ADR       0x434
+#define DEV_CS3_LO_DEC_ADR       0x438
+#define DEV_CS3_HI_DEC_ADR       0x43c
+#define DEV_BOOTCS_LO_DEC_ADR    0x440
+#define DEV_BOOTCS_HI_DEC_ADR    0x444
+#define DEV_ADR_DEC_ERR          0x470
+#define DRAM_CFG                 0x448   
+#define DRAM_BANK0_PARMS         0x44c   
+#define DRAM_BANK1_PARMS         0x450
+#define DRAM_BANK2_PARMS         0x454
+#define DRAM_BANK3_PARMS         0x458
+#define DEV_BANK0_PARMS          0x45c
+#define DEV_BANK1_PARMS          0x460
+#define DEV_BANK2_PARMS          0x464
+#define DEV_BANK3_PARMS          0x468
+#define DEV_BOOT_BANK_PARMS      0x46c
+#define CH0_DMA_BYTECOUNT        0x800
+#define CH1_DMA_BYTECOUNT        0x804
+#define CH2_DMA_BYTECOUNT        0x808
+#define CH3_DMA_BYTECOUNT        0x80c
+#define CH0_DMA_SRC_ADR          0x810
+#define CH1_DMA_SRC_ADR          0x814
+#define CH2_DMA_SRC_ADR          0x818
+#define CH3_DMA_SRC_ADR          0x81c
+#define CH0_DMA_DST_ADR          0x820
+#define CH1_DMA_DST_ADR          0x824
+#define CH2_DMA_DST_ADR          0x828
+#define CH3_DMA_DST_ADR          0x82c
+#define CH0_NEXT_REC_PTR         0x830
+#define CH1_NEXT_REC_PTR         0x834
+#define CH2_NEXT_REC_PTR         0x838
+#define CH3_NEXT_REC_PTR         0x83c
+#define CH0_CTRL                 0x840
+#define CH1_CTRL                 0x844
+#define CH2_CTRL                 0x848
+#define CH3_CTRL                 0x84c
+#define DMA_ARBITER              0x860
+#define TIMER0                   0x850
+#define TIMER1                   0x854
+#define TIMER2                   0x858
+#define TIMER3                   0x85c
+#define TIMER_CTRL               0x864
+#define PCI_CMD                  0xc00
+#define PCI_TIMEOUT              0xc04
+#define PCI_RAS10_BANK_SIZE      0xc08
+#define PCI_RAS32_BANK_SIZE      0xc0c
+#define PCI_CS20_BANK_SIZE       0xc10
+#define PCI_CS3_BANK_SIZE        0xc14
+#define PCI_SERRMASK             0xc28
+#define PCI_INTACK               0xc34
+#define PCI_BAR_EN               0xc3c
+#define PCI_CFG_ADR              0xcf8
+#define PCI_CFG_DATA             0xcfc
+#define PCI_INTCAUSE             0xc18
+#define PCI_MAST_MASK            0xc1c
+#define PCI_PCIMASK              0xc24
+#define BAR_ENABLE_ADR           0xc3c
+
+/* These are config registers, accessible via PCI space */
+#define PCI_CONFIG_RAS10_BASE_ADR   0x010
+#define PCI_CONFIG_RAS32_BASE_ADR   0x014
+#define PCI_CONFIG_CS20_BASE_ADR    0x018
+#define PCI_CONFIG_CS3_BASE_ADR     0x01c
+#define PCI_CONFIG_INT_REG_MM_ADR   0x020
+#define PCI_CONFIG_INT_REG_IO_ADR   0x024
+#define PCI_CONFIG_BOARD_VENDOR     0x02c
+#define PCI_CONFIG_ROM_ADR          0x030
+#define PCI_CONFIG_INT_PIN_LINE     0x03c
+
+
+
+
+
+#endif
+
diff -urN linux-2.5.73-bk9/include/asm-sh/overdrive/io.h linux-2.5.73-bk10/include/asm-sh/overdrive/io.h
--- linux-2.5.73-bk9/include/asm-sh/overdrive/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/overdrive/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,77 @@
+/*
+ * include/asm-sh/io_od.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an STMicroelectronics Overdrive
+ */
+
+#ifndef _ASM_SH_IO_OD_H
+#define _ASM_SH_IO_OD_H
+
+#include <asm/io_generic.h>
+
+extern unsigned char od_inb(unsigned long port);
+extern unsigned short od_inw(unsigned long port);
+extern unsigned int od_inl(unsigned long port);
+
+extern void od_outb(unsigned char value, unsigned long port);
+extern void od_outw(unsigned short value, unsigned long port);
+extern void od_outl(unsigned int value, unsigned long port);
+
+extern unsigned char od_inb_p(unsigned long port);
+extern unsigned short od_inw_p(unsigned long port);
+extern unsigned int od_inl_p(unsigned long port);
+extern void od_outb_p(unsigned char value, unsigned long port);
+extern void od_outw_p(unsigned short value, unsigned long port);
+extern void od_outl_p(unsigned int value, unsigned long port);
+
+extern void od_insb(unsigned long port, void *addr, unsigned long count);
+extern void od_insw(unsigned long port, void *addr, unsigned long count);
+extern void od_insl(unsigned long port, void *addr, unsigned long count);
+extern void od_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void od_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void od_outsl(unsigned long port, const void *addr, unsigned long count);
+
+extern unsigned long od_isa_port2addr(unsigned long offset);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			od_inb
+# define __inw			od_inw
+# define __inl			od_inl
+# define __outb			od_outb
+# define __outw			od_outw
+# define __outl			od_outl
+
+# define __inb_p		od_inb_p
+# define __inw_p		od_inw_p
+# define __inl_p		od_inl_p
+# define __outb_p		od_outb_p
+# define __outw_p		od_outw_p
+# define __outl_p		od_outl_p
+
+# define __insb			od_insb
+# define __insw			od_insw
+# define __insl			od_insl
+# define __outsb		od_outsb
+# define __outsw		od_outsw
+# define __outsl		od_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	od_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_OD_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/overdrive/overdrive.h linux-2.5.73-bk10/include/asm-sh/overdrive/overdrive.h
--- linux-2.5.73-bk9/include/asm-sh/overdrive/overdrive.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/overdrive/overdrive.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,89 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ */
+
+#include <linux/config.h>
+
+#ifndef __OVERDRIVE_H__
+#define __OVERDRIVE_H__
+
+#define OVERDRIVE_INT_CT 0xa3a00000
+#define OVERDRIVE_INT_DT 0xa3b00000
+
+#define OVERDRIVE_CTRL    0xa3000000
+
+/* Shoving all these bits into the same register is not a good idea. 
+ * As soon as I get a spare moment, I'll change the FPGA and put each 
+ * bit in a separate register
+ */
+
+#define VALID_CTRL_BITS		          0x1f
+
+#define ENABLE_RS232_MASK	  	  0x1e
+#define DISABLE_RS232_BIT		  0x01
+
+#define ENABLE_NMI_MASK			  0x1d
+#define DISABLE_NMI_BIT			  0x02
+
+#define RESET_PCI_MASK			  0x1b
+#define ENABLE_PCI_BIT			  0x04
+
+#define ENABLE_LED_MASK			  0x17
+#define DISABLE_LED_BIT			  0x08
+
+#define RESET_FPGA_MASK			  0x0f
+#define ENABLE_FPGA_BIT			  0x10
+
+
+#define FPGA_DCLK_ADDRESS           0xA3C00000
+
+#define FPGA_DATA        0x01	/*   W */
+#define FPGA_CONFDONE    0x02	/* R   */
+#define FPGA_NOT_STATUS  0x04	/* R   */
+#define FPGA_INITDONE    0x08	/* R   */
+
+#define FPGA_TIMEOUT     100000
+
+
+/* Interrupts for the overdrive. Note that these numbers have 
+ * nothing to do with the actual IRQ numbers they appear on, 
+ * this is all programmable. This is simply the position in the 
+ * INT_CT register.
+ */
+
+#define OVERDRIVE_PCI_INTA              0
+#define OVERDRIVE_PCI_INTB              1
+#define OVERDRIVE_PCI_INTC              2
+#define OVERDRIVE_PCI_INTD              3
+#define OVERDRIVE_GALILEO_INT           4
+#define OVERDRIVE_GALILEO_LOCAL_INT     5
+#define OVERDRIVE_AUDIO_INT             6
+#define OVERDRIVE_KEYBOARD_INT          7
+
+/* Which Linux IRQ should we assign to each interrupt source? */
+#define OVERDRIVE_PCI_IRQ1              2
+#ifdef CONFIG_HACKED_NE2K
+#define OVERDRIVE_PCI_IRQ2              7
+#else
+#define OVERDRIVE_PCI_IRQ2              2
+#undef OVERDRIVE_PCI_INTB 
+#define OVERDRIVE_PCI_INTB OVERDRIVE_PCI_INTA
+
+#endif
+
+/* Put the ESS solo audio chip on IRQ 4 */
+#define OVERDRIVE_ESS_IRQ               4
+
+/* Where the memory behind the PCI bus appears */
+#define PCI_DRAM_BASE   0xb7000000
+#define PCI_DRAM_SIZE (16*1024*1024)
+#define PCI_DRAM_FINISH (PCI_DRAM_BASE+PCI_DRAM_SIZE-1)
+
+/* Where the IO region appears in the memory */
+#define PCI_GTIO_BASE   0xb8000000
+
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/page.h linux-2.5.73-bk10/include/asm-sh/page.h
--- linux-2.5.73-bk9/include/asm-sh/page.h	2003-06-22 11:33:16.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/page.h	2003-07-02 04:57:38.000000000 -0700
@@ -27,12 +27,13 @@
 extern void clear_page(void *to);
 extern void copy_page(void *to, void *from);
 
-#if defined(__sh3__)
-#define clear_user_page(page, vaddr)	clear_page(page)
-#define copy_user_page(to, from, vaddr)	copy_page(to, from)
-#elif defined(__SH4__)
-extern void clear_user_page(void *to, unsigned long address);
-extern void copy_user_page(void *to, void *from, unsigned long address);
+#if defined(CONFIG_CPU_SH3)
+#define clear_user_page(page, vaddr, pg)	clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
+#elif defined(CONFIG_CPU_SH4)
+struct page;
+extern void clear_user_page(void *to, unsigned long address, struct page *pg);
+extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg);
 extern void __clear_user_page(void *to, void *orig_to);
 extern void __copy_user_page(void *to, void *from, void *orig_to);
 #endif
@@ -80,13 +81,24 @@
 #define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
 
+#define MAP_NR(addr)		(((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
+
 #ifndef CONFIG_DISCONTIGMEM
 #define phys_to_page(phys)	(mem_map + (((phys)-__MEMORY_START) >> PAGE_SHIFT))
-#define VALID_PAGE(page)	((page - mem_map) < max_mapnr)
 #define page_to_phys(page)	(((page - mem_map) << PAGE_SHIFT) + __MEMORY_START)
 #endif
 
-#define virt_to_page(kaddr)	phys_to_page(__pa(kaddr))
+/* PFN start number, because of __MEMORY_START */
+#define PFN_START		(__MEMORY_START >> PAGE_SHIFT)
+
+#define pfn_to_page(pfn)	(mem_map + (pfn) - PFN_START)
+#define page_to_pfn(page)	((unsigned long)((page) - mem_map) + PFN_START)
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define pfn_valid(pfn)		(((pfn) - PFN_START) < max_mapnr)
+#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #ifndef __ASSEMBLY__
 
diff -urN linux-2.5.73-bk9/include/asm-sh/param.h linux-2.5.73-bk10/include/asm-sh/param.h
--- linux-2.5.73-bk9/include/asm-sh/param.h	2003-06-22 11:33:33.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/param.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,6 +1,16 @@
 #ifndef __ASM_SH_PARAM_H
 #define __ASM_SH_PARAM_H
 
+#ifdef __KERNEL__
+# ifdef CONFIG_SH_WDT
+#  define HZ		1000		/* Needed for high-res WOVF */
+# else
+#  define HZ		100
+# endif
+# define USER_HZ	100		/* User interfaces are in "ticks" */
+# define CLOCKS_PER_SEC	(USER_HZ)	/* frequency at which times() counts */
+#endif
+
 #ifndef HZ
 #define HZ 100
 #endif
@@ -17,8 +27,4 @@
 
 #define MAXHOSTNAMELEN	64	/* max length of hostname */
 
-#ifdef __KERNEL__
-#define CLOCKS_PER_SEC	HZ	/* frequency at which times() counts */
-#endif
-
 #endif /* __ASM_SH_PARAM_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/pci.h linux-2.5.73-bk10/include/asm-sh/pci.h
--- linux-2.5.73-bk9/include/asm-sh/pci.h	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/pci.h	2003-07-02 04:57:38.000000000 -0700
@@ -4,6 +4,8 @@
 #ifdef __KERNEL__
 
 #include <linux/config.h>
+#include <linux/mm.h>		/* for struct page */
+#include <asm/cacheflush.h>
 
 /* Can be used to override the logic in pci_scan_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
@@ -29,6 +31,10 @@
 #elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
 #define PCIBIOS_MIN_IO          0x4000
 #define PCIBIOS_MIN_MEM         0xFD000000
+
+#elif defined(CONFIG_SH_MPC1211)
+#define PCIBIOS_MIN_IO          0x2000
+#define PCIBIOS_MIN_MEM         0xb0000000
 #endif
 
 struct pci_dev;
@@ -44,6 +50,12 @@
  * SuperH has everything mapped statically like x86.
  */
 
+/* The PCI address space does equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS	(1)
+
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <asm/scatterlist.h>
@@ -148,8 +160,10 @@
 #ifdef CONFIG_SH_PCIDMA_NONCOHERENT
 	int i;
 
-	for (i=0; i<nents; i++)
+	for (i=0; i<nents; i++) {
 		dma_cache_wback_inv(page_address(sg[i].page) + sg[i].offset, sg[i].length);
+		sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+	}
 #endif
 	if (direction == PCI_DMA_NONE)
                 BUG();
@@ -205,8 +219,10 @@
 #ifdef CONFIG_SH_PCIDMA_NONCOHERENT
 	int i;
 
-	for (i=0; i<nelems; i++)
+	for (i=0; i<nelems; i++) {
 		dma_cache_wback_inv(page_address(sg[i].page) + sg[i].offset, sg[i].length);
+		sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+	}
 #endif
 }
 
@@ -232,9 +248,34 @@
  * returns, or alternatively stop on the first sg_dma_len(sg) which
  * is 0.
  */
-#define sg_dma_address(sg)	(virt_to_bus((sg)->address))
+#define sg_dma_address(sg)	(virt_to_bus((sg)->dma_address))
 #define sg_dma_len(sg)		((sg)->length)
 
+/*
+ * A board can define one or more PCI channels that represent built-in (or
+ * external) PCI controllers.
+ */
+struct pci_channel {
+	struct pci_ops *pci_ops;
+	struct resource *io_resource;
+	struct resource *mem_resource;
+	int first_devfn;
+	int last_devfn;
+};
+
+/*
+ * Each board initializes this array and terminates it with a NULL entry.
+ */
+extern struct pci_channel board_pci_channels[];
+
+/* Board-specific fixup routines. */
+extern void pcibios_fixup(void);
+extern void pcibios_fixup_irqs(void);
+
+#ifdef CONFIG_PCI_AUTO
+extern int pciauto_assign_resources(int busno, struct pci_channel *hose);
+#endif
+
 #endif /* __KERNEL__ */
 
 /* generic pci stuff */
diff -urN linux-2.5.73-bk9/include/asm-sh/percpu.h linux-2.5.73-bk10/include/asm-sh/percpu.h
--- linux-2.5.73-bk9/include/asm-sh/percpu.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/percpu.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,6 @@
+#ifndef __ARCH_SH_PERCPU
+#define __ARCH_SH_PERCPU
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ARCH_SH_PERCPU */
diff -urN linux-2.5.73-bk9/include/asm-sh/pgalloc.h linux-2.5.73-bk10/include/asm-sh/pgalloc.h
--- linux-2.5.73-bk9/include/asm-sh/pgalloc.h	2003-06-22 11:32:45.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/pgalloc.h	2003-07-02 04:57:38.000000000 -0700
@@ -4,19 +4,25 @@
 #include <asm/processor.h>
 #include <linux/threads.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 
 #define pgd_quicklist ((unsigned long *)0)
 #define pmd_quicklist ((unsigned long *)0)
 #define pte_quicklist ((unsigned long *)0)
 #define pgtable_cache_size 0L
 
-#define pmd_populate(mm, pmd, pte) \
+#define pmd_populate_kernel(mm, pmd, pte) \
 		set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
 
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+				struct page *pte)
+{
+	set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte)));
+}
+
 /*
  * Allocate and free page tables.
  */
-
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
 	unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
@@ -33,70 +39,70 @@
 	kfree(pgd);
 }
 
-static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long address)
 {
-	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
-	if (pte)
-		clear_page(pte);
+	int count = 0;
+	pte_t *pte;
+
+   	do {
+		pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT);
+		if (pte)
+			clear_page(pte);
+		else {
+			current->state = TASK_UNINTERRUPTIBLE;
+			schedule_timeout(HZ);
+		}
+	} while (!pte && (count++ < 10));
+
 	return pte;
 }
 
-static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+					 unsigned long address)
 {
-	return 0;
+	int count = 0;
+	struct page *pte;
+
+   	do {
+		pte = alloc_pages(GFP_KERNEL, 0);
+		if (pte)
+			clear_page(page_address(pte));
+		else {
+			current->state = TASK_UNINTERRUPTIBLE;
+			schedule_timeout(HZ);
+		}
+	} while (!pte && (count++ < 10));
+
+	return pte;
 }
 
-static inline void pte_free_slow(pte_t *pte)
+static inline void pte_free_kernel(pte_t *pte)
 {
 	free_page((unsigned long)pte);
 }
 
-#define pte_free(pte)		pte_free_slow(pte)
+static inline void pte_free(struct page *pte)
+{
+	__free_page(pte);
+}
+
+#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
 
 /*
  * allocating and freeing a pmd is trivial: the 1-entry pmd is
  * inside the pgd, so has no extra memory associated with it.
  */
-static inline void pmd_free(pmd_t * pmd)
-{
-}
 
-#define pmd_alloc_one_fast(mm, addr)	({ BUG(); ((pmd_t *)1); })
 #define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
-#define pmd_free_slow(x)		do { } while (0)
-#define pmd_free_fast(x)		do { } while (0)
 #define pmd_free(x)			do { } while (0)
+#define __pmd_free_tlb(tlb,x)		do { } while (0)
 #define pgd_populate(mm, pmd, pte)	BUG()
 
-/* Do nothing */
-static inline int do_check_pgt_cache(int low, int high) { }
+#if defined(CONFIG_CPU_SH4)
+#define PG_mapped	PG_arch_1
 
 /*
- * TLB flushing:
- *
- *  - flush_tlb() flushes the current mm struct TLBs
- *  - flush_tlb_all() flushes all processes TLBs
- *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
- *  - flush_tlb_page(vma, vmaddr) flushes one page
- *  - flush_tlb_range(vma, start, end) flushes a range of pages
- *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
- */
-
-extern void flush_tlb(void);
-extern void flush_tlb_all(void);
-extern void flush_tlb_mm(struct mm_struct *mm);
-extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
-			    unsigned long end);
-extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
-extern void __flush_tlb_page(unsigned long asid, unsigned long page);
-
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
-				      unsigned long start, unsigned long end)
-{ /* Nothing to do */
-}
-
-#if defined(__SH4__)
-/*
  * For SH-4, we have our own implementation for ptep_get_and_clear
  */
 static inline pte_t ptep_get_and_clear(pte_t *ptep)
@@ -108,8 +114,9 @@
 		struct page *page;
 		unsigned long pfn = pte_pfn(pte);
 		if (pfn_valid(pfn)) {
-			page = pfn_to_page(page);
-			if (!page->mapping || !page->mapping->i_mmap_shared)
+			page = pfn_to_page(pfn);
+			if (!page->mapping
+			    || list_empty(&page->mapping->i_mmap_shared))
 				__clear_bit(PG_mapped, &page->flags);
 		}
 	}
@@ -156,4 +163,7 @@
 	pte_t old_pte = *ptep;
 	set_pte(ptep, pte_mkdirty(old_pte));
 }
+
+#define check_pgt_cache()	do { } while (0)
+
 #endif /* __ASM_SH_PGALLOC_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/pgtable-2level.h linux-2.5.73-bk10/include/asm-sh/pgtable-2level.h
--- linux-2.5.73-bk9/include/asm-sh/pgtable-2level.h	2003-06-22 11:33:32.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/pgtable-2level.h	2003-07-02 04:57:38.000000000 -0700
@@ -55,6 +55,11 @@
 {
 	return (pmd_t *) dir;
 }
+
+#define pte_pfn(x)		((unsigned long)(((x).pte >> PAGE_SHIFT)))
+#define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot)	__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_SH_PGTABLE_2LEVEL_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/pgtable.h linux-2.5.73-bk10/include/asm-sh/pgtable.h
--- linux-2.5.73-bk9/include/asm-sh/pgtable.h	2003-06-22 11:33:36.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/pgtable.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,8 +1,12 @@
 #ifndef __ASM_SH_PGTABLE_H
 #define __ASM_SH_PGTABLE_H
 
-/* Copyright (C) 1999 Niibe Yutaka */
+/*
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2002, 2003 Paul Mundt
+ */
 
+#include <linux/config.h>
 #include <asm/pgtable-2level.h>
 
 /*
@@ -17,70 +21,6 @@
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern void paging_init(void);
 
-#if defined(__sh3__)
-/* Cache flushing:
- *
- *  - flush_cache_all() flushes entire cache
- *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
- *  - flush_cache_page(mm, vmaddr) flushes a single page
- *  - flush_cache_range(vma, start, end) flushes a range of pages
- *
- *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
- *  - flush_icache_range(start, end) flushes(invalidates) a range for icache
- *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
- *
- *  Caches are indexed (effectively) by physical address on SH-3, so
- *  we don't need them.
- */
-#define flush_cache_all()			do { } while (0)
-#define flush_cache_mm(mm)			do { } while (0)
-#define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
-#define flush_dcache_page(page)			do { } while (0)
-#define flush_icache_range(start, end)		do { } while (0)
-#define flush_icache_page(vma,pg)		do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
-#define flush_cache_sigtramp(vaddr)		do { } while (0)
-
-#define p3_cache_init()				do { } while (0)
-
-#elif defined(__SH4__)
-/*
- *  Caches are broken on SH-4, so we need them.
- */
-
-/* Page is 4K, OC size is 16K, there are four lines. */
-#define CACHE_ALIAS 0x00003000
-
-extern void flush_cache_all(void);
-extern void flush_cache_mm(struct mm_struct *mm);
-extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-			      unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
-extern void flush_dcache_page(struct page *pg);
-extern void flush_icache_range(unsigned long start, unsigned long end);
-extern void flush_cache_sigtramp(unsigned long addr);
-
-#define flush_icache_page(vma,pg)		do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
-
-/* Initialization of P3 area for copy_user_page */
-extern void p3_cache_init(void);
-
-#define PG_mapped	PG_arch_1
-
-/* We provide our own get_unmapped_area to avoid cache alias issue */
-#define HAVE_ARCH_UNMAPPED_AREA
-#endif
-
-/* Flush (write-back only) a region (smaller than a page) */
-extern void __flush_wback_region(void *start, int size);
-/* Flush (write-back & invalidate) a region (smaller than a page) */
-extern void __flush_purge_region(void *start, int size);
-/* Flush (invalidate only) a region (smaller than a page) */
-extern void __flush_invalidate_region(void *start, int size);
-
-
 /*
  * Basically we have the same two-level (which is the logical three level
  * Linux page table layout folded) page tables as the i386.
@@ -127,6 +67,7 @@
 #define _PAGE_ACCESSED 	0x400  /* software: page referenced */
 #define _PAGE_U0_SHARED 0x800  /* software: page is shared in user space */
 
+#define	_PAGE_FILE	0x080  /* software: pagecache or swap? */
 
 /* software: moves to PTEA.TC (Timing Control) */
 #define _PAGE_PCC_AREA5	0x00000000	/* use BSC registers for area5 */
@@ -142,15 +83,18 @@
 #define _PAGE_PCC_ATR16	0x60000001	/* Attribute Memory space, 6 bit bus */
 
 
-/* Mask which drop software flags */
-#if defined(__sh3__)
+/* Mask which drop software flags
+ * We also drop SZ1 bit since it is always 0 and used for _PAGE_FILE
+ * bit in this implementation.
+ */
+#if defined(CONFIG_CPU_SH3)
 /*
  * MMU on SH-3 has bug on SH-bit: We can't use it if MMUCR.IX=1.
  * Work around: Just drop SH-bit.
  */
-#define _PAGE_FLAGS_HARDWARE_MASK	0x1ffff1fc
+#define _PAGE_FLAGS_HARDWARE_MASK	0x1ffff17c
 #else
-#define _PAGE_FLAGS_HARDWARE_MASK	0x1ffff1fe
+#define _PAGE_FLAGS_HARDWARE_MASK	0x1ffff17e
 #endif
 /* Hardware flags: SZ=1 (4k-byte) */
 #define _PAGE_FLAGS_HARD		0x00000010
@@ -161,6 +105,7 @@
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_SHARED)
 
+#ifdef CONFIG_MMU
 #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_FLAGS_HARD)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_SHARED | _PAGE_FLAGS_HARD)
 #define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_FLAGS_HARD)
@@ -169,6 +114,15 @@
 #define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD)
 #define PAGE_KERNEL_PCC(slot, type) \
 			__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_FLAGS_HARD | (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | (type))
+#else /* no mmu */
+#define PAGE_NONE	__pgprot(0)
+#define PAGE_SHARED	__pgprot(0)
+#define PAGE_COPY	__pgprot(0)
+#define PAGE_READONLY	__pgprot(0)
+#define PAGE_KERNEL	__pgprot(0)
+#define PAGE_KERNEL_RO	__pgprot(0)
+#define PAGE_KERNEL_PCC	__pgprot(0)
+#endif
 
 /*
  * As i386 and MIPS, SuperH can't do page protection for execute, and
@@ -214,6 +168,7 @@
 static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
 static inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
 static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_RW; }
 static inline int pte_not_present(pte_t pte){ return !(pte_val(pte) & _PAGE_PRESENT); }
 
@@ -247,26 +202,19 @@
  *
  * extern pte_t mk_pte(struct page *page, pgprot_t pgprot)
  */
-#define mk_pte(page,pgprot)						\
-({	pte_t __pte;							\
-									\
-	set_pte(&__pte, __pte(PHYSADDR(page_address(page))		\
-				+pgprot_val(pgprot)));			\
-	__pte;								\
-})
-
-/* This takes a physical page address that is used by the remapping functions */
-#define mk_pte_phys(physpage, pgprot) \
-({ pte_t __pte; set_pte(&__pte, __pte(physpage + pgprot_val(pgprot))); __pte; })
+#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; }
 
 #define page_pte(page) page_pte_prot(page, __pgprot(0))
 
-#define pmd_page(pmd) \
+#define pmd_page_kernel(pmd) \
 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
 
+#define pmd_page(pmd) \
+	(phys_to_page(pmd_val(pmd)))
+
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
@@ -277,16 +225,21 @@
 /* Find an entry in the third-level page table.. */
 #define pte_index(address) \
 		((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-#define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + \
-			pte_index(address))
+#define pte_offset_kernel(dir, address) \
+	((pte_t *) pmd_page_kernel(*(dir)) + pte_index(address))
+#define pte_offset_map(dir, address) pte_offset_kernel(dir, address)
+#define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address)
+#define pte_unmap(pte)		do { } while (0)
+#define pte_unmap_nested(pte)	do { } while (0)
 
+struct vm_area_struct;
 extern void update_mmu_cache(struct vm_area_struct * vma,
 			     unsigned long address, pte_t pte);
 
 /* Encode and de-code a swap entry */
 /*
  * NOTE: We should set ZEROs at the position of _PAGE_PRESENT
- *       and _PAGE_PROTONOE bits
+ *       and _PAGE_PROTNONE bits
  */
 #define __swp_type(x)		((x).val & 0xff)
 #define __swp_offset(x)		((x).val >> 10)
@@ -295,6 +248,13 @@
 #define __swp_entry_to_pte(x)	((pte_t) { (x).val })
 
 /*
+ * Encode and decode a nonlinear file mapping entry
+ */
+#define PTE_FILE_MAX_BITS	29
+#define pte_to_pgoff(pte)	(pte_val(pte))
+#define pgoff_to_pte(off)	((pte_t) { (off) | _PAGE_FILE })
+
+/*
  * Routines for update of PTE 
  *
  * We just can use generic implementation, as SuperH has no SMP feature.
@@ -317,4 +277,9 @@
  */
 #define pgtable_cache_init()	do { } while (0)
 
+#ifndef CONFIG_MMU
+extern unsigned int kobjsize(const void *objp);
+#endif /* !CONFIG_MMU */
+
 #endif /* __ASM_SH_PAGE_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/poll.h linux-2.5.73-bk10/include/asm-sh/poll.h
--- linux-2.5.73-bk9/include/asm-sh/poll.h	2003-06-22 11:33:35.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/poll.h	2003-07-02 04:57:38.000000000 -0700
@@ -15,6 +15,7 @@
 #define POLLWRNORM	0x0100
 #define POLLWRBAND	0x0200
 #define POLLMSG		0x0400
+#define POLLREMOVE	0x1000
 
 struct pollfd {
 	int fd;
diff -urN linux-2.5.73-bk9/include/asm-sh/posix_types.h linux-2.5.73-bk10/include/asm-sh/posix_types.h
--- linux-2.5.73-bk9/include/asm-sh/posix_types.h	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/posix_types.h	2003-07-02 04:57:38.000000000 -0700
@@ -22,6 +22,8 @@
 typedef long		__kernel_time_t;
 typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
 typedef unsigned short	__kernel_uid16_t;
diff -urN linux-2.5.73-bk9/include/asm-sh/processor.h linux-2.5.73-bk10/include/asm-sh/processor.h
--- linux-2.5.73-bk9/include/asm-sh/processor.h	2003-06-22 11:32:40.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/processor.h	2003-07-02 04:57:38.000000000 -0700
@@ -2,6 +2,7 @@
  * include/asm-sh/processor.h
  *
  * Copyright (C) 1999, 2000  Niibe Yutaka
+ * Copyright (C) 2002 Paul Mundt
  */
 
 #ifndef __ASM_SH_PROCESSOR_H
@@ -9,6 +10,7 @@
 
 #include <asm/page.h>
 #include <asm/types.h>
+#include <asm/cache.h>
 #include <linux/threads.h>
 
 /*
@@ -17,14 +19,23 @@
  */
 #define current_text_addr() ({ void *pc; __asm__("mova	1f, %0\n1:":"=z" (pc)); pc; })
 
+/* Core Processor Version Register */
+#define CCN_PVR		0xff000030
+#define CCN_PRR		0xff000044
 /*
  *  CPU type and hardware bug flags. Kept separately for each CPU.
  */
 enum cpu_type {
+	CPU_SH7604,		/* Represents 7604 */
 	CPU_SH7708,		/* Represents 7707, 7708, 7708S, 7708R, 7709 */
 	CPU_SH7729,		/* Represents 7709A, 7729 */
-	CPU_SH7750,     /* Represents 7750, 7751 */
-	CPU_ST40STB1,
+	CPU_SH7750,     	/* Represents 7750 */
+	CPU_SH7750S,		/* Represents 7750S */
+	CPU_SH7750R,		/* Represents 7750R */
+	CPU_SH7751,		/* Represents 7751 */
+	CPU_SH7751R,		/* Represents 7751R */
+	CPU_ST40RA,		/* Represents ST40RA (formerly ST40STB1) */
+	CPU_ST40GX1,		/* Represents ST40GX1 */
 	CPU_SH_NONE
 };
 
@@ -37,12 +48,22 @@
 #ifdef CONFIG_CPU_SUBTYPE_ST40STB1
 	unsigned int memory_clock;
 #endif
+
+	struct cache_info icache;
+	struct cache_info dcache;
+
+	unsigned long flags;
 };
 
+#ifdef CONFIG_SMP
+extern struct sh_cpuinfo cpu_data[];
+#define current_cpu_data cpu_data[smp_processor_id()]
+#else
 extern struct sh_cpuinfo boot_cpu_data;
 
 #define cpu_data (&boot_cpu_data)
 #define current_cpu_data boot_cpu_data
+#endif
 
 /*
  * User space process size: 2GB.
@@ -98,6 +119,8 @@
 	struct sh_fpu_soft_struct soft;
 };
 
+#define CPU_HAS_FPU	0x0001
+
 struct thread_struct {
 	unsigned long sp;
 	unsigned long pc;
@@ -147,9 +170,14 @@
  * Bus types
  */
 #define EISA_bus 0
+#define EISA_bus__is_a_macro /* for versions in ksyms.c */
 #define MCA_bus 0
 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
+/* Copy and release all segment info associated with a VM */
+#define copy_segments(p, mm)	do { } while(0)
+#define release_segments(mm)	do { } while(0)
+
 /*
  * FPU lazy state save handling.
  */
@@ -178,19 +206,23 @@
 			     : "r" (~SR_FD));
 }
 
+#ifdef CONFIG_CPU_SH4
 extern void save_fpu(struct task_struct *__tsk);
+#else
+#define save_fpu(tsk)	do { } while (0)
+#endif
 
-#define unlazy_fpu(tsk) do { 			\
-	if ((tsk)->flags & PF_USEDFPU) {	\
-		save_fpu(tsk); 			\
-	}					\
+#define unlazy_fpu(tsk) do { 				\
+	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {	\
+		save_fpu(tsk); 				\
+	}						\
 } while (0)
 
-#define clear_fpu(tsk) do { 			\
-	if ((tsk)->flags & PF_USEDFPU) { 	\
-		(tsk)->flags &= ~PF_USEDFPU; 	\
-		release_fpu();			\
-	}					\
+#define clear_fpu(tsk) do { 					\
+	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { 		\
+		clear_tsk_thread_flag(tsk, TIF_USEDFPU); 	\
+		release_fpu();					\
+	}							\
 } while (0)
 
 /* Double presision, NANS as NANS, rounding to nearest, no exceptions */
@@ -202,24 +234,13 @@
 /*
  * Return saved PC of a blocked thread.
  */
-static __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
-{
-	return t->pc;
-}
+#define thread_saved_pc(tsk)	(tsk->thread.pc)
 
 extern unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)  ((tsk)->thread.pc)
 #define KSTK_ESP(tsk)  ((tsk)->thread.sp)
 
-#define THREAD_SIZE (2*PAGE_SIZE)
-extern struct task_struct * alloc_task_struct(void);
-extern void free_task_struct(struct task_struct *);
-#define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count)
-
-#define init_task	(init_task_union.task)
-#define init_stack	(init_task_union.stack)
-
 #define cpu_relax()	barrier()
 
 #endif /* __ASM_SH_PROCESSOR_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/ptrace.h linux-2.5.73-bk10/include/asm-sh/ptrace.h
--- linux-2.5.73-bk9/include/asm-sh/ptrace.h	2003-06-22 11:33:11.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/ptrace.h	2003-07-02 04:57:38.000000000 -0700
@@ -2,6 +2,7 @@
 #define __ASM_SH_PTRACE_H
 
 #include <asm/processor.h>
+#include <asm/ubc.h>
 
 /*
  * Copyright (C) 1999, 2000  Niibe Yutaka
@@ -44,7 +45,8 @@
 #define REG_XDREG14	47
 #define REG_FPSCR	48
 
-#define PTRACE_OLDSETOPTIONS         21
+/* options set using PTRACE_SETOPTIONS */
+#define PTRACE_O_TRACESYSGOOD     0x00000001
 
 /*
  * This struct defines the way the registers are stored on the
@@ -58,75 +60,13 @@
 	unsigned long gbr;
 	unsigned long mach;
 	unsigned long macl;
-	long syscall_nr;
+	long tra;
 };
 
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
 extern void show_regs(struct pt_regs *);
-
-/* User Break Controller */
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7709)
-#define UBC_TYPE_SH7729	(cpu_data->type == CPU_SH7729)
-#else
-#define UBC_TYPE_SH7729	0
-#endif
-
-#if defined(__sh3__)
-#define UBC_BARA                0xffffffb0
-#define UBC_BAMRA               0xffffffb4
-#define UBC_BBRA                0xffffffb8
-#define UBC_BASRA               0xffffffe4
-#define UBC_BARB                0xffffffa0
-#define UBC_BAMRB               0xffffffa4
-#define UBC_BBRB                0xffffffa8
-#define UBC_BASRB               0xffffffe8
-#define UBC_BDRB                0xffffff90
-#define UBC_BDMRB               0xffffff94
-#define UBC_BRCR                0xffffff98
-#elif defined(__SH4__)
-#define UBC_BARA		0xff200000
-#define UBC_BAMRA		0xff200004
-#define UBC_BBRA		0xff200008
-#define UBC_BASRA		0xff000014
-#define UBC_BARB		0xff20000c
-#define UBC_BAMRB		0xff200010
-#define UBC_BBRB		0xff200014
-#define UBC_BASRB		0xff000018
-#define UBC_BDRB		0xff200018
-#define UBC_BDMRB		0xff20001c
-#define UBC_BRCR		0xff200020
-#endif
-
-#define BAMR_ASID		(1 << 2)
-#define BAMR_NONE		0
-#define BAMR_10			0x1
-#define BAMR_12			0x2
-#define BAMR_ALL		0x3
-#define BAMR_16			0x8
-#define BAMR_20			0x9
-
-#define BBR_INST		(1 << 4)
-#define BBR_DATA		(2 << 4)
-#define BBR_READ		(1 << 2)
-#define BBR_WRITE		(2 << 2)
-#define BBR_BYTE		0x1
-#define BBR_HALF		0x2
-#define BBR_LONG		0x3
-#define BBR_QUAD		(1 << 6)	/* SH7750 */
-#define BBR_CPU			(1 << 6)	/* SH7709A,SH7729 */
-#define BBR_DMA			(2 << 6)	/* SH7709A,SH7729 */
-
-#define BRCR_CMFA		(1 << 15)
-#define BRCR_CMFB		(1 << 14)
-#define BRCR_PCTE		(1 << 11)
-#define BRCR_PCBA		(1 << 10)	/* 1: after execution */
-#define BRCR_DBEB		(1 << 7)
-#define BRCR_PCBB		(1 << 6)
-#define BRCR_SEQ		(1 << 3)
-#define BRCR_UBDE		(1 << 0)
 #endif
 
 #endif /* __ASM_SH_PTRACE_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/rtc.h linux-2.5.73-bk10/include/asm-sh/rtc.h
--- linux-2.5.73-bk9/include/asm-sh/rtc.h	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/rtc.h	2003-07-02 04:57:38.000000000 -0700
@@ -2,12 +2,13 @@
 #define _ASM_RTC_H
 
 #include <asm/machvec.h>
+#include <asm/cpu/rtc.h>
 
 #define rtc_gettimeofday sh_mv.mv_rtc_gettimeofday
 #define rtc_settimeofday sh_mv.mv_rtc_settimeofday
 
-extern void sh_rtc_gettimeofday(struct timeval *tv);
-extern int sh_rtc_settimeofday(const struct timeval *tv);
+extern void sh_rtc_gettimeofday(struct timespec *ts);
+extern int sh_rtc_settimeofday(const time_t secs);
 
 /* RCR1 Bits */
 #define RCR1_CF		0x80	/* Carry Flag             */
@@ -23,46 +24,5 @@
 #define RCR2_RESET	0x02	/* Reset bit               */
 #define RCR2_START	0x01	/* Start bit               */
 
-#if defined(__sh3__)
-/* SH-3 RTC */
-#define R64CNT  	0xfffffec0
-#define RSECCNT 	0xfffffec2
-#define RMINCNT 	0xfffffec4
-#define RHRCNT  	0xfffffec6
-#define RWKCNT  	0xfffffec8
-#define RDAYCNT 	0xfffffeca
-#define RMONCNT 	0xfffffecc
-#define RYRCNT  	0xfffffece
-#define RSECAR  	0xfffffed0
-#define RMINAR  	0xfffffed2
-#define RHRAR   	0xfffffed4
-#define RWKAR   	0xfffffed6
-#define RDAYAR  	0xfffffed8
-#define RMONAR  	0xfffffeda
-#define RCR1    	0xfffffedc
-#define RCR2    	0xfffffede
-
-#define RTC_BIT_INVERTED	0	/* No bug on SH7708, SH7709A */
-#elif defined(__SH4__)
-/* SH-4 RTC */
-#define R64CNT  	0xffc80000
-#define RSECCNT 	0xffc80004
-#define RMINCNT 	0xffc80008
-#define RHRCNT  	0xffc8000c
-#define RWKCNT  	0xffc80010
-#define RDAYCNT 	0xffc80014
-#define RMONCNT 	0xffc80018
-#define RYRCNT  	0xffc8001c  /* 16bit */
-#define RSECAR  	0xffc80020
-#define RMINAR  	0xffc80024
-#define RHRAR   	0xffc80028
-#define RWKAR   	0xffc8002c
-#define RDAYAR  	0xffc80030
-#define RMONAR  	0xffc80034
-#define RCR1    	0xffc80038
-#define RCR2    	0xffc8003c
-
-#define RTC_BIT_INVERTED	0x40	/* bug on SH7750, SH7750S */
-#endif
-
 #endif /* _ASM_RTC_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/rwsem.h linux-2.5.73-bk10/include/asm-sh/rwsem.h
--- linux-2.5.73-bk9/include/asm-sh/rwsem.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/rwsem.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,170 @@
+/*
+ * include/asm-ppc/rwsem.h: R/W semaphores for SH using the stuff
+ * in lib/rwsem.c.
+ */
+
+#ifndef _ASM_SH_RWSEM_H
+#define _ASM_SH_RWSEM_H
+
+#ifdef __KERNEL__
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+	long		count;
+#define RWSEM_UNLOCKED_VALUE		0x00000000
+#define RWSEM_ACTIVE_BIAS		0x00000001
+#define RWSEM_ACTIVE_MASK		0x0000ffff
+#define RWSEM_WAITING_BIAS		(-0x00010000)
+#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#if RWSEM_DEBUG
+	int			debug;
+#endif
+};
+
+/*
+ * initialisation
+ */
+#if RWSEM_DEBUG
+#define __RWSEM_DEBUG_INIT      , 0
+#else
+#define __RWSEM_DEBUG_INIT	/* */
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEBUG_INIT }
+
+#define DECLARE_RWSEM(name)		\
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+
+static inline void init_rwsem(struct rw_semaphore *sem)
+{
+	sem->count = RWSEM_UNLOCKED_VALUE;
+	spin_lock_init(&sem->wait_lock);
+	INIT_LIST_HEAD(&sem->wait_list);
+#if RWSEM_DEBUG
+	sem->debug = 0;
+#endif
+}
+
+/*
+ * lock for reading
+ */
+static inline void __down_read(struct rw_semaphore *sem)
+{
+	if (atomic_inc_return((atomic_t *)(&sem->count)) > 0)
+		smp_wmb();
+	else
+		rwsem_down_read_failed(sem);
+}
+
+static inline int __down_read_trylock(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	while ((tmp = sem->count) >= 0) {
+		if (tmp == cmpxchg(&sem->count, tmp,
+				   tmp + RWSEM_ACTIVE_READ_BIAS)) {
+			smp_wmb();
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * lock for writing
+ */
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+				(atomic_t *)(&sem->count));
+	if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
+		smp_wmb();
+	else
+		rwsem_down_write_failed(sem);
+}
+
+static inline int __down_write_trylock(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+		      RWSEM_ACTIVE_WRITE_BIAS);
+	smp_wmb();
+	return tmp == RWSEM_UNLOCKED_VALUE;
+}
+
+/*
+ * unlock after reading
+ */
+static inline void __up_read(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	smp_wmb();
+	tmp = atomic_dec_return((atomic_t *)(&sem->count));
+	if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void __up_write(struct rw_semaphore *sem)
+{
+	smp_wmb();
+	if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+			      (atomic_t *)(&sem->count)) < 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * implement atomic add functionality
+ */
+static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+{
+	atomic_add(delta, (atomic_t *)(&sem->count));
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void __downgrade_write(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	smp_wmb();
+	tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
+	if (tmp < 0)
+		rwsem_downgrade_wake(sem);
+}
+
+/*
+ * implement exchange and add functionality
+ */
+static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+{
+	smp_mb();
+	return atomic_add_return(delta, (atomic_t *)(&sem->count));
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_SH_RWSEM_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/saturn/io.h linux-2.5.73-bk10/include/asm-sh/saturn/io.h
--- linux-2.5.73-bk9/include/asm-sh/saturn/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/saturn/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,57 @@
+/*
+ * include/asm-sh/saturn/io.h
+ *
+ * I/O functions for use on the Sega Saturn.
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#ifndef __ASM_SH_SATURN_IO_H
+#define __ASM_SH_SATURN_IO_H
+
+#include <asm/io_generic.h>
+
+/* arch/sh/boards/saturn/io.c */
+extern unsigned long saturn_isa_port2addr(unsigned long offset);
+extern void *saturn_ioremap(unsigned long offset, unsigned long size);
+extern void saturn_iounmap(void *addr);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			generic_inb
+# define __inw			generic_inw
+# define __inl			generic_inl
+# define __outb			generic_outb
+# define __outw			generic_outw
+# define __outl			generic_outl
+
+# define __inb_p		generic_inb_p
+# define __inw_p		generic_inw
+# define __inl_p		generic_inl
+# define __outb_p		generic_outb_p
+# define __outw_p		generic_outw
+# define __outl_p		generic_outl
+
+# define __insb			generic_insb
+# define __insw			generic_insw
+# define __insl			generic_insl
+# define __outsb		generic_outsb
+# define __outsw		generic_outsw
+# define __outsl		generic_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	saturn_isa_port2addr
+# define __ioremap		saturn_ioremap
+# define __iounmap		saturn_iounmap
+
+#endif
+
+#endif /* __ASM_SH_SATURN_IO_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/saturn/smpc.h linux-2.5.73-bk10/include/asm-sh/saturn/smpc.h
--- linux-2.5.73-bk9/include/asm-sh/saturn/smpc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/saturn/smpc.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,34 @@
+/*
+ * include/asm-sh/saturn/smpc.h
+ *
+ * System Manager / Peripheral Control definitions.
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#ifndef __ASM_SH_SATURN_SMPC_H
+#define __ASM_SH_SATURN_SMPC_H
+
+#include <asm/io.h>
+
+#define SMPC_COMMAND	0x2010001f	/* SMPC command register */
+#define SMPC_RESULT	0x2010005f	/* SMPC result register */
+#define SMPC_STATUS	0x20100063	/* SMPC status register */
+
+#define SMPC_CMD_MSHON	0x0001		/* Master SH On */
+#define SMPC_CMD_SSHON	0x0002		/* Slave SH On */
+#define SMPC_CMD_SSHOFF	0x0003		/* Slave SH Off */
+#define SMPC_CMD_SNDON	0x0004		/* Sound On */
+#define SMPC_CMD_SNDOFF	0x0005		/* Sound Off */
+#define SMPC_CMD_CDON	0x0006		/* CD On */
+#define SMPC_CMD_CDOFF	0x0007		/* CD Off */
+
+static inline void smpc_barrier(void)
+{
+	while ((ctrl_inb(SMPC_STATUS) & 0x0001) == 0x0001)
+		;
+}
+
+#endif /* __ASM_SH_SATURN_SMPC_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/se/io.h linux-2.5.73-bk10/include/asm-sh/se/io.h
--- linux-2.5.73-bk9/include/asm-sh/se/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/se/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,80 @@
+/*
+ * include/asm-sh/io_se.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an Hitachi SolutionEngine
+ */
+
+#ifndef _ASM_SH_IO_SE_H
+#define _ASM_SH_IO_SE_H
+
+#include <asm/io_generic.h>
+
+extern unsigned char se_inb(unsigned long port);
+extern unsigned short se_inw(unsigned long port);
+extern unsigned int se_inl(unsigned long port);
+
+extern void se_outb(unsigned char value, unsigned long port);
+extern void se_outw(unsigned short value, unsigned long port);
+extern void se_outl(unsigned int value, unsigned long port);
+
+extern unsigned char se_inb_p(unsigned long port);
+extern void se_outb_p(unsigned char value, unsigned long port);
+
+extern void se_insb(unsigned long port, void *addr, unsigned long count);
+extern void se_insw(unsigned long port, void *addr, unsigned long count);
+extern void se_insl(unsigned long port, void *addr, unsigned long count);
+extern void se_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void se_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void se_outsl(unsigned long port, const void *addr, unsigned long count);
+
+extern unsigned char se_readb(unsigned long addr);
+extern unsigned short se_readw(unsigned long addr);
+extern unsigned int se_readl(unsigned long addr);
+extern void se_writeb(unsigned char b, unsigned long addr);
+extern void se_writew(unsigned short b, unsigned long addr);
+extern void se_writel(unsigned int b, unsigned long addr);
+
+extern unsigned long se_isa_port2addr(unsigned long offset);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			se_inb
+# define __inw			se_inw
+# define __inl			se_inl
+# define __outb			se_outb
+# define __outw			se_outw
+# define __outl			se_outl
+
+# define __inb_p		se_inb_p
+# define __inw_p		se_inw
+# define __inl_p		se_inl
+# define __outb_p		se_outb_p
+# define __outw_p		se_outw
+# define __outl_p		se_outl
+
+# define __insb			se_insb
+# define __insw			se_insw
+# define __insl			se_insl
+# define __outsb		se_outsb
+# define __outsw		se_outsw
+# define __outsl		se_outsl
+
+# define __readb		se_readb
+# define __readw		se_readw
+# define __readl		se_readl
+# define __writeb		se_writeb
+# define __writew		se_writew
+# define __writel		se_writel
+
+# define __isa_port2addr	se_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_SE_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/se/se.h linux-2.5.73-bk10/include/asm-sh/se/se.h
--- linux-2.5.73-bk9/include/asm-sh/se/se.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/se/se.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,69 @@
+#ifndef __ASM_SH_HITACHI_SE_H
+#define __ASM_SH_HITACHI_SE_H
+
+/*
+ * linux/include/asm-sh/hitachi_se.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine support
+ */
+
+/* Box specific addresses.  */
+
+#define PA_ROM		0x00000000	/* EPROM */
+#define PA_ROM_SIZE	0x00400000	/* EPROM size 4M byte */
+#define PA_FROM		0x01000000	/* EPROM */
+#define PA_FROM_SIZE	0x00400000	/* EPROM size 4M byte */
+#define PA_EXT1		0x04000000
+#define PA_EXT1_SIZE	0x04000000
+#define PA_EXT2		0x08000000
+#define PA_EXT2_SIZE	0x04000000
+#define PA_SDRAM	0x0c000000
+#define PA_SDRAM_SIZE	0x04000000
+
+#define PA_EXT4		0x12000000
+#define PA_EXT4_SIZE	0x02000000
+#define PA_EXT5		0x14000000
+#define PA_EXT5_SIZE	0x04000000
+#define PA_PCIC		0x18000000	/* MR-SHPC-01 PCMCIA */
+
+#define PA_83902	0xb0000000	/* DP83902A */
+#define PA_83902_IF	0xb0040000	/* DP83902A remote io port */
+#define PA_83902_RST	0xb0080000	/* DP83902A reset port */
+
+#define PA_SUPERIO	0xb0400000	/* SMC37C935A super io chip */
+#define PA_DIPSW0	0xb0800000	/* Dip switch 5,6 */
+#define PA_DIPSW1	0xb0800002	/* Dip switch 7,8 */
+#define PA_LED		0xb0c00000	/* LED */
+#define PA_BCR		0xb1400000	/* FPGA */
+
+#define PA_MRSHPC	0xb83fffe0	/* MR-SHPC-01 PCMCIA controller */
+#define PA_MRSHPC_MW1	0xb8400000	/* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2	0xb8500000	/* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO	0xb8600000	/* MR-SHPC-01 I/O window base */
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+
+#define BCR_ILCRA	(PA_BCR + 0)
+#define BCR_ILCRB	(PA_BCR + 2)
+#define BCR_ILCRC	(PA_BCR + 4)
+#define BCR_ILCRD	(PA_BCR + 6)
+#define BCR_ILCRE	(PA_BCR + 8)
+#define BCR_ILCRF	(PA_BCR + 10)
+#define BCR_ILCRG	(PA_BCR + 12)
+
+#define IRQ_STNIC	10
+
+#endif  /* __ASM_SH_HITACHI_SE_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/se/smc37c93x.h linux-2.5.73-bk10/include/asm-sh/se/smc37c93x.h
--- linux-2.5.73-bk9/include/asm-sh/se/smc37c93x.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/se/smc37c93x.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,190 @@
+#ifndef __ASM_SH_SMC37C93X_H
+#define __ASM_SH_SMC37C93X_H
+
+/*
+ * linux/include/asm-sh/smc37c93x.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * SMSC 37C93x Super IO Chip support
+ */
+
+/* Default base I/O address */
+#define FDC_PRIMARY_BASE	0x3f0
+#define IDE1_PRIMARY_BASE	0x1f0
+#define IDE1_SECONDARY_BASE	0x170
+#define PARPORT_PRIMARY_BASE	0x378
+#define COM1_PRIMARY_BASE	0x2f8
+#define COM2_PRIMARY_BASE	0x3f8
+#define RTC_PRIMARY_BASE	0x070
+#define KBC_PRIMARY_BASE	0x060
+#define AUXIO_PRIMARY_BASE	0x000	/* XXX */
+
+/* Logical device number */
+#define LDN_FDC			0
+#define LDN_IDE1		1
+#define LDN_IDE2		2
+#define LDN_PARPORT		3
+#define LDN_COM1		4
+#define LDN_COM2		5
+#define LDN_RTC			6
+#define LDN_KBC			7
+#define LDN_AUXIO		8
+
+/* Configuration port and key */
+#define CONFIG_PORT		0x3f0
+#define INDEX_PORT		CONFIG_PORT
+#define DATA_PORT		0x3f1
+#define CONFIG_ENTER		0x55
+#define CONFIG_EXIT		0xaa
+
+/* Configuration index */
+#define CURRENT_LDN_INDEX	0x07
+#define POWER_CONTROL_INDEX	0x22
+#define ACTIVATE_INDEX		0x30
+#define IO_BASE_HI_INDEX	0x60
+#define IO_BASE_LO_INDEX	0x61
+#define IRQ_SELECT_INDEX	0x70
+#define DMA_SELECT_INDEX	0x74
+
+#define GPIO46_INDEX		0xc6
+#define GPIO47_INDEX		0xc7
+
+/* UART stuff. Only for debugging.  */
+/* UART Register */
+
+#define UART_RBR	0x0	/* Receiver Buffer Register (Read Only) */
+#define UART_THR	0x0	/* Transmitter Holding Register (Write Only) */
+#define UART_IER	0x2	/* Interrupt Enable Register */
+#define UART_IIR	0x4	/* Interrupt Ident Register (Read Only) */
+#define UART_FCR	0x4	/* FIFO Control Register (Write Only) */
+#define UART_LCR	0x6	/* Line Control Register */
+#define UART_MCR	0x8	/* MODEM Control Register */
+#define UART_LSR	0xa	/* Line Status Register */
+#define UART_MSR	0xc	/* MODEM Status Register */
+#define UART_SCR	0xe	/* Scratch Register */
+#define UART_DLL	0x0	/* Divisor Latch (LS) */
+#define UART_DLM	0x2	/* Divisor Latch (MS) */
+
+#ifndef __ASSEMBLY__
+typedef struct uart_reg {
+	volatile __u16 rbr;
+	volatile __u16 ier;
+	volatile __u16 iir;
+	volatile __u16 lcr;
+	volatile __u16 mcr;
+	volatile __u16 lsr;
+	volatile __u16 msr;
+	volatile __u16 scr;
+} uart_reg;
+#endif /* ! __ASSEMBLY__ */
+
+/* Alias for Write Only Register */
+
+#define thr	rbr
+#define tcr	iir
+
+/* Alias for Divisor Latch Register */
+
+#define dll	rbr
+#define dlm	ier
+#define fcr	iir
+
+/* Interrupt Enable Register */
+
+#define IER_ERDAI	0x0100	/* Enable Received Data Available Interrupt */
+#define IER_ETHREI	0x0200	/* Enable Transmitter Holding Register Empty Interrupt */
+#define IER_ELSI	0x0400	/* Enable Receiver Line Status Interrupt */
+#define IER_EMSI	0x0800	/* Enable MODEM Status Interrupt */
+
+/* Interrupt Ident Register */
+
+#define IIR_IP		0x0100	/* "0" if Interrupt Pending */
+#define IIR_IIB0	0x0200	/* Interrupt ID Bit 0 */
+#define IIR_IIB1	0x0400	/* Interrupt ID Bit 1 */
+#define IIR_IIB2	0x0800	/* Interrupt ID Bit 2 */
+#define IIR_FIFO	0xc000	/* FIFOs enabled */
+
+/* FIFO Control Register */
+
+#define FCR_FEN		0x0100	/* FIFO enable */
+#define FCR_RFRES	0x0200	/* Receiver FIFO reset */
+#define FCR_TFRES	0x0400	/* Transmitter FIFO reset */
+#define FCR_DMA		0x0800	/* DMA mode select */
+#define FCR_RTL		0x4000	/* Receiver triger (LSB) */
+#define FCR_RTM		0x8000	/* Receiver triger (MSB) */
+
+/* Line Control Register */
+
+#define LCR_WLS0	0x0100	/* Word Length Select Bit 0 */
+#define LCR_WLS1	0x0200	/* Word Length Select Bit 1 */
+#define LCR_STB		0x0400	/* Number of Stop Bits */
+#define LCR_PEN		0x0800	/* Parity Enable */
+#define LCR_EPS		0x1000	/* Even Parity Select */
+#define LCR_SP		0x2000	/* Stick Parity */
+#define LCR_SB		0x4000	/* Set Break */
+#define LCR_DLAB	0x8000	/* Divisor Latch Access Bit */
+
+/* MODEM Control Register */
+
+#define MCR_DTR		0x0100	/* Data Terminal Ready */
+#define MCR_RTS		0x0200	/* Request to Send */
+#define MCR_OUT1	0x0400	/* Out 1 */
+#define MCR_IRQEN	0x0800	/* IRQ Enable */
+#define MCR_LOOP	0x1000	/* Loop */
+
+/* Line Status Register */
+
+#define LSR_DR		0x0100	/* Data Ready */
+#define LSR_OE		0x0200	/* Overrun Error */
+#define LSR_PE		0x0400	/* Parity Error */
+#define LSR_FE		0x0800	/* Framing Error */
+#define LSR_BI		0x1000	/* Break Interrupt */
+#define LSR_THRE	0x2000	/* Transmitter Holding Register Empty */
+#define LSR_TEMT	0x4000	/* Transmitter Empty */
+#define LSR_FIFOE	0x8000	/* Receiver FIFO error */
+
+/* MODEM Status Register */
+
+#define MSR_DCTS	0x0100	/* Delta Clear to Send */
+#define MSR_DDSR	0x0200	/* Delta Data Set Ready */
+#define MSR_TERI	0x0400	/* Trailing Edge Ring Indicator */
+#define MSR_DDCD	0x0800	/* Delta Data Carrier Detect */
+#define MSR_CTS		0x1000	/* Clear to Send */
+#define MSR_DSR		0x2000	/* Data Set Ready */
+#define MSR_RI		0x4000	/* Ring Indicator */
+#define MSR_DCD		0x8000	/* Data Carrier Detect */
+
+/* Baud Rate Divisor */
+
+#define UART_CLK	(1843200)	/* 1.8432 MHz */
+#define UART_BAUD(x)	(UART_CLK / (16 * (x)))
+
+/* RTC register definition */
+#define RTC_SECONDS             0
+#define RTC_SECONDS_ALARM       1
+#define RTC_MINUTES             2
+#define RTC_MINUTES_ALARM       3
+#define RTC_HOURS               4
+#define RTC_HOURS_ALARM         5
+#define RTC_DAY_OF_WEEK         6
+#define RTC_DAY_OF_MONTH        7
+#define RTC_MONTH               8
+#define RTC_YEAR                9
+#define RTC_FREQ_SELECT		10
+# define RTC_UIP 0x80
+# define RTC_DIV_CTL 0x70
+/* This RTC can work under 32.768KHz clock only.  */
+# define RTC_OSC_ENABLE 0x20
+# define RTC_OSC_DISABLE 0x00
+#define RTC_CONTROL     	11
+# define RTC_SET 0x80
+# define RTC_PIE 0x40
+# define RTC_AIE 0x20
+# define RTC_UIE 0x10
+# define RTC_SQWE 0x08
+# define RTC_DM_BINARY 0x04
+# define RTC_24H 0x02
+# define RTC_DST_EN 0x01
+
+#endif  /* __ASM_SH_SMC37C93X_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/se7751/io.h linux-2.5.73-bk10/include/asm-sh/se7751/io.h
--- linux-2.5.73-bk9/include/asm-sh/se7751/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/se7751/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,80 @@
+/*
+ * include/asm-sh/io_7751se.h
+ *
+ * Modified version of io_se.h for the 7751se-specific functions.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an Hitachi SolutionEngine
+ */
+
+#ifndef _ASM_SH_IO_7751SE_H
+#define _ASM_SH_IO_7751SE_H
+
+#include <asm/io_generic.h>
+
+extern unsigned char sh7751se_inb(unsigned long port);
+extern unsigned short sh7751se_inw(unsigned long port);
+extern unsigned int sh7751se_inl(unsigned long port);
+
+extern void sh7751se_outb(unsigned char value, unsigned long port);
+extern void sh7751se_outw(unsigned short value, unsigned long port);
+extern void sh7751se_outl(unsigned int value, unsigned long port);
+
+extern unsigned char sh7751se_inb_p(unsigned long port);
+extern void sh7751se_outb_p(unsigned char value, unsigned long port);
+
+extern void sh7751se_insb(unsigned long port, void *addr, unsigned long count);
+extern void sh7751se_insw(unsigned long port, void *addr, unsigned long count);
+extern void sh7751se_insl(unsigned long port, void *addr, unsigned long count);
+extern void sh7751se_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void sh7751se_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count);
+
+extern unsigned char sh7751se_readb(unsigned long addr);
+extern unsigned short sh7751se_readw(unsigned long addr);
+extern unsigned int sh7751se_readl(unsigned long addr);
+extern void sh7751se_writeb(unsigned char b, unsigned long addr);
+extern void sh7751se_writew(unsigned short b, unsigned long addr);
+extern void sh7751se_writel(unsigned int b, unsigned long addr);
+
+extern unsigned long sh7751se_isa_port2addr(unsigned long offset);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			sh7751se_inb
+# define __inw			sh7751se_inw
+# define __inl			sh7751se_inl
+# define __outb			sh7751se_outb
+# define __outw			sh7751se_outw
+# define __outl			sh7751se_outl
+
+# define __inb_p		sh7751se_inb_p
+# define __inw_p		sh7751se_inw
+# define __inl_p		sh7751se_inl
+# define __outb_p		sh7751se_outb_p
+# define __outw_p		sh7751se_outw
+# define __outl_p		sh7751se_outl
+
+# define __insb			sh7751se_insb
+# define __insw			sh7751se_insw
+# define __insl			sh7751se_insl
+# define __outsb		sh7751se_outsb
+# define __outsw		sh7751se_outsw
+# define __outsl		sh7751se_outsl
+
+# define __readb		sh7751se_readb
+# define __readw		sh7751se_readw
+# define __readl		sh7751se_readl
+# define __writeb		sh7751se_writeb
+# define __writew		sh7751se_writew
+# define __writel		sh7751se_writel
+
+# define __isa_port2addr	sh7751se_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_7751SE_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/se7751/se7751.h linux-2.5.73-bk10/include/asm-sh/se7751/se7751.h
--- linux-2.5.73-bk9/include/asm-sh/se7751/se7751.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/se7751/se7751.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,68 @@
+#ifndef __ASM_SH_HITACHI_7751SE_H
+#define __ASM_SH_HITACHI_7751SE_H
+
+/*
+ * linux/include/asm-sh/hitachi_7751se.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine support
+
+ * Modified for 7751 Solution Engine by
+ * Ian da Silva and Jeremy Siegel, 2001.
+ */
+
+/* Box specific addresses.  */
+
+#define PA_ROM		0x00000000	/* EPROM */
+#define PA_ROM_SIZE	0x00400000	/* EPROM size 4M byte */
+#define PA_FROM		0x01000000	/* EPROM */
+#define PA_FROM_SIZE	0x00400000	/* EPROM size 4M byte */
+#define PA_EXT1		0x04000000
+#define PA_EXT1_SIZE	0x04000000
+#define PA_EXT2		0x08000000
+#define PA_EXT2_SIZE	0x04000000
+#define PA_SDRAM	0x0c000000
+#define PA_SDRAM_SIZE	0x04000000
+
+#define PA_EXT4		0x12000000
+#define PA_EXT4_SIZE	0x02000000
+#define PA_EXT5		0x14000000
+#define PA_EXT5_SIZE	0x04000000
+#define PA_PCIC		0x18000000	/* MR-SHPC-01 PCMCIA */
+
+#define PA_DIPSW0	0xb9000000	/* Dip switch 5,6 */
+#define PA_DIPSW1	0xb9000002	/* Dip switch 7,8 */
+#define PA_LED		0xba000000	/* LED */
+#define	PA_BCR		0xbb000000	/* FPGA on the MS7751SE01 */
+
+#define PA_MRSHPC	0xb83fffe0	/* MR-SHPC-01 PCMCIA controler */
+#define PA_MRSHPC_MW1	0xb8400000	/* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2	0xb8500000	/* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO	0xb8600000	/* MR-SHPC-01 I/O window base */
+#define MRSHPC_MODE     (PA_MRSHPC + 4)
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+
+#define BCR_ILCRA	(PA_BCR + 0)
+#define BCR_ILCRB	(PA_BCR + 2)
+#define BCR_ILCRC	(PA_BCR + 4)
+#define BCR_ILCRD	(PA_BCR + 6)
+#define BCR_ILCRE	(PA_BCR + 8)
+#define BCR_ILCRF	(PA_BCR + 10)
+#define BCR_ILCRG	(PA_BCR + 12)
+
+#define IRQ_79C973	13
+
+#endif  /* __ASM_SH_HITACHI_7751SE_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/semaphore.h linux-2.5.73-bk10/include/asm-sh/semaphore.h
--- linux-2.5.73-bk9/include/asm-sh/semaphore.h	2003-06-22 11:33:34.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/semaphore.h	2003-07-02 04:57:38.000000000 -0700
@@ -15,6 +15,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
+#include <linux/wait.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -23,12 +24,12 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	long __magic;
 #endif
 };
 
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 # define __SEM_DEBUG_INIT(name) \
 		, (int)&(name).__magic
 #else
@@ -59,7 +60,7 @@
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	sem->__magic = (int)&sem->__magic;
 #endif
 }
@@ -90,10 +91,11 @@
 
 static inline void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 
+	might_sleep();
 	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
 }
@@ -101,7 +103,7 @@
 static inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 
@@ -113,7 +115,7 @@
 static inline int down_trylock(struct semaphore * sem)
 {
 	int ret = 0;
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 
@@ -128,7 +130,7 @@
  */
 static inline void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 	if (atomic_inc_return(&sem->count) <= 0)
diff -urN linux-2.5.73-bk9/include/asm-sh/sh2000/io.h linux-2.5.73-bk10/include/asm-sh/sh2000/io.h
--- linux-2.5.73-bk9/include/asm-sh/sh2000/io.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/sh2000/io.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,56 @@
+/*
+ * include/asm-sh/io_sh2000.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *           2001 SUGIOKA Toshinobu (sugioka@itonet.co.jp)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for use when we don't know what machine we are on
+ */
+
+#ifndef _ASM_SH_IO_SH2000_H
+#define _ASM_SH_IO_SH2000_H
+
+#include <asm/io_generic.h>
+
+unsigned long sh2000_isa_port2addr(unsigned long offset);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			generic_inb
+# define __inw			generic_inw
+# define __inl			generic_inl
+# define __outb			generic_outb
+# define __outw			generic_outw
+# define __outl			generic_outl
+
+# define __inb_p		generic_inb_p
+# define __inw_p		generic_inw
+# define __inl_p		generic_inl
+# define __outb_p		generic_outb_p
+# define __outw_p		generic_outw
+# define __outl_p		generic_outl
+
+# define __insb			generic_insb
+# define __insw			generic_insw
+# define __insl			generic_insl
+# define __outsb		generic_outsb
+# define __outsw		generic_outsw
+# define __outsl		generic_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	sh2000_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_SH2000_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/sh2000/sh2000.h linux-2.5.73-bk10/include/asm-sh/sh2000/sh2000.h
--- linux-2.5.73-bk9/include/asm-sh/sh2000/sh2000.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/sh2000/sh2000.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,8 @@
+#ifndef __ASM_SH_SH2000_SH2000_H
+#define __ASM_SH_SH2000_SH2000_H
+
+/* arch/sh/boards/sh2000/setup.c */
+extern int setup_sh2000(void);
+
+#endif /* __ASM_SH_SH2000_SH2000_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/shmparam.h linux-2.5.73-bk10/include/asm-sh/shmparam.h
--- linux-2.5.73-bk9/include/asm-sh/shmparam.h	2003-06-22 11:32:31.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/shmparam.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,13 +1,6 @@
 #ifndef __ASM_SH_SHMPARAM_H
 #define __ASM_SH_SHMPARAM_H
 
-#if defined(__SH4__)
-/*
- * SH-4 has D-cache alias issue
- */
-#define	SHMLBA (PAGE_SIZE*4)		 /* attach addr a multiple of this */
-#else
-#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
-#endif
+#include <asm/cpu/shmparam.h>
 
 #endif /* __ASM_SH_SHMPARAM_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/sigcontext.h linux-2.5.73-bk10/include/asm-sh/sigcontext.h
--- linux-2.5.73-bk9/include/asm-sh/sigcontext.h	2003-06-22 11:33:37.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/sigcontext.h	2003-07-02 04:57:38.000000000 -0700
@@ -13,7 +13,7 @@
 	unsigned long sc_mach;
 	unsigned long sc_macl;
 
-#if defined(__SH4__)
+#if defined(CONFIG_CPU_SH4)
 	/* FPU registers */
 	unsigned long sc_fpregs[16];
 	unsigned long sc_xfpregs[16];
diff -urN linux-2.5.73-bk9/include/asm-sh/signal.h linux-2.5.73-bk10/include/asm-sh/signal.h
--- linux-2.5.73-bk9/include/asm-sh/signal.h	2003-06-22 11:32:55.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/signal.h	2003-07-02 04:57:38.000000000 -0700
@@ -4,6 +4,7 @@
 #include <linux/types.h>
 
 /* Avoid too many header ordering problems.  */
+struct pt_regs;
 struct siginfo;
 
 #define _NSIG		64
diff -urN linux-2.5.73-bk9/include/asm-sh/smp.h linux-2.5.73-bk10/include/asm-sh/smp.h
--- linux-2.5.73-bk9/include/asm-sh/smp.h	2003-06-22 11:32:57.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/smp.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,4 +1,46 @@
+/*
+ * Copyright (C) 2002 Paul Mundt
+ */
 #ifndef __ASM_SH_SMP_H
 #define __ASM_SH_SMP_H
 
+#include <linux/config.h>
+#include <linux/bitops.h>
+
+#ifdef CONFIG_SMP
+
+#include <asm/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/current.h>
+
+extern unsigned long cpu_online_map;
+
+#define cpu_online(cpu)		(cpu_online_map & (1 << (cpu)))
+#define cpu_possible(cpu)	(cpu_online(cpu))
+
+#define smp_processor_id()	(current_thread_info()->cpu)
+
+extern inline unsigned int num_online_cpus(void)
+{
+	return hweight32(cpu_online_map);
+}
+
+/* I've no idea what the real meaning of this is */
+#define PROC_CHANGE_PENALTY	20
+
+#define NO_PROC_ID	(-1)
+
+struct smp_fn_call_struct {
+	spinlock_t lock;
+	atomic_t   finished;
+	void (*fn)(void *);
+	void *data;
+};
+
+extern struct smp_fn_call_struct smp_fn_call;
+
+#define SMP_MSG_RESCHEDULE	0x0001
+
+#endif /* CONFIG_SMP */
+
 #endif /* __ASM_SH_SMP_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/spinlock.h linux-2.5.73-bk10/include/asm-sh/spinlock.h
--- linux-2.5.73-bk9/include/asm-sh/spinlock.h	2003-06-22 11:32:39.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/spinlock.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,6 +1,108 @@
+/*
+ * include/asm-sh/spinlock.h
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
 #ifndef __ASM_SH_SPINLOCK_H
 #define __ASM_SH_SPINLOCK_H
 
-#error "No SMP on SH"
+#include <asm/atomic.h>
+
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ */
+typedef struct {
+	volatile unsigned long lock;
+} spinlock_t;
+
+#define SPIN_LOCK_UNLOCKED	(spinlock_t) { 0 }
+
+#define spin_lock_init(x)	do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
+
+#define spin_is_locked(x)	((x)->lock != 0)
+#define spin_unlock_wait(x)	do { barrier(); } while (spin_is_locked(x))
+
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions.  They have a cost.
+ */
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+	__asm__ __volatile__ (
+		"1:\n\t"
+		"tas.b @%0\n\t"
+		"bf/s 1b\n\t"
+		"nop\n\t"
+		: "=r" (lock->lock)
+		: "r" (&lock->lock)
+		: "t", "memory"
+	);
+}
+
+static inline void _raw_spin_unlock(spinlock_t *lock)
+{
+#ifdef CONFIG_DEBUG_SPINLOCK
+	if (!spin_is_locked(lock))
+		BUG();
+#endif
+
+	lock->lock = 0;
+}
+
+#define _raw_spin_trylock(x) (!test_and_set_bit(0, &(x)->lock))
+
+/*
+ * Read-write spinlocks, allowing multiple readers but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts but no interrupt
+ * writers. For those circumstances we can "mix" irq-safe locks - any writer
+ * needs to get a irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct {
+	spinlock_t lock;
+	atomic_t counter;
+} rwlock_t;
+
+#define RW_LOCK_UNLOCKED	(rwlock_t) { { 0 } }
+#define rwlock_init(x)		do { *(x) = RW_LOCK_UNLOCKED; } while (0)
+#define rwlock_is_locked(x)	(*(volatile int *)(x) != 0)
+
+static inline void _raw_read_lock(rwlock_t *rw)
+{
+	_raw_spin_lock(&rw->lock);
+
+	atomic_inc(&rw->counter);
+
+	_raw_spin_unlock(&rw->lock);
+}
+
+static inline void _raw_read_unlock(rwlock_t *rw)
+{
+	_raw_spin_lock(&rw->lock);
+
+	atomic_dec(&rw->counter);
+
+	_raw_spin_unlock(&rw->lock);
+}
+
+static inline void _raw_write_lock(rwlock_t *rw)
+{
+	_raw_spin_lock(&rw->lock);
+	atomic_set(&rw->counter, -1);
+}
+
+static inline void _raw_write_unlock(rwlock_t *rw)
+{
+	atomic_set(&rw->counter, 0);
+	_raw_spin_unlock(&rw->lock);
+}
 
 #endif /* __ASM_SH_SPINLOCK_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/statfs.h linux-2.5.73-bk10/include/asm-sh/statfs.h
--- linux-2.5.73-bk9/include/asm-sh/statfs.h	2003-06-22 11:32:31.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/statfs.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,25 +1,6 @@
 #ifndef __ASM_SH_STATFS_H
 #define __ASM_SH_STATFS_H
 
-#ifndef __KERNEL_STRICT_NAMES
-
-#include <linux/types.h>
-
-typedef __kernel_fsid_t	fsid_t;
-
-#endif
-
-struct statfs {
-	long f_type;
-	long f_bsize;
-	long f_blocks;
-	long f_bfree;
-	long f_bavail;
-	long f_files;
-	long f_ffree;
-	__kernel_fsid_t f_fsid;
-	long f_namelen;
-	long f_spare[6];
-};
+#include <asm-generic/statfs.h>
 
 #endif /* __ASM_SH_STATFS_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/system.h linux-2.5.73-bk10/include/asm-sh/system.h
--- linux-2.5.73-bk9/include/asm-sh/system.h	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/system.h	2003-07-02 04:57:38.000000000 -0700
@@ -3,6 +3,7 @@
 
 /*
  * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
+ * Copyright (C) 2002 Paul Mundt
  */
 
 #include <linux/config.h>
@@ -12,62 +13,49 @@
  *	switch_to() should switch tasks to task nr n, first
  */
 
-typedef struct {
-	unsigned long seg;
-} mm_segment_t;
-
-#ifdef CONFIG_SMP
-#error no SMP SuperH
-#else
-#define prepare_to_switch()	do { } while(0)
-#define switch_to(prev,next,last) do { \
- register struct task_struct *__last; \
- register unsigned long *__ts1 __asm__ ("r1") = &prev->thread.sp; \
- register unsigned long *__ts2 __asm__ ("r2") = &prev->thread.pc; \
- register unsigned long *__ts4 __asm__ ("r4") = (unsigned long *)prev; \
- register unsigned long *__ts5 __asm__ ("r5") = (unsigned long *)next; \
- register unsigned long *__ts6 __asm__ ("r6") = &next->thread.sp; \
- register unsigned long __ts7 __asm__ ("r7") = next->thread.pc; \
- __asm__ __volatile__ (".balign 4\n\t" \
-		       "stc.l	gbr, @-r15\n\t" \
-		       "sts.l	pr, @-r15\n\t" \
-		       "mov.l	r8, @-r15\n\t" \
-		       "mov.l	r9, @-r15\n\t" \
-		       "mov.l	r10, @-r15\n\t" \
-		       "mov.l	r11, @-r15\n\t" \
-		       "mov.l	r12, @-r15\n\t" \
-		       "mov.l	r13, @-r15\n\t" \
-		       "mov.l	r14, @-r15\n\t" \
-		       "mov.l	r15, @r1	! save SP\n\t" \
+#define switch_to(prev, next, last) do {				\
+ register unsigned long __dummy;					\
+ register unsigned long *__ts1 __asm__ ("r1") = &prev->thread.sp;	\
+ register unsigned long *__ts2 __asm__ ("r2") = &prev->thread.pc;	\
+ register unsigned long *__ts4 __asm__ ("r4") = (unsigned long *)prev;	\
+ register unsigned long *__ts5 __asm__ ("r5") = (unsigned long *)next;	\
+ register unsigned long *__ts6 __asm__ ("r6") = &next->thread.sp;	\
+ register unsigned long __ts7 __asm__ ("r7") = next->thread.pc;		\
+ __asm__ __volatile__ (".balign 4\n\t" 					\
+		       "stc.l	gbr, @-r15\n\t" 			\
+		       "sts.l	pr, @-r15\n\t" 				\
+		       "mov.l	r8, @-r15\n\t" 				\
+		       "mov.l	r9, @-r15\n\t" 				\
+		       "mov.l	r10, @-r15\n\t" 			\
+		       "mov.l	r11, @-r15\n\t" 			\
+		       "mov.l	r12, @-r15\n\t" 			\
+		       "mov.l	r13, @-r15\n\t" 			\
+		       "mov.l	r14, @-r15\n\t" 			\
+		       "mov.l	r15, @r1	! save SP\n\t"		\
 		       "mov.l	@r6, r15	! change to new stack\n\t" \
-		       "mov.l	%0, @-r15	! push R0 onto new stack\n\t" \
-		       "mova	1f, %0\n\t" \
-		       "mov.l	%0, @r2	! save PC\n\t" \
-		       "mov.l	2f, %0\n\t" \
+		       "mova	1f, %0\n\t" 				\
+		       "mov.l	%0, @r2		! save PC\n\t" 		\
+		       "mov.l	2f, %0\n\t" 				\
 		       "jmp	@%0		! call __switch_to\n\t" \
-		       " lds	r7, pr	!  with return to new PC\n\t" \
-		       ".balign	4\n"	\
-		       "2:\n\t" \
-		       ".long	" "__switch_to\n" \
-		       "1:\n\t" \
-		       "mov.l	@r15+, %0	! pop R0 from new stack\n\t" \
-		       "mov.l	@r15+, r14\n\t" \
-		       "mov.l	@r15+, r13\n\t" \
-		       "mov.l	@r15+, r12\n\t" \
-		       "mov.l	@r15+, r11\n\t" \
-		       "mov.l	@r15+, r10\n\t" \
-		       "mov.l	@r15+, r9\n\t" \
-		       "mov.l	@r15+, r8\n\t" \
-		       "lds.l	@r15+, pr\n\t" \
-		       "ldc.l	@r15+, gbr\n\t" \
-		       :"=&z" (__last) \
-		       :"0" (prev), \
-			"r" (__ts1), "r" (__ts2), \
-			"r" (__ts4), "r" (__ts5), "r" (__ts6), "r" (__ts7) \
-		       :"r3", "t"); \
-  last = __last; \
+		       " lds	r7, pr		!  with return to new PC\n\t" \
+		       ".balign	4\n"					\
+		       "2:\n\t"						\
+		       ".long	__switch_to\n"				\
+		       "1:\n\t"						\
+		       "mov.l	@r15+, r14\n\t"				\
+		       "mov.l	@r15+, r13\n\t"				\
+		       "mov.l	@r15+, r12\n\t"				\
+		       "mov.l	@r15+, r11\n\t"				\
+		       "mov.l	@r15+, r10\n\t"				\
+		       "mov.l	@r15+, r9\n\t"				\
+		       "mov.l	@r15+, r8\n\t"				\
+		       "lds.l	@r15+, pr\n\t"				\
+		       "ldc.l	@r15+, gbr\n\t"				\
+		       : "=z" (__dummy)					\
+		       : "r" (__ts1), "r" (__ts2), "r" (__ts4), 	\
+			 "r" (__ts5), "r" (__ts6), "r" (__ts7) 		\
+		       : "r3", "t");					\
 } while (0)
-#endif
 
 #define nop() __asm__ __volatile__ ("nop")
 
@@ -135,6 +123,13 @@
 #define local_save_flags(x) \
 	__asm__("stc sr, %0; and #0xf0, %0" : "=&z" (x) :/**/: "memory" )
 
+#define irqs_disabled()			\
+({					\
+	unsigned long flags;		\
+	local_save_flags(flags);	\
+	(flags != 0);			\
+})
+
 static __inline__ unsigned long local_irq_save(void)
 {
 	unsigned long flags, __dummy;
@@ -221,35 +216,14 @@
 /* For spinlocks etc */
 #define local_irq_save(x)	x = local_irq_save()
 
-#ifdef CONFIG_SMP
-
-extern void __global_cli(void);
-extern void __global_sti(void);
-extern unsigned long __global_save_flags(void);
-extern void __global_restore_flags(unsigned long);
-#define cli() __global_cli()
-#define sti() __global_sti()
-#define save_flags(x) ((x)=__global_save_flags())
-#define restore_flags(x) __global_restore_flags(x)
-
-#else
-
-#define cli() local_irq_disable()
-#define sti() local_irq_enable()
-#define save_flags(x) local_save_flags(x)
-#define save_and_cli(x) x = local_irq_save()
-#define restore_flags(x) local_irq_restore(x)
-
-#endif
-
 static __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
 {
 	unsigned long flags, retval;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	retval = *m;
 	*m = val;
-	restore_flags(flags);
+	local_irq_restore(flags);
 	return retval;
 }
 
@@ -257,10 +231,10 @@
 {
 	unsigned long flags, retval;
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	retval = *m;
 	*m = val & 0xff;
-	restore_flags(flags);
+	local_irq_restore(flags);
 	return retval;
 }
 
diff -urN linux-2.5.73-bk9/include/asm-sh/thread_info.h linux-2.5.73-bk10/include/asm-sh/thread_info.h
--- linux-2.5.73-bk9/include/asm-sh/thread_info.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/thread_info.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,111 @@
+#ifndef __ASM_SH_THREAD_INFO_H
+#define __ASM_SH_THREAD_INFO_H
+
+/* SuperH version
+ * Copyright (C) 2002  Niibe Yutaka
+ *
+ * The copyright of original i386 version is:
+ *
+ *  Copyright (C) 2002  David Howells (dhowells@redhat.com)
+ *  - Incorporating suggestions made by Linus Torvalds and Dave Miller
+ */
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	__u32			flags;		/* low level flags */
+	__u32			cpu;
+	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+	struct restart_block	restart_block;
+	__u8			supervisor_stack[0];
+};
+
+#else /* !__ASSEMBLY__ */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK		0x00000000
+#define TI_EXEC_DOMAIN	0x00000004
+#define TI_FLAGS	0x00000008
+#define TI_CPU		0x0000000c
+#define TI_PRE_COUNT	0x00000010
+#define TI_RESTART_BLOCK 0x00000014
+
+#endif
+
+#define PREEMPT_ACTIVE		0x4000000
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
+#ifndef __ASSEMBLY__
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.task		= &tsk,			\
+	.exec_domain	= &default_exec_domain,	\
+	.flags		= 0,			\
+	.cpu		= 0,			\
+	.preempt_count	= 1,			\
+	.restart_block	= {			\
+		.fn = do_no_restart_syscall,	\
+	},					\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+	struct thread_info *ti;
+	__asm__("stc	r7_bank, %0" : "=r" (ti));
+	return ti;
+}
+
+/* thread information allocation */
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#else /* !__ASSEMBLY__ */
+
+/* how to get the thread information struct from ASM */
+#define GET_THREAD_INFO(reg) \
+	stc	r7_bank, reg
+
+#endif
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
+#define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_USERSPACE		31	/* true if FS sets userspace */
+
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_USEDFPU		(1<<TIF_USEDFPU)
+#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_USERSPACE		(1<<TIF_USERSPACE)
+
+#define _TIF_WORK_MASK		0x000000FE	/* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK	0x000000FF	/* work to do on any return to u-space */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_THREAD_INFO_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/tlb.h linux-2.5.73-bk10/include/asm-sh/tlb.h
--- linux-2.5.73-bk9/include/asm-sh/tlb.h	2003-06-22 11:33:06.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/tlb.h	2003-07-02 04:57:38.000000000 -0700
@@ -1 +1,18 @@
+#ifndef __ASM_SH_TLB_H
+#define __ASM_SH_TLB_H
+
+#define tlb_start_vma(tlb, vma) \
+	flush_cache_range(vma, vma->vm_start, vma->vm_end)
+
+#define tlb_end_vma(tlb, vma)	\
+	flush_tlb_range(vma, vma->vm_start, vma->vm_end)
+
+#define __tlb_remove_tlb_entry(tlb, pte, address)	do { } while (0)
+
+/*
+ * Flush whole TLBs for MM
+ */
+#define tlb_flush(tlb)				flush_tlb_mm((tlb)->mm)
+
 #include <asm-generic/tlb.h>
+#endif
diff -urN linux-2.5.73-bk9/include/asm-sh/tlbflush.h linux-2.5.73-bk10/include/asm-sh/tlbflush.h
--- linux-2.5.73-bk9/include/asm-sh/tlbflush.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/tlbflush.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,31 @@
+#ifndef __ASM_SH_TLBFLUSH_H
+#define __ASM_SH_TLBFLUSH_H
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+ */
+
+extern void flush_tlb(void);
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			    unsigned long end);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
+extern void __flush_tlb_page(unsigned long asid, unsigned long page);
+
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
+				      unsigned long start, unsigned long end)
+{ /* Nothing to do */
+}
+
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+#endif /* __ASM_SH_TLBFLUSH_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/types.h linux-2.5.73-bk10/include/asm-sh/types.h
--- linux-2.5.73-bk9/include/asm-sh/types.h	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/types.h	2003-07-02 04:57:38.000000000 -0700
@@ -51,6 +51,11 @@
 
 typedef u32 dma_addr_t;
 
+#ifdef CONFIG_LBD
+typedef u64 sector_t;
+#define HAVE_SECTOR_T
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff -urN linux-2.5.73-bk9/include/asm-sh/uaccess.h linux-2.5.73-bk10/include/asm-sh/uaccess.h
--- linux-2.5.73-bk9/include/asm-sh/uaccess.h	2003-06-22 11:32:44.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/uaccess.h	2003-07-02 04:57:38.000000000 -0700
@@ -1,8 +1,9 @@
-/* $Id: uaccess.h,v 1.13 2001/10/01 02:22:01 gniibe Exp $
+/* $Id: uaccess.h,v 1.9 2003/05/06 23:28:51 lethal Exp $
  *
  * User space memory access functions
  *
- * Copyright (C) 1999  Niibe Yutaka
+ * Copyright (C) 1999, 2002  Niibe Yutaka
+ * Copyright (C) 2003  Paul Mundt
  *
  *  Based on:
  *     MIPS implementation version 1.15 by
@@ -15,9 +16,21 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 
+/*
+ * NOTE: Macro/functions in this file depends on threads_info.h implementation.
+ * Assumes:
+ * TI_FLAGS == 8
+ * TIF_USERSPACE == 31
+ * USER_ADDR_LIMIT == 0x80000000
+ */
+
 #define VERIFY_READ    0
 #define VERIFY_WRITE   1
 
+typedef struct {
+	unsigned int is_user_space;
+} mm_segment_t;
+
 /*
  * The fs value determines whether argument validity checking should be
  * performed or not.  If get_fs() == USER_DS, checking is performed, with
@@ -27,34 +40,111 @@
  */
 
 #define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+#define segment_eq(a,b)	((a).is_user_space == (b).is_user_space)
+
+#define USER_ADDR_LIMIT	0x80000000
 
-#define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
-#define USER_DS		MAKE_MM_SEG(0x80000000)
+#define KERNEL_DS	MAKE_MM_SEG(0)
+#define USER_DS		MAKE_MM_SEG(1)
 
 #define get_ds()	(KERNEL_DS)
-#define get_fs()        (current->addr_limit)
-#define set_fs(x)       (current->addr_limit=(x))
 
-#define segment_eq(a,b)	((a).seg == (b).seg)
+#if !defined(CONFIG_MMU)
+static inline mm_segment_t get_fs(void)
+{
+	return USER_DS;
+}
 
-#define __addr_ok(addr) ((unsigned long)(addr) < (current->addr_limit.seg))
+static inline void set_fs(mm_segment_t s)
+{
+}
 
 /*
- * Uhhuh, this needs 33-bit arithmetic. We have a carry..
+ * __access_ok: Check if address with size is OK or not.
  *
- * sum := addr + size;  carry? --> flag = true;
- * if (sum >= addr_limit) flag = true;
+ * If we don't have an MMU (or if its disabled) the only thing we really have
+ * to look out for is if the address resides somewhere outside of what
+ * available RAM we have.
+ *
+ * TODO: This check could probably also stand to be restricted somewhat more..
+ * though it still does the Right Thing(tm) for the time being.
  */
-#define __range_ok(addr,size) ({					      \
-	unsigned long flag,sum; 					      \
-	__asm__("clrt; addc %3, %1; movt %0; cmp/hi %4, %1; rotcl %0"	      \
-		:"=&r" (flag), "=r" (sum) 				      \
-		:"1" (addr), "r" ((int)(size)), "r" (current->addr_limit.seg) \
-		:"t"); 							      \
-	flag; })
+static inline int __access_ok(unsigned long addr, unsigned long size)
+{
+	extern unsigned long memory_start, memory_end;
+
+	return ((addr >= memory_start) && ((addr + size) < memory_end));
+}
+#else /* CONFIG_MMU */
+static inline mm_segment_t get_fs(void)
+{
+	return MAKE_MM_SEG(test_thread_flag(TIF_USERSPACE));
+}
 
-#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
-#define __access_ok(addr,size) (__range_ok(addr,size) == 0)
+static inline void set_fs(mm_segment_t s)
+{
+	unsigned long ti, flag;
+	__asm__ __volatile__(
+		"stc	r7_bank, %0\n\t"
+		"mov.l	@(8,%0), %1\n\t"
+		"shal	%1\n\t"
+		"cmp/pl	%2\n\t"
+		"rotcr	%1\n\t"
+		"mov.l	%1, @(8,%0)"
+		: "=&r" (ti), "=&r" (flag)
+		: "r" (s.is_user_space)
+		: "t");
+/****
+	if (s.is_user_space)
+		set_thread_flag(TIF_USERSPACE);
+	else
+		clear_thread_flag(TIF_USERSPACE);
+****/
+}
+
+/*
+ * __access_ok: Check if address with size is OK or not.
+ *
+ * We do three checks:
+ * (1) is it user space? 
+ * (2) addr + size --> carry?
+ * (3) addr + size >= 0x80000000  (USER_ADDR_LIMIT)
+ *
+ * (1) (2) (3) | RESULT
+ *  0   0   0  |  ok
+ *  0   0   1  |  ok
+ *  0   1   0  |  bad
+ *  0   1   1  |  bad
+ *  1   0   0  |  ok
+ *  1   0   1  |  bad
+ *  1   1   0  |  bad
+ *  1   1   1  |  bad
+ */
+static inline int __access_ok(unsigned long addr, unsigned long size)
+{
+	unsigned long flag, tmp;
+
+	__asm__("stc	r7_bank, %0\n\t"
+		"mov.l	@(8,%0), %0\n\t"
+		"clrt\n\t"
+		"addc	%2, %1\n\t"
+		"and	%1, %0\n\t"
+		"rotcl	%0\n\t"
+		"rotcl	%0\n\t"
+		"and	#3, %0"
+		: "=&z" (flag), "=r" (tmp)
+		: "r" (addr), "1" (size)
+		: "t");
+
+	return flag == 0;
+}
+#endif /* CONFIG_MMU */
+
+static inline int access_ok(int type, const void *p, unsigned long size)
+{
+	unsigned long addr = (unsigned long)p;
+	return __access_ok(addr, size);
+}
 
 static inline int verify_area(int type, const void * addr, unsigned long size)
 {
@@ -101,20 +191,92 @@
 default: __get_user_unknown(); break; \
 } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
 
-#define __get_user_check(x,ptr,size) ({ \
-long __gu_err; \
-__typeof__(*(ptr)) __gu_val; \
-long __gu_addr; \
-__asm__("":"=r" (__gu_val)); \
-__gu_addr = (long) (ptr); \
-__asm__("":"=r" (__gu_err)); \
-if (__access_ok(__gu_addr,size)) { \
-switch (size) { \
-case 1: __get_user_asm("b"); break; \
-case 2: __get_user_asm("w"); break; \
-case 4: __get_user_asm("l"); break; \
-default: __get_user_unknown(); break; \
-} } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+#define __get_user_check(x,ptr,size)			\
+({ __typeof__(*(ptr)) __val; long __err;		\
+ switch(size) {						\
+ case 1: __err = __get_user_1(__val, ptr); break;	\
+ case 2: __err = __get_user_2(__val, ptr); break;	\
+ case 4: __err = __get_user_4(__val, ptr); break;	\
+ default: __get_user_unknown(); break;			\
+ }							\
+ (x) = __val; __err; })
+
+#define __get_user_1(x,ptr) ({			\
+long __gu_err;					\
+__typeof__(*(ptr)) __gu_val;			\
+long __gu_addr = (long) (ptr);			\
+__asm__("stc	r7_bank, %1\n\t"		\
+	"mov.l	@(8,%1), %1\n\t"		\
+	"and	%2, %1\n\t"			\
+	"cmp/pz	%1\n\t"				\
+	"bt/s	1f\n\t"				\
+	" mov	#0, %0\n\t"			\
+	"0:\n"					\
+	"mov	#-14, %0\n\t"			\
+	"bra	2f\n\t"				\
+	" mov	#0, %1\n"			\
+	"1:\n\t"				\
+	"mov.b	@%2, %1\n\t"			\
+	"extu.b	%1, %1\n"			\
+	"2:\n"					\
+	".section	__ex_table,\"a\"\n\t"	\
+	".long	1b, 0b\n\t"			\
+	".previous"				\
+	: "=&r" (__gu_err), "=&r" (__gu_val)	\
+	: "r" (__gu_addr)			\
+	: "t");					\
+x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+
+#define __get_user_2(x,ptr) ({			\
+long __gu_err;					\
+__typeof__(*(ptr)) __gu_val;			\
+long __gu_addr = (long) (ptr);			\
+__asm__("stc	r7_bank, %1\n\t"		\
+	"mov.l	@(8,%1), %1\n\t"		\
+	"and	%2, %1\n\t"			\
+	"cmp/pz	%1\n\t"				\
+	"bt/s	1f\n\t"				\
+	" mov	#0, %0\n\t"			\
+	"0:\n"					\
+	"mov	#-14, %0\n\t"			\
+	"bra	2f\n\t"				\
+	" mov	#0, %1\n"			\
+	"1:\n\t"				\
+	"mov.w	@%2, %1\n\t"			\
+	"extu.w	%1, %1\n"			\
+	"2:\n"					\
+	".section	__ex_table,\"a\"\n\t"	\
+	".long	1b, 0b\n\t"			\
+	".previous"				\
+	: "=&r" (__gu_err), "=&r" (__gu_val)	\
+	: "r" (__gu_addr)			\
+	: "t");					\
+x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+
+#define __get_user_4(x,ptr) ({			\
+long __gu_err;					\
+__typeof__(*(ptr)) __gu_val;			\
+long __gu_addr = (long) (ptr);			\
+__asm__("stc	r7_bank, %1\n\t"		\
+	"mov.l	@(8,%1), %1\n\t"		\
+	"and	%2, %1\n\t"			\
+	"cmp/pz	%1\n\t"				\
+	"bt/s	1f\n\t"				\
+	" mov	#0, %0\n\t"			\
+	"0:\n"					\
+	"mov	#-14, %0\n\t"			\
+	"bra	2f\n\t"				\
+	" mov	#0, %1\n"			\
+	"1:\n\t"				\
+	"mov.l	@%2, %1\n\t"			\
+	"2:\n"					\
+	".section	__ex_table,\"a\"\n\t"	\
+	".long	1b, 0b\n\t"			\
+	".previous"				\
+	: "=&r" (__gu_err), "=&r" (__gu_val)	\
+	: "r" (__gu_addr)			\
+	: "t");					\
+x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
 
 #define __get_user_asm(insn) \
 ({ \
@@ -244,42 +406,7 @@
 
 /* Generic arbitrary sized copy.  */
 /* Return the number of bytes NOT copied */
-/* XXX: should be such that: 4byte and the rest. */
-static __inline__ __kernel_size_t
-__copy_user(void *__to, const void *__from, __kernel_size_t __n)
-{
-	unsigned long __dummy, _f, _t;
-	__kernel_size_t res;
-
-	if ((res = __n))
-	__asm__ __volatile__(
-		"9:\n\t"
-		"mov.b	@%2+, %1\n\t"
-		"dt	%0\n"
-		"1:\n\t"
-		"mov.b	%1, @%3\n\t"
-		"bf/s	9b\n\t"
-		" add	#1, %3\n"
-		"2:\n"
-		".section .fixup,\"ax\"\n"
-		"3:\n\t"
-		"mov.l	5f, %1\n\t"
-		"jmp	@%1\n\t"
-		" add	#1, %0\n\t"
-		".balign 4\n"
-		"5:	.long 2b\n"
-		".previous\n"
-		".section __ex_table,\"a\"\n"
-		"	.balign 4\n"
-		"	.long 9b,2b\n"
-		"	.long 1b,3b\n"
-		".previous"
-		: "=r" (res), "=&z" (__dummy), "=r" (_f), "=r" (_t)
-		: "2" (__from), "3" (__to), "0" (res)
-		: "memory", "t");
-
-	return res;
-}
+extern __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
 
 #define copy_to_user(to,from,n) ({ \
 void *__copy_to = (void *) (to); \
@@ -308,39 +435,11 @@
 	__copy_user((void *)(to),		\
 		    (void *)(from), n)
 
-/* XXX: Not sure it works well..
-   should be such that: 4byte clear and the rest. */
-static __inline__ __kernel_size_t
-__clear_user(void *addr, __kernel_size_t size)
-{
-	unsigned long __a;
-
-	__asm__ __volatile__(
-		"9:\n\t"
-		"dt	%0\n"
-		"1:\n\t"
-		"mov.b	%4, @%1\n\t"
-		"bf/s	9b\n\t"
-		" add	#1, %1\n"
-		"2:\n"
-		".section .fixup,\"ax\"\n"
-		"3:\n\t"
-		"mov.l	4f, %1\n\t"
-		"jmp	@%1\n\t"
-		" nop\n"
-		".balign 4\n"
-		"4:	.long 2b\n"
-		".previous\n"
-		".section __ex_table,\"a\"\n"
-		"	.balign 4\n"
-		"	.long 1b,3b\n"
-		".previous"
-		: "=r" (size), "=r" (__a)
-		: "0" (size), "1" (addr), "r" (0)
-		: "memory", "t");
-
-	return size;
-}
+/*
+ * Clear the area and return remaining number of bytes
+ * (on failure.  Usually it's 0.)
+ */
+extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
 
 #define clear_user(addr,n) ({ \
 void * __cl_addr = (addr); \
@@ -396,8 +495,6 @@
 __sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
 } __sfu_res; })
 
-#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
-
 /*
  * Return the size of a string (including the ending 0!)
  */
@@ -436,24 +533,23 @@
 
 static __inline__ long strnlen_user(const char *s, long n)
 {
-	if (!__addr_ok(s))
+	if (!access_ok(VERIFY_READ, s, n))
 		return 0;
 	else
 		return __strnlen_user(s, n);
 }
 
+static __inline__ long strlen_user(const char *s)
+{
+	if (!access_ok(VERIFY_READ, s, 0))
+		return 0;
+	else
+		return __strnlen_user(s, ~0UL >> 1);
+}
+
 struct exception_table_entry
 {
 	unsigned long insn, fixup;
 };
 
-/* Returns 0 if exception not found and fixup.unit otherwise.  */
-extern unsigned long search_exception_table(unsigned long addr);
-
-/* Returns the new pc */
-#define fixup_exception(map_reg, fixup_unit, pc)                \
-({                                                              \
-	fixup_unit;                                             \
-})
-
 #endif /* __ASM_SH_UACCESS_H */
diff -urN linux-2.5.73-bk9/include/asm-sh/ubc.h linux-2.5.73-bk10/include/asm-sh/ubc.h
--- linux-2.5.73-bk9/include/asm-sh/ubc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/ubc.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,58 @@
+/*
+ * include/asm-sh/ubc.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_UBC_H
+#define __ASM_SH_UBC_H
+
+#include <asm/cpu/ubc.h>
+
+/* User Break Controller */
+#if defined(CONFIG_CPU_SUBTYPE_SH7709)
+#define UBC_TYPE_SH7729	(cpu_data->type == CPU_SH7729)
+#else
+#define UBC_TYPE_SH7729	0
+#endif
+
+#define BAMR_ASID		(1 << 2)
+#define BAMR_NONE		0
+#define BAMR_10			0x1
+#define BAMR_12			0x2
+#define BAMR_ALL		0x3
+#define BAMR_16			0x8
+#define BAMR_20			0x9
+
+#define BBR_INST		(1 << 4)
+#define BBR_DATA		(2 << 4)
+#define BBR_READ		(1 << 2)
+#define BBR_WRITE		(2 << 2)
+#define BBR_BYTE		0x1
+#define BBR_HALF		0x2
+#define BBR_LONG		0x3
+#define BBR_QUAD		(1 << 6)	/* SH7750 */
+#define BBR_CPU			(1 << 6)	/* SH7709A,SH7729 */
+#define BBR_DMA			(2 << 6)	/* SH7709A,SH7729 */
+
+#define BRCR_CMFA		(1 << 15)
+#define BRCR_CMFB		(1 << 14)
+#define BRCR_PCTE		(1 << 11)
+#define BRCR_PCBA		(1 << 10)	/* 1: after execution */
+#define BRCR_DBEB		(1 << 7)
+#define BRCR_PCBB		(1 << 6)
+#define BRCR_SEQ		(1 << 3)
+#define BRCR_UBDE		(1 << 0)
+
+#ifndef __ASSEMBLY__
+/* arch/sh/kernel/ubc.S */
+extern void ubc_wakeup(void);
+extern void ubc_sleep(void);
+#endif
+
+#endif /* __ASM_SH_UBC_H */
+
diff -urN linux-2.5.73-bk9/include/asm-sh/unistd.h linux-2.5.73-bk10/include/asm-sh/unistd.h
--- linux-2.5.73-bk9/include/asm-sh/unistd.h	2003-06-22 11:33:15.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-sh/unistd.h	2003-07-02 04:57:38.000000000 -0700
@@ -9,7 +9,7 @@
  * This file contains the system call numbers.
  */
 
-#define __NR_setup		  0	/* used only by init, to get system going */
+#define __NR_restart_syscall	  0
 #define __NR_exit		  1
 #define __NR_fork		  2
 #define __NR_read		  3
@@ -231,14 +231,58 @@
 #define __NR_madvise		219
 #define __NR_getdents64		220
 #define __NR_fcntl64		221
-#define __NR_gettid		222
-#define __NR_tkill		223
+/* 223 is unused */
+#define __NR_gettid		224
+#define __NR_setxattr		226
+#define __NR_lsetxattr		227
+#define __NR_fsetxattr		228
+#define __NR_getxattr		229
+#define __NR_lgetxattr		230
+#define __NR_fgetxattr		231
+#define __NR_listxattr		232
+#define __NR_llistxattr		233
+#define __NR_flistxattr		234
+#define __NR_removexattr	235
+#define __NR_lremovexattr	236
+#define __NR_fremovexattr	237
+#define __NR_tkill		238
+#define __NR_sendfile64		239
+#define __NR_futex		240
+#define __NR_sched_setaffinity	241
+#define __NR_sched_getaffinity	242
+#define __NR_set_thread_area	243
+#define __NR_get_thread_area	244
+#define __NR_io_setup		245
+#define __NR_io_destroy		246
+#define __NR_io_getevents	247
+#define __NR_io_submit		248
+#define __NR_io_cancel		249
+#define __NR_fadvise64		250
+
+#define __NR_exit_group		252
+#define __NR_lookup_dcookie	253
+#define __NR_epoll_create	254
+#define __NR_epoll_ctl		255
+#define __NR_epoll_wait		256
+#define __NR_remap_file_pages	257
+#define __NR_set_tid_address	258
+#define __NR_timer_create	259
+#define __NR_timer_settime	(__NR_timer_create+1)
+#define __NR_timer_gettime	(__NR_timer_create+2)
+#define __NR_timer_getoverrun	(__NR_timer_create+3)
+#define __NR_timer_delete	(__NR_timer_create+4)
+#define __NR_clock_settime	(__NR_timer_create+5)
+#define __NR_clock_gettime	(__NR_timer_create+6)
+#define __NR_clock_getres	(__NR_timer_create+7)
+#define __NR_clock_nanosleep	(__NR_timer_create+8)
 
-/* user-visible error numbers are in the range -1 - -125: see <asm-sh/errno.h> */
+#define NR_syscalls 268
+
+/* user-visible error numbers are in the range -1 - -124: see <asm-sh/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
-	if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+	if ((unsigned long)(res) >= (unsigned long)(-124)) { \
 	/* Avoid using "res" which is declared to be in register r0; \
 	   errno might expand to a function call and clobber it.  */ \
 		int __err = -(res); \
@@ -332,6 +376,24 @@
 __syscall_return(type,__sc0); \
 }
 
+#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
+{ \
+register long __sc3 __asm__ ("r3") = __NR_##name; \
+register long __sc4 __asm__ ("r4") = (long) arg1; \
+register long __sc5 __asm__ ("r5") = (long) arg2; \
+register long __sc6 __asm__ ("r6") = (long) arg3; \
+register long __sc7 __asm__ ("r7") = (long) arg4; \
+register long __sc0 __asm__ ("r0") = (long) arg5; \
+register long __sc1 __asm__ ("r1") = (long) arg6; \
+__asm__ __volatile__ ("trapa	#0x15" \
+	: "=z" (__sc0) \
+	: "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7),  \
+	  "r" (__sc3), "r" (__sc1) \
+	: "memory" ); \
+__syscall_return(type,__sc0); \
+}
+
 #ifdef __KERNEL_SYSCALLS__
 
 /*
@@ -347,6 +409,8 @@
  * some others too.
  */
 #define __NR__exit __NR_exit
+static __inline__ _syscall0(int,pause)
+static __inline__ _syscall0(int,sync)
 static __inline__ _syscall0(pid_t,setsid)
 static __inline__ _syscall3(int,write,int,fd,const char *,buf,off_t,count)
 static __inline__ _syscall3(int,read,int,fd,char *,buf,off_t,count)
@@ -357,7 +421,12 @@
 static __inline__ _syscall1(int,close,int,fd)
 static __inline__ _syscall1(int,_exit,int,exitcode)
 static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+static __inline__ _syscall1(int,delete_module,const char *,name)
 
+static __inline__ pid_t wait(int * wait_stat)
+{
+	return waitpid(-1,wait_stat,0);
+}
 #endif
 
 /*
diff -urN linux-2.5.73-bk9/include/asm-sh/watchdog.h linux-2.5.73-bk10/include/asm-sh/watchdog.h
--- linux-2.5.73-bk9/include/asm-sh/watchdog.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.73-bk10/include/asm-sh/watchdog.h	2003-07-02 04:57:38.000000000 -0700
@@ -0,0 +1,110 @@
+/*
+ * include/asm-sh/watchdog.h
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * 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.
+ */
+#ifndef __ASM_SH_WATCHDOG_H
+#define __ASM_SH_WATCHDOG_H
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <asm/cpu/watchdog.h>
+#include <asm/io.h>
+
+/* 
+ * See asm/cpu-sh2/watchdog.h for explanation of this stupidity..
+ */
+#ifndef WTCNT_R
+#  define WTCNT_R	WTCNT
+#endif
+
+#ifndef WTCSR_R
+#  define WTCSR_R	WTCSR
+#endif
+
+#define WTCNT_HIGH	0x5a
+#define WTCSR_HIGH	0xa5
+
+#define WTCSR_CKS2	0x04
+#define WTCSR_CKS1	0x02
+#define WTCSR_CKS0	0x01
+
+/*
+ * CKS0-2 supports a number of clock division ratios. At the time the watchdog
+ * is enabled, it defaults to a 41 usec overflow period .. we overload this to
+ * something a little more reasonable, and really can't deal with anything
+ * lower than WTCSR_CKS_1024, else we drop back into the usec range.
+ *
+ * Clock Division Ratio         Overflow Period
+ * --------------------------------------------
+ *     1/32 (initial value)       41 usecs
+ *     1/64                       82 usecs
+ *     1/128                     164 usecs
+ *     1/256                     328 usecs
+ *     1/512                     656 usecs
+ *     1/1024                   1.31 msecs
+ *     1/2048                   2.62 msecs
+ *     1/4096                   5.25 msecs
+ */
+#define WTCSR_CKS_32	0x00
+#define WTCSR_CKS_64	0x01
+#define WTCSR_CKS_128	0x02
+#define WTCSR_CKS_256	0x03
+#define WTCSR_CKS_512	0x04
+#define WTCSR_CKS_1024	0x05
+#define WTCSR_CKS_2048	0x06
+#define WTCSR_CKS_4096	0x07
+
+/**
+ * 	sh_wdt_read_cnt - Read from Counter
+ *
+ * 	Reads back the WTCNT value.
+ */
+static inline __u8 sh_wdt_read_cnt(void)
+{
+	return ctrl_inb(WTCNT_R);
+}
+
+/**
+ *	sh_wdt_write_cnt - Write to Counter
+ *
+ *	@val: Value to write
+ *
+ *	Writes the given value @val to the lower byte of the timer counter.
+ *	The upper byte is set manually on each write.
+ */
+static inline void sh_wdt_write_cnt(__u8 val)
+{
+	ctrl_outw((WTCNT_HIGH << 8) | (__u16)val, WTCNT);
+}
+
+/**
+ * 	sh_wdt_read_csr - Read from Control/Status Register
+ *
+ *	Reads back the WTCSR value.
+ */
+static inline __u8 sh_wdt_read_csr(void)
+{
+	return ctrl_inb(WTCSR_R);
+}
+
+/**
+ * 	sh_wdt_write_csr - Write to Control/Status Register
+ *
+ * 	@val: Value to write
+ *
+ * 	Writes the given value @val to the lower byte of the control/status
+ * 	register. The upper byte is set manually on each write.
+ */
+static inline void sh_wdt_write_csr(__u8 val)
+{
+	ctrl_outw((WTCSR_HIGH << 8) | (__u16)val, WTCSR);
+}
+
+#endif /* __ASM_SH_WATCHDOG_H */
+
diff -urN linux-2.5.73-bk9/include/asm-x86_64/apic.h linux-2.5.73-bk10/include/asm-x86_64/apic.h
--- linux-2.5.73-bk9/include/asm-x86_64/apic.h	2003-06-22 11:33:15.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-x86_64/apic.h	2003-07-02 04:57:39.000000000 -0700
@@ -77,6 +77,8 @@
 extern void setup_apic_nmi_watchdog (void);
 extern void disable_lapic_nmi_watchdog(void);
 extern void enable_lapic_nmi_watchdog(void);
+extern void disable_timer_nmi_watchdog(void);
+extern void enable_timer_nmi_watchdog(void);
 extern inline void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
 extern int APIC_init_uniprocessor (void);
 extern void disable_APIC_timer(void);
diff -urN linux-2.5.73-bk9/include/asm-x86_64/io_apic.h linux-2.5.73-bk10/include/asm-x86_64/io_apic.h
--- linux-2.5.73-bk9/include/asm-x86_64/io_apic.h	2003-06-22 11:32:33.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-x86_64/io_apic.h	2003-07-02 04:57:39.000000000 -0700
@@ -22,25 +22,44 @@
 /*
  * The structure of the IO-APIC:
  */
-struct IO_APIC_reg_00 {
-	__u32	__reserved_2	: 24,
-		ID		:  4,
-		__reserved_1	:  4;
-} __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,
+union IO_APIC_reg_01 {
+	u32	raw;
+	struct {
+		u32	version		:  8,
 		__reserved_2	:  7,
 		PRQ		:  1,
 		entries		:  8,
 		__reserved_1	:  8;
-} __attribute__ ((packed));
+	} __attribute__ ((packed)) bits;
+};
 
-struct IO_APIC_reg_02 {
-	__u32	__reserved_2	: 24,
+union IO_APIC_reg_02 {
+	u32	raw;
+	struct {
+		u32	__reserved_2	: 24,
 		arbitration	:  4,
 		__reserved_1	:  4;
-} __attribute__ ((packed));
+	} __attribute__ ((packed)) bits;
+};
+
+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-bk9/include/asm-x86_64/nmi.h linux-2.5.73-bk10/include/asm-x86_64/nmi.h
--- linux-2.5.73-bk9/include/asm-x86_64/nmi.h	2003-06-22 11:32:33.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-x86_64/nmi.h	2003-07-02 04:57:39.000000000 -0700
@@ -46,4 +46,6 @@
 
 #endif /* CONFIG_PM */
  
+extern void default_do_nmi(struct pt_regs *);
+ 
 #endif /* ASM_NMI_H */
diff -urN linux-2.5.73-bk9/include/asm-x86_64/pci.h linux-2.5.73-bk10/include/asm-x86_64/pci.h
--- linux-2.5.73-bk9/include/asm-x86_64/pci.h	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-x86_64/pci.h	2003-07-02 04:57:39.000000000 -0700
@@ -261,14 +261,6 @@
 	flush_write_buffers();
 }
 
-/* These macros should be used after a pci_map_sg call has been done
- * to get bus addresses of each of the SG entries and their lengths.
- * You should only work with the number of sg entries pci_map_sg
- * returns.
- */
-#define sg_dma_address(sg)	((sg)->dma_address)
-#define sg_dma_len(sg)		((sg)->length)
-
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 			       enum pci_mmap_state mmap_state, int write_combine);
diff -urN linux-2.5.73-bk9/include/asm-x86_64/ptrace.h linux-2.5.73-bk10/include/asm-x86_64/ptrace.h
--- linux-2.5.73-bk9/include/asm-x86_64/ptrace.h	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-x86_64/ptrace.h	2003-07-02 04:57:39.000000000 -0700
@@ -34,10 +34,6 @@
 
 #define PTRACE_OLDSETOPTIONS         21
 
-/* Dummy values for ptrace */ 
-#define FS 1000 
-#define GS 1008
-
 #ifndef __ASSEMBLY__ 
 
 struct pt_regs {
diff -urN linux-2.5.73-bk9/include/asm-x86_64/scatterlist.h linux-2.5.73-bk10/include/asm-x86_64/scatterlist.h
--- linux-2.5.73-bk9/include/asm-x86_64/scatterlist.h	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk10/include/asm-x86_64/scatterlist.h	2003-07-02 04:57:39.000000000 -0700
@@ -10,4 +10,12 @@
 
 #define ISA_DMA_THRESHOLD (0x00ffffff)
 
+/* These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns.
+ */
+#define sg_dma_address(sg)     ((sg)->dma_address)
+#define sg_dma_len(sg)         ((sg)->length)
+
 #endif 
diff -urN linux-2.5.73-bk9/include/linux/cdrom.h linux-2.5.73-bk10/include/linux/cdrom.h
--- linux-2.5.73-bk9/include/linux/cdrom.h	2003-06-22 11:32:30.000000000 -0700
+++ linux-2.5.73-bk10/include/linux/cdrom.h	2003-07-02 04:57:39.000000000 -0700
@@ -387,6 +387,7 @@
 #define CDC_DVD			0x8000	/* drive is a DVD */
 #define CDC_DVD_R		0x10000	/* drive can write DVD-R */
 #define CDC_DVD_RAM		0x20000	/* drive can write DVD-RAM */
+#define CDC_MO_DRIVE		0x40000 /* drive is an MO device */
 
 /* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
 #define CDS_NO_INFO		0	/* if not implemented */
diff -urN linux-2.5.73-bk9/include/linux/module.h linux-2.5.73-bk10/include/linux/module.h
--- linux-2.5.73-bk9/include/linux/module.h	2003-06-22 11:33:07.000000000 -0700
+++ linux-2.5.73-bk10/include/linux/module.h	2003-07-02 04:57:39.000000000 -0700
@@ -217,6 +217,9 @@
 	/* Here are the sizes of the init and core sections */
 	unsigned long init_size, core_size;
 
+	/* The size of the executable code in each section.  */
+	unsigned long init_text_size, core_text_size;
+
 	/* Arch-specific module values */
 	struct mod_arch_specific arch;
 
diff -urN linux-2.5.73-bk9/include/linux/usb.h linux-2.5.73-bk10/include/linux/usb.h
--- linux-2.5.73-bk9/include/linux/usb.h	2003-06-22 11:32:43.000000000 -0700
+++ linux-2.5.73-bk10/include/linux/usb.h	2003-07-02 04:57:40.000000000 -0700
@@ -207,8 +207,10 @@
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the bus */
 	struct dentry *usbdevfs_dentry;	/* usbdevfs dentry entry for the bus */
 
-	atomic_t refcnt;
+	struct class_device class_dev;	/* class device for this bus */
+	void (*release)(struct usb_bus *bus);	/* function to destroy this bus's memory */
 };
+#define	to_usb_bus(d) container_of(d, struct usb_bus, class_dev)
 
 
 /* -------------------------------------------------------------------------- */
diff -urN linux-2.5.73-bk9/include/net/addrconf.h linux-2.5.73-bk10/include/net/addrconf.h
--- linux-2.5.73-bk9/include/net/addrconf.h	2003-06-22 11:33:07.000000000 -0700
+++ linux-2.5.73-bk10/include/net/addrconf.h	2003-07-02 04:57:40.000000000 -0700
@@ -68,6 +68,8 @@
 					       struct in6_addr *saddr,
 					       int onlink);
 extern int			ipv6_get_lladdr(struct net_device *dev, struct in6_addr *);
+extern int			ipv6_rcv_saddr_equal(const struct sock *sk, 
+						      const struct sock *sk2);
 extern void			addrconf_join_solict(struct net_device *dev,
 					struct in6_addr *addr);
 extern void			addrconf_leave_solict(struct net_device *dev,
diff -urN linux-2.5.73-bk9/include/net/ip.h linux-2.5.73-bk10/include/net/ip.h
--- linux-2.5.73-bk9/include/net/ip.h	2003-06-22 11:32:58.000000000 -0700
+++ linux-2.5.73-bk10/include/net/ip.h	2003-07-02 04:57:40.000000000 -0700
@@ -79,8 +79,7 @@
 
 extern void		ip_mc_dropsocket(struct sock *);
 extern void		ip_mc_dropdevice(struct net_device *dev);
-extern int		ip_mc_procinfo(char *, char **, off_t, int);
-extern int		ip_mcf_procinfo(char *, char **, off_t, int);
+extern int		igmp_mc_proc_init(void);
 
 /*
  *	Functions provided by ip.c
diff -urN linux-2.5.73-bk9/ipc/util.c linux-2.5.73-bk10/ipc/util.c
--- linux-2.5.73-bk9/ipc/util.c	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk10/ipc/util.c	2003-07-02 04:57:40.000000000 -0700
@@ -508,7 +508,7 @@
 	return 0;
 }
 
-#ifndef __ia64__
+#if !defined(__ia64__) && !defined(__x86_64__)
 
 /**
  *	ipc_parse_version	-	IPC call version
diff -urN linux-2.5.73-bk9/ipc/util.h linux-2.5.73-bk10/ipc/util.h
--- linux-2.5.73-bk9/ipc/util.h	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk10/ipc/util.h	2003-07-02 04:57:40.000000000 -0700
@@ -56,7 +56,7 @@
 void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
 void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
 
-#ifdef __ia64__
+#if defined(__ia64__) || defined(__x86_64__)
   /* On IA-64, we always use the "64-bit version" of the IPC structures.  */ 
 # define ipc_parse_version(cmd)	IPC_64
 #else
diff -urN linux-2.5.73-bk9/kernel/kallsyms.c linux-2.5.73-bk10/kernel/kallsyms.c
--- linux-2.5.73-bk9/kernel/kallsyms.c	2003-06-22 11:33:33.000000000 -0700
+++ linux-2.5.73-bk10/kernel/kallsyms.c	2003-07-02 04:57:40.000000000 -0700
@@ -157,7 +157,7 @@
 	unsigned stemlen;
 
 	/* First char of each symbol name indicates prefix length
-	   shared with previous name (stem compresion). */
+	   shared with previous name (stem compression). */
 	stemlen = kallsyms_names[iter->nameoff++];
 
 	strlcpy(iter->name+stemlen, kallsyms_names+iter->nameoff, 128-stemlen);
diff -urN linux-2.5.73-bk9/kernel/module.c linux-2.5.73-bk10/kernel/module.c
--- linux-2.5.73-bk9/kernel/module.c	2003-06-22 11:33:02.000000000 -0700
+++ linux-2.5.73-bk10/kernel/module.c	2003-07-02 04:57:41.000000000 -0700
@@ -1176,6 +1176,9 @@
 			    const char *secstrings)
 {
 	static unsigned long const masks[][2] = {
+		/* NOTE: all executable code must be the first section
+		 * in this array; otherwise modify the text_size
+		 * finder in the two loops below */
 		{ SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL },
 		{ SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL },
 		{ SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL },
@@ -1199,6 +1202,8 @@
 			s->sh_entsize = get_offset(&mod->core_size, s);
 			DEBUGP("\t%s\n", secstrings + s->sh_name);
 		}
+		if (m == 0)
+			mod->core_text_size = mod->core_size;
 	}
 
 	DEBUGP("Init section allocation order:\n");
@@ -1215,6 +1220,8 @@
 					 | INIT_OFFSET_MASK);
 			DEBUGP("\t%s\n", secstrings + s->sh_name);
 		}
+		if (m == 0)
+			mod->init_text_size = mod->init_size;
 	}
 }
 
@@ -1726,6 +1733,7 @@
 	module_free(mod, mod->module_init);
 	mod->module_init = NULL;
 	mod->init_size = 0;
+	mod->init_text_size = 0;
 	up(&module_mutex);
 
 	return 0;
@@ -1747,9 +1755,9 @@
 
 	/* At worse, next value is at end of module */
 	if (within(addr, mod->module_init, mod->init_size))
-		nextval = (unsigned long)mod->module_init + mod->init_size;
+		nextval = (unsigned long)mod->module_init+mod->init_text_size;
 	else 
-		nextval = (unsigned long)mod->module_core + mod->core_size;
+		nextval = (unsigned long)mod->module_core+mod->core_text_size;
 
 	/* Scan for closest preceeding symbol, and next symbol. (ELF
            starts real symbols at 1). */
@@ -1757,11 +1765,15 @@
 		if (mod->symtab[i].st_shndx == SHN_UNDEF)
 			continue;
 
+		/* We ignore unnamed symbols: they're uninformative
+		 * and inserted at a whim. */
 		if (mod->symtab[i].st_value <= addr
-		    && mod->symtab[i].st_value > mod->symtab[best].st_value)
+		    && mod->symtab[i].st_value > mod->symtab[best].st_value
+		    && *(mod->strtab + mod->symtab[i].st_name) != '\0' )
 			best = i;
 		if (mod->symtab[i].st_value > addr
-		    && mod->symtab[i].st_value < nextval)
+		    && mod->symtab[i].st_value < nextval
+		    && *(mod->strtab + mod->symtab[i].st_name) != '\0')
 			nextval = mod->symtab[i].st_value;
 	}
 
@@ -1910,8 +1922,8 @@
 	struct module *mod;
 
 	list_for_each_entry(mod, &modules, list)
-		if (within(addr, mod->module_init, mod->init_size)
-		    || within(addr, mod->module_core, mod->core_size))
+		if (within(addr, mod->module_init, mod->init_text_size)
+		    || within(addr, mod->module_core, mod->core_text_size))
 			return mod;
 	return NULL;
 }
diff -urN linux-2.5.73-bk9/kernel/sched.c linux-2.5.73-bk10/kernel/sched.c
--- linux-2.5.73-bk9/kernel/sched.c	2003-07-02 04:57:17.000000000 -0700
+++ linux-2.5.73-bk10/kernel/sched.c	2003-07-02 04:57:41.000000000 -0700
@@ -33,6 +33,7 @@
 #include <linux/timer.h>
 #include <linux/rcupdate.h>
 #include <linux/cpu.h>
+#include <linux/percpu.h>
 
 #ifdef CONFIG_NUMA
 #define cpu_to_node_mask(cpu) node_to_cpumask(cpu_to_node(cpu))
@@ -170,12 +171,12 @@
 	struct list_head migration_queue;
 
 	atomic_t nr_iowait;
-} ____cacheline_aligned;
+};
 
-static struct runqueue runqueues[NR_CPUS] __cacheline_aligned;
+static DEFINE_PER_CPU(struct runqueue, runqueues);
 
-#define cpu_rq(cpu)		(runqueues + (cpu))
-#define this_rq()		cpu_rq(smp_processor_id())
+#define cpu_rq(cpu)		(&per_cpu(runqueues, (cpu)))
+#define this_rq()		(&__get_cpu_var(runqueues))
 #define task_rq(p)		cpu_rq(task_cpu(p))
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 #define rt_task(p)		((p)->prio < MAX_RT_PRIO)
diff -urN linux-2.5.73-bk9/net/bridge/br_fdb.c linux-2.5.73-bk10/net/bridge/br_fdb.c
--- linux-2.5.73-bk9/net/bridge/br_fdb.c	2003-06-22 11:32:32.000000000 -0700
+++ linux-2.5.73-bk10/net/bridge/br_fdb.c	2003-07-02 04:57:41.000000000 -0700
@@ -251,8 +251,21 @@
 	write_lock_bh(&br->hash_lock);
 	hlist_for_each(h, &br->hash[hash]) {
 		fdb = hlist_entry(h, struct net_bridge_fdb_entry, hlist);
-		if (!fdb->is_local &&
-		    !memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
+		if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
+			/* attempt to update an entry for a local interface */
+			if (unlikely(fdb->is_local)) {
+				if (is_local) 
+					printk(KERN_INFO "%s: attempt to add"
+					       " interface with same source address.\n",
+					       source->dev->name);
+				else if (net_ratelimit()) 
+					printk(KERN_WARNING "%s: received packet with "
+					       " own address as source address\n",
+					       source->dev->name);
+				goto out;
+			}
+
+
 			if (likely(!fdb->is_static || is_local)) {
 				/* move to end of age list */
 				list_del(&fdb->age_list);
diff -urN linux-2.5.73-bk9/net/bridge/br_if.c linux-2.5.73-bk10/net/bridge/br_if.c
--- linux-2.5.73-bk9/net/bridge/br_if.c	2003-06-22 11:33:34.000000000 -0700
+++ linux-2.5.73-bk10/net/bridge/br_if.c	2003-07-02 04:57:41.000000000 -0700
@@ -95,7 +95,7 @@
 	br->bridge_id.prio[1] = 0x00;
 	memset(br->bridge_id.addr, 0, ETH_ALEN);
 
-	br->stp_enabled = 1;
+	br->stp_enabled = 0;
 	br->designated_root = br->bridge_id;
 	br->root_path_cost = 0;
 	br->root_port = 0;
diff -urN linux-2.5.73-bk9/net/bridge/br_input.c linux-2.5.73-bk10/net/bridge/br_input.c
--- linux-2.5.73-bk9/net/bridge/br_input.c	2003-06-22 11:32:38.000000000 -0700
+++ linux-2.5.73-bk10/net/bridge/br_input.c	2003-07-02 04:57:41.000000000 -0700
@@ -129,12 +129,15 @@
 	if (p->br->stp_enabled &&
 	    !memcmp(dest, bridge_ula, 5) &&
 	    !(dest[5] & 0xF0)) {
-		if (!dest[5]) 
-			br_stp_handle_bpdu(skb);
-		goto err;
+		if (!dest[5]) {
+			NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, 
+				NULL, br_stp_handle_bpdu);
+			rcu_read_unlock();
+			return 0;
+		}
 	}
 
-	if (p->state == BR_STATE_FORWARDING) {
+	else if (p->state == BR_STATE_FORWARDING) {
 		if (br_should_route_hook && br_should_route_hook(&skb)) {
 			rcu_read_unlock();
 			return -1;
diff -urN linux-2.5.73-bk9/net/bridge/br_private.h linux-2.5.73-bk10/net/bridge/br_private.h
--- linux-2.5.73-bk9/net/bridge/br_private.h	2003-06-22 11:32:37.000000000 -0700
+++ linux-2.5.73-bk10/net/bridge/br_private.h	2003-07-02 04:57:41.000000000 -0700
@@ -206,7 +206,7 @@
 			  int path_cost);
 
 /* br_stp_bpdu.c */
-extern void br_stp_handle_bpdu(struct sk_buff *skb);
+extern int br_stp_handle_bpdu(struct sk_buff *skb);
 
 /* br_stp_timer.c */
 extern void br_stp_timer_init(struct net_bridge *br);
diff -urN linux-2.5.73-bk9/net/bridge/br_stp_bpdu.c linux-2.5.73-bk10/net/bridge/br_stp_bpdu.c
--- linux-2.5.73-bk9/net/bridge/br_stp_bpdu.c	2003-06-22 11:33:08.000000000 -0700
+++ linux-2.5.73-bk10/net/bridge/br_stp_bpdu.c	2003-07-02 04:57:41.000000000 -0700
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/if_ether.h>
 #include <linux/if_bridge.h>
+#include <linux/netfilter_bridge.h>
 #include "br_private.h"
 #include "br_private_stp.h"
 
@@ -53,7 +54,8 @@
 	memcpy(skb->nh.raw, data, length);
 	memset(skb->nh.raw + length, 0xa5, size - length - 2*ETH_ALEN - 2);
 
-	dev_queue_xmit(skb);
+	NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
+		dev_queue_xmit);
 }
 
 static __inline__ void br_set_ticks(unsigned char *dest, int jiff)
@@ -130,67 +132,75 @@
 	br_send_bpdu(p, buf, 7);
 }
 
-static unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
+static const unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
 
 /* NO locks */
-void br_stp_handle_bpdu(struct sk_buff *skb)
+int br_stp_handle_bpdu(struct sk_buff *skb)
 {
+	struct net_bridge_port *p = skb->dev->br_port;
+	struct net_bridge *br = p->br;
 	unsigned char *buf;
-	struct net_bridge_port *p;
-	struct net_bridge *br;
 
-	buf = skb->mac.raw + 14;
-	p = skb->dev->br_port;
-	br = p->br;
+	/* need at least the 802 and STP headers */
+	if (!pskb_may_pull(skb, sizeof(header)+1) ||
+	    memcmp(skb->data, header, sizeof(header)))
+		goto err;
+
+	buf = skb_pull(skb, sizeof(header));
 
 	spin_lock_bh(&br->lock);
 	if (p->state == BR_STATE_DISABLED 
 	    || !(br->dev->flags & IFF_UP)
-	    || !br->stp_enabled 
-	    || memcmp(buf, header, 6)) 
+	    || !br->stp_enabled)
 		goto out;
 
-	if (buf[6] == BPDU_TYPE_CONFIG) {
+	if (buf[0] == BPDU_TYPE_CONFIG) {
 		struct br_config_bpdu bpdu;
 
-		bpdu.topology_change = (buf[7] & 0x01) ? 1 : 0;
-		bpdu.topology_change_ack = (buf[7] & 0x80) ? 1 : 0;
-		bpdu.root.prio[0] = buf[8];
-		bpdu.root.prio[1] = buf[9];
-		bpdu.root.addr[0] = buf[10];
-		bpdu.root.addr[1] = buf[11];
-		bpdu.root.addr[2] = buf[12];
-		bpdu.root.addr[3] = buf[13];
-		bpdu.root.addr[4] = buf[14];
-		bpdu.root.addr[5] = buf[15];
+		if (!pskb_may_pull(skb, 32))
+		    goto out;
+
+		buf = skb->data;
+		bpdu.topology_change = (buf[1] & 0x01) ? 1 : 0;
+		bpdu.topology_change_ack = (buf[1] & 0x80) ? 1 : 0;
+
+		bpdu.root.prio[0] = buf[2];
+		bpdu.root.prio[1] = buf[3];
+		bpdu.root.addr[0] = buf[4];
+		bpdu.root.addr[1] = buf[5];
+		bpdu.root.addr[2] = buf[6];
+		bpdu.root.addr[3] = buf[7];
+		bpdu.root.addr[4] = buf[8];
+		bpdu.root.addr[5] = buf[9];
 		bpdu.root_path_cost =
-			(buf[16] << 24) |
-			(buf[17] << 16) |
-			(buf[18] << 8) |
-			buf[19];
-		bpdu.bridge_id.prio[0] = buf[20];
-		bpdu.bridge_id.prio[1] = buf[21];
-		bpdu.bridge_id.addr[0] = buf[22];
-		bpdu.bridge_id.addr[1] = buf[23];
-		bpdu.bridge_id.addr[2] = buf[24];
-		bpdu.bridge_id.addr[3] = buf[25];
-		bpdu.bridge_id.addr[4] = buf[26];
-		bpdu.bridge_id.addr[5] = buf[27];
-		bpdu.port_id = (buf[28] << 8) | buf[29];
-
-		bpdu.message_age = br_get_ticks(buf+30);
-		bpdu.max_age = br_get_ticks(buf+32);
-		bpdu.hello_time = br_get_ticks(buf+34);
-		bpdu.forward_delay = br_get_ticks(buf+36);
+			(buf[10] << 24) |
+			(buf[11] << 16) |
+			(buf[12] << 8) |
+			buf[13];
+		bpdu.bridge_id.prio[0] = buf[14];
+		bpdu.bridge_id.prio[1] = buf[15];
+		bpdu.bridge_id.addr[0] = buf[16];
+		bpdu.bridge_id.addr[1] = buf[17];
+		bpdu.bridge_id.addr[2] = buf[18];
+		bpdu.bridge_id.addr[3] = buf[19];
+		bpdu.bridge_id.addr[4] = buf[20];
+		bpdu.bridge_id.addr[5] = buf[21];
+		bpdu.port_id = (buf[22] << 8) | buf[23];
+
+		bpdu.message_age = br_get_ticks(buf+24);
+		bpdu.max_age = br_get_ticks(buf+26);
+		bpdu.hello_time = br_get_ticks(buf+28);
+		bpdu.forward_delay = br_get_ticks(buf+30);
 
 		br_received_config_bpdu(p, &bpdu);
-		goto out;
 	}
 
-	if (buf[6] == BPDU_TYPE_TCN) {
+	else if (buf[0] == BPDU_TYPE_TCN) {
 		br_received_tcn_bpdu(p);
-		goto out;
 	}
  out:
 	spin_unlock_bh(&br->lock);
+ err:
+	kfree(skb);
+	return 0;
 }
diff -urN linux-2.5.73-bk9/net/ipv4/igmp.c linux-2.5.73-bk10/net/ipv4/igmp.c
--- linux-2.5.73-bk9/net/ipv4/igmp.c	2003-07-02 04:57:17.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv4/igmp.c	2003-07-02 04:57:42.000000000 -0700
@@ -99,7 +99,10 @@
 #ifdef CONFIG_IP_MROUTE
 #include <linux/mroute.h>
 #endif
-
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#endif
 
 #define IP_MAX_MEMBERSHIPS 20
 
@@ -2090,127 +2093,343 @@
 	return rv;
 }
 
-
-int ip_mc_procinfo(char *buffer, char **start, off_t offset, int length)
-{
-	off_t pos=0, begin=0;
-	struct ip_mc_list *im;
-	int len=0;
+#if defined(CONFIG_PROC_FS)
+struct igmp_mc_iter_state {
 	struct net_device *dev;
+	struct in_device *in_dev;
+};
 
-	len=sprintf(buffer,"Idx\tDevice    : Count Querier\tGroup    Users Timer\tReporter\n");  
+#define	igmp_mc_seq_private(seq)	((struct igmp_mc_iter_state *)&seq->private)
 
-	read_lock(&dev_base_lock);
-	for(dev = dev_base; dev; dev = dev->next) {
-		struct in_device *in_dev = in_dev_get(dev);
-		char   *querier = "NONE";
+static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
+{
+	struct ip_mc_list *im = NULL;
+	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
 
-		if (in_dev == NULL)
+	for (state->dev = dev_base, state->in_dev = NULL;
+	     state->dev; 
+	     state->dev = state->dev->next) {
+		struct in_device *in_dev;
+		in_dev = in_dev_get(state->dev);
+		if (!in_dev)
 			continue;
-
-#ifdef CONFIG_IP_MULTICAST
-		querier = IGMP_V1_SEEN(in_dev) ? "V1" : "V2";
-#endif
-
-		len+=sprintf(buffer+len,"%d\t%-10s: %5d %7s\n",
-			     dev->ifindex, dev->name, dev->mc_count, querier);
-
 		read_lock(&in_dev->lock);
-		for (im = in_dev->mc_list; im; im = im->next) {
-			len+=sprintf(buffer+len,
-				     "\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
-				     im->multiaddr, im->users,
-				     im->tm_running, im->timer.expires-jiffies, im->reporter);
-
-			pos=begin+len;
-			if(pos<offset)
-			{
-				len=0;
-				begin=pos;
-			}
-			if(pos>offset+length) {
-				read_unlock(&in_dev->lock);
-				in_dev_put(in_dev);
-				goto done;
-			}
+		im = in_dev->mc_list;
+		if (im) {
+			state->in_dev = in_dev;
+			break;
 		}
 		read_unlock(&in_dev->lock);
-		in_dev_put(in_dev);
 	}
-done:
+	return im;
+}
+
+static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_list *im)
+{
+	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
+	im = im->next;
+	while (!im) {
+		if (likely(state->in_dev != NULL)) {
+			read_unlock(&state->in_dev->lock);
+			in_dev_put(state->in_dev);
+		}
+		state->dev = state->dev->next;
+		if (!state->dev) {
+			state->in_dev = NULL;
+			break;
+		}
+		state->in_dev = in_dev_get(state->dev);
+		if (!state->in_dev)
+			continue;
+		read_lock(&state->in_dev->lock);
+		im = state->in_dev->mc_list;
+	}
+	return im;
+}
+
+static struct ip_mc_list *igmp_mc_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct ip_mc_list *im = igmp_mc_get_first(seq);
+	if (im)
+		while (pos && (im = igmp_mc_get_next(seq, im)) != NULL)
+			--pos;
+	return pos ? NULL : im;
+}
+
+static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock(&dev_base_lock);
+	return *pos ? igmp_mc_get_idx(seq, *pos) : (void *)1;
+}
+
+static void *igmp_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct ip_mc_list *im;
+	if (v == (void *)1)
+		im = igmp_mc_get_first(seq);
+	else
+		im = igmp_mc_get_next(seq, v);
+	++*pos;
+	return im;
+}
+
+static void igmp_mc_seq_stop(struct seq_file *seq, void *v)
+{
+	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
+	if (likely(state->in_dev != NULL)) {
+		read_unlock(&state->in_dev->lock);
+		in_dev_put(state->in_dev);
+	}
 	read_unlock(&dev_base_lock);
+}
+
+static int igmp_mc_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == (void *)1)
+		seq_printf(seq, 
+			   "Idx\tDevice    : Count Querier\tGroup    Users Timer\tReporter\n");
+	else {
+		struct ip_mc_list *im = (struct ip_mc_list *)v;
+		struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
+		char   *querier;
+#ifdef CONFIG_IP_MULTICAST
+		querier = IGMP_V1_SEEN(state->in_dev) ? "V1" : "V2";
+#else
+		querier = "NONE";
+#endif
+
+		if (state->in_dev->mc_list == im) {
+			seq_printf(seq, "%d\t%-10s: %5d %7s\n",
+				   state->dev->ifindex, state->dev->name, state->dev->mc_count, querier);
+		}
+
+		seq_printf(seq,
+			   "\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
+			   im->multiaddr, im->users,
+			   im->tm_running, im->timer.expires-jiffies, im->reporter);
+	}
+	return 0;
+}
+
+static struct seq_operations igmp_mc_seq_ops = {
+	.start	=	igmp_mc_seq_start,
+	.next	=	igmp_mc_seq_next,
+	.stop	=	igmp_mc_seq_stop,
+	.show	=	igmp_mc_seq_show,
+};
+
+static int igmp_mc_seq_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct igmp_mc_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
 
-	*start=buffer+(offset-begin);
-	len-=(offset-begin);
-	if(len>length)
-		len=length;
-	if(len<0)
-		len=0;
-	return len;
+	if (!s)
+		goto out;
+	rc = seq_open(file, &igmp_mc_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
 }
 
-int ip_mcf_procinfo(char *buffer, char **start, off_t offset, int length)
-{
-	off_t pos=0, begin=0;
-	int len=0;
-	int first = 1;
+static struct file_operations igmp_mc_seq_fops = {
+	.owner		=	THIS_MODULE,
+	.open		=	igmp_mc_seq_open,
+	.read		=	seq_read,
+	.llseek		=	seq_lseek,
+	.release	=	seq_release_private,
+};
+
+struct igmp_mcf_iter_state {
 	struct net_device *dev;
+	struct in_device *idev;
+	struct ip_mc_list *im;
+};
 
-	read_lock(&dev_base_lock);
-	for(dev=dev_base; dev; dev=dev->next) {
-		struct in_device *in_dev = in_dev_get(dev);
-		struct ip_mc_list *imc;
+#define igmp_mcf_seq_private(seq)	((struct igmp_mcf_iter_state *)&seq->private)
 
-		if (in_dev == NULL)
+static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
+{
+	struct ip_sf_list *psf = NULL;
+	struct ip_mc_list *im = NULL;
+	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
+
+	for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
+	     state->dev; 
+	     state->dev = state->dev->next) {
+		struct in_device *idev;
+		idev = in_dev_get(state->dev);
+		if (unlikely(idev == NULL))
 			continue;
+		read_lock_bh(&idev->lock);
+		im = idev->mc_list;
+		if (likely(im != NULL)) {
+			spin_lock_bh(&im->lock);
+			psf = im->sources;
+			if (likely(psf != NULL)) {
+				state->im = im;
+				state->idev = idev;
+				break;
+			}
+			spin_unlock_bh(&im->lock);
+		}
+		read_unlock_bh(&idev->lock);
+	}
+	return psf;
+}
 
-		read_lock(&in_dev->lock);
-
-		for (imc=in_dev->mc_list; imc; imc=imc->next) {
-			struct ip_sf_list *psf;
+static struct ip_sf_list *igmp_mcf_get_next(struct seq_file *seq, struct ip_sf_list *psf)
+{
+	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
 
-			spin_lock_bh(&imc->lock);
-			for (psf=imc->sources; psf; psf=psf->sf_next) {
-				if (first) {
-					len += sprintf(buffer+len, "%3s %6s "
-						"%10s %10s %6s %6s\n", "Idx",
-						"Device", "MCA", "SRC", "INC",
-						"EXC");
-					first = 0;
-				}
-				len += sprintf(buffer+len, "%3d %6.6s 0x%08x "
-					"0x%08x %6lu %6lu\n", dev->ifindex,
-					dev->name, ntohl(imc->multiaddr),
-					ntohl(psf->sf_inaddr),
-					psf->sf_count[MCAST_INCLUDE],
-					psf->sf_count[MCAST_EXCLUDE]);
-				pos=begin+len;
-				if(pos<offset)
-				{
-					len=0;
-					begin=pos;
-				}
-				if(pos>offset+length) {
-					spin_unlock_bh(&imc->lock);
-					read_unlock(&in_dev->lock);
-					in_dev_put(in_dev);
-					goto done;
-				}
+	psf = psf->sf_next;
+	while (!psf) {
+		spin_unlock_bh(&state->im->lock);
+		state->im = state->im->next;
+		while (!state->im) {
+			if (likely(state->idev != NULL)) {
+				read_unlock_bh(&state->idev->lock);
+				in_dev_put(state->idev);
+			}
+			state->dev = state->dev->next;
+			if (!state->dev) {
+				state->idev = NULL;
+				goto out;
 			}
-			spin_unlock_bh(&imc->lock);
+			state->idev = in_dev_get(state->dev);
+			if (!state->idev)
+				continue;
+			read_lock_bh(&state->idev->lock);
+			state->im = state->idev->mc_list;
 		}
-		read_unlock(&in_dev->lock);
-		in_dev_put(in_dev);
+		if (!state->im)
+			break;
+		spin_lock_bh(&state->im->lock);
+		psf = state->im->sources;
+	}
+out:
+	return psf;
+}
+
+static struct ip_sf_list *igmp_mcf_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct ip_sf_list *psf = igmp_mcf_get_first(seq);
+	if (psf)
+		while (pos && (psf = igmp_mcf_get_next(seq, psf)) != NULL)
+			--pos;
+	return pos ? NULL : psf;
+}
+
+static void *igmp_mcf_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock(&dev_base_lock);
+	return *pos ? igmp_mcf_get_idx(seq, *pos) : (void *)1;
+}
+
+static void *igmp_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct ip_sf_list *psf;
+	if (v == (void *)1)
+		psf = igmp_mcf_get_first(seq);
+	else
+		psf = igmp_mcf_get_next(seq, v);
+	++*pos;
+	return psf;
+}
+
+static void igmp_mcf_seq_stop(struct seq_file *seq, void *v)
+{
+	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
+	if (likely(state->im != NULL))
+		spin_unlock_bh(&state->im->lock);
+	if (likely(state->idev != NULL)) {
+		read_unlock_bh(&state->idev->lock);
+		in_dev_put(state->idev);
 	}
-done:
 	read_unlock(&dev_base_lock);
+}
 
-	*start=buffer+(offset-begin);
-	len-=(offset-begin);
-	if(len>length)
-		len=length;
-	if(len<0)
-		len=0;
-	return len;
+static int igmp_mcf_seq_show(struct seq_file *seq, void *v)
+{
+	struct ip_sf_list *psf = (struct ip_sf_list *)v;
+	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
+
+	if (v == (void *)1) {
+		seq_printf(seq, 
+			   "%3s %6s "
+			   "%10s %10s %6s %6s\n", "Idx",
+			   "Device", "MCA",
+			   "SRC", "INC", "EXC");
+	} else {
+		seq_printf(seq,
+			   "%3d %6.6s 0x%08x "
+			   "0x%08x %6lu %6lu\n", 
+			   state->dev->ifindex, state->dev->name, 
+			   ntohl(state->im->multiaddr),
+			   ntohl(psf->sf_inaddr),
+			   psf->sf_count[MCAST_INCLUDE],
+			   psf->sf_count[MCAST_EXCLUDE]);
+	}
+	return 0;
+}
+
+static struct seq_operations igmp_mcf_seq_ops = {
+	.start	=	igmp_mcf_seq_start,
+	.next	=	igmp_mcf_seq_next,
+	.stop	=	igmp_mcf_seq_stop,
+	.show	=	igmp_mcf_seq_show,
+};
+
+static int igmp_mcf_seq_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct igmp_mcf_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (!s)
+		goto out;
+	rc = seq_open(file, &igmp_mcf_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
+}
+
+static struct file_operations igmp_mcf_seq_fops = {
+	.owner		=	THIS_MODULE,
+	.open		=	igmp_mcf_seq_open,
+	.read		=	seq_read,
+	.llseek		=	seq_lseek,
+	.release	=	seq_release_private,
+};
+
+int __init igmp_mc_proc_init(void)
+{
+	struct proc_dir_entry *p;
+
+	p = create_proc_entry("igmp", S_IRUGO, proc_net);
+	if (p)
+		p->proc_fops = &igmp_mc_seq_fops;
+
+	p = create_proc_entry("mcfilter", S_IRUGO, proc_net);
+	if (p)
+		p->proc_fops = &igmp_mcf_seq_fops;
+	return 0;
 }
+#endif
 
diff -urN linux-2.5.73-bk9/net/ipv4/ip_output.c linux-2.5.73-bk10/net/ipv4/ip_output.c
--- linux-2.5.73-bk9/net/ipv4/ip_output.c	2003-06-22 11:33:34.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv4/ip_output.c	2003-07-02 04:57:42.000000000 -0700
@@ -1314,7 +1314,6 @@
 	inet_initpeers();
 
 #ifdef CONFIG_IP_MULTICAST
-	proc_net_create("igmp", 0, ip_mc_procinfo);
+	igmp_mc_proc_init();
 #endif
-	proc_net_create("mcfilter", 0, ip_mcf_procinfo);
 }
diff -urN linux-2.5.73-bk9/net/ipv4/raw.c linux-2.5.73-bk10/net/ipv4/raw.c
--- linux-2.5.73-bk9/net/ipv4/raw.c	2003-06-22 11:32:55.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv4/raw.c	2003-07-02 04:57:43.000000000 -0700
@@ -801,7 +801,24 @@
 
 static int raw_seq_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &raw_seq_ops);
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct raw_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (!s)
+		goto out;
+	rc = seq_open(file, &raw_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
 }
 
 static struct file_operations raw_seq_fops = {
@@ -809,7 +826,7 @@
 	.open	 = raw_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
-	.release = seq_release,
+	.release = seq_release_private,
 };
 
 int __init raw_proc_init(void)
diff -urN linux-2.5.73-bk9/net/ipv6/addrconf.c linux-2.5.73-bk10/net/ipv6/addrconf.c
--- linux-2.5.73-bk9/net/ipv6/addrconf.c	2003-06-22 11:33:17.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/addrconf.c	2003-07-02 04:57:43.000000000 -0700
@@ -66,6 +66,7 @@
 #include <net/ndisc.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
+#include <net/tcp.h>
 #include <net/ip.h>
 #include <linux/if_tunnel.h>
 #include <linux/rtnetlink.h>
@@ -701,7 +702,7 @@
 	ift = ipv6_count_addresses(idev) < IPV6_MAX_ADDRESSES ?
 		ipv6_add_addr(idev, &addr, tmp_plen,
 			      ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, IFA_F_TEMPORARY) : 0;
-	if (IS_ERR(ift)) {
+	if (!ift || IS_ERR(ift)) {
 		in6_dev_put(idev);
 		in6_ifa_put(ifp);
 		printk(KERN_INFO
@@ -969,6 +970,43 @@
 	return ifp;
 }
 
+int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
+{
+	struct ipv6_pinfo *np = inet6_sk(sk);
+	int addr_type = ipv6_addr_type(&np->rcv_saddr);
+
+	if (!inet_sk(sk2)->rcv_saddr && !ipv6_only_sock(sk))
+		return 1;
+
+	if (sk2->sk_family == AF_INET6 &&
+	    ipv6_addr_any(&inet6_sk(sk2)->rcv_saddr) &&
+	    !(ipv6_only_sock(sk2) && addr_type == IPV6_ADDR_MAPPED))
+		return 1;
+
+	if (addr_type == IPV6_ADDR_ANY &&
+	    (!ipv6_only_sock(sk) ||
+	     !(sk2->sk_family == AF_INET6 ?
+	       (ipv6_addr_type(&inet6_sk(sk2)->rcv_saddr) == IPV6_ADDR_MAPPED) :
+	        1)))
+		return 1;
+
+	if (sk2->sk_family == AF_INET6 &&
+	    !ipv6_addr_cmp(&np->rcv_saddr,
+			   (sk2->sk_state != TCP_TIME_WAIT ?
+			    &inet6_sk(sk2)->rcv_saddr :
+			    &tcptw_sk(sk)->tw_v6_rcv_saddr)))
+		return 1;
+
+	if (addr_type == IPV6_ADDR_MAPPED &&
+	    !ipv6_only_sock(sk2) &&
+	    (!inet_sk(sk2)->rcv_saddr ||
+	     !inet_sk(sk)->rcv_saddr ||
+	     inet_sk(sk)->rcv_saddr == inet_sk(sk2)->rcv_saddr))
+		return 1;
+
+	return 0;
+}
+
 /* Gets referenced address, destroys ifaddr */
 
 void addrconf_dad_failure(struct inet6_ifaddr *ifp)
@@ -1372,7 +1410,7 @@
 				ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len,
 						    addr_type&IPV6_ADDR_SCOPE_MASK, 0);
 
-			if (IS_ERR(ifp)) {
+			if (!ifp || IS_ERR(ifp)) {
 				in6_dev_put(in6_dev);
 				return;
 			}
diff -urN linux-2.5.73-bk9/net/ipv6/af_inet6.c linux-2.5.73-bk10/net/ipv6/af_inet6.c
--- linux-2.5.73-bk9/net/ipv6/af_inet6.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/af_inet6.c	2003-07-02 04:57:43.000000000 -0700
@@ -85,7 +85,8 @@
 extern void udp6_proc_exit(void);
 extern int ipv6_misc_proc_init(void);
 extern void ipv6_misc_proc_exit(void);
-extern int anycast6_get_info(char *, char **, off_t, int);
+extern int ac6_proc_init(void);
+extern void ac6_proc_exit(void);
 extern int if6_proc_init(void);
 extern void if6_proc_exit(void);
 #endif
@@ -799,7 +800,7 @@
 	if (ipv6_misc_proc_init())
 		goto proc_misc6_fail;
 
-	if (!proc_net_create("anycast6", 0, anycast6_get_info))
+	if (ac6_proc_init())
 		goto proc_anycast6_fail;
 	if (if6_proc_init())
 		goto proc_if6_fail;
@@ -825,7 +826,7 @@
 
 #ifdef CONFIG_PROC_FS
 proc_if6_fail:
-	proc_net_remove("anycast6");
+	ac6_proc_exit();
 proc_anycast6_fail:
 	ipv6_misc_proc_exit();
 proc_misc6_fail:
@@ -863,7 +864,7 @@
 	sock_unregister(PF_INET6);
 #ifdef CONFIG_PROC_FS
 	if6_proc_exit();
- 	proc_net_remove("anycast6");
+	ac6_proc_exit();
  	ipv6_misc_proc_exit();
  	udp6_proc_exit();
  	tcp6_proc_exit();
diff -urN linux-2.5.73-bk9/net/ipv6/anycast.c linux-2.5.73-bk10/net/ipv6/anycast.c
--- linux-2.5.73-bk9/net/ipv6/anycast.c	2003-06-22 11:32:31.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/anycast.c	2003-07-02 04:57:43.000000000 -0700
@@ -29,6 +29,7 @@
 #include <linux/route.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <net/sock.h>
 #include <net/snmp.h>
@@ -435,56 +436,159 @@
 
 
 #ifdef CONFIG_PROC_FS
-int anycast6_get_info(char *buffer, char **start, off_t offset, int length)
-{
-	off_t pos=0, begin=0;
-	struct ifacaddr6 *im;
-	int len=0;
+struct ac6_iter_state {
 	struct net_device *dev;
-	
-	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev; dev = dev->next) {
-		struct inet6_dev *idev;
+	struct inet6_dev *idev;
+};
 
-		if ((idev = in6_dev_get(dev)) == NULL)
-			continue;
+#define ac6_seq_private(seq)	((struct ac6_iter_state *)&seq->private)
 
-		read_lock_bh(&idev->lock);
-		for (im = idev->ac_list; im; im = im->aca_next) {
-			int i;
+static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
+{
+	struct ifacaddr6 *im = NULL;
+	struct ac6_iter_state *state = ac6_seq_private(seq);
 
-			len += sprintf(buffer+len,"%-4d %-15s ", dev->ifindex, dev->name);
+	for (state->dev = dev_base, state->idev = NULL;
+	     state->dev;
+	     state->dev = state->dev->next) {
+		struct inet6_dev *idev;
+		idev = in6_dev_get(state->dev);
+		if (!idev)
+			continue;
+		read_lock_bh(&idev->lock);
+		im = idev->ac_list;
+		if (im) {
+			state->idev = idev;
+			break;
+		}
+		read_unlock_bh(&idev->lock);
+	}
+	return im;
+}
 
-			for (i=0; i<16; i++)
-				len += sprintf(buffer+len, "%02x", im->aca_addr.s6_addr[i]);
+static struct ifacaddr6 *ac6_get_next(struct seq_file *seq, struct ifacaddr6 *im)
+{
+	struct ac6_iter_state *state = ac6_seq_private(seq);
 
-			len += sprintf(buffer+len, " %5d\n", im->aca_users);
-
-			pos=begin+len;
-			if (pos < offset) {
-				len=0;
-				begin=pos;
-			}
-			if (pos > offset+length) {
-				read_unlock_bh(&idev->lock);
-				in6_dev_put(idev);
-				goto done;
-			}
+	im = im->aca_next;
+	while (!im) {
+		if (likely(state->idev != NULL)) {
+			read_unlock_bh(&state->idev->lock);
+			in6_dev_put(state->idev);
 		}
-		read_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
+		state->dev = state->dev->next;
+		if (!state->dev) {
+			state->idev = NULL;
+			break;
+		}
+		state->idev = in6_dev_get(state->dev);
+		if (!state->idev)
+			continue;
+		read_lock_bh(&state->idev->lock);
+		im = state->idev->ac_list;
 	}
+	return im;
+}
 
-done:
+static struct ifacaddr6 *ac6_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct ifacaddr6 *im = ac6_get_first(seq);
+	if (im)
+		while (pos && (im = ac6_get_next(seq, im)) != NULL)
+			--pos;
+	return pos ? NULL : im;
+}
+
+static void *ac6_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock(&dev_base_lock);
+	return *pos ? ac6_get_idx(seq, *pos) : ac6_get_first(seq);
+}
+
+static void *ac6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct ifacaddr6 *im;
+	im = ac6_get_next(seq, v);
+	++*pos;
+	return im;
+}
+
+static void ac6_seq_stop(struct seq_file *seq, void *v)
+{
+	struct ac6_iter_state *state = ac6_seq_private(seq);
+	if (likely(state->idev != NULL)) {
+		read_unlock_bh(&state->idev->lock);
+		in6_dev_put(state->idev);
+	}
 	read_unlock(&dev_base_lock);
+}
+
+static int ac6_seq_show(struct seq_file *seq, void *v)
+{
+	struct ifacaddr6 *im = (struct ifacaddr6 *)v;
+	struct ac6_iter_state *state = ac6_seq_private(seq);
 
-	*start=buffer+(offset-begin);
-	len-=(offset-begin);
-	if(len>length)
-		len=length;
-	if (len<0)
-		len=0;
-	return len;
+	seq_printf(seq,
+		   "%-4d %-15s "
+		   "%04x%04x%04x%04x%04x%04x%04x%04x "
+		   "%5d\n",
+		   state->dev->ifindex, state->dev->name,
+		   NIP6(im->aca_addr),
+		   im->aca_users);
+	return 0;
 }
 
+static struct seq_operations ac6_seq_ops = {
+	.start	=	ac6_seq_start,
+	.next	=	ac6_seq_next,
+	.stop	=	ac6_seq_stop,
+	.show	=	ac6_seq_show,
+};
+
+static int ac6_seq_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct ac6_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (!s)
+		goto out;
+
+	rc = seq_open(file, &ac6_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
+}
+
+static struct file_operations ac6_seq_fops = {
+	.owner		=	THIS_MODULE,
+	.open		=	ac6_seq_open,
+	.read		=	seq_read,
+	.llseek		=	seq_lseek,
+	.release	=	seq_release_private,
+};
+
+int __init ac6_proc_init(void)
+{
+	struct proc_dir_entry *p;
+
+	p = create_proc_entry("anycast6", S_IRUGO, proc_net);
+	if (p)
+		p->proc_fops = &ac6_seq_fops;
+	return 0;
+}
+
+void ac6_proc_exit(void)
+{
+	proc_net_remove("anycast6");
+}
 #endif
+
diff -urN linux-2.5.73-bk9/net/ipv6/ip6_flowlabel.c linux-2.5.73-bk10/net/ipv6/ip6_flowlabel.c
--- linux-2.5.73-bk9/net/ipv6/ip6_flowlabel.c	2003-07-02 04:57:17.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/ip6_flowlabel.c	2003-07-02 04:57:43.000000000 -0700
@@ -657,7 +657,25 @@
 
 static int ip6fl_seq_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &ip6fl_seq_ops);
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct ip6fl_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (!s)
+		goto out;
+
+	rc = seq_open(file, &ip6fl_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
 }
 
 static struct file_operations ip6fl_seq_fops = {
@@ -665,7 +683,7 @@
 	.open		=	ip6fl_seq_open,
 	.read		=	seq_read,
 	.llseek		=	seq_lseek,
-	.release	=	seq_release,
+	.release	=	seq_release_private,
 };
 #endif
 
diff -urN linux-2.5.73-bk9/net/ipv6/mcast.c linux-2.5.73-bk10/net/ipv6/mcast.c
--- linux-2.5.73-bk9/net/ipv6/mcast.c	2003-07-02 04:57:17.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/mcast.c	2003-07-02 04:57:43.000000000 -0700
@@ -44,6 +44,7 @@
 #include <linux/route.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <net/sock.h>
 #include <net/snmp.h>
@@ -2039,138 +2040,317 @@
 }
 
 #ifdef CONFIG_PROC_FS
-static int igmp6_read_proc(char *buffer, char **start, off_t offset,
-			   int length, int *eof, void *data)
-{
-	off_t pos=0, begin=0;
-	struct ifmcaddr6 *im;
-	int len=0;
+struct igmp6_mc_iter_state {
 	struct net_device *dev;
-	
-	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev; dev = dev->next) {
-		struct inet6_dev *idev;
+	struct inet6_dev *idev;
+};
 
-		if ((idev = in6_dev_get(dev)) == NULL)
-			continue;
+#define igmp6_mc_seq_private(seq)	((struct igmp6_mc_iter_state *)&seq->private)
 
-		read_lock_bh(&idev->lock);
-		for (im = idev->mc_list; im; im = im->next) {
-			int i;
+static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
+{
+	struct ifmcaddr6 *im = NULL;
+	struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
-			len += sprintf(buffer+len,"%-4d %-15s ", dev->ifindex, dev->name);
+	for (state->dev = dev_base, state->idev = NULL;
+	     state->dev; 
+	     state->dev = state->dev->next) {
+		struct inet6_dev *idev;
+		idev = in6_dev_get(state->dev);
+		if (!idev)
+			continue;
+		read_lock_bh(&idev->lock);
+		im = idev->mc_list;
+		if (im) {
+			state->idev = idev;
+			break;
+		}
+		read_unlock_bh(&idev->lock);
+	}
+	return im;
+}
 
-			for (i=0; i<16; i++)
-				len += sprintf(buffer+len, "%02x", im->mca_addr.s6_addr[i]);
+static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct ifmcaddr6 *im)
+{
+	struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
-			len+=sprintf(buffer+len,
-				     " %5d %08X %ld\n",
-				     im->mca_users,
-				     im->mca_flags,
-				     (im->mca_flags&MAF_TIMER_RUNNING) ? im->mca_timer.expires-jiffies : 0);
-
-			pos=begin+len;
-			if (pos < offset) {
-				len=0;
-				begin=pos;
-			}
-			if (pos > offset+length) {
-				read_unlock_bh(&idev->lock);
-				in6_dev_put(idev);
-				goto done;
-			}
+	im = im->next;
+	while (!im) {
+		if (likely(state->idev != NULL)) {
+			read_unlock_bh(&state->idev->lock);
+			in6_dev_put(state->idev);
 		}
-		read_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
+		state->dev = state->dev->next;
+		if (!state->dev) {
+			state->idev = NULL;
+			break;
+		}
+		state->idev = in6_dev_get(state->dev);
+		if (!state->idev)
+			continue;
+		read_lock_bh(&state->idev->lock);
+		im = state->idev->mc_list;
 	}
-	*eof = 1;
+	return im;
+}
 
-done:
+static struct ifmcaddr6 *igmp6_mc_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct ifmcaddr6 *im = igmp6_mc_get_first(seq);
+	if (im)
+		while (pos && (im = igmp6_mc_get_next(seq, im)) != NULL)
+			--pos;
+	return pos ? NULL : im;
+}
+
+static void *igmp6_mc_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock(&dev_base_lock);
+	return *pos ? igmp6_mc_get_idx(seq, *pos) : igmp6_mc_get_first(seq);
+}
+
+static void *igmp6_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct ifmcaddr6 *im;
+	im = igmp6_mc_get_next(seq, v);
+	++*pos;
+	return im;
+}
+
+static void igmp6_mc_seq_stop(struct seq_file *seq, void *v)
+{
+	struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
+	if (likely(state->idev != NULL)) {
+		read_unlock_bh(&state->idev->lock);
+		in6_dev_put(state->idev);
+	}
 	read_unlock(&dev_base_lock);
+}
+
+static int igmp6_mc_seq_show(struct seq_file *seq, void *v)
+{
+	struct ifmcaddr6 *im = (struct ifmcaddr6 *)v;
+	struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
-	*start=buffer+(offset-begin);
-	len-=(offset-begin);
-	if(len>length)
-		len=length;
-	if (len<0)
-		len=0;
-	return len;
+	seq_printf(seq,
+		   "%-4d %-15s %04x%04x%04x%04x%04x%04x%04x%04x %5d %08X %ld\n", 
+		   state->dev->ifindex, state->dev->name,
+		   NIP6(im->mca_addr),
+		   im->mca_users, im->mca_flags,
+		   (im->mca_flags&MAF_TIMER_RUNNING) ? im->mca_timer.expires-jiffies : 0);
+	return 0;
 }
 
-static int ip6_mcf_read_proc(char *buffer, char **start, off_t offset,
-			   int length, int *eof, void *data)
-{
-	off_t pos=0, begin=0;
-	int len=0;
-	int first=1;
-	struct net_device *dev;
-	
-	read_lock(&dev_base_lock);
-	for (dev=dev_base; dev; dev=dev->next) {
-		struct inet6_dev *idev = in6_dev_get(dev);
-		struct ifmcaddr6 *imc;
+static struct seq_operations igmp6_mc_seq_ops = {
+	.start	=	igmp6_mc_seq_start,
+	.next	=	igmp6_mc_seq_next,
+	.stop	=	igmp6_mc_seq_stop,
+	.show	=	igmp6_mc_seq_show,
+};
 
-		if (idev == NULL)
-			continue;
+static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct igmp6_mc_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (!s)
+		goto out;
+
+	rc = seq_open(file, &igmp6_mc_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
+}
 
-		read_lock_bh(&idev->lock);
+static struct file_operations igmp6_mc_seq_fops = {
+	.owner		=	THIS_MODULE,
+	.open		=	igmp6_mc_seq_open,
+	.read		=	seq_read,
+	.llseek		=	seq_lseek,
+	.release	=	seq_release_private,
+};
 
-		for (imc=idev->mc_list; imc; imc=imc->next) {
-			struct ip6_sf_list *psf;
-			unsigned long i;
+struct igmp6_mcf_iter_state {
+	struct net_device *dev;
+	struct inet6_dev *idev;
+	struct ifmcaddr6 *im;
+};
 
-			spin_lock_bh(&imc->mca_lock);
-			for (psf=imc->mca_sources; psf; psf=psf->sf_next) {
-				if (first) {
-					len += sprintf(buffer+len, "%3s %6s "
-						"%32s %32s %6s %6s\n", "Idx",
-						"Device", "Multicast Address",
-						"Source Address", "INC", "EXC");
-					first = 0;
-				}
-				len += sprintf(buffer+len,"%3d %6.6s ",
-					dev->ifindex, dev->name);
+#define igmp6_mcf_seq_private(seq)	((struct igmp6_mcf_iter_state *)&seq->private)
 
-				for (i=0; i<16; i++)
-					len += sprintf(buffer+len, "%02x",
-						imc->mca_addr.s6_addr[i]);
-				buffer[len++] = ' ';
-				for (i=0; i<16; i++)
-					len += sprintf(buffer+len, "%02x",
-						psf->sf_addr.s6_addr[i]);
-				len += sprintf(buffer+len, " %6lu %6lu\n",
-					psf->sf_count[MCAST_INCLUDE],
-					psf->sf_count[MCAST_EXCLUDE]);
-				pos = begin+len;
-				if (pos < offset) {
-					len=0;
-					begin=pos;
-				}
-				if (pos > offset+length) {
-					spin_unlock_bh(&imc->mca_lock);
-					read_unlock_bh(&idev->lock);
-					in6_dev_put(idev);
-					goto done;
-				}
+static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
+{
+	struct ip6_sf_list *psf = NULL;
+	struct ifmcaddr6 *im = NULL;
+	struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
+
+	for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
+	     state->dev; 
+	     state->dev = state->dev->next) {
+		struct inet6_dev *idev;
+		idev = in6_dev_get(state->dev);
+		if (unlikely(idev == NULL))
+			continue;
+		read_lock_bh(&idev->lock);
+		im = idev->mc_list;
+		if (likely(im != NULL)) {
+			spin_lock_bh(&im->mca_lock);
+			psf = im->mca_sources;
+			if (likely(psf != NULL)) {
+				state->im = im;
+				state->idev = idev;
+				break;
 			}
-			spin_unlock_bh(&imc->mca_lock);
+			spin_unlock_bh(&im->mca_lock);
 		}
 		read_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
 	}
-	*eof = 1;
+	return psf;
+}
 
-done:
+static struct ip6_sf_list *igmp6_mcf_get_next(struct seq_file *seq, struct ip6_sf_list *psf)
+{
+	struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
+
+	psf = psf->sf_next;
+	while (!psf) {
+		spin_unlock_bh(&state->im->mca_lock);
+		state->im = state->im->next;
+		while (!state->im) {
+			if (likely(state->idev != NULL)) {
+				read_unlock_bh(&state->idev->lock);
+				in6_dev_put(state->idev);
+			}
+			state->dev = state->dev->next;
+			if (!state->dev) {
+				state->idev = NULL;
+				goto out;
+			}
+			state->idev = in6_dev_get(state->dev);
+			if (!state->idev)
+				continue;
+			read_lock_bh(&state->idev->lock);
+			state->im = state->idev->mc_list;
+		}
+		if (!state->im)
+			break;
+		spin_lock_bh(&state->im->mca_lock);
+		psf = state->im->mca_sources;
+	}
+out:
+	return psf;
+}
+
+static struct ip6_sf_list *igmp6_mcf_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct ip6_sf_list *psf = igmp6_mcf_get_first(seq);
+	if (psf)
+		while (pos && (psf = igmp6_mcf_get_next(seq, psf)) != NULL)
+			--pos;
+	return pos ? NULL : psf;
+}
+
+static void *igmp6_mcf_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock(&dev_base_lock);
+	return *pos ? igmp6_mcf_get_idx(seq, *pos) : (void *)1;
+}
+
+static void *igmp6_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct ip6_sf_list *psf;
+	if (v == (void *)1)
+		psf = igmp6_mcf_get_first(seq);
+	else
+		psf = igmp6_mcf_get_next(seq, v);
+	++*pos;
+	return psf;
+}
+
+static void igmp6_mcf_seq_stop(struct seq_file *seq, void *v)
+{
+	struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
+	if (likely(state->im != NULL))
+		spin_unlock_bh(&state->im->mca_lock);
+	if (likely(state->idev != NULL)) {
+		read_unlock_bh(&state->idev->lock);
+		in6_dev_put(state->idev);
+	}
 	read_unlock(&dev_base_lock);
+}
 
-	*start=buffer+(offset-begin);
-	len-=(offset-begin);
-	if(len>length)
-		len=length;
-	if (len<0)
-		len=0;
-	return len;
+static int igmp6_mcf_seq_show(struct seq_file *seq, void *v)
+{
+	struct ip6_sf_list *psf = (struct ip6_sf_list *)v;
+	struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
+
+	if (v == (void *)1) {
+		seq_printf(seq, 
+			   "%3s %6s "
+			   "%32s %32s %6s %6s\n", "Idx",
+			   "Device", "Multicast Address",
+			   "Source Address", "INC", "EXC");
+	} else {
+		seq_printf(seq,
+			   "%3d %6.6s "
+			   "%04x%04x%04x%04x%04x%04x%04x%04x "
+			   "%04x%04x%04x%04x%04x%04x%04x%04x "
+			   "%6lu %6lu\n",
+			   state->dev->ifindex, state->dev->name,
+			   NIP6(state->im->mca_addr),
+			   NIP6(psf->sf_addr),
+			   psf->sf_count[MCAST_INCLUDE],
+			   psf->sf_count[MCAST_EXCLUDE]);
+	}
+	return 0;
+}
+
+static struct seq_operations igmp6_mcf_seq_ops = {
+	.start	=	igmp6_mcf_seq_start,
+	.next	=	igmp6_mcf_seq_next,
+	.stop	=	igmp6_mcf_seq_stop,
+	.show	=	igmp6_mcf_seq_show,
+};
+
+static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct igmp6_mcf_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+	
+	if (!s)
+		goto out;
+
+	rc = seq_open(file, &igmp6_mcf_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
 }
+
+static struct file_operations igmp6_mcf_seq_fops = {
+	.owner		=	THIS_MODULE,
+	.open		=	igmp6_mcf_seq_open,
+	.read		=	seq_read,
+	.llseek		=	seq_lseek,
+	.release	=	seq_release_private,
+};
 #endif
 
 int __init igmp6_init(struct net_proto_family *ops)
@@ -2178,6 +2358,9 @@
 	struct ipv6_pinfo *np;
 	struct sock *sk;
 	int err;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *p;
+#endif
 
 	err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket);
 	if (err < 0) {
@@ -2194,9 +2377,14 @@
 
 	np = inet6_sk(sk);
 	np->hop_limit = 1;
+
 #ifdef CONFIG_PROC_FS
-	create_proc_read_entry("net/igmp6", 0, 0, igmp6_read_proc, NULL);
-	create_proc_read_entry("net/mcfilter6", 0, 0, ip6_mcf_read_proc, NULL);
+	p = create_proc_entry("igmp6", S_IRUGO, proc_net);
+	if (p)
+		p->proc_fops = &igmp6_mc_seq_fops;
+	p = create_proc_entry("mcfilter6", S_IRUGO, proc_net);
+	if (p)
+		p->proc_fops = &igmp6_mcf_seq_fops;
 #endif
 
 	return 0;
@@ -2207,6 +2395,7 @@
 	sock_release(igmp6_socket);
 	igmp6_socket = NULL; /* for safety */
 #ifdef CONFIG_PROC_FS
-	remove_proc_entry("net/igmp6", 0);
+	proc_net_remove("mcfilter6");
+	proc_net_remove("igmp6");
 #endif
 }
diff -urN linux-2.5.73-bk9/net/ipv6/ndisc.c linux-2.5.73-bk10/net/ipv6/ndisc.c
--- linux-2.5.73-bk9/net/ipv6/ndisc.c	2003-07-02 04:57:17.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/ndisc.c	2003-07-02 04:57:43.000000000 -0700
@@ -884,7 +884,6 @@
 		in6_dev_put(idev);
 	} else {
 		struct inet6_dev *in6_dev = in6_dev_get(dev);
-		int addr_type = ipv6_addr_type(saddr);
 
 		if (in6_dev && in6_dev->cnf.forwarding &&
 		    (addr_type & IPV6_ADDR_UNICAST) &&
diff -urN linux-2.5.73-bk9/net/ipv6/raw.c linux-2.5.73-bk10/net/ipv6/raw.c
--- linux-2.5.73-bk9/net/ipv6/raw.c	2003-06-22 11:32:42.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/raw.c	2003-07-02 04:57:43.000000000 -0700
@@ -1029,7 +1029,22 @@
 
 static int raw6_seq_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &raw6_seq_ops);
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct raw6_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+	if (!s)
+		goto out;
+	rc = seq_open(file, &raw6_seq_ops);
+	if (rc)
+		goto out_kfree;
+	seq = file->private_data;
+	seq->private = s;
+	memset(s, 0, sizeof(*s));
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
 }
 
 static struct file_operations raw6_seq_fops = {
@@ -1037,7 +1052,7 @@
 	.open =		raw6_seq_open,
 	.read =		seq_read,
 	.llseek =	seq_lseek,
-	.release =	seq_release,
+	.release =	seq_release_private,
 };
 
 int __init raw6_proc_init(void)
diff -urN linux-2.5.73-bk9/net/ipv6/tcp_ipv6.c linux-2.5.73-bk10/net/ipv6/tcp_ipv6.c
--- linux-2.5.73-bk9/net/ipv6/tcp_ipv6.c	2003-06-22 11:32:56.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/tcp_ipv6.c	2003-07-02 04:57:43.000000000 -0700
@@ -93,43 +93,6 @@
 	return tcp_v6_hashfn(laddr, lport, faddr, fport);
 }
 
-static inline int ipv6_rcv_saddr_equal(struct sock *sk, struct sock *sk2)
-{
-	struct ipv6_pinfo *np = inet6_sk(sk);
-	int addr_type = ipv6_addr_type(&np->rcv_saddr);
-
-	if (!inet_sk(sk2)->rcv_saddr && !ipv6_only_sock(sk))
-		return 1;
-
-	if (sk2->sk_family == AF_INET6 &&
-	    ipv6_addr_any(&inet6_sk(sk2)->rcv_saddr) &&
-	    !(ipv6_only_sock(sk2) && addr_type == IPV6_ADDR_MAPPED))
-		return 1;
-
-	if (addr_type == IPV6_ADDR_ANY &&
-	    (!ipv6_only_sock(sk) ||
-	     !(sk2->sk_family == AF_INET6 ?
-	       (ipv6_addr_type(&inet6_sk(sk2)->rcv_saddr) == IPV6_ADDR_MAPPED) :
-	        1)))
-		return 1;
-
-	if (sk2->sk_family == AF_INET6 &&
-	    !ipv6_addr_cmp(&np->rcv_saddr,
-			   (sk2->sk_state != TCP_TIME_WAIT ?
-			    &inet6_sk(sk2)->rcv_saddr :
-			    &((struct tcp_tw_bucket *)sk)->tw_v6_rcv_saddr)))
-		return 1;
-
-	if (addr_type == IPV6_ADDR_MAPPED &&
-	    !ipv6_only_sock(sk2) &&
-	    (!inet_sk(sk2)->rcv_saddr ||
-	     !inet_sk(sk)->rcv_saddr ||
-	     inet_sk(sk)->rcv_saddr == inet_sk(sk2)->rcv_saddr))
-		return 1;
-
-	return 0;
-}
-
 static inline int tcp_v6_bind_conflict(struct sock *sk,
 				       struct tcp_bind_bucket *tb)
 {
diff -urN linux-2.5.73-bk9/net/ipv6/udp.c linux-2.5.73-bk10/net/ipv6/udp.c
--- linux-2.5.73-bk9/net/ipv6/udp.c	2003-06-22 11:33:09.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/udp.c	2003-07-02 04:57:43.000000000 -0700
@@ -59,43 +59,6 @@
 
 DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6);
 
-/* XXX This is identical to tcp_ipv6.c:ipv6_rcv_saddr_equal, put
- * XXX it somewhere common. -DaveM
- */
-static __inline__ int udv6_rcv_saddr_equal(struct sock *sk, struct sock *sk2)
-{
-	struct ipv6_pinfo *np = inet6_sk(sk);
-	int addr_type = ipv6_addr_type(&np->rcv_saddr);
-
-	if (!inet_sk(sk2)->rcv_saddr && !ipv6_only_sock(sk))
-		return 1;
-
-	if (sk2->sk_family == AF_INET6 && 
-	    ipv6_addr_any(&inet6_sk(sk2)->rcv_saddr) &&
-	    !(ipv6_only_sock(sk2) && addr_type == IPV6_ADDR_MAPPED))
-		return 1;
-
-	if (addr_type == IPV6_ADDR_ANY && 
-	    (!ipv6_only_sock(sk) || 
-	     !(sk2->sk_family == AF_INET6 ?
-	       (ipv6_addr_type(&inet6_sk(sk2)->rcv_saddr) == IPV6_ADDR_MAPPED) : 1)))
-		return 1;
-
-	if (sk2->sk_family == AF_INET6 && 
-	    !ipv6_addr_cmp(&inet6_sk(sk)->rcv_saddr,
-			   &inet6_sk(sk2)->rcv_saddr))
-		return 1;
-
-	if (addr_type == IPV6_ADDR_MAPPED &&
-	    !ipv6_only_sock(sk2) &&
-	    (!inet_sk(sk2)->rcv_saddr || 
-	     !inet_sk(sk)->rcv_saddr ||
-	     inet_sk(sk)->rcv_saddr == inet_sk(sk2)->rcv_saddr))
-		return 1;
-
-	return 0;
-}
-
 /* Grrr, addr_type already calculated by caller, but I don't want
  * to add some silly "cookie" argument to this method just for that.
  */
@@ -151,7 +114,7 @@
 			    sk2 != sk &&
 			    sk2->sk_bound_dev_if == sk->sk_bound_dev_if &&
 			    (!sk2->sk_reuse || !sk->sk_reuse) &&
-			    udv6_rcv_saddr_equal(sk, sk2))
+			    ipv6_rcv_saddr_equal(sk, sk2))
 				goto fail;
 		}
 	}
diff -urN linux-2.5.73-bk9/net/ipv6/xfrm6_input.c linux-2.5.73-bk10/net/ipv6/xfrm6_input.c
--- linux-2.5.73-bk9/net/ipv6/xfrm6_input.c	2003-06-22 11:33:36.000000000 -0700
+++ linux-2.5.73-bk10/net/ipv6/xfrm6_input.c	2003-07-02 04:57:43.000000000 -0700
@@ -67,10 +67,8 @@
 
 		xfrm_vec[xfrm_nr++].xvec = x;
 
-		iph = skb->nh.ipv6h;
-
 		if (x->props.mode) { /* XXX */
-			if (iph->nexthdr != IPPROTO_IPV6)
+			if (nexthdr != IPPROTO_IPV6)
 				goto drop;
 			skb->nh.raw = skb->data;
 			iph = skb->nh.ipv6h;
