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