1/* 2 * linux/arch/m68knommu/kernel/ints.c -- General interrupt handling code 3 * 4 * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com) 5 * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, 6 * Kenneth Albanowski <kjahds@kjahds.com>, 7 * Copyright (C) 2000 Lineo Inc. (www.lineo.com) 8 * 9 * Based on: 10 * 11 * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code 12 * 13 * This file is subject to the terms and conditions of the GNU General Public 14 * License. See the file COPYING in the main directory of this archive 15 * for more details. 16 */ 17 18#include <linux/module.h> 19#include <linux/types.h> 20#include <linux/init.h> 21#include <linux/sched.h> 22#include <linux/interrupt.h> 23#include <linux/kernel_stat.h> 24#include <linux/errno.h> 25#include <linux/seq_file.h> 26 27#include <asm/system.h> 28#include <asm/irq.h> 29#include <asm/irqnode.h> 30#include <asm/traps.h> 31#include <asm/page.h> 32#include <asm/machdep.h> 33 34/* 35 * This table stores the address info for each vector handler. 36 */ 37struct irq_entry irq_list[SYS_IRQS]; 38 39#define NUM_IRQ_NODES 16 40static irq_node_t nodes[NUM_IRQ_NODES]; 41 42/* The number of spurious interrupts */ 43volatile unsigned int num_spurious; 44 45unsigned int local_irq_count[NR_CPUS]; 46 47static irqreturn_t default_irq_handler(int irq, void *ptr) 48{ 49 printk(KERN_INFO "%s(%d): default irq handler vec=%d [0x%x]\n", 50 __FILE__, __LINE__, irq, irq); 51 return(IRQ_HANDLED); 52} 53 54/* 55 * void init_IRQ(void) 56 * 57 * Parameters: None 58 * 59 * Returns: Nothing 60 * 61 * This function should be called during kernel startup to initialize 62 * the IRQ handling routines. 63 */ 64 65void __init init_IRQ(void) 66{ 67 int i; 68 69 for (i = 0; i < SYS_IRQS; i++) { 70 if (mach_default_handler) 71 irq_list[i].handler = mach_default_handler; 72 else 73 irq_list[i].handler = default_irq_handler; 74 irq_list[i].flags = IRQ_FLG_STD; 75 irq_list[i].dev_id = NULL; 76 irq_list[i].devname = NULL; 77 } 78 79 for (i = 0; i < NUM_IRQ_NODES; i++) 80 nodes[i].handler = NULL; 81 82 if (mach_init_IRQ) 83 mach_init_IRQ(); 84} 85 86irq_node_t *new_irq_node(void) 87{ 88 irq_node_t *node; 89 short i; 90 91 for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) 92 if (!node->handler) 93 return node; 94 95 printk(KERN_INFO "new_irq_node: out of nodes\n"); 96 return NULL; 97} 98 99int request_irq( 100 unsigned int irq, 101 irq_handler_t handler, 102 unsigned long flags, 103 const char *devname, 104 void *dev_id) 105{ 106 if (irq < 0 || irq >= NR_IRQS) { 107 printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", __FUNCTION__, 108 irq, devname); 109 return -ENXIO; 110 } 111 112 if (!(irq_list[irq].flags & IRQ_FLG_STD)) { 113 if (irq_list[irq].flags & IRQ_FLG_LOCK) { 114 printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n", 115 __FUNCTION__, irq, irq_list[irq].devname); 116 return -EBUSY; 117 } 118 if (flags & IRQ_FLG_REPLACE) { 119 printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n", 120 __FUNCTION__, devname, irq, irq_list[irq].devname); 121 return -EBUSY; 122 } 123 } 124 125 if (flags & IRQ_FLG_FAST) { 126 extern asmlinkage void fasthandler(void); 127 extern void set_evector(int vecnum, void (*handler)(void)); 128 set_evector(irq, fasthandler); 129 } 130 131 irq_list[irq].handler = handler; 132 irq_list[irq].flags = flags; 133 irq_list[irq].dev_id = dev_id; 134 irq_list[irq].devname = devname; 135 return 0; 136} 137 138EXPORT_SYMBOL(request_irq); 139 140void free_irq(unsigned int irq, void *dev_id) 141{ 142 if (irq >= NR_IRQS) { 143 printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); 144 return; 145 } 146 147 if (irq_list[irq].dev_id != dev_id) 148 printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n", 149 __FUNCTION__, irq, irq_list[irq].devname); 150 151 if (irq_list[irq].flags & IRQ_FLG_FAST) { 152 extern asmlinkage void inthandler(void); 153 extern void set_evector(int vecnum, void (*handler)(void)); 154 set_evector(irq, inthandler); 155 } 156 157 if (mach_default_handler) 158 irq_list[irq].handler = mach_default_handler; 159 else 160 irq_list[irq].handler = default_irq_handler; 161 irq_list[irq].flags = IRQ_FLG_STD; 162 irq_list[irq].dev_id = NULL; 163 irq_list[irq].devname = NULL; 164} 165 166EXPORT_SYMBOL(free_irq); 167 168 169int sys_request_irq(unsigned int irq, irq_handler_t handler, 170 unsigned long flags, const char *devname, void *dev_id) 171{ 172 if (irq > IRQ7) { 173 printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", 174 __FUNCTION__, irq, devname); 175 return -ENXIO; 176 } 177 178 179 irq_list[irq].handler = handler; 180 irq_list[irq].flags = flags; 181 irq_list[irq].dev_id = dev_id; 182 irq_list[irq].devname = devname; 183 return 0; 184} 185 186void sys_free_irq(unsigned int irq, void *dev_id) 187{ 188 if (irq > IRQ7) { 189 printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); 190 return; 191 } 192 193 if (irq_list[irq].dev_id != dev_id) 194 printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n", 195 __FUNCTION__, irq, irq_list[irq].devname); 196 197 irq_list[irq].handler = mach_default_handler; 198 irq_list[irq].flags = 0; 199 irq_list[irq].dev_id = NULL; 200 irq_list[irq].devname = NULL; 201} 202 203/* 204 * Do we need these probe functions on the m68k? 205 * 206 * ... may be useful with ISA devices 207 */ 208unsigned long probe_irq_on (void) 209{ 210 return 0; 211} 212 213EXPORT_SYMBOL(probe_irq_on); 214 215int probe_irq_off (unsigned long irqs) 216{ 217 return 0; 218} 219 220EXPORT_SYMBOL(probe_irq_off); 221 222asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) 223{ 224 if (vec >= VEC_INT1 && vec <= VEC_INT7) { 225 vec -= VEC_SPUR; 226 kstat_cpu(0).irqs[vec]++; 227 irq_list[vec].handler(vec, irq_list[vec].dev_id); 228 } else { 229 if (mach_process_int) 230 mach_process_int(vec, fp); 231 else 232 panic("Can't process interrupt vector %ld\n", vec); 233 return; 234 } 235} 236 237 238int show_interrupts(struct seq_file *p, void *v) 239{ 240 int i = *(loff_t *) v; 241 242 if (i < NR_IRQS) { 243 if (! (irq_list[i].flags & IRQ_FLG_STD)) { 244 seq_printf(p, "%3d: %10u ", i, 245 (i ? kstat_cpu(0).irqs[i] : num_spurious)); 246 if (irq_list[i].flags & IRQ_FLG_LOCK) 247 seq_printf(p, "L "); 248 else 249 seq_printf(p, " "); 250 seq_printf(p, "%s\n", irq_list[i].devname); 251 } 252 } 253 254 if (i == NR_IRQS && mach_get_irq_list) 255 mach_get_irq_list(p, v); 256 return 0; 257} 258 259void init_irq_proc(void) 260{ 261 /* Insert /proc/irq driver here */ 262} 263