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, void *dev_id, 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
344
345
346 static inline void isa_device_interrupt(unsigned long vector,
347 struct pt_regs * regs)
348 {
349 #if defined(CONFIG_ALPHA_APECS)
350 # define IACK_SC APECS_IACK_SC
351 #elif defined(CONFIG_ALPHA_LCA)
352 # define IACK_SC LCA_IACK_SC
353 #elif defined(CONFIG_ALPHA_ALCOR)
354 # define IACK_SC ALCOR_IACK_SC
355 #else
356
357
358
359
360
361
362 # define IACK_SC 1L
363 #endif
364 int j;
365
366 #if 1
367
368
369
370
371
372
373
374 j = *(volatile int *) IACK_SC;
375 j &= 0xff;
376 if (j == 7) {
377 if (!(inb(0x20) & 0x80)) {
378
379 return;
380 }
381 }
382 device_interrupt(j, j, regs);
383 #else
384 unsigned long pic;
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399 pic = inb(0x20) | (inb(0xA0) << 8);
400 pic &= ~((cache_A1 << 8) | cache_21);
401 pic &= 0xFFFB;
402
403 while (pic) {
404 j = ffz(~pic);
405 pic &= pic - 1;
406 device_interrupt(j, j, regs);
407 }
408 #endif
409 }
410
411 static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector,
412 struct pt_regs * regs)
413 {
414 unsigned long pld;
415 unsigned int i;
416 unsigned long flags;
417
418 save_flags(flags);
419 cli();
420
421
422 pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
423
424 #if 0
425 printk("[0x%04X/0x%04X]", pld, inb(0x20) | (inb(0xA0) << 8));
426 #endif
427
428
429
430
431
432 while (pld) {
433 i = ffz(~pld);
434 pld &= pld - 1;
435 if (i == 4) {
436 isa_device_interrupt(vector, regs);
437 } else {
438 device_interrupt(16 + i, 16 + i, regs);
439 }
440 }
441 restore_flags(flags);
442 }
443
444 static inline void eb66_and_eb64p_device_interrupt(unsigned long vector,
445 struct pt_regs * regs)
446 {
447 unsigned long pld;
448 unsigned int i;
449 unsigned long flags;
450
451 save_flags(flags);
452 cli();
453
454
455 pld = inb(0x26) | (inb(0x27) << 8);
456
457
458
459
460 while (pld) {
461 i = ffz(~pld);
462 pld &= pld - 1;
463
464 if (i == 5) {
465 isa_device_interrupt(vector, regs);
466 } else {
467 device_interrupt(16 + i, 16 + i, regs);
468 }
469 }
470 restore_flags(flags);
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
496 static inline void srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
497 {
498 int irq, ack;
499 unsigned long flags;
500
501 save_flags(flags);
502 cli();
503
504
505 ack = irq = (vector - 0x800) >> 4;
506
507 #ifdef CONFIG_ALPHA_JENSEN
508 switch (vector) {
509 case 0x660: handle_nmi(regs); return;
510
511 case 0x900: handle_irq(4, regs); return;
512 case 0x920: handle_irq(3, regs); return;
513 case 0x980: handle_irq(1, regs); return;
514 case 0x990: handle_irq(9, regs); return;
515 default:
516 if (vector > 0x900) {
517 printk("Unknown local interrupt %lx\n", vector);
518 }
519 }
520
521 if (irq == 1)
522 irq = 7;
523 #endif
524
525 device_interrupt(irq, ack, regs);
526
527 restore_flags(flags) ;
528 }
529
530 #if NR_IRQS > 64
531 # error Number of irqs limited to 64 due to interrupt-probing.
532 #endif
533
534
535
536
537 unsigned long probe_irq_on(void)
538 {
539 struct irqaction * action;
540 unsigned long irqs = 0, irqmask;
541 unsigned long delay;
542 unsigned int i;
543
544 for (i = NR_IRQS - 1; i > 0; i--) {
545 action = irq_action[i];
546 if (!action) {
547 enable_irq(i);
548 irqs |= (1 << i);
549 }
550 }
551
552
553 for (delay = jiffies + HZ/10; delay > jiffies; )
554 ;
555
556
557 irqmask = (((unsigned long)cache_A1)<<8) | (unsigned long) cache_21;
558 #if NR_IRQS == 33
559 irqmask |= (unsigned long) cache_804 << 16;
560 #elif NR_IRQS == 32
561 irqmask |= ((((unsigned long)cache_26)<<16) |
562 (((unsigned long)cache_27)<<24));
563 #endif
564 irqs &= ~irqmask;
565 return irqs;
566 }
567
568
569
570
571
572
573 int probe_irq_off(unsigned long irqs)
574 {
575 unsigned long irqmask;
576 int i;
577
578 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
579 #if NR_IRQS == 33
580 irqmask |= (unsigned long) cache_804 << 16;
581 #elif NR_IRQS == 32
582 irqmask |= ((((unsigned long)cache_26)<<16) |
583 (((unsigned long)cache_27)<<24));
584 #endif
585 irqs &= irqmask & ~1;
586 #ifdef CONFIG_ALPHA_P2K
587 irqs &= ~(1 << 8);
588 #endif
589 if (!irqs)
590 return 0;
591 i = ffz(~irqs);
592 if (irqs != (1UL << i))
593 i = -i;
594 return i;
595 }
596
597 static void machine_check(unsigned long vector, unsigned long la, struct pt_regs * regs)
598 {
599 #if defined(CONFIG_ALPHA_LCA)
600 extern void lca_machine_check (unsigned long vector, unsigned long la,
601 struct pt_regs *regs);
602 lca_machine_check(vector, la, regs);
603 #elif defined(CONFIG_ALPHA_APECS)
604 extern void apecs_machine_check(unsigned long vector, unsigned long la,
605 struct pt_regs * regs);
606 apecs_machine_check(vector, la, regs);
607 #elif defined(CONFIG_ALPHA_ALCOR)
608 extern void alcor_machine_check(unsigned long vector, unsigned long la,
609 struct pt_regs * regs);
610 alcor_machine_check(vector, la, regs);
611 #else
612 printk("Machine check\n");
613 #endif
614 }
615
616 asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
617 unsigned long a3, unsigned long a4, unsigned long a5,
618 struct pt_regs regs)
619 {
620 switch (type) {
621 case 0:
622 printk("Interprocessor interrupt? You must be kidding\n");
623 break;
624 case 1:
625 timer_interrupt(®s);
626 return;
627 case 2:
628 machine_check(vector, la_ptr, ®s);
629 return;
630 case 3:
631 #if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME) || \
632 defined(CONFIG_ALPHA_P2K) || defined(CONFIG_ALPHA_SRM)
633 srm_device_interrupt(vector, ®s);
634 #elif NR_IRQS == 33
635 cabriolet_and_eb66p_device_interrupt(vector, ®s);
636 #elif NR_IRQS == 32
637 eb66_and_eb64p_device_interrupt(vector, ®s);
638 #elif NR_IRQS == 16
639 isa_device_interrupt(vector, ®s);
640 #endif
641 return;
642 case 4:
643 printk("Performance counter interrupt\n");
644 break;;
645 default:
646 printk("Hardware intr %ld %lx? Huh?\n", type, vector);
647 }
648 printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
649 }
650
651 extern asmlinkage void entInt(void);
652
653 void init_IRQ(void)
654 {
655 wrent(entInt, 0);
656 dma_outb(0, DMA1_RESET_REG);
657 dma_outb(0, DMA2_RESET_REG);
658 dma_outb(0, DMA1_CLR_MASK_REG);
659 dma_outb(0, DMA2_CLR_MASK_REG);
660 #if NR_IRQS == 33
661 outl(cache_804, 0x804);
662 #elif NR_IRQS == 32
663 outb(cache_26, 0x26);
664 outb(cache_27, 0x27);
665 #endif
666 enable_irq(2);
667 }