Import 2.3.9pre5
[davej-history.git] / arch / mips / kernel / irq.c
blobd4d6ff3009cc18ff7d4d1c23bf0a1930461f1e01
1 /* $Id: irq.c,v 1.15 1999/02/25 21:50:49 tsbogend Exp $
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
7 * Code to handle x86 style IRQs plus some generic interrupt stuff.
9 * Copyright (C) 1992 Linus Torvalds
10 * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
12 #include <linux/errno.h>
13 #include <linux/init.h>
14 #include <linux/kernel_stat.h>
15 #include <linux/module.h>
16 #include <linux/signal.h>
17 #include <linux/sched.h>
18 #include <linux/types.h>
19 #include <linux/interrupt.h>
20 #include <linux/ioport.h>
21 #include <linux/timex.h>
22 #include <linux/malloc.h>
23 #include <linux/random.h>
25 #include <asm/bitops.h>
26 #include <asm/bootinfo.h>
27 #include <asm/io.h>
28 #include <asm/irq.h>
29 #include <asm/mipsregs.h>
30 #include <asm/system.h>
31 #include <asm/sni.h>
34 * This contains the irq mask for both 8259A irq controllers, it's an
35 * int so we can deal with the third PIC in some systems like the RM300.
36 * (XXX This is broken for big endian.)
38 static unsigned int cached_irq_mask = 0xffff;
40 #define __byte(x,y) (((unsigned char *)&(y))[x])
41 #define __word(x,y) (((unsigned short *)&(y))[x])
42 #define __long(x,y) (((unsigned int *)&(y))[x])
44 #define cached_21 (__byte(0,cached_irq_mask))
45 #define cached_A1 (__byte(1,cached_irq_mask))
47 unsigned int local_bh_count[NR_CPUS];
48 unsigned int local_irq_count[NR_CPUS];
49 unsigned long spurious_count = 0;
52 * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
53 * PCI devices. Other onboard hardware needs specific routines.
55 static inline void mask_irq(unsigned int irq)
57 cached_irq_mask |= 1 << irq;
58 if (irq & 8) {
59 outb(cached_A1, 0xa1);
60 } else {
61 outb(cached_21, 0x21);
65 static inline void unmask_irq(unsigned int irq)
67 cached_irq_mask &= ~(1 << irq);
68 if (irq & 8) {
69 outb(cached_A1, 0xa1);
70 } else {
71 outb(cached_21, 0x21);
75 void disable_irq(unsigned int irq_nr)
77 unsigned long flags;
79 save_and_cli(flags);
80 mask_irq(irq_nr);
81 restore_flags(flags);
84 void enable_irq(unsigned int irq_nr)
86 unsigned long flags;
87 save_and_cli(flags);
88 unmask_irq(irq_nr);
89 restore_flags(flags);
92 static struct irqaction *irq_action[NR_IRQS] = {
93 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
94 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
95 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
96 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
97 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
98 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
99 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
100 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
103 int get_irq_list(char *buf)
105 int i, len = 0;
106 struct irqaction * action;
108 for (i = 0 ; i < 32 ; i++) {
109 action = irq_action[i];
110 if (!action)
111 continue;
112 len += sprintf(buf+len, "%2d: %8d %c %s",
113 i, kstat.irqs[0][i],
114 (action->flags & SA_INTERRUPT) ? '+' : ' ',
115 action->name);
116 for (action=action->next; action; action = action->next) {
117 len += sprintf(buf+len, ",%s %s",
118 (action->flags & SA_INTERRUPT) ? " +" : "",
119 action->name);
121 len += sprintf(buf+len, "\n");
123 return len;
126 atomic_t __mips_bh_counter;
128 static inline void i8259_mask_and_ack_irq(int irq)
130 cached_irq_mask |= 1 << irq;
132 if (irq & 8) {
133 inb(0xa1);
134 outb(cached_A1, 0xa1);
135 outb(0x62, 0x20); /* Specific EOI to cascade */
136 outb(0x20, 0xa0);
137 } else {
138 inb(0x21);
139 outb(cached_21, 0x21);
140 outb(0x20, 0x20);
144 asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs)
146 struct irqaction *action;
147 int do_random, cpu;
149 cpu = smp_processor_id();
150 hardirq_enter(cpu);
152 if (irq >= 16)
153 goto out;
155 i8259_mask_and_ack_irq(irq);
157 kstat.irqs[cpu][irq]++;
159 action = *(irq + irq_action);
160 if (!action)
161 goto out;
163 if (!(action->flags & SA_INTERRUPT))
164 __sti();
165 action = *(irq + irq_action);
166 do_random = 0;
167 do {
168 do_random |= action->flags;
169 action->handler(irq, action->dev_id, regs);
170 action = action->next;
171 } while (action);
172 if (do_random & SA_SAMPLE_RANDOM)
173 add_interrupt_randomness(irq);
174 __cli();
175 unmask_irq (irq);
177 out:
178 hardirq_exit(cpu);
182 * do_IRQ handles IRQ's that have been installed without the
183 * SA_INTERRUPT flag: it uses the full signal-handling return
184 * and runs with other interrupts enabled. All relatively slow
185 * IRQ's should use this format: notably the keyboard/timer
186 * routines.
188 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
190 struct irqaction *action;
191 int do_random, cpu;
193 cpu = smp_processor_id();
194 hardirq_enter(cpu);
195 kstat.irqs[cpu][irq]++;
197 action = *(irq + irq_action);
198 if (action) {
199 if (!(action->flags & SA_INTERRUPT))
200 __sti();
201 action = *(irq + irq_action);
202 do_random = 0;
203 do {
204 do_random |= action->flags;
205 action->handler(irq, action->dev_id, regs);
206 action = action->next;
207 } while (action);
208 if (do_random & SA_SAMPLE_RANDOM)
209 add_interrupt_randomness(irq);
210 __cli();
212 hardirq_exit(cpu);
214 /* unmasking and bottom half handling is done magically for us. */
217 int i8259_setup_irq(int irq, struct irqaction * new)
219 int shared = 0;
220 struct irqaction *old, **p;
221 unsigned long flags;
223 p = irq_action + irq;
224 if ((old = *p) != NULL) {
225 /* Can't share interrupts unless both agree to */
226 if (!(old->flags & new->flags & SA_SHIRQ))
227 return -EBUSY;
229 /* Can't share interrupts unless both are same type */
230 if ((old->flags ^ new->flags) & SA_INTERRUPT)
231 return -EBUSY;
233 /* add new interrupt at end of irq queue */
234 do {
235 p = &old->next;
236 old = *p;
237 } while (old);
238 shared = 1;
241 if (new->flags & SA_SAMPLE_RANDOM)
242 rand_initialize_irq(irq);
244 save_and_cli(flags);
245 *p = new;
247 if (!shared) {
248 unmask_irq(irq);
250 restore_flags(flags);
251 return 0;
255 * Request_interrupt and free_interrupt ``sort of'' handle interrupts of
256 * non i8259 devices. They will have to be replaced by architecture
257 * specific variants. For now we still use this as broken as it is because
258 * it used to work ...
260 int request_irq(unsigned int irq,
261 void (*handler)(int, void *, struct pt_regs *),
262 unsigned long irqflags, const char * devname, void *dev_id)
264 int retval;
265 struct irqaction * action;
267 if (irq >= 32)
268 return -EINVAL;
269 if (!handler)
270 return -EINVAL;
272 action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
273 if (!action)
274 return -ENOMEM;
276 action->handler = handler;
277 action->flags = irqflags;
278 action->mask = 0;
279 action->name = devname;
280 action->next = NULL;
281 action->dev_id = dev_id;
283 retval = i8259_setup_irq(irq, action);
285 if (retval)
286 kfree(action);
287 return retval;
290 void free_irq(unsigned int irq, void *dev_id)
292 struct irqaction * action, **p;
293 unsigned long flags;
295 if (irq > 31) {
296 printk("Trying to free IRQ%d\n",irq);
297 return;
299 for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
300 if (action->dev_id != dev_id)
301 continue;
303 /* Found it - now free it */
304 save_and_cli(flags);
305 *p = action->next;
306 if (!irq[irq_action])
307 mask_irq(irq);
308 restore_flags(flags);
309 kfree(action);
310 return;
312 printk("Trying to free free IRQ%d\n",irq);
315 unsigned long probe_irq_on (void)
317 unsigned int i, irqs = 0;
318 unsigned long delay;
320 /* first, enable any unassigned (E)ISA irqs */
321 for (i = 15; i > 0; i--) {
322 if (!irq_action[i]) {
323 enable_irq(i);
324 irqs |= (1 << i);
328 /* wait for spurious interrupts to mask themselves out again */
329 for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
330 /* about 100ms delay */;
332 /* now filter out any obviously spurious interrupts */
333 return irqs & ~cached_irq_mask;
336 int probe_irq_off (unsigned long irqs)
338 unsigned int i;
340 #ifdef DEBUG
341 printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
342 #endif
343 irqs &= cached_irq_mask;
344 if (!irqs)
345 return 0;
346 i = ffz(~irqs);
347 if (irqs != (irqs & (1 << i)))
348 i = -i;
349 return i;
352 int (*irq_cannonicalize)(int irq);
354 static int i8259_irq_cannonicalize(int irq)
356 return ((irq == 2) ? 9 : irq);
359 __initfunc(static void i8259_init(void))
361 /* Init master interrupt controller */
362 outb(0x11, 0x20); /* Start init sequence */
363 outb(0x00, 0x21); /* Vector base */
364 outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
365 outb(0x01, 0x21); /* Select 8086 mode */
366 outb(0xff, 0x21); /* Mask all */
368 /* Init slave interrupt controller */
369 outb(0x11, 0xa0); /* Start init sequence */
370 outb(0x08, 0xa1); /* Vector base */
371 outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */
372 outb(0x01, 0xa1); /* Select 8086 mode */
373 outb(0xff, 0xa1); /* Mask all */
375 outb(cached_A1, 0xa1);
376 outb(cached_21, 0x21);
379 __initfunc(void init_IRQ(void))
381 irq_cannonicalize = i8259_irq_cannonicalize;
382 /* i8259_init(); */
383 irq_setup();
386 EXPORT_SYMBOL(irq_cannonicalize);