|
|
1.1 root 1: /*
2: * linux/arch/i386/kernel/irq.c
3: *
4: * Copyright (C) 1992 Linus Torvalds
5: *
6: * This file contains the code used by various IRQ handling routines:
7: * asking for different IRQ's should be done through these routines
8: * instead of just grabbing them. Thus setups with different IRQ numbers
9: * shouldn't result in any weird surprises, and installing new handlers
10: * should be easier.
11: */
12:
13: /*
14: * IRQ's are in fact implemented a bit like signal handlers for the kernel.
15: * Naturally it's not a 1:1 relation, but there are similarities.
16: */
17:
18: #include <linux/ptrace.h>
19: #include <linux/errno.h>
20: #include <linux/kernel_stat.h>
21: #include <linux/signal.h>
22: #include <linux/sched.h>
23: #include <linux/ioport.h>
24: #include <linux/interrupt.h>
25: #include <linux/timex.h>
26: #include <linux/malloc.h>
27: #include <linux/random.h>
28:
29: #include <asm/system.h>
30: #include <asm/io.h>
31: #include <asm/irq.h>
32: #include <asm/bitops.h>
33: #include <asm/smp.h>
34:
35: #define CR0_NE 32
36:
37: static unsigned char cache_21 = 0xff;
38: static unsigned char cache_A1 = 0xff;
39:
40: #ifdef __SMP_PROF__
41: static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
42: #endif
43:
44: static inline void mask_irq(unsigned int irq_nr)
45: {
46: unsigned char mask;
47:
48: mask = 1 << (irq_nr & 7);
49: if (irq_nr < 8) {
50: cache_21 |= mask;
51: outb(cache_21,0x21);
52: } else {
53: cache_A1 |= mask;
54: outb(cache_A1,0xA1);
55: }
56: }
57:
58: static inline void unmask_irq(unsigned int irq_nr)
59: {
60: unsigned char mask;
61:
62: mask = ~(1 << (irq_nr & 7));
63: if (irq_nr < 8) {
64: cache_21 &= mask;
65: outb(cache_21,0x21);
66: } else {
67: cache_A1 &= mask;
68: outb(cache_A1,0xA1);
69: }
70: }
71:
72: void disable_irq(unsigned int irq_nr)
73: {
74: unsigned long flags;
75:
76: save_flags(flags);
77: cli();
78: mask_irq(irq_nr);
79: restore_flags(flags);
80: }
81:
82: void enable_irq(unsigned int irq_nr)
83: {
84: unsigned long flags;
85: save_flags(flags);
86: cli();
87: unmask_irq(irq_nr);
88: restore_flags(flags);
89: }
90:
91: /*
92: * This builds up the IRQ handler stubs using some ugly macros in irq.h
93: *
94: * These macros create the low-level assembly IRQ routines that do all
95: * the operations that are needed to keep the AT interrupt-controller
96: * happy. They are also written to be fast - and to disable interrupts
97: * as little as humanly possible.
98: *
99: * NOTE! These macros expand to three different handlers for each line: one
100: * complete handler that does all the fancy stuff (including signal handling),
101: * and one fast handler that is meant for simple IRQ's that want to be
102: * atomic. The specific handler is chosen depending on the SA_INTERRUPT
103: * flag when installing a handler. Finally, one "bad interrupt" handler, that
104: * is used when no handler is present.
105: *
106: * The timer interrupt is handled specially to insure that the jiffies
107: * variable is updated at all times. Specifically, the timer interrupt is
108: * just like the complete handlers except that it is invoked with interrupts
109: * disabled and should never re-enable them. If other interrupts were
110: * allowed to be processed while the timer interrupt is active, then the
111: * other interrupts would have to avoid using the jiffies variable for delay
112: * and interval timing operations to avoid hanging the system.
113: */
114: BUILD_TIMER_IRQ(FIRST,0,0x01)
115: BUILD_IRQ(FIRST,1,0x02)
116: BUILD_IRQ(FIRST,2,0x04)
117: BUILD_IRQ(FIRST,3,0x08)
118: BUILD_IRQ(FIRST,4,0x10)
119: BUILD_IRQ(FIRST,5,0x20)
120: BUILD_IRQ(FIRST,6,0x40)
121: BUILD_IRQ(FIRST,7,0x80)
122: BUILD_IRQ(SECOND,8,0x01)
123: BUILD_IRQ(SECOND,9,0x02)
124: BUILD_IRQ(SECOND,10,0x04)
125: BUILD_IRQ(SECOND,11,0x08)
126: BUILD_IRQ(SECOND,12,0x10)
127: #ifdef __SMP__
128: BUILD_MSGIRQ(SECOND,13,0x20)
129: #else
130: BUILD_IRQ(SECOND,13,0x20)
131: #endif
132: BUILD_IRQ(SECOND,14,0x40)
133: BUILD_IRQ(SECOND,15,0x80)
134: #ifdef __SMP__
135: BUILD_RESCHEDIRQ(16)
136: #endif
137:
138: /*
139: * Pointers to the low-level handlers: first the general ones, then the
140: * fast ones, then the bad ones.
141: */
142: static void (*interrupt[17])(void) = {
143: IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt,
144: IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
145: IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
146: IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt
147: #ifdef __SMP__
148: ,IRQ16_interrupt
149: #endif
150: };
151:
152: static void (*fast_interrupt[16])(void) = {
153: fast_IRQ0_interrupt, fast_IRQ1_interrupt,
154: fast_IRQ2_interrupt, fast_IRQ3_interrupt,
155: fast_IRQ4_interrupt, fast_IRQ5_interrupt,
156: fast_IRQ6_interrupt, fast_IRQ7_interrupt,
157: fast_IRQ8_interrupt, fast_IRQ9_interrupt,
158: fast_IRQ10_interrupt, fast_IRQ11_interrupt,
159: fast_IRQ12_interrupt, fast_IRQ13_interrupt,
160: fast_IRQ14_interrupt, fast_IRQ15_interrupt
161: };
162:
163: static void (*bad_interrupt[16])(void) = {
164: bad_IRQ0_interrupt, bad_IRQ1_interrupt,
165: bad_IRQ2_interrupt, bad_IRQ3_interrupt,
166: bad_IRQ4_interrupt, bad_IRQ5_interrupt,
167: bad_IRQ6_interrupt, bad_IRQ7_interrupt,
168: bad_IRQ8_interrupt, bad_IRQ9_interrupt,
169: bad_IRQ10_interrupt, bad_IRQ11_interrupt,
170: bad_IRQ12_interrupt, bad_IRQ13_interrupt,
171: bad_IRQ14_interrupt, bad_IRQ15_interrupt
172: };
173:
174: /*
175: * Initial irq handlers.
176: */
177:
178: static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
179:
180: #ifdef __SMP__
181:
182: /*
183: * On SMP boards, irq13 is used for interprocessor interrupts (IPI's).
184: */
185: static struct irqaction irq13 = { smp_message_irq, SA_INTERRUPT, 0, "IPI", NULL, NULL };
186:
187: #else
188:
189: /*
190: * Note that on a 486, we don't want to do a SIGFPE on a irq13
191: * as the irq is unreliable, and exception 16 works correctly
192: * (ie as explained in the intel literature). On a 386, you
193: * can't use exception 16 due to bad IBM design, so we have to
194: * rely on the less exact irq13.
195: *
196: * Careful.. Not only is IRQ13 unreliable, but it is also
197: * leads to races. IBM designers who came up with it should
198: * be shot.
199: */
200:
201:
202: static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
203: {
204: outb(0,0xF0);
205: if (ignore_irq13 || !hard_math)
206: return;
207: math_error();
208: }
209:
210: static struct irqaction irq13 = { math_error_irq, 0, 0, "math error", NULL, NULL };
211:
212: #endif
213:
214: /*
215: * IRQ2 is cascade interrupt to second interrupt controller
216: */
217: static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
218:
219: static struct irqaction *irq_action[16] = {
220: NULL, NULL, NULL, NULL,
221: NULL, NULL, NULL, NULL,
222: NULL, NULL, NULL, NULL,
223: NULL, NULL, NULL, NULL
224: };
225:
226: int get_irq_list(char *buf)
227: {
228: int i, len = 0;
229: struct irqaction * action;
230:
231: for (i = 0 ; i < 16 ; i++) {
232: action = irq_action[i];
233: if (!action)
234: continue;
235: len += sprintf(buf+len, "%2d: %10u %c %s",
236: i, kstat.interrupts[i],
237: (action->flags & SA_INTERRUPT) ? '+' : ' ',
238: action->name);
239: for (action=action->next; action; action = action->next) {
240: len += sprintf(buf+len, ",%s %s",
241: (action->flags & SA_INTERRUPT) ? " +" : "",
242: action->name);
243: }
244: len += sprintf(buf+len, "\n");
245: }
246: /*
247: * Linus - should you add NMI counts here ?????
248: */
249: #ifdef __SMP_PROF__
250: len+=sprintf(buf+len, "IPI: %8lu received\n",
251: ipi_count);
252: #endif
253: return len;
254: }
255:
256: #ifdef __SMP_PROF__
257:
258: int get_smp_prof_list(char *buf) {
259: int i,j, len = 0;
260: struct irqaction * action;
261: unsigned long sum_spins = 0;
262: unsigned long sum_spins_syscall = 0;
263: unsigned long sum_spins_sys_idle = 0;
264: unsigned long sum_smp_idle_count = 0;
265:
266: for (i=0;i<smp_num_cpus;i++) {
267: int cpunum = cpu_logical_map[i];
268: sum_spins+=smp_spins[cpunum];
269: sum_spins_syscall+=smp_spins_syscall[cpunum];
270: sum_spins_sys_idle+=smp_spins_sys_idle[cpunum];
271: sum_smp_idle_count+=smp_idle_count[cpunum];
272: }
273:
274: len += sprintf(buf+len,"CPUS: %10i \n", smp_num_cpus);
275: len += sprintf(buf+len," SUM ");
276: for (i=0;i<smp_num_cpus;i++)
277: len += sprintf(buf+len," P%1d ",cpu_logical_map[i]);
278: len += sprintf(buf+len,"\n");
279: for (i = 0 ; i < NR_IRQS ; i++) {
280: action = *(i + irq_action);
281: if (!action || !action->handler)
282: continue;
283: len += sprintf(buf+len, "%3d: %10d ",
284: i, kstat.interrupts[i]);
285: for (j=0;j<smp_num_cpus;j++)
286: len+=sprintf(buf+len, "%10d ",
287: int_count[cpu_logical_map[j]][i]);
288: len += sprintf(buf+len, "%c %s",
289: (action->flags & SA_INTERRUPT) ? '+' : ' ',
290: action->name);
291: for (action=action->next; action; action = action->next) {
292: len += sprintf(buf+len, ",%s %s",
293: (action->flags & SA_INTERRUPT) ? " +" : "",
294: action->name);
295: }
296: len += sprintf(buf+len, "\n");
297: }
298: len+=sprintf(buf+len, "LCK: %10lu",
299: sum_spins);
300:
301: for (i=0;i<smp_num_cpus;i++)
302: len+=sprintf(buf+len," %10lu",smp_spins[cpu_logical_map[i]]);
303:
304: len +=sprintf(buf+len," spins from int\n");
305:
306: len+=sprintf(buf+len, "LCK: %10lu",
307: sum_spins_syscall);
308:
309: for (i=0;i<smp_num_cpus;i++)
310: len+=sprintf(buf+len," %10lu",smp_spins_syscall[cpu_logical_map[i]]);
311:
312: len +=sprintf(buf+len," spins from syscall\n");
313:
314: len+=sprintf(buf+len, "LCK: %10lu",
315: sum_spins_sys_idle);
316:
317: for (i=0;i<smp_num_cpus;i++)
318: len+=sprintf(buf+len," %10lu",smp_spins_sys_idle[cpu_logical_map[i]]);
319:
320: len +=sprintf(buf+len," spins from sysidle\n");
321: len+=sprintf(buf+len,"IDLE %10lu",sum_smp_idle_count);
322:
323: for (i=0;i<smp_num_cpus;i++)
324: len+=sprintf(buf+len," %10lu",smp_idle_count[cpu_logical_map[i]]);
325:
326: len +=sprintf(buf+len," idle ticks\n");
327:
328: len+=sprintf(buf+len, "IPI: %10lu received\n",
329: ipi_count);
330:
331: return len;
332: }
333: #endif
334:
335:
336:
337: /*
338: * do_IRQ handles IRQ's that have been installed without the
339: * SA_INTERRUPT flag: it uses the full signal-handling return
340: * and runs with other interrupts enabled. All relatively slow
341: * IRQ's should use this format: notably the keyboard/timer
342: * routines.
343: */
344: asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
345: {
346: struct irqaction * action = *(irq + irq_action);
347: int do_random = 0;
348: int c,intm,mask;
349: #ifdef IRQ_DEBUG
350: static int count;
351: if (smp_processor_id() != 0 && count++ < 1000)
352: printk("IRQ %d: done by CPU %d\n",irq,smp_processor_id());
353: #endif
354: if (irq >= 8) {
355: c = cache_A1;
356: intm = inb(0xA1);
357: mask = 1 << (irq - 8);
358: } else {
359: c = cache_21;
360: intm = inb(0x21);
361: mask = 1 << irq;
362: }
363: if (!(c & mask) || !(intm & mask)) {
364: #ifdef IRQ_DEBUG
365: printk("IRQ %d (proc %d):cache_x1=0x%x,INT mask=0x%x\n", irq, smp_processor_id(),c,intm);
366: #endif
367: /* better to return because the interrupt may be asserted again,
368: the bad thing is that we may loose some interrupts */
369: return;
370: }
371: #ifdef __SMP__
372: if(smp_threads_ready && active_kernel_processor!=smp_processor_id())
373: panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
374: #endif
375:
376: kstat.interrupts[irq]++;
377: #ifdef __SMP_PROF__
378: int_count[smp_processor_id()][irq]++;
379: #endif
380: while (action) {
381: do_random |= action->flags;
382: action->handler(irq, action->dev_id, regs);
383: action = action->next;
384: }
385: if (do_random & SA_SAMPLE_RANDOM)
386: add_interrupt_randomness(irq);
387: }
388:
389: /*
390: * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return
391: * stuff - the handler is also running with interrupts disabled unless
392: * it explicitly enables them later.
393: */
394: asmlinkage void do_fast_IRQ(int irq)
395: {
396: struct irqaction * action = *(irq + irq_action);
397: int do_random = 0;
398:
399: #ifdef __SMP__
400: /* IRQ 13 is allowed - that's a flush tlb */
401: if(smp_threads_ready && active_kernel_processor!=smp_processor_id() && irq!=13)
402: panic("fast_IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
403: #endif
404:
405: kstat.interrupts[irq]++;
406: #ifdef __SMP_PROF__
407: int_count[smp_processor_id()][irq]++;
408: #endif
409: while (action) {
410: do_random |= action->flags;
411: action->handler(irq, action->dev_id, NULL);
412: action = action->next;
413: }
414: if (do_random & SA_SAMPLE_RANDOM)
415: add_interrupt_randomness(irq);
416: }
417:
418: int setup_x86_irq(int irq, struct irqaction * new)
419: {
420: int shared = 0;
421: struct irqaction *old, **p;
422: unsigned long flags;
423:
424: p = irq_action + irq;
425: if ((old = *p) != NULL) {
426: /* Can't share interrupts unless both agree to */
427: if (!(old->flags & new->flags & SA_SHIRQ))
428: return -EBUSY;
429:
430: /* Can't share interrupts unless both are same type */
431: if ((old->flags ^ new->flags) & SA_INTERRUPT)
432: return -EBUSY;
433:
434: /* add new interrupt at end of irq queue */
435: do {
436: p = &old->next;
437: old = *p;
438: } while (old);
439: shared = 1;
440: }
441:
442: if (new->flags & SA_SAMPLE_RANDOM)
443: rand_initialize_irq(irq);
444:
445: save_flags(flags);
446: cli();
447: *p = new;
448:
449: if (!shared) {
450: if (new->flags & SA_INTERRUPT)
451: set_intr_gate(0x20+irq,fast_interrupt[irq]);
452: else
453: set_intr_gate(0x20+irq,interrupt[irq]);
454: unmask_irq(irq);
455: }
456: restore_flags(flags);
457: return 0;
458: }
459:
460: int request_irq(unsigned int irq,
461: void (*handler)(int, void *, struct pt_regs *),
462: unsigned long irqflags,
463: const char * devname,
464: void *dev_id)
465: {
466: int retval;
467: struct irqaction * action;
468:
469: if (irq > 15)
470: return -EINVAL;
471: if (!handler)
472: return -EINVAL;
473:
474: action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
475: if (!action)
476: return -ENOMEM;
477:
478: action->handler = handler;
479: action->flags = irqflags;
480: action->mask = 0;
481: action->name = devname;
482: action->next = NULL;
483: action->dev_id = dev_id;
484:
485: retval = setup_x86_irq(irq, action);
486:
487: if (retval)
488: kfree(action);
489: return retval;
490: }
491:
492: void free_irq(unsigned int irq, void *dev_id)
493: {
494: struct irqaction * action, **p;
495: unsigned long flags;
496:
497: if (irq > 15) {
498: printk("Trying to free IRQ%d\n",irq);
499: return;
500: }
501: for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
502: if (action->dev_id != dev_id)
503: continue;
504:
505: /* Found it - now free it */
506: save_flags(flags);
507: cli();
508: *p = action->next;
509: if (!irq[irq_action]) {
510: mask_irq(irq);
511: set_intr_gate(0x20+irq,bad_interrupt[irq]);
512: }
513: restore_flags(flags);
514: kfree(action);
515: return;
516: }
517: printk("Trying to free free IRQ%d\n",irq);
518: }
519:
520: unsigned long probe_irq_on (void)
521: {
522: unsigned int i, irqs = 0, irqmask;
523: unsigned long delay;
524:
525: /* first, enable any unassigned irqs */
526: for (i = 15; i > 0; i--) {
527: if (!irq_action[i]) {
528: enable_irq(i);
529: irqs |= (1 << i);
530: }
531: }
532:
533: /* wait for spurious interrupts to mask themselves out again */
534: for (delay = jiffies + HZ/10; delay > jiffies; )
535: /* about 100ms delay */;
536:
537: /* now filter out any obviously spurious interrupts */
538: irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
539: return irqs & ~irqmask;
540: }
541:
542: int probe_irq_off (unsigned long irqs)
543: {
544: unsigned int i, irqmask;
545:
546: irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
547: #ifdef DEBUG
548: printk("probe_irq_off: irqs=0x%04lx irqmask=0x%04x\n", irqs, irqmask);
549: #endif
550: irqs &= irqmask;
551: if (!irqs)
552: return 0;
553: i = ffz(~irqs);
554: if (irqs != (irqs & (1 << i)))
555: i = -i;
556: return i;
557: }
558:
559: void init_IRQ(void)
560: {
561: int i;
562: static unsigned char smptrap=0;
563: if(smptrap)
564: return;
565: smptrap=1;
566:
567: /* set the clock to 100 Hz */
568: outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
569: outb_p(LATCH & 0xff , 0x40); /* LSB */
570: outb(LATCH >> 8 , 0x40); /* MSB */
571: for (i = 0; i < 16 ; i++)
572: set_intr_gate(0x20+i,bad_interrupt[i]);
573: /* This bit is a hack because we don't send timer messages to all processors yet */
574: /* It has to be here .. it doesn't work if you put it down the bottom - assembler explodes 8) */
575: #ifdef __SMP__
576: set_intr_gate(0x20+i, interrupt[i]); /* IRQ '16' - IPI for rescheduling */
577: #endif
578: request_region(0x20,0x20,"pic1");
579: request_region(0xa0,0x20,"pic2");
580: setup_x86_irq(2, &irq2);
581: setup_x86_irq(13, &irq13);
582: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.