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