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