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 # define NUM_IRQS 33
35 #elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
36 static unsigned char cache_26 = 0xdf;
37 static unsigned char cache_27 = 0xff;
38 # define NUM_IRQS 32
39 #else
40 # define NUM_IRQS 16
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 defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
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 defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
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 defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
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 defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
106 } else if 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 struct irqaction {
121 void (*handler)(int, struct pt_regs *);
122 unsigned long flags;
123 unsigned long mask;
124 const char *name;
125 };
126
127 static struct irqaction irq_action[NUM_IRQS];
128
129 int get_irq_list(char *buf)
130 {
131 int i, len = 0;
132 struct irqaction * action = irq_action;
133
134 for (i = 0 ; i < NUM_IRQS ; i++, action++) {
135 if (!action->handler)
136 continue;
137 len += sprintf(buf+len, "%2d: %8d %c %s\n",
138 i, kstat.interrupts[i],
139 (action->flags & SA_INTERRUPT) ? '+' : ' ',
140 action->name);
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 defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
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 defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P)
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 defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
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 defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P)
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, void (*handler)(int, struct pt_regs *),
223 unsigned long irqflags, const char * devname)
224 {
225 struct irqaction * action;
226 unsigned long flags;
227
228 if (irq >= NUM_IRQS)
229 return -EINVAL;
230 action = irq + irq_action;
231 if (action->handler)
232 return -EBUSY;
233 if (!handler)
234 return -EINVAL;
235 save_flags(flags);
236 cli();
237 action->handler = handler;
238 action->flags = irqflags;
239 action->mask = 0;
240 action->name = devname;
241 enable_irq(irq);
242 if (irq >= 8 && irq < 16) {
243 enable_irq(2);
244 }
245 restore_flags(flags);
246 return 0;
247 }
248
249 void free_irq(unsigned int irq)
250 {
251 struct irqaction * action = irq + irq_action;
252 unsigned long flags;
253
254 if (irq >= NUM_IRQS) {
255 printk("Trying to free IRQ%d\n", irq);
256 return;
257 }
258 if (!action->handler) {
259 printk("Trying to free free IRQ%d\n", irq);
260 return;
261 }
262 save_flags(flags);
263 cli();
264 mask_irq(irq);
265 action->handler = NULL;
266 action->flags = 0;
267 action->mask = 0;
268 action->name = NULL;
269 restore_flags(flags);
270 }
271
272 static inline void handle_nmi(struct pt_regs * regs)
273 {
274 printk("Whee.. NMI received. Probable hardware error\n");
275 printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
276 }
277
278 static void unexpected_irq(int irq, struct pt_regs * regs)
279 {
280 int i;
281
282 printk("IO device interrupt, irq = %d\n", irq);
283 printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
284 printk("Expecting: ");
285 for (i = 0; i < 16; i++)
286 if (irq_action[i].handler)
287 printk("[%s:%d] ", irq_action[i].name, i);
288 printk("\n");
289 printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
290 inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
291 outb(0x0c, 0x3fc);
292 outb(0x0c, 0x2fc);
293 outb(0,0x61);
294 outb(0,0x461);
295 }
296
297 static inline void handle_irq(int irq, struct pt_regs * regs)
298 {
299 struct irqaction * action = irq + irq_action;
300
301 kstat.interrupts[irq]++;
302 if (!action->handler) {
303 unexpected_irq(irq, regs);
304 return;
305 }
306 action->handler(irq, regs);
307 }
308
309 static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
310 {
311 struct irqaction * action;
312
313 if ((unsigned) irq > NUM_IRQS) {
314 printk("device_interrupt: unexpected interrupt %d\n", irq);
315 return;
316 }
317
318 kstat.interrupts[irq]++;
319 action = irq_action + irq;
320
321 if (action->flags & SA_INTERRUPT) {
322 action->handler(irq, regs);
323 ack_irq(ack);
324 return;
325 }
326
327
328
329
330
331
332
333
334
335 mask_irq(ack);
336 ack_irq(ack);
337 if (!action->handler)
338 return;
339 action->handler(irq, regs);
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 unsigned long pic;
350 int j;
351
352
353
354
355
356
357 pic = inb(0x20) | (inb(0xA0) << 8);
358 pic &= ~((cache_A1 << 8) | cache_21);
359 pic &= 0xFFFB;
360
361 while (pic) {
362 j = ffz(~pic);
363 pic &= pic - 1;
364 device_interrupt(j, j, regs);
365 }
366 }
367
368 static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector,
369 struct pt_regs * regs)
370 {
371 unsigned long pld;
372 unsigned int i;
373 unsigned long flags;
374
375 save_flags(flags);
376 cli();
377
378
379 pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
380
381
382
383
384
385 while (pld) {
386 i = ffz(~pld);
387 pld &= pld - 1;
388 if (i == 4) {
389 isa_device_interrupt(vector, regs);
390 } else {
391 device_interrupt(16 + i, 16 + i, regs);
392 }
393 }
394 restore_flags(flags);
395 }
396
397 static inline void eb66_and_eb64p_device_interrupt(unsigned long vector,
398 struct pt_regs * regs)
399 {
400 unsigned long pld;
401 unsigned int i;
402 unsigned long flags;
403
404 save_flags(flags);
405 cli();
406
407
408 pld = inb(0x26) | (inb(0x27) << 8);
409
410
411
412
413 while (pld) {
414 i = ffz(~pld);
415 pld &= pld - 1;
416
417 if (i == 5) {
418 isa_device_interrupt(vector, regs);
419 } else {
420 device_interrupt(16 + i, 16 + i, regs);
421 }
422 }
423 restore_flags(flags);
424 }
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449 static inline void srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
450 {
451 int irq, ack;
452 struct irqaction * action;
453
454 ack = irq = (vector - 0x800) >> 4;
455
456 #ifdef CONFIG_ALPHA_JENSEN
457 switch (vector) {
458 case 0x660: handle_nmi(regs); return;
459
460 case 0x900: handle_irq(4, regs); return;
461 case 0x920: handle_irq(3, regs); return;
462 case 0x980: handle_irq(1, regs); return;
463 case 0x990: handle_irq(9, regs); return;
464 default:
465 if (vector > 0x900) {
466 printk("Unknown local interrupt %lx\n", vector);
467 }
468 }
469
470 if (irq == 1)
471 irq = 7;
472 #endif
473
474 device_interrupt(irq, ack, regs);
475 }
476
477 #if NUM_IRQS > 64
478 # error Number of irqs limited to 64 due to interrupt-probing.
479 #endif
480
481
482
483
484 unsigned long probe_irq_on(void)
485 {
486 unsigned long irqs = 0, irqmask;
487 unsigned long delay;
488 unsigned int i;
489
490 for (i = NUM_IRQS - 1; i > 0; i--) {
491 if (!irq_action[i].handler) {
492 enable_irq(i);
493 irqs |= (1 << i);
494 }
495 }
496
497
498 for (delay = jiffies + HZ/10; delay > jiffies; )
499 ;
500
501
502 irqmask = (((unsigned long)cache_A1)<<8) | (unsigned long) cache_21;
503 #if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
504 irqmask |= ((((unsigned long)cache_804)<<16) |
505 (((unsigned long)cache_805)<<24) |
506 (((unsigned long)cache_806)<<24));
507 #elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
508 irqmask |= ((((unsigned long)cache_26)<<16) |
509 (((unsigned long)cache_27)<<24);
510 #endif
511 irqs &= ~irqmask;
512 return irqs;
513 }
514
515
516
517
518
519
520 int probe_irq_off(unsigned long irqs)
521 {
522 unsigned long irqmask;
523 int i;
524
525 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
526 #if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
527 irqmask |= ((((unsigned long)cache_804)<<16) |
528 (((unsigned long)cache_805)<<24) |
529 (((unsigned long)cache_806)<<24));
530 #elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
531 irqmask |= ((((unsigned long)cache_26)<<16) |
532 (((unsigned long)cache_27)<<24);
533 #endif
534 irqs &= irqmask;
535 if (!irqs)
536 return 0;
537 i = ffz(~irqs);
538 if (irqs != (1UL << i))
539 i = -i;
540 return i;
541 }
542
543 static void machine_check(unsigned long vector, unsigned long la, struct pt_regs * regs)
544 {
545 #if defined(CONFIG_ALPHA_LCA)
546 extern void lca_machine_check (unsigned long vector, unsigned long la,
547 struct pt_regs *regs);
548 lca_machine_check(vector, la, regs);
549 #elif defined(CONFIG_ALPHA_APECS)
550 extern void apecs_machine_check(unsigned long vector, unsigned long la,
551 struct pt_regs * regs);
552 apecs_machine_check(vector, la, regs);
553 #else
554 printk("Machine check\n");
555 #endif
556 }
557
558 asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
559 unsigned long a3, unsigned long a4, unsigned long a5,
560 struct pt_regs regs)
561 {
562 switch (type) {
563 case 0:
564 printk("Interprocessor interrupt? You must be kidding\n");
565 break;
566 case 1:
567
568 handle_irq(0, ®s);
569 return;
570 case 2:
571 machine_check(vector, la_ptr, ®s);
572 break;
573 case 3:
574 #if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME)
575 srm_device_interrupt(vector, ®s);
576 #elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
577 cabriolet_and_eb66p_device_interrupt(vector, ®s);
578 #elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
579 eb66_and_eb64p_device_interrupt(vector, ®s);
580 #endif
581 return;
582 case 4:
583 printk("Performance counter interrupt\n");
584 break;;
585 default:
586 printk("Hardware intr %ld %lx? Huh?\n", type, vector);
587 }
588 printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
589 }
590
591 extern asmlinkage void entInt(void);
592
593 void init_IRQ(void)
594 {
595 wrent(entInt, 0);
596 dma_outb(0, DMA1_RESET_REG);
597 dma_outb(0, DMA2_RESET_REG);
598 dma_outb(0, DMA1_CLR_MASK_REG);
599 dma_outb(0, DMA2_CLR_MASK_REG);
600 #if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
601 outb(cache_804, 0x804);
602 outb(cache_805, 0x805);
603 outb(cache_806, 0x806);
604 #elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
605 outb(cache_26, 0x26);
606 outb(cache_27, 0x27);
607 #endif
608 }