From 2f050944e80077febe655d02a0cd4cdc188f5db3 Mon Sep 17 00:00:00 2001 From: "Christian T. Steigies" Date: Tue, 27 Jun 2006 22:46:47 +0000 Subject: [PATCH] m68k updates svn path=/dists/trunk/linux-2.6/; revision=6911 --- debian/arch/m68k/defines | 16 +- debian/changelog | 8 +- debian/patches/m68k-2.6.17.patch | 11564 +++++++++++++++++++++++++++++ debian/patches/m68k-as.patch | 308 + debian/patches/m68k-macro.patch | 149 + debian/patches/series/1-extra | 3 + 6 files changed, 12039 insertions(+), 9 deletions(-) create mode 100644 debian/patches/m68k-2.6.17.patch create mode 100644 debian/patches/m68k-as.patch create mode 100644 debian/patches/m68k-macro.patch diff --git a/debian/arch/m68k/defines b/debian/arch/m68k/defines index 2c418e979..3560dea1a 100644 --- a/debian/arch/m68k/defines +++ b/debian/arch/m68k/defines @@ -1,15 +1,15 @@ [base] -compiler: gcc-3.3 +compiler: gcc-4.1 flavours: amiga - atari - bvme6000 - hp +# atari +# bvme6000 +# hp mac - mvme147 - mvme16x - q40 - sun3 +# mvme147 +# mvme16x +# q40 +# sun3 kernel-arch: m68k kernel-header-dirs: m68k diff --git a/debian/changelog b/debian/changelog index 3426e676e..2ac4c42df 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,7 +16,13 @@ linux-2.6 (2.6.17-2) UNRELEASED; urgency=low * [mipsel] Update configs. * [mipsel] Add a build fix for the Cobalt early console support. - -- Sven Luther Tue, 27 Jun 2006 13:52:03 +0200 + [ Christian T. Steigies ] + * [m68k] Update patches for 2.6.17. + * [m68k] Add m68k-as and m68k-macro patch which allow building with current binutils. + * [m68k] Use gcc 4.1. + * [m68k] Disable all subarches but amiga and mac for official linux-images. + + -- Christian T. Steigies Wed, 28 Jun 2006 00:41:00 +0200 linux-2.6 (2.6.17-1) unstable; urgency=low diff --git a/debian/patches/m68k-2.6.17.patch b/debian/patches/m68k-2.6.17.patch new file mode 100644 index 000000000..4a8c8b55d --- /dev/null +++ b/debian/patches/m68k-2.6.17.patch @@ -0,0 +1,11564 @@ +diff -urN linux-i386/Makefile linux-m68k/Makefile +--- linux-i386/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/Makefile 2006-06-22 09:48:16.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 linux-i386/arch/m68k/Kconfig linux-m68k/arch/m68k/Kconfig +--- linux-i386/arch/m68k/Kconfig 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/Kconfig 2006-06-18 19:06:43.000000000 +0200 +@@ -600,7 +600,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 linux-i386/arch/m68k/Makefile linux-m68k/arch/m68k/Makefile +--- linux-i386/arch/m68k/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/Makefile 2006-06-06 01:17:27.000000000 +0200 +@@ -19,6 +19,7 @@ + # override top level makefile + AS += -m68020 + LDFLAGS := -m m68kelf ++LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds + ifneq ($(COMPILE_ARCH),$(ARCH)) + # prefix for cross-compiling binaries + CROSS_COMPILE = m68k-linux- +diff -urN 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-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/amiga/amiga_ksyms.c 2006-01-28 22:32:48.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 linux-i386/arch/m68k/amiga/amiints.c linux-m68k/arch/m68k/amiga/amiints.c +--- linux-i386/arch/m68k/amiga/amiints.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/amiga/amiints.c 2006-04-10 00:21:43.000000000 +0200 +@@ -35,60 +35,29 @@ + * /Jes + */ + +-#include +-#include +-#include +-#include + #include ++#include + #include +-#include + +-#include + #include + #include + #include + #include + #include + +-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 linux-i386/arch/m68k/amiga/cia.c linux-m68k/arch/m68k/amiga/cia.c +--- linux-i386/arch/m68k/amiga/cia.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/amiga/cia.c 2006-04-10 00:21:43.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 linux-i386/arch/m68k/amiga/config.c linux-m68k/arch/m68k/amiga/config.c +--- linux-i386/arch/m68k/amiga/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/amiga/config.c 2006-04-10 00:21:43.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 linux-i386/arch/m68k/apollo/Makefile linux-m68k/arch/m68k/apollo/Makefile +--- linux-i386/arch/m68k/apollo/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/apollo/Makefile 2006-06-06 01:18:31.000000000 +0200 +@@ -2,4 +2,4 @@ + # Makefile for Linux arch/m68k/amiga source directory + # + +-obj-y := config.o dn_ints.o dma.o ++obj-y := config.o dn_ints.o +diff -urN linux-i386/arch/m68k/apollo/config.c linux-m68k/arch/m68k/apollo/config.c +--- linux-i386/arch/m68k/apollo/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/apollo/config.c 2006-01-28 22:33:11.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 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-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/apollo/dn_ints.c 2006-01-28 22:33:11.000000000 +0100 +@@ -1,125 +1,44 @@ +-#include +-#include +-#include +-#include +-#include ++#include + +-#include + #include + #include +-#include +-#include + #include +-#include + +-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<15)) { +- printk("Trying to free invalid IRQ\n"); +- return ; +- } +- +- if(irq<8) +- *(volatile unsigned char *)(pica+1)|=(1< 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 linux-i386/arch/m68k/atari/config.c linux-m68k/arch/m68k/atari/config.c +--- linux-i386/arch/m68k/atari/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/atari/config.c 2006-04-10 00:21:44.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 linux-i386/arch/m68k/bvme6000/Makefile linux-m68k/arch/m68k/bvme6000/Makefile +--- linux-i386/arch/m68k/bvme6000/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/bvme6000/Makefile 2006-01-28 22:33:47.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 linux-i386/arch/m68k/bvme6000/config.c linux-m68k/arch/m68k/bvme6000/config.c +--- linux-i386/arch/m68k/bvme6000/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/bvme6000/config.c 2006-06-18 19:06:43.000000000 +0200 +@@ -36,15 +36,8 @@ + #include + #include + +-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 linux-i386/arch/m68k/hp300/Makefile linux-m68k/arch/m68k/hp300/Makefile +--- linux-i386/arch/m68k/hp300/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/hp300/Makefile 2006-01-28 22:35:53.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 linux-i386/arch/m68k/hp300/config.c linux-m68k/arch/m68k/hp300/config.c +--- linux-i386/arch/m68k/hp300/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/hp300/config.c 2006-01-28 22:35:53.000000000 +0100 +@@ -21,7 +21,6 @@ + #include + #include + +-#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 linux-i386/arch/m68k/hp300/time.c linux-m68k/arch/m68k/hp300/time.c +--- linux-i386/arch/m68k/hp300/time.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/hp300/time.c 2006-01-28 22:35:53.000000000 +0100 +@@ -18,7 +18,6 @@ + #include + #include + #include +-#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 linux-i386/arch/m68k/kernel/Makefile linux-m68k/arch/m68k/kernel/Makefile +--- linux-i386/arch/m68k/kernel/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/Makefile 2006-06-06 01:18:31.000000000 +0200 +@@ -9,8 +9,8 @@ + endif + extra-y += vmlinux.lds + +-obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \ +- sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o ++obj-y := entry.o process.o traps.o ints.o dma.o signal.o ptrace.o \ ++ sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o + + obj-$(CONFIG_PCI) += bios32.o + obj-$(CONFIG_MODULES) += module.o +diff -urN linux-i386/arch/m68k/kernel/bios32.c linux-m68k/arch/m68k/kernel/bios32.c +--- linux-i386/arch/m68k/kernel/bios32.c 2006-06-18 03:49:35.000000000 +0200 ++++ 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 linux-i386/arch/m68k/kernel/dma.c linux-m68k/arch/m68k/kernel/dma.c +--- linux-i386/arch/m68k/kernel/dma.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-m68k/arch/m68k/kernel/dma.c 2006-06-24 16:32:07.000000000 +0200 +@@ -0,0 +1,129 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive ++ * for more details. ++ */ ++ ++#undef DEBUG ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++void *dma_alloc_coherent(struct device *dev, size_t size, ++ dma_addr_t *handle, int flag) ++{ ++ struct page *page, **map; ++ pgprot_t pgprot; ++ void *addr; ++ int i, order; ++ ++ pr_debug("dma_alloc_coherent: %d,%x\n", size, flag); ++ ++ size = PAGE_ALIGN(size); ++ order = get_order(size); ++ ++ page = alloc_pages(flag, order); ++ if (!page) ++ return NULL; ++ ++ *handle = page_to_phys(page); ++ map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA); ++ if (!map) { ++ __free_pages(page, order); ++ return NULL; ++ } ++ split_page(page, order); ++ ++ order = 1 << order; ++ size >>= PAGE_SHIFT; ++ map[0] = page; ++ for (i = 1; i < size; i++) ++ map[i] = page + i; ++ for (; i < order; i++) ++ __free_page(page + i); ++ pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); ++ if (CPU_IS_040_OR_060) ++ pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S; ++ else ++ pgprot_val(pgprot) |= _PAGE_NOCACHE030; ++ addr = vmap(map, size, flag, pgprot); ++ kfree(map); ++ ++ return addr; ++} ++EXPORT_SYMBOL(dma_alloc_coherent); ++ ++void dma_free_coherent(struct device *dev, size_t size, ++ void *addr, dma_addr_t handle) ++{ ++ pr_debug("dma_free_coherent: %p, %x\n", addr, handle); ++ vfree(addr); ++} ++EXPORT_SYMBOL(dma_free_coherent); ++ ++inline void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size, ++ enum dma_data_direction dir) ++{ ++ switch (dir) { ++ case DMA_TO_DEVICE: ++ cache_push(handle, size); ++ break; ++ case DMA_FROM_DEVICE: ++ cache_clear(handle, size); ++ break; ++ default: ++ if (printk_ratelimit()) ++ printk("dma_sync_single_for_device: unsupported dir %u\n", dir); ++ break; ++ } ++} ++EXPORT_SYMBOL(dma_sync_single_for_device); ++ ++void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, ++ enum dma_data_direction dir) ++{ ++ int i; ++ ++ for (i = 0; i < nents; sg++, i++) ++ dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); ++} ++EXPORT_SYMBOL(dma_sync_sg_for_device); ++ ++dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, ++ enum dma_data_direction dir) ++{ ++ dma_addr_t handle = virt_to_bus(addr); ++ ++ dma_sync_single_for_device(dev, handle, size, dir); ++ return handle; ++} ++EXPORT_SYMBOL(dma_map_single); ++ ++dma_addr_t dma_map_page(struct device *dev, struct page *page, ++ unsigned long offset, size_t size, ++ enum dma_data_direction dir) ++{ ++ dma_addr_t handle = page_to_phys(page) + offset; ++ ++ dma_sync_single_for_device(dev, handle, size, dir); ++ return handle; ++} ++EXPORT_SYMBOL(dma_map_page); ++ ++int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, ++ enum dma_data_direction dir) ++{ ++ int i; ++ ++ for (i = 0; i < nents; sg++, i++) { ++ sg->dma_address = page_to_phys(sg->page) + sg->offset; ++ dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); ++ } ++ return nents; ++} ++EXPORT_SYMBOL(dma_map_sg); +diff -urN linux-i386/arch/m68k/kernel/entry.S linux-m68k/arch/m68k/kernel/entry.S +--- linux-i386/arch/m68k/kernel/entry.S 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/entry.S 2006-02-11 17:28:36.000000000 +0100 +@@ -45,9 +45,11 @@ + #include + + .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@- +- movel %d0,%sp@- +- 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@- + movel %d0,%sp@- | 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@- ++ movel %d0,%sp@- | 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@- ++ 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 linux-i386/arch/m68k/kernel/ints.c linux-m68k/arch/m68k/kernel/ints.c +--- linux-i386/arch/m68k/kernel/ints.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/ints.c 2006-01-31 01:57:35.000000000 +0100 +@@ -39,47 +39,40 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_Q40 + #include + #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 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-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/m68k_ksyms.c 2006-06-18 19:06:44.000000000 +0200 +@@ -57,8 +57,6 @@ + EXPORT_SYMBOL(strnlen); + EXPORT_SYMBOL(strrchr); + EXPORT_SYMBOL(strstr); +-EXPORT_SYMBOL(enable_irq); +-EXPORT_SYMBOL(disable_irq); + EXPORT_SYMBOL(kernel_thread); + #ifdef CONFIG_VME + EXPORT_SYMBOL(vme_brdtype); +diff -urN linux-i386/arch/m68k/kernel/module.c linux-m68k/arch/m68k/kernel/module.c +--- linux-i386/arch/m68k/kernel/module.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/module.c 2006-06-06 01:17:28.000000000 +0200 +@@ -1,3 +1,9 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive ++ * for more details. ++ */ ++ + #include + #include + #include +@@ -116,10 +122,26 @@ + return 0; + } + ++void module_fixup(struct module *mod, struct m68k_fixup_info *start, ++ struct m68k_fixup_info *end) ++{ ++ struct m68k_fixup_info *fixup; ++ ++ for (fixup = start; fixup < end; fixup++) { ++ switch (fixup->type) { ++ case m68k_fixup_memoffset: ++ *(u32 *)fixup->addr = m68k_memoffset; ++ break; ++ } ++ } ++} ++ + int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, +- struct module *me) ++ struct module *mod) + { ++ module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); ++ + return 0; + } + +diff -urN linux-i386/arch/m68k/kernel/module.lds linux-m68k/arch/m68k/kernel/module.lds +--- linux-i386/arch/m68k/kernel/module.lds 1970-01-01 01:00:00.000000000 +0100 ++++ linux-m68k/arch/m68k/kernel/module.lds 2006-06-06 01:17:28.000000000 +0200 +@@ -0,0 +1,7 @@ ++SECTIONS { ++ .m68k_fixup : { ++ __start_fixup = .; ++ *(.m68k_fixup) ++ __stop_fixup = .; ++ } ++} +diff -urN linux-i386/arch/m68k/kernel/setup.c linux-m68k/arch/m68k/kernel/setup.c +--- linux-i386/arch/m68k/kernel/setup.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/setup.c 2006-04-10 00:21:45.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 linux-i386/arch/m68k/kernel/sun3-head.S linux-m68k/arch/m68k/kernel/sun3-head.S +--- linux-i386/arch/m68k/kernel/sun3-head.S 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/sun3-head.S 2006-05-11 13:14:10.000000000 +0200 +@@ -66,17 +66,7 @@ + /* Following code executes at high addresses (0xE000xxx). */ + 1: lea init_task,%curptr | get initial thread... + lea init_thread_union+THREAD_SIZE,%sp | ...and its stack. +- +-/* copy bootinfo records from the loader to _end */ +- lea _end, %a1 +- lea BI_START, %a0 +- /* number of longs to copy */ +- movel %a0@, %d0 +-1: addl #4, %a0 +- movel %a0@, %a1@ +- addl #4, %a1 +- dbf %d0, 1b +- ++ + /* Point MSP at an invalid page to trap if it's used. --m */ + movl #(PAGESIZE),%d0 + movc %d0,%msp +diff -urN linux-i386/arch/m68k/kernel/traps.c linux-m68k/arch/m68k/kernel/traps.c +--- linux-i386/arch/m68k/kernel/traps.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/traps.c 2006-06-01 02:34:48.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) +@@ -927,71 +885,94 @@ + void show_registers(struct pt_regs *regs) + { + struct frame *fp = (struct frame *)regs; ++ mm_segment_t old_fs = get_fs(); ++ u16 c, *cp; + unsigned long addr; + int i; + ++ print_modules(); ++ printk("PC: [<%08lx>]",regs->pc); ++ print_symbol(" %s\n", regs->pc); ++ printk("SR: %04x SP: %p a2: %08lx\n", ++ regs->sr, regs, regs->a2); ++ printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", ++ regs->d0, regs->d1, regs->d2, regs->d3); ++ printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", ++ regs->d4, regs->d5, regs->a0, regs->a1); ++ ++ printk("Process %s (pid: %d, task=%p)\n", ++ current->comm, current->pid, current); + addr = (unsigned long)&fp->un; +- printk("Frame format=%X ", fp->ptregs.format); +- switch (fp->ptregs.format) { ++ printk("Frame format=%X ", regs->format); ++ switch (regs->format) { + case 0x2: +- printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); +- addr += sizeof(fp->un.fmt2); +- break; ++ printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); ++ addr += sizeof(fp->un.fmt2); ++ break; + case 0x3: +- printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); +- addr += sizeof(fp->un.fmt3); +- break; ++ printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); ++ addr += sizeof(fp->un.fmt3); ++ break; + case 0x4: +- printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" +- : "eff addr=%08lx pc=%08lx\n"), +- fp->un.fmt4.effaddr, fp->un.fmt4.pc); +- addr += sizeof(fp->un.fmt4); +- break; ++ printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" ++ : "eff addr=%08lx pc=%08lx\n"), ++ fp->un.fmt4.effaddr, fp->un.fmt4.pc); ++ addr += sizeof(fp->un.fmt4); ++ break; + case 0x7: +- printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", +- fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); +- printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", +- fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); +- printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", +- fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); +- printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", +- fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); +- printk("push data: %08lx %08lx %08lx %08lx\n", +- fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, +- fp->un.fmt7.pd3); +- addr += sizeof(fp->un.fmt7); +- break; ++ printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", ++ fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); ++ printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", ++ fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); ++ printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", ++ fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); ++ printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", ++ fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); ++ printk("push data: %08lx %08lx %08lx %08lx\n", ++ fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, ++ fp->un.fmt7.pd3); ++ addr += sizeof(fp->un.fmt7); ++ break; + case 0x9: +- printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); +- addr += sizeof(fp->un.fmt9); +- break; ++ printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); ++ addr += sizeof(fp->un.fmt9); ++ break; + case 0xa: +- printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", +- fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, +- fp->un.fmta.daddr, fp->un.fmta.dobuf); +- addr += sizeof(fp->un.fmta); +- break; ++ printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", ++ fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, ++ fp->un.fmta.daddr, fp->un.fmta.dobuf); ++ addr += sizeof(fp->un.fmta); ++ break; + case 0xb: +- printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", +- fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, +- fp->un.fmtb.daddr, fp->un.fmtb.dobuf); +- printk("baddr=%08lx dibuf=%08lx ver=%x\n", +- fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); +- addr += sizeof(fp->un.fmtb); +- break; ++ printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", ++ fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, ++ fp->un.fmtb.daddr, fp->un.fmtb.dobuf); ++ printk("baddr=%08lx dibuf=%08lx ver=%x\n", ++ fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); ++ addr += sizeof(fp->un.fmtb); ++ break; + default: +- printk("\n"); ++ printk("\n"); + } + show_stack(NULL, (unsigned long *)addr); + +- printk("Code: "); +- for (i = 0; i < 10; i++) +- printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]); ++ printk("Code:"); ++ set_fs(KERNEL_DS); ++ cp = (u16 *)regs->pc; ++ for (i = -8; i < 16; i++) { ++ if (get_user(c, cp + i) && i >= 0) { ++ printk(" Bad PC value."); ++ break; ++ } ++ printk(i ? " %04x" : " <%04x>", c); ++ } ++ set_fs(old_fs); + printk ("\n"); + } + + void show_stack(struct task_struct *task, unsigned long *stack) + { ++ unsigned long *p; + unsigned long *endstack; + int i; + +@@ -1004,12 +985,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); +@@ -1188,19 +1170,7 @@ + + console_verbose(); + printk("%s: %08x\n",str,nr); +- print_modules(); +- printk("PC: [<%08lx>]",fp->pc); +- print_symbol(" %s\n", fp->pc); +- printk("\nSR: %04x SP: %p a2: %08lx\n", +- fp->sr, fp, fp->a2); +- printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", +- fp->d0, fp->d1, fp->d2, fp->d3); +- printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", +- fp->d4, fp->d5, fp->a0, fp->a1); +- +- printk("Process %s (pid: %d, stackpage=%08lx)\n", +- current->comm, current->pid, PAGE_SIZE+(unsigned long)current); +- show_stack(NULL, (unsigned long *)fp); ++ show_registers(fp); + do_exit(SIGSEGV); + } + +diff -urN linux-i386/arch/m68k/kernel/vmlinux-std.lds linux-m68k/arch/m68k/kernel/vmlinux-std.lds +--- linux-i386/arch/m68k/kernel/vmlinux-std.lds 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/vmlinux-std.lds 2006-06-06 01:17:28.000000000 +0200 +@@ -66,6 +66,11 @@ + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; ++ .m68k_fixup : { ++ __start_fixup = .; ++ *(.m68k_fixup) ++ __stop_fixup = .; ++ } + SECURITY_INIT + . = ALIGN(8192); + __initramfs_start = .; +diff -urN linux-i386/arch/m68k/kernel/vmlinux-sun3.lds linux-m68k/arch/m68k/kernel/vmlinux-sun3.lds +--- linux-i386/arch/m68k/kernel/vmlinux-sun3.lds 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/kernel/vmlinux-sun3.lds 2006-06-06 01:17:28.000000000 +0200 +@@ -8,7 +8,7 @@ + jiffies = jiffies_64 + 4; + SECTIONS + { +- . = 0xE004000; ++ . = 0xE002000; + _text = .; /* Text and read-only data */ + .text : { + *(.head) +@@ -60,6 +60,11 @@ + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; ++ .m68k_fixup : { ++ __start_fixup = .; ++ *(.m68k_fixup) ++ __stop_fixup = .; ++ } + SECURITY_INIT + . = ALIGN(8192); + __initramfs_start = .; +diff -urN linux-i386/arch/m68k/lib/Makefile linux-m68k/arch/m68k/lib/Makefile +--- linux-i386/arch/m68k/lib/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/lib/Makefile 2006-06-06 00:59:09.000000000 +0200 +@@ -4,5 +4,5 @@ + + EXTRA_AFLAGS := -traditional + +-lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ +- checksum.o string.o semaphore.o ++lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ ++ checksum.o string.o semaphore.o uaccess.o +diff -urN linux-i386/arch/m68k/lib/uaccess.c linux-m68k/arch/m68k/lib/uaccess.c +--- linux-i386/arch/m68k/lib/uaccess.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-m68k/arch/m68k/lib/uaccess.c 2006-06-06 00:59:09.000000000 +0200 +@@ -0,0 +1,222 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive ++ * for more details. ++ */ ++ ++#include ++#include ++ ++unsigned long __generic_copy_from_user(void *to, const void __user *from, ++ unsigned long n) ++{ ++ unsigned long tmp, res; ++ ++ asm volatile ("\n" ++ " tst.l %0\n" ++ " jeq 2f\n" ++ "1: moves.l (%1)+,%3\n" ++ " move.l %3,(%2)+\n" ++ " subq.l #1,%0\n" ++ " jne 1b\n" ++ "2: btst #1,%5\n" ++ " jeq 4f\n" ++ "3: moves.w (%1)+,%3\n" ++ " move.w %3,(%2)+\n" ++ "4: btst #0,%5\n" ++ " jeq 6f\n" ++ "5: moves.b (%1)+,%3\n" ++ " move.b %3,(%2)+\n" ++ "6:\n" ++ " .section .fixup,\"ax\"\n" ++ " .even\n" ++ "10: move.l %0,%3\n" ++ "7: clr.l (%2)+\n" ++ " subq.l #1,%3\n" ++ " jne 7b\n" ++ " lsl.l #2,%0\n" ++ " btst #1,%5\n" ++ " jeq 8f\n" ++ "30: clr.w (%2)+\n" ++ " addq.l #2,%0\n" ++ "8: btst #0,%5\n" ++ " jeq 6b\n" ++ "50: clr.b (%2)+\n" ++ " addq.l #1,%0\n" ++ " jra 6b\n" ++ " .previous\n" ++ "\n" ++ " .section __ex_table,\"a\"\n" ++ " .align 4\n" ++ " .long 1b,10b\n" ++ " .long 3b,30b\n" ++ " .long 5b,50b\n" ++ " .previous" ++ : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) ++ : "0" (n / 4), "d" (n & 3)); ++ ++ return res; ++} ++EXPORT_SYMBOL(__generic_copy_from_user); ++ ++unsigned long __generic_copy_to_user(void __user *to, const void *from, ++ unsigned long n) ++{ ++ unsigned long tmp, res; ++ ++ asm volatile ("\n" ++ " tst.l %0\n" ++ " jeq 4f\n" ++ "1: move.l (%1)+,%3\n" ++ "2: moves.l %3,(%2)+\n" ++ "3: subq.l #1,%0\n" ++ " jne 1b\n" ++ "4: btst #1,%5\n" ++ " jeq 6f\n" ++ " move.w (%1)+,%3\n" ++ "5: moves.w %3,(%2)+\n" ++ "6: btst #0,%5\n" ++ " jeq 8f\n" ++ " move.b (%1)+,%3\n" ++ "7: moves.b %3,(%2)+\n" ++ "8:\n" ++ " .section .fixup,\"ax\"\n" ++ " .even\n" ++ "20: lsl.l #2,%0\n" ++ "50: add.l %5,%0\n" ++ " jra 7b\n" ++ " .previous\n" ++ "\n" ++ " .section __ex_table,\"a\"\n" ++ " .align 4\n" ++ " .long 2b,20b\n" ++ " .long 3b,20b\n" ++ " .long 5b,50b\n" ++ " .long 6b,50b\n" ++ " .long 7b,50b\n" ++ " .long 8b,50b\n" ++ " .previous" ++ : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) ++ : "0" (n / 4), "d" (n & 3)); ++ ++ return res; ++} ++EXPORT_SYMBOL(__generic_copy_to_user); ++ ++/* ++ * Copy a null terminated string from userspace. ++ */ ++long strncpy_from_user(char *dst, const char __user *src, long count) ++{ ++ long res; ++ char c; ++ ++ if (count <= 0) ++ return count; ++ ++ asm volatile ("\n" ++ "1: moves.b (%2)+,%4\n" ++ " move.b %4,(%1)+\n" ++ " jeq 2f\n" ++ " subq.l #1,%3\n" ++ " jne 1b\n" ++ "2: sub.l %3,%0\n" ++ "3:\n" ++ " .section .fixup,\"ax\"\n" ++ " .even\n" ++ "10: move.l %5,%0\n" ++ " jra 3b\n" ++ " .previous\n" ++ "\n" ++ " .section __ex_table,\"a\"\n" ++ " .align 4\n" ++ " .long 1b,10b\n" ++ " .previous" ++ : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c) ++ : "i" (-EFAULT), "0" (count)); ++ ++ return res; ++} ++EXPORT_SYMBOL(strncpy_from_user); ++ ++/* ++ * Return the size of a string (including the ending 0) ++ * ++ * Return 0 on exception, a value greater than N if too long ++ */ ++long strnlen_user(const char __user *src, long n) ++{ ++ char c; ++ long res; ++ ++ asm volatile ("\n" ++ "1: subq.l #1,%1\n" ++ " jmi 3f\n" ++ "2: moves.b (%0)+,%2\n" ++ " tst.b %2\n" ++ " jne 1b\n" ++ " jra 4f\n" ++ "\n" ++ "3: addq.l #1,%0\n" ++ "4: sub.l %4,%0\n" ++ "5:\n" ++ " .section .fixup,\"ax\"\n" ++ " .even\n" ++ "20: sub.l %0,%0\n" ++ " jra 5b\n" ++ " .previous\n" ++ "\n" ++ " .section __ex_table,\"a\"\n" ++ " .align 4\n" ++ " .long 2b,20b\n" ++ " .previous\n" ++ : "=&a" (res), "+d" (n), "=&d" (c) ++ : "0" (src), "r" (src)); ++ ++ return res; ++} ++EXPORT_SYMBOL(strnlen_user); ++ ++/* ++ * Zero Userspace ++ */ ++ ++unsigned long clear_user(void __user *to, unsigned long n) ++{ ++ unsigned long res; ++ ++ asm volatile ("\n" ++ " tst.l %0\n" ++ " jeq 3f\n" ++ "1: moves.l %2,(%1)+\n" ++ "2: subq.l #1,%0\n" ++ " jne 1b\n" ++ "3: btst #1,%4\n" ++ " jeq 5f\n" ++ "4: moves.w %2,(%1)+\n" ++ "5: btst #0,%4\n" ++ " jeq 7f\n" ++ "6: moves.b %2,(%1)\n" ++ "7:\n" ++ " .section .fixup,\"ax\"\n" ++ " .even\n" ++ "10: lsl.l #2,%0\n" ++ "40: add.l %4,%0\n" ++ " jra 7b\n" ++ " .previous\n" ++ "\n" ++ " .section __ex_table,\"a\"\n" ++ " .align 4\n" ++ " .long 1b,10b\n" ++ " .long 2b,10b\n" ++ " .long 4b,40b\n" ++ " .long 5b,40b\n" ++ " .long 6b,40b\n" ++ " .long 7b,40b\n" ++ " .previous" ++ : "=d" (res), "+a" (to) ++ : "r" (0), "0" (n / 4), "d" (n & 3)); ++ ++ return res; ++} ++EXPORT_SYMBOL(clear_user); +diff -urN linux-i386/arch/m68k/mac/baboon.c linux-m68k/arch/m68k/mac/baboon.c +--- linux-i386/arch/m68k/mac/baboon.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mac/baboon.c 2006-01-28 22:36:16.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 linux-i386/arch/m68k/mac/config.c linux-m68k/arch/m68k/mac/config.c +--- linux-i386/arch/m68k/mac/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mac/config.c 2006-05-26 11:53:40.000000000 +0200 +@@ -89,38 +89,11 @@ + + static void mac_get_model(char *str); + +-void mac_bang(int irq, void *vector, struct pt_regs *p) +-{ +- printk(KERN_INFO "Resetting ...\n"); +- mac_reset(); +-} +- + static void mac_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *)) + { + via_init_clock(vector); + } + +-#if 0 +-void mac_waitbut (void) +-{ +- ; +-} +-#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 +169,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 linux-i386/arch/m68k/mac/iop.c linux-m68k/arch/m68k/mac/iop.c +--- linux-i386/arch/m68k/mac/iop.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mac/iop.c 2006-04-10 00:21:46.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 linux-i386/arch/m68k/mac/macints.c linux-m68k/arch/m68k/mac/macints.c +--- linux-i386/arch/m68k/mac/macints.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mac/macints.c 2006-05-26 11:53:40.000000000 +0200 +@@ -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,34 +201,37 @@ + * 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 + */ + +-extern irqreturn_t mac_bang(int, void *, struct pt_regs *); + irqreturn_t mac_nmi_handler(int, void *, struct pt_regs *); + irqreturn_t mac_debug_handler(int, void *, struct pt_regs *); + + /* #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 +248,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 +265,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 +273,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 +430,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 +459,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 +503,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 linux-i386/arch/m68k/mac/oss.c linux-m68k/arch/m68k/mac/oss.c +--- linux-i386/arch/m68k/mac/oss.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mac/oss.c 2006-01-28 22:36:16.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 linux-i386/arch/m68k/mac/psc.c linux-m68k/arch/m68k/mac/psc.c +--- linux-i386/arch/m68k/mac/psc.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mac/psc.c 2006-01-28 22:36:16.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 linux-i386/arch/m68k/mac/via.c linux-m68k/arch/m68k/mac/via.c +--- linux-i386/arch/m68k/mac/via.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mac/via.c 2006-05-26 11:53:40.000000000 +0200 +@@ -25,7 +25,6 @@ + #include + #include + +-#include + #include + #include + #include +@@ -71,7 +70,6 @@ + void via_irq_disable(int irq); + void via_irq_clear(int irq); + +-extern irqreturn_t mac_bang(int, void *, struct pt_regs *); + extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *); + extern int oss_present; + +@@ -212,11 +210,6 @@ + break; + } + #else +- /* The alernate IRQ mapping seems to just not work. Anyone with a */ +- /* supported machine is welcome to take a stab at fixing it. It */ +- /* _should_ work on the following Quadras: 610,650,700,800,900,950 */ +- /* - 1999-06-12 (jmt) */ +- + via_alt_mapping = 0; + #endif + +@@ -260,27 +253,21 @@ + 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, +- "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 +424,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 +439,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,8 +458,8 @@ + 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); + via2[gIFR] = irq_bit | rbv_clear; ++ m68k_handle_int(VIA2_SOURCE_BASE + i, regs); + via2[gIER] = irq_bit | 0x80; + } + return IRQ_HANDLED; +@@ -494,7 +481,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); + } + } +@@ -529,6 +516,7 @@ + } + via2[gIER] = irq_bit | 0x80; + } else if (irq_src == 7) { ++ nubus_active |= irq_bit; + if (rbv_present) { + /* enable the slot interrupt. SIER works like IER. */ + via2[rSIER] = IER_SET_BIT(irq_idx); +@@ -550,7 +538,6 @@ + } + } + } +- nubus_active |= irq_bit; + } + } + +diff -urN linux-i386/arch/m68k/mm/kmap.c linux-m68k/arch/m68k/mm/kmap.c +--- linux-i386/arch/m68k/mm/kmap.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mm/kmap.c 2006-06-06 00:59:41.000000000 +0200 +@@ -259,13 +259,15 @@ + + if (CPU_IS_020_OR_030) { + int pmd_off = (virtaddr/PTRTREESIZE) & 15; ++ int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK; + +- if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) { ++ if (pmd_type == _PAGE_PRESENT) { + pmd_dir->pmd[pmd_off] = 0; + virtaddr += PTRTREESIZE; + size -= PTRTREESIZE; + continue; +- } ++ } else if (pmd_type == 0) ++ continue; + } + + if (pmd_bad(*pmd_dir)) { +diff -urN linux-i386/arch/m68k/mm/motorola.c linux-m68k/arch/m68k/mm/motorola.c +--- linux-i386/arch/m68k/mm/motorola.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mm/motorola.c 2006-06-18 19:06:45.000000000 +0200 +@@ -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 + { +@@ -223,6 +223,9 @@ + pgprot_val(protection_map[i]) |= _PAGE_CACHE040; + } + ++ module_fixup(NULL, __start_fixup, __stop_fixup); ++ flush_icache(); ++ + /* + * Map the physical memory available into the kernel virtual + * address space. It may allocate some memory for page +@@ -257,12 +260,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 linux-i386/arch/m68k/mm/sun3mmu.c linux-m68k/arch/m68k/mm/sun3mmu.c +--- linux-i386/arch/m68k/mm/sun3mmu.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mm/sun3mmu.c 2006-05-11 13:14:11.000000000 +0200 +@@ -46,10 +46,9 @@ + 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; + +- + #ifdef TEST_VERIFY_AREA + wp_works_ok = 0; + #endif +@@ -92,10 +91,13 @@ + 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; ++ ++ /* I really wish I knew why the following change made things better... -- Sam */ ++/* free_area_init(zones_size); */ ++ free_area_init_node(0, NODE_DATA(0), zones_size, ++ (__pa(PAGE_OFFSET) >> PAGE_SHIFT) + 1, NULL); + +- free_area_init(zones_size); + + } + +diff -urN linux-i386/arch/m68k/mvme147/Makefile linux-m68k/arch/m68k/mvme147/Makefile +--- linux-i386/arch/m68k/mvme147/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mvme147/Makefile 2006-01-28 22:36:38.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 linux-i386/arch/m68k/mvme147/config.c linux-m68k/arch/m68k/mvme147/config.c +--- linux-i386/arch/m68k/mvme147/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mvme147/config.c 2006-01-28 22:36:38.000000000 +0100 +@@ -36,15 +36,8 @@ + #include + + +-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 linux-i386/arch/m68k/mvme16x/Makefile linux-m68k/arch/m68k/mvme16x/Makefile +--- linux-i386/arch/m68k/mvme16x/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mvme16x/Makefile 2006-01-28 22:37:06.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 linux-i386/arch/m68k/mvme16x/config.c linux-m68k/arch/m68k/mvme16x/config.c +--- linux-i386/arch/m68k/mvme16x/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/mvme16x/config.c 2006-01-28 22:37:06.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 linux-i386/arch/m68k/q40/config.c linux-m68k/arch/m68k/q40/config.c +--- linux-i386/arch/m68k/q40/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/q40/config.c 2006-04-10 00:21:47.000000000 +0200 +@@ -37,15 +37,9 @@ + #include + + 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 linux-i386/arch/m68k/q40/q40ints.c linux-m68k/arch/m68k/q40/q40ints.c +--- linux-i386/arch/m68k/q40/q40ints.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/q40/q40ints.c 2006-01-28 22:37:37.000000000 +0100 +@@ -14,13 +14,8 @@ + #include + #include + #include +-#include +-#include +-#include + #include +-#include + +-#include + #include + #include + #include +@@ -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_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 (irqpc, 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 linux-i386/arch/m68k/sun3/config.c linux-m68k/arch/m68k/sun3/config.c +--- linux-i386/arch/m68k/sun3/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/sun3/config.c 2006-01-28 22:37:55.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 linux-i386/arch/m68k/sun3/sun3ints.c linux-m68k/arch/m68k/sun3/sun3ints.c +--- linux-i386/arch/m68k/sun3/sun3ints.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/sun3/sun3ints.c 2006-01-28 22:37:55.000000000 +0100 +@@ -19,7 +19,6 @@ + #include + + 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<= 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 linux-i386/arch/m68k/sun3x/config.c linux-m68k/arch/m68k/sun3x/config.c +--- linux-i386/arch/m68k/sun3x/config.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/arch/m68k/sun3x/config.c 2006-01-28 22:37:55.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 linux-i386/drivers/block/amiflop.c linux-m68k/drivers/block/amiflop.c +--- linux-i386/drivers/block/amiflop.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/block/amiflop.c 2006-06-18 19:08:07.000000000 +0200 +@@ -64,6 +64,7 @@ + #include + #include + #include ++#include + + #include + #include +diff -urN 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@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 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 ++ */ ++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 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 ++#include ++ ++#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 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@darkness.gun.de) and the data sheet of Phillip's clone device (SCN68681) ++ * (from Richard Hirst, srh@gpt.co.uk) ++ * ++ * 11.11.95 copyright Joerg Dorchain (dorchain@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 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, ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++/*#include */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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 " ++#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 linux-i386/drivers/char/serial167.c linux-m68k/drivers/char/serial167.c +--- linux-i386/drivers/char/serial167.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/char/serial167.c 2006-05-22 00:00:37.000000000 +0200 +@@ -63,6 +63,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -439,8 +440,9 @@ + overflowing, we still loose + the next incoming character. + */ +- tty_insert_flip_char(tty, data, TTY_NORMAL); +- } ++ if (tty_buffer_request_room(tty, 1) != 0){ ++ tty_insert_flip_char(tty, data, TTY_FRAME); ++ } + /* These two conditions may imply */ + /* a normal read should be done. */ + /* else if(data & CyTIMEOUT) */ +@@ -449,14 +451,14 @@ + tty_insert_flip_char(tty, 0, TTY_NORMAL); + } + }else{ +- tty_insert_flip_char(tty, data, TTY_NORMAL); ++ tty_insert_flip_char(tty, data, TTY_NORMAL); + } + }else{ + /* there was a software buffer overrun + and nothing could be done about it!!! */ + } + } +- schedule_delayed_work(&tty->flip.work, 1); ++ tty_schedule_flip(tty); + /* end of service */ + base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; + return IRQ_HANDLED; +@@ -647,6 +649,7 @@ + char data; + int char_count; + int save_cnt; ++ int len; + + /* determine the channel and change to that context */ + channel = (u_short ) (base_addr[CyLICR] >> 2); +@@ -679,14 +682,15 @@ + info->mon.char_max = char_count; + info->mon.char_last = char_count; + #endif +- while(char_count--){ ++ len = tty_buffer_request_room(tty, char_count); ++ while(len--){ + data = base_addr[CyRDR]; + tty_insert_flip_char(tty, data, TTY_NORMAL); + #ifdef CYCLOM_16Y_HACK + udelay(10L); + #endif + } +- schedule_delayed_work(&tty->flip.work, 1); ++ tty_schedule_flip(tty); + } + /* end of service */ + base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; +@@ -1434,7 +1438,6 @@ + volatile unsigned char *base_addr = (u_char *)BASE_ADDR; + unsigned long flags; + unsigned char status; +- unsigned int result; + + channel = info->line; + +@@ -1458,7 +1461,6 @@ + int channel; + volatile unsigned char *base_addr = (u_char *)BASE_ADDR; + unsigned long flags; +- unsigned int arg; + + channel = info->line; + +diff -urN linux-i386/drivers/ide/ide-iops.c linux-m68k/drivers/ide/ide-iops.c +--- linux-i386/drivers/ide/ide-iops.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/ide/ide-iops.c 2006-04-10 00:22:36.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 linux-i386/drivers/ide/ide.c linux-m68k/drivers/ide/ide.c +--- linux-i386/drivers/ide/ide.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/ide/ide.c 2006-06-18 19:08:21.000000000 +0200 +@@ -726,6 +726,7 @@ + { + int i; + ++ memset(hw, 0, sizeof(hw_regs_t)); + for (i = 0; i < IDE_NR_PORTS; i++) { + if (offsets[i] == -1) { + switch(i) { +diff -urN linux-i386/drivers/ide/legacy/q40ide.c linux-m68k/drivers/ide/legacy/q40ide.c +--- linux-i386/drivers/ide/legacy/q40ide.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/ide/legacy/q40ide.c 2006-05-12 01:52:07.000000000 +0200 +@@ -80,6 +80,7 @@ + { + int i; + ++ memset(hw, 0, sizeof(hw_regs_t)); + for (i = 0; i < IDE_NR_PORTS; i++) { + /* BIG FAT WARNING: + assumption: only DATA port is ever used in 16 bit mode */ +diff -urN linux-i386/drivers/input/keyboard/Kconfig linux-m68k/drivers/input/keyboard/Kconfig +--- linux-i386/drivers/input/keyboard/Kconfig 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/input/keyboard/Kconfig 2006-06-18 19:08:22.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 linux-i386/drivers/input/keyboard/amikbd.c linux-m68k/drivers/input/keyboard/amikbd.c +--- linux-i386/drivers/input/keyboard/amikbd.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/input/keyboard/amikbd.c 2006-01-28 22:27:33.000000000 +0100 +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -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 linux-i386/drivers/input/misc/Kconfig linux-m68k/drivers/input/misc/Kconfig +--- linux-i386/drivers/input/misc/Kconfig 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/input/misc/Kconfig 2006-04-10 00:22:39.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 linux-i386/drivers/input/mouse/Kconfig linux-m68k/drivers/input/mouse/Kconfig +--- linux-i386/drivers/input/mouse/Kconfig 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/input/mouse/Kconfig 2006-04-10 00:22:40.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 linux-i386/drivers/input/serio/Kconfig linux-m68k/drivers/input/serio/Kconfig +--- linux-i386/drivers/input/serio/Kconfig 2006-06-18 03:49:35.000000000 +0200 ++++ 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 linux-i386/drivers/macintosh/adb.c linux-m68k/drivers/macintosh/adb.c +--- linux-i386/drivers/macintosh/adb.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/macintosh/adb.c 2006-06-18 19:08:24.000000000 +0200 +@@ -480,13 +480,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 linux-i386/drivers/net/7990.c linux-m68k/drivers/net/7990.c +--- linux-i386/drivers/net/7990.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/net/7990.c 2006-06-18 19:08:38.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 linux-i386/drivers/net/Kconfig linux-m68k/drivers/net/Kconfig +--- linux-i386/drivers/net/Kconfig 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/net/Kconfig 2006-06-18 19:08:38.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 linux-i386/drivers/net/hplance.c linux-m68k/drivers/net/hplance.c +--- linux-i386/drivers/net/hplance.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/net/hplance.c 2006-06-18 19:08:39.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 linux-i386/drivers/net/mac89x0.c linux-m68k/drivers/net/mac89x0.c +--- linux-i386/drivers/net/mac89x0.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/net/mac89x0.c 2006-06-18 19:08:40.000000000 +0200 +@@ -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 linux-i386/drivers/net/sun3lance.c linux-m68k/drivers/net/sun3lance.c +--- linux-i386/drivers/net/sun3lance.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/net/sun3lance.c 2006-06-18 19:08:41.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 linux-i386/drivers/scsi/53c7xx.c linux-m68k/drivers/scsi/53c7xx.c +--- linux-i386/drivers/scsi/53c7xx.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/53c7xx.c 2006-04-10 00:23:01.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 linux-i386/drivers/scsi/53c7xx.h linux-m68k/drivers/scsi/53c7xx.h +--- linux-i386/drivers/scsi/53c7xx.h 2006-06-18 03:49:35.000000000 +0200 ++++ 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 linux-i386/drivers/scsi/Kconfig linux-m68k/drivers/scsi/Kconfig +--- linux-i386/drivers/scsi/Kconfig 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/Kconfig 2006-06-18 19:08:56.000000000 +0200 +@@ -1661,7 +1661,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: +@@ -1761,7 +1761,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 +@@ -1770,7 +1770,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 +@@ -1787,7 +1787,7 @@ + + config SUN3_SCSI + tristate "Sun3 NCR5380 SCSI" +- depends on SUN3 && SCSI && BROKEN ++ depends on SUN3 && SCSI + select SCSI_SPI_ATTRS + help + This option will enable support for the OBIO (onboard io) NCR5380 +diff -urN linux-i386/drivers/scsi/NCR5380.c linux-m68k/drivers/scsi/NCR5380.c +--- linux-i386/drivers/scsi/NCR5380.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/NCR5380.c 2006-04-10 00:23:01.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 linux-i386/drivers/scsi/amiga7xx.c linux-m68k/drivers/scsi/amiga7xx.c +--- linux-i386/drivers/scsi/amiga7xx.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/amiga7xx.c 2006-01-15 02:01:20.000000000 +0100 +@@ -26,8 +26,14 @@ + #include "scsi.h" + #include + #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 linux-i386/drivers/scsi/amiga7xx.h linux-m68k/drivers/scsi/amiga7xx.h +--- linux-i386/drivers/scsi/amiga7xx.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/amiga7xx.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,23 +0,0 @@ +-#ifndef AMIGA7XX_H +- +-#include +- +-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 +- +-#endif /* AMIGA7XX_H */ +diff -urN linux-i386/drivers/scsi/bvme6000.c linux-m68k/drivers/scsi/bvme6000.c +--- linux-i386/drivers/scsi/bvme6000.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/bvme6000.c 2006-01-15 02:01:21.000000000 +0100 +@@ -18,10 +18,16 @@ + #include "scsi.h" + #include + #include "53c7xx.h" +-#include "bvme6000.h" + + #include + ++#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 linux-i386/drivers/scsi/bvme6000.h linux-m68k/drivers/scsi/bvme6000.h +--- linux-i386/drivers/scsi/bvme6000.h 2006-06-18 03:49:35.000000000 +0200 ++++ 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 +- +-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 +- +-#endif /* BVME6000_SCSI_H */ +diff -urN linux-i386/drivers/scsi/mac_esp.c linux-m68k/drivers/scsi/mac_esp.c +--- linux-i386/drivers/scsi/mac_esp.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/mac_esp.c 2006-01-31 01:55:58.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 linux-i386/drivers/scsi/mac_scsi.c linux-m68k/drivers/scsi/mac_scsi.c +--- linux-i386/drivers/scsi/mac_scsi.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/mac_scsi.c 2006-01-31 01:55:58.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 linux-i386/drivers/scsi/mvme16x.c linux-m68k/drivers/scsi/mvme16x.c +--- linux-i386/drivers/scsi/mvme16x.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/mvme16x.c 2006-01-15 02:01:22.000000000 +0100 +@@ -16,10 +16,16 @@ + #include "scsi.h" + #include + #include "53c7xx.h" +-#include "mvme16x.h" + + #include + ++#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 linux-i386/drivers/scsi/mvme16x.h linux-m68k/drivers/scsi/mvme16x.h +--- linux-i386/drivers/scsi/mvme16x.h 2006-06-18 03:49:35.000000000 +0200 ++++ 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 +- +-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 +- +-#endif /* MVME16x_SCSI_H */ +diff -urN linux-i386/drivers/scsi/sun3_NCR5380.c linux-m68k/drivers/scsi/sun3_NCR5380.c +--- linux-i386/drivers/scsi/sun3_NCR5380.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/sun3_NCR5380.c 2006-05-11 13:16:27.000000000 +0200 +@@ -1269,7 +1269,7 @@ + NCR_PRINT(NDEBUG_INTR); + if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) { + done = 0; +- ENABLE_IRQ(); ++// ENABLE_IRQ(); + INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO); + NCR5380_reselect(instance); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); +@@ -1302,7 +1302,7 @@ + INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO); + NCR5380_dma_complete( instance ); + done = 0; +- ENABLE_IRQ(); ++// ENABLE_IRQ(); + } else + #endif /* REAL_DMA */ + { +diff -urN linux-i386/drivers/scsi/sun3_scsi.c linux-m68k/drivers/scsi/sun3_scsi.c +--- linux-i386/drivers/scsi/sun3_scsi.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/sun3_scsi.c 2006-05-11 13:16:27.000000000 +0200 +@@ -75,9 +75,9 @@ + #define REAL_DMA + + #include "scsi.h" ++#include "initio.h" + #include + #include "sun3_scsi.h" +-#include "NCR5380.h" + + static void NCR5380_print(struct Scsi_Host *instance); + +diff -urN linux-i386/drivers/scsi/sun3_scsi.h linux-m68k/drivers/scsi/sun3_scsi.h +--- linux-i386/drivers/scsi/sun3_scsi.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/sun3_scsi.h 2006-05-11 13:16:27.000000000 +0200 +@@ -220,7 +220,7 @@ + * + */ + +- ++#include "NCR5380.h" + + #if NDEBUG & NDEBUG_ARBITRATION + #define ARB_PRINTK(format, args...) \ +diff -urN linux-i386/drivers/scsi/sun3_scsi_vme.c linux-m68k/drivers/scsi/sun3_scsi_vme.c +--- linux-i386/drivers/scsi/sun3_scsi_vme.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/sun3_scsi_vme.c 2006-05-11 13:16:27.000000000 +0200 +@@ -41,9 +41,9 @@ + #define REAL_DMA + + #include "scsi.h" ++#include "initio.h" + #include + #include "sun3_scsi.h" +-#include "NCR5380.h" + + extern int sun3_map_test(unsigned long, char *); + +diff -urN linux-i386/drivers/scsi/sun3x_esp.c linux-m68k/drivers/scsi/sun3x_esp.c +--- linux-i386/drivers/scsi/sun3x_esp.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/sun3x_esp.c 2006-06-06 01:18:32.000000000 +0200 +@@ -332,11 +332,11 @@ + struct scatterlist *sg = sp->SCp.buffer; + + while (sz >= 0) { +- sg[sz].dvma_address = dvma_map((unsigned long)page_address(sg[sz].page) + ++ sg[sz].dma_address = dvma_map((unsigned long)page_address(sg[sz].page) + + sg[sz].offset, sg[sz].length); + sz--; + } +- sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address); ++ sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address); + } + + static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp) +@@ -350,14 +350,14 @@ + struct scatterlist *sg = (struct scatterlist *)sp->buffer; + + while(sz >= 0) { +- dvma_unmap((char *)sg[sz].dvma_address); ++ dvma_unmap((char *)sg[sz].dma_address); + sz--; + } + } + + static void dma_advance_sg (Scsi_Cmnd *sp) + { +- sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address); ++ sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dma_address); + } + + static int sun3x_esp_release(struct Scsi_Host *instance) +diff -urN linux-i386/drivers/scsi/wd33c93.c linux-m68k/drivers/scsi/wd33c93.c +--- linux-i386/drivers/scsi/wd33c93.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/scsi/wd33c93.c 2006-06-18 19:09:00.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 linux-i386/drivers/video/aty/atyfb_base.c linux-m68k/drivers/video/aty/atyfb_base.c +--- linux-i386/drivers/video/aty/atyfb_base.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/drivers/video/aty/atyfb_base.c 2006-06-18 19:09:36.000000000 +0200 +@@ -3722,7 +3722,9 @@ + atyfb_setup(option); + #endif + ++#ifdef CONFIG_PCI + pci_register_driver(&atyfb_driver); ++#endif + #ifdef CONFIG_ATARI + atyfb_atari_probe(); + #endif +@@ -3731,7 +3733,9 @@ + + static void __exit atyfb_exit(void) + { ++#ifdef CONFIG_PCI + pci_unregister_driver(&atyfb_driver); ++#endif + } + + module_init(atyfb_init); +diff -urN linux-i386/fs/fat/inode.c linux-m68k/fs/fat/inode.c +--- linux-i386/fs/fat/inode.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/fs/fat/inode.c 2006-06-18 19:09:42.000000000 +0200 +@@ -11,12 +11,14 @@ + */ + + #include ++#include + #include + #include + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -857,7 +859,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, +@@ -882,6 +884,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"}, +@@ -956,6 +961,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) +@@ -1004,6 +1016,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; +@@ -1339,8 +1357,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 linux-i386/include/asm-m68k/amigaints.h linux-m68k/include/asm-m68k/amigaints.h +--- linux-i386/include/asm-m68k/amigaints.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/amigaints.h 2006-01-28 22:32:49.000000000 +0100 +@@ -13,6 +13,8 @@ + #ifndef _ASMm68k_AMIGAINTS_H_ + #define _ASMm68k_AMIGAINTS_H_ + ++#include ++ + /* + ** 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 linux-i386/include/asm-m68k/apollohw.h linux-m68k/include/asm-m68k/apollohw.h +--- linux-i386/include/asm-m68k/apollohw.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/apollohw.h 2006-01-28 22:33:11.000000000 +0100 +@@ -3,6 +3,8 @@ + #ifndef _ASMm68k_APOLLOHW_H_ + #define _ASMm68k_APOLLOHW_H_ + ++#include ++ + /* + 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 linux-i386/include/asm-m68k/atari_stdma.h linux-m68k/include/asm-m68k/atari_stdma.h +--- linux-i386/include/asm-m68k/atari_stdma.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/atari_stdma.h 2006-05-09 20:47:28.000000000 +0200 +@@ -3,7 +3,7 @@ + #define _atari_stdma_h + + +-#include ++#include + + + /***************************** Prototypes *****************************/ +diff -urN linux-i386/include/asm-m68k/atariints.h linux-m68k/include/asm-m68k/atariints.h +--- linux-i386/include/asm-m68k/atariints.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/atariints.h 2006-01-28 22:30:07.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 linux-i386/include/asm-m68k/bvme6000hw.h linux-m68k/include/asm-m68k/bvme6000hw.h +--- linux-i386/include/asm-m68k/bvme6000hw.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/bvme6000hw.h 2006-01-28 22:33:48.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 linux-i386/include/asm-m68k/cacheflush.h linux-m68k/include/asm-m68k/cacheflush.h +--- linux-i386/include/asm-m68k/cacheflush.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/cacheflush.h 2006-06-06 01:01:40.000000000 +0200 +@@ -3,26 +3,30 @@ + + #include + ++/* cache code */ ++#define FLUSH_I_AND_D (0x00000808) ++#define FLUSH_I (0x00000008) ++ + /* + * Cache handling functions + */ + +-#define flush_icache() \ +-({ \ +- if (CPU_IS_040_OR_060) \ +- __asm__ __volatile__("nop\n\t" \ +- ".chip 68040\n\t" \ +- "cinva %%ic\n\t" \ +- ".chip 68k" : ); \ +- else { \ +- unsigned long _tmp; \ +- __asm__ __volatile__("movec %%cacr,%0\n\t" \ +- "orw %1,%0\n\t" \ +- "movec %0,%%cacr" \ +- : "=&d" (_tmp) \ +- : "id" (FLUSH_I)); \ +- } \ +-}) ++static inline void flush_icache(void) ++{ ++ if (CPU_IS_040_OR_060) ++ asm volatile ( "nop\n" ++ " .chip 68040\n" ++ " cpusha %bc\n" ++ " .chip 68k"); ++ else { ++ unsigned long tmp; ++ asm volatile ( "movec %%cacr,%0\n" ++ " or.w %1,%0\n" ++ " movec %0,%%cacr" ++ : "=&d" (tmp) ++ : "id" (FLUSH_I)); ++ } ++} + + /* + * invalidate the cache for the specified memory range. +@@ -43,10 +47,6 @@ + */ + extern void cache_push_v(unsigned long vaddr, int len); + +-/* cache code */ +-#define FLUSH_I_AND_D (0x00000808) +-#define FLUSH_I (0x00000008) +- + /* This is needed whenever the virtual mapping of the current + process changes. */ + #define __flush_cache_all() \ +diff -urN linux-i386/include/asm-m68k/dma-mapping.h linux-m68k/include/asm-m68k/dma-mapping.h +--- linux-i386/include/asm-m68k/dma-mapping.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/dma-mapping.h 2006-06-08 22:20:50.000000000 +0200 +@@ -1,12 +1,91 @@ + #ifndef _M68K_DMA_MAPPING_H + #define _M68K_DMA_MAPPING_H + +-#include ++#include + +-#ifdef CONFIG_PCI +-#include +-#else +-#include +-#endif ++struct scatterlist; ++ ++static inline int dma_supported(struct device *dev, u64 mask) ++{ ++ return 1; ++} ++ ++static inline int dma_set_mask(struct device *dev, u64 mask) ++{ ++ return 0; ++} ++ ++static inline int dma_get_cache_alignment(void) ++{ ++ return 1 << L1_CACHE_SHIFT; ++} ++ ++static inline int dma_is_consistent(dma_addr_t dma_addr) ++{ ++ return 0; ++} ++ ++extern void *dma_alloc_coherent(struct device *, size_t, ++ dma_addr_t *, int); ++extern void dma_free_coherent(struct device *, size_t, ++ void *, dma_addr_t); ++ ++static inline void *dma_alloc_noncoherent(struct device *dev, size_t size, ++ dma_addr_t *handle, int flag) ++{ ++ return dma_alloc_coherent(dev, size, handle, flag); ++} ++static inline void dma_free_noncoherent(struct device *dev, size_t size, ++ void *addr, dma_addr_t handle) ++{ ++ dma_free_coherent(dev, size, addr, handle); ++} ++static inline void dma_cache_sync(void *vaddr, size_t size, ++ enum dma_data_direction dir) ++{ ++ /* we use coherent allocation, so not much to do here. */ ++} ++ ++extern dma_addr_t dma_map_single(struct device *, void *, size_t, ++ enum dma_data_direction); ++static inline void dma_unmap_single(struct device *dev, dma_addr_t addr, ++ size_t size, enum dma_data_direction dir) ++{ ++} ++ ++extern dma_addr_t dma_map_page(struct device *, struct page *, ++ unsigned long, size_t size, ++ enum dma_data_direction); ++static inline void dma_unmap_page(struct device *dev, dma_addr_t address, ++ size_t size, enum dma_data_direction dir) ++{ ++} ++ ++extern int dma_map_sg(struct device *, struct scatterlist *, int, ++ enum dma_data_direction); ++static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, ++ int nhwentries, enum dma_data_direction dir) ++{ ++} ++ ++extern void dma_sync_single_for_device(struct device *, dma_addr_t, size_t, ++ enum dma_data_direction); ++extern void dma_sync_sg_for_device(struct device *, struct scatterlist *, int, ++ enum dma_data_direction); ++ ++static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, ++ size_t size, enum dma_data_direction dir) ++{ ++} ++ ++static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, ++ int nents, enum dma_data_direction dir) ++{ ++} ++ ++static inline int dma_mapping_error(dma_addr_t handle) ++{ ++ return 0; ++} + + #endif /* _M68K_DMA_MAPPING_H */ +diff -urN linux-i386/include/asm-m68k/io.h linux-m68k/include/asm-m68k/io.h +--- linux-i386/include/asm-m68k/io.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/io.h 2006-04-10 00:23:26.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 linux-i386/include/asm-m68k/irq.h linux-m68k/include/asm-m68k/irq.h +--- linux-i386/include/asm-m68k/irq.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/irq.h 2006-04-10 00:23:26.000000000 +0200 +@@ -2,13 +2,8 @@ + #define _M68K_IRQ_H_ + + #include +-#include +- +-/* +- * # of m68k interrupts +- */ +- +-#define SYS_IRQS 8 ++#include ++#include + + /* + * 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 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-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/mac_oss.h 2006-01-28 22:36:17.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 linux-i386/include/asm-m68k/machdep.h linux-m68k/include/asm-m68k/machdep.h +--- linux-i386/include/asm-m68k/machdep.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/machdep.h 2006-04-10 00:23:26.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 linux-i386/include/asm-m68k/macintosh.h linux-m68k/include/asm-m68k/macintosh.h +--- linux-i386/include/asm-m68k/macintosh.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/macintosh.h 2006-01-28 22:36:17.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 linux-i386/include/asm-m68k/macints.h linux-m68k/include/asm-m68k/macints.h +--- linux-i386/include/asm-m68k/macints.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/macints.h 2006-01-28 22:36:17.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 linux-i386/include/asm-m68k/module.h linux-m68k/include/asm-m68k/module.h +--- linux-i386/include/asm-m68k/module.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/module.h 2006-06-06 01:17:29.000000000 +0200 +@@ -1,7 +1,38 @@ + #ifndef _ASM_M68K_MODULE_H + #define _ASM_M68K_MODULE_H +-struct mod_arch_specific { }; ++ ++struct mod_arch_specific { ++ struct m68k_fixup_info *fixup_start, *fixup_end; ++}; ++ ++#define MODULE_ARCH_INIT { \ ++ .fixup_start = __start_fixup, \ ++ .fixup_end = __stop_fixup, \ ++} ++ + #define Elf_Shdr Elf32_Shdr + #define Elf_Sym Elf32_Sym + #define Elf_Ehdr Elf32_Ehdr ++ ++ ++enum m68k_fixup_type { ++ m68k_fixup_memoffset, ++}; ++ ++struct m68k_fixup_info { ++ enum m68k_fixup_type type; ++ void *addr; ++}; ++ ++#define m68k_fixup(type, addr) \ ++ " .section \".m68k_fixup\",\"aw\"\n" \ ++ " .long " #type "," #addr "\n" \ ++ " .previous\n" ++ ++extern struct m68k_fixup_info __start_fixup[], __stop_fixup[]; ++ ++struct module; ++extern void module_fixup(struct module *mod, struct m68k_fixup_info *start, ++ struct m68k_fixup_info *end); ++ + #endif /* _ASM_M68K_MODULE_H */ +diff -urN linux-i386/include/asm-m68k/mvme147hw.h linux-m68k/include/asm-m68k/mvme147hw.h +--- linux-i386/include/asm-m68k/mvme147hw.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/mvme147hw.h 2006-01-28 22:36:38.000000000 +0100 +@@ -1,6 +1,8 @@ + #ifndef _MVME147HW_H_ + #define _MVME147HW_H_ + ++#include ++ + 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 linux-i386/include/asm-m68k/mvme16xhw.h linux-m68k/include/asm-m68k/mvme16xhw.h +--- linux-i386/include/asm-m68k/mvme16xhw.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/mvme16xhw.h 2006-01-28 22:37:06.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 linux-i386/include/asm-m68k/page.h linux-m68k/include/asm-m68k/page.h +--- linux-i386/include/asm-m68k/page.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/page.h 2006-06-06 01:17:29.000000000 +0200 +@@ -28,6 +28,8 @@ + + #ifndef __ASSEMBLY__ + ++#include ++ + #define get_user_page(vaddr) __get_free_page(GFP_KERNEL) + #define free_user_page(page, addr) free_page(addr) + +@@ -115,14 +117,35 @@ + + #ifndef __ASSEMBLY__ + ++extern unsigned long m68k_memoffset; ++ + #ifndef CONFIG_SUN3 + + #define WANT_PAGE_VIRTUAL + #ifdef CONFIG_SINGLE_MEMORY_CHUNK +-extern unsigned long m68k_memoffset; + +-#define __pa(vaddr) ((unsigned long)(vaddr)+m68k_memoffset) +-#define __va(paddr) ((void *)((unsigned long)(paddr)-m68k_memoffset)) ++static inline unsigned long ___pa(void *vaddr) ++{ ++ unsigned long paddr; ++ asm ( ++ "1: addl #0,%0\n" ++ m68k_fixup(%c2, 1b+2) ++ : "=r" (paddr) ++ : "0" (vaddr), "i" (m68k_fixup_memoffset)); ++ return paddr; ++} ++#define __pa(vaddr) ___pa((void *)(vaddr)) ++static inline void *__va(unsigned long paddr) ++{ ++ void *vaddr; ++ asm ( ++ "1: subl #0,%0\n" ++ m68k_fixup(%c2, 1b+2) ++ : "=r" (vaddr) ++ : "0" (paddr), "i" (m68k_fixup_memoffset)); ++ return vaddr; ++} ++ + #else + #define __pa(vaddr) virt_to_phys((void *)(vaddr)) + #define __va(paddr) phys_to_virt((unsigned long)(paddr)) +diff -urN linux-i386/include/asm-m68k/processor.h linux-m68k/include/asm-m68k/processor.h +--- linux-i386/include/asm-m68k/processor.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/processor.h 2006-01-28 22:25:23.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 linux-i386/include/asm-m68k/scatterlist.h linux-m68k/include/asm-m68k/scatterlist.h +--- linux-i386/include/asm-m68k/scatterlist.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/scatterlist.h 2006-06-06 01:18:33.000000000 +0200 +@@ -2,18 +2,17 @@ + #define _M68K_SCATTERLIST_H + + struct scatterlist { +- /* These two are only valid if ADDRESS member of this +- * struct is NULL. +- */ + struct page *page; + unsigned int offset; +- + unsigned int length; + +- __u32 dvma_address; /* A place to hang host-specific addresses at. */ ++ __u32 dma_address; /* A place to hang host-specific addresses at. */ + }; + + /* This is bogus and should go away. */ + #define ISA_DMA_THRESHOLD (0x00ffffff) + ++#define sg_dma_address(sg) ((sg)->dma_address) ++#define sg_dma_len(sg) ((sg)->length) ++ + #endif /* !(_M68K_SCATTERLIST_H) */ +diff -urN linux-i386/include/asm-m68k/serial.h linux-m68k/include/asm-m68k/serial.h +--- linux-i386/include/asm-m68k/serial.h 2006-06-18 03:49:35.000000000 +0200 ++++ 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 linux-i386/include/asm-m68k/signal.h linux-m68k/include/asm-m68k/signal.h +--- linux-i386/include/asm-m68k/signal.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/signal.h 2006-06-06 00:57:58.000000000 +0200 +@@ -156,13 +156,17 @@ + + static inline void sigaddset(sigset_t *set, int _sig) + { +- __asm__("bfset %0{%1,#1}" : "=m" (*set) : "id" ((_sig - 1) ^ 31) ++ asm ("bfset %0{%1,#1}" ++ : "+od" (*set) ++ : "id" ((_sig - 1) ^ 31) + : "cc"); + } + + static inline void sigdelset(sigset_t *set, int _sig) + { +- __asm__("bfclr %0{%1,#1}" : "=m"(*set) : "id"((_sig - 1) ^ 31) ++ asm ("bfclr %0{%1,#1}" ++ : "+od" (*set) ++ : "id" ((_sig - 1) ^ 31) + : "cc"); + } + +@@ -175,8 +179,10 @@ + static inline int __gen_sigismember(sigset_t *set, int _sig) + { + int ret; +- __asm__("bfextu %1{%2,#1},%0" +- : "=d"(ret) : "m"(*set), "id"((_sig-1) ^ 31)); ++ asm ("bfextu %1{%2,#1},%0" ++ : "=d" (ret) ++ : "od" (*set), "id" ((_sig-1) ^ 31) ++ : "cc"); + return ret; + } + +@@ -187,7 +193,10 @@ + + static inline int sigfindinword(unsigned long word) + { +- __asm__("bfffo %1{#0,#0},%0" : "=d"(word) : "d"(word & -word) : "cc"); ++ asm ("bfffo %1{#0,#0},%0" ++ : "=d" (word) ++ : "d" (word & -word) ++ : "cc"); + return word ^ 31; + } + +diff -urN linux-i386/include/asm-m68k/sun3-head.h linux-m68k/include/asm-m68k/sun3-head.h +--- linux-i386/include/asm-m68k/sun3-head.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/sun3-head.h 2006-05-11 13:14:11.000000000 +0200 +@@ -4,7 +4,6 @@ + + #define KERNBASE 0xE000000 /* First address the kernel will eventually be */ + #define LOAD_ADDR 0x4000 /* prom jumps to us here unless this is elf /boot */ +-#define BI_START (KERNBASE + 0x3000) /* beginning of the bootinfo records */ + #define FC_CONTROL 3 + #define FC_SUPERD 5 + #define FC_CPU 7 +diff -urN linux-i386/include/asm-m68k/sun3ints.h linux-m68k/include/asm-m68k/sun3ints.h +--- linux-i386/include/asm-m68k/sun3ints.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/sun3ints.h 2006-05-11 13:14:11.000000000 +0200 +@@ -12,37 +12,26 @@ + #define SUN3INTS_H + + #include +-#include +-#include +-#include + #include +-#include +-#include + #include + #include ++#include ++#include + + #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 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-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/thread_info.h 2006-04-11 01:58:28.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 linux-i386/include/asm-m68k/traps.h linux-m68k/include/asm-m68k/traps.h +--- linux-i386/include/asm-m68k/traps.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/traps.h 2006-01-28 22:32:08.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 linux-i386/include/asm-m68k/uaccess.h linux-m68k/include/asm-m68k/uaccess.h +--- linux-i386/include/asm-m68k/uaccess.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/uaccess.h 2006-06-23 16:34:41.000000000 +0200 +@@ -4,8 +4,9 @@ + /* + * User space memory access functions + */ ++#include + #include +-#include ++#include + #include + + #define VERIFY_READ 0 +@@ -32,858 +33,335 @@ + unsigned long insn, fixup; + }; + ++extern int __put_user_bad(void); ++extern int __get_user_bad(void); ++ ++#define __put_user_asm(res, x, ptr, bwl, reg, err) \ ++asm volatile ("\n" \ ++ "1: moves."#bwl" %2,%1\n" \ ++ "2:\n" \ ++ " .section .fixup,\"ax\"\n" \ ++ " .even\n" \ ++ "10: moveq.l %3,%0\n" \ ++ " jra 2b\n" \ ++ " .previous\n" \ ++ "\n" \ ++ " .section __ex_table,\"a\"\n" \ ++ " .align 4\n" \ ++ " .long 1b,10b\n" \ ++ " .long 2b,10b\n" \ ++ " .previous" \ ++ : "+d" (res), "=m" (*(ptr)) \ ++ : #reg (x), "i" (err)) + + /* + * These are the main single-value transfer routines. They automatically + * use the right size if we just have the right pointer type. + */ + +-#define put_user(x, ptr) \ +-({ \ +- int __pu_err; \ +- typeof(*(ptr)) __pu_val = (x); \ +- __chk_user_ptr(ptr); \ +- switch (sizeof (*(ptr))) { \ +- case 1: \ +- __put_user_asm(__pu_err, __pu_val, ptr, b); \ +- break; \ +- case 2: \ +- __put_user_asm(__pu_err, __pu_val, ptr, w); \ +- break; \ +- case 4: \ +- __put_user_asm(__pu_err, __pu_val, ptr, l); \ +- break; \ +- case 8: \ +- __pu_err = __constant_copy_to_user(ptr, &__pu_val, 8); \ +- break; \ +- default: \ +- __pu_err = __put_user_bad(); \ +- break; \ +- } \ +- __pu_err; \ ++#define __put_user(x, ptr) \ ++({ \ ++ typeof(*(ptr)) __pu_val = (x); \ ++ int __pu_err = 0; \ ++ __chk_user_ptr(ptr); \ ++ switch (sizeof (*(ptr))) { \ ++ case 1: \ ++ __put_user_asm(__pu_err, __pu_val, ptr, b, d, -EFAULT); \ ++ break; \ ++ case 2: \ ++ __put_user_asm(__pu_err, __pu_val, ptr, w, d, -EFAULT); \ ++ break; \ ++ case 4: \ ++ __put_user_asm(__pu_err, __pu_val, ptr, l, r, -EFAULT); \ ++ break; \ ++ case 8: \ ++ { \ ++ const void *__pu_ptr = (ptr); \ ++ asm volatile ("\n" \ ++ "1: moves.l %2,(%1)+\n" \ ++ "2: moves.l %R2,(%1)\n" \ ++ "3:\n" \ ++ " .section .fixup,\"ax\"\n" \ ++ " .even\n" \ ++ "10: movel %3,%0\n" \ ++ " jra 3b\n" \ ++ " .previous\n" \ ++ "\n" \ ++ " .section __ex_table,\"a\"\n" \ ++ " .align 4\n" \ ++ " .long 1b,10b\n" \ ++ " .long 2b,10b\n" \ ++ " .long 3b,10b\n" \ ++ " .previous" \ ++ : "+d" (__pu_err), "+a" (__pu_ptr) \ ++ : "r" (__pu_val), "i" (-EFAULT) \ ++ : "memory"); \ ++ break; \ ++ } \ ++ default: \ ++ __pu_err = __put_user_bad(); \ ++ break; \ ++ } \ ++ __pu_err; \ + }) +-#define __put_user(x, ptr) put_user(x, ptr) ++#define put_user(x, ptr) __put_user(x, ptr) + +-extern int __put_user_bad(void); + +-/* +- * Tell gcc we read from memory instead of writing: this is because +- * we do not write to any memory gcc knows about, so there are no +- * aliasing issues. +- */ +-#define __put_user_asm(err,x,ptr,bwl) \ +-__asm__ __volatile__ \ +- ("21:moves" #bwl " %2,%1\n" \ +- "1:\n" \ +- ".section .fixup,\"ax\"\n" \ +- " .even\n" \ +- "2: movel %3,%0\n" \ +- " jra 1b\n" \ +- ".previous\n" \ +- ".section __ex_table,\"a\"\n" \ +- " .align 4\n" \ +- " .long 21b,2b\n" \ +- " .long 1b,2b\n" \ +- ".previous" \ +- : "=d"(err) \ +- : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0)) +- +-#define get_user(x, ptr) \ +-({ \ +- int __gu_err; \ +- typeof(*(ptr)) __gu_val; \ +- __chk_user_ptr(ptr); \ +- switch (sizeof(*(ptr))) { \ +- case 1: \ +- __get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \ +- break; \ +- case 2: \ +- __get_user_asm(__gu_err, __gu_val, ptr, w, "=r"); \ +- break; \ +- case 4: \ +- __get_user_asm(__gu_err, __gu_val, ptr, l, "=r"); \ +- break; \ +- case 8: \ +- __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8); \ +- break; \ +- default: \ +- __gu_val = (typeof(*(ptr)))0; \ +- __gu_err = __get_user_bad(); \ +- break; \ +- } \ +- (x) = __gu_val; \ +- __gu_err; \ ++#define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({ \ ++ type __gu_val; \ ++ asm volatile ("\n" \ ++ "1: moves."#bwl" %2,%1\n" \ ++ "2:\n" \ ++ " .section .fixup,\"ax\"\n" \ ++ " .even\n" \ ++ "10: move.l %3,%0\n" \ ++ " sub."#bwl" %1,%1\n" \ ++ " jra 2b\n" \ ++ " .previous\n" \ ++ "\n" \ ++ " .section __ex_table,\"a\"\n" \ ++ " .align 4\n" \ ++ " .long 1b,10b\n" \ ++ " .previous" \ ++ : "+d" (res), "=&" #reg (__gu_val) \ ++ : "m" (*(ptr)), "i" (err)); \ ++ (x) = (typeof(*(ptr)))(long)__gu_val; \ + }) +-#define __get_user(x, ptr) get_user(x, ptr) +- +-extern int __get_user_bad(void); + +-#define __get_user_asm(err,x,ptr,bwl,reg) \ +-__asm__ __volatile__ \ +- ("1: moves" #bwl " %2,%1\n" \ +- "2:\n" \ +- ".section .fixup,\"ax\"\n" \ +- " .even\n" \ +- "3: movel %3,%0\n" \ +- " sub" #bwl " %1,%1\n" \ +- " jra 2b\n" \ +- ".previous\n" \ +- ".section __ex_table,\"a\"\n" \ +- " .align 4\n" \ +- " .long 1b,3b\n" \ +- ".previous" \ +- : "=d"(err), reg(x) \ +- : "m"(*(ptr)), "i" (-EFAULT), "0"(0)) +- +-static inline unsigned long +-__generic_copy_from_user(void *to, const void __user *from, unsigned long n) +-{ +- unsigned long tmp; +- __asm__ __volatile__ +- (" tstl %2\n" +- " jeq 2f\n" +- "1: movesl (%1)+,%3\n" +- " movel %3,(%0)+\n" +- " subql #1,%2\n" +- " jne 1b\n" +- "2: movel %4,%2\n" +- " bclr #1,%2\n" +- " jeq 4f\n" +- "3: movesw (%1)+,%3\n" +- " movew %3,(%0)+\n" +- "4: bclr #0,%2\n" +- " jeq 6f\n" +- "5: movesb (%1)+,%3\n" +- " moveb %3,(%0)+\n" +- "6:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "7: movel %2,%%d0\n" +- "71:clrl (%0)+\n" +- " subql #1,%%d0\n" +- " jne 71b\n" +- " lsll #2,%2\n" +- " addl %4,%2\n" +- " btst #1,%4\n" +- " jne 81f\n" +- " btst #0,%4\n" +- " jne 91f\n" +- " jra 6b\n" +- "8: addql #2,%2\n" +- "81:clrw (%0)+\n" +- " btst #0,%4\n" +- " jne 91f\n" +- " jra 6b\n" +- "9: addql #1,%2\n" +- "91:clrb (%0)+\n" +- " jra 6b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,7b\n" +- " .long 3b,8b\n" +- " .long 5b,9b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp) +- : "d"(n & 3), "0"(to), "1"(from), "2"(n/4) +- : "d0", "memory"); +- return n; +-} ++#define __get_user(x, ptr) \ ++({ \ ++ int __gu_err = 0; \ ++ __chk_user_ptr(ptr); \ ++ switch (sizeof(*(ptr))) { \ ++ case 1: \ ++ __get_user_asm(__gu_err, x, ptr, u8, b, d, -EFAULT); \ ++ break; \ ++ case 2: \ ++ __get_user_asm(__gu_err, x, ptr, u16, w, d, -EFAULT); \ ++ break; \ ++ case 4: \ ++ __get_user_asm(__gu_err, x, ptr, u32, l, r, -EFAULT); \ ++ break; \ ++/* case 8: disabled because gcc-4.1 has a broken typeof \ ++ { \ ++ const void *__gu_ptr = (ptr); \ ++ u64 __gu_val; \ ++ asm volatile ("\n" \ ++ "1: moves.l (%2)+,%1\n" \ ++ "2: moves.l (%2),%R1\n" \ ++ "3:\n" \ ++ " .section .fixup,\"ax\"\n" \ ++ " .even\n" \ ++ "10: move.l %3,%0\n" \ ++ " sub.l %1,%1\n" \ ++ " sub.l %R1,%R1\n" \ ++ " jra 3b\n" \ ++ " .previous\n" \ ++ "\n" \ ++ " .section __ex_table,\"a\"\n" \ ++ " .align 4\n" \ ++ " .long 1b,10b\n" \ ++ " .long 2b,10b\n" \ ++ " .previous" \ ++ : "+d" (__gu_err), "=&r" (__gu_val), \ ++ "+a" (__gu_ptr) \ ++ : "i" (-EFAULT) \ ++ : "memory"); \ ++ (x) = (typeof(*(ptr)))__gu_val; \ ++ break; \ ++ } */ \ ++ default: \ ++ __gu_err = __get_user_bad(); \ ++ break; \ ++ } \ ++ __gu_err; \ ++}) ++#define get_user(x, ptr) __get_user(x, ptr) + +-static inline unsigned long +-__generic_copy_to_user(void __user *to, const void *from, unsigned long n) +-{ +- unsigned long tmp; +- __asm__ __volatile__ +- (" tstl %2\n" +- " jeq 3f\n" +- "1: movel (%1)+,%3\n" +- "22:movesl %3,(%0)+\n" +- "2: subql #1,%2\n" +- " jne 1b\n" +- "3: movel %4,%2\n" +- " bclr #1,%2\n" +- " jeq 4f\n" +- " movew (%1)+,%3\n" +- "24:movesw %3,(%0)+\n" +- "4: bclr #0,%2\n" +- " jeq 5f\n" +- " moveb (%1)+,%3\n" +- "25:movesb %3,(%0)+\n" +- "5:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "60:addql #1,%2\n" +- "6: lsll #2,%2\n" +- " addl %4,%2\n" +- " jra 5b\n" +- "7: addql #2,%2\n" +- " jra 5b\n" +- "8: addql #1,%2\n" +- " jra 5b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,60b\n" +- " .long 22b,6b\n" +- " .long 2b,6b\n" +- " .long 24b,7b\n" +- " .long 3b,60b\n" +- " .long 4b,7b\n" +- " .long 25b,8b\n" +- " .long 5b,8b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp) +- : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4) +- : "memory"); +- return n; +-} ++unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n); ++unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n); + +-#define __copy_from_user_big(to, from, n, fixup, copy) \ +- __asm__ __volatile__ \ +- ("10: movesl (%1)+,%%d0\n" \ +- " movel %%d0,(%0)+\n" \ +- " subql #1,%2\n" \ +- " jne 10b\n" \ +- ".section .fixup,\"ax\"\n" \ +- " .even\n" \ +- "11: movel %2,%%d0\n" \ +- "13: clrl (%0)+\n" \ +- " subql #1,%%d0\n" \ +- " jne 13b\n" \ +- " lsll #2,%2\n" \ +- fixup "\n" \ +- " jra 12f\n" \ +- ".previous\n" \ +- ".section __ex_table,\"a\"\n" \ +- " .align 4\n" \ +- " .long 10b,11b\n" \ +- ".previous\n" \ +- copy "\n" \ +- "12:" \ +- : "=a"(to), "=a"(from), "=d"(n) \ +- : "0"(to), "1"(from), "2"(n/4) \ +- : "d0", "memory") ++#define __constant_copy_from_user_asm(res, to, from, tmp, n, s1, s2, s3)\ ++ asm volatile ("\n" \ ++ "1: moves."#s1" (%2)+,%3\n" \ ++ " move."#s1" %3,(%1)+\n" \ ++ "2: moves."#s2" (%2)+,%3\n" \ ++ " move."#s2" %3,(%1)+\n" \ ++ " .ifnc \""#s3"\",\"\"\n" \ ++ "3: moves."#s3" (%2)+,%3\n" \ ++ " move."#s3" %3,(%1)+\n" \ ++ " .endif\n" \ ++ "4:\n" \ ++ " .section __ex_table,\"a\"\n" \ ++ " .align 4\n" \ ++ " .long 1b,10f\n" \ ++ " .long 2b,20f\n" \ ++ " .ifnc \""#s3"\",\"\"\n" \ ++ " .long 3b,30f\n" \ ++ " .endif\n" \ ++ " .previous\n" \ ++ "\n" \ ++ " .section .fixup,\"ax\"\n" \ ++ " .even\n" \ ++ "10: clr."#s1" (%1)+\n" \ ++ "20: clr."#s2" (%1)+\n" \ ++ " .ifnc \""#s3"\",\"\"\n" \ ++ "30: clr."#s3" (%1)+\n" \ ++ " .endif\n" \ ++ " moveq.l #"#n",%0\n" \ ++ " jra 4b\n" \ ++ " .previous\n" \ ++ : "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp) \ ++ : : "memory") + +-static inline unsigned long ++static __always_inline unsigned long + __constant_copy_from_user(void *to, const void __user *from, unsigned long n) + { +- switch (n) { +- case 0: +- break; +- case 1: +- __asm__ __volatile__ +- ("1: movesb (%1)+,%%d0\n" +- " moveb %%d0,(%0)+\n" +- "2:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "3: addql #1,%2\n" +- " clrb (%0)+\n" +- " jra 2b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,3b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 2: +- __asm__ __volatile__ +- ("1: movesw (%1)+,%%d0\n" +- " movew %%d0,(%0)+\n" +- "2:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "3: addql #2,%2\n" +- " clrw (%0)+\n" +- " jra 2b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,3b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 3: +- __asm__ __volatile__ +- ("1: movesw (%1)+,%%d0\n" +- " movew %%d0,(%0)+\n" +- "2: movesb (%1)+,%%d0\n" +- " moveb %%d0,(%0)+\n" +- "3:" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "4: addql #2,%2\n" +- " clrw (%0)+\n" +- "5: addql #1,%2\n" +- " clrb (%0)+\n" +- " jra 3b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,4b\n" +- " .long 2b,5b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 4: +- __asm__ __volatile__ +- ("1: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "2:" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "3: addql #4,%2\n" +- " clrl (%0)+\n" +- " jra 2b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,3b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 8: +- __asm__ __volatile__ +- ("1: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "2: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "3:" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "4: addql #4,%2\n" +- " clrl (%0)+\n" +- "5: addql #4,%2\n" +- " clrl (%0)+\n" +- " jra 3b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,4b\n" +- " .long 2b,5b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 12: +- __asm__ __volatile__ +- ("1: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "2: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "3: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "4:" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "5: addql #4,%2\n" +- " clrl (%0)+\n" +- "6: addql #4,%2\n" +- " clrl (%0)+\n" +- "7: addql #4,%2\n" +- " clrl (%0)+\n" +- " jra 4b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,5b\n" +- " .long 2b,6b\n" +- " .long 3b,7b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 16: +- __asm__ __volatile__ +- ("1: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "2: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "3: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "4: movesl (%1)+,%%d0\n" +- " movel %%d0,(%0)+\n" +- "5:" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "6: addql #4,%2\n" +- " clrl (%0)+\n" +- "7: addql #4,%2\n" +- " clrl (%0)+\n" +- "8: addql #4,%2\n" +- " clrl (%0)+\n" +- "9: addql #4,%2\n" +- " clrl (%0)+\n" +- " jra 5b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,6b\n" +- " .long 2b,7b\n" +- " .long 3b,8b\n" +- " .long 4b,9b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- default: +- switch (n & 3) { +- case 0: +- __copy_from_user_big(to, from, n, "", ""); +- break; ++ unsigned long res = 0, tmp; ++ ++ switch (n) { + case 1: +- __copy_from_user_big(to, from, n, +- /* fixup */ +- "1: addql #1,%2\n" +- " clrb (%0)+", +- /* copy */ +- "2: movesb (%1)+,%%d0\n" +- " moveb %%d0,(%0)+\n" +- ".section __ex_table,\"a\"\n" +- " .long 2b,1b\n" +- ".previous"); +- break; ++ __get_user_asm(res, *(u8 *)to, (u8 *)from, u8, b, d, 1); ++ break; + case 2: +- __copy_from_user_big(to, from, n, +- /* fixup */ +- "1: addql #2,%2\n" +- " clrw (%0)+", +- /* copy */ +- "2: movesw (%1)+,%%d0\n" +- " movew %%d0,(%0)+\n" +- ".section __ex_table,\"a\"\n" +- " .long 2b,1b\n" +- ".previous"); +- break; ++ __get_user_asm(res, *(u16 *)to, (u16 *)from, u16, w, d, 2); ++ break; + case 3: +- __copy_from_user_big(to, from, n, +- /* fixup */ +- "1: addql #2,%2\n" +- " clrw (%0)+\n" +- "2: addql #1,%2\n" +- " clrb (%0)+", +- /* copy */ +- "3: movesw (%1)+,%%d0\n" +- " movew %%d0,(%0)+\n" +- "4: movesb (%1)+,%%d0\n" +- " moveb %%d0,(%0)+\n" +- ".section __ex_table,\"a\"\n" +- " .long 3b,1b\n" +- " .long 4b,2b\n" +- ".previous"); +- break; ++ __constant_copy_from_user_asm(res, to, from, tmp, 3, w, b,); ++ break; ++ case 4: ++ __get_user_asm(res, *(u32 *)to, (u32 *)from, u32, l, r, 4); ++ break; ++ case 5: ++ __constant_copy_from_user_asm(res, to, from, tmp, 5, l, b,); ++ break; ++ case 6: ++ __constant_copy_from_user_asm(res, to, from, tmp, 6, l, w,); ++ break; ++ case 7: ++ __constant_copy_from_user_asm(res, to, from, tmp, 7, l, w, b); ++ break; ++ case 8: ++ __constant_copy_from_user_asm(res, to, from, tmp, 8, l, l,); ++ break; ++ case 9: ++ __constant_copy_from_user_asm(res, to, from, tmp, 9, l, l, b); ++ break; ++ case 10: ++ __constant_copy_from_user_asm(res, to, from, tmp, 10, l, l, w); ++ break; ++ case 12: ++ __constant_copy_from_user_asm(res, to, from, tmp, 12, l, l, l); ++ break; ++ default: ++ /* we limit the inlined version to 3 moves */ ++ return __generic_copy_from_user(to, from, n); + } +- break; +- } +- return n; +-} + +-#define __copy_to_user_big(to, from, n, fixup, copy) \ +- __asm__ __volatile__ \ +- ("10: movel (%1)+,%%d0\n" \ +- "31: movesl %%d0,(%0)+\n" \ +- "11: subql #1,%2\n" \ +- " jne 10b\n" \ +- "41:\n" \ +- ".section .fixup,\"ax\"\n" \ +- " .even\n" \ +- "22: addql #1,%2\n" \ +- "12: lsll #2,%2\n" \ +- fixup "\n" \ +- " jra 13f\n" \ +- ".previous\n" \ +- ".section __ex_table,\"a\"\n" \ +- " .align 4\n" \ +- " .long 10b,22b\n" \ +- " .long 31b,12b\n" \ +- " .long 11b,12b\n" \ +- " .long 41b,22b\n" \ +- ".previous\n" \ +- copy "\n" \ +- "13:" \ +- : "=a"(to), "=a"(from), "=d"(n) \ +- : "0"(to), "1"(from), "2"(n/4) \ +- : "d0", "memory") ++ return res; ++} + +-#define __copy_to_user_inatomic __copy_to_user +-#define __copy_from_user_inatomic __copy_from_user ++#define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3) \ ++ asm volatile ("\n" \ ++ " move."#s1" (%2)+,%3\n" \ ++ "11: moves."#s1" %3,(%1)+\n" \ ++ "12: move."#s2" (%2)+,%3\n" \ ++ "21: moves."#s2" %3,(%1)+\n" \ ++ "22:\n" \ ++ " .ifnc \""#s3"\",\"\"\n" \ ++ " move."#s3" (%2)+,%3\n" \ ++ "31: moves."#s3" %3,(%1)+\n" \ ++ "32:\n" \ ++ " .endif\n" \ ++ "4:\n" \ ++ "\n" \ ++ " .section __ex_table,\"a\"\n" \ ++ " .align 4\n" \ ++ " .long 11b,5f\n" \ ++ " .long 12b,5f\n" \ ++ " .long 21b,5f\n" \ ++ " .long 22b,5f\n" \ ++ " .ifnc \""#s3"\",\"\"\n" \ ++ " .long 31b,5f\n" \ ++ " .long 32b,5f\n" \ ++ " .endif\n" \ ++ " .previous\n" \ ++ "\n" \ ++ " .section .fixup,\"ax\"\n" \ ++ " .even\n" \ ++ "5: moveq.l #"#n",%0\n" \ ++ " jra 4b\n" \ ++ " .previous\n" \ ++ : "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp) \ ++ : : "memory") + +-static inline unsigned long ++static __always_inline unsigned long + __constant_copy_to_user(void __user *to, const void *from, unsigned long n) + { +- switch (n) { +- case 0: +- break; +- case 1: +- __asm__ __volatile__ +- (" moveb (%1)+,%%d0\n" +- "21:movesb %%d0,(%0)+\n" +- "1:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "2: addql #1,%2\n" +- " jra 1b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n " +- " .long 21b,2b\n" +- " .long 1b,2b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 2: +- __asm__ __volatile__ +- (" movew (%1)+,%%d0\n" +- "21:movesw %%d0,(%0)+\n" +- "1:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "2: addql #2,%2\n" +- " jra 1b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 21b,2b\n" +- " .long 1b,2b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 3: +- __asm__ __volatile__ +- (" movew (%1)+,%%d0\n" +- "21:movesw %%d0,(%0)+\n" +- "1: moveb (%1)+,%%d0\n" +- "22:movesb %%d0,(%0)+\n" +- "2:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "3: addql #2,%2\n" +- "4: addql #1,%2\n" +- " jra 2b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 21b,3b\n" +- " .long 1b,3b\n" +- " .long 22b,4b\n" +- " .long 2b,4b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 4: +- __asm__ __volatile__ +- (" movel (%1)+,%%d0\n" +- "21:movesl %%d0,(%0)+\n" +- "1:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "2: addql #4,%2\n" +- " jra 1b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 21b,2b\n" +- " .long 1b,2b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 8: +- __asm__ __volatile__ +- (" movel (%1)+,%%d0\n" +- "21:movesl %%d0,(%0)+\n" +- "1: movel (%1)+,%%d0\n" +- "22:movesl %%d0,(%0)+\n" +- "2:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "3: addql #4,%2\n" +- "4: addql #4,%2\n" +- " jra 2b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 21b,3b\n" +- " .long 1b,3b\n" +- " .long 22b,4b\n" +- " .long 2b,4b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 12: +- __asm__ __volatile__ +- (" movel (%1)+,%%d0\n" +- "21:movesl %%d0,(%0)+\n" +- "1: movel (%1)+,%%d0\n" +- "22:movesl %%d0,(%0)+\n" +- "2: movel (%1)+,%%d0\n" +- "23:movesl %%d0,(%0)+\n" +- "3:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "4: addql #4,%2\n" +- "5: addql #4,%2\n" +- "6: addql #4,%2\n" +- " jra 3b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 21b,4b\n" +- " .long 1b,4b\n" +- " .long 22b,5b\n" +- " .long 2b,5b\n" +- " .long 23b,6b\n" +- " .long 3b,6b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- case 16: +- __asm__ __volatile__ +- (" movel (%1)+,%%d0\n" +- "21:movesl %%d0,(%0)+\n" +- "1: movel (%1)+,%%d0\n" +- "22:movesl %%d0,(%0)+\n" +- "2: movel (%1)+,%%d0\n" +- "23:movesl %%d0,(%0)+\n" +- "3: movel (%1)+,%%d0\n" +- "24:movesl %%d0,(%0)+\n" +- "4:" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "5: addql #4,%2\n" +- "6: addql #4,%2\n" +- "7: addql #4,%2\n" +- "8: addql #4,%2\n" +- " jra 4b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 21b,5b\n" +- " .long 1b,5b\n" +- " .long 22b,6b\n" +- " .long 2b,6b\n" +- " .long 23b,7b\n" +- " .long 3b,7b\n" +- " .long 24b,8b\n" +- " .long 4b,8b\n" +- ".previous" +- : "=a"(to), "=a"(from), "=d"(n) +- : "0"(to), "1"(from), "2"(0) +- : "d0", "memory"); +- break; +- default: +- switch (n & 3) { +- case 0: +- __copy_to_user_big(to, from, n, "", ""); +- break; ++ unsigned long res = 0, tmp; ++ ++ switch (n) { + case 1: +- __copy_to_user_big(to, from, n, +- /* fixup */ +- "1: addql #1,%2", +- /* copy */ +- " moveb (%1)+,%%d0\n" +- "22:movesb %%d0,(%0)+\n" +- "2:" +- ".section __ex_table,\"a\"\n" +- " .long 22b,1b\n" +- " .long 2b,1b\n" +- ".previous"); +- break; ++ __put_user_asm(res, *(u8 *)from, (u8 *)to, b, d, 1); ++ break; + case 2: +- __copy_to_user_big(to, from, n, +- /* fixup */ +- "1: addql #2,%2", +- /* copy */ +- " movew (%1)+,%%d0\n" +- "22:movesw %%d0,(%0)+\n" +- "2:" +- ".section __ex_table,\"a\"\n" +- " .long 22b,1b\n" +- " .long 2b,1b\n" +- ".previous"); +- break; ++ __put_user_asm(res, *(u16 *)from, (u16 *)to, w, d, 2); ++ break; + case 3: +- __copy_to_user_big(to, from, n, +- /* fixup */ +- "1: addql #2,%2\n" +- "2: addql #1,%2", +- /* copy */ +- " movew (%1)+,%%d0\n" +- "23:movesw %%d0,(%0)+\n" +- "3: moveb (%1)+,%%d0\n" +- "24:movesb %%d0,(%0)+\n" +- "4:" +- ".section __ex_table,\"a\"\n" +- " .long 23b,1b\n" +- " .long 3b,1b\n" +- " .long 24b,2b\n" +- " .long 4b,2b\n" +- ".previous"); +- break; ++ __constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,); ++ break; ++ case 4: ++ __put_user_asm(res, *(u32 *)from, (u32 *)to, l, r, 4); ++ break; ++ case 5: ++ __constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,); ++ break; ++ case 6: ++ __constant_copy_to_user_asm(res, to, from, tmp, 6, l, w,); ++ break; ++ case 7: ++ __constant_copy_to_user_asm(res, to, from, tmp, 7, l, w, b); ++ break; ++ case 8: ++ __constant_copy_to_user_asm(res, to, from, tmp, 8, l, l,); ++ break; ++ case 9: ++ __constant_copy_to_user_asm(res, to, from, tmp, 9, l, l, b); ++ break; ++ case 10: ++ __constant_copy_to_user_asm(res, to, from, tmp, 10, l, l, w); ++ break; ++ case 12: ++ __constant_copy_to_user_asm(res, to, from, tmp, 12, l, l, l); ++ break; ++ default: ++ /* limit the inlined version to 3 moves */ ++ return __generic_copy_to_user(to, from, n); + } +- break; +- } +- return n; ++ ++ return res; + } + +-#define copy_from_user(to, from, n) \ ++#define __copy_from_user(to, from, n) \ + (__builtin_constant_p(n) ? \ + __constant_copy_from_user(to, from, n) : \ + __generic_copy_from_user(to, from, n)) + +-#define copy_to_user(to, from, n) \ ++#define __copy_to_user(to, from, n) \ + (__builtin_constant_p(n) ? \ + __constant_copy_to_user(to, from, n) : \ + __generic_copy_to_user(to, from, n)) + +-#define __copy_from_user(to, from, n) copy_from_user(to, from, n) +-#define __copy_to_user(to, from, n) copy_to_user(to, from, n) ++#define __copy_to_user_inatomic __copy_to_user ++#define __copy_from_user_inatomic __copy_from_user + +-/* +- * Copy a null terminated string from userspace. +- */ +- +-static inline long +-strncpy_from_user(char *dst, const char __user *src, long count) +-{ +- long res; +- if (count == 0) return count; +- __asm__ __volatile__ +- ("1: movesb (%2)+,%%d0\n" +- "12:moveb %%d0,(%1)+\n" +- " jeq 2f\n" +- " subql #1,%3\n" +- " jne 1b\n" +- "2: subl %3,%0\n" +- "3:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "4: movel %4,%0\n" +- " jra 3b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,4b\n" +- " .long 12b,4b\n" +- ".previous" +- : "=d"(res), "=a"(dst), "=a"(src), "=d"(count) +- : "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count) +- : "d0", "memory"); +- return res; +-} ++#define copy_from_user(to, from, n) __copy_from_user(to, from, n) ++#define copy_to_user(to, from, n) __copy_to_user(to, from, n) + +-/* +- * Return the size of a string (including the ending 0) +- * +- * Return 0 on exception, a value greater than N if too long +- */ +-static inline long strnlen_user(const char __user *src, long n) +-{ +- long res; +- +- res = -(unsigned long)src; +- __asm__ __volatile__ +- ("1:\n" +- " tstl %2\n" +- " jeq 3f\n" +- "2: movesb (%1)+,%%d0\n" +- "22:\n" +- " subql #1,%2\n" +- " tstb %%d0\n" +- " jne 1b\n" +- " jra 4f\n" +- "3:\n" +- " addql #1,%0\n" +- "4:\n" +- " addl %1,%0\n" +- "5:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "6: moveq %3,%0\n" +- " jra 5b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 2b,6b\n" +- " .long 22b,6b\n" +- ".previous" +- : "=d"(res), "=a"(src), "=d"(n) +- : "i"(0), "0"(res), "1"(src), "2"(n) +- : "d0"); +- return res; +-} ++long strncpy_from_user(char *dst, const char __user *src, long count); ++long strnlen_user(const char __user *src, long n); ++unsigned long clear_user(void __user *to, unsigned long n); + + #define strlen_user(str) strnlen_user(str, 32767) + +-/* +- * Zero Userspace +- */ +- +-static inline unsigned long +-clear_user(void __user *to, unsigned long n) +-{ +- __asm__ __volatile__ +- (" tstl %1\n" +- " jeq 3f\n" +- "1: movesl %3,(%0)+\n" +- "2: subql #1,%1\n" +- " jne 1b\n" +- "3: movel %2,%1\n" +- " bclr #1,%1\n" +- " jeq 4f\n" +- "24:movesw %3,(%0)+\n" +- "4: bclr #0,%1\n" +- " jeq 5f\n" +- "25:movesb %3,(%0)+\n" +- "5:\n" +- ".section .fixup,\"ax\"\n" +- " .even\n" +- "61:addql #1,%1\n" +- "6: lsll #2,%1\n" +- " addl %2,%1\n" +- " jra 5b\n" +- "7: addql #2,%1\n" +- " jra 5b\n" +- "8: addql #1,%1\n" +- " jra 5b\n" +- ".previous\n" +- ".section __ex_table,\"a\"\n" +- " .align 4\n" +- " .long 1b,61b\n" +- " .long 2b,6b\n" +- " .long 3b,61b\n" +- " .long 24b,7b\n" +- " .long 4b,7b\n" +- " .long 25b,8b\n" +- " .long 5b,8b\n" +- ".previous" +- : "=a"(to), "=d"(n) +- : "r"(n & 3), "r"(0), "0"(to), "1"(n/4)); +- return n; +-} +- + #endif /* _M68K_UACCESS_H */ +diff -urN linux-i386/include/asm-m68k/unistd.h linux-m68k/include/asm-m68k/unistd.h +--- linux-i386/include/asm-m68k/unistd.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/asm-m68k/unistd.h 2006-02-11 17:28:36.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 + */ +diff -urN linux-i386/include/linux/adb.h linux-m68k/include/linux/adb.h +--- linux-i386/include/linux/adb.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/linux/adb.h 2006-06-18 19:10:20.000000000 +0200 +@@ -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 linux-i386/include/linux/bootmem.h linux-m68k/include/linux/bootmem.h +--- linux-i386/include/linux/bootmem.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/linux/bootmem.h 2006-06-18 19:10:21.000000000 +0200 +@@ -61,11 +61,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 linux-i386/include/linux/file.h linux-m68k/include/linux/file.h +--- linux-i386/include/linux/file.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/linux/file.h 2006-06-18 19:10:21.000000000 +0200 +@@ -5,7 +5,6 @@ + #ifndef __LINUX_FILE_H + #define __LINUX_FILE_H + +-#include + #include + #include + #include +diff -urN linux-i386/include/linux/ide.h linux-m68k/include/linux/ide.h +--- linux-i386/include/linux/ide.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/linux/ide.h 2006-06-18 19:10:21.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 linux-i386/include/linux/init_task.h linux-m68k/include/linux/init_task.h +--- linux-i386/include/linux/init_task.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/linux/init_task.h 2006-06-18 19:10:21.000000000 +0200 +@@ -81,7 +81,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 linux-i386/include/linux/kernel_stat.h linux-m68k/include/linux/kernel_stat.h +--- linux-i386/include/linux/kernel_stat.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/linux/kernel_stat.h 2006-06-18 19:10:21.000000000 +0200 +@@ -2,12 +2,12 @@ + #define _LINUX_KERNEL_STAT_H + + #include +-#include + #include + #include + #include + #include + #include ++#include + + /* + * 'kernel_stat.h' contains the definitions needed for doing +diff -urN linux-i386/include/linux/module.h linux-m68k/include/linux/module.h +--- linux-i386/include/linux/module.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/linux/module.h 2006-06-18 19:10:21.000000000 +0200 +@@ -324,6 +324,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 linux-i386/include/linux/sched.h linux-m68k/include/linux/sched.h +--- linux-i386/include/linux/sched.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/linux/sched.h 2006-06-18 19:10:22.000000000 +0200 +@@ -695,7 +695,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; +@@ -1273,6 +1274,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 linux-i386/include/linux/thread_info.h linux-m68k/include/linux/thread_info.h +--- linux-i386/include/linux/thread_info.h 2006-06-18 03:49:35.000000000 +0200 ++++ 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 linux-i386/include/linux/zorro.h linux-m68k/include/linux/zorro.h +--- linux-i386/include/linux/zorro.h 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/include/linux/zorro.h 2006-06-18 19:10:25.000000000 +0200 +@@ -11,8 +11,6 @@ + #ifndef _LINUX_ZORRO_H + #define _LINUX_ZORRO_H + +-#ifndef __ASSEMBLY__ +- + #include + + +@@ -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__ +@@ -290,7 +249,6 @@ + #define Z2RAM_CHUNKSHIFT (16) + + +-#endif /* !__ASSEMBLY__ */ + #endif /* __KERNEL__ */ + + #endif /* _LINUX_ZORRO_H */ +diff -urN linux-i386/kernel/fork.c linux-m68k/kernel/fork.c +--- linux-i386/kernel/fork.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/kernel/fork.c 2006-06-18 19:10:30.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); +@@ -156,7 +156,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); + +@@ -164,14 +164,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 linux-i386/kernel/mutex-debug.c linux-m68k/kernel/mutex-debug.c +--- linux-i386/kernel/mutex-debug.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/kernel/mutex-debug.c 2006-05-09 20:50:42.000000000 +0200 +@@ -149,7 +149,7 @@ + continue; + lock = list_entry(curr, struct mutex, held_list); + t = lock->owner; +- if (filter && (t != filter->thread_info)) ++ if (filter && (t != task_thread_info(filter))) + continue; + count++; + cursor = curr->next; +@@ -312,7 +312,7 @@ + list_for_each_safe(curr, next, &debug_mutex_held_locks) { + lock = list_entry(curr, struct mutex, held_list); + t = lock->owner; +- if (t != task->thread_info) ++ if (t != task_thread_info(task)) + continue; + list_del_init(curr); + DEBUG_OFF(); +@@ -321,7 +321,7 @@ + printk("BUG: %s/%d, lock held at task exit time!\n", + task->comm, task->pid); + printk_lock(lock, 1); +- if (lock->owner != task->thread_info) ++ if (lock->owner != task_thread_info(task)) + printk("exiting task is not even the owner??\n"); + return; + } +diff -urN linux-i386/kernel/mutex.c linux-m68k/kernel/mutex.c +--- linux-i386/kernel/mutex.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/kernel/mutex.c 2006-05-09 20:50:42.000000000 +0200 +@@ -130,7 +130,7 @@ + + spin_lock_mutex(&lock->wait_lock); + +- debug_mutex_add_waiter(lock, &waiter, task->thread_info, ip); ++ debug_mutex_add_waiter(lock, &waiter, task_thread_info(task), ip); + + /* add waiting tasks to the end of the waitqueue (FIFO): */ + list_add_tail(&waiter.list, &lock->wait_list); +@@ -156,7 +156,7 @@ + */ + if (unlikely(state == TASK_INTERRUPTIBLE && + signal_pending(task))) { +- mutex_remove_waiter(lock, &waiter, task->thread_info); ++ mutex_remove_waiter(lock, &waiter, task_thread_info(task)); + spin_unlock_mutex(&lock->wait_lock); + + debug_mutex_free_waiter(&waiter); +@@ -171,8 +171,8 @@ + } + + /* got the lock - rejoice! */ +- mutex_remove_waiter(lock, &waiter, task->thread_info); +- debug_mutex_set_owner(lock, task->thread_info __IP__); ++ mutex_remove_waiter(lock, &waiter, task_thread_info(task)); ++ debug_mutex_set_owner(lock, task_thread_info(task) __IP__); + + /* set it to 0 if there are no waiters left: */ + if (likely(list_empty(&lock->wait_list))) +@@ -183,7 +183,7 @@ + debug_mutex_free_waiter(&waiter); + + DEBUG_WARN_ON(list_empty(&lock->held_list)); +- DEBUG_WARN_ON(lock->owner != task->thread_info); ++ DEBUG_WARN_ON(lock->owner != task_thread_info(task)); + + return 0; + } +diff -urN linux-i386/lib/kref.c linux-m68k/lib/kref.c +--- linux-i386/lib/kref.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/lib/kref.c 2006-06-18 19:10:31.000000000 +0200 +@@ -11,8 +11,8 @@ + * + */ + +-#include + #include ++#include + + /** + * kref_init - initialize object. +diff -urN linux-i386/mm/bootmem.c linux-m68k/mm/bootmem.c +--- linux-i386/mm/bootmem.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/mm/bootmem.c 2006-06-18 19:10:31.000000000 +0200 +@@ -305,7 +305,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 */ +@@ -318,26 +317,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 linux-i386/scripts/mod/modpost.c linux-m68k/scripts/mod/modpost.c +--- linux-i386/scripts/mod/modpost.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-m68k/scripts/mod/modpost.c 2006-06-18 19:10:38.000000000 +0200 +@@ -1012,6 +1012,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"); + } + diff --git a/debian/patches/m68k-as.patch b/debian/patches/m68k-as.patch new file mode 100644 index 000000000..f228e6d30 --- /dev/null +++ b/debian/patches/m68k-as.patch @@ -0,0 +1,308 @@ +From: Al Viro +Date: 1134413482 -0500 + +recent as(1) doesn't think that . terminates a macro name, so +getuser.l is _not_ treated as invoking getuser with .l as the +first argument. + +Signed-off-by: Al Viro + +--- + + arch/m68k/math-emu/fp_cond.S | 2 +- + arch/m68k/math-emu/fp_decode.h | 4 ++-- + arch/m68k/math-emu/fp_move.S | 14 +++++++------- + arch/m68k/math-emu/fp_movem.S | 16 ++++++++-------- + arch/m68k/math-emu/fp_scan.S | 22 +++++++++++----------- + arch/m68k/math-emu/fp_util.S | 16 ++++++++-------- + 6 files changed, 37 insertions(+), 37 deletions(-) + +3c4ab44571b5a46917ad28620995c326e386a909 +diff --git a/arch/m68k/math-emu/fp_cond.S b/arch/m68k/math-emu/fp_cond.S +index ddae8b1..1cddeb0 100644 +--- a/arch/m68k/math-emu/fp_cond.S ++++ b/arch/m68k/math-emu/fp_cond.S +@@ -163,7 +163,7 @@ fp_absolute_long: + + fp_do_scc: + swap %d1 +- putuser.b %d1,(%a0),fp_err_ua1,%a0 ++ putuser .b,%d1,(%a0),fp_err_ua1,%a0 + printf PDECODE,"\n" + jra fp_end + +diff --git a/arch/m68k/math-emu/fp_decode.h b/arch/m68k/math-emu/fp_decode.h +index 759679d..a2595d9 100644 +--- a/arch/m68k/math-emu/fp_decode.h ++++ b/arch/m68k/math-emu/fp_decode.h +@@ -311,7 +311,7 @@ debug move.l "(%sp)+,%d1" + btst #2,%d2 + jne 1f + printf PDECODE,")@(" +- getuser.l (%a1),%a1,fp_err_ua1,%a1 ++ getuser .l,(%a1),%a1,fp_err_ua1,%a1 + debug jra "2f" + 1: printf PDECODE,"," + 2: +@@ -322,7 +322,7 @@ debug jra "2f" + btst #2,%d2 + jeq 1f + printf PDECODE,")@(" +- getuser.l (%a1),%a1,fp_err_ua1,%a1 ++ getuser .l,(%a1),%a1,fp_err_ua1,%a1 + debug jra "2f" + 1: printf PDECODE,"," + 2: +diff --git a/arch/m68k/math-emu/fp_move.S b/arch/m68k/math-emu/fp_move.S +index 71bdf83..9bd0334 100644 +--- a/arch/m68k/math-emu/fp_move.S ++++ b/arch/m68k/math-emu/fp_move.S +@@ -200,12 +200,12 @@ fp_putdest: + + fp_format_long: + jsr fp_conv_ext2long +- putuser.l %d0,(%a1),fp_err_ua1,%a1 ++ putuser .l,%d0,(%a1),fp_err_ua1,%a1 + jra fp_finish_move + + fp_format_single: + jsr fp_conv_ext2single +- putuser.l %d0,(%a1),fp_err_ua1,%a1 ++ putuser .l,%d0,(%a1),fp_err_ua1,%a1 + jra fp_finish_move + + fp_format_extended: +@@ -213,11 +213,11 @@ fp_format_extended: + lsl.w #1,%d0 + lsl.l #7,%d0 + lsl.l #8,%d0 +- putuser.l %d0,(%a1)+,fp_err_ua1,%a1 ++ putuser .l,%d0,(%a1)+,fp_err_ua1,%a1 + move.l (%a0)+,%d0 +- putuser.l %d0,(%a1)+,fp_err_ua1,%a1 ++ putuser .l,%d0,(%a1)+,fp_err_ua1,%a1 + move.l (%a0),%d0 +- putuser.l %d0,(%a1),fp_err_ua1,%a1 ++ putuser .l,%d0,(%a1),fp_err_ua1,%a1 + jra fp_finish_move + + fp_format_packed: +@@ -227,7 +227,7 @@ fp_format_packed: + + fp_format_word: + jsr fp_conv_ext2short +- putuser.w %d0,(%a1),fp_err_ua1,%a1 ++ putuser .w,%d0,(%a1),fp_err_ua1,%a1 + jra fp_finish_move + + fp_format_double: +@@ -236,7 +236,7 @@ fp_format_double: + + fp_format_byte: + jsr fp_conv_ext2byte +- putuser.b %d0,(%a1),fp_err_ua1,%a1 ++ putuser .b,%d0,(%a1),fp_err_ua1,%a1 + | jra fp_finish_move + + fp_finish_move: +diff --git a/arch/m68k/math-emu/fp_movem.S b/arch/m68k/math-emu/fp_movem.S +index 8354d39..9c74134 100644 +--- a/arch/m68k/math-emu/fp_movem.S ++++ b/arch/m68k/math-emu/fp_movem.S +@@ -141,14 +141,14 @@ fpr_do_movem: + | move register from memory into fpu + jra 3f + 1: printf PMOVEM,"(%p>%p)",2,%a0,%a1 +- getuser.l (%a0)+,%d2,fp_err_ua1,%a0 ++ getuser .l,(%a0)+,%d2,fp_err_ua1,%a0 + lsr.l #8,%d2 + lsr.l #7,%d2 + lsr.w #1,%d2 + move.l %d2,(%a1)+ +- getuser.l (%a0)+,%d2,fp_err_ua1,%a0 ++ getuser .l,(%a0)+,%d2,fp_err_ua1,%a0 + move.l %d2,(%a1)+ +- getuser.l (%a0),%d2,fp_err_ua1,%a0 ++ getuser .l,(%a0),%d2,fp_err_ua1,%a0 + move.l %d2,(%a1) + subq.l #8,%a0 + subq.l #8,%a1 +@@ -164,11 +164,11 @@ fpr_do_movem: + lsl.w #1,%d2 + lsl.l #7,%d2 + lsl.l #8,%d2 +- putuser.l %d2,(%a0)+,fp_err_ua1,%a0 ++ putuser .l,%d2,(%a0)+,fp_err_ua1,%a0 + move.l (%a1)+,%d2 +- putuser.l %d2,(%a0)+,fp_err_ua1,%a0 ++ putuser .l,%d2,(%a0)+,fp_err_ua1,%a0 + move.l (%a1),%d2 +- putuser.l %d2,(%a0),fp_err_ua1,%a0 ++ putuser .l,%d2,(%a0),fp_err_ua1,%a0 + subq.l #8,%a1 + subq.l #8,%a0 + add.l %d0,%a0 +@@ -325,7 +325,7 @@ fpc_do_movem: + | move register from memory into fpu + jra 3f + 1: printf PMOVEM,"(%p>%p)",2,%a0,%a1 +- getuser.l (%a0)+,%d0,fp_err_ua1,%a0 ++ getuser .l,(%a0)+,%d0,fp_err_ua1,%a0 + move.l %d0,(%a1) + 2: addq.l #4,%a1 + 3: lsl.b #1,%d1 +@@ -336,7 +336,7 @@ fpc_do_movem: + | move register from fpu into memory + 1: printf PMOVEM,"(%p>%p)",2,%a1,%a0 + move.l (%a1),%d0 +- putuser.l %d0,(%a0)+,fp_err_ua1,%a0 ++ putuser .l,%d0,(%a0)+,fp_err_ua1,%a0 + 2: addq.l #4,%a1 + 4: lsl.b #1,%d1 + jcs 1b +diff --git a/arch/m68k/math-emu/fp_scan.S b/arch/m68k/math-emu/fp_scan.S +index e4146ed..5f49b93 100644 +--- a/arch/m68k/math-emu/fp_scan.S ++++ b/arch/m68k/math-emu/fp_scan.S +@@ -64,7 +64,7 @@ fp_scan: + | normal fpu instruction? (this excludes fsave/frestore) + fp_get_pc %a0 + printf PDECODE,"%08x: ",1,%a0 +- getuser.b (%a0),%d0,fp_err_ua1,%a0 ++ getuser .b,(%a0),%d0,fp_err_ua1,%a0 + #if 1 + cmp.b #0xf2,%d0 | cpid = 1 + #else +@@ -72,7 +72,7 @@ fp_scan: + #endif + jne fp_nonstd + | first two instruction words are kept in %d2 +- getuser.l (%a0)+,%d2,fp_err_ua1,%a0 ++ getuser .l,(%a0)+,%d2,fp_err_ua1,%a0 + fp_put_pc %a0 + fp_decode_cond: | separate conditional instr + fp_decode_cond_instr_type +@@ -230,7 +230,7 @@ fp_immediate: + movel %a0,%a1 + clr.l %d1 + jra 2f +-1: getuser.b (%a1)+,%d1,fp_err_ua1,%a1 ++1: getuser .b,(%a1)+,%d1,fp_err_ua1,%a1 + printf PDECODE,"%02x",1,%d1 + 2: dbra %d0,1b + movem.l (%sp)+,%d0/%d1 +@@ -252,24 +252,24 @@ fp_fetchsource: + .long fp_byte, fp_ill + + fp_long: +- getuser.l (%a1),%d0,fp_err_ua1,%a1 ++ getuser .l,(%a1),%d0,fp_err_ua1,%a1 + jsr fp_conv_long2ext + jra fp_getdest + + fp_single: +- getuser.l (%a1),%d0,fp_err_ua1,%a1 ++ getuser .l,(%a1),%d0,fp_err_ua1,%a1 + jsr fp_conv_single2ext + jra fp_getdest + + fp_ext: +- getuser.l (%a1)+,%d0,fp_err_ua1,%a1 ++ getuser .l,(%a1)+,%d0,fp_err_ua1,%a1 + lsr.l #8,%d0 + lsr.l #7,%d0 + lsr.w #1,%d0 + move.l %d0,(%a0)+ +- getuser.l (%a1)+,%d0,fp_err_ua1,%a1 ++ getuser .l,(%a1)+,%d0,fp_err_ua1,%a1 + move.l %d0,(%a0)+ +- getuser.l (%a1),%d0,fp_err_ua1,%a1 ++ getuser .l,(%a1),%d0,fp_err_ua1,%a1 + move.l %d0,(%a0) + subq.l #8,%a0 + jra fp_getdest +@@ -279,7 +279,7 @@ fp_pack: + jra fp_ill + + fp_word: +- getuser.w (%a1),%d0,fp_err_ua1,%a1 ++ getuser .w,(%a1),%d0,fp_err_ua1,%a1 + ext.l %d0 + jsr fp_conv_long2ext + jra fp_getdest +@@ -289,7 +289,7 @@ fp_double: + jra fp_getdest + + fp_byte: +- getuser.b (%a1),%d0,fp_err_ua1,%a1 ++ getuser .b,(%a1),%d0,fp_err_ua1,%a1 + extb.l %d0 + jsr fp_conv_long2ext + | jra fp_getdest +@@ -465,7 +465,7 @@ fp_fdsub: + + fp_nonstd: + fp_get_pc %a0 +- getuser.l (%a0),%d0,fp_err_ua1,%a0 ++ getuser .l,(%a0),%d0,fp_err_ua1,%a0 + printf ,"nonstd ((%08x)=%08x)\n",2,%a0,%d0 + moveq #-1,%d0 + rts +diff --git a/arch/m68k/math-emu/fp_util.S b/arch/m68k/math-emu/fp_util.S +index a9f7f01..f9f24d5 100644 +--- a/arch/m68k/math-emu/fp_util.S ++++ b/arch/m68k/math-emu/fp_util.S +@@ -160,11 +160,11 @@ fp_s2e_large: + + fp_conv_double2ext: + #ifdef FPU_EMU_DEBUG +- getuser.l %a1@(0),%d0,fp_err_ua2,%a1 +- getuser.l %a1@(4),%d1,fp_err_ua2,%a1 ++ getuser .l,%a1@(0),%d0,fp_err_ua2,%a1 ++ getuser .l,%a1@(4),%d1,fp_err_ua2,%a1 + printf PCONV,"d2e: %p%p -> %p(",3,%d0,%d1,%a0 + #endif +- getuser.l (%a1)+,%d0,fp_err_ua2,%a1 ++ getuser .l,(%a1)+,%d0,fp_err_ua2,%a1 + move.l %d0,%d1 + lsl.l #8,%d0 | shift high mantissa + lsl.l #3,%d0 +@@ -178,7 +178,7 @@ fp_conv_double2ext: + add.w #0x3fff-0x3ff,%d1 | re-bias the exponent. + 9: move.l %d1,(%a0)+ | fp_ext.sign, fp_ext.exp + move.l %d0,(%a0)+ +- getuser.l (%a1)+,%d0,fp_err_ua2,%a1 ++ getuser .l,(%a1)+,%d0,fp_err_ua2,%a1 + move.l %d0,%d1 + lsl.l #8,%d0 + lsl.l #3,%d0 +@@ -1287,17 +1287,17 @@ fp_conv_ext2double: + lsr.l #4,%d0 + lsr.l #8,%d0 + or.l %d2,%d0 +- putuser.l %d0,(%a1)+,fp_err_ua2,%a1 ++ putuser .l,%d0,(%a1)+,fp_err_ua2,%a1 + moveq #21,%d0 + lsl.l %d0,%d1 + move.l (%a0),%d0 + lsr.l #4,%d0 + lsr.l #7,%d0 + or.l %d1,%d0 +- putuser.l %d0,(%a1),fp_err_ua2,%a1 ++ putuser .l,%d0,(%a1),fp_err_ua2,%a1 + #ifdef FPU_EMU_DEBUG +- getuser.l %a1@(-4),%d0,fp_err_ua2,%a1 +- getuser.l %a1@(0),%d1,fp_err_ua2,%a1 ++ getuser .l,%a1@(-4),%d0,fp_err_ua2,%a1 ++ getuser .l,%a1@(0),%d1,fp_err_ua2,%a1 + printf PCONV,"%p(%08x%08x)\n",3,%a1,%d0,%d1 + #endif + rts +-- +0.99.9.GIT + +- +To unsubscribe from this list: send the line "unsubscribe linux-m68k" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/debian/patches/m68k-macro.patch b/debian/patches/m68k-macro.patch new file mode 100644 index 000000000..ba97b3bdd --- /dev/null +++ b/debian/patches/m68k-macro.patch @@ -0,0 +1,149 @@ +From: Al Viro +Date: 1134435322 -0500 + +cretinous thing doesn't believe that (%a0)+ is one macro argument and +splits it in two; worked around by quoting the argument... + +Signed-off-by: Al Viro + +--- + + arch/m68k/math-emu/fp_move.S | 4 ++-- + arch/m68k/math-emu/fp_movem.S | 12 ++++++------ + arch/m68k/math-emu/fp_scan.S | 6 +++--- + arch/m68k/math-emu/fp_util.S | 6 +++--- + 4 files changed, 14 insertions(+), 14 deletions(-) + +5ea87cc472a0aebf479e94ac287c50e1c070f741 +diff --git a/arch/m68k/math-emu/fp_move.S b/arch/m68k/math-emu/fp_move.S +index 9bd0334..19363b3 100644 +--- a/arch/m68k/math-emu/fp_move.S ++++ b/arch/m68k/math-emu/fp_move.S +@@ -213,9 +213,9 @@ fp_format_extended: + lsl.w #1,%d0 + lsl.l #7,%d0 + lsl.l #8,%d0 +- putuser .l,%d0,(%a1)+,fp_err_ua1,%a1 ++ putuser .l,%d0,"(%a1)+",fp_err_ua1,%a1 + move.l (%a0)+,%d0 +- putuser .l,%d0,(%a1)+,fp_err_ua1,%a1 ++ putuser .l,%d0,"(%a1)+",fp_err_ua1,%a1 + move.l (%a0),%d0 + putuser .l,%d0,(%a1),fp_err_ua1,%a1 + jra fp_finish_move +diff --git a/arch/m68k/math-emu/fp_movem.S b/arch/m68k/math-emu/fp_movem.S +index 9c74134..4173655 100644 +--- a/arch/m68k/math-emu/fp_movem.S ++++ b/arch/m68k/math-emu/fp_movem.S +@@ -141,12 +141,12 @@ fpr_do_movem: + | move register from memory into fpu + jra 3f + 1: printf PMOVEM,"(%p>%p)",2,%a0,%a1 +- getuser .l,(%a0)+,%d2,fp_err_ua1,%a0 ++ getuser .l,"(%a0)+",%d2,fp_err_ua1,%a0 + lsr.l #8,%d2 + lsr.l #7,%d2 + lsr.w #1,%d2 + move.l %d2,(%a1)+ +- getuser .l,(%a0)+,%d2,fp_err_ua1,%a0 ++ getuser .l,"(%a0)+",%d2,fp_err_ua1,%a0 + move.l %d2,(%a1)+ + getuser .l,(%a0),%d2,fp_err_ua1,%a0 + move.l %d2,(%a1) +@@ -164,9 +164,9 @@ fpr_do_movem: + lsl.w #1,%d2 + lsl.l #7,%d2 + lsl.l #8,%d2 +- putuser .l,%d2,(%a0)+,fp_err_ua1,%a0 ++ putuser .l,%d2,"(%a0)+",fp_err_ua1,%a0 + move.l (%a1)+,%d2 +- putuser .l,%d2,(%a0)+,fp_err_ua1,%a0 ++ putuser .l,%d2,"(%a0)+",fp_err_ua1,%a0 + move.l (%a1),%d2 + putuser .l,%d2,(%a0),fp_err_ua1,%a0 + subq.l #8,%a1 +@@ -325,7 +325,7 @@ fpc_do_movem: + | move register from memory into fpu + jra 3f + 1: printf PMOVEM,"(%p>%p)",2,%a0,%a1 +- getuser .l,(%a0)+,%d0,fp_err_ua1,%a0 ++ getuser .l,"(%a0)+",%d0,fp_err_ua1,%a0 + move.l %d0,(%a1) + 2: addq.l #4,%a1 + 3: lsl.b #1,%d1 +@@ -336,7 +336,7 @@ fpc_do_movem: + | move register from fpu into memory + 1: printf PMOVEM,"(%p>%p)",2,%a1,%a0 + move.l (%a1),%d0 +- putuser .l,%d0,(%a0)+,fp_err_ua1,%a0 ++ putuser .l,%d0,"(%a0)+",fp_err_ua1,%a0 + 2: addq.l #4,%a1 + 4: lsl.b #1,%d1 + jcs 1b +diff --git a/arch/m68k/math-emu/fp_scan.S b/arch/m68k/math-emu/fp_scan.S +index 5f49b93..6a71ed1 100644 +--- a/arch/m68k/math-emu/fp_scan.S ++++ b/arch/m68k/math-emu/fp_scan.S +@@ -72,7 +72,7 @@ fp_scan: + #endif + jne fp_nonstd + | first two instruction words are kept in %d2 +- getuser .l,(%a0)+,%d2,fp_err_ua1,%a0 ++ getuser .l,"(%a0)+",%d2,fp_err_ua1,%a0 + fp_put_pc %a0 + fp_decode_cond: | separate conditional instr + fp_decode_cond_instr_type +@@ -262,12 +262,12 @@ fp_single: + jra fp_getdest + + fp_ext: +- getuser .l,(%a1)+,%d0,fp_err_ua1,%a1 ++ getuser .l,"(%a1)+",%d0,fp_err_ua1,%a1 + lsr.l #8,%d0 + lsr.l #7,%d0 + lsr.w #1,%d0 + move.l %d0,(%a0)+ +- getuser .l,(%a1)+,%d0,fp_err_ua1,%a1 ++ getuser .l,"(%a1)+",%d0,fp_err_ua1,%a1 + move.l %d0,(%a0)+ + getuser .l,(%a1),%d0,fp_err_ua1,%a1 + move.l %d0,(%a0) +diff --git a/arch/m68k/math-emu/fp_util.S b/arch/m68k/math-emu/fp_util.S +index f9f24d5..170110a 100644 +--- a/arch/m68k/math-emu/fp_util.S ++++ b/arch/m68k/math-emu/fp_util.S +@@ -164,7 +164,7 @@ fp_conv_double2ext: + getuser .l,%a1@(4),%d1,fp_err_ua2,%a1 + printf PCONV,"d2e: %p%p -> %p(",3,%d0,%d1,%a0 + #endif +- getuser .l,(%a1)+,%d0,fp_err_ua2,%a1 ++ getuser .l,"(%a1)+",%d0,fp_err_ua2,%a1 + move.l %d0,%d1 + lsl.l #8,%d0 | shift high mantissa + lsl.l #3,%d0 +@@ -178,7 +178,7 @@ fp_conv_double2ext: + add.w #0x3fff-0x3ff,%d1 | re-bias the exponent. + 9: move.l %d1,(%a0)+ | fp_ext.sign, fp_ext.exp + move.l %d0,(%a0)+ +- getuser .l,(%a1)+,%d0,fp_err_ua2,%a1 ++ getuser .l,"(%a1)+",%d0,fp_err_ua2,%a1 + move.l %d0,%d1 + lsl.l #8,%d0 + lsl.l #3,%d0 +@@ -1287,7 +1287,7 @@ fp_conv_ext2double: + lsr.l #4,%d0 + lsr.l #8,%d0 + or.l %d2,%d0 +- putuser .l,%d0,(%a1)+,fp_err_ua2,%a1 ++ putuser .l,%d0,"(%a1)+",fp_err_ua2,%a1 + moveq #21,%d0 + lsl.l %d0,%d1 + move.l (%a0),%d0 +-- +0.99.9.GIT + +- +To unsubscribe from this list: send the line "unsubscribe linux-m68k" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/debian/patches/series/1-extra b/debian/patches/series/1-extra index c8a6ced3a..a4a8ef7f9 100644 --- a/debian/patches/series/1-extra +++ b/debian/patches/series/1-extra @@ -5,3 +5,6 @@ + hppa.patch hppa + vserver-version.patch *_vserver *_xen-vserver + vserver-vs2.0.2-rc24.patch *_vserver *_xen-vserver ++ m68k-2.6.17.patch m68k ++ m68k-as.patch m68k ++ m68k-macro.patch m68k