X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fm68k%2Fkernel%2Fints.c;h=514d323ad5369beeba60be337126d8f854309767;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=b33e37fb7b0e4eb88a78bfdfb282be42c1c9e61c;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index b33e37fb7..514d323ad 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -25,6 +25,7 @@ * which must be served /Roman Zippel */ +#include #include #include #include @@ -38,40 +39,47 @@ #include #include #include -#include #ifdef CONFIG_Q40 #include #endif -extern u32 auto_irqhandler_fixup[]; -extern u32 user_irqhandler_fixup[]; -extern u16 user_irqvec_fixup[]; - /* 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, +static irq_handler_t irq_list[SYS_IRQS]; + +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" }; -static struct irq_controller user_irq_controller = { - .name = "user", - .lock = SPIN_LOCK_UNLOCKED, - .startup = m68k_irq_startup, - .shutdown = m68k_irq_shutdown, -}; +/* The number of spurious interrupts */ +volatile unsigned int num_spurious; #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) * @@ -87,76 +95,18 @@ void __init init_IRQ(void) { int 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 < 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]; } - for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; 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; + for (i = 0; i < NUM_IRQ_NODES; i++) + nodes[i].handler = NULL; - for (i = 0; i < cnt; i++) - irq_controller[irq + i] = contr; + mach_init_IRQ (); } irq_node_t *new_irq_node(void) @@ -164,183 +114,84 @@ irq_node_t *new_irq_node(void) irq_node_t *node; short i; - for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { - if (!node->handler) { - memset(node, 0, sizeof(*node)); + for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) + if (!node->handler) return node; - } - } printk ("new_irq_node: out of nodes\n"); return NULL; } -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 & IRQF_SHARED)) { - 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; -} - +/* + * 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 request_irq(unsigned int irq, irqreturn_t (*handler) (int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *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; + return mach_request_irq(irq, handler, flags, devname, dev_id); } EXPORT_SYMBOL(request_irq); void free_irq(unsigned int irq, void *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); + mach_free_irq(irq, dev_id); } EXPORT_SYMBOL(free_irq); -void enable_irq(unsigned int 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) { - 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 < IRQ1 || irq > IRQ7) { + printk("%s: Incorrect IRQ %d from %s\n", + __FUNCTION__, irq, devname); + return -ENXIO; } - spin_lock_irqsave(&contr->lock, flags); - if (irq_depth[irq]) { - if (!--irq_depth[irq]) { - if (contr->enable) - contr->enable(irq); +#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; } - } else - WARN_ON(1); - spin_unlock_irqrestore(&contr->lock, flags); -} + 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; + } + } +#endif -EXPORT_SYMBOL(enable_irq); + irq_list[irq].handler = handler; + irq_list[irq].flags = flags; + irq_list[irq].dev_id = dev_id; + irq_list[irq].devname = devname; + return 0; +} -void disable_irq(unsigned int irq) +void cpu_free_irq(unsigned int irq, void *dev_id) { - struct irq_controller *contr; - unsigned long flags; - - if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { - printk("%s: Incorrect IRQ %d\n", - __FUNCTION__, irq); + if (irq < IRQ1 || irq > IRQ7) { + printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); return; } - spin_lock_irqsave(&contr->lock, flags); - if (!irq_depth[irq]++) { - if (contr->disable) - contr->disable(irq); - } - spin_unlock_irqrestore(&contr->lock, flags); -} + if (irq_list[irq].dev_id != dev_id) + printk("%s: Removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, irq_list[irq].devname); -EXPORT_SYMBOL(disable_irq); - -int m68k_irq_startup(unsigned int irq) -{ - if (irq <= IRQ_AUTO_7) - vectors[VEC_SPUR + irq] = auto_inthandler; - else - vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler; - return 0; + 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]; } -void m68k_irq_shutdown(unsigned int irq) -{ - if (irq <= IRQ_AUTO_7) - 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? * @@ -368,50 +219,58 @@ int probe_irq_off (unsigned long irqs) EXPORT_SYMBOL(probe_irq_off); -unsigned int irq_canonicalize(unsigned int irq) +static void dummy_enable_irq(unsigned int irq) { -#ifdef CONFIG_Q40 - if (MACH_IS_Q40 && irq == 11) - irq = 10; -#endif - return irq; + printk("calling uninitialized enable_irq()\n"); } -EXPORT_SYMBOL(irq_canonicalize); +static void dummy_disable_irq(unsigned int irq) +{ + printk("calling uninitialized disable_irq()\n"); +} -asmlinkage void m68k_handle_int(unsigned int irq, struct pt_regs *regs) +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) { - struct irq_node *node; - - kstat_cpu(0).irqs[irq]++; - node = irq_list[irq]; - do { - node->handler(irq, node->dev_id, regs); - node = node->next; - } while (node); + printk("calling uninitialized request_irq()\n"); + return 0; } -asmlinkage void handle_badint(struct pt_regs *regs) +static void dummy_free_irq(unsigned int irq, void *dev_id) { - kstat_cpu(0).irqs[0]++; - printk("unexpected interrupt from %u\n", regs->vector); + printk("calling uninitialized disable_irq()\n"); +} + +asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) +{ + 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; + } } 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 (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"); - } + 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); return 0; }