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