This source file includes following definitions.
- disable_irq
- enable_irq
- get_irq_list
- ack_irq
- mask_irq
- unmask_irq
- request_irq
- free_irq
- handle_nmi
- unexpected_irq
- handle_irq
- device_interrupt
- isa_device_interrupt
- cabriolet_and_eb66p_device_interrupt
- eb66_and_eb64p_device_interrupt
- srm_device_interrupt
- probe_irq_on
- probe_irq_off
- machine_check
- do_entInt
- init_IRQ
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/config.h>
14 #include <linux/ptrace.h>
15 #include <linux/errno.h>
16 #include <linux/kernel_stat.h>
17 #include <linux/signal.h>
18 #include <linux/sched.h>
19 #include <linux/interrupt.h>
20 #include <linux/random.h>
21
22 #include <asm/system.h>
23 #include <asm/io.h>
24 #include <asm/irq.h>
25 #include <asm/bitops.h>
26 #include <asm/dma.h>
27
28 extern void timer_interrupt(struct pt_regs * regs);
29
30 static unsigned char cache_21 = 0xff;
31 static unsigned char cache_A1 = 0xff;
32
33 #if NR_IRQS == 33
34 static unsigned char cache_804 = 0xef;
35 static unsigned char cache_805 = 0xff;
36 static unsigned char cache_806 = 0xff;
37 #elif NR_IRQS == 32
38 static unsigned char cache_26 = 0xdf;
39 static unsigned char cache_27 = 0xff;
40 #endif
41
42 void disable_irq(unsigned int irq_nr)
43 {
44 unsigned long flags;
45 unsigned char mask;
46
47 save_flags(flags);
48 cli();
49 mask = 1 << (irq_nr & 7);
50
51 if (irq_nr < 8) {
52 cache_21 |= mask;
53 outb(cache_21,0x21);
54 } else if (irq_nr < 16) {
55 cache_A1 |= mask;
56 outb(cache_A1,0xA1);
57 #if NR_IRQS == 33
58 } else if (irq_nr < 24) {
59 cache_804 |= mask;
60 outb(cache_804, 0x804);
61 } else if (irq_nr < 32) {
62 cache_805 |= mask;
63 outb(cache_805, 0x805);
64 } else {
65 cache_806 |= mask;
66 outb(cache_806, 0x806);
67 #elif NR_IRQS == 32
68 } else if (irq_nr < 24) {
69 cache_26 |= mask;
70 outb(cache_26, 0x26);
71 } else {
72 cache_27 |= mask;
73 outb(cache_27, 0x27);
74 #endif
75 }
76 restore_flags(flags);
77 }
78
79 void enable_irq(unsigned int irq_nr)
80 {
81 unsigned long flags;
82 unsigned char mask;
83
84 mask = ~(1 << (irq_nr & 7));
85 save_flags(flags);
86 cli();
87
88 if (irq_nr < 8) {
89 cache_21 &= mask;
90 outb(cache_21,0x21);
91 } else if (irq_nr < 16) {
92 cache_A1 &= mask;
93 outb(cache_A1,0xA1);
94 #if NR_IRQS == 33
95 } else if (irq_nr < 24) {
96 cache_804 &= mask;
97 outb(cache_804, 0x804);
98 } else if (irq_nr < 32) {
99 cache_805 &= mask;
100 outb(cache_805, 0x805);
101 } else {
102 cache_806 &= mask;
103 outb(cache_806, 0x806);
104 #elif NR_IRQS == 32
105 } else if (irq_nr < 24) {
106 cache_26 &= mask;
107 outb(cache_26, 0x26);
108 } else {
109 cache_27 &= mask;
110 outb(cache_27, 0x27);
111 #endif
112 }
113 restore_flags(flags);
114 }
115
116
117
118
119 struct irqaction {
120 void (*handler)(int, struct pt_regs *);
121 unsigned long flags;
122 unsigned long mask;
123 const char *name;
124 };
125
126 static struct irqaction irq_action[NR_IRQS];
127
128 int get_irq_list(char *buf)
129 {
130 int i, len = 0;
131 struct irqaction * action = irq_action;
132
133 for (i = 0 ; i < NR_IRQS ; i++, action++) {
134 if (!action->handler)
135 continue;
136 len += sprintf(buf+len, "%2d: %8d %c %s\n",
137 i, kstat.interrupts[i],
138 (action->flags & SA_INTERRUPT) ? '+' : ' ',
139 action->name);
140 }
141 return len;
142 }
143
144 static inline void ack_irq(int irq)
145 {
146 if (irq < 16) {
147
148
149 if (irq > 7) {
150 outb(0xE0 | (irq - 8), 0xa0);
151 irq = 2;
152 }
153
154 outb(0xE0 | irq, 0x20);
155 }
156 }
157
158 static inline void mask_irq(int irq)
159 {
160 unsigned char mask;
161
162 mask = 1 << (irq & 7);
163 if (irq < 8) {
164 cache_21 |= mask;
165 outb(cache_21, 0x21);
166 } else if (irq < 16) {
167 cache_A1 |= mask;
168 outb(cache_A1, 0xA1);
169 #if NR_IRQS == 33
170 } else if (irq < 24) {
171 cache_804 |= mask;
172 outb(cache_804, 0x804);
173 } else if (irq < 32) {
174 cache_805 |= mask;
175 outb(cache_805, 0x805);
176 } else {
177 cache_806 |= mask;
178 outb(cache_806, 0x806);
179 #elif NR_IRQS == 32
180 } else if (irq < 24) {
181 cache_26 |= mask;
182 outb(cache_26, 0x26);
183 } else {
184 cache_27 |= mask;
185 outb(cache_27, 0x27);
186 #endif
187 }
188 }
189
190 static inline void unmask_irq(unsigned long irq)
191 {
192 unsigned char mask = ~(1 << (irq & 7));
193
194 if (irq < 8) {
195 cache_21 &= mask;
196 outb(cache_21, 0x21);
197 } else if (irq < 16) {
198 cache_A1 &= mask;
199 outb(cache_A1, 0xA1);
200 #if NR_IRQS == 33
201 } else if (irq < 24) {
202 cache_804 &= mask;
203 outb(cache_804, 0x804);
204 } else if (irq < 32) {
205 cache_805 &= mask;
206 outb(cache_805, 0x805);
207 } else {
208 cache_806 &= mask;
209 outb(cache_806, 0x806);
210 #elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P)
211 } else if (irq < 24) {
212 cache_26 &= mask;
213 outb(cache_26, 0x26);
214 } else {
215 cache_27 &= mask;
216 outb(cache_27, 0x27);
217 #endif
218 }
219 }
220
221 int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
222 unsigned long irqflags, const char * devname)
223 {
224 struct irqaction * action;
225 unsigned long flags;
226
227 if (irq >= NR_IRQS)
228 return -EINVAL;
229
230 if (!irq)
231 return -EINVAL;
232 action = irq + irq_action;
233 if (action->handler)
234 return -EBUSY;
235 if (!handler)
236 return -EINVAL;
237 save_flags(flags);
238 cli();
239 action->handler = handler;
240 action->flags = irqflags;
241 action->mask = 0;
242 action->name = devname;
243 enable_irq(irq);
244 if (irq >= 8 && irq < 16) {
245 enable_irq(2);
246 }
247 restore_flags(flags);
248 return 0;
249 }
250
251 void free_irq(unsigned int irq)
252 {
253 struct irqaction * action = irq + irq_action;
254 unsigned long flags;
255
256 if (irq >= NR_IRQS) {
257 printk("Trying to free IRQ%d\n", irq);
258 return;
259 }
260 if (!action->handler) {
261 printk("Trying to free free IRQ%d\n", irq);
262 return;
263 }
264 save_flags(flags);
265 cli();
266 mask_irq(irq);
267 action->handler = NULL;
268 action->flags = 0;
269 action->mask = 0;
270 action->name = NULL;
271 restore_flags(flags);
272 }
273
274 static inline void handle_nmi(struct pt_regs * regs)
275 {
276 printk("Whee.. NMI received. Probable hardware error\n");
277 printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
278 }
279
280 static void unexpected_irq(int irq, struct pt_regs * regs)
281 {
282 int i;
283
284 printk("IO device interrupt, irq = %d\n", irq);
285 printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
286 printk("Expecting: ");
287 for (i = 0; i < 16; i++)
288 if (irq_action[i].handler)
289 printk("[%s:%d] ", irq_action[i].name, i);
290 printk("\n");
291 #if defined(CONFIG_ALPHA_JENSEN)
292 printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
293 inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
294 outb(0x0c, 0x3fc);
295 outb(0x0c, 0x2fc);
296 outb(0,0x61);
297 outb(0,0x461);
298 #endif
299 }
300
301 static inline void handle_irq(int irq, struct pt_regs * regs)
302 {
303 struct irqaction * action = irq + irq_action;
304
305 kstat.interrupts[irq]++;
306 if (!action->handler) {
307 unexpected_irq(irq, regs);
308 return;
309 }
310 action->handler(irq, regs);
311 }
312
313 static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
314 {
315 struct irqaction * action;
316
317 if ((unsigned) irq > NR_IRQS) {
318 printk("device_interrupt: unexpected interrupt %d\n", irq);
319 return;
320 }
321
322 kstat.interrupts[irq]++;
323 action = irq_action + irq;
324 if (action->flags & SA_SAMPLE_RANDOM)
325 add_interrupt_randomness(irq);
326
327 if (action->flags & SA_INTERRUPT) {
328 action->handler(irq, regs);
329 ack_irq(ack);
330 return;
331 }
332
333
334
335
336
337
338
339
340
341 mask_irq(ack);
342 ack_irq(ack);
343 if (!action->handler)
344 return;
345 action->handler(irq, regs);
346 unmask_irq(ack);
347 }
348
349
350
351
352 static inline void isa_device_interrupt(unsigned long vector,
353 struct pt_regs * regs)
354 {
355 #if defined(CONFIG_ALPHA_APECS)
356 # define IACK_SC APECS_IACK_SC
357 #elif defined(CONFIG_ALPHA_LCA)
358 # define IACK_SC LCA_IACK_SC
359 #else
360
361
362
363
364
365
366 # define IACK_SC 1L
367 #endif
368 int j;
369
370
371
372
373
374
375
376
377 j = *(volatile int *) IACK_SC;
378 j &= 0xff;
379 if (j == 7) {
380 if (!(inb(0x20) & 0x80)) {
381
382 return;
383 }
384 }
385 device_interrupt(j, j, regs);
386 #if 0
387 unsigned long pic;
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402 pic = inb(0x20) | (inb(0xA0) << 8);
403 pic &= ~((cache_A1 << 8) | cache_21);
404 pic &= 0xFFFB;
405
406 while (pic) {
407 j = ffz(~pic);
408 pic &= pic - 1;
409 device_interrupt(j, j, regs);
410 }
411 #endif
412 }
413
414 static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector,
415 struct pt_regs * regs)
416 {
417 unsigned long pld;
418 unsigned int i;
419 unsigned long flags;
420
421 save_flags(flags);
422 cli();
423
424
425 pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
426
427
428
429
430
431 while (pld) {
432 i = ffz(~pld);
433 pld &= pld - 1;
434 if (i == 4) {
435 isa_device_interrupt(vector, regs);
436 } else {
437 device_interrupt(16 + i, 16 + i, regs);
438 }
439 }
440 restore_flags(flags);
441 }
442
443 static inline void eb66_and_eb64p_device_interrupt(unsigned long vector,
444 struct pt_regs * regs)
445 {
446 unsigned long pld;
447 unsigned int i;
448 unsigned long flags;
449
450 save_flags(flags);
451 cli();
452
453
454 pld = inb(0x26) | (inb(0x27) << 8);
455
456
457
458
459 while (pld) {
460 i = ffz(~pld);
461 pld &= pld - 1;
462
463 if (i == 5) {
464 isa_device_interrupt(vector, regs);
465 } else {
466 device_interrupt(16 + i, 16 + i, regs);
467 }
468 }
469 restore_flags(flags);
470 }
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495 static inline void srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
496 {
497 int irq, ack;
498
499 ack = irq = (vector - 0x800) >> 4;
500
501 #ifdef CONFIG_ALPHA_JENSEN
502 switch (vector) {
503 case 0x660: handle_nmi(regs); return;
504
505 case 0x900: handle_irq(4, regs); return;
506 case 0x920: handle_irq(3, regs); return;
507 case 0x980: handle_irq(1, regs); return;
508 case 0x990: handle_irq(9, regs); return;
509 default:
510 if (vector > 0x900) {
511 printk("Unknown local interrupt %lx\n", vector);
512 }
513 }
514
515 if (irq == 1)
516 irq = 7;
517 #endif
518
519 device_interrupt(irq, ack, regs);
520 }
521
522 #if NR_IRQS > 64
523 # error Number of irqs limited to 64 due to interrupt-probing.
524 #endif
525
526
527
528
529 unsigned long probe_irq_on(void)
530 {
531 unsigned long irqs = 0, irqmask;
532 unsigned long delay;
533 unsigned int i;
534
535 for (i = NR_IRQS - 1; i > 0; i--) {
536 if (!irq_action[i].handler) {
537 enable_irq(i);
538 irqs |= (1 << i);
539 }
540 }
541
542
543 for (delay = jiffies + HZ/10; delay > jiffies; )
544 ;
545
546
547 irqmask = (((unsigned long)cache_A1)<<8) | (unsigned long) cache_21;
548 #if NR_IRQS == 33
549 irqmask |= ((((unsigned long)cache_804)<<16) |
550 (((unsigned long)cache_805)<<24) |
551 (((unsigned long)cache_806)<<24));
552 #elif NR_IRQS == 32
553 irqmask |= ((((unsigned long)cache_26)<<16) |
554 (((unsigned long)cache_27)<<24));
555 #endif
556 irqs &= ~irqmask;
557 return irqs;
558 }
559
560
561
562
563
564
565 int probe_irq_off(unsigned long irqs)
566 {
567 unsigned long irqmask;
568 int i;
569
570 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
571 #if NR_IRQS == 33
572 irqmask |= ((((unsigned long)cache_804)<<16) |
573 (((unsigned long)cache_805)<<24) |
574 (((unsigned long)cache_806)<<24));
575 #elif NR_IRQS == 32
576 irqmask |= ((((unsigned long)cache_26)<<16) |
577 (((unsigned long)cache_27)<<24));
578 #endif
579 irqs &= irqmask & ~1;
580 if (!irqs)
581 return 0;
582 i = ffz(~irqs);
583 if (irqs != (1UL << i))
584 i = -i;
585 return i;
586 }
587
588 static void machine_check(unsigned long vector, unsigned long la, struct pt_regs * regs)
589 {
590 #if defined(CONFIG_ALPHA_LCA)
591 extern void lca_machine_check (unsigned long vector, unsigned long la,
592 struct pt_regs *regs);
593 lca_machine_check(vector, la, regs);
594 #elif defined(CONFIG_ALPHA_APECS)
595 extern void apecs_machine_check(unsigned long vector, unsigned long la,
596 struct pt_regs * regs);
597 apecs_machine_check(vector, la, regs);
598 #else
599 printk("Machine check\n");
600 #endif
601 }
602
603 asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
604 unsigned long a3, unsigned long a4, unsigned long a5,
605 struct pt_regs regs)
606 {
607 switch (type) {
608 case 0:
609 printk("Interprocessor interrupt? You must be kidding\n");
610 break;
611 case 1:
612 timer_interrupt(®s);
613 return;
614 case 2:
615 machine_check(vector, la_ptr, ®s);
616 return;
617 case 3:
618 #if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME) || \
619 defined(CONFIG_ALPHA_SRM)
620 srm_device_interrupt(vector, ®s);
621 #elif NR_IRQS == 33
622 cabriolet_and_eb66p_device_interrupt(vector, ®s);
623 #elif NR_IRQS == 32
624 eb66_and_eb64p_device_interrupt(vector, ®s);
625 #endif
626 return;
627 case 4:
628 printk("Performance counter interrupt\n");
629 break;;
630 default:
631 printk("Hardware intr %ld %lx? Huh?\n", type, vector);
632 }
633 printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
634 }
635
636 extern asmlinkage void entInt(void);
637
638 void init_IRQ(void)
639 {
640 wrent(entInt, 0);
641 dma_outb(0, DMA1_RESET_REG);
642 dma_outb(0, DMA2_RESET_REG);
643 dma_outb(0, DMA1_CLR_MASK_REG);
644 dma_outb(0, DMA2_CLR_MASK_REG);
645 #if NR_IRQS == 33
646 outb(cache_804, 0x804);
647 outb(cache_805, 0x805);
648 outb(cache_806, 0x806);
649 #elif NR_IRQS == 32
650 outb(cache_26, 0x26);
651 outb(cache_27, 0x27);
652 #endif
653 }