1/* 2 * Linux/m68k general interrupt handling code from arch/m68k/kernel/ints.c 3 * Needed to drive the m68k emulating IRQ hardware on the PowerUp boards. 4 */ 5 6#include <linux/types.h> 7#include <linux/sched.h> 8#include <linux/kernel_stat.h> 9#include <linux/errno.h> 10#include <linux/init.h> 11#include <linux/seq_file.h> 12 13#include <asm/setup.h> 14#include <asm/system.h> 15#include <asm/irq.h> 16#include <asm/traps.h> 17#include <asm/page.h> 18#include <asm/machdep.h> 19 20/* table for system interrupt handlers */ 21static irq_handler_t irq_list[SYS_IRQS]; 22 23static const char *default_names[SYS_IRQS] = { 24 "spurious int", "int1 handler", "int2 handler", "int3 handler", 25 "int4 handler", "int5 handler", "int6 handler", "int7 handler" 26}; 27 28/* The number of spurious interrupts */ 29volatile unsigned int num_spurious; 30 31#define NUM_IRQ_NODES 100 32static irq_node_t nodes[NUM_IRQ_NODES]; 33 34 35/* 36 * void init_IRQ(void) 37 * 38 * Parameters: None 39 * 40 * Returns: Nothing 41 * 42 * This function should be called during kernel startup to initialize 43 * the IRQ handling routines. 44 */ 45 46__init 47void m68k_init_IRQ(void) 48{ 49 int i; 50 51 for (i = 0; i < SYS_IRQS; i++) { 52 if (mach_default_handler) 53 irq_list[i].handler = (*mach_default_handler)[i]; 54 irq_list[i].flags = 0; 55 irq_list[i].dev_id = NULL; 56 irq_list[i].devname = default_names[i]; 57 } 58 59 for (i = 0; i < NUM_IRQ_NODES; i++) 60 nodes[i].handler = NULL; 61 62 mach_init_IRQ (); 63} 64 65irq_node_t *new_irq_node(void) 66{ 67 irq_node_t *node; 68 short i; 69 70 for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) 71 if (!node->handler) 72 return node; 73 74 printk ("new_irq_node: out of nodes\n"); 75 return NULL; 76} 77 78int sys_request_irq(unsigned int irq, 79 void (*handler)(int, void *, struct pt_regs *), 80 unsigned long flags, const char *devname, void *dev_id) 81{ 82 if (irq < IRQ1 || irq > IRQ7) { 83 printk("%s: Incorrect IRQ %d from %s\n", 84 __FUNCTION__, irq, devname); 85 return -ENXIO; 86 } 87 88 89 irq_list[irq].handler = handler; 90 irq_list[irq].flags = flags; 91 irq_list[irq].dev_id = dev_id; 92 irq_list[irq].devname = devname; 93 return 0; 94} 95 96void sys_free_irq(unsigned int irq, void *dev_id) 97{ 98 if (irq < IRQ1 || irq > IRQ7) { 99 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); 100 return; 101 } 102 103 if (irq_list[irq].dev_id != dev_id) 104 printk("%s: Removing probably wrong IRQ %d from %s\n", 105 __FUNCTION__, irq, irq_list[irq].devname); 106 107 irq_list[irq].handler = (*mach_default_handler)[irq]; 108 irq_list[irq].flags = 0; 109 irq_list[irq].dev_id = NULL; 110 irq_list[irq].devname = default_names[irq]; 111} 112 113asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) 114{ 115 if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) { 116 vec -= VEC_SPUR; 117 kstat_cpu(0).irqs[vec]++; 118 irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); 119 } else { 120 if (mach_process_int) 121 mach_process_int(vec, fp); 122 else 123 panic("Can't process interrupt vector %ld\n", vec); 124 return; 125 } 126} 127 128int m68k_get_irq_list(struct seq_file *p, void *v) 129{ 130 int i; 131 132 /* autovector interrupts */ 133 if (mach_default_handler) { 134 for (i = 0; i < SYS_IRQS; i++) { 135 seq_printf(p, "auto %2d: %10u ", i, 136 i ? kstat_cpu(0).irqs[i] : num_spurious); 137 seq_puts(p, " "); 138 seq_printf(p, "%s\n", irq_list[i].devname); 139 } 140 } 141 142 mach_get_irq_list(p, v); 143 return 0; 144} 145