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 int shared = 0;
176 struct irqaction * action, **p;
177 unsigned long flags;
178
179 if (irq >= NR_IRQS)
180 return -EINVAL;
181 if (!handler)
182 return -EINVAL;
183 p = irq_action + irq;
184 action = *p;
185 if (action) {
186
187 if (!(action->flags & irqflags & SA_SHIRQ))
188 return -EBUSY;
189
190
191 if ((action->flags ^ irqflags) & SA_INTERRUPT)
192 return -EBUSY;
193
194
195 do {
196 p = &action->next;
197 action = *p;
198 } while (action);
199 shared = 1;
200 }
201
202 action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
203 if (!action)
204 return -ENOMEM;
205
206 if (irqflags & SA_SAMPLE_RANDOM)
207 rand_initialize_irq(irq);
208
209 action->handler = handler;
210 action->flags = irqflags;
211 action->mask = 0;
212 action->name = devname;
213 action->next = NULL;
214 action->dev_id = dev_id;
215
216 save_flags(flags);
217 cli();
218 *p = action;
219
220 if (!shared)
221 unmask_irq(irq);
222
223 restore_flags(flags);
224 return 0;
225 }
226
227 void free_irq(unsigned int irq, void *dev_id)
228 {
229 struct irqaction * action, **p;
230 unsigned long flags;
231
232 if (irq >= NR_IRQS) {
233 printk("Trying to free IRQ%d\n",irq);
234 return;
235 }
236 for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
237 if (action->dev_id != dev_id)
238 continue;
239
240
241 save_flags(flags);
242 cli();
243 *p = action->next;
244 if (!irq[irq_action])
245 mask_irq(irq);
246 restore_flags(flags);
247 kfree(action);
248 return;
249 }
250 printk("Trying to free free IRQ%d\n",irq);
251 }
252
253 static inline void handle_nmi(struct pt_regs * regs)
254 {
255 printk("Whee.. NMI received. Probable hardware error\n");
256 printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
257 }
258
259 static void unexpected_irq(int irq, struct pt_regs * regs)
260 {
261 struct irqaction *action;
262 int i;
263
264 printk("IO device interrupt, irq = %d\n", irq);
265 printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
266 printk("Expecting: ");
267 for (i = 0; i < 16; i++)
268 if ((action = irq_action[i]))
269 while (action->handler) {
270 printk("[%s:%d] ", action->name, i);
271 action = action->next;
272 }
273 printk("\n");
274 #if defined(CONFIG_ALPHA_JENSEN)
275 printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
276 inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
277 outb(0x0c, 0x3fc);
278 outb(0x0c, 0x2fc);
279 outb(0,0x61);
280 outb(0,0x461);
281 #endif
282 }
283
284 static inline void handle_irq(int irq, struct pt_regs * regs)
285 {
286 struct irqaction * action = irq_action[irq];
287
288 kstat.interrupts[irq]++;
289 if (!action) {
290 unexpected_irq(irq, regs);
291 return;
292 }
293 do {
294 action->handler(irq, action->dev_id, regs);
295 action = action->next;
296 } while (action);
297 }
298
299 static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
300 {
301 struct irqaction * action;
302
303 if ((unsigned) irq > NR_IRQS) {
304 printk("device_interrupt: unexpected interrupt %d\n", irq);
305 return;
306 }
307
308 kstat.interrupts[irq]++;
309 action = irq_action[irq];
310 if (action) {
311
312 if (action->flags & SA_INTERRUPT) {
313 while (action) {
314 action->handler(irq, action->dev_id, regs);
315 action = action->next;
316 }
317 ack_irq(ack);
318 return;
319 }
320 }
321
322
323
324
325
326
327
328
329
330 mask_irq(ack);
331 ack_irq(ack);
332 if (!action)
333 return;
334 if (action->flags & SA_SAMPLE_RANDOM)
335 add_interrupt_randomness(irq);
336 while (action) {
337 action->handler(irq, action->dev_id, regs);
338 action = action->next;
339 }
340 unmask_irq(ack);
341 }
342
343 #ifdef CONFIG_PCI
344
345
346
347
348 static inline void isa_device_interrupt(unsigned long vector,
349 struct pt_regs * regs)
350 {
351 #if defined(CONFIG_ALPHA_APECS)
352 # define IACK_SC APECS_IACK_SC
353 #elif defined(CONFIG_ALPHA_LCA)
354 # define IACK_SC LCA_IACK_SC
355 #elif defined(CONFIG_ALPHA_ALCOR)
356 # define IACK_SC ALCOR_IACK_SC
357 #else
358
359
360
361
362
363
364 # define IACK_SC 1L
365 #endif
366 int j;
367
368 #if 1
369
370
371
372
373
374
375
376 j = *(volatile int *) IACK_SC;
377 j &= 0xff;
378 if (j == 7) {
379 if (!(inb(0x20) & 0x80)) {
380
381 return;
382 }
383 }
384 device_interrupt(j, j, regs);
385 #else
386 unsigned long pic;
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401 pic = inb(0x20) | (inb(0xA0) << 8);
402 pic &= ~((cache_A1 << 8) | cache_21);
403 pic &= 0xFFFB;
404
405 while (pic) {
406 j = ffz(~pic);
407 pic &= pic - 1;
408 device_interrupt(j, j, regs);
409 }
410 #endif
411 }
412
413 static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector,
414 struct pt_regs * regs)
415 {
416 unsigned long pld;
417 unsigned int i;
418 unsigned long flags;
419
420 save_flags(flags);
421 cli();
422
423
424 pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
425
426 #if 0
427 printk("[0x%04X/0x%04X]", pld, inb(0x20) | (inb(0xA0) << 8));
428 #endif
429
430
431
432
433
434 while (pld) {
435 i = ffz(~pld);
436 pld &= pld - 1;
437 if (i == 4) {
438 isa_device_interrupt(vector, regs);
439 } else {
440 device_interrupt(16 + i, 16 + i, regs);
441 }
442 }
443 restore_flags(flags);
444 }
445
446 static inline void eb66_and_eb64p_device_interrupt(unsigned long vector,
447 struct pt_regs * regs)
448 {
449 unsigned long pld;
450 unsigned int i;
451 unsigned long flags;
452
453 save_flags(flags);
454 cli();
455
456
457 pld = inb(0x26) | (inb(0x27) << 8);
458
459
460
461
462 while (pld) {
463 i = ffz(~pld);
464 pld &= pld - 1;
465
466 if (i == 5) {
467 isa_device_interrupt(vector, regs);
468 } else {
469 device_interrupt(16 + i, 16 + i, regs);
470 }
471 }
472 restore_flags(flags);
473 }
474
475 #endif
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500 static inline void srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
501 {
502 int irq, ack;
503 unsigned long flags;
504
505 save_flags(flags);
506 cli();
507
508
509 ack = irq = (vector - 0x800) >> 4;
510
511 #ifdef CONFIG_ALPHA_JENSEN
512 switch (vector) {
513 case 0x660: handle_nmi(regs); return;
514
515 case 0x900: handle_irq(4, regs); return;
516 case 0x920: handle_irq(3, regs); return;
517 case 0x980: handle_irq(1, regs); return;
518 case 0x990: handle_irq(9, regs); return;
519 default:
520 if (vector > 0x900) {
521 printk("Unknown local interrupt %lx\n", vector);
522 }
523 }
524
525 if (irq == 1)
526 irq = 7;
527 #endif
528
529 device_interrupt(irq, ack, regs);
530
531 restore_flags(flags) ;
532 }
533
534 #if NR_IRQS > 64
535 # error Number of irqs limited to 64 due to interrupt-probing.
536 #endif
537
538
539
540
541 unsigned long probe_irq_on(void)
542 {
543 struct irqaction * action;
544 unsigned long irqs = 0, irqmask;
545 unsigned long delay;
546 unsigned int i;
547
548 for (i = NR_IRQS - 1; i > 0; i--) {
549 action = irq_action[i];
550 if (!action) {
551 enable_irq(i);
552 irqs |= (1 << i);
553 }
554 }
555
556
557 for (delay = jiffies + HZ/10; delay > jiffies; )
558 ;
559
560
561 irqmask = (((unsigned long)cache_A1)<<8) | (unsigned long) cache_21;
562 #if NR_IRQS == 33
563 irqmask |= (unsigned long) cache_804 << 16;
564 #elif NR_IRQS == 32
565 irqmask |= ((((unsigned long)cache_26)<<16) |
566 (((unsigned long)cache_27)<<24));
567 #endif
568 irqs &= ~irqmask;
569 return irqs;
570 }
571
572
573
574
575
576
577 int probe_irq_off(unsigned long irqs)
578 {
579 unsigned long irqmask;
580 int i;
581
582 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
583 #if NR_IRQS == 33
584 irqmask |= (unsigned long) cache_804 << 16;
585 #elif NR_IRQS == 32
586 irqmask |= ((((unsigned long)cache_26)<<16) |
587 (((unsigned long)cache_27)<<24));
588 #endif
589 irqs &= irqmask & ~1;
590 #ifdef CONFIG_ALPHA_P2K
591 irqs &= ~(1 << 8);
592 #endif
593 if (!irqs)
594 return 0;
595 i = ffz(~irqs);
596 if (irqs != (1UL << i))
597 i = -i;
598 return i;
599 }
600
601 static void machine_check(unsigned long vector, unsigned long la, struct pt_regs * regs)
602 {
603 #if defined(CONFIG_ALPHA_LCA)
604 extern void lca_machine_check (unsigned long vector, unsigned long la,
605 struct pt_regs *regs);
606 lca_machine_check(vector, la, regs);
607 #elif defined(CONFIG_ALPHA_APECS)
608 extern void apecs_machine_check(unsigned long vector, unsigned long la,
609 struct pt_regs * regs);
610 apecs_machine_check(vector, la, regs);
611 #elif defined(CONFIG_ALPHA_ALCOR)
612 extern void alcor_machine_check(unsigned long vector, unsigned long la,
613 struct pt_regs * regs);
614 alcor_machine_check(vector, la, regs);
615 #else
616 printk("Machine check\n");
617 #endif
618 }
619
620 asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
621 unsigned long a3, unsigned long a4, unsigned long a5,
622 struct pt_regs regs)
623 {
624 switch (type) {
625 case 0:
626 printk("Interprocessor interrupt? You must be kidding\n");
627 break;
628 case 1:
629 timer_interrupt(®s);
630 return;
631 case 2:
632 machine_check(vector, la_ptr, ®s);
633 return;
634 case 3:
635 #if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME) || \
636 defined(CONFIG_ALPHA_P2K) || defined(CONFIG_ALPHA_SRM)
637 srm_device_interrupt(vector, ®s);
638 #elif NR_IRQS == 33
639 cabriolet_and_eb66p_device_interrupt(vector, ®s);
640 #elif NR_IRQS == 32
641 eb66_and_eb64p_device_interrupt(vector, ®s);
642 #elif NR_IRQS == 16
643 isa_device_interrupt(vector, ®s);
644 #endif
645 return;
646 case 4:
647 printk("Performance counter interrupt\n");
648 break;;
649 default:
650 printk("Hardware intr %ld %lx? Huh?\n", type, vector);
651 }
652 printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
653 }
654
655 extern asmlinkage void entInt(void);
656
657 void init_IRQ(void)
658 {
659 wrent(entInt, 0);
660 dma_outb(0, DMA1_RESET_REG);
661 dma_outb(0, DMA2_RESET_REG);
662 dma_outb(0, DMA1_CLR_MASK_REG);
663 dma_outb(0, DMA2_CLR_MASK_REG);
664 #if NR_IRQS == 33
665 outl(cache_804, 0x804);
666 #elif NR_IRQS == 32
667 outb(cache_26, 0x26);
668 outb(cache_27, 0x27);
669 #endif
670 enable_irq(2);
671 }