1 /* $Id: irq.c,v 1.8 2003/07/04 08:27:52 starvik Exp $
3 * linux/arch/cris/kernel/irq.c
5 * Copyright (c) 2000,2001 Axis Communications AB
7 * Authors: Bjorn Wesen (bjornw@axis.com)
9 * This file contains the code used by various IRQ handling routines:
10 * asking for different IRQ's should be done through these routines
11 * instead of just grabbing them. Thus setups with different IRQ numbers
12 * shouldn't result in any weird surprises, and installing new handlers
15 * Notice Linux/CRIS: these routines do not care about SMP
20 * IRQ's are in fact implemented a bit like signal handlers for the kernel.
21 * Naturally it's not a 1:1 relation, but there are similarities.
24 #include <linux/config.h>
25 #include <linux/module.h>
26 #include <linux/ptrace.h>
28 #include <linux/kernel_stat.h>
29 #include <linux/signal.h>
30 #include <linux/sched.h>
31 #include <linux/ioport.h>
32 #include <linux/interrupt.h>
33 #include <linux/timex.h>
34 #include <linux/slab.h>
35 #include <linux/random.h>
36 #include <linux/init.h>
37 #include <linux/seq_file.h>
38 #include <linux/errno.h>
41 #include <asm/bitops.h>
43 /* Defined in arch specific irq.c */
44 extern void arch_setup_irq(int irq);
45 extern void arch_free_irq(int irq);
48 disable_irq(unsigned int irq_nr)
52 local_save_flags(flags);
55 local_irq_restore(flags);
59 enable_irq(unsigned int irq_nr)
62 local_save_flags(flags);
65 local_irq_restore(flags);
74 EXPORT_SYMBOL(probe_irq_on);
77 probe_irq_off(unsigned long x)
82 EXPORT_SYMBOL(probe_irq_off);
85 * Initial irq handlers.
88 static struct irqaction *irq_action[NR_IRQS];
90 int show_interrupts(struct seq_file *p, void *v)
92 int i = *(loff_t *) v;
93 struct irqaction * action;
97 local_irq_save(flags);
98 action = irq_action[i];
101 seq_printf(p, "%2d: %10u %c %s",
102 i, kstat_cpu(0).irqs[i],
103 (action->flags & SA_INTERRUPT) ? '+' : ' ',
105 for (action = action->next; action; action = action->next) {
106 seq_printf(p, ",%s %s",
107 (action->flags & SA_INTERRUPT) ? " +" : "",
112 local_irq_restore(flags);
117 /* called by the assembler IRQ entry functions defined in irq.h
118 * to dispatch the interrupts to registred handlers
119 * interrupts are disabled upon entry - depending on if the
120 * interrupt was registred with SA_INTERRUPT or not, interrupts
121 * are re-enabled or not.
124 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
126 struct irqaction *action;
130 cpu = smp_processor_id();
132 kstat_cpu(cpu).irqs[irq]++;
134 action = irq_action[irq];
136 if (!(action->flags & SA_INTERRUPT))
138 action = irq_action[irq];
141 do_random |= action->flags;
142 retval |= action->handler(irq, action->dev_id, regs);
143 action = action->next;
148 printk("irq event %d: bogus retval mask %x\n",
151 printk("irq %d: nobody cared\n", irq);
155 if (do_random & SA_SAMPLE_RANDOM)
156 add_interrupt_randomness(irq);
161 if (softirq_pending(cpu))
164 /* unmasking and bottom half handling is done magically for us. */
167 /* this function links in a handler into the chain of handlers for the
168 given irq, and if the irq has never been registred, the appropriate
169 handler is entered into the interrupt vector
172 int setup_irq(int irq, struct irqaction * new)
175 struct irqaction *old, **p;
178 p = irq_action + irq;
179 if ((old = *p) != NULL) {
180 /* Can't share interrupts unless both agree to */
181 if (!(old->flags & new->flags & SA_SHIRQ))
184 /* Can't share interrupts unless both are same type */
185 if ((old->flags ^ new->flags) & SA_INTERRUPT)
188 /* add new interrupt at end of irq queue */
196 if (new->flags & SA_SAMPLE_RANDOM)
197 rand_initialize_irq(irq);
199 local_save_flags(flags);
204 /* if the irq wasn't registred before, enter it into the vector table
205 and unmask it physically
211 local_irq_restore(flags);
215 /* this function is called by a driver to register an irq handler
217 SA_INTERRUPT -> it's a fast interrupt, handler called with irq disabled and
218 no signal checking etc is performed upon exit
219 SA_SHIRQ -> the interrupt can be shared between different handlers, the handler
220 is required to check if the irq was "aimed" at it explicitely
221 SA_RANDOM -> the interrupt will add to the random generators entropy
224 int request_irq(unsigned int irq,
225 irqreturn_t (*handler)(int, void *, struct pt_regs *),
226 unsigned long irqflags,
227 const char * devname,
231 struct irqaction * action;
233 /* interrupts 0 and 1 are hardware breakpoint and NMI and we can't support
234 these yet. interrupt 15 is the multiple irq, it's special. */
236 if(irq < 2 || irq == 15 || irq >= NR_IRQS)
242 /* allocate and fill in a handler structure and setup the irq */
244 action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
248 action->handler = handler;
249 action->flags = irqflags;
251 action->name = devname;
253 action->dev_id = dev_id;
255 retval = setup_irq(irq, action);
262 EXPORT_SYMBOL(request_irq);
264 void free_irq(unsigned int irq, void *dev_id)
266 struct irqaction * action, **p;
269 if (irq >= NR_IRQS) {
270 printk("Trying to free IRQ%d\n",irq);
273 for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
274 if (action->dev_id != dev_id)
277 /* Found it - now free it */
278 local_save_flags(flags);
281 if (!irq_action[irq]) {
285 local_irq_restore(flags);
289 printk("Trying to free free IRQ%d\n",irq);
292 EXPORT_SYMBOL(free_irq);
297 printk("weird irq\n");
301 #if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
302 /* Used by other archs to show/control IRQ steering during SMP */