This source file includes following definitions.
- disable_irq
- enable_irq
- get_irq_list
- get_smp_prof_list
- do_IRQ
- do_fast_IRQ
- request_irq
- free_irq
- math_error_irq
- no_action
- probe_irq_on
- probe_irq_off
- init_IRQ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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/random.h>
27
28 #include <asm/system.h>
29 #include <asm/io.h>
30 #include <asm/irq.h>
31 #include <asm/bitops.h>
32 #include <asm/smp.h>
33
34 #define CR0_NE 32
35
36 static unsigned char cache_21 = 0xff;
37 static unsigned char cache_A1 = 0xff;
38
39 #ifdef __SMP_PROF__
40 static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
41 #endif
42
43 void disable_irq(unsigned int irq_nr)
44 {
45 unsigned long flags;
46 unsigned char mask;
47
48 mask = 1 << (irq_nr & 7);
49 save_flags(flags);
50 if (irq_nr < 8) {
51 cli();
52 cache_21 |= mask;
53 outb(cache_21,0x21);
54 restore_flags(flags);
55 return;
56 }
57 cli();
58 cache_A1 |= mask;
59 outb(cache_A1,0xA1);
60 restore_flags(flags);
61 }
62
63 void enable_irq(unsigned int irq_nr)
64 {
65 unsigned long flags;
66 unsigned char mask;
67
68 mask = ~(1 << (irq_nr & 7));
69 save_flags(flags);
70 if (irq_nr < 8) {
71 cli();
72 cache_21 &= mask;
73 outb(cache_21,0x21);
74 restore_flags(flags);
75 return;
76 }
77 cli();
78 cache_A1 &= mask;
79 outb(cache_A1,0xA1);
80 restore_flags(flags);
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 BUILD_IRQ(FIRST,0,0x01)
99 BUILD_IRQ(FIRST,1,0x02)
100 BUILD_IRQ(FIRST,2,0x04)
101 BUILD_IRQ(FIRST,3,0x08)
102 BUILD_IRQ(FIRST,4,0x10)
103 BUILD_IRQ(FIRST,5,0x20)
104 BUILD_IRQ(FIRST,6,0x40)
105 BUILD_IRQ(FIRST,7,0x80)
106 BUILD_IRQ(SECOND,8,0x01)
107 BUILD_IRQ(SECOND,9,0x02)
108 BUILD_IRQ(SECOND,10,0x04)
109 BUILD_IRQ(SECOND,11,0x08)
110 BUILD_IRQ(SECOND,12,0x10)
111 #ifdef __SMP__
112 BUILD_MSGIRQ(SECOND,13,0x20)
113 #else
114 BUILD_IRQ(SECOND,13,0x20)
115 #endif
116 BUILD_IRQ(SECOND,14,0x40)
117 BUILD_IRQ(SECOND,15,0x80)
118 #ifdef __SMP__
119 BUILD_RESCHEDIRQ(16)
120 #endif
121
122
123
124
125
126 static void (*interrupt[17])(void) = {
127 IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt,
128 IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
129 IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
130 IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt
131 #ifdef __SMP__
132 ,IRQ16_interrupt
133 #endif
134 };
135
136 static void (*fast_interrupt[16])(void) = {
137 fast_IRQ0_interrupt, fast_IRQ1_interrupt,
138 fast_IRQ2_interrupt, fast_IRQ3_interrupt,
139 fast_IRQ4_interrupt, fast_IRQ5_interrupt,
140 fast_IRQ6_interrupt, fast_IRQ7_interrupt,
141 fast_IRQ8_interrupt, fast_IRQ9_interrupt,
142 fast_IRQ10_interrupt, fast_IRQ11_interrupt,
143 fast_IRQ12_interrupt, fast_IRQ13_interrupt,
144 fast_IRQ14_interrupt, fast_IRQ15_interrupt
145 };
146
147 static void (*bad_interrupt[16])(void) = {
148 bad_IRQ0_interrupt, bad_IRQ1_interrupt,
149 bad_IRQ2_interrupt, bad_IRQ3_interrupt,
150 bad_IRQ4_interrupt, bad_IRQ5_interrupt,
151 bad_IRQ6_interrupt, bad_IRQ7_interrupt,
152 bad_IRQ8_interrupt, bad_IRQ9_interrupt,
153 bad_IRQ10_interrupt, bad_IRQ11_interrupt,
154 bad_IRQ12_interrupt, bad_IRQ13_interrupt,
155 bad_IRQ14_interrupt, bad_IRQ15_interrupt
156 };
157
158
159
160
161 struct irqaction {
162 void (*handler)(int, struct pt_regs *);
163 unsigned long flags;
164 unsigned long mask;
165 const char *name;
166 };
167
168 static struct irqaction irq_action[16] = {
169 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
170 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
171 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
172 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
173 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
174 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
175 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
176 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
177 };
178
179 int get_irq_list(char *buf)
180 {
181 int i, len = 0;
182 struct irqaction * action = irq_action;
183
184 for (i = 0 ; i < 16 ; i++, action++) {
185 if (!action->handler)
186 continue;
187 len += sprintf(buf+len, "%3d: %8d %c %s\n",
188 i, kstat.interrupts[i],
189 (action->flags & SA_INTERRUPT) ? '+' : ' ',
190 action->name);
191 }
192
193
194
195 #ifdef __SMP_PROF__
196 len+=sprintf(buf+len, "IPI: %8lu received\n",
197 ipi_count);
198 #endif
199 return len;
200 }
201
202 #ifdef __SMP_PROF__
203
204 int get_smp_prof_list(char *buf) {
205 int i,j, len = 0;
206 struct irqaction * action = irq_action;
207 unsigned long sum_spins = 0;
208 unsigned long sum_spins_syscall = 0;
209 unsigned long sum_spins_sys_idle = 0;
210 unsigned long sum_smp_idle_count = 0;
211
212 for (i=0;i<=smp_num_cpus;i++) {
213 sum_spins+=smp_spins[i];
214 sum_spins_syscall+=smp_spins_syscall[i];
215 sum_spins_sys_idle+=smp_spins_sys_idle[i];
216 sum_smp_idle_count+=smp_idle_count[i];
217 }
218
219 len += sprintf(buf+len,"CPUS: %10i \n",
220 0==smp_num_cpus?1:smp_num_cpus);
221 len += sprintf(buf+len," SUM ");
222 for (i=0;i<smp_num_cpus;i++)
223 len += sprintf(buf+len," P%1d ",i);
224 len += sprintf(buf+len,"\n");
225 for (i = 0 ; i < NR_IRQS ; i++, action++) {
226 if (!action->handler)
227 continue;
228 len += sprintf(buf+len, "%3d: %10d ",
229 i, kstat.interrupts[i]);
230 for (j=0;j<smp_num_cpus;j++)
231 len+=sprintf(buf+len, "%10d ",int_count[j][i]);
232 len += sprintf(buf+len, "%c %s\n",
233 (action->flags & SA_INTERRUPT) ? '+' : ' ',
234 action->name);
235 }
236 len+=sprintf(buf+len, "LCK: %10lu",
237 sum_spins);
238 for (i=0;i<smp_num_cpus;i++)
239 len+=sprintf(buf+len," %10lu",smp_spins[i]);
240 len +=sprintf(buf+len," spins from int\n");
241
242 len+=sprintf(buf+len, "LCK: %10lu",
243 sum_spins_syscall);
244 for (i=0;i<smp_num_cpus;i++)
245 len+=sprintf(buf+len," %10lu",smp_spins_syscall[i]);
246 len +=sprintf(buf+len," spins from syscall\n");
247
248 len+=sprintf(buf+len, "LCK: %10lu",
249 sum_spins_sys_idle);
250 for (i=0;i<smp_num_cpus;i++)
251 len+=sprintf(buf+len," %10lu",smp_spins_sys_idle[i]);
252 len +=sprintf(buf+len," spins from sysidle\n");
253 len+=sprintf(buf+len,"IDLE %10lu",sum_smp_idle_count);
254 for (i=0;i<smp_num_cpus;i++)
255 len+=sprintf(buf+len," %10lu",smp_idle_count[i]);
256 len +=sprintf(buf+len," idle ticks\n");
257
258 len+=sprintf(buf+len, "IPI: %10lu received\n",
259 ipi_count);
260
261 return len;
262 }
263 #endif
264
265
266
267
268
269
270
271
272
273
274 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
275 {
276 struct irqaction * action = irq + irq_action;
277 #ifdef __SMP__
278 if(smp_threads_ready && active_kernel_processor!=smp_processor_id())
279 panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
280 #endif
281
282 kstat.interrupts[irq]++;
283 #ifdef __SMP_PROF__
284 int_count[smp_processor_id()][irq]++;
285 #endif
286 if (action->flags & SA_SAMPLE_RANDOM)
287 add_interrupt_randomness(irq);
288 action->handler(irq, regs);
289 }
290
291
292
293
294
295
296 asmlinkage void do_fast_IRQ(int irq)
297 {
298 struct irqaction * action = irq + irq_action;
299 #ifdef __SMP__
300
301 if(smp_threads_ready && active_kernel_processor!=smp_processor_id() && irq!=13)
302 panic("fast_IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
303 #endif
304
305 kstat.interrupts[irq]++;
306 #ifdef __SMP_PROF__
307 int_count[smp_processor_id()][irq]++;
308 #endif
309 if (action->flags & SA_SAMPLE_RANDOM)
310 add_interrupt_randomness(irq);
311 action->handler(irq, NULL);
312 }
313
314 #define SA_PROBE SA_ONESHOT
315
316 int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
317 unsigned long irqflags, const char * devname)
318 {
319 struct irqaction * action;
320 unsigned long flags;
321
322 if (irq > 15)
323 return -EINVAL;
324 action = irq + irq_action;
325 if (action->handler)
326 return -EBUSY;
327 if (!handler)
328 return -EINVAL;
329 if (irqflags & SA_SAMPLE_RANDOM)
330 rand_initialize_irq(irq);
331 save_flags(flags);
332 cli();
333 action->handler = handler;
334 action->flags = irqflags;
335 action->mask = 0;
336 action->name = devname;
337 if (!(action->flags & SA_PROBE)) {
338 if (action->flags & SA_INTERRUPT)
339 set_intr_gate(0x20+irq,fast_interrupt[irq]);
340 else
341 set_intr_gate(0x20+irq,interrupt[irq]);
342 }
343 if (irq < 8) {
344 cache_21 &= ~(1<<irq);
345 outb(cache_21,0x21);
346 } else {
347 cache_21 &= ~(1<<2);
348 cache_A1 &= ~(1<<(irq-8));
349 outb(cache_21,0x21);
350 outb(cache_A1,0xA1);
351 }
352 restore_flags(flags);
353 return 0;
354 }
355
356 void free_irq(unsigned int irq)
357 {
358 struct irqaction * action = irq + irq_action;
359 unsigned long flags;
360
361 if (irq > 15) {
362 printk("Trying to free IRQ%d\n",irq);
363 return;
364 }
365 if (!action->handler) {
366 printk("Trying to free free IRQ%d\n",irq);
367 return;
368 }
369 save_flags(flags);
370 cli();
371 if (irq < 8) {
372 cache_21 |= 1 << irq;
373 outb(cache_21,0x21);
374 } else {
375 cache_A1 |= 1 << (irq-8);
376 outb(cache_A1,0xA1);
377 }
378 set_intr_gate(0x20+irq,bad_interrupt[irq]);
379 action->handler = NULL;
380 action->flags = 0;
381 action->mask = 0;
382 action->name = NULL;
383 restore_flags(flags);
384 }
385
386 #ifndef __SMP__
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401 static void math_error_irq(int cpl, struct pt_regs *regs)
402 {
403 outb(0,0xF0);
404 if (ignore_irq13 || !hard_math)
405 return;
406 math_error();
407 }
408
409 #endif
410
411 static void no_action(int cpl, struct pt_regs * regs) { }
412
413 unsigned long probe_irq_on (void)
414 {
415 unsigned int i, irqs = 0, irqmask;
416 unsigned long delay;
417
418
419 for (i = 15; i > 0; i--) {
420 if (!request_irq(i, no_action, SA_PROBE, "probe")) {
421 enable_irq(i);
422 irqs |= (1 << i);
423 }
424 }
425
426
427 for (delay = jiffies + 2; delay > jiffies; );
428
429
430 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
431 for (i = 15; i > 0; i--) {
432 if (irqs & (1 << i) & irqmask) {
433 irqs ^= (1 << i);
434 free_irq(i);
435 }
436 }
437 #ifdef DEBUG
438 printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
439 #endif
440 return irqs;
441 }
442
443 int probe_irq_off (unsigned long irqs)
444 {
445 unsigned int i, irqmask;
446
447 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
448 for (i = 15; i > 0; i--) {
449 if (irqs & (1 << i)) {
450 free_irq(i);
451 }
452 }
453 #ifdef DEBUG
454 printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
455 #endif
456 irqs &= irqmask;
457 if (!irqs)
458 return 0;
459 i = ffz(~irqs);
460 if (irqs != (irqs & (1 << i)))
461 i = -i;
462 return i;
463 }
464
465 void init_IRQ(void)
466 {
467 int i;
468 static unsigned char smptrap=0;
469 if(smptrap)
470 return;
471 smptrap=1;
472
473
474 outb_p(0x34,0x43);
475 outb_p(LATCH & 0xff , 0x40);
476 outb(LATCH >> 8 , 0x40);
477 for (i = 0; i < 16 ; i++)
478 set_intr_gate(0x20+i,bad_interrupt[i]);
479
480
481 #ifdef __SMP__
482 set_intr_gate(0x20+i, interrupt[i]);
483 #endif
484 if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
485 printk("Unable to get IRQ2 for cascade.\n");
486 #ifndef __SMP__
487 if (request_irq(13,math_error_irq, 0, "math error"))
488 printk("Unable to get IRQ13 for math-error handler.\n");
489 #else
490 if (request_irq(13, smp_message_irq, SA_INTERRUPT, "IPI"))
491 printk("Unable to get IRQ13 for IPI.\n");
492 #endif
493 request_region(0x20,0x20,"pic1");
494 request_region(0xa0,0x20,"pic2");
495 }