[kernel] r6416 - dists/trunk/linux-2.6/debian/patches

Christian T. Steigies cts at costa.debian.org
Fri Apr 14 13:46:22 UTC 2006


Author: cts
Date: Fri Apr 14 13:46:07 2006
New Revision: 6416

Added:
   dists/trunk/linux-2.6/debian/patches/m68k-2.6.16.patch
Log:
2.6.16 patch for m68k


Added: dists/trunk/linux-2.6/debian/patches/m68k-2.6.16.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/m68k-2.6.16.patch	Fri Apr 14 13:46:07 2006
@@ -0,0 +1,9001 @@
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/Makefile linux-m68k/Makefile
+--- linux-i386/Makefile	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/Makefile	2006-04-11 16:31:06.000000000 +0200
+@@ -172,7 +172,7 @@
+ # Default value for CROSS_COMPILE is not to prefix executables
+ # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
+ 
+-ARCH		?= $(SUBARCH)
++ARCH		?= m68k
+ CROSS_COMPILE	?=
+ 
+ # Architecture as present in compile.h
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/Kconfig linux-m68k/arch/m68k/Kconfig
+--- linux-i386/arch/m68k/Kconfig	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/Kconfig	2006-04-11 16:32:18.000000000 +0200
+@@ -596,7 +596,7 @@
+ 
+ config SERIAL167
+ 	bool "CD2401 support for MVME166/7 serial ports"
+-	depends on MVME16x && BROKEN
++	depends on MVME16x
+ 	help
+ 	  This is the driver for the serial ports on the Motorola MVME166,
+ 	  167, and 172 boards.  Everyone using one of these boards should say
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/amiga/amiga_ksyms.c linux-m68k/arch/m68k/amiga/amiga_ksyms.c
+--- linux-i386/arch/m68k/amiga/amiga_ksyms.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/amiga/amiga_ksyms.c	2006-01-28 23:52:25.000000000 +0100
+@@ -23,8 +23,6 @@
+ EXPORT_SYMBOL(amiga_chip_size);
+ EXPORT_SYMBOL(amiga_audio_period);
+ EXPORT_SYMBOL(amiga_audio_min_period);
+-EXPORT_SYMBOL(amiga_do_irq);
+-EXPORT_SYMBOL(amiga_do_irq_list);
+ 
+ #ifdef CONFIG_AMIGA_PCMCIA
+   EXPORT_SYMBOL(pcmcia_reset);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/amiga/amiints.c linux-m68k/arch/m68k/amiga/amiints.c
+--- linux-i386/arch/m68k/amiga/amiints.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/amiga/amiints.c	2006-04-11 16:32:18.000000000 +0200
+@@ -35,60 +35,29 @@
+  *           /Jes
+  */
+ 
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/kernel_stat.h>
+ #include <linux/init.h>
++#include <linux/interrupt.h>
+ #include <linux/errno.h>
+-#include <linux/seq_file.h>
+ 
+-#include <asm/system.h>
+ #include <asm/irq.h>
+ #include <asm/traps.h>
+ #include <asm/amigahw.h>
+ #include <asm/amigaints.h>
+ #include <asm/amipcmcia.h>
+ 
+-extern int cia_request_irq(struct ciabase *base,int irq,
+-                           irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                           unsigned long flags, const char *devname, void *dev_id);
+-extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id);
+-extern void cia_init_IRQ(struct ciabase *base);
+-extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p);
+-
+-/* irq node variables for amiga interrupt sources */
+-static irq_node_t *ami_irq_list[AMI_STD_IRQS];
+-
+-static unsigned short amiga_intena_vals[AMI_STD_IRQS] = {
+-	[IRQ_AMIGA_VERTB]	= IF_VERTB,
+-	[IRQ_AMIGA_COPPER]	= IF_COPER,
+-	[IRQ_AMIGA_AUD0]	= IF_AUD0,
+-	[IRQ_AMIGA_AUD1]	= IF_AUD1,
+-	[IRQ_AMIGA_AUD2]	= IF_AUD2,
+-	[IRQ_AMIGA_AUD3]	= IF_AUD3,
+-	[IRQ_AMIGA_BLIT]	= IF_BLIT,
+-	[IRQ_AMIGA_DSKSYN]	= IF_DSKSYN,
+-	[IRQ_AMIGA_DSKBLK]	= IF_DSKBLK,
+-	[IRQ_AMIGA_RBF]		= IF_RBF,
+-	[IRQ_AMIGA_TBE]		= IF_TBE,
+-	[IRQ_AMIGA_SOFT]	= IF_SOFT,
+-	[IRQ_AMIGA_PORTS]	= IF_PORTS,
+-	[IRQ_AMIGA_EXTER]	= IF_EXTER
++static void amiga_enable_irq(unsigned int irq);
++static void amiga_disable_irq(unsigned int irq);
++static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp);
++static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp);
++static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp);
++static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp);
++
++static struct irq_controller amiga_irq_controller = {
++	.name		= "amiga",
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.enable		= amiga_enable_irq,
++	.disable	= amiga_disable_irq,
+ };
+-static const unsigned char ami_servers[AMI_STD_IRQS] = {
+-	[IRQ_AMIGA_VERTB]	= 1,
+-	[IRQ_AMIGA_PORTS]	= 1,
+-	[IRQ_AMIGA_EXTER]	= 1
+-};
+-
+-static short ami_ablecount[AMI_IRQS];
+-
+-static irqreturn_t ami_badint(int irq, void *dev_id, struct pt_regs *fp)
+-{
+-	num_spurious += 1;
+-	return IRQ_NONE;
+-}
+ 
+ /*
+  * void amiga_init_IRQ(void)
+@@ -103,23 +72,12 @@
+ 
+ void __init amiga_init_IRQ(void)
+ {
+-	int i;
++	request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL);
++	request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL);
++	request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL);
++	request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL);
+ 
+-	/* initialize handlers */
+-	for (i = 0; i < AMI_STD_IRQS; i++) {
+-		if (ami_servers[i]) {
+-			ami_irq_list[i] = NULL;
+-		} else {
+-			ami_irq_list[i] = new_irq_node();
+-			ami_irq_list[i]->handler = ami_badint;
+-			ami_irq_list[i]->flags   = 0;
+-			ami_irq_list[i]->dev_id  = NULL;
+-			ami_irq_list[i]->devname = NULL;
+-			ami_irq_list[i]->next    = NULL;
+-		}
+-	}
+-	for (i = 0; i < AMI_IRQS; i++)
+-		ami_ablecount[i] = 0;
++	m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
+ 
+ 	/* turn off PCMCIA interrupts */
+ 	if (AMIGAHW_PRESENT(PCMCIA))
+@@ -134,249 +92,21 @@
+ 	cia_init_IRQ(&ciab_base);
+ }
+ 
+-static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node)
+-{
+-	unsigned long flags;
+-	irq_node_t *cur;
+-
+-	if (!node->dev_id)
+-		printk("%s: Warning: dev_id of %s is zero\n",
+-		       __FUNCTION__, node->devname);
+-
+-	local_irq_save(flags);
+-
+-	cur = *list;
+-
+-	if (node->flags & SA_INTERRUPT) {
+-		if (node->flags & SA_SHIRQ)
+-			return -EBUSY;
+-		/*
+-		 * There should never be more than one
+-		 */
+-		while (cur && cur->flags & SA_INTERRUPT) {
+-			list = &cur->next;
+-			cur = cur->next;
+-		}
+-	} else {
+-		while (cur) {
+-			list = &cur->next;
+-			cur = cur->next;
+-		}
+-	}
+-
+-	node->next = cur;
+-	*list = node;
+-
+-	local_irq_restore(flags);
+-	return 0;
+-}
+-
+-static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
+-{
+-	unsigned long flags;
+-	irq_node_t *node;
+-
+-	local_irq_save(flags);
+-
+-	for (node = *list; node; list = &node->next, node = *list) {
+-		if (node->dev_id == dev_id) {
+-			*list = node->next;
+-			/* Mark it as free. */
+-			node->handler = NULL;
+-			local_irq_restore(flags);
+-			return;
+-		}
+-	}
+-	local_irq_restore(flags);
+-	printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
+-}
+-
+-/*
+- * amiga_request_irq : add an interrupt service routine for a particular
+- *                     machine specific interrupt source.
+- *                     If the addition was successful, it returns 0.
+- */
+-
+-int amiga_request_irq(unsigned int irq,
+-		      irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                      unsigned long flags, const char *devname, void *dev_id)
+-{
+-	irq_node_t *node;
+-	int error = 0;
+-
+-	if (irq >= AMI_IRQS) {
+-		printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__,
+-			irq, devname);
+-		return -ENXIO;
+-	}
+-
+-	if (irq >= IRQ_AMIGA_AUTO)
+-		return cpu_request_irq(irq - IRQ_AMIGA_AUTO, handler,
+-		                       flags, devname, dev_id);
+-
+-	if (irq >= IRQ_AMIGA_CIAB)
+-		return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB,
+-		                       handler, flags, devname, dev_id);
+-
+-	if (irq >= IRQ_AMIGA_CIAA)
+-		return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
+-		                       handler, flags, devname, dev_id);
+-
+-	/*
+-	 * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared,
+-	 * we could add a check here for the SA_SHIRQ flag but all drivers
+-	 * should be aware of sharing anyway.
+-	 */
+-	if (ami_servers[irq]) {
+-		if (!(node = new_irq_node()))
+-			return -ENOMEM;
+-		node->handler = handler;
+-		node->flags   = flags;
+-		node->dev_id  = dev_id;
+-		node->devname = devname;
+-		node->next    = NULL;
+-		error = amiga_insert_irq(&ami_irq_list[irq], node);
+-	} else {
+-		ami_irq_list[irq]->handler = handler;
+-		ami_irq_list[irq]->flags   = flags;
+-		ami_irq_list[irq]->dev_id  = dev_id;
+-		ami_irq_list[irq]->devname = devname;
+-	}
+-
+-	/* enable the interrupt */
+-	if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
+-		amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq];
+-
+-	return error;
+-}
+-
+-void amiga_free_irq(unsigned int irq, void *dev_id)
+-{
+-	if (irq >= AMI_IRQS) {
+-		printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+-		return;
+-	}
+-
+-	if (irq >= IRQ_AMIGA_AUTO)
+-		cpu_free_irq(irq - IRQ_AMIGA_AUTO, dev_id);
+-
+-	if (irq >= IRQ_AMIGA_CIAB) {
+-		cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id);
+-		return;
+-	}
+-
+-	if (irq >= IRQ_AMIGA_CIAA) {
+-		cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id);
+-		return;
+-	}
+-
+-	if (ami_servers[irq]) {
+-		amiga_delete_irq(&ami_irq_list[irq], dev_id);
+-		/* if server list empty, disable the interrupt */
+-		if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
+-			amiga_custom.intena = amiga_intena_vals[irq];
+-	} else {
+-		if (ami_irq_list[irq]->dev_id != dev_id)
+-			printk("%s: removing probably wrong IRQ %d from %s\n",
+-			       __FUNCTION__, irq, ami_irq_list[irq]->devname);
+-		ami_irq_list[irq]->handler = ami_badint;
+-		ami_irq_list[irq]->flags   = 0;
+-		ami_irq_list[irq]->dev_id  = NULL;
+-		ami_irq_list[irq]->devname = NULL;
+-		amiga_custom.intena = amiga_intena_vals[irq];
+-	}
+-}
+-
+ /*
+  * Enable/disable a particular machine specific interrupt source.
+  * Note that this may affect other interrupts in case of a shared interrupt.
+  * This function should only be called for a _very_ short time to change some
+  * internal data, that may not be changed by the interrupt at the same time.
+- * ami_(enable|disable)_irq calls may also be nested.
+  */
+ 
+-void amiga_enable_irq(unsigned int irq)
+-{
+-	if (irq >= AMI_IRQS) {
+-		printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+-		return;
+-	}
+-
+-	if (--ami_ablecount[irq])
+-		return;
+-
+-	/* No action for auto-vector interrupts */
+-	if (irq >= IRQ_AMIGA_AUTO){
+-		printk("%s: Trying to enable auto-vector IRQ %i\n",
+-		       __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+-		return;
+-	}
+-
+-	if (irq >= IRQ_AMIGA_CIAB) {
+-		cia_set_irq(&ciab_base, (1 << (irq - IRQ_AMIGA_CIAB)));
+-		cia_able_irq(&ciab_base, CIA_ICR_SETCLR |
+-		             (1 << (irq - IRQ_AMIGA_CIAB)));
+-		return;
+-	}
+-
+-	if (irq >= IRQ_AMIGA_CIAA) {
+-		cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA)));
+-		cia_able_irq(&ciaa_base, CIA_ICR_SETCLR |
+-		             (1 << (irq - IRQ_AMIGA_CIAA)));
+-		return;
+-	}
+-
+-	/* enable the interrupt */
+-	amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq];
+-}
+-
+-void amiga_disable_irq(unsigned int irq)
+-{
+-	if (irq >= AMI_IRQS) {
+-		printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+-		return;
+-	}
+-
+-	if (ami_ablecount[irq]++)
+-		return;
+-
+-	/* No action for auto-vector interrupts */
+-	if (irq >= IRQ_AMIGA_AUTO) {
+-		printk("%s: Trying to disable auto-vector IRQ %i\n",
+-		       __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+-		return;
+-	}
+-
+-	if (irq >= IRQ_AMIGA_CIAB) {
+-		cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
+-		return;
+-	}
+-
+-	if (irq >= IRQ_AMIGA_CIAA) {
+-		cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
+-		return;
+-	}
+-
+-	/* disable the interrupt */
+-	amiga_custom.intena = amiga_intena_vals[irq];
+-}
+-
+-inline void amiga_do_irq(int irq, struct pt_regs *fp)
++static void amiga_enable_irq(unsigned int irq)
+ {
+-	kstat_cpu(0).irqs[SYS_IRQS + irq]++;
+-	ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
++	amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER));
+ }
+ 
+-void amiga_do_irq_list(int irq, struct pt_regs *fp)
++static void amiga_disable_irq(unsigned int irq)
+ {
+-	irq_node_t *node;
+-
+-	kstat_cpu(0).irqs[SYS_IRQS + irq]++;
+-
+-	amiga_custom.intreq = amiga_intena_vals[irq];
+-
+-	for (node = ami_irq_list[irq]; node; node = node->next)
+-		node->handler(irq, node->dev_id, fp);
++	amiga_custom.intena = 1 << (irq - IRQ_USER);
+ }
+ 
+ /*
+@@ -390,19 +120,19 @@
+ 	/* if serial transmit buffer empty, interrupt */
+ 	if (ints & IF_TBE) {
+ 		amiga_custom.intreq = IF_TBE;
+-		amiga_do_irq(IRQ_AMIGA_TBE, fp);
++		m68k_handle_int(IRQ_AMIGA_TBE, fp);
+ 	}
+ 
+ 	/* if floppy disk transfer complete, interrupt */
+ 	if (ints & IF_DSKBLK) {
+ 		amiga_custom.intreq = IF_DSKBLK;
+-		amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
++		m68k_handle_int(IRQ_AMIGA_DSKBLK, fp);
+ 	}
+ 
+ 	/* if software interrupt set, interrupt */
+ 	if (ints & IF_SOFT) {
+ 		amiga_custom.intreq = IF_SOFT;
+-		amiga_do_irq(IRQ_AMIGA_SOFT, fp);
++		m68k_handle_int(IRQ_AMIGA_SOFT, fp);
+ 	}
+ 	return IRQ_HANDLED;
+ }
+@@ -414,18 +144,20 @@
+ 	/* if a blitter interrupt */
+ 	if (ints & IF_BLIT) {
+ 		amiga_custom.intreq = IF_BLIT;
+-		amiga_do_irq(IRQ_AMIGA_BLIT, fp);
++		m68k_handle_int(IRQ_AMIGA_BLIT, fp);
+ 	}
+ 
+ 	/* if a copper interrupt */
+ 	if (ints & IF_COPER) {
+ 		amiga_custom.intreq = IF_COPER;
+-		amiga_do_irq(IRQ_AMIGA_COPPER, fp);
++		m68k_handle_int(IRQ_AMIGA_COPPER, fp);
+ 	}
+ 
+ 	/* if a vertical blank interrupt */
+-	if (ints & IF_VERTB)
+-		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
++	if (ints & IF_VERTB) {
++		amiga_custom.intreq = IF_VERTB;
++		m68k_handle_int(IRQ_AMIGA_VERTB, fp);
++	}
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -436,25 +168,25 @@
+ 	/* if audio 0 interrupt */
+ 	if (ints & IF_AUD0) {
+ 		amiga_custom.intreq = IF_AUD0;
+-		amiga_do_irq(IRQ_AMIGA_AUD0, fp);
++		m68k_handle_int(IRQ_AMIGA_AUD0, fp);
+ 	}
+ 
+ 	/* if audio 1 interrupt */
+ 	if (ints & IF_AUD1) {
+ 		amiga_custom.intreq = IF_AUD1;
+-		amiga_do_irq(IRQ_AMIGA_AUD1, fp);
++		m68k_handle_int(IRQ_AMIGA_AUD1, fp);
+ 	}
+ 
+ 	/* if audio 2 interrupt */
+ 	if (ints & IF_AUD2) {
+ 		amiga_custom.intreq = IF_AUD2;
+-		amiga_do_irq(IRQ_AMIGA_AUD2, fp);
++		m68k_handle_int(IRQ_AMIGA_AUD2, fp);
+ 	}
+ 
+ 	/* if audio 3 interrupt */
+ 	if (ints & IF_AUD3) {
+ 		amiga_custom.intreq = IF_AUD3;
+-		amiga_do_irq(IRQ_AMIGA_AUD3, fp);
++		m68k_handle_int(IRQ_AMIGA_AUD3, fp);
+ 	}
+ 	return IRQ_HANDLED;
+ }
+@@ -466,55 +198,13 @@
+ 	/* if serial receive buffer full interrupt */
+ 	if (ints & IF_RBF) {
+ 		/* acknowledge of IF_RBF must be done by the serial interrupt */
+-		amiga_do_irq(IRQ_AMIGA_RBF, fp);
++		m68k_handle_int(IRQ_AMIGA_RBF, fp);
+ 	}
+ 
+ 	/* if a disk sync interrupt */
+ 	if (ints & IF_DSKSYN) {
+ 		amiga_custom.intreq = IF_DSKSYN;
+-		amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
++		m68k_handle_int(IRQ_AMIGA_DSKSYN, fp);
+ 	}
+ 	return IRQ_HANDLED;
+ }
+-
+-static irqreturn_t ami_int7(int irq, void *dev_id, struct pt_regs *fp)
+-{
+-	panic ("level 7 interrupt received\n");
+-}
+-
+-irqreturn_t (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+-	[0] = ami_badint,
+-	[1] = ami_int1,
+-	[2] = ami_badint,
+-	[3] = ami_int3,
+-	[4] = ami_int4,
+-	[5] = ami_int5,
+-	[6] = ami_badint,
+-	[7] = ami_int7
+-};
+-
+-int show_amiga_interrupts(struct seq_file *p, void *v)
+-{
+-	int i;
+-	irq_node_t *node;
+-
+-	for (i = 0; i < AMI_STD_IRQS; i++) {
+-		if (!(node = ami_irq_list[i]))
+-			continue;
+-		seq_printf(p, "ami  %2d: %10u ", i,
+-		               kstat_cpu(0).irqs[SYS_IRQS + i]);
+-		do {
+-			if (node->flags & SA_INTERRUPT)
+-				seq_puts(p, "F ");
+-			else
+-				seq_puts(p, "  ");
+-			seq_printf(p, "%s\n", node->devname);
+-			if ((node = node->next))
+-				seq_puts(p, "                    ");
+-		} while (node);
+-	}
+-
+-	cia_get_irq_list(&ciaa_base, p);
+-	cia_get_irq_list(&ciab_base, p);
+-	return 0;
+-}
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/amiga/cia.c linux-m68k/arch/m68k/amiga/cia.c
+--- linux-i386/arch/m68k/amiga/cia.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/amiga/cia.c	2006-04-11 16:32:18.000000000 +0200
+@@ -29,21 +29,18 @@
+ 	unsigned short int_mask;
+ 	int handler_irq, cia_irq, server_irq;
+ 	char *name;
+-	irq_handler_t irq_list[CIA_IRQS];
+ } ciaa_base = {
+ 	.cia		= &ciaa,
+ 	.int_mask	= IF_PORTS,
+-	.handler_irq	= IRQ_AMIGA_AUTO_2,
++	.handler_irq	= IRQ_AMIGA_PORTS,
+ 	.cia_irq	= IRQ_AMIGA_CIAA,
+-	.server_irq	= IRQ_AMIGA_PORTS,
+-	.name		= "CIAA handler"
++	.name		= "CIAA"
+ }, ciab_base = {
+ 	.cia		= &ciab,
+ 	.int_mask	= IF_EXTER,
+-	.handler_irq	= IRQ_AMIGA_AUTO_6,
++	.handler_irq	= IRQ_AMIGA_EXTER,
+ 	.cia_irq	= IRQ_AMIGA_CIAB,
+-	.server_irq	= IRQ_AMIGA_EXTER,
+-	.name		= "CIAB handler"
++	.name		= "CIAB"
+ };
+ 
+ /*
+@@ -66,13 +63,11 @@
+ 
+ /*
+  *  Enable or disable CIA interrupts, return old interrupt mask,
+- *  interrupts will only be enabled if a handler exists
+  */
+ 
+ unsigned char cia_able_irq(struct ciabase *base, unsigned char mask)
+ {
+-	unsigned char old, tmp;
+-	int i;
++	unsigned char old;
+ 
+ 	old = base->icr_mask;
+ 	base->icr_data |= base->cia->icr;
+@@ -82,99 +77,104 @@
+ 	else
+ 		base->icr_mask &= ~mask;
+ 	base->icr_mask &= CIA_ICR_ALL;
+-	for (i = 0, tmp = 1; i < CIA_IRQS; i++, tmp <<= 1) {
+-		if ((tmp & base->icr_mask) && !base->irq_list[i].handler) {
+-			base->icr_mask &= ~tmp;
+-			base->cia->icr = tmp;
+-		}
+-	}
+ 	if (base->icr_data & base->icr_mask)
+ 		amiga_custom.intreq = IF_SETCLR | base->int_mask;
+ 	return old;
+ }
+ 
+-int cia_request_irq(struct ciabase *base, unsigned int irq,
+-                    irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                    unsigned long flags, const char *devname, void *dev_id)
+-{
+-	unsigned char mask;
+-
+-	base->irq_list[irq].handler = handler;
+-	base->irq_list[irq].flags   = flags;
+-	base->irq_list[irq].dev_id  = dev_id;
+-	base->irq_list[irq].devname = devname;
+-
+-	/* enable the interrupt */
+-	mask = 1 << irq;
+-	cia_set_irq(base, mask);
+-	cia_able_irq(base, CIA_ICR_SETCLR | mask);
+-	return 0;
+-}
+-
+-void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id)
+-{
+-	if (base->irq_list[irq].dev_id != dev_id)
+-		printk("%s: removing probably wrong IRQ %i from %s\n",
+-		       __FUNCTION__, base->cia_irq + irq,
+-		       base->irq_list[irq].devname);
+-
+-	base->irq_list[irq].handler = NULL;
+-	base->irq_list[irq].flags   = 0;
+-
+-	cia_able_irq(base, 1 << irq);
+-}
+-
+ static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp)
+ {
+ 	struct ciabase *base = (struct ciabase *)dev_id;
+-	int mach_irq, i;
++	int mach_irq;
+ 	unsigned char ints;
+ 
+ 	mach_irq = base->cia_irq;
+-	irq = SYS_IRQS + mach_irq;
+ 	ints = cia_set_irq(base, CIA_ICR_ALL);
+ 	amiga_custom.intreq = base->int_mask;
+-	for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) {
+-		if (ints & 1) {
+-			kstat_cpu(0).irqs[irq]++;
+-			base->irq_list[i].handler(mach_irq, base->irq_list[i].dev_id, fp);
+-		}
+-		ints >>= 1;
++	for (; ints; mach_irq++, ints >>= 1) {
++		if (ints & 1)
++			m68k_handle_int(mach_irq, fp);
+ 	}
+-	amiga_do_irq_list(base->server_irq, fp);
+ 	return IRQ_HANDLED;
+ }
+ 
+-void __init cia_init_IRQ(struct ciabase *base)
++static void cia_enable_irq(unsigned int irq)
+ {
+-	int i;
++	unsigned char mask;
+ 
+-	/* init isr handlers */
+-	for (i = 0; i < CIA_IRQS; i++) {
+-		base->irq_list[i].handler = NULL;
+-		base->irq_list[i].flags   = 0;
++	if (irq >= IRQ_AMIGA_CIAB) {
++		mask = 1 << (irq - IRQ_AMIGA_CIAB);
++		cia_set_irq(&ciab_base, mask);
++		cia_able_irq(&ciab_base, CIA_ICR_SETCLR | mask);
++	} else {
++		mask = 1 << (irq - IRQ_AMIGA_CIAA);
++		cia_set_irq(&ciaa_base, mask);
++		cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | mask);
+ 	}
++}
+ 
+-	/* clear any pending interrupt and turn off all interrupts */
+-	cia_set_irq(base, CIA_ICR_ALL);
+-	cia_able_irq(base, CIA_ICR_ALL);
++static void cia_disable_irq(unsigned int irq)
++{
++	if (irq >= IRQ_AMIGA_CIAB)
++		cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
++	else
++		cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
++}
+ 
+-	/* install CIA handler */
+-	request_irq(base->handler_irq, cia_handler, 0, base->name, base);
++static struct irq_controller cia_irq_controller = {
++	.name		= "cia",
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.enable		= cia_enable_irq,
++	.disable	= cia_disable_irq,
++};
+ 
+-	amiga_custom.intena = IF_SETCLR | base->int_mask;
+-}
++/*
++ * Override auto irq 2 & 6 and use them as general chain
++ * for external interrupts, we link the CIA interrupt sources
++ * into this chain.
++ */
+ 
+-int cia_get_irq_list(struct ciabase *base, struct seq_file *p)
++static void auto_enable_irq(unsigned int irq)
+ {
+-	int i, j;
++	switch (irq) {
++	case IRQ_AUTO_2:
++		amiga_custom.intena = IF_SETCLR | IF_PORTS;
++		break;
++	case IRQ_AUTO_6:
++		amiga_custom.intena = IF_SETCLR | IF_EXTER;
++		break;
++	}
++}
+ 
+-	j = base->cia_irq;
+-	for (i = 0; i < CIA_IRQS; i++) {
+-		seq_printf(p, "cia  %2d: %10d ", j + i,
+-			       kstat_cpu(0).irqs[SYS_IRQS + j + i]);
+-		seq_puts(p, "  ");
+-		seq_printf(p, "%s\n", base->irq_list[i].devname);
++static void auto_disable_irq(unsigned int irq)
++{
++	switch (irq) {
++	case IRQ_AUTO_2:
++		amiga_custom.intena = IF_PORTS;
++		break;
++	case IRQ_AUTO_6:
++		amiga_custom.intena = IF_EXTER;
++		break;
+ 	}
+-	return 0;
++}
++
++static struct irq_controller auto_irq_controller = {
++	.name		= "auto",
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.enable		= auto_enable_irq,
++	.disable	= auto_disable_irq,
++};
++
++void __init cia_init_IRQ(struct ciabase *base)
++{
++	m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS);
++
++	/* clear any pending interrupt and turn off all interrupts */
++	cia_set_irq(base, CIA_ICR_ALL);
++	cia_able_irq(base, CIA_ICR_ALL);
++
++	/* override auto int and install CIA handler */
++	m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
++	m68k_irq_startup(base->handler_irq);
++	request_irq(base->handler_irq, cia_handler, SA_SHIRQ, base->name, base);
+ }
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/amiga/config.c linux-m68k/arch/m68k/amiga/config.c
+--- linux-i386/arch/m68k/amiga/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/amiga/config.c	2006-04-11 16:32:18.000000000 +0200
+@@ -87,17 +87,8 @@
+ static void amiga_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+ /* amiga specific irq functions */
+ extern void amiga_init_IRQ (void);
+-extern irqreturn_t (*amiga_default_handler[]) (int, void *, struct pt_regs *);
+-extern int amiga_request_irq (unsigned int irq,
+-			      irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                              unsigned long flags, const char *devname,
+-			      void *dev_id);
+-extern void amiga_free_irq (unsigned int irq, void *dev_id);
+-extern void amiga_enable_irq (unsigned int);
+-extern void amiga_disable_irq (unsigned int);
+ static void amiga_get_model(char *model);
+ static int amiga_get_hardware_list(char *buffer);
+-extern int show_amiga_interrupts (struct seq_file *, void *);
+ /* amiga specific timer functions */
+ static unsigned long amiga_gettimeoffset (void);
+ static int a3000_hwclk (int, struct rtc_time *);
+@@ -392,14 +383,8 @@
+ 
+   mach_sched_init      = amiga_sched_init;
+   mach_init_IRQ        = amiga_init_IRQ;
+-  mach_default_handler = &amiga_default_handler;
+-  mach_request_irq     = amiga_request_irq;
+-  mach_free_irq        = amiga_free_irq;
+-  enable_irq           = amiga_enable_irq;
+-  disable_irq          = amiga_disable_irq;
+   mach_get_model       = amiga_get_model;
+   mach_get_hardware_list = amiga_get_hardware_list;
+-  mach_get_irq_list    = show_amiga_interrupts;
+   mach_gettimeoffset   = amiga_gettimeoffset;
+   if (AMIGAHW_PRESENT(A3000_CLK)){
+     mach_hwclk         = a3000_hwclk;
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/apollo/config.c linux-m68k/arch/m68k/apollo/config.c
+--- linux-i386/arch/m68k/apollo/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/apollo/config.c	2006-01-28 23:52:25.000000000 +0100
+@@ -28,11 +28,6 @@
+ 
+ extern void dn_sched_init(irqreturn_t (*handler)(int,void *,struct pt_regs *));
+ extern void dn_init_IRQ(void);
+-extern int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+-extern void dn_free_irq(unsigned int irq, void *dev_id);
+-extern void dn_enable_irq(unsigned int);
+-extern void dn_disable_irq(unsigned int);
+-extern int show_dn_interrupts(struct seq_file *, void *);
+ extern unsigned long dn_gettimeoffset(void);
+ extern int dn_dummy_hwclk(int, struct rtc_time *);
+ extern int dn_dummy_set_clock_mmss(unsigned long);
+@@ -40,13 +35,11 @@
+ extern void dn_dummy_waitbut(void);
+ extern struct fb_info *dn_fb_init(long *);
+ extern void dn_dummy_debug_init(void);
+-extern void dn_dummy_video_setup(char *,int *);
+ extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp);
+ #ifdef CONFIG_HEARTBEAT
+ static void dn_heartbeat(int on);
+ #endif
+ static irqreturn_t dn_timer_int(int irq,void *, struct pt_regs *);
+-static irqreturn_t (*sched_timer_handler)(int, void *, struct pt_regs *)=NULL;
+ static void dn_get_model(char *model);
+ static const char *apollo_models[] = {
+ 	[APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)",
+@@ -164,17 +157,10 @@
+ 
+ 	mach_sched_init=dn_sched_init; /* */
+ 	mach_init_IRQ=dn_init_IRQ;
+-	mach_default_handler=NULL;
+-	mach_request_irq     = dn_request_irq;
+-	mach_free_irq        = dn_free_irq;
+-	enable_irq      = dn_enable_irq;
+-	disable_irq     = dn_disable_irq;
+-	mach_get_irq_list    = show_dn_interrupts;
+ 	mach_gettimeoffset   = dn_gettimeoffset;
+ 	mach_max_dma_address = 0xffffffff;
+ 	mach_hwclk           = dn_dummy_hwclk; /* */
+ 	mach_set_clock_mmss  = dn_dummy_set_clock_mmss; /* */
+-	mach_process_int     = dn_process_int;
+ 	mach_reset	     = dn_dummy_reset;  /* */
+ #ifdef CONFIG_HEARTBEAT
+ 	mach_heartbeat = dn_heartbeat;
+@@ -189,11 +175,13 @@
+ 
+ }
+ 
+-irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp) {
++irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp)
++{
++	irqreturn_t (*timer_handler)(int, void *, struct pt_regs *) = dev_id;
+ 
+ 	volatile unsigned char x;
+ 
+-	sched_timer_handler(irq,dev_id,fp);
++	timer_handler(irq, dev_id, fp);
+ 
+ 	x=*(volatile unsigned char *)(timer+3);
+ 	x=*(volatile unsigned char *)(timer+5);
+@@ -217,9 +205,7 @@
+ 	printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3));
+ #endif
+ 
+-	sched_timer_handler=timer_routine;
+-	request_irq(0,dn_timer_int,0,NULL,NULL);
+-
++	request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine);
+ }
+ 
+ unsigned long dn_gettimeoffset(void) {
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/apollo/dn_ints.c linux-m68k/arch/m68k/apollo/dn_ints.c
+--- linux-i386/arch/m68k/apollo/dn_ints.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/apollo/dn_ints.c	2006-01-28 23:52:25.000000000 +0100
+@@ -1,125 +1,44 @@
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/jiffies.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/timer.h>
++#include <linux/interrupt.h>
+ 
+-#include <asm/system.h>
+ #include <asm/irq.h>
+ #include <asm/traps.h>
+-#include <asm/page.h>
+-#include <asm/machdep.h>
+ #include <asm/apollohw.h>
+-#include <asm/errno.h>
+ 
+-static irq_handler_t dn_irqs[16];
+-
+-irqreturn_t dn_process_int(int irq, struct pt_regs *fp)
++void dn_process_int(unsigned int irq, struct pt_regs *fp)
+ {
+-  irqreturn_t res = IRQ_NONE;
+-
+-  if(dn_irqs[irq-160].handler) {
+-    res = dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp);
+-  } else {
+-    printk("spurious irq %d occurred\n",irq);
+-  }
+-
+-  *(volatile unsigned char *)(pica)=0x20;
+-  *(volatile unsigned char *)(picb)=0x20;
+-
+-  return res;
+-}
+-
+-void dn_init_IRQ(void) {
+-
+-  int i;
+-
+-  for(i=0;i<16;i++) {
+-    dn_irqs[i].handler=NULL;
+-    dn_irqs[i].flags=IRQ_FLG_STD;
+-    dn_irqs[i].dev_id=NULL;
+-    dn_irqs[i].devname=NULL;
+-  }
+-
+-}
+-
+-int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) {
+-
+-  if((irq<0) || (irq>15)) {
+-    printk("Trying to request invalid IRQ\n");
+-    return -ENXIO;
+-  }
+-
+-  if(!dn_irqs[irq].handler) {
+-    dn_irqs[irq].handler=handler;
+-    dn_irqs[irq].flags=IRQ_FLG_STD;
+-    dn_irqs[irq].dev_id=dev_id;
+-    dn_irqs[irq].devname=devname;
+-    if(irq<8)
+-      *(volatile unsigned char *)(pica+1)&=~(1<<irq);
+-    else
+-      *(volatile unsigned char *)(picb+1)&=~(1<<(irq-8));
+-
+-    return 0;
+-  }
+-  else {
+-    printk("Trying to request already assigned irq %d\n",irq);
+-    return -ENXIO;
+-  }
+-
+-}
+-
+-void dn_free_irq(unsigned int irq, void *dev_id) {
+-
+-  if((irq<0) || (irq>15)) {
+-    printk("Trying to free invalid IRQ\n");
+-    return ;
+-  }
+-
+-  if(irq<8)
+-    *(volatile unsigned char *)(pica+1)|=(1<<irq);
+-  else
+-    *(volatile unsigned char *)(picb+1)|=(1<<(irq-8));
+-
+-  dn_irqs[irq].handler=NULL;
+-  dn_irqs[irq].flags=IRQ_FLG_STD;
+-  dn_irqs[irq].dev_id=NULL;
+-  dn_irqs[irq].devname=NULL;
+-
+-  return ;
++	m68k_handle_int(irq, fp);
+ 
++	*(volatile unsigned char *)(pica)=0x20;
++	*(volatile unsigned char *)(picb)=0x20;
+ }
+ 
+-void dn_enable_irq(unsigned int irq) {
+-
+-  printk("dn enable irq\n");
+-
+-}
+-
+-void dn_disable_irq(unsigned int irq) {
+-
+-  printk("dn disable irq\n");
+-
+-}
+-
+-int show_dn_interrupts(struct seq_file *p, void *v) {
+-
+-  printk("dn get irq list\n");
+-
+-  return 0;
+-
++int apollo_irq_startup(unsigned int irq)
++{
++	if (irq < 8)
++		*(volatile unsigned char *)(pica+1) &= ~(1 << irq);
++	else
++		*(volatile unsigned char *)(picb+1) &= ~(1 << (irq - 8));
++	return 0;
+ }
+ 
+-struct fb_info *dn_dummy_fb_init(long *mem_start) {
+-
+-  printk("fb init\n");
+-
+-  return NULL;
+-
++void apollo_irq_shutdown(unsigned int irq)
++{
++	if (irq < 8)
++		*(volatile unsigned char *)(pica+1) |= (1 << irq);
++	else
++		*(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
+ }
+ 
+-void dn_dummy_video_setup(char *options,int *ints) {
++static struct irq_controller apollo_irq_controller = {
++	.name           = "apollo",
++	.lock           = SPIN_LOCK_UNLOCKED,
++	.startup        = apollo_irq_startup,
++	.shutdown       = apollo_irq_shutdown,
++};
+ 
+-  printk("no video yet\n");
+ 
++void dn_init_IRQ(void)
++{
++	m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int);
++	m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16);
+ }
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/atari/ataints.c linux-m68k/arch/m68k/atari/ataints.c
+--- linux-i386/arch/m68k/atari/ataints.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/atari/ataints.c	2006-01-28 23:52:25.000000000 +0100
+@@ -104,6 +104,7 @@
+  * the sr copy in the frame.
+  */
+ 
++#if 0
+ 
+ #define	NUM_INT_SOURCES	(8 + NUM_ATARI_SOURCES)
+ 
+@@ -133,13 +134,6 @@
+  */
+ static struct irqparam irq_param[NUM_INT_SOURCES];
+ 
+-/*
+- * Bitmap for free interrupt vector numbers
+- * (new vectors starting from 0x70 can be allocated by
+- * atari_register_vme_int())
+- */
+-static int free_vme_vec_bitmap;
+-
+ /* check for valid int number (complex, sigh...) */
+ #define	IS_VALID_INTNO(n)											\
+ 	((n) > 0 &&														\
+@@ -301,6 +295,14 @@
+ );
+ 	for (;;);
+ }
++#endif
++
++/*
++ * Bitmap for free interrupt vector numbers
++ * (new vectors starting from 0x70 can be allocated by
++ * atari_register_vme_int())
++ */
++static int free_vme_vec_bitmap;
+ 
+ /* GK:
+  * HBL IRQ handler for Falcon. Nobody needs it :-)
+@@ -313,13 +315,34 @@
+ 	"orw	#0x200,%sp@\n\t"	/* set saved ipl to 2 */
+ 	"rte");
+ 
+-/* Defined in entry.S; only increments 'num_spurious' */
+-asmlinkage void bad_interrupt(void);
+-
+-extern void atari_microwire_cmd( int cmd );
++extern void atari_microwire_cmd(int cmd);
+ 
+ extern int atari_SCC_reset_done;
+ 
++static int atari_startup_irq(unsigned int irq)
++{
++	m68k_irq_startup(irq);
++	atari_turnon_irq(irq);
++	atari_enable_irq(irq);
++	return 0;
++}
++
++static void atari_shutdown_irq(unsigned int irq)
++{
++	atari_disable_irq(irq);
++	atari_turnoff_irq(irq);
++	m68k_irq_shutdown(irq);
++}
++
++static struct irq_controller atari_irq_controller = {
++	.name		= "atari",
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.startup	= atari_startup_irq,
++	.shutdown	= atari_shutdown_irq,
++	.enable		= atari_enable_irq,
++	.disable	= atari_disable_irq,
++};
++
+ /*
+  * void atari_init_IRQ (void)
+  *
+@@ -333,12 +356,8 @@
+ 
+ void __init atari_init_IRQ(void)
+ {
+-	int i;
+-
+-	/* initialize the vector table */
+-	for (i = 0; i < NUM_INT_SOURCES; ++i) {
+-		vectors[IRQ_SOURCE_TO_VECTOR(i)] = bad_interrupt;
+-	}
++	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
++	m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
+ 
+ 	/* Initialize the MFP(s) */
+ 
+@@ -378,8 +397,7 @@
+ 									 * enabled in VME mask
+ 									 */
+ 		tt_scu.vme_mask = 0x60;		/* enable MFP and SCC ints */
+-	}
+-	else {
++	} else {
+ 		/* If no SCU and no Hades, the HSYNC interrupt needs to be
+ 		 * disabled this way. (Else _inthandler in kernel/sys_call.S
+ 		 * gets overruns)
+@@ -404,184 +422,6 @@
+ }
+ 
+ 
+-static irqreturn_t atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp )
+-{
+-	irq_node_t *node;
+-
+-	for (node = (irq_node_t *)dev_id; node; node = node->next)
+-		node->handler(irq, node->dev_id, fp);
+-	return IRQ_HANDLED;
+-}
+-
+-
+-/*
+- * atari_request_irq : add an interrupt service routine for a particular
+- *                     machine specific interrupt source.
+- *                     If the addition was successful, it returns 0.
+- */
+-
+-int atari_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                      unsigned long flags, const char *devname, void *dev_id)
+-{
+-	int vector;
+-	unsigned long oflags = flags;
+-
+-	/*
+-	 * The following is a hack to make some PCI card drivers work,
+-	 * which set the SA_SHIRQ flag.
+-	 */
+-
+-	flags &= ~SA_SHIRQ;
+-
+-	if (flags == SA_INTERRUPT) {
+-		printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n",
+-			__FUNCTION__, devname);
+-		flags = IRQ_TYPE_SLOW;
+-	}
+-	if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) {
+-		printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n",
+-		        __FUNCTION__, flags, oflags, devname);
+-		return -EINVAL;
+-	}
+-	if (!IS_VALID_INTNO(irq)) {
+-		printk ("%s: Unknown irq %d requested from %s\n",
+-		        __FUNCTION__, irq, devname);
+-		return -ENXIO;
+-	}
+-	vector = IRQ_SOURCE_TO_VECTOR(irq);
+-
+-	/*
+-	 * Check type/source combination: slow ints are (currently)
+-	 * only possible for MFP-interrupts.
+-	 */
+-	if (flags == IRQ_TYPE_SLOW &&
+-		(irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE)) {
+-		printk ("%s: Slow irq requested for non-MFP source %d from %s\n",
+-		        __FUNCTION__, irq, devname);
+-		return -EINVAL;
+-	}
+-
+-	if (vectors[vector] == bad_interrupt) {
+-		/* int has no handler yet */
+-		irq_handler[irq].handler = handler;
+-		irq_handler[irq].dev_id  = dev_id;
+-		irq_param[irq].flags   = flags;
+-		irq_param[irq].devname = devname;
+-		vectors[vector] =
+-			(flags == IRQ_TYPE_SLOW) ? slow_handlers[irq-STMFP_SOURCE_BASE] :
+-			(flags == IRQ_TYPE_FAST) ? atari_fast_irq_handler :
+-			                          atari_prio_irq_handler;
+-		/* If MFP int, also enable and umask it */
+-		atari_turnon_irq(irq);
+-		atari_enable_irq(irq);
+-
+-		return 0;
+-	}
+-	else if (irq_param[irq].flags == flags) {
+-		/* old handler is of same type -> handlers can be chained */
+-		irq_node_t *node;
+-		unsigned long flags;
+-
+-		local_irq_save(flags);
+-
+-		if (irq_handler[irq].handler != atari_call_irq_list) {
+-			/* Only one handler yet, make a node for this first one */
+-			if (!(node = new_irq_node()))
+-				return -ENOMEM;
+-			node->handler = irq_handler[irq].handler;
+-			node->dev_id  = irq_handler[irq].dev_id;
+-			node->devname = irq_param[irq].devname;
+-			node->next = NULL;
+-
+-			irq_handler[irq].handler = atari_call_irq_list;
+-			irq_handler[irq].dev_id  = node;
+-			irq_param[irq].devname   = "chained";
+-		}
+-
+-		if (!(node = new_irq_node()))
+-			return -ENOMEM;
+-		node->handler = handler;
+-		node->dev_id  = dev_id;
+-		node->devname = devname;
+-		/* new handlers are put in front of the queue */
+-		node->next = irq_handler[irq].dev_id;
+-		irq_handler[irq].dev_id = node;
+-
+-		local_irq_restore(flags);
+-		return 0;
+-	} else {
+-		printk ("%s: Irq %d allocated by other type int (call from %s)\n",
+-		        __FUNCTION__, irq, devname);
+-		return -EBUSY;
+-	}
+-}
+-
+-void atari_free_irq(unsigned int irq, void *dev_id)
+-{
+-	unsigned long flags;
+-	int vector;
+-	irq_node_t **list, *node;
+-
+-	if (!IS_VALID_INTNO(irq)) {
+-		printk("%s: Unknown irq %d\n", __FUNCTION__, irq);
+-		return;
+-	}
+-
+-	vector = IRQ_SOURCE_TO_VECTOR(irq);
+-	if (vectors[vector] == bad_interrupt)
+-		goto not_found;
+-
+-	local_irq_save(flags);
+-
+-	if (irq_handler[irq].handler != atari_call_irq_list) {
+-		/* It's the only handler for the interrupt */
+-		if (irq_handler[irq].dev_id != dev_id) {
+-			local_irq_restore(flags);
+-			goto not_found;
+-		}
+-		irq_handler[irq].handler = NULL;
+-		irq_handler[irq].dev_id  = NULL;
+-		irq_param[irq].devname   = NULL;
+-		vectors[vector] = bad_interrupt;
+-		/* If MFP int, also disable it */
+-		atari_disable_irq(irq);
+-		atari_turnoff_irq(irq);
+-
+-		local_irq_restore(flags);
+-		return;
+-	}
+-
+-	/* The interrupt is chained, find the irq on the list */
+-	for(list = (irq_node_t **)&irq_handler[irq].dev_id; *list; list = &(*list)->next) {
+-		if ((*list)->dev_id == dev_id) break;
+-	}
+-	if (!*list) {
+-		local_irq_restore(flags);
+-		goto not_found;
+-	}
+-
+-	(*list)->handler = NULL; /* Mark it as free for reallocation */
+-	*list = (*list)->next;
+-
+-	/* If there's now only one handler, unchain the interrupt, i.e. plug in
+-	 * the handler directly again and omit atari_call_irq_list */
+-	node = (irq_node_t *)irq_handler[irq].dev_id;
+-	if (node && !node->next) {
+-		irq_handler[irq].handler = node->handler;
+-		irq_handler[irq].dev_id  = node->dev_id;
+-		irq_param[irq].devname   = node->devname;
+-		node->handler = NULL; /* Mark it as free for reallocation */
+-	}
+-
+-	local_irq_restore(flags);
+-	return;
+-
+-not_found:
+-	printk("%s: tried to remove invalid irq\n", __FUNCTION__);
+-	return;
+-}
+-
+-
+ /*
+  * atari_register_vme_int() returns the number of a free interrupt vector for
+  * hardware with a programmable int vector (probably a VME board).
+@@ -591,58 +431,24 @@
+ {
+ 	int i;
+ 
+-	for(i = 0; i < 32; i++)
+-		if((free_vme_vec_bitmap & (1 << i)) == 0)
++	for (i = 0; i < 32; i++)
++		if ((free_vme_vec_bitmap & (1 << i)) == 0)
+ 			break;
+ 
+-	if(i == 16)
++	if (i == 16)
+ 		return 0;
+ 
+ 	free_vme_vec_bitmap |= 1 << i;
+-	return (VME_SOURCE_BASE + i);
++	return VME_SOURCE_BASE + i;
+ }
+ 
+ 
+ void atari_unregister_vme_int(unsigned long irq)
+ {
+-	if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
++	if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
+ 		irq -= VME_SOURCE_BASE;
+ 		free_vme_vec_bitmap &= ~(1 << irq);
+ 	}
+ }
+ 
+ 
+-int show_atari_interrupts(struct seq_file *p, void *v)
+-{
+-	int i;
+-
+-	for (i = 0; i < NUM_INT_SOURCES; ++i) {
+-		if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt)
+-			continue;
+-		if (i < STMFP_SOURCE_BASE)
+-			seq_printf(p, "auto %2d: %10u ",
+-				       i, kstat_cpu(0).irqs[i]);
+-		else
+-			seq_printf(p, "vec $%02x: %10u ",
+-				       IRQ_SOURCE_TO_VECTOR(i),
+-				       kstat_cpu(0).irqs[i]);
+-
+-		if (irq_handler[i].handler != atari_call_irq_list) {
+-			seq_printf(p, "%s\n", irq_param[i].devname);
+-		}
+-		else {
+-			irq_node_t *n;
+-			for( n = (irq_node_t *)irq_handler[i].dev_id; n; n = n->next ) {
+-				seq_printf(p, "%s\n", n->devname);
+-				if (n->next)
+-					seq_puts(p, "                    " );
+-			}
+-		}
+-	}
+-	if (num_spurious)
+-		seq_printf(p, "spurio.: %10u\n", num_spurious);
+-
+-	return 0;
+-}
+-
+-
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/atari/config.c linux-m68k/arch/m68k/atari/config.c
+--- linux-i386/arch/m68k/atari/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/atari/config.c	2006-04-11 16:32:18.000000000 +0200
+@@ -57,12 +57,6 @@
+ 
+ /* atari specific irq functions */
+ extern void atari_init_IRQ (void);
+-extern int atari_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                              unsigned long flags, const char *devname, void *dev_id);
+-extern void atari_free_irq (unsigned int irq, void *dev_id);
+-extern void atari_enable_irq (unsigned int);
+-extern void atari_disable_irq (unsigned int);
+-extern int show_atari_interrupts (struct seq_file *, void *);
+ extern void atari_mksound( unsigned int count, unsigned int ticks );
+ #ifdef CONFIG_HEARTBEAT
+ static void atari_heartbeat( int on );
+@@ -232,13 +226,8 @@
+ 
+     mach_sched_init      = atari_sched_init;
+     mach_init_IRQ        = atari_init_IRQ;
+-    mach_request_irq     = atari_request_irq;
+-    mach_free_irq        = atari_free_irq;
+-    enable_irq           = atari_enable_irq;
+-    disable_irq          = atari_disable_irq;
+     mach_get_model	 = atari_get_model;
+     mach_get_hardware_list = atari_get_hardware_list;
+-    mach_get_irq_list	 = show_atari_interrupts;
+     mach_gettimeoffset   = atari_gettimeoffset;
+     mach_reset           = atari_reset;
+     mach_max_dma_address = 0xffffff;
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/bvme6000/Makefile linux-m68k/arch/m68k/bvme6000/Makefile
+--- linux-i386/arch/m68k/bvme6000/Makefile	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/bvme6000/Makefile	2006-01-28 23:52:25.000000000 +0100
+@@ -2,4 +2,4 @@
+ # Makefile for Linux arch/m68k/bvme6000 source directory
+ #
+ 
+-obj-y		:= config.o bvmeints.o rtc.o
++obj-y		:= config.o rtc.o
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/bvme6000/config.c linux-m68k/arch/m68k/bvme6000/config.c
+--- linux-i386/arch/m68k/bvme6000/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/bvme6000/config.c	2006-01-28 23:52:25.000000000 +0100
+@@ -36,15 +36,8 @@
+ #include <asm/machdep.h>
+ #include <asm/bvme6000hw.h>
+ 
+-extern irqreturn_t bvme6000_process_int (int level, struct pt_regs *regs);
+-extern void bvme6000_init_IRQ (void);
+-extern void bvme6000_free_irq (unsigned int, void *);
+-extern int  show_bvme6000_interrupts(struct seq_file *, void *);
+-extern void bvme6000_enable_irq (unsigned int);
+-extern void bvme6000_disable_irq (unsigned int);
+ static void bvme6000_get_model(char *model);
+ static int  bvme6000_get_hardware_list(char *buffer);
+-extern int  bvme6000_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+ extern void bvme6000_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+ extern unsigned long bvme6000_gettimeoffset (void);
+ extern int bvme6000_hwclk (int, struct rtc_time *);
+@@ -100,6 +93,14 @@
+     return 0;
+ }
+ 
++/*
++ * This function is called during kernel startup to initialize
++ * the bvme6000 IRQ handling routines.
++ */
++static void bvme6000_init_IRQ(void)
++{
++	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
++}
+ 
+ void __init config_bvme6000(void)
+ {
+@@ -127,12 +128,6 @@
+     mach_hwclk           = bvme6000_hwclk;
+     mach_set_clock_mmss	 = bvme6000_set_clock_mmss;
+     mach_reset		 = bvme6000_reset;
+-    mach_free_irq	 = bvme6000_free_irq;
+-    mach_process_int	 = bvme6000_process_int;
+-    mach_get_irq_list	 = show_bvme6000_interrupts;
+-    mach_request_irq	 = bvme6000_request_irq;
+-    enable_irq		 = bvme6000_enable_irq;
+-    disable_irq          = bvme6000_disable_irq;
+     mach_get_model       = bvme6000_get_model;
+     mach_get_hardware_list = bvme6000_get_hardware_list;
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/hp300/Makefile linux-m68k/arch/m68k/hp300/Makefile
+--- linux-i386/arch/m68k/hp300/Makefile	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/hp300/Makefile	2006-01-28 23:52:26.000000000 +0100
+@@ -2,4 +2,4 @@
+ # Makefile for Linux arch/m68k/hp300 source directory
+ #
+ 
+-obj-y		:= ksyms.o config.o ints.o time.o reboot.o
++obj-y		:= ksyms.o config.o time.o reboot.o
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/hp300/config.c linux-m68k/arch/m68k/hp300/config.c
+--- linux-i386/arch/m68k/hp300/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/hp300/config.c	2006-01-28 23:52:26.000000000 +0100
+@@ -21,7 +21,6 @@
+ #include <asm/hp300hw.h>
+ #include <asm/rtc.h>
+ 
+-#include "ints.h"
+ #include "time.h"
+ 
+ unsigned long hp300_model;
+@@ -64,8 +63,6 @@
+ static char hp300_model_name[13] = "HP9000/";
+ 
+ extern void hp300_reset(void);
+-extern irqreturn_t (*hp300_default_handler[])(int, void *, struct pt_regs *);
+-extern int show_hp300_interrupts(struct seq_file *, void *);
+ #ifdef CONFIG_SERIAL_8250_CONSOLE
+ extern int hp300_setup_serial_console(void) __init;
+ #endif
+@@ -245,16 +242,16 @@
+ 		hp300_rtc_read(RTC_REG_SEC2);
+ }
+ 
++static void __init hp300_init_IRQ(void)
++{
++}
++
+ void __init config_hp300(void)
+ {
+ 	mach_sched_init      = hp300_sched_init;
+ 	mach_init_IRQ        = hp300_init_IRQ;
+-	mach_request_irq     = hp300_request_irq;
+-	mach_free_irq        = hp300_free_irq;
+ 	mach_get_model       = hp300_get_model;
+-	mach_get_irq_list    = show_hp300_interrupts;
+ 	mach_gettimeoffset   = hp300_gettimeoffset;
+-	mach_default_handler = &hp300_default_handler;
+ 	mach_hwclk	     = hp300_hwclk;
+ 	mach_get_ss	     = hp300_get_ss;
+ 	mach_reset           = hp300_reset;
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/hp300/time.c linux-m68k/arch/m68k/hp300/time.c
+--- linux-i386/arch/m68k/hp300/time.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/hp300/time.c	2006-01-28 23:52:26.000000000 +0100
+@@ -18,7 +18,6 @@
+ #include <asm/system.h>
+ #include <asm/traps.h>
+ #include <asm/blinken.h>
+-#include "ints.h"
+ 
+ /* Clock hardware definitions */
+ 
+@@ -71,7 +70,7 @@
+ 
+   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
+ 
+-  cpu_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
++  request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
+ 
+   out_8(CLOCKBASE + CLKCR2, 0x1);		/* select CR1 */
+   out_8(CLOCKBASE + CLKCR1, 0x40);		/* enable irq */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/kernel/bios32.c linux-m68k/arch/m68k/kernel/bios32.c
+--- linux-i386/arch/m68k/kernel/bios32.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/kernel/bios32.c	2004-10-20 01:06:39.000000000 +0200
+@@ -285,7 +285,7 @@
+ 
+ 	DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
+ 
+-	if (!bus->devices && !bus->children)
++	if (list_empty(&bus->devices) && list_empty(&bus->children))
+ 		return;
+ 
+ 	/*
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/kernel/entry.S linux-m68k/arch/m68k/kernel/entry.S
+--- linux-i386/arch/m68k/kernel/entry.S	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/kernel/entry.S	2006-02-12 16:31:29.000000000 +0100
+@@ -45,9 +45,11 @@
+ #include <asm/asm-offsets.h>
+ 
+ .globl system_call, buserr, trap, resume
+-.globl inthandler, sys_call_table
++.globl sys_call_table
+ .globl sys_fork, sys_clone, sys_vfork
+ .globl ret_from_interrupt, bad_interrupt
++.globl auto_irqhandler_fixup
++.globl user_irqvec_fixup, user_irqhandler_fixup
+ 
+ .text
+ ENTRY(buserr)
+@@ -191,65 +193,29 @@
+ 	jbra	resume_userspace
+ 
+ 
+-#if 0
+-#ifdef CONFIG_AMIGA
+-ami_inthandler:
+-	addql	#1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT
+-	SAVE_ALL_INT
+-	GET_CURRENT(%d0)
++/* This is the main interrupt handler for autovector interrupts */
+ 
+-	bfextu	%sp@(PT_VECTOR){#4,#12},%d0
+-	movel	%d0,%a0
+-	addql	#1,%a0@(kstat+STAT_IRQ-VECOFF(VEC_SPUR))
+-	movel	%a0@(autoirq_list-VECOFF(VEC_SPUR)),%a0
+-
+-| amiga vector int handler get the req mask instead of irq vector
+-	lea	CUSTOMBASE,%a1
+-	movew	%a1@(C_INTREQR),%d0
+-	andw	%a1@(C_INTENAR),%d0
+-
+-| prepare stack (push frame pointer, dev_id & req mask)
+-	pea	%sp@
+-	movel	%a0@(IRQ_DEVID),%sp at -
+-	movel	%d0,%sp at -
+-	pea	%pc@(ret_from_interrupt:w)
+-	jbra	@(IRQ_HANDLER,%a0)@(0)
+-
+-ENTRY(nmi_handler)
+-	rte
+-#endif
+-#endif
+-
+-/*
+-** This is the main interrupt handler, responsible for calling process_int()
+-*/
+-inthandler:
++ENTRY(auto_inthandler)
+ 	SAVE_ALL_INT
+ 	GET_CURRENT(%d0)
+-	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
++	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+ 					|  put exception # in d0
+-	bfextu %sp@(PT_VECTOR){#4,#10},%d0
++	bfextu	%sp@(PT_VECTOR){#4,#10},%d0
++	subw	#VEC_SPUR,%d0
+ 
+ 	movel	%sp,%sp at -
+ 	movel	%d0,%sp at -		|  put vector # on stack
+-#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
+-	btstb	#4,0xff000000		| Q40 floppy needs very special treatment ...
+-	jbeq	1f
+-	btstb	#3,0xff000004
+-	jbeq	1f
+-	jbsr	floppy_hardint
+-	jbra	3f
+-1:
+-#endif
+-	jbsr	process_int		|  process the IRQ
+-3:	addql	#8,%sp			|  pop parameters off stack
++auto_irqhandler_fixup = . + 2
++	jsr	m68k_handle_int		|  process the IRQ
++	addql	#8,%sp			|  pop parameters off stack
+ 
+ ret_from_interrupt:
+-	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
+-	jeq	1f
+-2:
+-	RESTORE_ALL
+-1:
++	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
++	jeq	ret_from_last_interrupt
++2:	RESTORE_ALL
++
++	ALIGN
++ret_from_last_interrupt:
+ 	moveq	#(~ALLOWINT>>8)&0xff,%d0
+ 	andb	%sp@(PT_SR),%d0
+ 	jne	2b
+@@ -260,12 +226,42 @@
+ 	pea	ret_from_exception
+ 	jra	do_softirq
+ 
++/* Handler for user defined interrupt vectors */
++
++ENTRY(user_inthandler)
++	SAVE_ALL_INT
++	GET_CURRENT(%d0)
++	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
++					|  put exception # in d0
++	bfextu	%sp@(PT_VECTOR){#4,#10},%d0
++user_irqvec_fixup = . + 2
++	subw	#VEC_USER,%d0
++
++	movel	%sp,%sp at -
++	movel	%d0,%sp at -		|  put vector # on stack
++user_irqhandler_fixup = . + 2
++	jsr	m68k_handle_int		|  process the IRQ
++	addql	#8,%sp			|  pop parameters off stack
++
++	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
++	jeq	ret_from_last_interrupt
++	RESTORE_ALL
+ 
+ /* Handler for uninitialized and spurious interrupts */
+ 
+-bad_interrupt:
+-	addql	#1,num_spurious
+-	rte
++ENTRY(bad_inthandler)
++	SAVE_ALL_INT
++	GET_CURRENT(%d0)
++	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
++
++	movel	%sp,%sp at -
++	jsr	handle_badint
++	addql	#4,%sp
++
++	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
++	jeq	ret_from_last_interrupt
++	RESTORE_ALL
++
+ 
+ ENTRY(sys_fork)
+ 	SAVE_SWITCH_STACK
+@@ -711,4 +707,9 @@
+ 	.long sys_add_key
+ 	.long sys_request_key	/* 280 */
+ 	.long sys_keyctl
++	.long sys_ioprio_set
++	.long sys_ioprio_get
++	.long sys_inotify_init
++	.long sys_inotify_add_watch	/* 285 */
++	.long sys_inotify_rm_watch
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/kernel/ints.c linux-m68k/arch/m68k/kernel/ints.c
+--- linux-i386/arch/m68k/kernel/ints.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/kernel/ints.c	2006-01-31 16:32:01.000000000 +0100
+@@ -39,47 +39,40 @@
+ #include <asm/traps.h>
+ #include <asm/page.h>
+ #include <asm/machdep.h>
++#include <asm/cacheflush.h>
+ 
+ #ifdef CONFIG_Q40
+ #include <asm/q40ints.h>
+ #endif
+ 
+-/* table for system interrupt handlers */
+-static irq_handler_t irq_list[SYS_IRQS];
++extern u32 auto_irqhandler_fixup[];
++extern u32 user_irqhandler_fixup[];
++extern u16 user_irqvec_fixup[];
+ 
+-static const char *default_names[SYS_IRQS] = {
+-	[0] = "spurious int",
+-	[1] = "int1 handler",
+-	[2] = "int2 handler",
+-	[3] = "int3 handler",
+-	[4] = "int4 handler",
+-	[5] = "int5 handler",
+-	[6] = "int6 handler",
+-	[7] = "int7 handler"
++/* table for system interrupt handlers */
++static struct irq_node *irq_list[NR_IRQS];
++static struct irq_controller *irq_controller[NR_IRQS];
++static int irq_depth[NR_IRQS];
++
++static int m68k_first_user_vec;
++
++static struct irq_controller auto_irq_controller = {
++	.name		= "auto",
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.startup	= m68k_irq_startup,
++	.shutdown	= m68k_irq_shutdown,
+ };
+ 
+-/* The number of spurious interrupts */
+-volatile unsigned int num_spurious;
++static struct irq_controller user_irq_controller = {
++	.name		= "user",
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.startup	= m68k_irq_startup,
++	.shutdown	= m68k_irq_shutdown,
++};
+ 
+ #define NUM_IRQ_NODES 100
+ static irq_node_t nodes[NUM_IRQ_NODES];
+ 
+-static void dummy_enable_irq(unsigned int irq);
+-static void dummy_disable_irq(unsigned int irq);
+-static int dummy_request_irq(unsigned int irq,
+-		irqreturn_t (*handler) (int, void *, struct pt_regs *),
+-		unsigned long flags, const char *devname, void *dev_id);
+-static void dummy_free_irq(unsigned int irq, void *dev_id);
+-
+-void (*enable_irq) (unsigned int) = dummy_enable_irq;
+-void (*disable_irq) (unsigned int) = dummy_disable_irq;
+-
+-int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *),
+-                      unsigned long, const char *, void *) = dummy_request_irq;
+-void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
+-
+-void init_irq_proc(void);
+-
+ /*
+  * void init_IRQ(void)
+  *
+@@ -95,18 +88,76 @@
+ {
+ 	int i;
+ 
+-	for (i = 0; i < SYS_IRQS; i++) {
+-		if (mach_default_handler)
+-			irq_list[i].handler = (*mach_default_handler)[i];
+-		irq_list[i].flags   = 0;
+-		irq_list[i].dev_id  = NULL;
+-		irq_list[i].devname = default_names[i];
++	/* assembly irq entry code relies on this... */
++	if (HARDIRQ_MASK != 0x00ff0000) {
++		extern void hardirq_mask_is_broken(void);
++		hardirq_mask_is_broken();
+ 	}
+ 
+-	for (i = 0; i < NUM_IRQ_NODES; i++)
+-		nodes[i].handler = NULL;
++	for (i = IRQ_AUTO_1; i < IRQ_USER; i++)
++		irq_controller[i] = &auto_irq_controller;
++
++	mach_init_IRQ();
++}
++
++/**
++ * m68k_setup_auto_interrupt
++ * @handler: called from auto vector interrupts
++ *
++ * setup the handler to be called from auto vector interrupts instead of the
++ * standard m68k_handle_int(), it will be called with irq numbers in the range
++ * from IRQ_AUTO_1 - IRQ_AUTO_7.
++ */
++void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
++{
++	if (handler)
++		*auto_irqhandler_fixup = (u32)handler;
++	flush_icache();
++}
++
++/**
++ * m68k_setup_user_interrupt
++ * @vec: first user vector interrupt to handle
++ * @cnt: number of active user vector interrupts
++ * @handler: called from user vector interrupts
++ *
++ * setup user vector interrupts, this includes activating the specified range
++ * of interrupts, only then these interrupts can be requested (note: this is
++ * different from auto vector interrupts). An optional handler can be installed
++ * to be called instead of the default m68k_handle_int(), it will be called
++ * with irq numbers starting from IRQ_USER.
++ */
++void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
++				      void (*handler)(unsigned int, struct pt_regs *))
++{
++	int i;
++
++	m68k_first_user_vec = vec;
++	for (i = 0; i < cnt; i++)
++		irq_controller[IRQ_USER + i] = &user_irq_controller;
++	*user_irqvec_fixup = vec - IRQ_USER;
++	if (handler)
++		*user_irqhandler_fixup = (u32)handler;
++	flush_icache();
++}
++
++/**
++ * m68k_setup_irq_controller
++ * @contr: irq controller which controls specified irq
++ * @irq: first irq to be managed by the controller
++ *
++ * Change the controller for the specified range of irq, which will be used to
++ * manage these irq. auto/user irq already have a default controller, which can
++ * be changed as well, but the controller probably should use m68k_irq_startup/
++ * m68k_irq_shutdown.
++ */
++void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
++			       unsigned int cnt)
++{
++	int i;
+ 
+-	mach_init_IRQ ();
++	for (i = 0; i < cnt; i++)
++		irq_controller[irq + i] = contr;
+ }
+ 
+ irq_node_t *new_irq_node(void)
+@@ -114,84 +165,183 @@
+ 	irq_node_t *node;
+ 	short i;
+ 
+-	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
+-		if (!node->handler)
++	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
++		if (!node->handler) {
++			memset(node, 0, sizeof(*node));
+ 			return node;
++		}
++	}
+ 
+ 	printk ("new_irq_node: out of nodes\n");
+ 	return NULL;
+ }
+ 
+-/*
+- * We will keep these functions until I have convinced Linus to move
+- * the declaration of them from include/linux/sched.h to
+- * include/asm/irq.h.
+- */
++int setup_irq(unsigned int irq, struct irq_node *node)
++{
++	struct irq_controller *contr;
++	struct irq_node **prev;
++	unsigned long flags;
++
++	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
++		printk("%s: Incorrect IRQ %d from %s\n",
++		       __FUNCTION__, irq, node->devname);
++		return -ENXIO;
++	}
++
++	spin_lock_irqsave(&contr->lock, flags);
++
++	prev = irq_list + irq;
++	if (*prev) {
++		/* Can't share interrupts unless both agree to */
++		if (!((*prev)->flags & node->flags & SA_SHIRQ)) {
++			spin_unlock_irqrestore(&contr->lock, flags);
++			return -EBUSY;
++		}
++		while (*prev)
++			prev = &(*prev)->next;
++	}
++
++	if (!irq_list[irq]) {
++		if (contr->startup)
++			contr->startup(irq);
++		else
++			contr->enable(irq);
++	}
++	node->next = NULL;
++	*prev = node;
++
++	spin_unlock_irqrestore(&contr->lock, flags);
++
++	return 0;
++}
++
+ int request_irq(unsigned int irq,
+ 		irqreturn_t (*handler) (int, void *, struct pt_regs *),
+ 		unsigned long flags, const char *devname, void *dev_id)
+ {
+-	return mach_request_irq(irq, handler, flags, devname, dev_id);
++	struct irq_node *node;
++	int res;
++
++	node = new_irq_node();
++	if (!node)
++		return -ENOMEM;
++
++	node->handler = handler;
++	node->flags   = flags;
++	node->dev_id  = dev_id;
++	node->devname = devname;
++
++	res = setup_irq(irq, node);
++	if (res)
++		node->handler = NULL;
++
++	return res;
+ }
+ 
+ EXPORT_SYMBOL(request_irq);
+ 
+ void free_irq(unsigned int irq, void *dev_id)
+ {
+-	mach_free_irq(irq, dev_id);
++	struct irq_controller *contr;
++	struct irq_node **p, *node;
++	unsigned long flags;
++
++	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
++		printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
++		return;
++	}
++
++	spin_lock_irqsave(&contr->lock, flags);
++
++	p = irq_list + irq;
++	while ((node = *p)) {
++		if (node->dev_id == dev_id)
++			break;
++		p = &node->next;
++	}
++
++	if (node) {
++		*p = node->next;
++		node->handler = NULL;
++	} else
++		printk("%s: Removing probably wrong IRQ %d\n",
++		       __FUNCTION__, irq);
++
++	if (!irq_list[irq]) {
++		if (contr->shutdown)
++			contr->shutdown(irq);
++		else
++			contr->disable(irq);
++	}
++
++	spin_unlock_irqrestore(&contr->lock, flags);
+ }
+ 
+ EXPORT_SYMBOL(free_irq);
+ 
+-int cpu_request_irq(unsigned int irq,
+-                    irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                    unsigned long flags, const char *devname, void *dev_id)
++void enable_irq(unsigned int irq)
+ {
+-	if (irq < IRQ1 || irq > IRQ7) {
+-		printk("%s: Incorrect IRQ %d from %s\n",
+-		       __FUNCTION__, irq, devname);
+-		return -ENXIO;
+-	}
++	struct irq_controller *contr;
++	unsigned long flags;
+ 
+-#if 0
+-	if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
+-		if (irq_list[irq].flags & IRQ_FLG_LOCK) {
+-			printk("%s: IRQ %d from %s is not replaceable\n",
+-			       __FUNCTION__, irq, 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, irq_list[irq].devname);
+-			return -EBUSY;
+-		}
++	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
++		printk("%s: Incorrect IRQ %d\n",
++		       __FUNCTION__, irq);
++		return;
+ 	}
+-#endif
+ 
+-	irq_list[irq].handler = handler;
+-	irq_list[irq].flags   = flags;
+-	irq_list[irq].dev_id  = dev_id;
+-	irq_list[irq].devname = devname;
+-	return 0;
++	spin_lock_irqsave(&contr->lock, flags);
++	if (irq_depth[irq]) {
++		if (!--irq_depth[irq]) {
++			if (contr->enable)
++				contr->enable(irq);
++		}
++	} else
++		WARN_ON(1);
++	spin_unlock_irqrestore(&contr->lock, flags);
+ }
+ 
+-void cpu_free_irq(unsigned int irq, void *dev_id)
++EXPORT_SYMBOL(enable_irq);
++
++void disable_irq(unsigned int irq)
+ {
+-	if (irq < IRQ1 || irq > IRQ7) {
+-		printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
++	struct irq_controller *contr;
++	unsigned long flags;
++
++	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
++		printk("%s: Incorrect IRQ %d\n",
++		       __FUNCTION__, irq);
+ 		return;
+ 	}
+ 
+-	if (irq_list[irq].dev_id != dev_id)
+-		printk("%s: Removing probably wrong IRQ %d from %s\n",
+-		       __FUNCTION__, irq, irq_list[irq].devname);
+-
+-	irq_list[irq].handler = (*mach_default_handler)[irq];
+-	irq_list[irq].flags   = 0;
+-	irq_list[irq].dev_id  = NULL;
+-	irq_list[irq].devname = default_names[irq];
++	spin_lock_irqsave(&contr->lock, flags);
++	if (!irq_depth[irq]++) {
++		if (contr->disable)
++			contr->disable(irq);
++	}
++	spin_unlock_irqrestore(&contr->lock, flags);
++}
++
++EXPORT_SYMBOL(disable_irq);
++
++int m68k_irq_startup(unsigned int irq)
++{
++	if (irq < IRQ_USER)
++		vectors[VEC_SPUR + irq] = auto_inthandler;
++	else
++		vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler;
++	return 0;
+ }
+ 
++void m68k_irq_shutdown(unsigned int irq)
++{
++	if (irq < IRQ_USER)
++		vectors[VEC_SPUR + irq] = bad_inthandler;
++	else
++		vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
++}
++
++
+ /*
+  * Do we need these probe functions on the m68k?
+  *
+@@ -219,58 +369,50 @@
+ 
+ EXPORT_SYMBOL(probe_irq_off);
+ 
+-static void dummy_enable_irq(unsigned int irq)
++unsigned int irq_canonicalize(unsigned int irq)
+ {
+-	printk("calling uninitialized enable_irq()\n");
++#ifdef CONFIG_Q40
++	if (MACH_IS_Q40 && irq == 11)
++		irq = 10;
++#endif
++	return irq;
+ }
+ 
+-static void dummy_disable_irq(unsigned int irq)
+-{
+-	printk("calling uninitialized disable_irq()\n");
+-}
++EXPORT_SYMBOL(irq_canonicalize);
+ 
+-static int dummy_request_irq(unsigned int irq,
+-		irqreturn_t (*handler) (int, void *, struct pt_regs *),
+-		unsigned long flags, const char *devname, void *dev_id)
++asmlinkage void m68k_handle_int(unsigned int irq, struct pt_regs *regs)
+ {
+-	printk("calling uninitialized request_irq()\n");
+-	return 0;
+-}
++	struct irq_node *node;
+ 
+-static void dummy_free_irq(unsigned int irq, void *dev_id)
+-{
+-	printk("calling uninitialized disable_irq()\n");
++	kstat_cpu(0).irqs[irq]++;
++	node = irq_list[irq];
++	do {
++		node->handler(irq, node->dev_id, regs);
++		node = node->next;
++	} while (node);
+ }
+ 
+-asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
++asmlinkage void handle_badint(struct pt_regs *regs)
+ {
+-	if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
+-		vec -= VEC_SPUR;
+-		kstat_cpu(0).irqs[vec]++;
+-		irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
+-	} else {
+-		if (mach_process_int)
+-			mach_process_int(vec, fp);
+-		else
+-			panic("Can't process interrupt vector %ld\n", vec);
+-		return;
+-	}
++	kstat_cpu(0).irqs[0]++;
++	printk("unexpected interrupt from %u\n", regs->vector);
+ }
+ 
+ int show_interrupts(struct seq_file *p, void *v)
+ {
++	struct irq_controller *contr;
++	struct irq_node *node;
+ 	int i = *(loff_t *) v;
+ 
+ 	/* autovector interrupts */
+-	if (i < SYS_IRQS) {
+-		if (mach_default_handler) {
+-			seq_printf(p, "auto %2d: %10u ", i,
+-			               i ? kstat_cpu(0).irqs[i] : num_spurious);
+-			seq_puts(p, "  ");
+-			seq_printf(p, "%s\n", irq_list[i].devname);
+-		}
+-	} else if (i == SYS_IRQS)
+-		mach_get_irq_list(p, v);
++	if (irq_list[i]) {
++		contr = irq_controller[i];
++		node = irq_list[i];
++		seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
++		while ((node = node->next))
++			seq_printf(p, ", %s", node->devname);
++		seq_puts(p, "\n");
++	}
+ 	return 0;
+ }
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/kernel/m68k_ksyms.c linux-m68k/arch/m68k/kernel/m68k_ksyms.c
+--- linux-i386/arch/m68k/kernel/m68k_ksyms.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/kernel/m68k_ksyms.c	2006-04-11 16:32:22.000000000 +0200
+@@ -58,8 +58,6 @@
+ EXPORT_SYMBOL(strrchr);
+ EXPORT_SYMBOL(strstr);
+ EXPORT_SYMBOL(strpbrk);
+-EXPORT_SYMBOL(enable_irq);
+-EXPORT_SYMBOL(disable_irq);
+ EXPORT_SYMBOL(kernel_thread);
+ #ifdef CONFIG_VME
+ EXPORT_SYMBOL(vme_brdtype);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/kernel/setup.c linux-m68k/arch/m68k/kernel/setup.c
+--- linux-i386/arch/m68k/kernel/setup.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/kernel/setup.c	2006-04-11 16:32:22.000000000 +0200
+@@ -68,11 +68,8 @@
+ void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
+ /* machine dependent irq functions */
+ void (*mach_init_IRQ) (void) __initdata = NULL;
+-irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
+ void (*mach_get_model) (char *model);
+ int (*mach_get_hardware_list) (char *buffer);
+-int (*mach_get_irq_list) (struct seq_file *, void *);
+-irqreturn_t (*mach_process_int) (int, struct pt_regs *);
+ /* machine dependent timer functions */
+ unsigned long (*mach_gettimeoffset) (void);
+ int (*mach_hwclk) (int, struct rtc_time*);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/kernel/traps.c linux-m68k/arch/m68k/kernel/traps.c
+--- linux-i386/arch/m68k/kernel/traps.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/kernel/traps.c	2006-04-11 16:32:22.000000000 +0200
+@@ -45,7 +45,6 @@
+ asmlinkage void system_call(void);
+ asmlinkage void buserr(void);
+ asmlinkage void trap(void);
+-asmlinkage void inthandler(void);
+ asmlinkage void nmihandler(void);
+ #ifdef CONFIG_M68KFPU_EMU
+ asmlinkage void fpu_emu(void);
+@@ -53,51 +52,7 @@
+ 
+ e_vector vectors[256] = {
+ 	[VEC_BUSERR]	= buserr,
+-	[VEC_ADDRERR]	= trap,
+-	[VEC_ILLEGAL]	= trap,
+-	[VEC_ZERODIV]	= trap,
+-	[VEC_CHK]	= trap,
+-	[VEC_TRAP]	= trap,
+-	[VEC_PRIV]	= trap,
+-	[VEC_TRACE]	= trap,
+-	[VEC_LINE10]	= trap,
+-	[VEC_LINE11]	= trap,
+-	[VEC_RESV12]	= trap,
+-	[VEC_COPROC]	= trap,
+-	[VEC_FORMAT]	= trap,
+-	[VEC_UNINT]	= trap,
+-	[VEC_RESV16]	= trap,
+-	[VEC_RESV17]	= trap,
+-	[VEC_RESV18]	= trap,
+-	[VEC_RESV19]	= trap,
+-	[VEC_RESV20]	= trap,
+-	[VEC_RESV21]	= trap,
+-	[VEC_RESV22]	= trap,
+-	[VEC_RESV23]	= trap,
+-	[VEC_SPUR]	= inthandler,
+-	[VEC_INT1]	= inthandler,
+-	[VEC_INT2]	= inthandler,
+-	[VEC_INT3]	= inthandler,
+-	[VEC_INT4]	= inthandler,
+-	[VEC_INT5]	= inthandler,
+-	[VEC_INT6]	= inthandler,
+-	[VEC_INT7]	= inthandler,
+ 	[VEC_SYS]	= system_call,
+-	[VEC_TRAP1]	= trap,
+-	[VEC_TRAP2]	= trap,
+-	[VEC_TRAP3]	= trap,
+-	[VEC_TRAP4]	= trap,
+-	[VEC_TRAP5]	= trap,
+-	[VEC_TRAP6]	= trap,
+-	[VEC_TRAP7]	= trap,
+-	[VEC_TRAP8]	= trap,
+-	[VEC_TRAP9]	= trap,
+-	[VEC_TRAP10]	= trap,
+-	[VEC_TRAP11]	= trap,
+-	[VEC_TRAP12]	= trap,
+-	[VEC_TRAP13]	= trap,
+-	[VEC_TRAP14]	= trap,
+-	[VEC_TRAP15]	= trap,
+ };
+ 
+ /* nmi handler for the Amiga */
+@@ -132,12 +87,15 @@
+ {
+ 	int i;
+ 
+-	for (i = 48; i < 64; i++)
++	for (i = VEC_SPUR; i <= VEC_INT7; i++)
++		vectors[i] = bad_inthandler;
++
++	for (i = 0; i < VEC_USER; i++)
+ 		if (!vectors[i])
+ 			vectors[i] = trap;
+ 
+-	for (i = 64; i < 256; i++)
+-		vectors[i] = inthandler;
++	for (i = VEC_USER; i < 256; i++)
++		vectors[i] = bad_inthandler;
+ 
+ #ifdef CONFIG_M68KFPU_EMU
+ 	if (FPU_IS_EMU)
+@@ -992,6 +950,7 @@
+ 
+ void show_stack(struct task_struct *task, unsigned long *stack)
+ {
++	unsigned long *p;
+ 	unsigned long *endstack;
+ 	int i;
+ 
+@@ -1004,12 +963,13 @@
+ 	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
+ 
+ 	printk("Stack from %08lx:", (unsigned long)stack);
++	p = stack;
+ 	for (i = 0; i < kstack_depth_to_print; i++) {
+-		if (stack + 1 > endstack)
++		if (p + 1 > endstack)
+ 			break;
+ 		if (i % 8 == 0)
+ 			printk("\n       ");
+-		printk(" %08lx", *stack++);
++		printk(" %08lx", *p++);
+ 	}
+ 	printk("\n");
+ 	show_trace(stack);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mac/baboon.c linux-m68k/arch/m68k/mac/baboon.c
+--- linux-i386/arch/m68k/mac/baboon.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mac/baboon.c	2006-01-28 23:52:27.000000000 +0100
+@@ -81,7 +81,7 @@
+ 	for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
+ 	        if (events & irq_bit/* & baboon_active*/) {
+ 			baboon_active &= ~irq_bit;
+-			mac_do_irq_list(IRQ_BABOON_0 + i, regs);
++			m68k_handle_int(IRQ_BABOON_0 + i, regs);
+ 			baboon_active |= irq_bit;
+ 			baboon->mb_ifr &= ~irq_bit;
+ 		}
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mac/config.c linux-m68k/arch/m68k/mac/config.c
+--- linux-i386/arch/m68k/mac/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mac/config.c	2006-01-28 23:52:27.000000000 +0100
+@@ -107,20 +107,6 @@
+ }
+ #endif
+ 
+-extern irqreturn_t mac_default_handler(int, void *, struct pt_regs *);
+-
+-irqreturn_t (*mac_handlers[8])(int, void *, struct pt_regs *)=
+-{
+-	mac_default_handler,
+-	mac_default_handler,
+-	mac_default_handler,
+-	mac_default_handler,
+-	mac_default_handler,
+-	mac_default_handler,
+-	mac_default_handler,
+-	mac_default_handler
+-};
+-
+ /*
+  * Parse a Macintosh-specific record in the bootinfo
+  */
+@@ -196,13 +182,7 @@
+ 
+ 	mach_sched_init      = mac_sched_init;
+ 	mach_init_IRQ        = mac_init_IRQ;
+-	mach_request_irq     = mac_request_irq;
+-	mach_free_irq        = mac_free_irq;
+-	enable_irq           = mac_enable_irq;
+-	disable_irq          = mac_disable_irq;
+ 	mach_get_model	 = mac_get_model;
+-	mach_default_handler = &mac_handlers;
+-	mach_get_irq_list    = show_mac_interrupts;
+ 	mach_gettimeoffset   = mac_gettimeoffset;
+ #warning move to adb/via init
+ #if 0
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mac/iop.c linux-m68k/arch/m68k/mac/iop.c
+--- linux-i386/arch/m68k/mac/iop.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mac/iop.c	2006-04-11 16:32:23.000000000 +0200
+@@ -317,7 +317,7 @@
+ {
+ 	if (iop_ism_present) {
+ 		if (oss_present) {
+-			cpu_request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
++			request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
+ 					IRQ_FLG_LOCK, "ISM IOP",
+ 					(void *) IOP_NUM_ISM);
+ 			oss_irq_enable(IRQ_MAC_ADB);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mac/macints.c linux-m68k/arch/m68k/mac/macints.c
+--- linux-i386/arch/m68k/mac/macints.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mac/macints.c	2006-01-28 23:52:27.000000000 +0100
+@@ -137,14 +137,6 @@
+ #define DEBUG_SPURIOUS
+ #define SHUTUP_SONIC
+ 
+-/*
+- * The mac_irq_list array is an array of linked lists of irq_node_t nodes.
+- * Each node contains one handler to be called whenever the interrupt
+- * occurs, with fast handlers listed before slow handlers.
+- */
+-
+-irq_node_t *mac_irq_list[NUM_MAC_SOURCES];
+-
+ /* SCC interrupt mask */
+ 
+ static int scc_mask;
+@@ -209,8 +201,8 @@
+  * SCC interrupt routines
+  */
+ 
+-static void scc_irq_enable(int);
+-static void scc_irq_disable(int);
++static void scc_irq_enable(unsigned int);
++static void scc_irq_disable(unsigned int);
+ 
+ /*
+  * console_loglevel determines NMI handler function
+@@ -222,21 +214,25 @@
+ 
+ /* #define DEBUG_MACINTS */
+ 
++static void mac_enable_irq(unsigned int irq);
++static void mac_disable_irq(unsigned int irq);
++
++static struct irq_controller mac_irq_controller = {
++	.name		= "mac",
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.enable		= mac_enable_irq,
++	.disable	= mac_disable_irq,
++};
++
+ void mac_init_IRQ(void)
+ {
+-        int i;
+-
+ #ifdef DEBUG_MACINTS
+ 	printk("mac_init_IRQ(): Setting things up...\n");
+ #endif
+-	/* Initialize the IRQ handler lists. Initially each list is empty, */
+-
+-	for (i = 0; i < NUM_MAC_SOURCES; i++) {
+-		mac_irq_list[i] = NULL;
+-	}
+-
+ 	scc_mask = 0;
+ 
++	m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER,
++				  NUM_MAC_SOURCES - IRQ_USER);
+ 	/* Make sure the SONIC interrupt is cleared or things get ugly */
+ #ifdef SHUTUP_SONIC
+ 	printk("Killing onboard sonic... ");
+@@ -253,15 +249,16 @@
+ 	 * at levels 1-7. Most of the work is done elsewhere.
+ 	 */
+ 
+-	if (oss_present) {
++	if (oss_present)
+ 		oss_register_interrupts();
+-	} else {
++	else
+ 		via_register_interrupts();
+-	}
+-	if (psc_present) psc_register_interrupts();
+-	if (baboon_present) baboon_register_interrupts();
++	if (psc_present)
++		psc_register_interrupts();
++	if (baboon_present)
++		baboon_register_interrupts();
+ 	iop_register_interrupts();
+-	cpu_request_irq(7, mac_nmi_handler, IRQ_FLG_LOCK, "NMI",
++	request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
+ 			mac_nmi_handler);
+ #ifdef DEBUG_MACINTS
+ 	printk("mac_init_IRQ(): Done!\n");
+@@ -269,104 +266,6 @@
+ }
+ 
+ /*
+- * Routines to work with irq_node_t's on linked lists lifted from
+- * the Amiga code written by Roman Zippel.
+- */
+-
+-static inline void mac_insert_irq(irq_node_t **list, irq_node_t *node)
+-{
+-	unsigned long flags;
+-	irq_node_t *cur;
+-
+-	if (!node->dev_id)
+-		printk("%s: Warning: dev_id of %s is zero\n",
+-		       __FUNCTION__, node->devname);
+-
+-	local_irq_save(flags);
+-
+-	cur = *list;
+-
+-	if (node->flags & IRQ_FLG_FAST) {
+-		node->flags &= ~IRQ_FLG_SLOW;
+-		while (cur && cur->flags & IRQ_FLG_FAST) {
+-			list = &cur->next;
+-			cur = cur->next;
+-		}
+-	} else if (node->flags & IRQ_FLG_SLOW) {
+-		while (cur) {
+-			list = &cur->next;
+-			cur = cur->next;
+-		}
+-	} else {
+-		while (cur && !(cur->flags & IRQ_FLG_SLOW)) {
+-			list = &cur->next;
+-			cur = cur->next;
+-		}
+-	}
+-
+-	node->next = cur;
+-	*list = node;
+-
+-	local_irq_restore(flags);
+-}
+-
+-static inline void mac_delete_irq(irq_node_t **list, void *dev_id)
+-{
+-	unsigned long flags;
+-	irq_node_t *node;
+-
+-	local_irq_save(flags);
+-
+-	for (node = *list; node; list = &node->next, node = *list) {
+-		if (node->dev_id == dev_id) {
+-			*list = node->next;
+-			/* Mark it as free. */
+-			node->handler = NULL;
+-			local_irq_restore(flags);
+-			return;
+-		}
+-	}
+-	local_irq_restore(flags);
+-	printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
+-}
+-
+-/*
+- * Call all the handlers for a given interrupt. Fast handlers are called
+- * first followed by slow handlers.
+- *
+- * This code taken from the original Amiga code written by Roman Zippel.
+- */
+-
+-void mac_do_irq_list(int irq, struct pt_regs *fp)
+-{
+-	irq_node_t *node, *slow_nodes;
+-	unsigned long flags;
+-
+-	kstat_cpu(0).irqs[irq]++;
+-
+-#ifdef DEBUG_SPURIOUS
+-	if (!mac_irq_list[irq] && (console_loglevel > 7)) {
+-		printk("mac_do_irq_list: spurious interrupt %d!\n", irq);
+-		return;
+-	}
+-#endif
+-
+-	/* serve first fast and normal handlers */
+-	for (node = mac_irq_list[irq];
+-	     node && (!(node->flags & IRQ_FLG_SLOW));
+-	     node = node->next)
+-		node->handler(irq, node->dev_id, fp);
+-	if (!node) return;
+-	local_save_flags(flags);
+-	local_irq_restore((flags & ~0x0700) | (fp->sr & 0x0700));
+-	/* if slow handlers exists, serve them now */
+-	slow_nodes = node;
+-	for (; node; node = node->next) {
+-		node->handler(irq, node->dev_id, fp);
+-	}
+-}
+-
+-/*
+  *  mac_enable_irq - enable an interrupt source
+  * mac_disable_irq - disable an interrupt source
+  *   mac_clear_irq - clears a pending interrupt
+@@ -375,276 +274,124 @@
+  * These routines are just dispatchers to the VIA/OSS/PSC routines.
+  */
+ 
+-void mac_enable_irq (unsigned int irq)
++static void mac_enable_irq(unsigned int irq)
+ {
+-	int irq_src	= IRQ_SRC(irq);
++	int irq_src = IRQ_SRC(irq);
+ 
+ 	switch(irq_src) {
+-		case 1: via_irq_enable(irq);
+-			break;
+-		case 2:
+-		case 7: if (oss_present) {
+-				oss_irq_enable(irq);
+-			} else {
+-				via_irq_enable(irq);
+-			}
+-			break;
+-		case 3:
+-		case 4:
+-		case 5:
+-		case 6: if (psc_present) {
+-				psc_irq_enable(irq);
+-			} else if (oss_present) {
+-				oss_irq_enable(irq);
+-			} else if (irq_src == 4) {
+-				scc_irq_enable(irq);
+-			}
+-			break;
+-		case 8: if (baboon_present) {
+-				baboon_irq_enable(irq);
+-			}
+-			break;
++	case 1:
++		via_irq_enable(irq);
++		break;
++	case 2:
++	case 7:
++		if (oss_present)
++			oss_irq_enable(irq);
++		else
++			via_irq_enable(irq);
++		break;
++	case 3:
++	case 4:
++	case 5:
++	case 6:
++		if (psc_present)
++			psc_irq_enable(irq);
++		else if (oss_present)
++			oss_irq_enable(irq);
++		else if (irq_src == 4)
++			scc_irq_enable(irq);
++		break;
++	case 8:
++		if (baboon_present)
++			baboon_irq_enable(irq);
++		break;
+ 	}
+ }
+ 
+-void mac_disable_irq (unsigned int irq)
++static void mac_disable_irq(unsigned int irq)
+ {
+-	int irq_src	= IRQ_SRC(irq);
++	int irq_src = IRQ_SRC(irq);
+ 
+ 	switch(irq_src) {
+-		case 1: via_irq_disable(irq);
+-			break;
+-		case 2:
+-		case 7: if (oss_present) {
+-				oss_irq_disable(irq);
+-			} else {
+-				via_irq_disable(irq);
+-			}
+-			break;
+-		case 3:
+-		case 4:
+-		case 5:
+-		case 6: if (psc_present) {
+-				psc_irq_disable(irq);
+-			} else if (oss_present) {
+-				oss_irq_disable(irq);
+-			} else if (irq_src == 4) {
+-				scc_irq_disable(irq);
+-			}
+-			break;
+-		case 8: if (baboon_present) {
+-				baboon_irq_disable(irq);
+-			}
+-			break;
++	case 1:
++		via_irq_disable(irq);
++		break;
++	case 2:
++	case 7:
++		if (oss_present)
++			oss_irq_disable(irq);
++		else
++			via_irq_disable(irq);
++		break;
++	case 3:
++	case 4:
++	case 5:
++	case 6:
++		if (psc_present)
++			psc_irq_disable(irq);
++		else if (oss_present)
++			oss_irq_disable(irq);
++		else if (irq_src == 4)
++			scc_irq_disable(irq);
++		break;
++	case 8:
++		if (baboon_present)
++			baboon_irq_disable(irq);
++		break;
+ 	}
+ }
+ 
+-void mac_clear_irq( unsigned int irq )
++void mac_clear_irq(unsigned int irq)
+ {
+ 	switch(IRQ_SRC(irq)) {
+-		case 1: via_irq_clear(irq);
+-			break;
+-		case 2:
+-		case 7: if (oss_present) {
+-				oss_irq_clear(irq);
+-			} else {
+-				via_irq_clear(irq);
+-			}
+-			break;
+-		case 3:
+-		case 4:
+-		case 5:
+-		case 6: if (psc_present) {
+-				psc_irq_clear(irq);
+-			} else if (oss_present) {
+-				oss_irq_clear(irq);
+-			}
+-			break;
+-		case 8: if (baboon_present) {
+-				baboon_irq_clear(irq);
+-			}
+-			break;
++	case 1:
++		via_irq_clear(irq);
++		break;
++	case 2:
++	case 7:
++		if (oss_present)
++			oss_irq_clear(irq);
++		else
++			via_irq_clear(irq);
++		break;
++	case 3:
++	case 4:
++	case 5:
++	case 6:
++		if (psc_present)
++			psc_irq_clear(irq);
++		else if (oss_present)
++			oss_irq_clear(irq);
++		break;
++	case 8:
++		if (baboon_present)
++			baboon_irq_clear(irq);
++		break;
+ 	}
+ }
+ 
+-int mac_irq_pending( unsigned int irq )
++int mac_irq_pending(unsigned int irq)
+ {
+ 	switch(IRQ_SRC(irq)) {
+-		case 1: return via_irq_pending(irq);
+-		case 2:
+-		case 7: if (oss_present) {
+-				return oss_irq_pending(irq);
+-			} else {
+-				return via_irq_pending(irq);
+-			}
+-		case 3:
+-		case 4:
+-		case 5:
+-		case 6: if (psc_present) {
+-				return psc_irq_pending(irq);
+-			} else if (oss_present) {
+-				return oss_irq_pending(irq);
+-			}
+-	}
+-	return 0;
+-}
+-
+-/*
+- * Add an interrupt service routine to an interrupt source.
+- * Returns 0 on success.
+- *
+- * FIXME: You can register interrupts on nonexistent source (ie PSC4 on a
+- *        non-PSC machine). We should return -EINVAL in those cases.
+- */
+-
+-int mac_request_irq(unsigned int irq,
+-		    irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-		    unsigned long flags, const char *devname, void *dev_id)
+-{
+-	irq_node_t *node;
+-
+-#ifdef DEBUG_MACINTS
+-	printk ("%s: irq %d requested for %s\n", __FUNCTION__, irq, devname);
+-#endif
+-
+-	if (irq < VIA1_SOURCE_BASE) {
+-		return cpu_request_irq(irq, handler, flags, devname, dev_id);
++	case 1:
++		return via_irq_pending(irq);
++	case 2:
++	case 7:
++		if (oss_present)
++			return oss_irq_pending(irq);
++		else
++			return via_irq_pending(irq);
++	case 3:
++	case 4:
++	case 5:
++	case 6:
++		if (psc_present)
++			return psc_irq_pending(irq);
++		else if (oss_present)
++			return oss_irq_pending(irq);
+ 	}
+-
+-	if (irq >= NUM_MAC_SOURCES) {
+-		printk ("%s: unknown irq %d requested by %s\n",
+-		        __FUNCTION__, irq, devname);
+-	}
+-
+-	/* Get a node and stick it onto the right list */
+-
+-	if (!(node = new_irq_node())) return -ENOMEM;
+-
+-	node->handler	= handler;
+-	node->flags	= flags;
+-	node->dev_id	= dev_id;
+-	node->devname	= devname;
+-	node->next	= NULL;
+-	mac_insert_irq(&mac_irq_list[irq], node);
+-
+-	/* Now enable the IRQ source */
+-
+-	mac_enable_irq(irq);
+-
+ 	return 0;
+ }
+ 
+-/*
+- * Removes an interrupt service routine from an interrupt source.
+- */
+-
+-void mac_free_irq(unsigned int irq, void *dev_id)
+-{
+-#ifdef DEBUG_MACINTS
+-	printk ("%s: irq %d freed by %p\n", __FUNCTION__, irq, dev_id);
+-#endif
+-
+-	if (irq < VIA1_SOURCE_BASE) {
+-		cpu_free_irq(irq, dev_id);
+-		return;
+-	}
+-
+-	if (irq >= NUM_MAC_SOURCES) {
+-		printk ("%s: unknown irq %d freed\n",
+-		        __FUNCTION__, irq);
+-		return;
+-	}
+-
+-	mac_delete_irq(&mac_irq_list[irq], dev_id);
+-
+-	/* If the list for this interrupt is */
+-	/* empty then disable the source.    */
+-
+-	if (!mac_irq_list[irq]) {
+-		mac_disable_irq(irq);
+-	}
+-}
+-
+-/*
+- * Generate a pretty listing for /proc/interrupts
+- *
+- * By the time we're called the autovector interrupt list has already been
+- * generated, so we just need to do the machspec interrupts.
+- *
+- * 990506 (jmt) - rewritten to handle chained machspec interrupt handlers.
+- *                Also removed display of num_spurious it is already
+- *		  displayed for us as autovector irq 0.
+- */
+-
+-int show_mac_interrupts(struct seq_file *p, void *v)
+-{
+-	int i;
+-	irq_node_t *node;
+-	char *base;
+-
+-	/* Don't do Nubus interrupts in this loop; we do them separately  */
+-	/* below so that we can print slot numbers instead of IRQ numbers */
+-
+-	for (i = VIA1_SOURCE_BASE ; i < NUM_MAC_SOURCES ; ++i) {
+-
+-		/* Nonexistant interrupt or nothing registered; skip it. */
+-
+-		if ((node = mac_irq_list[i]) == NULL) continue;
+-		if (node->flags & IRQ_FLG_STD) continue;
+-
+-		base = "";
+-		switch(IRQ_SRC(i)) {
+-			case 1: base = "via1";
+-				break;
+-			case 2: if (oss_present) {
+-					base = "oss";
+-				} else {
+-					base = "via2";
+-				}
+-				break;
+-			case 3:
+-			case 4:
+-			case 5:
+-			case 6: if (psc_present) {
+-					base = "psc";
+-				} else if (oss_present) {
+-					base = "oss";
+-				} else {
+-					if (IRQ_SRC(i) == 4) base = "scc";
+-				}
+-				break;
+-			case 7: base = "nbus";
+-				break;
+-			case 8: base = "bbn";
+-				break;
+-		}
+-		seq_printf(p, "%4s %2d: %10u ", base, i, kstat_cpu(0).irqs[i]);
+-
+-		do {
+-			if (node->flags & IRQ_FLG_FAST) {
+-				seq_puts(p, "F ");
+-			} else if (node->flags & IRQ_FLG_SLOW) {
+-				seq_puts(p, "S ");
+-			} else {
+-				seq_puts(p, "  ");
+-			}
+-			seq_printf(p, "%s\n", node->devname);
+-			if ((node = node->next)) {
+-				seq_puts(p, "                    ");
+-			}
+-		} while(node);
+-
+-	}
+-	return 0;
+-}
+-
+-void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
+-{
+-#ifdef DEBUG_SPURIOUS
+-	printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
+-#endif
+-}
+-
+ static int num_debug[8];
+ 
+ irqreturn_t mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs)
+@@ -684,7 +431,7 @@
+ 	while (nmi_hold == 1)
+ 		udelay(1000);
+ 
+-	if ( console_loglevel >= 8 ) {
++	if (console_loglevel >= 8) {
+ #if 0
+ 		show_state();
+ 		printk("PC: %08lx\nSR: %04x  SP: %p\n", fp->pc, fp->sr, fp);
+@@ -713,14 +460,16 @@
+  * done in hardware (only the PSC can do that.)
+  */
+ 
+-static void scc_irq_enable(int irq) {
+-	int irq_idx     = IRQ_IDX(irq);
++static void scc_irq_enable(unsigned int irq)
++{
++	int irq_idx = IRQ_IDX(irq);
+ 
+ 	scc_mask |= (1 << irq_idx);
+ }
+ 
+-static void scc_irq_disable(int irq) {
+-	int irq_idx     = IRQ_IDX(irq);
++static void scc_irq_disable(unsigned int irq)
++{
++	int irq_idx = IRQ_IDX(irq);
+ 
+ 	scc_mask &= ~(1 << irq_idx);
+ }
+@@ -755,6 +504,8 @@
+ 	/* and since they're autovector interrupts they */
+ 	/* pretty much kill the system.                 */
+ 
+-	if (reg & 0x38) mac_do_irq_list(IRQ_SCCA, regs);
+-	if (reg & 0x07) mac_do_irq_list(IRQ_SCCB, regs);
++	if (reg & 0x38)
++		m68k_handle_int(IRQ_SCCA, regs);
++	if (reg & 0x07)
++		m68k_handle_int(IRQ_SCCB, regs);
+ }
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mac/oss.c linux-m68k/arch/m68k/mac/oss.c
+--- linux-i386/arch/m68k/mac/oss.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mac/oss.c	2006-01-28 23:52:27.000000000 +0100
+@@ -67,15 +67,15 @@
+ 
+ void __init oss_register_interrupts(void)
+ {
+-	cpu_request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
++	request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
+ 			"scsi", (void *) oss);
+-	cpu_request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
++	request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
+ 			"scc", mac_scc_dispatch);
+-	cpu_request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
++	request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
+ 			"nubus", (void *) oss);
+-	cpu_request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
++	request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
+ 			"sound", (void *) oss);
+-	cpu_request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
++	request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
+ 			"via1", (void *) via1);
+ }
+ 
+@@ -113,7 +113,7 @@
+ 		oss->irq_pending &= ~OSS_IP_SOUND;
+ 	} else if (events & OSS_IP_SCSI) {
+ 		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
+-		mac_do_irq_list(IRQ_MAC_SCSI, regs);
++		m68k_handle_int(IRQ_MAC_SCSI, regs);
+ 		oss->irq_pending &= ~OSS_IP_SCSI;
+ 		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
+ 	} else {
+@@ -146,7 +146,7 @@
+ 	for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
+ 		if (events & irq_bit) {
+ 			oss->irq_level[i] = OSS_IRQLEV_DISABLED;
+-			mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs);
++			m68k_handle_int(NUBUS_SOURCE_BASE + i, regs);
+ 			oss->irq_pending &= ~irq_bit;
+ 			oss->irq_level[i] = OSS_IRQLEV_NUBUS;
+ 		}
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mac/psc.c linux-m68k/arch/m68k/mac/psc.c
+--- linux-i386/arch/m68k/mac/psc.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mac/psc.c	2006-01-28 23:52:27.000000000 +0100
+@@ -117,10 +117,10 @@
+ 
+ void __init psc_register_interrupts(void)
+ {
+-	cpu_request_irq(3, psc_irq, IRQ_FLG_LOCK, "psc3", (void *) 0x30);
+-	cpu_request_irq(4, psc_irq, IRQ_FLG_LOCK, "psc4", (void *) 0x40);
+-	cpu_request_irq(5, psc_irq, IRQ_FLG_LOCK, "psc5", (void *) 0x50);
+-	cpu_request_irq(6, psc_irq, IRQ_FLG_LOCK, "psc6", (void *) 0x60);
++	request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30);
++	request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40);
++	request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50);
++	request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60);
+ }
+ 
+ /*
+@@ -149,7 +149,7 @@
+ 	for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
+ 	        if (events & irq_bit) {
+ 			psc_write_byte(pIER, irq_bit);
+-			mac_do_irq_list(base_irq + i, regs);
++			m68k_handle_int(base_irq + i, regs);
+ 			psc_write_byte(pIFR, irq_bit);
+ 			psc_write_byte(pIER, irq_bit | 0x80);
+ 		}
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mac/via.c linux-m68k/arch/m68k/mac/via.c
+--- linux-i386/arch/m68k/mac/via.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mac/via.c	2006-01-28 23:52:27.000000000 +0100
+@@ -260,27 +260,27 @@
+ void __init via_register_interrupts(void)
+ {
+ 	if (via_alt_mapping) {
+-		cpu_request_irq(IRQ_AUTO_1, via1_irq,
++		request_irq(IRQ_AUTO_1, via1_irq,
+ 				IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
+ 				(void *) via1);
+-		cpu_request_irq(IRQ_AUTO_6, via1_irq,
++		request_irq(IRQ_AUTO_6, via1_irq,
+ 				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
+ 				(void *) via1);
+ 	} else {
+-		cpu_request_irq(IRQ_AUTO_1, via1_irq,
++		request_irq(IRQ_AUTO_1, via1_irq,
+ 				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
+ 				(void *) via1);
+ #if 0 /* interferes with serial on some machines */
+ 		if (!psc_present) {
+-			cpu_request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
++			request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
+ 					"Off Switch", mac_bang);
+ 		}
+ #endif
+ 	}
+-	cpu_request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
++	request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ 			"via2", (void *) via2);
+ 	if (!psc_present) {
+-		cpu_request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
++		request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
+ 				"scc", mac_scc_dispatch);
+ 	}
+ 	request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+@@ -437,7 +437,7 @@
+ 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
+ 		if (events & irq_bit) {
+ 			via1[vIER] = irq_bit;
+-			mac_do_irq_list(VIA1_SOURCE_BASE + i, regs);
++			m68k_handle_int(VIA1_SOURCE_BASE + i, regs);
+ 			via1[vIFR] = irq_bit;
+ 			via1[vIER] = irq_bit | 0x80;
+ 		}
+@@ -452,7 +452,7 @@
+ 		/* No, it won't be set. that's why we're doing this. */
+ 		via_irq_disable(IRQ_MAC_NUBUS);
+ 		via_irq_clear(IRQ_MAC_NUBUS);
+-		mac_do_irq_list(IRQ_MAC_NUBUS, regs);
++		m68k_handle_int(IRQ_MAC_NUBUS, regs);
+ 		via_irq_enable(IRQ_MAC_NUBUS);
+ 	}
+ #endif
+@@ -471,7 +471,7 @@
+ 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
+ 		if (events & irq_bit) {
+ 			via2[gIER] = irq_bit;
+-			mac_do_irq_list(VIA2_SOURCE_BASE + i, regs);
++			m68k_handle_int(VIA2_SOURCE_BASE + i, regs);
+ 			via2[gIFR] = irq_bit | rbv_clear;
+ 			via2[gIER] = irq_bit | 0x80;
+ 		}
+@@ -494,7 +494,7 @@
+ 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
+ 		if (events & irq_bit) {
+ 			via_irq_disable(NUBUS_SOURCE_BASE + i);
+-			mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs);
++			m68k_handle_int(NUBUS_SOURCE_BASE + i, regs);
+ 			via_irq_enable(NUBUS_SOURCE_BASE + i);
+ 		}
+ 	}
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mm/motorola.c linux-m68k/arch/m68k/mm/motorola.c
+--- linux-i386/arch/m68k/mm/motorola.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mm/motorola.c	2006-01-28 23:52:28.000000000 +0100
+@@ -203,7 +203,7 @@
+ {
+ 	int chunk;
+ 	unsigned long mem_avail = 0;
+-	unsigned long zones_size[3] = { 0, };
++	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+ 
+ #ifdef DEBUG
+ 	{
+@@ -257,12 +257,12 @@
+ #ifdef DEBUG
+ 	printk ("before free_area_init\n");
+ #endif
+-	zones_size[0] = (mach_max_dma_address < (unsigned long)high_memory ?
+-			 (mach_max_dma_address+1) : (unsigned long)high_memory);
+-	zones_size[1] = (unsigned long)high_memory - zones_size[0];
++	zones_size[ZONE_DMA] = (mach_max_dma_address < (unsigned long)high_memory ?
++				(mach_max_dma_address+1) : (unsigned long)high_memory);
++	zones_size[ZONE_NORMAL] = (unsigned long)high_memory - zones_size[0];
+ 
+-	zones_size[0] = (zones_size[0] - PAGE_OFFSET) >> PAGE_SHIFT;
+-	zones_size[1] >>= PAGE_SHIFT;
++	zones_size[ZONE_DMA] = (zones_size[ZONE_DMA] - PAGE_OFFSET) >> PAGE_SHIFT;
++	zones_size[ZONE_NORMAL] >>= PAGE_SHIFT;
+ 
+ 	free_area_init(zones_size);
+ }
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mm/sun3mmu.c linux-m68k/arch/m68k/mm/sun3mmu.c
+--- linux-i386/arch/m68k/mm/sun3mmu.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mm/sun3mmu.c	2006-01-28 23:52:28.000000000 +0100
+@@ -46,7 +46,7 @@
+ 	unsigned long address;
+ 	unsigned long next_pgtable;
+ 	unsigned long bootmem_end;
+-	unsigned long zones_size[3] = {0, 0, 0};
++	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+ 	unsigned long size;
+ 
+ 
+@@ -92,8 +92,7 @@
+ 	current->mm = NULL;
+ 
+ 	/* memory sizing is a hack stolen from motorola.c..  hope it works for us */
+-	zones_size[0] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
+-	zones_size[1] = 0;
++	zones_size[ZONE_DMA] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
+ 
+ 	free_area_init(zones_size);
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mvme147/Makefile linux-m68k/arch/m68k/mvme147/Makefile
+--- linux-i386/arch/m68k/mvme147/Makefile	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mvme147/Makefile	2006-01-28 23:52:28.000000000 +0100
+@@ -2,4 +2,4 @@
+ # Makefile for Linux arch/m68k/mvme147 source directory
+ #
+ 
+-obj-y		:= config.o 147ints.o
++obj-y		:= config.o
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mvme147/config.c linux-m68k/arch/m68k/mvme147/config.c
+--- linux-i386/arch/m68k/mvme147/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mvme147/config.c	2006-01-28 23:52:28.000000000 +0100
+@@ -36,15 +36,8 @@
+ #include <asm/mvme147hw.h>
+ 
+ 
+-extern irqreturn_t mvme147_process_int (int level, struct pt_regs *regs);
+-extern void mvme147_init_IRQ (void);
+-extern void mvme147_free_irq (unsigned int, void *);
+-extern int  show_mvme147_interrupts (struct seq_file *, void *);
+-extern void mvme147_enable_irq (unsigned int);
+-extern void mvme147_disable_irq (unsigned int);
+ static void mvme147_get_model(char *model);
+ static int  mvme147_get_hardware_list(char *buffer);
+-extern int mvme147_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+ extern void mvme147_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+ extern unsigned long mvme147_gettimeoffset (void);
+ extern int mvme147_hwclk (int, struct rtc_time *);
+@@ -91,6 +84,15 @@
+ 	return 0;
+ }
+ 
++/*
++ * This function is called during kernel startup to initialize
++ * the mvme147 IRQ handling routines.
++ */
++
++void mvme147_init_IRQ(void)
++{
++	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
++}
+ 
+ void __init config_mvme147(void)
+ {
+@@ -101,12 +103,6 @@
+ 	mach_hwclk		= mvme147_hwclk;
+ 	mach_set_clock_mmss	= mvme147_set_clock_mmss;
+ 	mach_reset		= mvme147_reset;
+-	mach_free_irq		= mvme147_free_irq;
+-	mach_process_int	= mvme147_process_int;
+-	mach_get_irq_list	= show_mvme147_interrupts;
+-	mach_request_irq	= mvme147_request_irq;
+-	enable_irq		= mvme147_enable_irq;
+-	disable_irq		= mvme147_disable_irq;
+ 	mach_get_model		= mvme147_get_model;
+ 	mach_get_hardware_list	= mvme147_get_hardware_list;
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mvme16x/Makefile linux-m68k/arch/m68k/mvme16x/Makefile
+--- linux-i386/arch/m68k/mvme16x/Makefile	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mvme16x/Makefile	2006-01-28 23:52:28.000000000 +0100
+@@ -2,4 +2,4 @@
+ # Makefile for Linux arch/m68k/mvme16x source directory
+ #
+ 
+-obj-y		:= config.o 16xints.o rtc.o mvme16x_ksyms.o
++obj-y		:= config.o rtc.o mvme16x_ksyms.o
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/mvme16x/config.c linux-m68k/arch/m68k/mvme16x/config.c
+--- linux-i386/arch/m68k/mvme16x/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/mvme16x/config.c	2006-01-28 23:52:28.000000000 +0100
+@@ -40,15 +40,8 @@
+ 
+ static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
+ 
+-extern irqreturn_t mvme16x_process_int (int level, struct pt_regs *regs);
+-extern void mvme16x_init_IRQ (void);
+-extern void mvme16x_free_irq (unsigned int, void *);
+-extern int show_mvme16x_interrupts (struct seq_file *, void *);
+-extern void mvme16x_enable_irq (unsigned int);
+-extern void mvme16x_disable_irq (unsigned int);
+ static void mvme16x_get_model(char *model);
+ static int  mvme16x_get_hardware_list(char *buffer);
+-extern int  mvme16x_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+ extern void mvme16x_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+ extern unsigned long mvme16x_gettimeoffset (void);
+ extern int mvme16x_hwclk (int, struct rtc_time *);
+@@ -120,6 +113,16 @@
+     return (len);
+ }
+ 
++/*
++ * This function is called during kernel startup to initialize
++ * the mvme16x IRQ handling routines.  Should probably ensure
++ * that the base vectors for the VMEChip2 and PCCChip2 are valid.
++ */
++
++static void mvme16x_init_IRQ (void)
++{
++	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
++}
+ 
+ #define pcc2chip	((volatile u_char *)0xfff42000)
+ #define PccSCCMICR	0x1d
+@@ -138,12 +141,6 @@
+     mach_hwclk           = mvme16x_hwclk;
+     mach_set_clock_mmss	 = mvme16x_set_clock_mmss;
+     mach_reset		 = mvme16x_reset;
+-    mach_free_irq	 = mvme16x_free_irq;
+-    mach_process_int	 = mvme16x_process_int;
+-    mach_get_irq_list	 = show_mvme16x_interrupts;
+-    mach_request_irq	 = mvme16x_request_irq;
+-    enable_irq           = mvme16x_enable_irq;
+-    disable_irq          = mvme16x_disable_irq;
+     mach_get_model       = mvme16x_get_model;
+     mach_get_hardware_list = mvme16x_get_hardware_list;
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/q40/config.c linux-m68k/arch/m68k/q40/config.c
+--- linux-i386/arch/m68k/q40/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/q40/config.c	2006-04-11 16:32:24.000000000 +0200
+@@ -37,15 +37,9 @@
+ #include <asm/q40_master.h>
+ 
+ extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
+-extern irqreturn_t (*q40_default_handler[]) (int, void *, struct pt_regs *);  /* added just for debugging */
+ extern void q40_init_IRQ (void);
+-extern void q40_free_irq (unsigned int, void *);
+-extern int  show_q40_interrupts (struct seq_file *, void *);
+-extern void q40_enable_irq (unsigned int);
+-extern void q40_disable_irq (unsigned int);
+ static void q40_get_model(char *model);
+ static int  q40_get_hardware_list(char *buffer);
+-extern int  q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+ extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+ 
+ extern unsigned long q40_gettimeoffset (void);
+@@ -175,13 +169,6 @@
+     mach_set_clock_mmss	 = q40_set_clock_mmss;
+ 
+     mach_reset		 = q40_reset;
+-    mach_free_irq	 = q40_free_irq;
+-    mach_process_int	 = q40_process_int;
+-    mach_get_irq_list	 = show_q40_interrupts;
+-    mach_request_irq	 = q40_request_irq;
+-    enable_irq		 = q40_enable_irq;
+-    disable_irq          = q40_disable_irq;
+-    mach_default_handler = &q40_default_handler;
+     mach_get_model       = q40_get_model;
+     mach_get_hardware_list = q40_get_hardware_list;
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/q40/q40ints.c linux-m68k/arch/m68k/q40/q40ints.c
+--- linux-i386/arch/m68k/q40/q40ints.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/q40/q40ints.c	2006-01-28 23:52:28.000000000 +0100
+@@ -14,13 +14,8 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/sched.h>
+-#include <linux/seq_file.h>
+ #include <linux/interrupt.h>
+-#include <linux/hardirq.h>
+ 
+-#include <asm/rtc.h>
+ #include <asm/ptrace.h>
+ #include <asm/system.h>
+ #include <asm/irq.h>
+@@ -39,29 +34,37 @@
+  *
+ */
+ 
+-extern int ints_inited;
++static void q40_irq_handler(unsigned int, struct pt_regs *fp);
++static void q40_enable_irq(unsigned int);
++static void q40_disable_irq(unsigned int);
+ 
++unsigned short q40_ablecount[35];
++unsigned short q40_state[35];
+ 
+-irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp);
+-
+-
+-static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
+-static irqreturn_t default_handler(int lev, void *dev_id, struct pt_regs *regs);
+-
+-
+-#define DEVNAME_SIZE 24
++static int q40_irq_startup(unsigned int irq)
++{
++	/* test for ISA ints not implemented by HW */
++	switch (irq) {
++	case 1: case 2: case 8: case 9:
++	case 11: case 12: case 13:
++		printk("%s: ISA IRQ %d not implemented by HW\n", __FUNCTION__, irq);
++		return -ENXIO;
++	}
++	return 0;
++}
+ 
+-static struct q40_irq_node {
+-	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
+-	unsigned long	flags;
+-	void		*dev_id;
+-  /*        struct q40_irq_node *next;*/
+-        char	        devname[DEVNAME_SIZE];
+-	unsigned	count;
+-        unsigned short  state;
+-} irq_tab[Q40_IRQ_MAX+1];
++static void q40_irq_shutdown(unsigned int irq)
++{
++}
+ 
+-short unsigned q40_ablecount[Q40_IRQ_MAX+1];
++static struct irq_controller q40_irq_controller = {
++	.name		= "q40",
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.startup	= q40_irq_startup,
++	.shutdown	= q40_irq_shutdown,
++	.enable		= q40_enable_irq,
++	.disable	= q40_disable_irq,
++};
+ 
+ /*
+  * void q40_init_IRQ (void)
+@@ -74,139 +77,29 @@
+  * the q40 IRQ handling routines.
+  */
+ 
+-static int disabled=0;
++static int disabled;
+ 
+-void q40_init_IRQ (void)
++void q40_init_IRQ(void)
+ {
+-	int i;
+-
+-	disabled=0;
+-	for (i = 0; i <= Q40_IRQ_MAX; i++) {
+-		irq_tab[i].handler = q40_defhand;
+-		irq_tab[i].flags = 0;
+-		irq_tab[i].dev_id = NULL;
+-		/*		irq_tab[i].next = NULL;*/
+-		irq_tab[i].devname[0] = 0;
+-		irq_tab[i].count = 0;
+-		irq_tab[i].state =0;
+-		q40_ablecount[i]=0;   /* all enabled */
+-	}
++	m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);
+ 
+ 	/* setup handler for ISA ints */
+-	cpu_request_irq(IRQ2, q40_irq2_handler, 0, "q40 ISA and master chip",
+-			NULL);
++	m68k_setup_auto_interrupt(q40_irq_handler);
++
++	m68k_irq_startup(IRQ_AUTO_2);
++	m68k_irq_startup(IRQ_AUTO_4);
+ 
+ 	/* now enable some ints.. */
+-	master_outb(1,EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
++	master_outb(1, EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
+ 
+ 	/* make sure keyboard IRQ is disabled */
+-	master_outb(0,KEY_IRQ_ENABLE_REG);
++	master_outb(0, KEY_IRQ_ENABLE_REG);
+ }
+ 
+-int q40_request_irq(unsigned int irq,
+-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                unsigned long flags, const char *devname, void *dev_id)
+-{
+-  /*printk("q40_request_irq %d, %s\n",irq,devname);*/
+-
+-	if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
+-		printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
+-		return -ENXIO;
+-	}
+-
+-	/* test for ISA ints not implemented by HW */
+-	switch (irq)
+-	  {
+-	  case 1: case 2: case 8: case 9:
+-	  case 12: case 13:
+-	    printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);
+-	    return -ENXIO;
+-	  case 11:
+-	    printk("warning IRQ 10 and 11 not distinguishable\n");
+-	    irq=10;
+-	  default:
+-	    ;
+-	  }
+-
+-	if (irq<Q40_IRQ_SAMPLE)
+-	  {
+-	    if (irq_tab[irq].dev_id != NULL)
+-		  {
+-		    printk("%s: IRQ %d from %s is not replaceable\n",
+-			   __FUNCTION__, irq, irq_tab[irq].devname);
+-		    return -EBUSY;
+-		  }
+-	    /*printk("IRQ %d set to handler %p\n",irq,handler);*/
+-	    if (dev_id==NULL)
+-		  {
+-		printk("WARNING: dev_id == NULL in request_irq\n");
+-		dev_id=(void*)1;
+-	      }
+-	    irq_tab[irq].handler = handler;
+-	    irq_tab[irq].flags   = flags;
+-	    irq_tab[irq].dev_id  = dev_id;
+-	    strlcpy(irq_tab[irq].devname,devname,sizeof(irq_tab[irq].devname));
+-	    irq_tab[irq].state = 0;
+-	    return 0;
+-	  }
+-	else {
+-	  /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/
+-	  cpu_request_irq(4, handler, flags, devname, dev_id);
+-	  cpu_request_irq(6, handler, flags, devname, dev_id);
+-	  return 0;
+-	}
+-}
+-
+-void q40_free_irq(unsigned int irq, void *dev_id)
+-{
+-	if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
+-		printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id);
+-		return;
+-	}
+-
+-	/* test for ISA ints not implemented by HW */
+-	switch (irq)
+-	  {
+-	  case 1: case 2: case 8: case 9:
+-	  case 12: case 13:
+-	    printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id);
+-	    return;
+-	  case 11: irq=10;
+-	  default:
+-	    ;
+-	  }
+-
+-	if (irq<Q40_IRQ_SAMPLE)
+-	  {
+-	    if (irq_tab[irq].dev_id != dev_id)
+-	      printk("%s: Removing probably wrong IRQ %d from %s\n",
+-		     __FUNCTION__, irq, irq_tab[irq].devname);
+-
+-	    irq_tab[irq].handler = q40_defhand;
+-	    irq_tab[irq].flags   = 0;
+-	    irq_tab[irq].dev_id  = NULL;
+-	    /* irq_tab[irq].devname = NULL; */
+-	    /* do not reset state !! */
+-	  }
+-	else
+-	  { /* == Q40_IRQ_SAMPLE */
+-	    cpu_free_irq(4, dev_id);
+-	    cpu_free_irq(6, dev_id);
+-	  }
+-}
+-
+-
+-irqreturn_t q40_process_int (int level, struct pt_regs *fp)
+-{
+-  printk("unexpected interrupt vec=%x, pc=%lx, d0=%lx, d0_orig=%lx, d1=%lx, d2=%lx\n",
+-          level, fp->pc, fp->d0, fp->orig_d0, fp->d1, fp->d2);
+-  printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG));
+-  return IRQ_HANDLED;
+-}
+ 
+ /*
+  * this stuff doesn't really belong here..
+-*/
++ */
+ 
+ int ql_ticks;              /* 200Hz ticks since last jiffie */
+ static int sound_ticks;
+@@ -215,54 +108,53 @@
+ 
+ void q40_mksound(unsigned int hz, unsigned int ticks)
+ {
+-  /* for now ignore hz, except that hz==0 switches off sound */
+-  /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
+-  if (hz==0)
+-    {
+-      if (sound_ticks)
+-	sound_ticks=1;
+-
+-      *DAC_LEFT=128;
+-      *DAC_RIGHT=128;
+-
+-      return;
+-    }
+-  /* sound itself is done in q40_timer_int */
+-  if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */
+-  sound_ticks=ticks<<1;
++	/* for now ignore hz, except that hz==0 switches off sound */
++	/* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
++	if (hz == 0) {
++		if (sound_ticks)
++			sound_ticks = 1;
++
++		*DAC_LEFT = 128;
++		*DAC_RIGHT = 128;
++
++		return;
++	}
++	/* sound itself is done in q40_timer_int */
++	if (sound_ticks == 0)
++		sound_ticks = 1000; /* pretty long beep */
++	sound_ticks = ticks << 1;
+ }
+ 
+ static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *);
+ 
+ static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs)
+ {
+-    ql_ticks = ql_ticks ? 0 : 1;
+-    if (sound_ticks)
+-      {
+-	unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
+-	sound_ticks--;
+-	*DAC_LEFT=sval;
+-	*DAC_RIGHT=sval;
+-      }
+-
+-    if (!ql_ticks)
+-	q40_timer_routine(irq, dev, regs);
+-    return IRQ_HANDLED;
++	ql_ticks = ql_ticks ? 0 : 1;
++	if (sound_ticks) {
++		unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
++		sound_ticks--;
++		*DAC_LEFT=sval;
++		*DAC_RIGHT=sval;
++	}
++
++	if (!ql_ticks)
++		q40_timer_routine(irq, dev, regs);
++	return IRQ_HANDLED;
+ }
+ 
+ void q40_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
+ {
+-    int timer_irq;
++	int timer_irq;
+ 
+-    q40_timer_routine = timer_routine;
+-    timer_irq=Q40_IRQ_FRAME;
++	q40_timer_routine = timer_routine;
++	timer_irq = Q40_IRQ_FRAME;
+ 
+-    if (request_irq(timer_irq, q40_timer_int, 0,
++	if (request_irq(timer_irq, q40_timer_int, 0,
+ 				"timer", q40_timer_int))
+-	panic ("Couldn't register timer int");
++		panic("Couldn't register timer int");
+ 
+-    master_outb(-1,FRAME_CLEAR_REG);
+-    master_outb( 1,FRAME_RATE_REG);
++	master_outb(-1, FRAME_CLEAR_REG);
++	master_outb( 1, FRAME_RATE_REG);
+ }
+ 
+ 
+@@ -308,169 +200,132 @@
+ static int aliased_irq=0;  /* how many times inside handler ?*/
+ 
+ 
+-/* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */
+-irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
++/* got interrupt, dispatch to ISA or keyboard/timer IRQs */
++static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
+ {
+-  unsigned mir, mer;
+-  int irq,i;
++	unsigned mir, mer;
++	int i;
+ 
+ //repeat:
+-  mir=master_inb(IIRQ_REG);
+-  if (mir&Q40_IRQ_FRAME_MASK) {
+-	  irq_tab[Q40_IRQ_FRAME].count++;
+-	  irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp);
+-	  master_outb(-1,FRAME_CLEAR_REG);
+-  }
+-  if ((mir&Q40_IRQ_SER_MASK) || (mir&Q40_IRQ_EXT_MASK)) {
+-	  mer=master_inb(EIRQ_REG);
+-	  for (i=0; eirqs[i].mask; i++) {
+-		  if (mer&(eirqs[i].mask)) {
+-			  irq=eirqs[i].irq;
++	mir = master_inb(IIRQ_REG);
++#ifdef CONFIG_BLK_DEV_FD
++	if ((mir & Q40_IRQ_EXT_MASK) &&
++	    (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) {
++		floppy_hardint();
++		return;
++	}
++#endif
++	switch (irq) {
++	case 4:
++	case 6:
++		m68k_handle_int(Q40_IRQ_SAMPLE, fp);
++		return;
++	}
++	if (mir & Q40_IRQ_FRAME_MASK) {
++		m68k_handle_int(Q40_IRQ_FRAME, fp);
++		master_outb(-1, FRAME_CLEAR_REG);
++	}
++	if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
++		mer = master_inb(EIRQ_REG);
++		for (i = 0; eirqs[i].mask; i++) {
++			if (mer & eirqs[i].mask) {
++				irq = eirqs[i].irq;
+ /*
+  * There is a little mess wrt which IRQ really caused this irq request. The
+  * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they
+  * are read - which is long after the request came in. In theory IRQs should
+  * not just go away but they occassionally do
+  */
+-			  if (irq>4 && irq<=15 && mext_disabled) {
+-				  /*aliased_irq++;*/
+-				  goto iirq;
+-			  }
+-			  if (irq_tab[irq].handler == q40_defhand ) {
+-				  printk("handler for IRQ %d not defined\n",irq);
+-				  continue; /* ignore uninited INTs :-( */
+-			  }
+-			  if ( irq_tab[irq].state & IRQ_INPROGRESS ) {
+-				  /* some handlers do local_irq_enable() for irq latency reasons, */
+-				  /* however reentering an active irq handler is not permitted */
++				if (irq > 4 && irq <= 15 && mext_disabled) {
++					/*aliased_irq++;*/
++					goto iirq;
++				}
++				if (q40_state[irq] & IRQ_INPROGRESS) {
++					/* some handlers do local_irq_enable() for irq latency reasons, */
++					/* however reentering an active irq handler is not permitted */
+ #ifdef IP_USE_DISABLE
+-				  /* in theory this is the better way to do it because it still */
+-				  /* lets through eg the serial irqs, unfortunately it crashes */
+-				  disable_irq(irq);
+-				  disabled=1;
++					/* in theory this is the better way to do it because it still */
++					/* lets through eg the serial irqs, unfortunately it crashes */
++					disable_irq(irq);
++					disabled = 1;
+ #else
+-				  /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */
+-				  fp->sr = (((fp->sr) & (~0x700))+0x200);
+-				  disabled=1;
++					/*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",
++						irq, disabled ? "already" : "not yet"); */
++					fp->sr = (((fp->sr) & (~0x700))+0x200);
++					disabled = 1;
+ #endif
+-				  goto iirq;
+-			  }
+-			  irq_tab[irq].count++;
+-			  irq_tab[irq].state |= IRQ_INPROGRESS;
+-			  irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
+-			  irq_tab[irq].state &= ~IRQ_INPROGRESS;
+-
+-			  /* naively enable everything, if that fails than    */
+-			  /* this function will be reentered immediately thus */
+-			  /* getting another chance to disable the IRQ        */
++					goto iirq;
++				}
++				q40_state[irq] |= IRQ_INPROGRESS;
++				m68k_handle_int(irq, fp);
++				q40_state[irq] &= ~IRQ_INPROGRESS;
++
++				/* naively enable everything, if that fails than    */
++				/* this function will be reentered immediately thus */
++				/* getting another chance to disable the IRQ        */
+ 
+-			  if ( disabled ) {
++				if (disabled) {
+ #ifdef IP_USE_DISABLE
+-				  if (irq>4){
+-					  disabled=0;
+-					  enable_irq(irq);}
++					if (irq > 4) {
++						disabled = 0;
++						enable_irq(irq);
++					}
+ #else
+-				  disabled=0;
+-				  /*printk("reenabling irq %d\n",irq); */
++					disabled = 0;
++					/*printk("reenabling irq %d\n", irq); */
+ #endif
+-			  }
++				}
+ // used to do 'goto repeat;' here, this delayed bh processing too long
+-			  return IRQ_HANDLED;
+-		  }
+-	  }
+-	  if (mer && ccleirq>0 && !aliased_irq)
+-		  printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
+-  }
++				return;
++			}
++		}
++		if (mer && ccleirq > 0 && !aliased_irq) {
++			printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer);
++			ccleirq--;
++		}
++	}
+  iirq:
+-  mir=master_inb(IIRQ_REG);
+-  /* should test whether keyboard irq is really enabled, doing it in defhand */
+-  if (mir&Q40_IRQ_KEYB_MASK) {
+-	  irq_tab[Q40_IRQ_KEYBOARD].count++;
+-	  irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
+-  }
+-  return IRQ_HANDLED;
+-}
+-
+-int show_q40_interrupts (struct seq_file *p, void *v)
+-{
+-	int i;
+-
+-	for (i = 0; i <= Q40_IRQ_MAX; i++) {
+-		if (irq_tab[i].count)
+-		      seq_printf(p, "%sIRQ %02d: %8d  %s%s\n",
+-			      (i<=15) ? "ISA-" : "    " ,
+-			    i, irq_tab[i].count,
+-			    irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
+-			    irq_tab[i].handler == q40_defhand ?
+-					" (now unassigned)" : "");
++	mir = master_inb(IIRQ_REG);
++	/* should test whether keyboard irq is really enabled, doing it in defhand */
++	if (mir & Q40_IRQ_KEYB_MASK)
++		m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
++
++	return;
++}
++
++void q40_enable_irq(unsigned int irq)
++{
++	if (irq >= 5 && irq <= 15) {
++		mext_disabled--;
++		if (mext_disabled > 0)
++			printk("q40_enable_irq : nested disable/enable\n");
++		if (mext_disabled == 0)
++			master_outb(1, EXT_ENABLE_REG);
+ 	}
+-	return 0;
+ }
+ 
+ 
+-static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
+-{
+-        if (irq!=Q40_IRQ_KEYBOARD)
+-	     printk ("Unknown q40 interrupt %d\n", irq);
+-	else master_outb(-1,KEYBOARD_UNLOCK_REG);
+-	return IRQ_NONE;
+-}
+-static irqreturn_t default_handler(int lev, void *dev_id, struct pt_regs *regs)
+-{
+-	printk ("Uninitialised interrupt level %d\n", lev);
+-	return IRQ_NONE;
+-}
+-
+-irqreturn_t (*q40_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+-	 [0] = default_handler,
+-	 [1] = default_handler,
+-	 [2] = default_handler,
+-	 [3] = default_handler,
+-	 [4] = default_handler,
+-	 [5] = default_handler,
+-	 [6] = default_handler,
+-	 [7] = default_handler
+-};
+-
+-
+-void q40_enable_irq (unsigned int irq)
++void q40_disable_irq(unsigned int irq)
+ {
+-  if ( irq>=5 && irq<=15 )
+-  {
+-    mext_disabled--;
+-    if (mext_disabled>0)
+-	  printk("q40_enable_irq : nested disable/enable\n");
+-    if (mext_disabled==0)
+-    master_outb(1,EXT_ENABLE_REG);
+-    }
+-}
+-
+-
+-void q40_disable_irq (unsigned int irq)
+-{
+-  /* disable ISA iqs : only do something if the driver has been
+-   * verified to be Q40 "compatible" - right now IDE, NE2K
+-   * Any driver should not attempt to sleep across disable_irq !!
+-   */
+-
+-  if ( irq>=5 && irq<=15 ) {
+-    master_outb(0,EXT_ENABLE_REG);
+-    mext_disabled++;
+-    if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled);
+-  }
++	/* disable ISA iqs : only do something if the driver has been
++	 * verified to be Q40 "compatible" - right now IDE, NE2K
++	 * Any driver should not attempt to sleep across disable_irq !!
++	 */
++
++	if (irq >= 5 && irq <= 15) {
++		master_outb(0, EXT_ENABLE_REG);
++		mext_disabled++;
++		if (mext_disabled > 1)
++			printk("disable_irq nesting count %d\n",mext_disabled);
++	}
+ }
+ 
+-unsigned long q40_probe_irq_on (void)
++unsigned long q40_probe_irq_on(void)
+ {
+-  printk("irq probing not working - reconfigure the driver to avoid this\n");
+-  return -1;
++	printk("irq probing not working - reconfigure the driver to avoid this\n");
++	return -1;
+ }
+-int q40_probe_irq_off (unsigned long irqs)
++int q40_probe_irq_off(unsigned long irqs)
+ {
+-  return -1;
++	return -1;
+ }
+-/*
+- * Local variables:
+- * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040   -c -o q40ints.o q40ints.c"
+- * End:
+- */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/sun3/config.c linux-m68k/arch/m68k/sun3/config.c
+--- linux-i386/arch/m68k/sun3/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/sun3/config.c	2006-01-28 23:52:28.000000000 +0100
+@@ -36,7 +36,6 @@
+ char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
+ 
+ extern unsigned long sun3_gettimeoffset(void);
+-extern int show_sun3_interrupts (struct seq_file *, void *);
+ extern void sun3_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+ extern void sun3_get_model (char* model);
+ extern void idprom_init (void);
+@@ -147,13 +146,6 @@
+ 
+         mach_sched_init      =  sun3_sched_init;
+         mach_init_IRQ        =  sun3_init_IRQ;
+-        mach_default_handler = &sun3_default_handler;
+-        mach_request_irq     =  sun3_request_irq;
+-        mach_free_irq        =  sun3_free_irq;
+-	enable_irq	     =  sun3_enable_irq;
+-        disable_irq	     =  sun3_disable_irq;
+-	mach_process_int     =  sun3_process_int;
+-        mach_get_irq_list    =  show_sun3_interrupts;
+         mach_reset           =  sun3_reboot;
+ 	mach_gettimeoffset   =  sun3_gettimeoffset;
+ 	mach_get_model	     =  sun3_get_model;
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/sun3/sun3ints.c linux-m68k/arch/m68k/sun3/sun3ints.c
+--- linux-i386/arch/m68k/sun3/sun3ints.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/sun3/sun3ints.c	2006-01-28 23:52:28.000000000 +0100
+@@ -19,7 +19,6 @@
+ #include <linux/seq_file.h>
+ 
+ extern void sun3_leds (unsigned char);
+-static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp);
+ 
+ void sun3_disable_interrupts(void)
+ {
+@@ -40,48 +39,30 @@
+ 
+ volatile unsigned char* sun3_intreg;
+ 
+-void sun3_insert_irq(irq_node_t **list, irq_node_t *node)
+-{
+-}
+-
+-void sun3_delete_irq(irq_node_t **list, void *dev_id)
+-{
+-}
+-
+ void sun3_enable_irq(unsigned int irq)
+ {
+-	*sun3_intreg |=  (1<<irq);
++	*sun3_intreg |=  (1 << irq);
+ }
+ 
+ void sun3_disable_irq(unsigned int irq)
+ {
+-	*sun3_intreg &= ~(1<<irq);
+-}
+-
+-inline void sun3_do_irq(int irq, struct pt_regs *fp)
+-{
+-	kstat_cpu(0).irqs[SYS_IRQS + irq]++;
+-	*sun3_intreg &= ~(1<<irq);
+-	*sun3_intreg |=  (1<<irq);
++	*sun3_intreg &= ~(1 << irq);
+ }
+ 
+ static irqreturn_t sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
+ {
+-	sun3_do_irq(irq,fp);
+-	if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 2000))
+-		sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%16000)
+-			  /2000]);
++	*sun3_intreg |=  (1 << irq);
++	if (!(kstat_cpu(0).irqs[irq] % 2000))
++		sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 16000) / 2000]);
+ 	return IRQ_HANDLED;
+ }
+ 
+ static irqreturn_t sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
+ {
+-        kstat_cpu(0).irqs[SYS_IRQS + irq]++;
+ #ifdef CONFIG_SUN3
+ 	intersil_clear();
+ #endif
+-        *sun3_intreg &= ~(1<<irq);
+-        *sun3_intreg |=  (1<<irq);
++        *sun3_intreg |=  (1 << irq);
+ #ifdef CONFIG_SUN3
+ 	intersil_clear();
+ #endif
+@@ -89,65 +70,8 @@
+ #ifndef CONFIG_SMP
+ 	update_process_times(user_mode(fp));
+ #endif
+-        if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 20))
+-                sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%160)
+-                /20]);
+-	return IRQ_HANDLED;
+-}
+-
+-/* handle requested ints, excepting 5 and 7, which always do the same
+-   thing */
+-irqreturn_t (*sun3_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+-	[0] = sun3_inthandle,
+-	[1] = sun3_inthandle,
+-	[2] = sun3_inthandle,
+-	[3] = sun3_inthandle,
+-	[4] = sun3_inthandle,
+-	[5] = sun3_int5,
+-	[6] = sun3_inthandle,
+-	[7] = sun3_int7
+-};
+-
+-static const char *dev_names[SYS_IRQS] = {
+-	[5] = "timer",
+-	[7] = "int7 handler"
+-};
+-static void *dev_ids[SYS_IRQS];
+-static irqreturn_t (*sun3_inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+-	[5] = sun3_int5,
+-	[7] = sun3_int7
+-};
+-static irqreturn_t (*sun3_vechandler[SUN3_INT_VECS])(int, void *, struct pt_regs *);
+-static void *vec_ids[SUN3_INT_VECS];
+-static const char *vec_names[SUN3_INT_VECS];
+-static int vec_ints[SUN3_INT_VECS];
+-
+-
+-int show_sun3_interrupts(struct seq_file *p, void *v)
+-{
+-	int i;
+-
+-	for(i = 0; i < (SUN3_INT_VECS-1); i++) {
+-		if(sun3_vechandler[i] != NULL) {
+-			seq_printf(p, "vec %3d: %10u %s\n", i+64,
+-				   vec_ints[i],
+-				   (vec_names[i]) ? vec_names[i] :
+-				   "sun3_vechandler");
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp)
+-{
+-	if(sun3_inthandler[irq] == NULL)
+-		panic ("bad interrupt %d received (id %p)\n",irq, dev_id);
+-
+-        kstat_cpu(0).irqs[SYS_IRQS + irq]++;
+-        *sun3_intreg &= ~(1<<irq);
+-
+-	sun3_inthandler[irq](irq, dev_ids[irq], fp);
++        if (!(kstat_cpu(0).irqs[irq] % 20))
++                sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -157,109 +81,31 @@
+ 	return IRQ_HANDLED;
+ }
+ 
+-void sun3_init_IRQ(void)
+-{
+-	int i;
+-
+-	*sun3_intreg = 1;
+-
+-	for(i = 0; i < SYS_IRQS; i++)
+-	{
+-		if(dev_names[i])
+-			cpu_request_irq(i, sun3_default_handler[i], 0,
+-					dev_names[i], NULL);
+-	}
+-
+-	for(i = 0; i < 192; i++)
+-		sun3_vechandler[i] = NULL;
+-
+-	sun3_vechandler[191] = sun3_vec255;
+-}
+-
+-int sun3_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                      unsigned long flags, const char *devname, void *dev_id)
++static void sun3_inthandle(unsigned int irq, struct pt_regs *fp)
+ {
++        *sun3_intreg &= ~(1 << irq);
+ 
+-	if(irq < SYS_IRQS) {
+-		if(sun3_inthandler[irq] != NULL) {
+-			printk("sun3_request_irq: request for irq %d -- already taken!\n", irq);
+-			return 1;
+-		}
+-
+-		sun3_inthandler[irq] = handler;
+-		dev_ids[irq] = dev_id;
+-		dev_names[irq] = devname;
+-
+-		/* setting devname would be nice */
+-		cpu_request_irq(irq, sun3_default_handler[irq], 0, devname,
+-				NULL);
+-
+-		return 0;
+-	} else {
+-		if((irq >= 64) && (irq <= 255)) {
+-		        int vec;
+-
+-			vec = irq - 64;
+-			if(sun3_vechandler[vec] != NULL) {
+-				printk("sun3_request_irq: request for vec %d -- already taken!\n", irq);
+-				return 1;
+-			}
+-
+-			sun3_vechandler[vec] = handler;
+-			vec_ids[vec] = dev_id;
+-			vec_names[vec] = devname;
+-			vec_ints[vec] = 0;
+-
+-			return 0;
+-		}
+-	}
+-
+-	printk("sun3_request_irq: invalid irq %d\n", irq);
+-	return 1;
+-
++	m68k_handle_int(irq, fp);
+ }
+ 
+-void sun3_free_irq(unsigned int irq, void *dev_id)
+-{
+-
+-	if(irq < SYS_IRQS) {
+-		if(sun3_inthandler[irq] == NULL)
+-			panic("sun3_free_int: attempt to free unused irq %d\n", irq);
+-		if(dev_ids[irq] != dev_id)
+-			panic("sun3_free_int: incorrect dev_id for irq %d\n", irq);
+-
+-		sun3_inthandler[irq] = NULL;
+-		return;
+-	} else if((irq >= 64) && (irq <= 255)) {
+-		int vec;
+-
+-		vec = irq - 64;
+-		if(sun3_vechandler[vec] == NULL)
+-			panic("sun3_free_int: attempt to free unused vector %d\n", irq);
+-		if(vec_ids[irq] != dev_id)
+-			panic("sun3_free_int: incorrect dev_id for vec %d\n", irq);
+-
+-		sun3_vechandler[vec] = NULL;
+-		return;
+-	} else {
+-		panic("sun3_free_irq: invalid irq %d\n", irq);
+-	}
+-}
++static struct irq_controller sun3_irq_controller = {
++	.name		= "sun3",
++	.lock		= SPIN_LOCK_UNLOCKED,
++	.startup	= m68k_irq_startup,
++	.shutdown	= m68k_irq_shutdown,
++	.enable		= sun3_enable_irq,
++	.disable	= sun3_disable_irq,
++};
+ 
+-irqreturn_t sun3_process_int(int irq, struct pt_regs *regs)
++void sun3_init_IRQ(void)
+ {
++	*sun3_intreg = 1;
+ 
+-	if((irq >= 64) && (irq <= 255)) {
+-		int vec;
+-
+-		vec = irq - 64;
+-		if(sun3_vechandler[vec] == NULL)
+-			panic ("bad interrupt vector %d received\n",irq);
+-
+-		vec_ints[vec]++;
+-		return sun3_vechandler[vec](irq, vec_ids[vec], regs);
+-	} else {
+-		panic("sun3_process_int: unable to handle interrupt vector %d\n",
+-		      irq);
+-	}
++	m68k_setup_auto_interrupt(sun3_inthandle);
++	m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
++	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
++
++	request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL);
++	request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL);
++	request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL);
+ }
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/arch/m68k/sun3x/config.c linux-m68k/arch/m68k/sun3x/config.c
+--- linux-i386/arch/m68k/sun3x/config.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/arch/m68k/sun3x/config.c	2006-01-28 23:52:29.000000000 +0100
+@@ -52,17 +52,10 @@
+ 
+ 	sun3x_prom_init();
+ 
+-	mach_get_irq_list	 = show_sun3_interrupts;
+ 	mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
+ 
+-	mach_default_handler = &sun3_default_handler;
+ 	mach_sched_init      = sun3x_sched_init;
+ 	mach_init_IRQ        = sun3_init_IRQ;
+-	enable_irq           = sun3_enable_irq;
+-	disable_irq          = sun3_disable_irq;
+-	mach_request_irq     = sun3_request_irq;
+-	mach_free_irq        = sun3_free_irq;
+-	mach_process_int     = sun3_process_int;
+ 
+ 	mach_gettimeoffset   = sun3x_gettimeoffset;
+ 	mach_reset           = sun3x_reboot;
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/block/amiflop.c linux-m68k/drivers/block/amiflop.c
+--- linux-i386/drivers/block/amiflop.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/block/amiflop.c	2006-04-11 16:34:39.000000000 +0200
+@@ -64,6 +64,7 @@
+ #include <linux/buffer_head.h>
+ #include <linux/blkdev.h>
+ #include <linux/elevator.h>
++#include <linux/interrupt.h>
+ 
+ #include <asm/setup.h>
+ #include <asm/uaccess.h>
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/char/16c552.h linux-m68k/drivers/char/16c552.h
+--- linux-i386/drivers/char/16c552.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-m68k/drivers/char/16c552.h	2001-10-22 11:34:32.000000000 +0200
+@@ -0,0 +1,165 @@
++/*
++ * Definitions for the 16c552 DACE
++ * (dual-asynchronous-communications-element) used on the GVP
++ * IO-Extender. 
++ *
++ * Basically this is two 16c550 uarts's and a parallel port, which is
++ * why the serial definitions should be valid for the 16c550 uart
++ * aswell.
++ *
++ * Data was taken from National Semiconductors duart 16c552
++ * data-sheets and the Texas Instruments DACE 16c552 data-sheets (the
++ * NS version of the chip is _non_ standard and their data-sheets did
++ * cost me several wasted hours of work).
++ *
++ * This file is (C) 1995 Jes Sorensen (jds at kom.auc.dk)
++ *
++ * Moved from drivers/char/ to include/linux/, because it's useful
++ * on more than just the one card. I'm using it on the hp300 DCA
++ * serial driver, for example.  
++ *      -- Peter Maydell <pmaydell at chiark.greenend.org.uk> 05/1998
++ */
++
++#ifndef _16C552_H_
++#define _16C552_H_
++
++/* Serial stuff */
++
++struct uart_16c550 {
++	volatile u_char skip0;
++	volatile u_char RBR;
++	volatile u_char skip1;
++	volatile u_char IER;
++	volatile u_char skip2;
++	volatile u_char IIR;
++	volatile u_char skip3;
++	volatile u_char LCR;
++	volatile u_char skip4;
++	volatile u_char MCR;
++	volatile u_char skip5;
++	volatile u_char LSR;
++	volatile u_char skip6;
++	volatile u_char MSR;
++	volatile u_char skip7;
++	volatile u_char SCR;
++};
++
++#define THR RBR
++#define FCR IIR
++#define DLL RBR
++#define DLM IER
++#define AFR IIR
++
++/*
++ * Bit-defines for the various registers.
++ */
++
++
++/* IER */
++
++#define ERDAI         (1<<0)
++#define ETHREI        (1<<1)
++#define ELSI          (1<<2)
++#define EMSI          (1<<3)
++
++/* IIR - Interrupt Ident. Register */
++
++#define IRQ_PEND      (1<<0) /* NOTE: IRQ_PEND=0 implies irq pending */
++#define IRQ_ID1       (1<<1)
++#define IRQ_ID2       (1<<2)
++#define IRQ_ID3       (1<<3)
++#define FIFO_ENA0     (1<<6) /* Both these are set when FCR(1<<0)=1 */
++#define FIFO_ENA1     (1<<7)
++
++#define IRQ_RLS  (IRQ_ID1 | IRQ_ID2)
++#define IRQ_RDA  (IRQ_ID2)
++#define IRQ_CTI  (IRQ_ID2 | IRQ_ID3)
++#define IRQ_THRE (IRQ_ID1)
++#define IRQ_MS   0
++
++/* FCR - FIFO Control Register */
++
++#define FIFO_ENA      (1<<0)
++#define RCVR_FIFO_RES (1<<1)
++#define XMIT_FIFO_RES (1<<2)
++#define DMA_MODE_SEL  (1<<3)
++#define RCVR_TRIG_LSB (1<<6)
++#define RCVR_TRIG_MSB (1<<7)
++
++#define FIFO_TRIG_1   0x00
++#define FIFO_TRIG_4   RCVR_TRIG_LSB
++#define FIFO_TRIG_8   RCVR_TRIG_MSB
++#define FIFO_TRIG_14  RCVR_TRIG_LSB|RCVR_TRIG_MSB
++
++/* LCR - Line Control Register */
++
++#define WLS0          (1<<0)
++#define WLS1          (1<<1)
++#define STB           (1<<2)
++#define PEN           (1<<3)
++#define EPS           (1<<4)
++#define STICK_PARITY  (1<<5)
++#define SET_BREAK     (1<<6)
++#define DLAB          (1<<7)
++
++#define data_5bit      0x00
++#define data_6bit      0x01
++#define data_7bit      0x02
++#define data_8bit      0x03
++
++
++/* MCR - Modem Control Register */
++
++#define DTR           (1<<0)
++#define RTS           (1<<1)
++#define OUT1          (1<<2)
++#define OUT2          (1<<3)
++#define LOOP          (1<<4)
++
++/* LSR - Line Status Register */
++
++#define DR            (1<<0)
++#define OE            (1<<1)
++#define PE            (1<<2)
++#define FE            (1<<3)
++#define BI            (1<<4)
++#define THRE          (1<<5)
++#define TEMT          (1<<6)
++#define RCVR_FIFO_ERR (1<<7)
++
++/* MSR - Modem Status Register */
++
++#define DCTS          (1<<0)
++#define DDSR          (1<<1)
++#define TERI          (1<<2)
++#define DDCD          (1<<3)
++#define CTS           (1<<4)
++#define DSR           (1<<5)
++#define RING_I        (1<<6)
++#define DCD           (1<<7)
++
++/* AFR - Alternate Function Register */
++
++#define CONCUR_WRITE  (1<<0)
++#define BAUDOUT       (1<<1)
++#define RXRDY         (1<<2)
++
++/* Parallel stuff */
++
++/*
++ * Unfortunately National Semiconductors did not supply the
++ * specifications for the parallel port in the chip :-(
++ * TI succed though, so here they are :-)
++ *
++ * Defines for the bits can be found by including <linux/lp.h>
++ */
++struct IOEXT_par {
++	volatile u_char skip0;
++	volatile u_char DATA;
++	volatile u_char skip1;
++	volatile u_char STATUS;
++	volatile u_char skip2;
++	volatile u_char CTRL;
++};
++
++#endif
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/char/ioext.h linux-m68k/drivers/char/ioext.h
+--- linux-i386/drivers/char/ioext.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-m68k/drivers/char/ioext.h	2001-10-22 11:34:32.000000000 +0200
+@@ -0,0 +1,108 @@
++/*
++ * Shared data structure for GVP IO-Extender support.
++ *
++ * Merge of ioext.h and ser_ioext.h
++ */
++#ifndef _IOEXT_H_
++#define _IOEXT_H_
++
++#include <linux/config.h>
++#include <linux/netdevice.h>
++
++#include "16c552.h"
++
++#define MAX_IOEXT 5 /*
++		     * The maximum number of io-extenders is 5, as you
++		     * can't have more than 5 ZII boards in any Amiga.
++		     */
++
++#define UART_CLK 7372800
++
++#define IOEXT_BAUD_BASE (UART_CLK / 16)
++
++#define IOEXT_MAX_LINES 2
++
++#define IOEXT_PAR_PLIP  0x0001
++#define IOEXT_PAR_LP    0x0002
++
++
++/*
++ * Macros for the serial driver.
++ */
++#define curruart(info) ((struct uart_16c550 *)(info->port))
++
++#define ser_DTRon(info)  curruart(info)->MCR |=  DTR
++#define ser_RTSon(info)  curruart(info)->MCR |=  RTS
++#define ser_DTRoff(info) curruart(info)->MCR &= ~DTR
++#define ser_RTSoff(info) curruart(info)->MCR &= ~RTS
++
++
++/*
++ * CNTR defines (copied from the GVP SCSI-driver file gvp11.h
++ */
++#define GVP_BUSY	(1<<0)
++#define GVP_IRQ_PEND	(1<<1)
++#define GVP_IRQ_ENA 	(1<<3)
++#define GVP_DIR_WRITE   (1<<4)
++
++
++/*
++ * CTRL defines 
++ */
++#define PORT0_MIDI   (1<<0)  /* CLR = DRIVERS         SET = MIDI      */
++#define PORT1_MIDI   (1<<1)  /* CLR = DRIVERS         SET = MIDI      */
++#define PORT0_DRIVER (1<<2)  /* CLR = RS232,          SET = MIDI      */
++#define PORT1_DRIVER (1<<3)  /* CLR = RS232,          SET = MIDI      */
++#define IRQ_SEL      (1<<4)  /* CLR = INT2,           SET = INT6      */
++#define ROM_BANK_SEL (1<<5)  /* CLR = LOW 32K,        SET = HIGH 32K  */
++#define PORT0_CTRL   (1<<6)  /* CLR = RTSx or RXRDYx, SET = RTSx ONLY */
++#define PORT1_CTRL   (1<<7)  /* CLR = RTSx or RXRDYx, SET = RTSx ONLY */
++
++
++/*
++ * This is the struct describing the registers on the IO-Extender.
++ * NOTE: The board uses a dual uart (16c552), which should be equal to
++ * two 16c550 uarts.
++ */
++typedef struct {
++	char gap0[0x41];
++	volatile unsigned char CNTR;	/* GVP DMAC CNTR (status register)   */
++	char gap1[0x11e];
++	struct uart_16c550 uart0;	/* The first uart                    */
++	char gap2[0xf0];
++	struct uart_16c550 uart1;	/* The second uart                   */
++	char gap3[0xf0];
++	struct IOEXT_par par;		/* The parallel port                 */
++	char gap4[0xfb];
++	volatile unsigned char CTRL;	/* The control-register on the board */
++} IOEXT_struct;
++
++
++typedef struct {
++	int num_uarts;
++	int line[IOEXT_MAX_LINES];
++	volatile struct uart_16c550 *uart[IOEXT_MAX_LINES];
++	IOEXT_struct *board;
++	int spurious_count;
++	unsigned char par_use;		/* IOEXT_PAR_xxx */
++#if defined(CONFIG_GVPIOEXT_PLIP) || defined(CONFIG_GVPIOEXT_PLIP_MODULE)
++	struct nt_device *dev;
++#endif
++#if defined(CONFIG_GVPIOEXT_LP) || defined(CONFIG_GVPIOEXT_LP_MODULE)
++	struct lp_struct *lp_table;
++	int lp_dev;
++	int lp_interrupt;
++#endif
++} IOExtInfoType;
++
++/* Number of detected boards.  */
++extern int ioext_num;
++extern IOExtInfoType ioext_info[MAX_IOEXT];
++
++void ioext_plip_interrupt(struct net_device *dev, int *spurious_count);
++void ioext_lp_interrupt(int dev, int *spurious_count);
++
++extern struct net_device ioext_dev_plip[3];
++extern struct lp_struct ioext_lp_table[1];
++
++#endif
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/char/mc68681.h linux-m68k/drivers/char/mc68681.h
+--- linux-i386/drivers/char/mc68681.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-m68k/drivers/char/mc68681.h	2001-10-22 11:34:32.000000000 +0200
+@@ -0,0 +1,131 @@
++#ifndef _MC68681_H_
++#define _MC68681_H_
++
++/* 
++ * This describes an MC68681 DUART. It has almost only overlayed registers, which
++ * the structure very ugly.
++ * Note that the ri-register isn't really a register of the duart but a kludge of bsc
++ * to make the ring indicator available.
++ * 
++ * The data came from the MFC-31-Developer Kit (from Ralph Seidel,
++ * zodiac at darkness.gun.de) and the data sheet of Phillip's clone device (SCN68681)
++ * (from Richard Hirst, srh at gpt.co.uk)
++ *
++ * 11.11.95 copyright Joerg Dorchain (dorchain at mpi-sb.mpg.de)
++ *
++ */
++
++struct duarthalf {
++union {
++volatile u_char mr1; /* rw */
++volatile u_char mr2; /* rw */
++}  mr;
++volatile u_char ri;   /* special, read */
++union {
++volatile u_char sr;  /* read */
++volatile u_char csr; /* write */
++} sr_csr;
++u_char pad1;
++volatile u_char cr; /* write */
++u_char pad2;
++union {
++volatile u_char rhr; /* read */
++volatile u_char thr; /* write */
++} hr;
++u_char pad3;
++};
++
++struct duart {
++struct duarthalf pa;
++union {
++volatile u_char ipcr; /* read */
++volatile u_char acr;  /* write */
++} ipcr_acr;
++u_char pad1;
++union {
++volatile u_char isr; /* read */
++volatile u_char imr; /* write */
++} ir;
++u_char pad2;
++volatile u_char ctu;
++u_char pad3;
++volatile u_char ctl;
++u_char pad4;
++struct duarthalf pb;
++volatile u_char ivr;
++u_char pad5;
++union {
++volatile u_char ipr; /* read */
++volatile u_char opcr; /* write */
++} ipr_opcr;
++u_char pad6;
++union {
++volatile u_char start; /* read */
++volatile u_char sopc; /* write */
++} start_sopc;
++u_char pad7;
++union {
++volatile u_char stop; /* read */
++volatile u_char ropc; /* write */
++} stop_ropc;
++u_char pad8;
++};
++
++#define MR1_BITS 3
++#define MR1_5BITS 0
++#define MR1_6BITS 1
++#define MR1_7BITS 2
++#define MR1_8BITS 3
++
++#define MR1_PARITY_ODD 4
++
++#define MR1_PARITY 24
++#define MR1_PARITY_WITH 0
++#define MR1_PARITY_FORCE 8
++#define MR1_PARITY_NO 16
++#define MR1_PARITY_MULTIDROP 24
++
++#define MR1_ERROR_BLOCK 32
++#define MR1_FFULL_IRQ 64
++#define MR1_RxRTS_ON 128
++
++#define MR2_STOPS 15
++#define MR2_1STOP 7
++#define MR2_2STOP 15
++
++#define MR2_CTS_ON 16
++#define MR2_TxRTS_ON 32
++
++#define MR2_MODE 192
++#define MR2_NORMAL 0
++#define MR2_ECHO 64
++#define MR2_LOCALLOOP 128
++#define MR2_REMOTELOOP 192
++
++#define CR_RXCOMMAND 3
++#define CR_NONE 0
++#define CR_RX_ON 1
++#define CR_RX_OFF 2
++#define CR_TXCOMMAND 12
++#define CR_TX_ON 4
++#define CR_TX_OFF 8
++#define CR_MISC 112
++#define CR_RESET_MR 16
++#define CR_RESET_RX 32
++#define CR_RESET_TX 48
++#define CR_RESET_ERR 64
++#define CR_RESET_BREAK 80
++#define CR_START_BREAK 96
++#define CR_STOP_BREAK 112
++
++#define SR_RXRDY 1
++#define SR_FFULL 2
++#define SR_TXRDY 4
++#define SR_TXEMPT 8
++#define SR_OVERRUN 16
++#define SR_PARITY 32
++#define SR_FRAMING 64
++#define SR_BREAK 128
++
++
++#endif
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/char/plip_ioext.c linux-m68k/drivers/char/plip_ioext.c
+--- linux-i386/drivers/char/plip_ioext.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-m68k/drivers/char/plip_ioext.c	2004-10-24 22:59:56.000000000 +0200
+@@ -0,0 +1,1058 @@
++/*
++ * plip_ioext: A parallel port "network" driver for GVP IO-Extender.
++ *
++ * Authors:	See drivers/net/plip.c
++ *              IO-Extender version by Steve Bennett, <msteveb at ozemail.com.au>
++ *
++ * This driver is for use with a 5-bit cable (LapLink (R) cable).
++ */
++
++static const char *version = "NET3 PLIP version 2.2/m68k";
++
++#define __NO_VERSION__
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/termios.h>
++#include <linux/tty.h>
++#include <linux/serial.h>
++
++#include <asm/setup.h>
++#include <asm/irq.h>
++#include <asm/amigahw.h>
++#include <asm/amigaints.h>
++#include <linux/zorro.h>
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/fcntl.h>
++#include <linux/string.h>
++#include <linux/ptrace.h>
++#include <linux/if_ether.h>
++
++#include <asm/system.h>
++
++#include <linux/in.h>
++#include <linux/delay.h>
++/*#include <linux/lp_m68k.h>*/
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/skbuff.h>
++#include <linux/if_plip.h>
++
++#include <linux/tqueue.h>
++#include <linux/ioport.h>
++#include <linux/bitops.h>
++#include <asm/byteorder.h>
++
++#include "ioext.h"
++
++#define DEBUG 0
++
++/* Map 'struct device *' to our control structure */
++#define PLIP_DEV(DEV) (&ioext_info[(DEV)->irq])
++
++/************************************************************************
++**
++** PLIP definitions
++**
++*************************************************************************
++*/
++
++/* Use 0 for production, 1 for verification, >2 for debug */
++#ifndef NET_DEBUG
++#define NET_DEBUG 2
++#endif
++static unsigned int net_debug = NET_DEBUG;
++
++/* In micro second */
++#define PLIP_DELAY_UNIT       1
++
++/* Connection time out = PLIP_TRIGGER_WAIT * PLIP_DELAY_UNIT usec */
++#define PLIP_TRIGGER_WAIT	 500
++
++/* Nibble time out = PLIP_NIBBLE_WAIT * PLIP_DELAY_UNIT usec */
++#define PLIP_NIBBLE_WAIT        3000
++
++#define PAR_DATA(dev)     ((dev)->base_addr+0)
++#define PAR_STATUS(dev)   ((dev)->base_addr+2)
++#define PAR_CONTROL(dev)  ((dev)->base_addr+4)
++
++static void enable_par_irq(struct device *dev, int on);
++static int plip_init(struct device *dev);
++
++/* Bottom halfs */
++static void plip_kick_bh(struct device *dev);
++static void plip_bh(struct device *dev);
++
++/* Functions for DEV methods */
++static int plip_rebuild_header(struct sk_buff *skb);
++static int plip_tx_packet(struct sk_buff *skb, struct device *dev);
++static int plip_open(struct device *dev);
++static int plip_close(struct device *dev);
++static struct enet_statistics *plip_get_stats(struct device *dev);
++static int plip_config(struct device *dev, struct ifmap *map);
++static int plip_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
++
++enum plip_connection_state {
++	PLIP_CN_NONE=0,
++	PLIP_CN_RECEIVE,
++	PLIP_CN_SEND,
++	PLIP_CN_CLOSING,
++	PLIP_CN_ERROR
++};
++
++enum plip_packet_state {
++	PLIP_PK_DONE=0,
++	PLIP_PK_TRIGGER,
++	PLIP_PK_LENGTH_LSB,
++	PLIP_PK_LENGTH_MSB,
++	PLIP_PK_DATA,
++	PLIP_PK_CHECKSUM
++};
++
++enum plip_nibble_state {
++	PLIP_NB_BEGIN,
++	PLIP_NB_1,
++	PLIP_NB_2,
++};
++
++struct plip_local {
++	enum plip_packet_state state;
++	enum plip_nibble_state nibble;
++	union {
++		struct {
++#if defined(__LITTLE_ENDIAN)
++			unsigned char lsb;
++			unsigned char msb;
++#elif defined(__BIG_ENDIAN)
++			unsigned char msb;
++			unsigned char lsb;
++#else
++#error  "Please fix the endianness defines in <asm/byteorder.h>"
++#endif            
++		} b;
++		unsigned short h;
++	} length;
++	unsigned short byte;
++	unsigned char  checksum;
++	unsigned char  data;
++	struct sk_buff *skb;
++};
++
++struct net_local {
++	struct enet_statistics enet_stats;
++	struct tq_struct immediate;
++	struct tq_struct deferred;
++	struct plip_local snd_data;
++	struct plip_local rcv_data;
++	unsigned long  trigger;
++	unsigned long  nibble;
++	enum plip_connection_state connection;
++	unsigned short timeout_count;
++	char is_deferred;
++	int (*orig_rebuild_header)(struct sk_buff *skb);
++};
++
++struct device ioext_dev_plip[] = {
++	{
++		"plip0",
++		0, 0, 0, 0,    /* memory */
++		0, 0,    /* base, irq */
++		0, 0, 0, NULL, plip_init 
++	},
++	{
++		"plip1",
++		0, 0, 0, 0,    /* memory */
++		0, 0,    /* base, irq */
++		0, 0, 0, NULL, plip_init 
++	},
++	{
++		"plip2",
++		0, 0, 0, 0,    /* memory */
++		0, 0,    /* base, irq */
++		0, 0, 0, NULL, plip_init 
++	}
++};
++
++/*
++ * Check for and handle an interrupt for this PLIP device.
++ *
++ */
++void ioext_plip_interrupt(struct device *dev, int *spurious_count)
++{
++	struct net_local *nl;
++	struct plip_local *rcv;
++	unsigned char c0;
++	unsigned long flags;
++
++	nl = (struct net_local *)dev->priv;
++	rcv = &nl->rcv_data;
++
++	c0 = z_readb(PAR_STATUS(dev));
++
++	if (dev->interrupt) {
++		return;
++	}
++
++	if ((c0 & 0xf8) != 0xc0) {
++		/* Not for us */
++		++*spurious_count;
++		return;
++	}
++
++	*spurious_count = 0;
++	dev->interrupt = 1;
++
++	local_irq_save(flags);
++
++	switch (nl->connection) {
++	case PLIP_CN_CLOSING:
++		dev->tbusy = 0;
++	case PLIP_CN_NONE:
++	case PLIP_CN_SEND:
++		dev->last_rx = jiffies;
++		rcv->state = PLIP_PK_TRIGGER;
++		nl->connection = PLIP_CN_RECEIVE;
++		nl->timeout_count = 0;
++		queue_task(&nl->immediate, &tq_immediate);
++		mark_bh(IMMEDIATE_BH);
++		local_irq_restore(flags);
++#if 0
++		printk("%s: receive irq in SEND/NONE/CLOSING (%d) ok\n",
++		       dev->name, nl->connection);
++#endif
++		break;
++
++	case PLIP_CN_RECEIVE:
++		local_irq_restore(flags);
++		printk("%s: receive interrupt when receiving packet\n",
++		       dev->name);
++		break;
++
++	case PLIP_CN_ERROR:
++		local_irq_restore(flags);
++		printk("%s: receive interrupt in error state\n", dev->name);
++		break;
++	}
++}
++
++
++/* Bottom half handler for the delayed request.
++   This routine is kicked by do_timer().
++   Request `plip_bh' to be invoked. */
++static void
++plip_kick_bh(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++
++	if (nl->is_deferred) {
++		queue_task(&nl->immediate, &tq_immediate);
++		mark_bh(IMMEDIATE_BH);
++	}
++}
++
++/* Forward declarations of internal routines */
++static int plip_none(struct device *, struct net_local *,
++		     struct plip_local *, struct plip_local *);
++static int plip_receive_packet(struct device *, struct net_local *,
++			       struct plip_local *, struct plip_local *);
++static int plip_send_packet(struct device *, struct net_local *,
++			    struct plip_local *, struct plip_local *);
++static int plip_connection_close(struct device *, struct net_local *,
++				 struct plip_local *, struct plip_local *);
++static int plip_error(struct device *, struct net_local *,
++		      struct plip_local *, struct plip_local *);
++static int plip_bh_timeout_error(struct device *dev, struct net_local *nl,
++				 struct plip_local *snd,
++				 struct plip_local *rcv,
++				 int error);
++
++#define OK        0
++#define TIMEOUT   1
++#define ERROR     2
++
++typedef int (*plip_func)(struct device *dev, struct net_local *nl,
++			 struct plip_local *snd, struct plip_local *rcv);
++
++static plip_func connection_state_table[] =
++{
++	plip_none,
++	plip_receive_packet,
++	plip_send_packet,
++	plip_connection_close,
++	plip_error
++};
++
++/*
++** enable_par_irq()
++** 
++** Enable or disable parallel irq for 'dev' according to 'on'.
++**
++** It is NOT possible to disable only the parallel irq.
++** So we disable the board interrupt instead. This means that
++** during reception of a PLIP packet, no serial interrupts can
++** happen. Sorry.
++*/
++static void enable_par_irq(struct device *dev, int on)
++{
++	if (on) {
++		PLIP_DEV(dev)->board->CNTR |= GVP_IRQ_ENA;
++	}
++	else {
++		PLIP_DEV(dev)->board->CNTR &= ~GVP_IRQ_ENA;
++	}
++}
++
++/* Bottom half handler of PLIP. */
++static void
++plip_bh(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct plip_local *snd = &nl->snd_data;
++	struct plip_local *rcv = &nl->rcv_data;
++	plip_func f;
++	int r;
++
++	nl->is_deferred = 0;
++	f = connection_state_table[nl->connection];
++	if ((r = (*f)(dev, nl, snd, rcv)) != OK
++	    && (r = plip_bh_timeout_error(dev, nl, snd, rcv, r)) != OK) {
++		nl->is_deferred = 1;
++		queue_task(&nl->deferred, &tq_timer);
++	}
++}
++
++static int
++plip_bh_timeout_error(struct device *dev, struct net_local *nl,
++		      struct plip_local *snd, struct plip_local *rcv,
++		      int error)
++{
++	unsigned char c0;
++	unsigned long flags;
++
++	local_irq_save(flags);
++	if (nl->connection == PLIP_CN_SEND) {
++
++		if (error != ERROR) { /* Timeout */
++			nl->timeout_count++;
++			if ((snd->state == PLIP_PK_TRIGGER
++			     && nl->timeout_count <= 10)
++			    || nl->timeout_count <= 3) {
++				local_irq_restore(flags);
++				/* Try again later */
++				return TIMEOUT;
++			}
++			c0 = z_readb(PAR_STATUS(dev));
++			printk(KERN_INFO "%s: transmit timeout(%d,%02x)\n",
++			       dev->name, snd->state, c0);
++		}
++		nl->enet_stats.tx_errors++;
++		nl->enet_stats.tx_aborted_errors++;
++	} else if (nl->connection == PLIP_CN_RECEIVE) {
++		if (rcv->state == PLIP_PK_TRIGGER) {
++			/* Transmission was interrupted. */
++			local_irq_restore(flags);
++			return OK;
++		}
++		if (error != ERROR) { /* Timeout */
++			if (++nl->timeout_count <= 3) {
++				local_irq_restore(flags);
++				/* Try again later */
++				return TIMEOUT;
++			}
++			c0 = z_readb(PAR_STATUS(dev));
++			printk(KERN_INFO "%s: receive timeout(%d,%02x)\n",
++			       dev->name, rcv->state, c0);
++		}
++		nl->enet_stats.rx_dropped++;
++	}
++	rcv->state = PLIP_PK_DONE;
++	if (rcv->skb) {
++		kfree_skb(rcv->skb);
++		rcv->skb = NULL;
++	}
++	snd->state = PLIP_PK_DONE;
++	if (snd->skb) {
++		dev_kfree_skb(snd->skb);
++		snd->skb = NULL;
++	}
++	enable_par_irq(dev, 0);
++	dev->tbusy = 1;
++	nl->connection = PLIP_CN_ERROR;
++	z_writeb(0x00, PAR_DATA(dev));
++	local_irq_restore(flags);
++
++	return TIMEOUT;
++}
++
++static int
++plip_none(struct device *dev, struct net_local *nl,
++	  struct plip_local *snd, struct plip_local *rcv)
++{
++	return OK;
++}
++
++/* PLIP_RECEIVE --- receive a byte(two nibbles)
++   Returns OK on success, TIMEOUT on timeout */
++inline static int
++plip_receive(struct device *dev, unsigned short nibble_timeout, 
++	     enum plip_nibble_state *ns_p, unsigned char *data_p)
++{
++	unsigned char c0, c1;
++	unsigned int cx;
++
++	switch (*ns_p) {
++	case PLIP_NB_BEGIN:
++		cx = nibble_timeout;
++		while (1) {
++			c0 = z_readb(PAR_STATUS(dev));
++			udelay(PLIP_DELAY_UNIT);
++			if ((c0 & 0x80) == 0) {
++				c1 = z_readb(PAR_STATUS(dev));
++				if (c0 == c1)
++					break;
++			}
++			if (--cx == 0)
++				return TIMEOUT;
++		}
++#if 0
++		printk("received first nybble: %02X -> %02X\n",
++		       c0, (c0 >> 3) & 0x0F);
++#endif
++		*data_p = (c0 >> 3) & 0x0f;
++		z_writeb(0x10, PAR_DATA(dev)); /* send ACK */
++		*ns_p = PLIP_NB_1;
++
++	case PLIP_NB_1:
++		cx = nibble_timeout;
++		while (1) {
++			c0 = z_readb(PAR_STATUS(dev));
++			udelay(PLIP_DELAY_UNIT);
++			if (c0 & 0x80) {
++				c1 = z_readb(PAR_STATUS(dev));
++				if (c0 == c1)
++					break;
++			}
++			if (--cx == 0)
++				return TIMEOUT;
++		}
++#if 0
++		printk("received second nybble: %02X -> %02X\n",
++		       c0, (c0 << 1) & 0xF0);
++#endif
++		*data_p |= (c0 << 1) & 0xf0;
++		z_writeb(0x00, PAR_DATA(dev)); /* send ACK */
++		*ns_p = PLIP_NB_BEGIN;
++	case PLIP_NB_2:
++		break;
++	}
++	return OK;
++}
++
++/* PLIP_RECEIVE_PACKET --- receive a packet */
++static int
++plip_receive_packet(struct device *dev, struct net_local *nl,
++		    struct plip_local *snd, struct plip_local *rcv)
++{
++	unsigned short nibble_timeout = nl->nibble;
++	unsigned char *lbuf;
++	unsigned long flags;
++
++	switch (rcv->state) {
++	case PLIP_PK_TRIGGER:
++		enable_par_irq(dev, 0);
++		dev->interrupt = 0;
++		z_writeb(0x01, PAR_DATA(dev)); /* send ACK */
++		if (net_debug > 2)
++			printk(KERN_DEBUG "%s: receive start\n", dev->name);
++		rcv->state = PLIP_PK_LENGTH_LSB;
++		rcv->nibble = PLIP_NB_BEGIN;
++
++	case PLIP_PK_LENGTH_LSB:
++		if (snd->state != PLIP_PK_DONE) {
++			if (plip_receive(dev, nl->trigger,
++					 &rcv->nibble, &rcv->length.b.lsb)) {
++				/* collision, here dev->tbusy == 1 */
++				rcv->state = PLIP_PK_DONE;
++				nl->is_deferred = 1;
++				nl->connection = PLIP_CN_SEND;
++				queue_task(&nl->deferred, &tq_timer);
++				enable_par_irq(dev, 1);
++				return OK;
++			}
++		} else {
++			if (plip_receive(dev, nibble_timeout, 
++					 &rcv->nibble, &rcv->length.b.lsb))
++				return TIMEOUT;
++		}
++		rcv->state = PLIP_PK_LENGTH_MSB;
++
++	case PLIP_PK_LENGTH_MSB:
++		if (plip_receive(dev, nibble_timeout, 
++				 &rcv->nibble, &rcv->length.b.msb))
++			return TIMEOUT;
++		if (rcv->length.h > dev->mtu + dev->hard_header_len
++		    || rcv->length.h < 8) {
++			printk(KERN_INFO "%s: bogus packet size %d.\n",
++			       dev->name, rcv->length.h);
++			return ERROR;
++		}
++		/* Malloc up new buffer. */
++		rcv->skb = dev_alloc_skb(rcv->length.h);
++		if (rcv->skb == NULL) {
++			printk(KERN_INFO "%s: Memory squeeze.\n", dev->name);
++			return ERROR;
++		}
++		skb_put(rcv->skb,rcv->length.h);
++		rcv->skb->dev = dev;
++		rcv->state = PLIP_PK_DATA;
++		rcv->byte = 0;
++		rcv->checksum = 0;
++
++	case PLIP_PK_DATA:
++		lbuf = rcv->skb->data;
++		do
++			if (plip_receive(dev, nibble_timeout, 
++					 &rcv->nibble, &lbuf[rcv->byte]))
++				return TIMEOUT;
++		while (++rcv->byte < rcv->length.h);
++		do
++			rcv->checksum += lbuf[--rcv->byte];
++		while (rcv->byte);
++		rcv->state = PLIP_PK_CHECKSUM;
++
++	case PLIP_PK_CHECKSUM:
++		if (plip_receive(dev, nibble_timeout, 
++				 &rcv->nibble, &rcv->data))
++			return TIMEOUT;
++		if (rcv->data != rcv->checksum) {
++			nl->enet_stats.rx_crc_errors++;
++			if (net_debug)
++				printk(KERN_INFO "%s: checksum error\n",
++				       dev->name);
++			return ERROR;
++		}
++		rcv->state = PLIP_PK_DONE;
++
++	case PLIP_PK_DONE:
++		/* Inform the upper layer for the arrival of a packet. */
++		rcv->skb->protocol=eth_type_trans(rcv->skb, dev);
++		netif_rx(rcv->skb);
++		nl->enet_stats.rx_packets++;
++		rcv->skb = NULL;
++		if (net_debug > 2)
++			printk(KERN_DEBUG "%s: receive end\n", dev->name);
++
++		/* Close the connection. */
++		z_writeb (0x00, PAR_DATA(dev));
++
++		local_irq_save(flags);
++		if (snd->state != PLIP_PK_DONE) {
++			nl->connection = PLIP_CN_SEND;
++			local_irq_restore(flags);
++			queue_task(&nl->immediate, &tq_immediate);
++			mark_bh(IMMEDIATE_BH);
++			enable_par_irq(dev, 1);
++			return OK;
++		} else {
++			nl->connection = PLIP_CN_NONE;
++			local_irq_restore(flags);
++			enable_par_irq(dev, 1);
++			return OK;
++		}
++	}
++	return OK;
++}
++
++/* PLIP_SEND --- send a byte (two nibbles) 
++   Returns OK on success, TIMEOUT when timeout    */
++inline static int
++plip_send(struct device *dev, unsigned short nibble_timeout, 
++	  enum plip_nibble_state *ns_p, unsigned char data)
++{
++	unsigned char c0;
++	unsigned int cx;
++
++	switch (*ns_p) {
++	case PLIP_NB_BEGIN:
++		z_writeb((data & 0x0f), PAR_DATA(dev));
++		*ns_p = PLIP_NB_1;
++
++	case PLIP_NB_1:
++		z_writeb(0x10 | (data & 0x0f), PAR_DATA(dev));
++		cx = nibble_timeout;
++		while (1) {
++			c0 = z_readb(PAR_STATUS(dev));
++			if ((c0 & 0x80) == 0) 
++				break;
++			if (--cx == 0)
++				return TIMEOUT;
++			udelay(PLIP_DELAY_UNIT);
++		}
++		z_writeb(0x10 | (data >> 4), PAR_DATA(dev));
++		*ns_p = PLIP_NB_2;
++
++	case PLIP_NB_2:
++		z_writeb((data >> 4), PAR_DATA(dev));
++		cx = nibble_timeout;
++		while (1) {
++			c0 = z_readb(PAR_STATUS(dev));
++			if (c0 & 0x80)
++				break;
++			if (--cx == 0)
++				return TIMEOUT;
++			udelay(PLIP_DELAY_UNIT);
++		}
++		*ns_p = PLIP_NB_BEGIN;
++		return OK;
++	}
++	return OK;
++}
++
++/* PLIP_SEND_PACKET --- send a packet */
++static int
++plip_send_packet(struct device *dev, struct net_local *nl,
++		 struct plip_local *snd, struct plip_local *rcv)
++{
++	unsigned short nibble_timeout = nl->nibble;
++	unsigned char *lbuf;
++	unsigned char c0;
++	unsigned int cx;
++	unsigned long flags;
++
++	if (snd->skb == NULL || (lbuf = snd->skb->data) == NULL) {
++		printk(KERN_INFO "%s: send skb lost\n", dev->name);
++		snd->state = PLIP_PK_DONE;
++		snd->skb = NULL;
++		return ERROR;
++	}
++
++	if (snd->length.h == 0) {
++		return OK;
++	}
++
++	switch (snd->state) {
++	case PLIP_PK_TRIGGER:
++		if ((z_readb(PAR_STATUS(dev)) & 0xf8) != 0x80)
++			return TIMEOUT;
++
++		/* Trigger remote rx interrupt. */
++		z_writeb(0x08, PAR_DATA(dev));
++		cx = nl->trigger;
++		while (1) {
++			udelay(PLIP_DELAY_UNIT);
++                        local_irq_save(flags);
++			if (nl->connection == PLIP_CN_RECEIVE) {
++				local_irq_restore(flags);
++				/* interrupted */
++				nl->enet_stats.collisions++;
++				if (net_debug > 1)
++					printk(KERN_INFO "%s: collision.\n",
++					       dev->name);
++				return OK;
++			}
++			c0 = z_readb(PAR_STATUS(dev));
++			if (c0 & 0x08) {
++				enable_par_irq(dev, 0);
++				if (net_debug > 2)
++					printk(KERN_DEBUG "%s: send start\n",
++					       dev->name);
++				snd->state = PLIP_PK_LENGTH_LSB;
++				snd->nibble = PLIP_NB_BEGIN;
++				nl->timeout_count = 0;
++				local_irq_restore(flags);
++				break;
++			}
++			local_irq_restore(flags);
++			if (--cx == 0) {
++				z_writeb(0x00, PAR_DATA(dev));
++				return TIMEOUT;
++			}
++		}
++
++	case PLIP_PK_LENGTH_LSB:
++		if (plip_send(dev, nibble_timeout, 
++			      &snd->nibble, snd->length.b.lsb))
++			return TIMEOUT;
++		snd->state = PLIP_PK_LENGTH_MSB;
++
++	case PLIP_PK_LENGTH_MSB:
++		if (plip_send(dev, nibble_timeout, 
++			      &snd->nibble, snd->length.b.msb))
++			return TIMEOUT;
++		snd->state = PLIP_PK_DATA;
++		snd->byte = 0;
++		snd->checksum = 0;
++
++	case PLIP_PK_DATA:
++		do
++			if (plip_send(dev, nibble_timeout, 
++				      &snd->nibble, lbuf[snd->byte]))
++				return TIMEOUT;
++		while (++snd->byte < snd->length.h);
++		do
++			snd->checksum += lbuf[--snd->byte];
++		while (snd->byte);
++		snd->state = PLIP_PK_CHECKSUM;
++
++	case PLIP_PK_CHECKSUM:
++		if (plip_send(dev, nibble_timeout, 
++			      &snd->nibble, snd->checksum))
++			return TIMEOUT;
++
++		dev_kfree_skb(snd->skb);
++		nl->enet_stats.tx_packets++;
++		snd->state = PLIP_PK_DONE;
++
++	case PLIP_PK_DONE:
++		/* Close the connection */
++		z_writeb (0x00, PAR_DATA(dev));
++		snd->skb = NULL;
++		if (net_debug > 2)
++			printk(KERN_DEBUG "%s: send end\n", dev->name);
++		nl->connection = PLIP_CN_CLOSING;
++		nl->is_deferred = 1;
++		queue_task(&nl->deferred, &tq_timer);
++		enable_par_irq(dev, 1);
++		return OK;
++	}
++	return OK;
++}
++
++static int
++plip_connection_close(struct device *dev, struct net_local *nl,
++		      struct plip_local *snd, struct plip_local *rcv)
++{
++	unsigned long flags;
++
++        local_irq_save(flags);
++	if (nl->connection == PLIP_CN_CLOSING) {
++		nl->connection = PLIP_CN_NONE;
++		dev->tbusy = 0;
++		mark_bh(NET_BH);
++	}
++	local_irq_restore(flags);
++	return OK;
++}
++
++/* PLIP_ERROR --- wait till other end settled */
++static int
++plip_error(struct device *dev, struct net_local *nl,
++	   struct plip_local *snd, struct plip_local *rcv)
++{
++	unsigned char status;
++
++	status = z_readb(PAR_STATUS(dev));
++	if ((status & 0xf8) == 0x80) {
++		if (net_debug > 2)
++			printk(KERN_DEBUG "%s: reset interface.\n", dev->name);
++		nl->connection = PLIP_CN_NONE;
++		dev->tbusy = 0;
++		dev->interrupt = 0;
++		enable_par_irq(dev, 1);
++		mark_bh(NET_BH);
++	} else {
++		nl->is_deferred = 1;
++		queue_task(&nl->deferred, &tq_timer);
++	}
++
++	return OK;
++}
++
++/* We don't need to send arp, for plip is point-to-point. */
++static int
++plip_rebuild_header(struct sk_buff *skb)
++{
++	struct device *dev = skb->dev;
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct ethhdr *eth = (struct ethhdr *)skb->data;
++	int i;
++
++	if ((dev->flags & IFF_NOARP)==0)
++		return nl->orig_rebuild_header(skb);
++
++	if (eth->h_proto != __constant_htons(ETH_P_IP)
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++	    && eth->h_proto != __constant_htons(ETH_P_IPV6)
++#endif
++		) {
++		printk(KERN_ERR "plip_rebuild_header: Don't know how to resolve type %d addresses?\n", (int)eth->h_proto);
++		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
++		return 0;
++	}
++
++	for (i=0; i < ETH_ALEN - sizeof(u32); i++)
++		eth->h_dest[i] = 0xfc;
++#if 0
++	*(u32 *)(eth->h_dest+i) = dst;
++#else
++	/* Do not want to include net/route.h here.
++	 * In any case, it is TOP of silliness to emulate
++	 * hardware addresses on PtP link. --ANK
++	 */
++	*(u32 *)(eth->h_dest+i) = 0;
++#endif
++	return 0;
++}
++
++static int
++plip_tx_packet(struct sk_buff *skb, struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct plip_local *snd = &nl->snd_data;
++	unsigned long flags;
++
++	if (dev->tbusy)
++		return 1;
++
++	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
++		printk(KERN_ERR "%s: Transmitter access conflict.\n",
++		       dev->name);
++		return 1;
++	}
++
++	if (skb->len > dev->mtu + dev->hard_header_len) {
++		printk(KERN_ERR "%s: packet too big, %d.\n",
++		       dev->name, (int)skb->len);
++		dev->tbusy = 0;
++		return 0;
++	}
++
++	if (net_debug > 2)
++		printk(KERN_DEBUG "%s: send request\n", dev->name);
++
++	local_irq_save(flags);
++	dev->trans_start = jiffies;
++	snd->skb = skb;
++	snd->length.h = skb->len;
++	snd->state = PLIP_PK_TRIGGER;
++	if (nl->connection == PLIP_CN_NONE) {
++		nl->connection = PLIP_CN_SEND;
++		nl->timeout_count = 0;
++	}
++	queue_task(&nl->immediate, &tq_immediate);
++	mark_bh(IMMEDIATE_BH);
++	local_irq_restore(flags);
++
++	return 0;
++}
++
++/* Open/initialize the board.  This is called (in the current kernel)
++   sometime after booting when the 'ifconfig' program is run.
++
++ */
++static int
++plip_open(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct in_device *in_dev;
++
++#if defined(CONFIG_GVPIOEXT_LP) || defined(CONFIG_GVPIOEXT_LP_MODULE)
++	/* Yes, there is a race condition here. Fix it later */
++	if (PLIP_DEV(dev)->par_use & IOEXT_PAR_LP) {
++		/* Can't open if lp is in use */
++#if DEBUG
++		printk("par is in use by lp\n");
++#endif
++		return(-EBUSY);
++	}
++#endif
++	PLIP_DEV(dev)->par_use |= IOEXT_PAR_PLIP;
++
++#if DEBUG
++	printk("plip_open(): sending 00 to data port\n");
++#endif
++
++	/* Clear the data port. */
++	z_writeb (0x00, PAR_DATA(dev));
++
++#if DEBUG
++	printk("plip_open(): sent\n");
++#endif
++
++	/* Initialize the state machine. */
++	nl->rcv_data.state = nl->snd_data.state = PLIP_PK_DONE;
++	nl->rcv_data.skb = nl->snd_data.skb = NULL;
++	nl->connection = PLIP_CN_NONE;
++	nl->is_deferred = 0;
++
++	/* Fill in the MAC-level header.
++	   (ab)Use "dev->broadcast" to store point-to-point MAC address.
++
++	   PLIP doesn't have a real mac address, but we need to create one
++	   to be DOS compatible.  */
++	memset(dev->dev_addr,  0xfc, ETH_ALEN);
++	memset(dev->broadcast, 0xfc, ETH_ALEN);
++
++	if ((in_dev=dev->ip_ptr) != NULL) {
++		/*
++		 *	Any address will do - we take the first
++		 */
++		struct in_ifaddr *ifa=in_dev->ifa_list;
++		if (ifa != NULL) {
++			memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
++			memcpy(dev->broadcast+2, &ifa->ifa_address, 4);
++		}
++	}
++
++	dev->interrupt = 0;
++	dev->start = 1;
++	dev->tbusy = 0;
++
++	MOD_INC_USE_COUNT;
++
++	/* Enable rx interrupt. */
++	enable_par_irq(dev, 1);
++
++	return 0;
++}
++
++/* The inverse routine to plip_open (). */
++static int
++plip_close(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct plip_local *snd = &nl->snd_data;
++	struct plip_local *rcv = &nl->rcv_data;
++	unsigned long flags;
++
++	dev->tbusy = 1;
++	dev->start = 0;
++        local_irq_save(flags);
++	nl->is_deferred = 0;
++	nl->connection = PLIP_CN_NONE;
++	local_irq_restore(flags);
++	z_writeb(0x00, PAR_DATA(dev));
++
++	snd->state = PLIP_PK_DONE;
++	if (snd->skb) {
++		dev_kfree_skb(snd->skb);
++		snd->skb = NULL;
++	}
++	rcv->state = PLIP_PK_DONE;
++	if (rcv->skb) {
++		kfree_skb(rcv->skb);
++		rcv->skb = NULL;
++	}
++
++	PLIP_DEV(dev)->par_use &= ~IOEXT_PAR_PLIP;
++
++	MOD_DEC_USE_COUNT;
++	return 0;
++}
++
++static struct enet_statistics *
++plip_get_stats(struct device *dev)
++{
++	struct net_local *nl = (struct net_local *)dev->priv;
++	struct enet_statistics *r = &nl->enet_stats;
++
++	return r;
++}
++
++static int
++plip_config(struct device *dev, struct ifmap *map)
++{
++	if (dev->flags & IFF_UP)
++		return -EBUSY;
++
++	printk(KERN_INFO "%s: This interface is autodetected (ignored).\n",
++	       dev->name);
++
++	return 0;
++}
++
++static int
++plip_ioctl(struct device *dev, struct ifreq *rq, int cmd)
++{
++	struct net_local *nl = (struct net_local *) dev->priv;
++	struct plipconf *pc = (struct plipconf *) &rq->ifr_data;
++  
++	switch(pc->pcmd) {
++	case PLIP_GET_TIMEOUT:
++		pc->trigger = nl->trigger;
++		pc->nibble  = nl->nibble;
++		break;
++	case PLIP_SET_TIMEOUT:
++		nl->trigger = pc->trigger;
++		nl->nibble  = pc->nibble;
++		break;
++	default:
++		return -EOPNOTSUPP;
++	}
++	return 0;
++}
++
++/*
++ * Detect and initialize all IO-Extenders in this system.
++ *
++ * Both PLIP and serial devices are configured.
++ */
++int plip_init(struct device *dev)
++{
++	IOEXT_struct *board;
++	struct net_local *nl;
++
++	if (ioext_num == 0) {
++		printk(KERN_INFO "%s\n", version);
++	}
++
++	board = PLIP_DEV(dev)->board;
++	dev->base_addr = (unsigned long)&board->par.DATA;
++
++	/* Cheat and use irq to index into our table */
++	dev->irq = ioext_num;
++
++	printk(KERN_INFO "%s: IO-Extender parallel port at 0x%08lX\n", dev->name, dev->base_addr);
++
++	/* Fill in the generic fields of the device structure. */
++	ether_setup(dev);
++
++	/* Then, override parts of it */
++	dev->hard_start_xmit  = plip_tx_packet;
++	dev->open    = plip_open;
++	dev->stop    = plip_close;
++	dev->get_stats     = plip_get_stats;
++	dev->set_config    = plip_config;
++	dev->do_ioctl    = plip_ioctl;
++	dev->tx_queue_len  = 10;
++	dev->flags          = IFF_POINTOPOINT|IFF_NOARP;
++
++	/* Set the private structure */
++	dev->priv = kmalloc(sizeof (struct net_local), GFP_KERNEL);
++	if (dev->priv == NULL) {
++		printk(KERN_ERR "%s: out of memory\n", dev->name);
++		return -ENOMEM;
++	}
++	memset(dev->priv, 0, sizeof(struct net_local));
++	nl = (struct net_local *) dev->priv;
++
++	nl->orig_rebuild_header = dev->rebuild_header;
++	dev->rebuild_header   = plip_rebuild_header;
++
++	/* Initialize constants */
++	nl->trigger  = PLIP_TRIGGER_WAIT;
++	nl->nibble  = PLIP_NIBBLE_WAIT;
++
++	/* Initialize task queue structures */
++	nl->immediate.next = NULL;
++	nl->immediate.sync = 0;
++	nl->immediate.routine = (void *)(void *)plip_bh;
++	nl->immediate.data = dev;
++
++	nl->deferred.next = NULL;
++	nl->deferred.sync = 0;
++	nl->deferred.routine = (void *)(void *)plip_kick_bh;
++	nl->deferred.data = dev;
++
++	/* Don't enable interrupts yet */
++
++	return 0;
++}
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/char/serial167.c linux-m68k/drivers/char/serial167.c
+--- linux-i386/drivers/char/serial167.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/char/serial167.c	2006-04-11 16:34:45.000000000 +0200
+@@ -1434,7 +1434,6 @@
+   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
+   unsigned long flags;
+   unsigned char status;
+-  unsigned int result;
+ 
+     channel = info->line;
+ 
+@@ -1458,7 +1457,6 @@
+   int channel;
+   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
+   unsigned long flags;
+-  unsigned int arg;
+ 	  
+     channel = info->line;
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/ide/ide-iops.c linux-m68k/drivers/ide/ide-iops.c
+--- linux-i386/drivers/ide/ide-iops.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/ide/ide-iops.c	2006-04-11 16:35:25.000000000 +0200
+@@ -337,6 +337,23 @@
+ 	int i;
+ 	u16 *stringcast;
+ 
++#ifdef __mc68000__
++	if (!MACH_IS_AMIGA && !MACH_IS_MAC && !MACH_IS_Q40 && !MACH_IS_ATARI)
++		return;
++
++#ifdef M68K_IDE_SWAPW
++	if (M68K_IDE_SWAPW) {	/* fix bus byteorder first */
++		u_char *p = (u_char *)id;
++		u_char t;
++		for (i = 0; i < 512; i += 2) {
++			t = p[i];
++			p[i] = p[i+1];
++			p[i+1] = t;
++		}
++	}
++#endif
++#endif /* __mc68000__ */
++
+ 	id->config         = __le16_to_cpu(id->config);
+ 	id->cyls           = __le16_to_cpu(id->cyls);
+ 	id->reserved2      = __le16_to_cpu(id->reserved2);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/ide/legacy/gayle.c linux-m68k/drivers/ide/legacy/gayle.c
+--- linux-i386/drivers/ide/legacy/gayle.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/ide/legacy/gayle.c	2005-09-02 00:29:58.000000000 +0200
+@@ -161,6 +161,7 @@
+ 	base = (unsigned long)ZTWO_VADDR(phys_base);
+ 	ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
+ 
++	memset(&hw, 0, sizeof(hw));
+ 	ide_setup_ports(&hw, base, gayle_offsets,
+ 			ctrlport, irqport, ack_intr,
+ //			&gayle_iops,
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/input/keyboard/Kconfig linux-m68k/drivers/input/keyboard/Kconfig
+--- linux-i386/drivers/input/keyboard/Kconfig	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/input/keyboard/Kconfig	2006-04-11 16:35:35.000000000 +0200
+@@ -155,7 +155,7 @@
+ 
+ config KEYBOARD_HIL_OLD
+ 	tristate "HP HIL keyboard support (simple driver)"
+-	depends on GSC
++	depends on GSC || HP300
+ 	default y
+ 	help
+ 	  The "Human Interface Loop" is a older, 8-channel USB-like
+@@ -172,7 +172,7 @@
+ 
+ config KEYBOARD_HIL
+ 	tristate "HP HIL keyboard support"
+-	depends on GSC
++	depends on GSC || HP300
+ 	default y
+ 	select HP_SDC
+ 	select HIL_MLC
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/input/keyboard/amikbd.c linux-m68k/drivers/input/keyboard/amikbd.c
+--- linux-i386/drivers/input/keyboard/amikbd.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/input/keyboard/amikbd.c	2006-01-28 23:53:40.000000000 +0100
+@@ -36,6 +36,7 @@
+ #include <linux/input.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
++#include <linux/keyboard.h>
+ 
+ #include <asm/amigaints.h>
+ #include <asm/amigahw.h>
+@@ -45,7 +46,7 @@
+ MODULE_DESCRIPTION("Amiga keyboard driver");
+ MODULE_LICENSE("GPL");
+ 
+-static unsigned char amikbd_keycode[0x78] = {
++static unsigned char amikbd_keycode[0x78] __initdata = {
+ 	[0]	 = KEY_GRAVE,
+ 	[1]	 = KEY_1,
+ 	[2]	 = KEY_2,
+@@ -170,12 +171,9 @@
+ 	scancode >>= 1;
+ 
+ 	if (scancode < 0x78) {		/* scancodes < 0x78 are keys */
+-
+-		scancode = amikbd_keycode[scancode];
+-
+ 		input_regs(amikbd_dev, fp);
+ 
+-		if (scancode == KEY_CAPSLOCK) {	/* CapsLock is a toggle switch key on Amiga */
++		if (scancode == 98) {	/* CapsLock is a toggle switch key on Amiga */
+ 			input_report_key(amikbd_dev, scancode, 1);
+ 			input_report_key(amikbd_dev, scancode, 0);
+ 		} else {
+@@ -191,7 +189,7 @@
+ 
+ static int __init amikbd_init(void)
+ {
+-	int i;
++	int i, j;
+ 
+ 	if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
+ 		return -EIO;
+@@ -214,14 +212,26 @@
+ 	amikbd_dev->id.version = 0x0100;
+ 
+ 	amikbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+-	amikbd_dev->keycode = amikbd_keycode;
+-	amikbd_dev->keycodesize = sizeof(unsigned char);
+-	amikbd_dev->keycodemax = ARRAY_SIZE(amikbd_keycode);
+ 
+ 	for (i = 0; i < 0x78; i++)
+-		if (amikbd_keycode[i])
+-			set_bit(amikbd_keycode[i], amikbd_dev->keybit);
++		set_bit(i, amikbd_dev->keybit);
+ 
++	for (i = 0; i < MAX_NR_KEYMAPS; i++) {
++		static u_short temp_map[NR_KEYS] __initdata;
++		if (!key_maps[i])
++			continue;
++		memset(temp_map, 0, sizeof(temp_map));
++		for (j = 0; j < 0x78; j++) {
++			if (!amikbd_keycode[j])
++				continue;
++			temp_map[j] = key_maps[i][amikbd_keycode[j]];
++		}
++		for (j = 0; j < NR_KEYS; j++) {
++			if (!temp_map[j])
++				temp_map[j] = 0xf200;
++		}
++		memcpy(key_maps[i], temp_map, sizeof(temp_map));
++	}
+ 	ciaa.cra &= ~0x41;	 /* serial data in, turn off TA */
+ 	request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/input/misc/Kconfig linux-m68k/drivers/input/misc/Kconfig
+--- linux-i386/drivers/input/misc/Kconfig	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/input/misc/Kconfig	2006-04-11 16:35:36.000000000 +0200
+@@ -73,7 +73,7 @@
+ 
+ config HP_SDC_RTC
+ 	tristate "HP SDC Real Time Clock"       
+-	depends on GSC
++	depends on GSC || HP300
+ 	select HP_SDC
+ 	help
+ 	  Say Y here if you want to support the built-in real time clock
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/input/mouse/Kconfig linux-m68k/drivers/input/mouse/Kconfig
+--- linux-i386/drivers/input/mouse/Kconfig	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/input/mouse/Kconfig	2006-04-11 16:35:36.000000000 +0200
+@@ -119,7 +119,7 @@
+ 
+ config MOUSE_HIL
+ 	tristate "HIL pointers (mice etc)."     
+-	depends on GSC
++	depends on GSC || HP300
+ 	select HP_SDC
+ 	select HIL_MLC
+ 	help
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/input/serio/Kconfig linux-m68k/drivers/input/serio/Kconfig
+--- linux-i386/drivers/input/serio/Kconfig	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/input/serio/Kconfig	2005-08-29 21:17:45.000000000 +0200
+@@ -112,7 +112,7 @@
+ 
+ config HP_SDC
+ 	tristate "HP System Device Controller i8042 Support"
+-	depends on GSC && SERIO
++	depends on (GSC || HP300) && SERIO
+ 	default y
+ 	---help---
+ 	  This option enables supports for the the "System Device
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/macintosh/adb.c linux-m68k/drivers/macintosh/adb.c
+--- linux-i386/drivers/macintosh/adb.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/macintosh/adb.c	2006-01-19 22:07:24.000000000 +0100
+@@ -476,13 +476,15 @@
+ 		use_sreq = 1;
+ 	} else
+ 		use_sreq = 0;
+-	req->nbytes = nbytes+1;
++	i = (flags & ADBREQ_RAW) ? 0 : 1;
++	req->nbytes = nbytes+i;
+ 	req->done = done;
+ 	req->reply_expected = flags & ADBREQ_REPLY;
+ 	req->data[0] = ADB_PACKET;
+ 	va_start(list, nbytes);
+-	for (i = 0; i < nbytes; ++i)
+-		req->data[i+1] = va_arg(list, int);
++	while (i < req->nbytes) {
++		req->data[i++] = va_arg(list, int);
++	}
+ 	va_end(list);
+ 
+ 	if (flags & ADBREQ_NOSEND)
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/net/7990.c linux-m68k/drivers/net/7990.c
+--- linux-i386/drivers/net/7990.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/net/7990.c	2005-10-11 22:57:19.000000000 +0200
+@@ -500,7 +500,7 @@
+ 	int res;
+         
+         /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
+-        if (request_irq(lp->irq, lance_interrupt, 0, lp->name, dev))
++        if (request_irq(lp->irq, lance_interrupt, SA_SHIRQ, lp->name, dev))
+                 return -EAGAIN;
+ 
+         res = lance_reset(dev);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/net/Kconfig linux-m68k/drivers/net/Kconfig
+--- linux-i386/drivers/net/Kconfig	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/net/Kconfig	2006-04-11 16:36:26.000000000 +0200
+@@ -307,7 +307,7 @@
+ 
+ config MAC89x0
+ 	tristate "Macintosh CS89x0 based ethernet cards"
+-	depends on NET_ETHERNET && MAC && BROKEN
++	depends on NET_ETHERNET && MAC
+ 	---help---
+ 	  Support for CS89x0 chipset based Ethernet cards.  If you have a
+ 	  Nubus or LC-PDS network (Ethernet) card of this type, say Y and
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/net/hplance.c linux-m68k/drivers/net/hplance.c
+--- linux-i386/drivers/net/hplance.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/net/hplance.c	2006-04-11 16:36:30.000000000 +0200
+@@ -77,6 +77,7 @@
+ {
+ 	struct net_device *dev;
+ 	int err = -ENOMEM;
++	int i;
+ 
+ 	dev = alloc_etherdev(sizeof(struct hplance_private));
+ 	if (!dev)
+@@ -93,6 +94,15 @@
+ 		goto out_release_mem_region;
+ 
+ 	dio_set_drvdata(d, dev);
++
++	printk(KERN_INFO "%s: %s; select code %d, addr %2.2x", dev->name, d->name, d->scode, dev->dev_addr[0]);
++
++	for (i=1; i<6; i++) {
++		printk(":%2.2x", dev->dev_addr[i]);
++	}
++
++	printk(", irq %d\n", d->ipl);
++
+ 	return 0;
+ 
+  out_release_mem_region:
+@@ -118,9 +128,7 @@
+         unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
+         struct hplance_private *lp;
+         int i;
+-        
+-        printk(KERN_INFO "%s: %s; select code %d, addr", dev->name, d->name, d->scode);
+-
++ 
+         /* reset the board */
+         out_8(va+DIO_IDOFF, 0xff);
+         udelay(100);                              /* ariba! ariba! udelay! udelay! */
+@@ -143,7 +151,6 @@
+                  */
+                 dev->dev_addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
+                         | (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
+-                printk("%c%2.2x", i == 0 ? ' ' : ':', dev->dev_addr[i]);
+         }
+         
+         lp = netdev_priv(dev);
+@@ -160,7 +167,6 @@
+         lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
+         lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
+         lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
+-	printk(", irq %d\n", lp->lance.irq);
+ }
+ 
+ /* This is disgusting. We have to check the DIO status register for ack every
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/net/mac89x0.c linux-m68k/drivers/net/mac89x0.c
+--- linux-i386/drivers/net/mac89x0.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/net/mac89x0.c	2004-12-30 01:59:08.000000000 +0100
+@@ -128,7 +128,7 @@
+ extern void reset_chip(struct net_device *dev);
+ #endif
+ static int net_open(struct net_device *dev);
+-static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
++static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
+ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+ static void set_multicast_list(struct net_device *dev);
+ static void net_rx(struct net_device *dev);
+@@ -374,56 +374,37 @@
+ static int
+ net_send_packet(struct sk_buff *skb, struct net_device *dev)
+ {
+-	if (dev->tbusy) {
+-		/* If we get here, some higher level has decided we are broken.
+-		   There should really be a "kick me" function call instead. */
+-		int tickssofar = jiffies - dev->trans_start;
+-		if (tickssofar < 5)
+-			return 1;
+-		if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
+-			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
+-		/* Try to restart the adaptor. */
+-		dev->tbusy=0;
+-		dev->trans_start = jiffies;
+-	}
+-
+-	/* Block a timer-based transmit from overlapping.  This could better be
+-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
+-		printk("%s: Transmitter access conflict.\n", dev->name);
+-	else {
+-		struct net_local *lp = netdev_priv(dev);
+-		unsigned long flags;
+-
+-		if (net_debug > 3)
+-			printk("%s: sent %d byte packet of type %x\n",
+-			       dev->name, skb->len,
+-			       (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+-			       | skb->data[ETH_ALEN+ETH_ALEN+1]);
+-
+-		/* keep the upload from being interrupted, since we
+-                   ask the chip to start transmitting before the
+-                   whole packet has been completely uploaded. */
+-		local_irq_save(flags);
+-
+-		/* initiate a transmit sequence */
+-		writereg(dev, PP_TxCMD, lp->send_cmd);
+-		writereg(dev, PP_TxLength, skb->len);
+-
+-		/* Test to see if the chip has allocated memory for the packet */
+-		if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
+-			/* Gasp!  It hasn't.  But that shouldn't happen since
+-			   we're waiting for TxOk, so return 1 and requeue this packet. */
+-			local_irq_restore(flags);
+-			return 1;
+-		}
++	struct net_local *lp = netdev_priv(dev);
++	unsigned long flags;
+ 
+-		/* Write the contents of the packet */
+-		memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
++	if (net_debug > 3)
++		printk("%s: sent %d byte packet of type %x\n",
++		       dev->name, skb->len,
++		       (skb->data[ETH_ALEN+ETH_ALEN] << 8)
++		       | skb->data[ETH_ALEN+ETH_ALEN+1]);
++
++	/* keep the upload from being interrupted, since we
++	   ask the chip to start transmitting before the
++	   whole packet has been completely uploaded. */
++	local_irq_save(flags);
+ 
++	/* initiate a transmit sequence */
++	writereg(dev, PP_TxCMD, lp->send_cmd);
++	writereg(dev, PP_TxLength, skb->len);
++
++	/* Test to see if the chip has allocated memory for the packet */
++	if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
++		/* Gasp!  It hasn't.  But that shouldn't happen since
++		   we're waiting for TxOk, so return 1 and requeue this packet. */
+ 		local_irq_restore(flags);
+-		dev->trans_start = jiffies;
++		return 1;
+ 	}
++
++	/* Write the contents of the packet */
++	memcpy((void *)(dev->mem_start + PP_TxFrame), skb->data, skb->len+1);
++
++	local_irq_restore(flags);
++	dev->trans_start = jiffies;
+ 	dev_kfree_skb (skb);
+ 
+ 	return 0;
+@@ -441,9 +422,6 @@
+ 		printk ("net_interrupt(): irq %d for unknown device.\n", irq);
+ 		return IRQ_NONE;
+ 	}
+-	if (dev->interrupt)
+-		printk("%s: Re-entering the interrupt handler.\n", dev->name);
+-	dev->interrupt = 1;
+ 
+ 	ioaddr = dev->base_addr;
+ 	lp = netdev_priv(dev);
+@@ -464,8 +442,7 @@
+ 			break;
+ 		case ISQ_TRANSMITTER_EVENT:
+ 			lp->stats.tx_packets++;
+-			dev->tbusy = 0;
+-			mark_bh(NET_BH);	/* Inform upper layers. */
++			netif_wake_queue(dev);
+ 			if ((status & TX_OK) == 0) lp->stats.tx_errors++;
+ 			if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
+ 			if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
+@@ -479,8 +456,7 @@
+                                    That shouldn't happen since we only ever
+                                    load one packet.  Shrug.  Do the right
+                                    thing anyway. */
+-				dev->tbusy = 0;
+-				mark_bh(NET_BH);	/* Inform upper layers. */
++				netif_wake_queue(dev);
+ 			}
+ 			if (status & TX_UNDERRUN) {
+ 				if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
+@@ -497,7 +473,6 @@
+ 			break;
+ 		}
+ 	}
+-	dev->interrupt = 0;
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -532,7 +507,7 @@
+ 	skb_put(skb, length);
+ 	skb->dev = dev;
+ 
+-	memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
++	memcpy(skb->data, (void *)(dev->mem_start + PP_RxFrame), length);
+ 
+ 	if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
+                                  dev->name, length,
+@@ -611,8 +586,6 @@
+ static int set_mac_address(struct net_device *dev, void *addr)
+ {
+ 	int i;
+-	if (dev->start)
+-		return -EBUSY;
+ 	printk("%s: Setting MAC address to ", dev->name);
+ 	for (i = 0; i < 6; i++)
+ 		printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/net/sun3lance.c linux-m68k/drivers/net/sun3lance.c
+--- linux-i386/drivers/net/sun3lance.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/net/sun3lance.c	2006-04-11 16:36:42.000000000 +0200
+@@ -55,7 +55,7 @@
+ /* sun3/60 addr/irq for the lance chip.  If your sun is different,
+    change this. */
+ #define LANCE_OBIO 0x120000
+-#define LANCE_IRQ IRQ3
++#define LANCE_IRQ IRQ_AUTO_3
+ 
+ /* Debug level:
+  *  0 = silent, print only serious errors
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/53c7xx.c linux-m68k/drivers/scsi/53c7xx.c
+--- linux-i386/drivers/scsi/53c7xx.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/53c7xx.c	2006-04-11 16:37:15.000000000 +0200
+@@ -308,7 +308,7 @@
+ 
+ static int check_address (unsigned long addr, int size);
+ static void dump_events (struct Scsi_Host *host, int count);
+-static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, 
++static struct scsi_cmnd * return_outstanding_commands (struct Scsi_Host *host, 
+     int free, int issue);
+ static void hard_reset (struct Scsi_Host *host);
+ static void ncr_scsi_reset (struct Scsi_Host *host);
+@@ -317,7 +317,7 @@
+     int scntl3, int now_connected);
+ static int datapath_residual (struct Scsi_Host *host);
+ static const char * sbcl_to_phase (int sbcl);
+-static void print_progress (Scsi_Cmnd *cmd);
++static void print_progress (struct scsi_cmnd *cmd);
+ static void print_queues (struct Scsi_Host *host);
+ static void process_issue_queue (unsigned long flags);
+ static int shutdown (struct Scsi_Host *host);
+@@ -342,9 +342,8 @@
+ static void NCR53c7x0_soft_reset (struct Scsi_Host *host);
+ 
+ /* Size of event list (per host adapter) */
+-static int track_events = 0;
+-static struct Scsi_Host *first_host = NULL;	/* Head of list of NCR boards */
+-static struct scsi_host_template *the_template = NULL;
++static int track_events;
++static struct scsi_host_template *the_template;
+ 
+ /* NCR53c710 script handling code */
+ 
+@@ -667,8 +666,11 @@
+ 
+ static struct Scsi_Host *
+ find_host (int host) {
+-    struct Scsi_Host *h;
+-    for (h = first_host; h && h->host_no != host; h = h->next);
++    struct Scsi_Host *h, *s;
++    list_for_each_entry_safe(h, s, &the_template->legacy_hosts, sht_legacy_list) {
++	if (h->host_no == host)
++	    break;
++    }
+     if (!h) {
+ 	printk (KERN_ALERT "scsi%d not found\n", host);
+ 	return NULL;
+@@ -716,14 +718,14 @@
+     }
+     hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0];
+ 
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     if (hostdata->initiate_sdtr & (1 << target)) {
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+ 	printk (KERN_ALERT "target %d already doing SDTR\n", target);
+ 	return -1;
+     } 
+     hostdata->initiate_sdtr |= (1 << target);
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+     return 0;
+ }
+ #endif
+@@ -1034,9 +1036,6 @@
+    
+     ccf = clock_to_ccf_710 (expected_clock);
+ 
+-    for (i = 0; i < 16; ++i) 
+-	hostdata->cmd_allocated[i] = 0;
+-
+     if (hostdata->init_save_regs)
+     	hostdata->init_save_regs (host);
+     if (hostdata->init_fixup)
+@@ -1044,7 +1043,6 @@
+ 
+     if (!the_template) {
+ 	the_template = host->hostt;
+-	first_host = host;
+     }
+ 
+     /* 
+@@ -1307,7 +1305,6 @@
+     hostdata->free->size = max_cmd_size;
+     hostdata->free->free = NULL;
+     hostdata->free->next = NULL;
+-    hostdata->extra_allocate = 0;
+ 
+     /* Allocate command start code space */
+     hostdata->schedule = (chip == 700 || chip == 70066) ?
+@@ -1590,10 +1587,10 @@
+ 
+     /* The NCR chip _must_ be idle to run the test scripts */
+ 
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     if (!hostdata->idle) {
+ 	printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+ 	return -1;
+     }
+ 
+@@ -1617,7 +1614,7 @@
+ 	    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM |
+ 						DCNTL_STD);
+ 	printk (" started\n");
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+ 
+ 	/* 
+ 	 * This is currently a .5 second timeout, since (in theory) no slow 
+@@ -1656,7 +1653,7 @@
+ 		hostdata->script, start);
+ 	    printk ("scsi%d : DSPS = 0x%x\n", host->host_no,
+ 		NCR53c7x0_read32(DSPS_REG));
+-	    local_irq_restore(flags);
++	    spin_unlock_irqrestore(host->host_lock, flags);
+ 	    return -1;
+ 	}
+     	hostdata->test_running = 0;
+@@ -1694,7 +1691,7 @@
+ 	    local_irq_disable();
+ 	    if (!hostdata->idle) {
+ 		printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
+-		local_irq_restore(flags);
++		spin_unlock_irqrestore(host->host_lock, flags);
+ 		return -1;
+ 	    }
+ 
+@@ -1710,7 +1707,7 @@
+ 	    if (hostdata->options & OPTION_DEBUG_TRACE)
+ 	        NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
+ 				DCNTL_SSM | DCNTL_STD);
+-	    local_irq_restore(flags);
++	    spin_unlock_irqrestore(host->host_lock, flags);
+ 
+ 	    timeout = jiffies + 5 * HZ;	/* arbitrary */
+ 	    while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
+@@ -1732,19 +1729,19 @@
+ 		    host->host_no, i);
+ 		if (!hostdata->idle) {
+ 		    printk("scsi%d : not idle\n", host->host_no);
+-		    local_irq_restore(flags);
++		    spin_unlock_irqrestore(host->host_lock, flags);
+ 		    return -1;
+ 		}
+ 	    } else if (hostdata->test_completed == -1) {
+ 		printk ("scsi%d : test 2 timed out\n", host->host_no);
+-		local_irq_restore(flags);
++		spin_unlock_irqrestore(host->host_lock, flags);
+ 		return -1;
+ 	    } 
+ 	    hostdata->test_running = 0;
+ 	}
+     }
+ 
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+     return 0;
+ }
+ 
+@@ -1760,7 +1757,7 @@
+ 
+ static void 
+ NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) {
+-    Scsi_Cmnd *c = cmd->cmd;
++    struct scsi_cmnd *c = cmd->cmd;
+     struct Scsi_Host *host = c->device->host;
+     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+     	host->hostdata[0];
+@@ -1846,7 +1843,7 @@
+  *
+  * Purpose : mark SCSI command as finished, OR'ing the host portion 
+  *	of the result word into the result field of the corresponding
+- *	Scsi_Cmnd structure, and removing it from the internal queues.
++ *	scsi_cmnd structure, and removing it from the internal queues.
+  *
+  * Inputs : cmd - command, result - entire result field
+  *
+@@ -1857,7 +1854,7 @@
+ 
+ static void 
+ abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {
+-    Scsi_Cmnd *c = cmd->cmd;
++    struct scsi_cmnd *c = cmd->cmd;
+     struct Scsi_Host *host = c->device->host;
+     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+     	host->hostdata[0];
+@@ -1871,7 +1868,7 @@
+     printk ("scsi%d: abnormal finished\n", host->host_no);
+ #endif
+ 
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     found = 0;
+     /* 
+      * Traverse the NCR issue array until we find a match or run out 
+@@ -1954,7 +1951,7 @@
+     c->result = result;
+     c->scsi_done(c);
+ 
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+     run_process_issue_queue();
+ }
+ 
+@@ -1976,7 +1973,7 @@
+     NCR53c7x0_local_declare();
+     struct NCR53c7x0_break *bp;
+ #if 0
+-    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
++    struct scsi_cmnd *c = cmd ? cmd->cmd : NULL;
+ #endif
+     u32 *dsp;
+     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+@@ -1989,7 +1986,7 @@
+      * dump the appropriate debugging information to standard 
+      * output.  
+      */
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
+     for (bp = hostdata->breakpoints; bp && bp->address != dsp; 
+     	bp = bp->next);
+@@ -2011,7 +2008,7 @@
+      * instruction in bytes.
+      */
+ 
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+ }
+ /*
+  * Function : static void print_synchronous (const char *prefix, 
+@@ -2253,7 +2250,7 @@
+     NCR53c7x0_cmd *cmd) {
+     NCR53c7x0_local_declare();
+     int print;
+-    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
++    struct scsi_cmnd *c = cmd ? cmd->cmd : NULL;
+     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+ 	host->hostdata[0];		
+     u32 dsps,*dsp;	/* Argument of the INT instruction */
+@@ -2917,7 +2914,7 @@
+ 	host->hostdata[0];
+     NCR53c7x0_local_setup(host);
+ 
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+ 
+     /* Disable scsi chip and s/w level 7 ints */
+ 
+@@ -3018,12 +3015,12 @@
+     }
+ #endif
+     /* Anything needed for your hardware? */
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+ }
+ 
+ 
+ /*
+- * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd)
++ * Function static struct NCR53c7x0_cmd *allocate_cmd (struct scsi_cmnd *cmd)
+  * 
+  * Purpose : Return the first free NCR53c7x0_cmd structure (which are 
+  * 	reused in a LIFO manner to minimize cache thrashing).
+@@ -3050,86 +3047,25 @@
+ }
+ 
+ static struct NCR53c7x0_cmd *
+-allocate_cmd (Scsi_Cmnd *cmd) {
++allocate_cmd (struct scsi_cmnd *cmd) {
+     struct Scsi_Host *host = cmd->device->host;
+     struct NCR53c7x0_hostdata *hostdata = 
+ 	(struct NCR53c7x0_hostdata *) host->hostdata[0];
+-    u32 real;			/* Real address */
+-    int size;			/* Size of *tmp */
+     struct NCR53c7x0_cmd *tmp;
+     unsigned long flags;
+ 
+     if (hostdata->options & OPTION_DEBUG_ALLOCATION)
+ 	printk ("scsi%d : num_cmds = %d, can_queue = %d\n"
+-		"         target = %d, lun = %d, %s\n",
++		"         target = %d, lun = %d\n",
+ 	    host->host_no, hostdata->num_cmds, host->can_queue,
+-	    cmd->device->id, cmd->device->lun, (hostdata->cmd_allocated[cmd->device->id] &
+-		(1 << cmd->device->lun)) ? "already allocated" : "not allocated");
+-
+-/*
+- * If we have not yet reserved commands for this I_T_L nexus, and
+- * the device exists (as indicated by permanent Scsi_Cmnd structures
+- * being allocated under 1.3.x, or being outside of scan_scsis in
+- * 1.2.x), do so now.
+- */
+-    if (!(hostdata->cmd_allocated[cmd->device->id] & (1 << cmd->device->lun)) &&
+-				cmd->device && cmd->device->has_cmdblocks) {
+-      if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue)
+-          hostdata->extra_allocate += host->cmd_per_lun;
+-      hostdata->cmd_allocated[cmd->device->id] |= (1 << cmd->device->lun);
+-    }
+-
+-    for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, 
+-    	++hostdata->num_cmds) {
+-    /* historically, kmalloc has returned unaligned addresses; pad so we
+-       have enough room to ROUNDUP */
+-	size = hostdata->max_cmd_size + sizeof (void *);
+-#ifdef FORCE_DSA_ALIGNMENT
+-	/*
+-	 * 53c710 rev.0 doesn't have an add-with-carry instruction.
+-	 * Ensure we allocate enough memory to force alignment.
+-	 */
+-	size += 256;
+-#endif
+-/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
++	    cmd->device->id, cmd->device->lun);
+ 
+-        if (size > 4096) {
+-            printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n");
+-	    return NULL;
+-	}
+-        real = get_zeroed_page(GFP_ATOMIC);
+-        if (real == 0)
+-        	return NULL;
+-        memset((void *)real, 0, 4096);
+-        cache_push(virt_to_phys((void *)real), 4096);
+-        cache_clear(virt_to_phys((void *)real), 4096);
+-        kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER);
+-	tmp = ROUNDUP(real, void *);
+-#ifdef FORCE_DSA_ALIGNMENT
+-	{
+-	    if (((u32)tmp & 0xff) > CmdPageStart)
+-		tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255);
+-	    tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart);
+-#if 0
+-	    printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n",
+-			size, real, (u32)tmp);
+-#endif
+-	}
+-#endif
+-	tmp->real = (void *)real;
+-	tmp->size = size;			
+-	tmp->free = ((void (*)(void *, int)) my_free_page);
+-	local_irq_save(flags);
+-	tmp->next = hostdata->free;
+-	hostdata->free = tmp;
+-	local_irq_restore(flags);
+-    }
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     tmp = (struct NCR53c7x0_cmd *) hostdata->free;
+     if (tmp) {
+ 	hostdata->free = tmp->next;
+     }
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+     if (!tmp)
+ 	printk ("scsi%d : can't allocate command for target %d lun %d\n",
+ 	    host->host_no, cmd->device->id, cmd->device->lun);
+@@ -3137,11 +3073,11 @@
+ }
+ 
+ /*
+- * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) 
++ * Function static struct NCR53c7x0_cmd *create_cmd (struct scsi_cmnd *cmd) 
+  *
+  *
+  * Purpose : allocate a NCR53c7x0_cmd structure, initialize it based on the 
+- * 	Scsi_Cmnd structure passed in cmd, including dsa and Linux field 
++ * 	scsi_cmnd structure passed in cmd, including dsa and Linux field 
+  * 	initialization, and dsa code relocation.
+  *
+  * Inputs : cmd - SCSI command
+@@ -3150,7 +3086,7 @@
+  *	NULL on failure.
+  */
+ static struct NCR53c7x0_cmd *
+-create_cmd (Scsi_Cmnd *cmd) {
++create_cmd (struct scsi_cmnd *cmd) {
+     NCR53c7x0_local_declare();
+     struct Scsi_Host *host = cmd->device->host;
+     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+@@ -3174,7 +3110,7 @@
+ 	return NULL;
+ 
+     /*
+-     * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd.
++     * Copy CDB and initialised result fields from scsi_cmnd to NCR53c7x0_cmd.
+      * We do this because NCR53c7x0_cmd may have a special cache mode
+      * selected to cope with lack of bus snooping, etc.
+      */
+@@ -3317,7 +3253,7 @@
+ 
+     patch_dsa_32(tmp->dsa, dsa_next, 0, 0);
+     /*
+-     * XXX is this giving 53c710 access to the Scsi_Cmnd in some way?
++     * XXX is this giving 53c710 access to the scsi_cmnd in some way?
+      * Do we need to change it for caching reasons?
+      */
+     patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd));
+@@ -3348,17 +3284,17 @@
+ 	memcpy ((void *) (tmp->select + 1), (void *) wdtr_message,
+ 	    sizeof(wdtr_message));
+     	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message));
+-	local_irq_save(flags);
++	spin_lock_irqsave(host->host_lock, flags);
+ 	hostdata->initiate_wdtr &= ~(1 << cmd->device->id);
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+     } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) {
+ 	memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, 
+ 	    sizeof(sdtr_message));
+     	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message));
+ 	tmp->flags |= CMD_FLAG_SDTR;
+-	local_irq_save(flags);
++	spin_lock_irqsave(host->host_lock, flags);
+ 	hostdata->initiate_sdtr &= ~(1 << cmd->device->id);
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+     
+     }
+ #if 1
+@@ -3571,8 +3507,8 @@
+ }
+ 
+ /*
+- * Function : int NCR53c7xx_queue_command (Scsi_Cmnd *cmd,
+- *      void (*done)(Scsi_Cmnd *))
++ * Function : int NCR53c7xx_queue_command (struct scsi_cmnd *cmd,
++ *      void (*done)(struct scsi_cmnd *))
+  *
+  * Purpose :  enqueues a SCSI command
+  *
+@@ -3586,18 +3522,18 @@
+  *      twiddling done to the host specific fields of cmd.  If the
+  *      process_issue_queue coroutine isn't running, it is restarted.
+  * 
+- * NOTE : we use the host_scribble field of the Scsi_Cmnd structure to 
++ * NOTE : we use the host_scribble field of the scsi_cmnd structure to 
+  *	hold our own data, and pervert the ptr field of the SCp field
+  *	to create a linked list.
+  */
+ 
+ int
+-NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
++NCR53c7xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) {
+     struct Scsi_Host *host = cmd->device->host;
+     struct NCR53c7x0_hostdata *hostdata = 
+ 	(struct NCR53c7x0_hostdata *) host->hostdata[0];
+     unsigned long flags;
+-    Scsi_Cmnd *tmp;
++    struct scsi_cmnd *tmp;
+ 
+     cmd->scsi_done = done;
+     cmd->host_scribble = NULL;
+@@ -3615,7 +3551,7 @@
+     }
+ #endif
+ 
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY)) 
+ 	|| ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
+ 	    !(hostdata->debug_lun_limit[cmd->device->id] & (1 << cmd->device->lun)))
+@@ -3630,7 +3566,7 @@
+ 	    cmd->device->id, cmd->device->lun);
+ 	cmd->result = (DID_BAD_TARGET << 16);
+ 	done(cmd);
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+ 	return 0;
+     }
+ 
+@@ -3639,7 +3575,7 @@
+ 	printk("scsi%d : maximum commands exceeded\n", host->host_no);
+ 	cmd->result = (DID_BAD_TARGET << 16);
+ 	done(cmd);
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+ 	return 0;
+     }
+ 
+@@ -3651,7 +3587,7 @@
+ 		host->host_no);
+ 	    cmd->result = (DID_BAD_TARGET << 16);
+ 	    done(cmd);
+-	    local_irq_restore(flags);
++	    spin_unlock_irqrestore(host->host_lock, flags);
+ 	    return 0;
+ 	}
+     }
+@@ -3674,18 +3610,18 @@
+ 	cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
+ 	hostdata->issue_queue = cmd;
+     } else {
+-	for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->SCp.ptr; 
+-		tmp = (Scsi_Cmnd *) tmp->SCp.ptr);
++	for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp->SCp.ptr; 
++		tmp = (struct scsi_cmnd *) tmp->SCp.ptr);
+ 	tmp->SCp.ptr = (unsigned char *) cmd;
+     }
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+     run_process_issue_queue();
+     return 0;
+ }
+ 
+ /*
+  * Function : void to_schedule_list (struct Scsi_Host *host,
+- * 	struct NCR53c7x0_hostdata * hostdata, Scsi_Cmnd *cmd)
++ * 	struct NCR53c7x0_hostdata * hostdata, struct scsi_cmnd *cmd)
+  *
+  * Purpose : takes a SCSI command which was just removed from the 
+  *	issue queue, and deals with it by inserting it in the first
+@@ -3706,7 +3642,7 @@
+ to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
+     struct NCR53c7x0_cmd *cmd) {
+     NCR53c7x0_local_declare();
+-    Scsi_Cmnd *tmp = cmd->cmd;
++    struct scsi_cmnd *tmp = cmd->cmd;
+     unsigned long flags;
+     /* dsa start is negative, so subtraction is used */
+     volatile u32 *ncrcurrent;
+@@ -3718,7 +3654,7 @@
+ 	virt_to_bus(hostdata->dsa), hostdata->dsa);
+ #endif
+ 
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     
+     /* 
+      * Work around race condition : if an interrupt fired and we 
+@@ -3731,7 +3667,7 @@
+ 	cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
+ 	hostdata->free = cmd;
+ 	tmp->scsi_done(tmp);
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+ 	return;
+     }
+ 
+@@ -3761,7 +3697,7 @@
+ 	cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
+ 	hostdata->free = cmd;
+ 	tmp->scsi_done(tmp);
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+ 	return;
+     }
+ 
+@@ -3782,12 +3718,12 @@
+ 	NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP);
+     }
+ 
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+ }
+ 
+ /*
+  * Function : busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata 
+- *	*hostdata, Scsi_Cmnd *cmd)
++ *	*hostdata, struct scsi_cmnd *cmd)
+  *
+  * Purpose : decide if we can pass the given SCSI command on to the 
+  *	device in question or not.
+@@ -3797,7 +3733,7 @@
+ 
+ static __inline__ int
+ busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, 
+-    Scsi_Cmnd *cmd) {
++    struct scsi_cmnd *cmd) {
+     /* FIXME : in the future, this needs to accommodate SCSI-II tagged
+        queuing, and we may be able to play with fairness here a bit.
+      */
+@@ -3823,8 +3759,8 @@
+ 
+ static void 
+ process_issue_queue (unsigned long flags) {
+-    Scsi_Cmnd *tmp, *prev;
+-    struct Scsi_Host *host;
++    struct scsi_cmnd *tmp, *prev;
++    struct Scsi_Host *host, *s;
+     struct NCR53c7x0_hostdata *hostdata;
+     int done;
+ 
+@@ -3842,14 +3778,13 @@
+     do {
+ 	local_irq_disable(); /* Freeze request queues */
+ 	done = 1;
+-	for (host = first_host; host && host->hostt == the_template;
+-	    host = host->next) {
++	list_for_each_entry_safe(host, s, &the_template->legacy_hosts, sht_legacy_list) {
+ 	    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
+-	    local_irq_disable();
++	    spin_lock_irq(host->host_lock);
+ 	    if (hostdata->issue_queue) {
+ 	    	if (hostdata->state == STATE_DISABLED) {
+-		    tmp = (Scsi_Cmnd *) hostdata->issue_queue;
+-		    hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
++		    tmp = (struct scsi_cmnd *) hostdata->issue_queue;
++		    hostdata->issue_queue = (struct scsi_cmnd *) tmp->SCp.ptr;
+ 		    tmp->result = (DID_BAD_TARGET << 16);
+ 		    if (tmp->host_scribble) {
+ 			((struct NCR53c7x0_cmd *)tmp->host_scribble)->next = 
+@@ -3861,15 +3796,15 @@
+ 		    tmp->scsi_done (tmp);
+ 		    done = 0;
+ 		} else 
+-		    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 
+-			prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) 
++		    for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, 
++			prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) 
+ 			tmp->SCp.ptr) 
+ 			if (!tmp->host_scribble || 
+ 			    !busyp (host, hostdata, tmp)) {
+ 				if (prev)
+ 				    prev->SCp.ptr = tmp->SCp.ptr;
+ 				else
+-				    hostdata->issue_queue = (Scsi_Cmnd *) 
++				    hostdata->issue_queue = (struct scsi_cmnd *) 
+ 					tmp->SCp.ptr;
+ 			    tmp->SCp.ptr = NULL;
+ 			    if (tmp->host_scribble) {
+@@ -3894,6 +3829,7 @@
+ 			    done = 0;
+ 			} /* if target/lun is not busy */
+ 	    } /* if hostdata->issue_queue */
++	    spin_unlock(host->host_lock);
+ 	    if (!done)
+ 		local_irq_restore(flags);
+     	} /* for host */
+@@ -4104,7 +4040,7 @@
+ 	int cnt = 0;
+ 	int i = insn_log_index;
+ 	int size;
+-	struct Scsi_Host *host = first_host;
++	struct Scsi_Host *host = (struct Scsi_Host *)the_template->legacy_hosts->next;
+ 
+ 	while (cnt < 4096) {
+ 		printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4);
+@@ -4162,14 +4098,14 @@
+     * completion.
+     */
+ 
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+ restart:
+     for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list),
+ 	cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
+ 	cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), 
+     	cmd = (struct NCR53c7x0_cmd *) cmd->next)
+     {
+-	Scsi_Cmnd *tmp;
++	struct scsi_cmnd *tmp;
+ 
+ 	if (!cmd) {
+ 	    printk("scsi%d : very weird.\n", host->host_no);
+@@ -4177,7 +4113,7 @@
+ 	}
+ 
+ 	if (!(tmp = cmd->cmd)) {
+-	    printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n",
++	    printk("scsi%d : weird.  NCR53c7x0_cmd has no scsi_cmnd\n",
+ 		    host->host_no);
+ 	    continue;
+ 	}
+@@ -4216,7 +4152,7 @@
+ 	tmp->scsi_done(tmp);
+ 	goto restart;
+     }
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+ 
+     if (!search_found)  {
+ 	printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
+@@ -4251,7 +4187,7 @@
+     struct NCR53c7x0_cmd *cmd;			/* command which halted */
+     u32 *dsa;					/* DSA */
+     int handled = 0;
+-
++    unsigned long flags;
+ #ifdef NCR_DEBUG
+     char buf[80];				/* Debugging sprintf buffer */
+     size_t buflen;				/* Length of same */
+@@ -4260,6 +4196,7 @@
+     host     = (struct Scsi_Host *)dev_id;
+     hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
+     NCR53c7x0_local_setup(host);
++    spin_lock_irqsave(host->host_lock, flags);
+ 
+     /*
+      * Only read istat once per loop, since reading it again will unstack
+@@ -4352,7 +4289,8 @@
+ 	    }
+ 	}
+     }
+-    return IRQ_HANDLED;
++    spin_unlock_irqrestore(host->host_lock, flags);
++    return IRQ_RETVAL(handled);
+ }
+ 
+ 
+@@ -4361,7 +4299,7 @@
+  *
+  * Purpose : Assuming that the NCR SCSI processor is currently 
+  * 	halted, break the currently established nexus.  Clean
+- *	up of the NCR53c7x0_cmd and Scsi_Cmnd structures should
++ *	up of the NCR53c7x0_cmd and scsi_cmnd structures should
+  *	be done on receipt of the abort interrupt.
+  *
+  * Inputs : host - SCSI host
+@@ -4900,12 +4838,12 @@
+ 	    /* Don't print instr. until we write DSP at end of intr function */
+ 	} else if (hostdata->options & OPTION_DEBUG_SINGLE) {
+ 	    print_insn (host, dsp, "s ", 0);
+-	    local_irq_save(flags);
++	    spin_lock_irqsave(host->host_lock, flags);
+ /* XXX - should we do this, or can we get away with writing dsp? */
+ 
+ 	    NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) & 
+     	    	~DCNTL_SSM) | DCNTL_STD);
+-	    local_irq_restore(flags);
++	    spin_unlock_irqrestore(host->host_lock, flags);
+ 	} else {
+ 	    printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n"
+ 		   "         ", host->host_no);
+@@ -5128,7 +5066,7 @@
+ }
+ 
+ /*
+- * Function : int NCR53c7xx_abort (Scsi_Cmnd *cmd)
++ * Function : int NCR53c7xx_abort (struct scsi_cmnd *cmd)
+  * 
+  * Purpose : Abort an errant SCSI command, doing all necessary
+  *	cleanup of the issue_queue, running_list, shared Linux/NCR
+@@ -5140,14 +5078,14 @@
+  */
+ 
+ int 
+-NCR53c7xx_abort (Scsi_Cmnd *cmd) {
++NCR53c7xx_abort (struct scsi_cmnd *cmd) {
+     NCR53c7x0_local_declare();
+     struct Scsi_Host *host = cmd->device->host;
+     struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) 
+ 	host->hostdata[0] : NULL;
+     unsigned long flags;
+     struct NCR53c7x0_cmd *curr, **prev;
+-    Scsi_Cmnd *me, **last;
++    struct scsi_cmnd *me, **last;
+ #if 0
+     static long cache_pid = -1;
+ #endif
+@@ -5156,10 +5094,10 @@
+     if (!host) {
+ 	printk ("Bogus SCSI command pid %ld; no host structure\n",
+ 	    cmd->pid);
+-	return SCSI_ABORT_ERROR;
++	return FAILED;
+     } else if (!hostdata) {
+ 	printk ("Bogus SCSI host %d; no hostdata\n", host->host_no);
+-	return SCSI_ABORT_ERROR;
++	return FAILED;
+     }
+     NCR53c7x0_local_setup(host);
+ 
+@@ -5180,10 +5118,10 @@
+ 	printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no,
+ 	    cmd->pid);
+ 	NCR53c7x0_intr (host->irq, NULL, NULL);
+-	return SCSI_ABORT_BUSY;
++	return FAILED;
+     }
+ 	
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+ #if 0
+     if (cache_pid == cmd->pid) 
+ 	panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid);
+@@ -5202,13 +5140,13 @@
+  * pull the command out of the old queue, and call it aborted.
+  */
+ 
+-    for (me = (Scsi_Cmnd *) hostdata->issue_queue, 
+-         last = (Scsi_Cmnd **) &(hostdata->issue_queue);
+-	 me && me != cmd;  last = (Scsi_Cmnd **)&(me->SCp.ptr), 
+-	 me = (Scsi_Cmnd *)me->SCp.ptr);
++    for (me = (struct scsi_cmnd *) hostdata->issue_queue, 
++         last = (struct scsi_cmnd **) &(hostdata->issue_queue);
++	 me && me != cmd;  last = (struct scsi_cmnd **)&(me->SCp.ptr), 
++	 me = (struct scsi_cmnd *)me->SCp.ptr);
+ 
+     if (me) {
+-	*last = (Scsi_Cmnd *) me->SCp.ptr;
++	*last = (struct scsi_cmnd *) me->SCp.ptr;
+ 	if (me->host_scribble) {
+ 	    ((struct NCR53c7x0_cmd *)me->host_scribble)->next = hostdata->free;
+ 	    hostdata->free = (struct NCR53c7x0_cmd *) me->host_scribble;
+@@ -5218,9 +5156,9 @@
+ 	cmd->scsi_done(cmd);
+ 	printk ("scsi%d : found command %ld in Linux issue queue\n", 
+ 	    host->host_no, me->pid);
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+     	run_process_issue_queue();
+-	return SCSI_ABORT_SUCCESS;
++	return SUCCESS;
+     }
+ 
+ /* 
+@@ -5244,13 +5182,13 @@
+ 	    cmd->scsi_done(cmd);
+ 	printk ("scsi%d : found finished command %ld in running list\n", 
+ 	    host->host_no, cmd->pid);
+-	    local_irq_restore(flags);
+-	    return SCSI_ABORT_NOT_RUNNING;
++	    spin_unlock_irqrestore(host->host_lock, flags);
++	    return SUCCESS;
+ 	} else {
+ 	    printk ("scsi%d : DANGER : command running, can not abort.\n",
+ 		cmd->device->host->host_no);
+-	    local_irq_restore(flags);
+-	    return SCSI_ABORT_BUSY;
++	    spin_unlock_irqrestore(host->host_lock, flags);
++	    return FAILED;
+ 	}
+     }
+ 
+@@ -5281,21 +5219,20 @@
+  */
+         --hostdata->busy[cmd->device->id][cmd->device->lun];
+     }
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+     cmd->scsi_done(cmd);
+ 
+ /* 
+  * We need to run process_issue_queue since termination of this command 
+  * may allow another queued command to execute first? 
+  */
+-    return SCSI_ABORT_NOT_RUNNING;
++    return SUCCESS;
+ }
+ 
+ /*
+- * Function : int NCR53c7xx_reset (Scsi_Cmnd *cmd) 
++ * Function : int NCR53c7xx_reset (struct scsi_cmnd *cmd) 
+  * 
+- * Purpose : perform a hard reset of the SCSI bus and NCR
+- * 	chip.
++ * Purpose : perform a hard reset of the SCSI bus.
+  *
+  * Inputs : cmd - command which caused the SCSI RESET
+  *
+@@ -5303,12 +5240,12 @@
+  */
+  
+ int 
+-NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) {
++NCR53c7xx_reset (struct scsi_cmnd *cmd) {
+     NCR53c7x0_local_declare();
+     unsigned long flags;
+     int found = 0;
+     struct NCR53c7x0_cmd * c;
+-    Scsi_Cmnd *tmp;
++    struct scsi_cmnd *tmp;
+     /*
+      * When we call scsi_done(), it's going to wake up anything sleeping on the
+      * resources which were in use by the aborted commands, and we'll start to 
+@@ -5323,19 +5260,19 @@
+      * pointer), do our reinitialization, and then call the done function for
+      * each command.  
+      */
+-    Scsi_Cmnd *nuke_list = NULL;
++    struct scsi_cmnd *nuke_list = NULL;
+     struct Scsi_Host *host = cmd->device->host;
+     struct NCR53c7x0_hostdata *hostdata = 
+     	(struct NCR53c7x0_hostdata *) host->hostdata[0];
+ 
+     NCR53c7x0_local_setup(host);
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     ncr_halt (host);
+     print_lots (host);
+     dump_events (host, 30);
+     ncr_scsi_reset (host);
+     for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */,
+-	0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer)
++	0 /* issue */ ); tmp; tmp = (struct scsi_cmnd *) tmp->SCp.buffer)
+ 	if (tmp == cmd) {
+ 	    found = 1;
+ 	    break;
+@@ -5358,19 +5295,21 @@
+     }
+ 
+     NCR53c7x0_driver_init (host);
++#if 0
+     hostdata->soft_reset (host);
++#endif
+     if (hostdata->resets == 0) 
+ 	disable(host);
+     else if (hostdata->resets != -1)
+ 	--hostdata->resets;
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+     for (; nuke_list; nuke_list = tmp) {
+-	tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
++	tmp = (struct scsi_cmnd *) nuke_list->SCp.buffer;
+     	nuke_list->result = DID_RESET << 16;
+ 	nuke_list->scsi_done (nuke_list);
+     }
+-    local_irq_restore(flags);
+-    return SCSI_RESET_SUCCESS;
++    spin_unlock_irqrestore(host->host_lock, flags);
++    return SUCCESS;
+ }
+ 
+ /*
+@@ -5379,7 +5318,7 @@
+  */
+ 
+ /*
+- * Function : int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn)
++ * Function : int insn_to_offset (struct scsi_cmnd *cmd, u32 *insn)
+  *
+  * Purpose : convert instructions stored at NCR pointer into data 
+  *	pointer offset.
+@@ -5392,7 +5331,7 @@
+ 
+ 
+ static int 
+-insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
++insn_to_offset (struct scsi_cmnd *cmd, u32 *insn) {
+     struct NCR53c7x0_hostdata *hostdata = 
+ 	(struct NCR53c7x0_hostdata *) cmd->device->host->hostdata[0];
+     struct NCR53c7x0_cmd *ncmd = 
+@@ -5446,7 +5385,7 @@
+ 
+ 
+ /*
+- * Function : void print_progress (Scsi_Cmnd *cmd) 
++ * Function : void print_progress (struct scsi_cmnd *cmd) 
+  * 
+  * Purpose : print the current location of the saved data pointer
+  *
+@@ -5455,7 +5394,7 @@
+  */
+ 
+ static void 
+-print_progress (Scsi_Cmnd *cmd) {
++print_progress (struct scsi_cmnd *cmd) {
+     NCR53c7x0_local_declare();
+     struct NCR53c7x0_cmd *ncmd = 
+ 	(struct NCR53c7x0_cmd *) cmd->host_scribble;
+@@ -5513,7 +5452,7 @@
+ 	host->hostdata[0];
+     int i, len;
+     char *ptr;
+-    Scsi_Cmnd *cmd;
++    struct scsi_cmnd *cmd;
+ 
+     if (check_address ((unsigned long) dsa, hostdata->dsa_end - 
+ 	hostdata->dsa_start) == -1) {
+@@ -5549,7 +5488,7 @@
+ 
+     printk("        + %d : select_indirect = 0x%x\n",
+ 	hostdata->dsa_select, dsa[hostdata->dsa_select / sizeof(u32)]);
+-    cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]);
++    cmd = (struct scsi_cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]);
+     printk("        + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd,
+ 	   (u32) virt_to_bus(cmd));
+     /* XXX Maybe we should access cmd->host_scribble->result here. RGH */
+@@ -5589,16 +5528,16 @@
+     u32 *dsa, *next_dsa;
+     volatile u32 *ncrcurrent;
+     int left;
+-    Scsi_Cmnd *cmd, *next_cmd;
++    struct scsi_cmnd *cmd, *next_cmd;
+     unsigned long flags;
+ 
+     printk ("scsi%d : issue queue\n", host->host_no);
+ 
+-    for (left = host->can_queue, cmd = (Scsi_Cmnd *) hostdata->issue_queue; 
++    for (left = host->can_queue, cmd = (struct scsi_cmnd *) hostdata->issue_queue; 
+ 	    left >= 0 && cmd; 
+ 	    cmd = next_cmd) {
+-	next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr;
+-	local_irq_save(flags);
++	next_cmd = (struct scsi_cmnd *) cmd->SCp.ptr;
++	spin_lock_irqsave(host->host_lock, flags);
+ 	if (cmd->host_scribble) {
+ 	    if (check_address ((unsigned long) (cmd->host_scribble), 
+ 		sizeof (cmd->host_scribble)) == -1)
+@@ -5611,7 +5550,7 @@
+ 	} else 
+ 	    printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n",
+ 		host->host_no, cmd->pid, cmd->device->id, cmd->device->lun);
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+     }
+ 
+     if (left <= 0) {
+@@ -5643,7 +5582,7 @@
+ 	dsa = bus_to_virt (hostdata->reconnect_dsa_head);
+ 	left >= 0 && dsa; 
+ 	dsa = next_dsa) {
+-	local_irq_save(flags);
++	spin_lock_irqsave(host->host_lock, flags);
+ 	if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) {
+ 	    printk ("scsi%d: bad DSA pointer 0x%p", host->host_no,
+ 		dsa);
+@@ -5654,7 +5593,7 @@
+ 	    next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]);
+ 	    print_dsa (host, dsa, "");
+ 	}
+-	local_irq_restore(flags);
++	spin_unlock_irqrestore(host->host_lock, flags);
+     }
+     printk ("scsi%d : end reconnect_dsa_head\n", host->host_no);
+     if (left < 0)
+@@ -5744,14 +5683,14 @@
+     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+ 	host->hostdata[0];
+     NCR53c7x0_local_setup(host);
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+ /* Get in a state where we can reset the SCSI bus */
+     ncr_halt (host);
+     ncr_scsi_reset (host);
+     hostdata->soft_reset(host);
+ 
+     disable (host);
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+     return 0;
+ }
+ 
+@@ -5766,11 +5705,11 @@
+     NCR53c7x0_local_declare();
+     unsigned long flags;
+     NCR53c7x0_local_setup(host);
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+     udelay(25);	/* Minimum amount of time to assert RST */
+     NCR53c7x0_write8(SCNTL1_REG, 0);
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+ }
+ 
+ /* 
+@@ -5783,26 +5722,26 @@
+     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+ 	host->hostdata[0];
+     unsigned long flags;
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     ncr_scsi_reset(host);
+     NCR53c7x0_driver_init (host);
+     if (hostdata->soft_reset)
+ 	hostdata->soft_reset (host);
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+ }
+ 
+ 
+ /*
+- * Function : Scsi_Cmnd *return_outstanding_commands (struct Scsi_Host *host,
++ * Function : struct scsi_cmnd *return_outstanding_commands (struct Scsi_Host *host,
+  *	int free, int issue)
+  *
+  * Purpose : return a linked list (using the SCp.buffer field as next,
+  *	so we don't perturb hostdata.  We don't use a field of the 
+  *	NCR53c7x0_cmd structure since we may not have allocated one 
+- *	for the command causing the reset.) of Scsi_Cmnd structures that 
++ *	for the command causing the reset.) of scsi_cmnd structures that 
+  *  	had propagated below the Linux issue queue level.  If free is set, 
+  *	free the NCR53c7x0_cmd structures which are associated with 
+- *	the Scsi_Cmnd structures, and clean up any internal 
++ *	the scsi_cmnd structures, and clean up any internal 
+  *	NCR lists that the commands were on.  If issue is set,
+  *	also return commands in the issue queue.
+  *
+@@ -5812,14 +5751,14 @@
+  *	if the free flag is set. 
+  */
+ 
+-static Scsi_Cmnd *
++static struct scsi_cmnd *
+ return_outstanding_commands (struct Scsi_Host *host, int free, int issue) {
+     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+ 	host->hostdata[0];
+     struct NCR53c7x0_cmd *c;
+     int i;
+     u32 *ncrcurrent;
+-    Scsi_Cmnd *list = NULL, *tmp;
++    struct scsi_cmnd *list = NULL, *tmp, *next_cmd;
+     for (c = (struct NCR53c7x0_cmd *) hostdata->running_list; c; 
+     	c = (struct NCR53c7x0_cmd *) c->next)  {
+ 	if (c->cmd->SCp.buffer) {
+@@ -5848,7 +5787,9 @@
+     }
+ 
+     if (issue) {
+-	for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; tmp = tmp->next) {
++	for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp; tmp = next_cmd) {
++	    next_cmd = (struct scsi_cmnd *) tmp->SCp.ptr;
++
+ 	    if (tmp->SCp.buffer) {
+ 		printk ("scsi%d : loop detected in issue queue!\n", 
+ 			host->host_no);
+@@ -5883,17 +5824,17 @@
+     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
+ 	host->hostdata[0];
+     unsigned long flags;
+-    Scsi_Cmnd *nuke_list, *tmp;
+-    local_irq_save(flags);
++    struct scsi_cmnd *nuke_list, *tmp;
++    spin_lock_irqsave(host->host_lock, flags);
+     if (hostdata->state != STATE_HALTED)
+ 	ncr_halt (host);
+     nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */);
+     hard_reset (host);
+     hostdata->state = STATE_DISABLED;
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+     printk ("scsi%d : nuking commands\n", host->host_no);
+     for (; nuke_list; nuke_list = tmp) {
+-	    tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
++	    tmp = (struct scsi_cmnd *) nuke_list->SCp.buffer;
+ 	    nuke_list->result = DID_ERROR << 16;
+ 	    nuke_list->scsi_done(nuke_list);
+     }
+@@ -5923,7 +5864,7 @@
+     int stage;
+     NCR53c7x0_local_setup(host);
+ 
+-    local_irq_save(flags);
++    spin_lock_irqsave(host->host_lock, flags);
+     /* Stage 0 : eat all interrupts
+        Stage 1 : set ABORT
+        Stage 2 : eat all but abort interrupts
+@@ -5958,7 +5899,7 @@
+ 	}
+     }
+     hostdata->state = STATE_HALTED;
+-    local_irq_restore(flags);
++    spin_unlock_irqrestore(host->host_lock, flags);
+ #if 0
+     print_lots (host);
+ #endif
+@@ -6012,7 +5953,7 @@
+  * still be guaranteed that they're happening on the same 
+  * event structure.
+  */
+-	    local_irq_save(flags);
++	    spin_lock_irqsave(host->host_lock, flags);
+ #if 0
+ 	    event = hostdata->events[i];
+ #else
+@@ -6020,7 +5961,7 @@
+ 		sizeof(event));
+ #endif
+ 
+-	    local_irq_restore(flags);
++	    spin_unlock_irqrestore(host->host_lock, flags);
+ 	    printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n",
+ 		host->host_no, event_name (event.event), count,
+ 		(long) event.time.tv_sec, (long) event.time.tv_usec,
+@@ -6055,6 +5996,72 @@
+     return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ?  -1 : 0);
+ }
+ 
++int
++NCR53c7xx_slave_configure(struct scsi_device *sdev) {
++    struct Scsi_Host *host = sdev->host;
++    struct NCR53c7x0_hostdata *hostdata = 
++	(struct NCR53c7x0_hostdata *) host->hostdata[0];
++    struct NCR53c7x0_cmd *tmp;
++    u32 real;			/* Real address */
++    int size;			/* Size of *tmp */
++    unsigned long flags;
++    int extra_allocate = 0;
++
++/*
++ * Reserve commands for this I_T_L nexus.
++ */
++    if (hostdata->num_cmds < host->can_queue)
++        extra_allocate = host->cmd_per_lun;
++
++    for (; extra_allocate > 0 ; --extra_allocate, 
++    	++hostdata->num_cmds) {
++    /* historically, kmalloc has returned unaligned addresses; pad so we
++       have enough room to ROUNDUP */
++	size = hostdata->max_cmd_size + sizeof (void *);
++#ifdef FORCE_DSA_ALIGNMENT
++	/*
++	 * 53c710 rev.0 doesn't have an add-with-carry instruction.
++	 * Ensure we allocate enough memory to force alignment.
++	 */
++	size += 256;
++#endif
++/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
++
++        if (size > 4096) {
++            printk (KERN_ERR "53c7xx: slave_configure size > 4K\n");
++	    return -ENOMEM;
++	}
++        real = get_zeroed_page(GFP_ATOMIC);
++        if (real == 0)
++        	return -ENOMEM;
++        memset((void *)real, 0, 4096);
++        cache_push(virt_to_phys((void *)real), 4096);
++        cache_clear(virt_to_phys((void *)real), 4096);
++        kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER);
++	tmp = ROUNDUP(real, void *);
++#ifdef FORCE_DSA_ALIGNMENT
++	{
++	    if (((u32)tmp & 0xff) > CmdPageStart)
++		tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255);
++	    tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart);
++#if 0
++	    printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n",
++			size, real, (u32)tmp);
++#endif
++	}
++#endif
++	tmp->real = (void *)real;
++	tmp->size = size;			
++	tmp->free = ((void (*)(void *, int)) my_free_page);
++	spin_lock_irqsave(host->host_lock, flags);
++	tmp->next = hostdata->free;
++	hostdata->free = tmp;
++	spin_unlock_irqrestore(host->host_lock, flags);
++    }
++
++    return 0;
++}
++
+ #ifdef MODULE
+ int 
+ NCR53c7x0_release(struct Scsi_Host *host) {
+@@ -6064,19 +6071,22 @@
+     shutdown (host);
+     if (host->irq != SCSI_IRQ_NONE)
+ 	{
+-	    int irq_count;
+-	    struct Scsi_Host *tmp;
+-	    for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next)
+-		if (tmp->hostt == the_template && tmp->irq == host->irq)
++	    int irq_count = 0;
++	    struct Scsi_Host *tmp, *s;
++	    list_for_each_entry_safe(tmp, s, &the_template->legacy_hosts, sht_legacy_list) {
++		if (tmp->irq == host->irq)
+ 		    ++irq_count;
++	    }
+ 	    if (irq_count == 1)
+ 		free_irq(host->irq, NULL);
+ 	}
++#ifdef CONFIG_ISA
+     if (host->dma_channel != DMA_NONE)
+ 	free_dma(host->dma_channel);
++#endif
+     if (host->io_port)
+ 	release_region(host->io_port, host->n_io_port);
+-    
++
+     for (cmd = (struct NCR53c7x0_cmd *) hostdata->free; cmd; cmd = tmp, 
+ 	--hostdata->num_cmds) {
+ 	tmp = (struct NCR53c7x0_cmd *) cmd->next;
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/53c7xx.h linux-m68k/drivers/scsi/53c7xx.h
+--- linux-i386/drivers/scsi/53c7xx.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/53c7xx.h	2004-10-30 14:41:36.000000000 +0200
+@@ -997,7 +997,7 @@
+     u32 *dsa;			/* What's in the DSA register now (virt) */
+ /* 
+  * A few things from that SCSI pid so we know what happened after 
+- * the Scsi_Cmnd structure in question may have disappeared.
++ * the scsi_cmnd structure in question may have disappeared.
+  */
+     unsigned long pid;		/* The SCSI PID which caused this 
+ 				   event */
+@@ -1029,8 +1029,8 @@
+     void (* free)(void *, int);		/* Command to deallocate; NULL
+ 					   for structures allocated with
+ 					   scsi_register, etc. */
+-    Scsi_Cmnd *cmd;			/* Associated Scsi_Cmnd 
+-					   structure, Scsi_Cmnd points
++    struct scsi_cmnd *cmd;		/* Associated scsi_cmnd 
++					   structure, scsi_cmnd points
+ 					   at NCR53c7x0_cmd using 
+ 					   host_scribble structure */
+ 
+@@ -1039,8 +1039,8 @@
+ 
+     int flags;				/* CMD_* flags */
+ 
+-    unsigned char      cmnd[12];	/* CDB, copied from Scsi_Cmnd */
+-    int                result;		/* Copy to Scsi_Cmnd when done */
++    unsigned char      cmnd[12];	/* CDB, copied from scsi_cmnd */
++    int                result;		/* Copy to scsi_cmnd when done */
+ 
+     struct {				/* Private non-cached bounce buffer */
+         unsigned char buf[256];
+@@ -1339,7 +1339,7 @@
+     volatile struct NCR53c7x0_synchronous sync[16]
+ 	__attribute__ ((aligned (4)));
+ 
+-    volatile Scsi_Cmnd *issue_queue
++    volatile struct scsi_cmnd *issue_queue
+ 	__attribute__ ((aligned (4)));
+ 						/* waiting to be issued by
+ 						   Linux driver */
+@@ -1363,10 +1363,6 @@
+ 						   */
+     volatile int num_cmds;			/* Number of commands 
+ 						   allocated */
+-    volatile int extra_allocate;
+-    volatile unsigned char cmd_allocated[16];	/* Have we allocated commands
+-						   for this target yet?  If not,
+-						   do so ASAP */
+     volatile unsigned char busy[16][8];     	/* number of commands 
+ 						   executing on each target
+     	    	    	    	    	    	 */
+@@ -1589,11 +1585,11 @@
+ /* Patch field in dsa structure (assignment should be +=?) */
+ #define patch_dsa_32(dsa, symbol, word, value)				\
+ 	{								\
+-	(dsa)[(hostdata->##symbol - hostdata->dsa_start) / sizeof(u32)	\
++	(dsa)[(hostdata->symbol - hostdata->dsa_start) / sizeof(u32)	\
+ 	    + (word)] = (value);					\
+ 	if (hostdata->options & OPTION_DEBUG_DSA)			\
+ 	    printk("scsi : dsa %s symbol %s(%d) word %d now 0x%x\n",	\
+-		#dsa, #symbol, hostdata->##symbol, 			\
++		#dsa, #symbol, hostdata->symbol, 			\
+ 		(word), (u32) (value));					\
+ 	}
+ 
+@@ -1603,6 +1599,12 @@
+ extern int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip,
+ 			  unsigned long base, int io_port, int irq, int dma,
+ 			  long long options, int clock);
++extern const char *NCR53c7x0_info(void);
++extern int NCR53c7xx_queue_command(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *));
++extern int NCR53c7xx_abort(struct scsi_cmnd *);
++extern int NCR53c7x0_release (struct Scsi_Host *);
++extern int NCR53c7xx_reset(struct scsi_cmnd *);
++extern int NCR53c7xx_slave_configure(struct scsi_device *);
+ 
+ #endif /* NCR53c710_C */
+ #endif /* NCR53c710_H */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/Kconfig linux-m68k/drivers/scsi/Kconfig
+--- linux-i386/drivers/scsi/Kconfig	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/Kconfig	2006-04-11 16:37:15.000000000 +0200
+@@ -1659,7 +1659,7 @@
+ 
+ config SCSI_AMIGA7XX
+ 	bool "Amiga NCR53c710 SCSI support (EXPERIMENTAL)"
+-	depends on AMIGA && SCSI && EXPERIMENTAL && BROKEN
++	depends on AMIGA && SCSI && EXPERIMENTAL
+ 	help
+ 	  Support for various NCR53c710-based SCSI controllers on the Amiga.
+ 	  This includes:
+@@ -1759,7 +1759,7 @@
+ 
+ config MVME16x_SCSI
+ 	bool "NCR53C710 SCSI driver for MVME16x"
+-	depends on MVME16x && SCSI && BROKEN
++	depends on MVME16x && SCSI
+ 	select SCSI_SPI_ATTRS
+ 	help
+ 	  The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
+@@ -1768,7 +1768,7 @@
+ 
+ config BVME6000_SCSI
+ 	bool "NCR53C710 SCSI driver for BVME6000"
+-	depends on BVME6000 && SCSI && BROKEN
++	depends on BVME6000 && SCSI
+ 	select SCSI_SPI_ATTRS
+ 	help
+ 	  The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/NCR5380.c linux-m68k/drivers/scsi/NCR5380.c
+--- linux-i386/drivers/scsi/NCR5380.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/NCR5380.c	2006-04-11 16:37:15.000000000 +0200
+@@ -354,6 +354,7 @@
+ 	return -ETIMEDOUT;
+ }
+ 
++#if NDEBUG
+ static struct {
+ 	unsigned char value;
+ 	const char *name;
+@@ -367,7 +368,6 @@
+ 	{PHASE_UNKNOWN, "UNKNOWN"}
+ };
+ 
+-#if NDEBUG
+ static struct {
+ 	unsigned char mask;
+ 	const char *name;
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/amiga7xx.c linux-m68k/drivers/scsi/amiga7xx.c
+--- linux-i386/drivers/scsi/amiga7xx.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/amiga7xx.c	2006-01-19 22:08:23.000000000 +0100
+@@ -26,8 +26,14 @@
+ #include "scsi.h"
+ #include <scsi/scsi_host.h>
+ #include "53c7xx.h"
+-#include "amiga7xx.h"
+ 
++#ifndef CMD_PER_LUN
++#define CMD_PER_LUN 3
++#endif
++
++#ifndef CAN_QUEUE
++#define CAN_QUEUE 24
++#endif
+ 
+ static int amiga7xx_register_one(struct scsi_host_template *tpnt,
+ 				 unsigned long address)
+@@ -114,8 +120,10 @@
+ {
+ 	if (shost->irq)
+ 		free_irq(shost->irq, NULL);
++#ifdef CONFIG_ISA
+ 	if (shost->dma_channel != 0xff)
+ 		free_dma(shost->dma_channel);
++#endif
+ 	if (shost->io_port && shost->n_io_port)
+ 		release_region(shost->io_port, shost->n_io_port);
+ 	scsi_unregister(shost);
+@@ -127,8 +135,9 @@
+ 	.detect			= amiga7xx_detect,
+ 	.release		= amiga7xx_release,
+ 	.queuecommand		= NCR53c7xx_queue_command,
+-	.abort			= NCR53c7xx_abort,
+-	.reset			= NCR53c7xx_reset,
++	.eh_abort_handler	= NCR53c7xx_abort,
++	.eh_bus_reset_handler	= NCR53c7xx_reset,
++	.slave_configure	= NCR53c7xx_slave_configure,
+ 	.can_queue		= 24,
+ 	.this_id		= 7,
+ 	.sg_tablesize		= 63,
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/amiga7xx.h linux-m68k/drivers/scsi/amiga7xx.h
+--- linux-i386/drivers/scsi/amiga7xx.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/amiga7xx.h	1970-01-01 01:00:00.000000000 +0100
+@@ -1,23 +0,0 @@
+-#ifndef AMIGA7XX_H
+-
+-#include <linux/types.h>
+-
+-int amiga7xx_detect(struct scsi_host_template *);
+-const char *NCR53c7x0_info(void);
+-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+-int NCR53c7xx_abort(Scsi_Cmnd *);
+-int NCR53c7x0_release (struct Scsi_Host *);
+-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
+-void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+-
+-#ifndef CMD_PER_LUN
+-#define CMD_PER_LUN 3
+-#endif
+-
+-#ifndef CAN_QUEUE
+-#define CAN_QUEUE 24
+-#endif
+-
+-#include <scsi/scsicam.h>
+-
+-#endif /* AMIGA7XX_H */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/bvme6000.c linux-m68k/drivers/scsi/bvme6000.c
+--- linux-i386/drivers/scsi/bvme6000.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/bvme6000.c	2006-01-19 22:08:23.000000000 +0100
+@@ -18,10 +18,16 @@
+ #include "scsi.h"
+ #include <scsi/scsi_host.h>
+ #include "53c7xx.h"
+-#include "bvme6000.h"
+ 
+ #include<linux/stat.h>
+ 
++#ifndef CMD_PER_LUN
++#define CMD_PER_LUN 3
++#endif
++
++#ifndef CAN_QUEUE
++#define CAN_QUEUE 24
++#endif
+ 
+ int bvme6000_scsi_detect(struct scsi_host_template *tpnt)
+ {
+@@ -51,8 +57,10 @@
+ {
+ 	if (shost->irq)
+ 		free_irq(shost->irq, NULL);
++#ifdef CONFIG_ISA
+ 	if (shost->dma_channel != 0xff)
+ 		free_dma(shost->dma_channel);
++#endif
+ 	if (shost->io_port && shost->n_io_port)
+ 		release_region(shost->io_port, shost->n_io_port);
+ 	scsi_unregister(shost);
+@@ -64,8 +72,9 @@
+ 	.detect			= bvme6000_scsi_detect,
+ 	.release		= bvme6000_scsi_release,
+ 	.queuecommand		= NCR53c7xx_queue_command,
+-	.abort			= NCR53c7xx_abort,
+-	.reset			= NCR53c7xx_reset,
++	.eh_abort_handler	= NCR53c7xx_abort,
++	.eh_bus_reset_handler	= NCR53c7xx_reset,
++	.slave_configure	= NCR53c7xx_slave_configure,
+ 	.can_queue		= 24,
+ 	.this_id		= 7,
+ 	.sg_tablesize		= 63,
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/bvme6000.h linux-m68k/drivers/scsi/bvme6000.h
+--- linux-i386/drivers/scsi/bvme6000.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/bvme6000.h	1970-01-01 01:00:00.000000000 +0100
+@@ -1,24 +0,0 @@
+-#ifndef BVME6000_SCSI_H
+-#define BVME6000_SCSI_H
+-
+-#include <linux/types.h>
+-
+-int bvme6000_scsi_detect(struct scsi_host_template *);
+-const char *NCR53c7x0_info(void);
+-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+-int NCR53c7xx_abort(Scsi_Cmnd *);
+-int NCR53c7x0_release (struct Scsi_Host *);
+-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
+-void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+-
+-#ifndef CMD_PER_LUN
+-#define CMD_PER_LUN 3
+-#endif
+-
+-#ifndef CAN_QUEUE
+-#define CAN_QUEUE 24
+-#endif
+-
+-#include <scsi/scsicam.h>
+-
+-#endif /* BVME6000_SCSI_H */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/mac_esp.c linux-m68k/drivers/scsi/mac_esp.c
+--- linux-i386/drivers/scsi/mac_esp.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/mac_esp.c	2006-01-31 16:33:52.000000000 +0100
+@@ -43,9 +43,6 @@
+ 
+ /* #define DEBUG_MAC_ESP */
+ 
+-#define mac_turnon_irq(x)	mac_enable_irq(x)
+-#define mac_turnoff_irq(x)	mac_disable_irq(x)
+-
+ extern void esp_handle(struct NCR_ESP *esp);
+ extern void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+ 
+@@ -639,13 +636,13 @@
+ 
+ static void dma_ints_off(struct NCR_ESP * esp)
+ {
+-	mac_turnoff_irq(esp->irq);
++	disable_irq(esp->irq);
+ }
+ 
+ 
+ static void dma_ints_on(struct NCR_ESP * esp)
+ {
+-	mac_turnon_irq(esp->irq);
++	enable_irq(esp->irq);
+ }
+ 
+ /*
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/mac_scsi.c linux-m68k/drivers/scsi/mac_scsi.c
+--- linux-i386/drivers/scsi/mac_scsi.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/mac_scsi.c	2006-01-31 16:33:52.000000000 +0100
+@@ -65,9 +65,6 @@
+ #define RESET_BOOT
+ #define DRIVER_SETUP
+ 
+-#define	ENABLE_IRQ()	mac_enable_irq( IRQ_MAC_SCSI ); 
+-#define	DISABLE_IRQ()	mac_disable_irq( IRQ_MAC_SCSI );
+-
+ extern void via_scsi_clear(void);
+ 
+ #ifdef RESET_BOOT
+@@ -351,7 +348,7 @@
+ 	printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
+ 
+ 	/* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
+-	mac_disable_irq(IRQ_MAC_SCSI);
++	disable_irq(IRQ_MAC_SCSI);
+ 
+ 	/* get in phase */
+ 	NCR5380_write( TARGET_COMMAND_REG,
+@@ -369,7 +366,7 @@
+ 		barrier();
+ 
+ 	/* switch on SCSI IRQ again */
+-	mac_enable_irq(IRQ_MAC_SCSI);
++	enable_irq(IRQ_MAC_SCSI);
+ 
+ 	printk(KERN_INFO " done\n" );
+ }
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/mvme16x.c linux-m68k/drivers/scsi/mvme16x.c
+--- linux-i386/drivers/scsi/mvme16x.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/mvme16x.c	2006-01-19 22:08:29.000000000 +0100
+@@ -16,10 +16,16 @@
+ #include "scsi.h"
+ #include <scsi/scsi_host.h>
+ #include "53c7xx.h"
+-#include "mvme16x.h"
+ 
+ #include<linux/stat.h>
+ 
++#ifndef CMD_PER_LUN
++#define CMD_PER_LUN 3
++#endif
++
++#ifndef CAN_QUEUE
++#define CAN_QUEUE 24
++#endif
+ 
+ int mvme16x_scsi_detect(struct scsi_host_template *tpnt)
+ {
+@@ -53,8 +59,10 @@
+ {
+ 	if (shost->irq)
+ 		free_irq(shost->irq, NULL);
++#ifdef CONFIG_ISA
+ 	if (shost->dma_channel != 0xff)
+ 		free_dma(shost->dma_channel);
++#endif
+ 	if (shost->io_port && shost->n_io_port)
+ 		release_region(shost->io_port, shost->n_io_port);
+ 	scsi_unregister(shost);
+@@ -66,8 +74,9 @@
+ 	.detect			= mvme16x_scsi_detect,
+ 	.release		= mvme16x_scsi_release,
+ 	.queuecommand		= NCR53c7xx_queue_command,
+-	.abort			= NCR53c7xx_abort,
+-	.reset			= NCR53c7xx_reset,
++	.eh_abort_handler	= NCR53c7xx_abort,
++	.eh_bus_reset_handler	= NCR53c7xx_reset,
++	.slave_configure	= NCR53c7xx_slave_configure,
+ 	.can_queue		= 24,
+ 	.this_id		= 7,
+ 	.sg_tablesize		= 63,
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/mvme16x.h linux-m68k/drivers/scsi/mvme16x.h
+--- linux-i386/drivers/scsi/mvme16x.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/mvme16x.h	1970-01-01 01:00:00.000000000 +0100
+@@ -1,24 +0,0 @@
+-#ifndef MVME16x_SCSI_H
+-#define MVME16x_SCSI_H
+-
+-#include <linux/types.h>
+-
+-int mvme16x_scsi_detect(struct scsi_host_template *);
+-const char *NCR53c7x0_info(void);
+-int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+-int NCR53c7xx_abort(Scsi_Cmnd *);
+-int NCR53c7x0_release (struct Scsi_Host *);
+-int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
+-void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+-
+-#ifndef CMD_PER_LUN
+-#define CMD_PER_LUN 3
+-#endif
+-
+-#ifndef CAN_QUEUE
+-#define CAN_QUEUE 24
+-#endif
+-
+-#include <scsi/scsicam.h>
+-
+-#endif /* MVME16x_SCSI_H */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/drivers/scsi/wd33c93.c linux-m68k/drivers/scsi/wd33c93.c
+--- linux-i386/drivers/scsi/wd33c93.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/drivers/scsi/wd33c93.c	2006-04-11 16:37:26.000000000 +0200
+@@ -939,6 +939,7 @@
+ 		DB(DB_INTR, printk("%02x", cmd->SCp.Status))
+ 		    if (hostdata->level2 >= L2_BASIC) {
+ 			sr = read_wd33c93(regs, WD_SCSI_STATUS);	/* clear interrupt */
++			udelay(7);
+ 			hostdata->state = S_RUNNING_LEVEL2;
+ 			write_wd33c93(regs, WD_COMMAND_PHASE, 0x50);
+ 			write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
+@@ -955,6 +956,7 @@
+ 
+ 		msg = read_1_byte(regs);
+ 		sr = read_wd33c93(regs, WD_SCSI_STATUS);	/* clear interrupt */
++		udelay(7);
+ 
+ 		hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
+ 		if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
+@@ -1358,6 +1360,7 @@
+ 			} else {
+ 				/* Verify this is a change to MSG_IN and read the message */
+ 				sr = read_wd33c93(regs, WD_SCSI_STATUS);
++				udelay(7);
+ 				if (sr == (CSR_ABORT | PHS_MESS_IN) ||
+ 				    sr == (CSR_UNEXP | PHS_MESS_IN) ||
+ 				    sr == (CSR_SRV_REQ | PHS_MESS_IN)) {
+@@ -1374,6 +1377,7 @@
+ 							     asr);
+ 					}
+ 					sr = read_wd33c93(regs, WD_SCSI_STATUS);
++					udelay(7);
+ 					if (sr != CSR_MSGIN)
+ 						printk
+ 						    ("wd33c93: Not paused with ACK on RESEL (%02x)\n",
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/fs/fat/inode.c linux-m68k/fs/fat/inode.c
+--- linux-i386/fs/fat/inode.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/fs/fat/inode.c	2006-04-11 16:39:04.000000000 +0200
+@@ -11,12 +11,14 @@
+  */
+ 
+ #include <linux/module.h>
++#include <linux/config.h>
+ #include <linux/init.h>
+ #include <linux/time.h>
+ #include <linux/slab.h>
+ #include <linux/smp_lock.h>
+ #include <linux/seq_file.h>
+ #include <linux/msdos_fs.h>
++#include <linux/major.h>
+ #include <linux/pagemap.h>
+ #include <linux/mpage.h>
+ #include <linux/buffer_head.h>
+@@ -856,7 +858,7 @@
+ 	Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,
+ 	Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_nocase,
+ 	Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable,
+-	Opt_dots, Opt_nodots,
++	Opt_dots, Opt_nodots, Opt_atari_no, Opt_atari_yes,
+ 	Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
+ 	Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
+ 	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
+@@ -881,6 +883,9 @@
+ 	{Opt_showexec, "showexec"},
+ 	{Opt_debug, "debug"},
+ 	{Opt_immutable, "sys_immutable"},
++	{Opt_atari_yes, "atari=yes"},
++	{Opt_atari_yes, "atari"},
++	{Opt_atari_no, "atari=no"},
+ 	{Opt_obsolate, "conv=binary"},
+ 	{Opt_obsolate, "conv=text"},
+ 	{Opt_obsolate, "conv=auto"},
+@@ -955,6 +960,13 @@
+ 	opts->utf8 = opts->unicode_xlate = 0;
+ 	opts->numtail = 1;
+ 	opts->nocase = 0;
++	opts->atari = 0;
++
++#ifdef CONFIG_ATARI
++	if(MACH_IS_ATARI)
++	/* make Atari GEMDOS format the default if machine is an Atari */
++		opts->atari = 1;
++#endif
+ 	*debug = 0;
+ 
+ 	if (!options)
+@@ -1003,6 +1015,12 @@
+ 		case Opt_immutable:
+ 			opts->sys_immutable = 1;
+ 			break;
++		case Opt_atari_yes:
++			opts->atari = 1;
++			break;
++		case Opt_atari_no:
++			opts->atari = 0;
++			break;
+ 		case Opt_uid:
+ 			if (match_int(&args[0], &option))
+ 				return 0;
+@@ -1338,8 +1356,31 @@
+ 
+ 	total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus;
+ 
+-	if (sbi->fat_bits != 32)
+-		sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12;
++	if (!sbi->options.atari) {
++		if (sbi->fat_bits != 32)
++			sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12;
++	} else {
++		int sectors;
++		/* Atari GEMDOS partitions always have 16-bit fat */
++		if (sbi->fat_bits != 32)
++			sbi->fat_bits = 16;
++		/* If more clusters than fat entries in 16-bit fat, we assume
++		 * it's a real MSDOS partition with 12-bit fat.
++		 */
++		if (sbi->fat_bits != 32 && total_clusters+2 > sbi->
++			fat_length*SECTOR_SIZE*8/sbi->fat_bits)
++			sbi->fat_bits = 12;
++		/* if it's a floppy disk --> 12bit fat */
++		if (sbi->fat_bits != 32 && MAJOR(sb->s_dev) == FLOPPY_MAJOR)
++			sbi->fat_bits = 12;
++		/* if it's a ramdisk or loopback device and has one of the usual
++		 * floppy sizes -> 12bit FAT  */
++		sectors = total_sectors + sbi->data_start;
++		if (sbi->fat_bits != 32 && (MAJOR(sb->s_dev) == RAMDISK_MAJOR ||
++			 MAJOR(sb->s_dev) == LOOP_MAJOR) &&
++			(sectors == 720 || sectors == 1440 || sectors == 2880))
++			sbi->fat_bits = 12;
++	}
+ 
+ 	/* check that FAT table does not overflow */
+ 	fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits;
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/amigaints.h linux-m68k/include/asm-m68k/amigaints.h
+--- linux-i386/include/asm-m68k/amigaints.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/amigaints.h	2006-01-28 23:55:19.000000000 +0100
+@@ -13,6 +13,8 @@
+ #ifndef _ASMm68k_AMIGAINTS_H_
+ #define _ASMm68k_AMIGAINTS_H_
+ 
++#include <asm/irq.h>
++
+ /*
+ ** Amiga Interrupt sources.
+ **
+@@ -23,72 +25,52 @@
+ #define CIA_IRQS            (5)
+ #define AMI_IRQS            (32) /* AUTO_IRQS+AMI_STD_IRQS+2*CIA_IRQS */
+ 
+-/* vertical blanking interrupt */
+-#define IRQ_AMIGA_VERTB     0
++/* builtin serial port interrupts */
++#define IRQ_AMIGA_TBE		(IRQ_USER+0)
++#define IRQ_AMIGA_RBF		(IRQ_USER+11)
+ 
+-/* copper interrupt */
+-#define IRQ_AMIGA_COPPER    1
++/* floppy disk interrupts */
++#define IRQ_AMIGA_DSKBLK	(IRQ_USER+1)
++#define IRQ_AMIGA_DSKSYN	(IRQ_USER+12)
+ 
+-/* Audio interrupts */
+-#define IRQ_AMIGA_AUD0	    2
+-#define IRQ_AMIGA_AUD1	    3
+-#define IRQ_AMIGA_AUD2	    4
+-#define IRQ_AMIGA_AUD3	    5
++/* software interrupts */
++#define IRQ_AMIGA_SOFT		(IRQ_USER+2)
+ 
+-/* Blitter done interrupt */
+-#define IRQ_AMIGA_BLIT	    6
++/* interrupts from external hardware */
++#define IRQ_AMIGA_PORTS		IRQ_AUTO_2
++#define IRQ_AMIGA_EXTER		IRQ_AUTO_6
+ 
+-/* floppy disk interrupts */
+-#define IRQ_AMIGA_DSKSYN    7
+-#define IRQ_AMIGA_DSKBLK    8
++/* copper interrupt */
++#define IRQ_AMIGA_COPPER	(IRQ_USER+4)
+ 
+-/* builtin serial port interrupts */
+-#define IRQ_AMIGA_RBF	    9
+-#define IRQ_AMIGA_TBE	    10
++/* vertical blanking interrupt */
++#define IRQ_AMIGA_VERTB		(IRQ_USER+5)
+ 
+-/* software interrupts */
+-#define IRQ_AMIGA_SOFT      11
++/* Blitter done interrupt */
++#define IRQ_AMIGA_BLIT		(IRQ_USER+6)
+ 
+-/* interrupts from external hardware */
+-#define IRQ_AMIGA_PORTS	    12
+-#define IRQ_AMIGA_EXTER	    13
++/* Audio interrupts */
++#define IRQ_AMIGA_AUD0		(IRQ_USER+7)
++#define IRQ_AMIGA_AUD1		(IRQ_USER+8)
++#define IRQ_AMIGA_AUD2		(IRQ_USER+9)
++#define IRQ_AMIGA_AUD3		(IRQ_USER+10)
+ 
+ /* CIA interrupt sources */
+-#define IRQ_AMIGA_CIAA      14
+-#define IRQ_AMIGA_CIAA_TA   14
+-#define IRQ_AMIGA_CIAA_TB   15
+-#define IRQ_AMIGA_CIAA_ALRM 16
+-#define IRQ_AMIGA_CIAA_SP   17
+-#define IRQ_AMIGA_CIAA_FLG  18
+-#define IRQ_AMIGA_CIAB      19
+-#define IRQ_AMIGA_CIAB_TA   19
+-#define IRQ_AMIGA_CIAB_TB   20
+-#define IRQ_AMIGA_CIAB_ALRM 21
+-#define IRQ_AMIGA_CIAB_SP   22
+-#define IRQ_AMIGA_CIAB_FLG  23
+-
+-/* auto-vector interrupts */
+-#define IRQ_AMIGA_AUTO      24
+-#define IRQ_AMIGA_AUTO_0    24 /* This is just a dummy */
+-#define IRQ_AMIGA_AUTO_1    25
+-#define IRQ_AMIGA_AUTO_2    26
+-#define IRQ_AMIGA_AUTO_3    27
+-#define IRQ_AMIGA_AUTO_4    28
+-#define IRQ_AMIGA_AUTO_5    29
+-#define IRQ_AMIGA_AUTO_6    30
+-#define IRQ_AMIGA_AUTO_7    31
++#define IRQ_AMIGA_CIAA		(IRQ_USER+14)
++#define IRQ_AMIGA_CIAA_TA	(IRQ_USER+14)
++#define IRQ_AMIGA_CIAA_TB	(IRQ_USER+15)
++#define IRQ_AMIGA_CIAA_ALRM	(IRQ_USER+16)
++#define IRQ_AMIGA_CIAA_SP	(IRQ_USER+17)
++#define IRQ_AMIGA_CIAA_FLG	(IRQ_USER+18)
++#define IRQ_AMIGA_CIAB		(IRQ_USER+19)
++#define IRQ_AMIGA_CIAB_TA	(IRQ_USER+19)
++#define IRQ_AMIGA_CIAB_TB	(IRQ_USER+20)
++#define IRQ_AMIGA_CIAB_ALRM	(IRQ_USER+21)
++#define IRQ_AMIGA_CIAB_SP	(IRQ_USER+22)
++#define IRQ_AMIGA_CIAB_FLG	(IRQ_USER+23)
+ 
+-#define IRQ_FLOPPY	    IRQ_AMIGA_DSKBLK
+ 
+ /* INTREQR masks */
+-#define IRQ1_MASK   0x0007	/* INTREQR mask for IRQ 1 */
+-#define IRQ2_MASK   0x0008	/* INTREQR mask for IRQ 2 */
+-#define IRQ3_MASK   0x0070	/* INTREQR mask for IRQ 3 */
+-#define IRQ4_MASK   0x0780	/* INTREQR mask for IRQ 4 */
+-#define IRQ5_MASK   0x1800	/* INTREQR mask for IRQ 5 */
+-#define IRQ6_MASK   0x2000	/* INTREQR mask for IRQ 6 */
+-#define IRQ7_MASK   0x4000	/* INTREQR mask for IRQ 7 */
+-
+ #define IF_SETCLR   0x8000      /* set/clr bit */
+ #define IF_INTEN    0x4000	/* master interrupt bit in INT* registers */
+ #define IF_EXTER    0x2000	/* external level 6 and CIA B interrupt */
+@@ -106,9 +88,6 @@
+ #define IF_DSKBLK   0x0002	/* diskblock DMA finished */
+ #define IF_TBE	    0x0001	/* serial transmit buffer empty interrupt */
+ 
+-extern void amiga_do_irq(int irq, struct pt_regs *fp);
+-extern void amiga_do_irq_list(int irq, struct pt_regs *fp);
+-
+ /* CIA interrupt control register bits */
+ 
+ #define CIA_ICR_TA	0x01
+@@ -125,6 +104,7 @@
+ 
+ extern struct ciabase ciaa_base, ciab_base;
+ 
++extern void cia_init_IRQ(struct ciabase *base);
+ extern unsigned char cia_set_irq(struct ciabase *base, unsigned char mask);
+ extern unsigned char cia_able_irq(struct ciabase *base, unsigned char mask);
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/apollohw.h linux-m68k/include/asm-m68k/apollohw.h
+--- linux-i386/include/asm-m68k/apollohw.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/apollohw.h	2006-01-28 23:55:19.000000000 +0100
+@@ -3,6 +3,8 @@
+ #ifndef _ASMm68k_APOLLOHW_H_
+ #define _ASMm68k_APOLLOHW_H_
+ 
++#include <linux/types.h>
++
+ /*
+    apollo models
+ */
+@@ -101,4 +103,6 @@
+ 
+ #define isaIO2mem(x) (((((x) & 0x3f8)  << 7) | (((x) & 0xfc00) >> 6) | ((x) & 0x7)) + 0x40000 + IO_BASE)
+ 
++#define IRQ_APOLLO	IRQ_USER
++
+ #endif
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/atariints.h linux-m68k/include/asm-m68k/atariints.h
+--- linux-i386/include/asm-m68k/atariints.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/atariints.h	2006-01-28 23:55:19.000000000 +0100
+@@ -45,17 +45,6 @@
+ #define IRQ_TYPE_FAST     1
+ #define IRQ_TYPE_PRIO     2
+ 
+-#define	IRQ_SPURIOUS      (0)
+-
+-/* auto-vector interrupts */
+-#define IRQ_AUTO_1        (1)
+-#define IRQ_AUTO_2        (2)
+-#define IRQ_AUTO_3        (3)
+-#define IRQ_AUTO_4        (4)
+-#define IRQ_AUTO_5        (5)
+-#define IRQ_AUTO_6        (6)
+-#define IRQ_AUTO_7        (7)
+-
+ /* ST-MFP interrupts */
+ #define IRQ_MFP_BUSY      (8)
+ #define IRQ_MFP_DCD       (9)
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/bvme6000hw.h linux-m68k/include/asm-m68k/bvme6000hw.h
+--- linux-i386/include/asm-m68k/bvme6000hw.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/bvme6000hw.h	2006-01-28 23:55:19.000000000 +0100
+@@ -109,23 +109,23 @@
+ 
+ #define BVME_IRQ_TYPE_PRIO	0
+ 
+-#define BVME_IRQ_PRN		0x54
+-#define BVME_IRQ_I596		0x1a
+-#define BVME_IRQ_SCSI		0x1b
+-#define BVME_IRQ_TIMER		0x59
+-#define BVME_IRQ_RTC		0x1e
+-#define BVME_IRQ_ABORT		0x1f
++#define BVME_IRQ_PRN		(IRQ_USER+20)
++#define BVME_IRQ_TIMER		(IRQ_USER+25)
++#define BVME_IRQ_I596		IRQ_AUTO_2
++#define BVME_IRQ_SCSI		IRQ_AUTO_3
++#define BVME_IRQ_RTC		IRQ_AUTO_6
++#define BVME_IRQ_ABORT		IRQ_AUTO_7
+ 
+ /* SCC interrupts */
+-#define BVME_IRQ_SCC_BASE		0x40
+-#define BVME_IRQ_SCCB_TX		0x40
+-#define BVME_IRQ_SCCB_STAT		0x42
+-#define BVME_IRQ_SCCB_RX		0x44
+-#define BVME_IRQ_SCCB_SPCOND		0x46
+-#define BVME_IRQ_SCCA_TX		0x48
+-#define BVME_IRQ_SCCA_STAT		0x4a
+-#define BVME_IRQ_SCCA_RX		0x4c
+-#define BVME_IRQ_SCCA_SPCOND		0x4e
++#define BVME_IRQ_SCC_BASE		IRQ_USER
++#define BVME_IRQ_SCCB_TX		IRQ_USER
++#define BVME_IRQ_SCCB_STAT		(IRQ_USER+2)
++#define BVME_IRQ_SCCB_RX		(IRQ_USER+4)
++#define BVME_IRQ_SCCB_SPCOND		(IRQ_USER+6)
++#define BVME_IRQ_SCCA_TX		(IRQ_USER+8)
++#define BVME_IRQ_SCCA_STAT		(IRQ_USER+10)
++#define BVME_IRQ_SCCA_RX		(IRQ_USER+12)
++#define BVME_IRQ_SCCA_SPCOND		(IRQ_USER+14)
+ 
+ /* Address control registers */
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/io.h linux-m68k/include/asm-m68k/io.h
+--- linux-i386/include/asm-m68k/io.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/io.h	2006-04-11 16:41:20.000000000 +0200
+@@ -325,8 +325,6 @@
+ #define writel(val,addr) out_le32((addr),(val))
+ #endif
+ 
+-#define mmiowb()
+-
+ static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
+ {
+ 	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/irq.h linux-m68k/include/asm-m68k/irq.h
+--- linux-i386/include/asm-m68k/irq.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/irq.h	2006-04-11 16:41:20.000000000 +0200
+@@ -2,13 +2,8 @@
+ #define _M68K_IRQ_H_
+ 
+ #include <linux/config.h>
+-#include <linux/interrupt.h>
+-
+-/*
+- * # of m68k interrupts
+- */
+-
+-#define SYS_IRQS 8
++#include <linux/linkage.h>
++#include <linux/spinlock_types.h>
+ 
+ /*
+  * This should be the same as the max(NUM_X_SOURCES) for all the
+@@ -16,10 +11,20 @@
+  * Currently the Atari has 72 and the Amiga 24, but if both are
+  * supported in the kernel it is better to make room for 72.
+  */
+-#if defined(CONFIG_ATARI) || defined(CONFIG_MAC)
+-#define NR_IRQS (72+SYS_IRQS)
++#if defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
++#define NR_IRQS 200
++#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
++#define NR_IRQS 72
++#elif defined(CONFIG_Q40)
++#define NR_IRQS	43
++#elif defined(CONFIG_AMIGA)
++#define NR_IRQS	32
++#elif defined(CONFIG_APOLLO)
++#define NR_IRQS	24
++#elif defined(CONFIG_HP300)
++#define NR_IRQS	8
+ #else
+-#define NR_IRQS (24+SYS_IRQS)
++#error unknown nr of irqs
+ #endif
+ 
+ /*
+@@ -41,53 +46,26 @@
+  * that routine requires service.
+  */
+ 
+-#define IRQ1		(1)	/* level 1 interrupt */
+-#define IRQ2		(2)	/* level 2 interrupt */
+-#define IRQ3		(3)	/* level 3 interrupt */
+-#define IRQ4		(4)	/* level 4 interrupt */
+-#define IRQ5		(5)	/* level 5 interrupt */
+-#define IRQ6		(6)	/* level 6 interrupt */
+-#define IRQ7		(7)	/* level 7 interrupt (non-maskable) */
+-
+-/*
+- * "Generic" interrupt sources
+- */
+-
+-#define IRQ_SCHED_TIMER	(8)    /* interrupt source for scheduling timer */
+-
+-static __inline__ int irq_canonicalize(int irq)
+-{
+-	return irq;
+-}
+-
+-/*
+- * Machine specific interrupt sources.
+- *
+- * Adding an interrupt service routine for a source with this bit
+- * set indicates a special machine specific interrupt source.
+- * The machine specific files define these sources.
+- *
+- * The IRQ_MACHSPEC bit is now gone - the only thing it did was to
+- * introduce unnecessary overhead.
+- *
+- * All interrupt handling is actually machine specific so it is better
+- * to use function pointers, as used by the Sparc port, and select the
+- * interrupt handling functions when initializing the kernel. This way
+- * we save some unnecessary overhead at run-time.
+- *                                                      01/11/97 - Jes
+- */
++#define IRQ_SPURIOUS	0
++
++#define IRQ_AUTO_1	1	/* level 1 interrupt */
++#define IRQ_AUTO_2	2	/* level 2 interrupt */
++#define IRQ_AUTO_3	3	/* level 3 interrupt */
++#define IRQ_AUTO_4	4	/* level 4 interrupt */
++#define IRQ_AUTO_5	5	/* level 5 interrupt */
++#define IRQ_AUTO_6	6	/* level 6 interrupt */
++#define IRQ_AUTO_7	7	/* level 7 interrupt (non-maskable) */
++
++#define IRQ_USER	8
++
++extern unsigned int irq_canonicalize(unsigned int irq);
++extern void enable_irq(unsigned int);
++extern void disable_irq(unsigned int);
+ 
+-extern void (*enable_irq)(unsigned int);
+-extern void (*disable_irq)(unsigned int);
+ #define disable_irq_nosync	disable_irq
+ 
+ struct pt_regs;
+ 
+-extern int cpu_request_irq(unsigned int,
+-			   irqreturn_t (*)(int, void *, struct pt_regs *),
+-			   unsigned long, const char *, void *);
+-extern void cpu_free_irq(unsigned int, void *);
+-
+ /*
+  * various flags for request_irq() - the Amiga now uses the standard
+  * mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ
+@@ -106,33 +84,45 @@
+  * interrupt source (if it supports chaining).
+  */
+ typedef struct irq_node {
+-	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
+-	unsigned long	flags;
++	int		(*handler)(int, void *, struct pt_regs *);
+ 	void		*dev_id;
+-	const char	*devname;
+ 	struct irq_node *next;
++	unsigned long	flags;
++	const char	*devname;
+ } irq_node_t;
+ 
+ /*
+  * This structure has only 4 elements for speed reasons
+  */
+ typedef struct irq_handler {
+-	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
++	int		(*handler)(int, void *, struct pt_regs *);
+ 	unsigned long	flags;
+ 	void		*dev_id;
+ 	const char	*devname;
+ } irq_handler_t;
+ 
+-/* count of spurious interrupts */
+-extern volatile unsigned int num_spurious;
++struct irq_controller {
++	const char *name;
++	spinlock_t lock;
++	int (*startup)(unsigned int irq);
++	void (*shutdown)(unsigned int irq);
++	void (*enable)(unsigned int irq);
++	void (*disable)(unsigned int irq);
++};
++
++extern int m68k_irq_startup(unsigned int);
++extern void m68k_irq_shutdown(unsigned int);
+ 
+ /*
+  * This function returns a new irq_node_t
+  */
+ extern irq_node_t *new_irq_node(void);
+ 
+-struct irqaction;
+-struct pt_regs;
+-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
++extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
++extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
++				      void (*handler)(unsigned int, struct pt_regs *));
++extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
++
++asmlinkage void m68k_handle_int(unsigned int, struct pt_regs *);
+ 
+ #endif /* _M68K_IRQ_H_ */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/mac_oss.h linux-m68k/include/asm-m68k/mac_oss.h
+--- linux-i386/include/asm-m68k/mac_oss.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/mac_oss.h	2006-01-28 23:55:20.000000000 +0100
+@@ -69,12 +69,12 @@
+ 
+ #define OSS_IRQLEV_DISABLED	0
+ #define OSS_IRQLEV_IOPISM	1	/* ADB? */
+-#define OSS_IRQLEV_SCSI		2
+-#define OSS_IRQLEV_NUBUS	3	/* keep this on its own level */
+-#define OSS_IRQLEV_IOPSCC	4	/* matches VIA alternate mapping */
+-#define OSS_IRQLEV_SOUND	5	/* matches VIA alternate mapping */
++#define OSS_IRQLEV_SCSI		IRQ_AUTO_2
++#define OSS_IRQLEV_NUBUS	IRQ_AUTO_3	/* keep this on its own level */
++#define OSS_IRQLEV_IOPSCC	IRQ_AUTO_4	/* matches VIA alternate mapping */
++#define OSS_IRQLEV_SOUND	IRQ_AUTO_5	/* matches VIA alternate mapping */
+ #define OSS_IRQLEV_60HZ		6	/* matches VIA alternate mapping */
+-#define OSS_IRQLEV_VIA1		6	/* matches VIA alternate mapping */
++#define OSS_IRQLEV_VIA1		IRQ_AUTO_6	/* matches VIA alternate mapping */
+ #define OSS_IRQLEV_PARITY	7	/* matches VIA alternate mapping */
+ 
+ #ifndef __ASSEMBLY__
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/machdep.h linux-m68k/include/asm-m68k/machdep.h
+--- linux-i386/include/asm-m68k/machdep.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/machdep.h	2006-04-11 16:41:20.000000000 +0200
+@@ -13,14 +13,8 @@
+ extern void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *));
+ /* machine dependent irq functions */
+ extern void (*mach_init_IRQ) (void);
+-extern irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
+-extern int (*mach_request_irq) (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                                unsigned long flags, const char *devname, void *dev_id);
+-extern void (*mach_free_irq) (unsigned int irq, void *dev_id);
+ extern void (*mach_get_model) (char *model);
+ extern int (*mach_get_hardware_list) (char *buffer);
+-extern int (*mach_get_irq_list) (struct seq_file *p, void *v);
+-extern irqreturn_t (*mach_process_int) (int irq, struct pt_regs *fp);
+ /* machine dependent timer functions */
+ extern unsigned long (*mach_gettimeoffset)(void);
+ extern int (*mach_hwclk)(int, struct rtc_time*);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/macintosh.h linux-m68k/include/asm-m68k/macintosh.h
+--- linux-i386/include/asm-m68k/macintosh.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/macintosh.h	2006-01-28 23:55:20.000000000 +0100
+@@ -11,17 +11,7 @@
+ extern void mac_reset(void);
+ extern void mac_poweroff(void);
+ extern void mac_init_IRQ(void);
+-extern int mac_request_irq (unsigned int, irqreturn_t (*)(int, void *,
+-				struct pt_regs *),
+-				unsigned long, const char *, void *);
+-extern void mac_free_irq(unsigned int, void *);
+-extern void mac_enable_irq(unsigned int);
+-extern void mac_disable_irq(unsigned int);
+ extern int mac_irq_pending(unsigned int);
+-extern int show_mac_interrupts(struct seq_file *, void *);
+-#if 0
+-extern void mac_default_handler(int irq);
+-#endif
+ extern void mac_identify(void);
+ extern void mac_report_hardware(void);
+ extern void mac_debugging_penguin(int);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/macints.h linux-m68k/include/asm-m68k/macints.h
+--- linux-i386/include/asm-m68k/macints.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/macints.h	2006-01-28 23:55:20.000000000 +0100
+@@ -59,17 +59,6 @@
+ #define IRQ_SRC(irq)	(irq >> 3)
+ #define	IRQ_IDX(irq)	(irq & 7)
+ 
+-#define	IRQ_SPURIOUS      (0)
+-
+-/* auto-vector interrupts */
+-#define IRQ_AUTO_1        (1)
+-#define IRQ_AUTO_2        (2)
+-#define IRQ_AUTO_3        (3)
+-#define IRQ_AUTO_4        (4)
+-#define IRQ_AUTO_5        (5)
+-#define IRQ_AUTO_6        (6)
+-#define IRQ_AUTO_7        (7)
+-
+ /* VIA1 interrupts */
+ #define IRQ_VIA1_0	  (8)		/* one second int. */
+ #define IRQ_VIA1_1        (9)		/* VBlank int. */
+@@ -163,7 +152,4 @@
+ #define INT_CLK   24576	    /* CLK while int_clk =2.456MHz and divide = 100 */
+ #define INT_TICKS 246	    /* to make sched_time = 99.902... HZ */
+ 
+-extern irq_node_t *mac_irq_list[NUM_MAC_SOURCES];
+-extern void mac_do_irq_list(int irq, struct pt_regs *);
+-
+ #endif /* asm/macints.h */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/mvme147hw.h linux-m68k/include/asm-m68k/mvme147hw.h
+--- linux-i386/include/asm-m68k/mvme147hw.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/mvme147hw.h	2006-01-28 23:55:20.000000000 +0100
+@@ -1,6 +1,8 @@
+ #ifndef _MVME147HW_H_
+ #define _MVME147HW_H_
+ 
++#include <asm/irq.h>
++
+ typedef struct {
+ 	unsigned char
+ 		ctrl,
+@@ -72,39 +74,39 @@
+ #define PCC_LEVEL_SCSI_PORT	0x04
+ #define PCC_LEVEL_SCSI_DMA	0x04
+ 
+-#define PCC_IRQ_AC_FAIL		0x40
+-#define PCC_IRQ_BERR		0x41
+-#define PCC_IRQ_ABORT		0x42
+-/* #define PCC_IRQ_SERIAL	0x43 */
+-#define PCC_IRQ_PRINTER		0x47
+-#define PCC_IRQ_TIMER1		0x48
+-#define PCC_IRQ_TIMER2		0x49
+-#define PCC_IRQ_SOFTWARE1	0x4a
+-#define PCC_IRQ_SOFTWARE2	0x4b
++#define PCC_IRQ_AC_FAIL		(IRQ_USER+0)
++#define PCC_IRQ_BERR		(IRQ_USER+1)
++#define PCC_IRQ_ABORT		(IRQ_USER+2)
++/* #define PCC_IRQ_SERIAL	(IRQ_USER+3) */
++#define PCC_IRQ_PRINTER		(IRQ_USER+7)
++#define PCC_IRQ_TIMER1		(IRQ_USER+8)
++#define PCC_IRQ_TIMER2		(IRQ_USER+9)
++#define PCC_IRQ_SOFTWARE1	(IRQ_USER+10)
++#define PCC_IRQ_SOFTWARE2	(IRQ_USER+11)
+ 
+ 
+ #define M147_SCC_A_ADDR		0xfffe3002
+ #define M147_SCC_B_ADDR		0xfffe3000
+ #define M147_SCC_PCLK		5000000
+ 
+-#define MVME147_IRQ_SCSI_PORT	0x45
+-#define MVME147_IRQ_SCSI_DMA	0x46
++#define MVME147_IRQ_SCSI_PORT	(IRQ_USER+0x45)
++#define MVME147_IRQ_SCSI_DMA	(IRQ_USER+0x46)
+ 
+ /* SCC interrupts, for MVME147 */
+ 
+ #define MVME147_IRQ_TYPE_PRIO	0
+-#define MVME147_IRQ_SCC_BASE		0x60
+-#define MVME147_IRQ_SCCB_TX		0x60
+-#define MVME147_IRQ_SCCB_STAT		0x62
+-#define MVME147_IRQ_SCCB_RX		0x64
+-#define MVME147_IRQ_SCCB_SPCOND		0x66
+-#define MVME147_IRQ_SCCA_TX		0x68
+-#define MVME147_IRQ_SCCA_STAT		0x6a
+-#define MVME147_IRQ_SCCA_RX		0x6c
+-#define MVME147_IRQ_SCCA_SPCOND		0x6e
++#define MVME147_IRQ_SCC_BASE		(IRQ_USER+32)
++#define MVME147_IRQ_SCCB_TX		(IRQ_USER+32)
++#define MVME147_IRQ_SCCB_STAT		(IRQ_USER+34)
++#define MVME147_IRQ_SCCB_RX		(IRQ_USER+36)
++#define MVME147_IRQ_SCCB_SPCOND		(IRQ_USER+38)
++#define MVME147_IRQ_SCCA_TX		(IRQ_USER+40)
++#define MVME147_IRQ_SCCA_STAT		(IRQ_USER+42)
++#define MVME147_IRQ_SCCA_RX		(IRQ_USER+44)
++#define MVME147_IRQ_SCCA_SPCOND		(IRQ_USER+46)
+ 
+ #define MVME147_LANCE_BASE	0xfffe1800
+-#define MVME147_LANCE_IRQ	0x44
++#define MVME147_LANCE_IRQ	(IRQ_USER+4)
+ 
+ #define ETHERNET_ADDRESS 0xfffe0778
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/mvme16xhw.h linux-m68k/include/asm-m68k/mvme16xhw.h
+--- linux-i386/include/asm-m68k/mvme16xhw.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/mvme16xhw.h	2006-01-28 23:55:20.000000000 +0100
+@@ -66,28 +66,28 @@
+ 
+ #define MVME162_IRQ_TYPE_PRIO	0
+ 
+-#define MVME167_IRQ_PRN		0x54
+-#define MVME16x_IRQ_I596	0x57
+-#define MVME16x_IRQ_SCSI	0x55
+-#define MVME16x_IRQ_FLY		0x7f
+-#define MVME167_IRQ_SER_ERR	0x5c
+-#define MVME167_IRQ_SER_MODEM	0x5d
+-#define MVME167_IRQ_SER_TX	0x5e
+-#define MVME167_IRQ_SER_RX	0x5f
+-#define MVME16x_IRQ_TIMER	0x59
+-#define MVME167_IRQ_ABORT	0x6e
+-#define MVME162_IRQ_ABORT	0x5e
++#define MVME167_IRQ_PRN		(IRQ_USER+20)
++#define MVME16x_IRQ_I596	(IRQ_USER+23)
++#define MVME16x_IRQ_SCSI	(IRQ_USER+21)
++#define MVME16x_IRQ_FLY		(IRQ_USER+63)
++#define MVME167_IRQ_SER_ERR	(IRQ_USER+28)
++#define MVME167_IRQ_SER_MODEM	(IRQ_USER+29)
++#define MVME167_IRQ_SER_TX	(IRQ_USER+30)
++#define MVME167_IRQ_SER_RX	(IRQ_USER+31)
++#define MVME16x_IRQ_TIMER	(IRQ_USER+25)
++#define MVME167_IRQ_ABORT	(IRQ_USER+46)
++#define MVME162_IRQ_ABORT	(IRQ_USER+30)
+ 
+ /* SCC interrupts, for MVME162 */
+-#define MVME162_IRQ_SCC_BASE		0x40
+-#define MVME162_IRQ_SCCB_TX		0x40
+-#define MVME162_IRQ_SCCB_STAT		0x42
+-#define MVME162_IRQ_SCCB_RX		0x44
+-#define MVME162_IRQ_SCCB_SPCOND		0x46
+-#define MVME162_IRQ_SCCA_TX		0x48
+-#define MVME162_IRQ_SCCA_STAT		0x4a
+-#define MVME162_IRQ_SCCA_RX		0x4c
+-#define MVME162_IRQ_SCCA_SPCOND		0x4e
++#define MVME162_IRQ_SCC_BASE		(IRQ_USER+0)
++#define MVME162_IRQ_SCCB_TX		(IRQ_USER+0)
++#define MVME162_IRQ_SCCB_STAT		(IRQ_USER+2)
++#define MVME162_IRQ_SCCB_RX		(IRQ_USER+4)
++#define MVME162_IRQ_SCCB_SPCOND		(IRQ_USER+6)
++#define MVME162_IRQ_SCCA_TX		(IRQ_USER+8)
++#define MVME162_IRQ_SCCA_STAT		(IRQ_USER+10)
++#define MVME162_IRQ_SCCA_RX		(IRQ_USER+12)
++#define MVME162_IRQ_SCCA_SPCOND		(IRQ_USER+14)
+ 
+ /* MVME162 version register */
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/processor.h linux-m68k/include/asm-m68k/processor.h
+--- linux-i386/include/asm-m68k/processor.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/processor.h	2006-01-28 23:55:20.000000000 +0100
+@@ -72,10 +72,10 @@
+ };
+ 
+ #define INIT_THREAD  {							\
+-	ksp:	sizeof(init_stack) + (unsigned long) init_stack,	\
+-	sr:	PS_S,							\
+-	fs:	__KERNEL_DS,						\
+-	info:	INIT_THREAD_INFO(init_task)				\
++	.ksp	= sizeof(init_stack) + (unsigned long) init_stack,	\
++	.sr	= PS_S,							\
++	.fs	= __KERNEL_DS,						\
++	.info	= INIT_THREAD_INFO(init_task),				\
+ }
+ 
+ /*
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/serial.h linux-m68k/include/asm-m68k/serial.h
+--- linux-i386/include/asm-m68k/serial.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/serial.h	2005-08-29 17:37:10.000000000 +0200
+@@ -26,9 +26,11 @@
+ #define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
+ #endif
+ 
++#ifdef CONFIG_ISA
+ #define SERIAL_PORT_DFNS			\
+ 	/* UART CLK   PORT IRQ     FLAGS        */			\
+ 	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
+ 	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
+ 	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
+ 	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
++#endif
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/sun3ints.h linux-m68k/include/asm-m68k/sun3ints.h
+--- linux-i386/include/asm-m68k/sun3ints.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/sun3ints.h	2006-01-28 23:55:20.000000000 +0100
+@@ -12,37 +12,25 @@
+ #define SUN3INTS_H
+ 
+ #include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/kernel_stat.h>
+ #include <linux/interrupt.h>
+-#include <linux/seq_file.h>
+-#include <asm/segment.h>
+ #include <asm/intersil.h>
+ #include <asm/oplib.h>
++#include <asm/traps.h>
+ 
+ #define SUN3_INT_VECS 192
+ 
+ void sun3_enable_irq(unsigned int irq);
+ void sun3_disable_irq(unsigned int irq);
+-int sun3_request_irq(unsigned int irq,
+-                     irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-                     unsigned long flags, const char *devname, void *dev_id
+-		    );
+ extern void sun3_init_IRQ (void);
+-extern irqreturn_t (*sun3_default_handler[]) (int, void *, struct pt_regs *);
+-extern void sun3_free_irq (unsigned int irq, void *dev_id);
+ extern void sun3_enable_interrupts (void);
+ extern void sun3_disable_interrupts (void);
+-extern int show_sun3_interrupts(struct seq_file *, void *);
+-extern irqreturn_t sun3_process_int(int, struct pt_regs *);
+ extern volatile unsigned char* sun3_intreg;
+ 
+ /* master list of VME vectors -- don't fuck with this */
+-#define SUN3_VEC_FLOPPY 0x40
+-#define SUN3_VEC_VMESCSI0 0x40
+-#define SUN3_VEC_VMESCSI1 0x41
+-#define SUN3_VEC_CG 0xA8
++#define SUN3_VEC_FLOPPY		(IRQ_USER+0)
++#define SUN3_VEC_VMESCSI0	(IRQ_USER+0)
++#define SUN3_VEC_VMESCSI1	(IRQ_USER+1)
++#define SUN3_VEC_CG		(IRQ_USER+104)
+ 
+ 
+ #endif /* SUN3INTS_H */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/thread_info.h linux-m68k/include/asm-m68k/thread_info.h
+--- linux-i386/include/asm-m68k/thread_info.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/thread_info.h	2006-04-11 16:41:20.000000000 +0200
+@@ -26,24 +26,24 @@
+ 
+ /* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */
+ #if PAGE_SHIFT == 13 /* 8k machines */
+-#define alloc_thread_info(tsk)   ((struct thread_info *)__get_free_pages(GFP_KERNEL,0))
+-#define free_thread_info(ti)  free_pages((unsigned long)(ti),0)
++#define alloc_thread_stack(tsk) ((void *)__get_free_pages(GFP_KERNEL,0))
++#define free_thread_stack(ti)  free_pages((unsigned long)(ti),0)
+ #else /* otherwise assume 4k pages */
+-#define alloc_thread_info(tsk)   ((struct thread_info *)__get_free_pages(GFP_KERNEL,1))
+-#define free_thread_info(ti)  free_pages((unsigned long)(ti),1)
++#define alloc_thread_stack(tsk) ((void *)__get_free_pages(GFP_KERNEL,1))
++#define free_thread_stack(ti)  free_pages((unsigned long)(ti),1)
+ #endif /* PAGE_SHIFT == 13 */
+ 
+ #define init_thread_info	(init_task.thread.info)
+ #define init_stack		(init_thread_union.stack)
+ 
+ #define task_thread_info(tsk)	(&(tsk)->thread.info)
+-#define task_stack_page(tsk)	((void *)(tsk)->thread_info)
++#define task_stack_page(tsk)	((void *)(tsk)->stack)
+ #define current_thread_info()	task_thread_info(current)
+ 
+ #define __HAVE_THREAD_FUNCTIONS
+ 
+ #define setup_thread_stack(p, org) ({			\
+-	*(struct task_struct **)(p)->thread_info = (p);	\
++	*(struct task_struct **)(p)->stack = (p);	\
+ 	task_thread_info(p)->task = (p);		\
+ })
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/traps.h linux-m68k/include/asm-m68k/traps.h
+--- linux-i386/include/asm-m68k/traps.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/traps.h	2006-01-28 23:55:20.000000000 +0100
+@@ -15,6 +15,10 @@
+ 
+ typedef void (*e_vector)(void);
+ 
++asmlinkage void auto_inthandler(void);
++asmlinkage void user_inthandler(void);
++asmlinkage void bad_inthandler(void);
++
+ extern e_vector vectors[];
+ 
+ #endif
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/asm-m68k/unistd.h linux-m68k/include/asm-m68k/unistd.h
+--- linux-i386/include/asm-m68k/unistd.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/asm-m68k/unistd.h	2006-02-12 16:33:52.000000000 +0100
+@@ -284,8 +284,13 @@
+ #define __NR_add_key		279
+ #define __NR_request_key	280
+ #define __NR_keyctl		281
++#define __NR_ioprio_set		282
++#define __NR_ioprio_get		283
++#define __NR_inotify_init	284
++#define __NR_inotify_add_watch	285
++#define __NR_inotify_rm_watch	286
+ 
+-#define NR_syscalls		282
++#define NR_syscalls		287
+ 
+ /* user-visible error numbers are in the range -1 - -124: see
+    <asm-m68k/errno.h> */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/adb.h linux-m68k/include/linux/adb.h
+--- linux-i386/include/linux/adb.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/adb.h	2003-03-25 20:25:16.000000000 +0100
+@@ -76,6 +76,7 @@
+ #define ADBREQ_REPLY	1	/* expect reply */
+ #define ADBREQ_SYNC	2	/* poll until done */
+ #define ADBREQ_NOSEND	4	/* build the request, but don't send it */
++#define ADBREQ_RAW	8	/* send raw packet (don't prepend ADB_PACKET) */
+ 
+ /* Messages sent thru the client_list notifier. You should NOT stop
+    the operation, at least not with this version */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/bootmem.h linux-m68k/include/linux/bootmem.h
+--- linux-i386/include/linux/bootmem.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/bootmem.h	2006-04-11 16:41:45.000000000 +0200
+@@ -56,11 +56,11 @@
+ #define alloc_bootmem(x) \
+ 	__alloc_bootmem((x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+ #define alloc_bootmem_low(x) \
+-	__alloc_bootmem_low((x), SMP_CACHE_BYTES, 0)
++	__alloc_bootmem_low((x), SMP_CACHE_BYTES, __pa(PAGE_OFFSET))
+ #define alloc_bootmem_pages(x) \
+ 	__alloc_bootmem((x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
+ #define alloc_bootmem_low_pages(x) \
+-	__alloc_bootmem_low((x), PAGE_SIZE, 0)
++	__alloc_bootmem_low((x), PAGE_SIZE, __pa(PAGE_OFFSET))
+ #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
+ extern unsigned long __init free_all_bootmem (void);
+ extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/file.h linux-m68k/include/linux/file.h
+--- linux-i386/include/linux/file.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/file.h	2006-04-11 16:41:47.000000000 +0200
+@@ -5,7 +5,6 @@
+ #ifndef __LINUX_FILE_H
+ #define __LINUX_FILE_H
+ 
+-#include <asm/atomic.h>
+ #include <linux/posix_types.h>
+ #include <linux/compiler.h>
+ #include <linux/spinlock.h>
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/ide.h linux-m68k/include/linux/ide.h
+--- linux-i386/include/linux/ide.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/ide.h	2006-04-11 16:41:50.000000000 +0200
+@@ -510,7 +510,7 @@
+  * sense_key	: Sense key of the last failed packet command
+  */
+ typedef union {
+-	unsigned all			:8;
++	u8 all;
+ 	struct {
+ #if defined(__LITTLE_ENDIAN_BITFIELD)
+ 		unsigned ili		:1;
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/init_task.h linux-m68k/include/linux/init_task.h
+--- linux-i386/include/linux/init_task.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/init_task.h	2006-01-19 22:10:55.000000000 +0100
+@@ -79,7 +79,7 @@
+ #define INIT_TASK(tsk)	\
+ {									\
+ 	.state		= 0,						\
+-	.thread_info	= &init_thread_info,				\
++	.stack		= &init_stack,					\
+ 	.usage		= ATOMIC_INIT(2),				\
+ 	.flags		= 0,						\
+ 	.lock_depth	= -1,						\
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/kernel_stat.h linux-m68k/include/linux/kernel_stat.h
+--- linux-i386/include/linux/kernel_stat.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/kernel_stat.h	2006-04-11 16:41:51.000000000 +0200
+@@ -2,12 +2,12 @@
+ #define _LINUX_KERNEL_STAT_H
+ 
+ #include <linux/config.h>
+-#include <asm/irq.h>
+ #include <linux/smp.h>
+ #include <linux/threads.h>
+ #include <linux/percpu.h>
+ #include <linux/cpumask.h>
+ #include <asm/cputime.h>
++#include <asm/irq.h>
+ 
+ /*
+  * 'kernel_stat.h' contains the definitions needed for doing
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/module.h linux-m68k/include/linux/module.h
+--- linux-i386/include/linux/module.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/module.h	2006-01-28 23:55:42.000000000 +0100
+@@ -314,6 +314,9 @@
+ 	   keeping pointers to this stuff */
+ 	char *args;
+ };
++#ifndef MODULE_ARCH_INIT
++#define MODULE_ARCH_INIT {}
++#endif
+ 
+ /* FIXME: It'd be nice to isolate modules during init, too, so they
+    aren't used before they (may) fail.  But presently too much code
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/sched.h linux-m68k/include/linux/sched.h
+--- linux-i386/include/linux/sched.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/sched.h	2006-04-11 16:41:54.000000000 +0200
+@@ -691,7 +691,8 @@
+ 
+ struct task_struct {
+ 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
+-	struct thread_info *thread_info;
++	//struct thread_info *thread_info;
++	void *stack;
+ 	atomic_t usage;
+ 	unsigned long flags;	/* per process flags, defined below */
+ 	unsigned long ptrace;
+@@ -1257,6 +1258,7 @@
+ /* set thread flags in other task's structures
+  * - see asm/thread_info.h for TIF_xxxx flags available
+  */
++
+ static inline void set_tsk_thread_flag(struct task_struct *tsk, int flag)
+ {
+ 	set_ti_thread_flag(task_thread_info(tsk), flag);
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/thread_info.h linux-m68k/include/linux/thread_info.h
+--- linux-i386/include/linux/thread_info.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/thread_info.h	2005-05-30 02:26:01.000000000 +0200
+@@ -66,6 +66,6 @@
+ #define set_need_resched()	set_thread_flag(TIF_NEED_RESCHED)
+ #define clear_need_resched()	clear_thread_flag(TIF_NEED_RESCHED)
+ 
+-#endif
++#endif	/* __KERNEL__ */
+ 
+ #endif /* _LINUX_THREAD_INFO_H */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/include/linux/zorro.h linux-m68k/include/linux/zorro.h
+--- linux-i386/include/linux/zorro.h	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/include/linux/zorro.h	2006-01-28 23:55:43.000000000 +0100
+@@ -11,8 +11,6 @@
+ #ifndef _LINUX_ZORRO_H
+ #define _LINUX_ZORRO_H
+ 
+-#ifndef __ASSEMBLY__
+-
+ #include <linux/device.h>
+ 
+ 
+@@ -112,45 +110,6 @@
+     __u32		cd_Unused[4];	/* for whatever the driver wants */
+ } __attribute__ ((packed));
+ 
+-#else /* __ASSEMBLY__ */
+-
+-LN_Succ		= 0
+-LN_Pred		= LN_Succ+4
+-LN_Type		= LN_Pred+4
+-LN_Pri		= LN_Type+1
+-LN_Name		= LN_Pri+1
+-LN_sizeof	= LN_Name+4
+-
+-ER_Type		= 0
+-ER_Product	= ER_Type+1
+-ER_Flags	= ER_Product+1
+-ER_Reserved03	= ER_Flags+1
+-ER_Manufacturer	= ER_Reserved03+1
+-ER_SerialNumber	= ER_Manufacturer+2
+-ER_InitDiagVec	= ER_SerialNumber+4
+-ER_Reserved0c	= ER_InitDiagVec+2
+-ER_Reserved0d	= ER_Reserved0c+1
+-ER_Reserved0e	= ER_Reserved0d+1
+-ER_Reserved0f	= ER_Reserved0e+1
+-ER_sizeof	= ER_Reserved0f+1
+-
+-CD_Node		= 0
+-CD_Flags	= CD_Node+LN_sizeof
+-CD_Pad		= CD_Flags+1
+-CD_Rom		= CD_Pad+1
+-CD_BoardAddr	= CD_Rom+ER_sizeof
+-CD_BoardSize	= CD_BoardAddr+4
+-CD_SlotAddr	= CD_BoardSize+4
+-CD_SlotSize	= CD_SlotAddr+2
+-CD_Driver	= CD_SlotSize+2
+-CD_NextCD	= CD_Driver+4
+-CD_Unused	= CD_NextCD+4
+-CD_sizeof	= CD_Unused+(4*4)
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#ifndef __ASSEMBLY__
+-
+ #define ZORRO_NUM_AUTO		16
+ 
+ #ifdef __KERNEL__
+@@ -323,7 +282,6 @@
+ #define Z2RAM_CHUNKSHIFT	(16)
+ 
+ 
+-#endif /* !__ASSEMBLY__ */
+ #endif /* __KERNEL__ */
+ 
+ #endif /* _LINUX_ZORRO_H */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/kernel/fork.c linux-m68k/kernel/fork.c
+--- linux-i386/kernel/fork.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/kernel/fork.c	2006-04-11 16:42:19.000000000 +0200
+@@ -103,7 +103,7 @@
+ 
+ void free_task(struct task_struct *tsk)
+ {
+-	free_thread_info(tsk->thread_info);
++	free_thread_stack(tsk->stack);
+ 	free_task_struct(tsk);
+ }
+ EXPORT_SYMBOL(free_task);
+@@ -160,7 +160,7 @@
+ static struct task_struct *dup_task_struct(struct task_struct *orig)
+ {
+ 	struct task_struct *tsk;
+-	struct thread_info *ti;
++	void *stack;
+ 
+ 	prepare_to_copy(orig);
+ 
+@@ -168,14 +168,14 @@
+ 	if (!tsk)
+ 		return NULL;
+ 
+-	ti = alloc_thread_info(tsk);
+-	if (!ti) {
++	stack = alloc_thread_stack(tsk);
++	if (!stack) {
+ 		free_task_struct(tsk);
+ 		return NULL;
+ 	}
+ 
+ 	*tsk = *orig;
+-	tsk->thread_info = ti;
++	tsk->stack = stack;
+ 	setup_thread_stack(tsk, orig);
+ 
+ 	/* One for us, one for whoever does the "release_task()" (usually parent) */
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/lib/kref.c linux-m68k/lib/kref.c
+--- linux-i386/lib/kref.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/lib/kref.c	2005-11-01 02:17:02.000000000 +0100
+@@ -11,8 +11,8 @@
+  *
+  */
+ 
+-#include <linux/kref.h>
+ #include <linux/module.h>
++#include <linux/kref.h>
+ 
+ /**
+  * kref_init - initialize object.
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/mm/bootmem.c linux-m68k/mm/bootmem.c
+--- linux-i386/mm/bootmem.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/mm/bootmem.c	2006-04-11 16:42:33.000000000 +0200
+@@ -285,7 +285,6 @@
+ 
+ 	count = 0;
+ 	/* first extant page of the node */
+-	pfn = bdata->node_boot_start >> PAGE_SHIFT;
+ 	idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
+ 	map = bdata->node_bootmem_map;
+ 	/* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */
+@@ -298,26 +297,24 @@
+ 		if (gofast && v == ~0UL) {
+ 			int order;
+ 
+-			page = pfn_to_page(pfn);
++			page = virt_to_page(phys_to_virt((i << PAGE_SHIFT) +
++							 bdata->node_boot_start));
+ 			count += BITS_PER_LONG;
+ 			order = ffs(BITS_PER_LONG) - 1;
+ 			__free_pages_bootmem(page, order);
+ 			i += BITS_PER_LONG;
+-			page += BITS_PER_LONG;
+ 		} else if (v) {
+ 			unsigned long m;
+-
+-			page = pfn_to_page(pfn);
+-			for (m = 1; m && i < idx; m<<=1, page++, i++) {
++			for (m = 1; m && i < idx; m<<=1, i++) {
+ 				if (v & m) {
++					page = virt_to_page(phys_to_virt((i << PAGE_SHIFT) +
++									 bdata->node_boot_start));
+ 					count++;
+ 					__free_pages_bootmem(page, 0);
+ 				}
+ 			}
+-		} else {
++		} else
+ 			i+=BITS_PER_LONG;
+-		}
+-		pfn += BITS_PER_LONG;
+ 	}
+ 	total += count;
+ 
+diff -urN --exclude-from=/usr/src/exclude-file linux-i386/scripts/mod/modpost.c linux-m68k/scripts/mod/modpost.c
+--- linux-i386/scripts/mod/modpost.c	2006-03-20 06:53:29.000000000 +0100
++++ linux-m68k/scripts/mod/modpost.c	2006-04-11 16:44:12.000000000 +0200
+@@ -543,6 +543,7 @@
+ 		buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
+ 			      " .exit = cleanup_module,\n"
+ 			      "#endif\n");
++	buf_printf(b, " .arch = MODULE_ARCH_INIT,\n");
+ 	buf_printf(b, "};\n");
+ }
+ 



More information about the Kernel-svn-changes mailing list