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
- local_device_interrupt
- 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 void disable_irq(unsigned int irq_nr)
31 {
32 unsigned long flags;
33 unsigned char mask;
34
35 mask = 1 << (irq_nr & 7);
36 save_flags(flags);
37 if (irq_nr < 8) {
38 cli();
39 cache_21 |= mask;
40 outb(cache_21,0x21);
41 restore_flags(flags);
42 return;
43 }
44 cli();
45 cache_A1 |= mask;
46 outb(cache_A1,0xA1);
47 restore_flags(flags);
48 }
49
50 void enable_irq(unsigned int irq_nr)
51 {
52 unsigned long flags;
53 unsigned char mask;
54
55 mask = ~(1 << (irq_nr & 7));
56 save_flags(flags);
57 if (irq_nr < 8) {
58 cli();
59 cache_21 &= mask;
60 outb(cache_21,0x21);
61 restore_flags(flags);
62 return;
63 }
64 cli();
65 cache_A1 &= mask;
66 outb(cache_A1,0xA1);
67 restore_flags(flags);
68 }
69
70
71
72
73 struct irqaction {
74 void (*handler)(int, struct pt_regs *);
75 unsigned long flags;
76 unsigned long mask;
77 const char *name;
78 };
79
80 static struct irqaction irq_action[16] = {
81 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
82 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
83 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
84 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
85 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
86 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
87 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
88 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
89 };
90
91 int get_irq_list(char *buf)
92 {
93 int i, len = 0;
94 struct irqaction * action = irq_action;
95
96 for (i = 0 ; i < 16 ; i++, action++) {
97 if (!action->handler)
98 continue;
99 len += sprintf(buf+len, "%2d: %8d %c %s\n",
100 i, kstat.interrupts[i],
101 (action->flags & SA_INTERRUPT) ? '+' : ' ',
102 action->name);
103 }
104 return len;
105 }
106
107 static inline void ack_irq(int irq)
108 {
109
110
111 if (irq > 7) {
112 outb(0xE0 | (irq - 8), 0xa0);
113 irq = 2;
114 }
115
116 outb(0xE0 | irq, 0x20);
117 }
118
119 static inline void mask_irq(int irq)
120 {
121 if (irq < 8) {
122 cache_21 |= 1 << irq;
123 outb(cache_21, 0x21);
124 } else {
125 cache_A1 |= 1 << (irq - 8);
126 outb(cache_A1, 0xA1);
127 }
128 }
129
130 static inline void unmask_irq(unsigned long irq)
131 {
132 if (irq < 8) {
133 cache_21 &= ~(1 << irq);
134 outb(cache_21, 0x21);
135 } else {
136 cache_A1 &= ~(1 << (irq - 8));
137 outb(cache_A1, 0xA1);
138 }
139 }
140
141 int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
142 unsigned long irqflags, const char * devname)
143 {
144 struct irqaction * action;
145 unsigned long flags;
146
147 if (irq > 15)
148 return -EINVAL;
149 action = irq + irq_action;
150 if (action->handler)
151 return -EBUSY;
152 if (!handler)
153 return -EINVAL;
154 save_flags(flags);
155 cli();
156 action->handler = handler;
157 action->flags = irqflags;
158 action->mask = 0;
159 action->name = devname;
160 if (irq < 8) {
161 if (irq) {
162 cache_21 &= ~(1<<irq);
163 outb(cache_21,0x21);
164 }
165 } else {
166 cache_21 &= ~(1<<2);
167 cache_A1 &= ~(1<<(irq-8));
168 outb(cache_21,0x21);
169 outb(cache_A1,0xA1);
170 }
171 restore_flags(flags);
172 return 0;
173 }
174
175 void free_irq(unsigned int irq)
176 {
177 struct irqaction * action = irq + irq_action;
178 unsigned long flags;
179
180 if (irq > 15) {
181 printk("Trying to free IRQ%d\n", irq);
182 return;
183 }
184 if (!action->handler) {
185 printk("Trying to free free IRQ%d\n", irq);
186 return;
187 }
188 save_flags(flags);
189 cli();
190 mask_irq(irq);
191 action->handler = NULL;
192 action->flags = 0;
193 action->mask = 0;
194 action->name = NULL;
195 restore_flags(flags);
196 }
197
198 static void handle_nmi(struct pt_regs * regs)
199 {
200 printk("Whee.. NMI received. Probable hardware error\n");
201 printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
202 }
203
204 static void unexpected_irq(int irq, struct pt_regs * regs)
205 {
206 int i;
207
208 printk("IO device interrupt, irq = %d\n", irq);
209 printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
210 printk("Expecting: ");
211 for (i = 0; i < 16; i++)
212 if (irq_action[i].handler)
213 printk("[%s:%d] ", irq_action[i].name, i);
214 printk("\n");
215 printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
216 inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
217 outb(0x0c, 0x3fc);
218 outb(0x0c, 0x2fc);
219 outb(0,0x61);
220 outb(0,0x461);
221 }
222
223 static inline void handle_irq(int irq, struct pt_regs * regs)
224 {
225 struct irqaction * action = irq + irq_action;
226
227 kstat.interrupts[irq]++;
228 if (!action->handler) {
229 unexpected_irq(irq, regs);
230 return;
231 }
232 action->handler(irq, regs);
233 }
234
235 #ifndef CONFIG_PCI
236
237 static void local_device_interrupt(unsigned long vector, struct pt_regs * regs)
238 {
239 switch (vector) {
240
241 case 0x900:
242 handle_irq(4, regs);
243 return;
244
245
246 case 0x920:
247 handle_irq(3, regs);
248 return;
249
250
251 case 0x980:
252 handle_irq(1, regs);
253 return;
254
255
256 case 0x990:
257 handle_irq(9, regs);
258 return;
259 default:
260 printk("Unknown local interrupt %lx\n", vector);
261 }
262 }
263
264 #endif
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288 static void device_interrupt(unsigned long vector, struct pt_regs * regs)
289 {
290 int irq, ack;
291 struct irqaction * action;
292
293 if (vector == 0x660) {
294 handle_nmi(regs);
295 return;
296 }
297
298 ack = irq = (vector - 0x800) >> 4;
299 #ifndef CONFIG_PCI
300 if (vector >= 0x900) {
301 local_device_interrupt(vector, regs);
302 return;
303 }
304
305 if (irq == 1)
306 irq = 7;
307 #endif
308 kstat.interrupts[irq]++;
309 action = irq_action + irq;
310
311 if (action->flags & SA_INTERRUPT) {
312 action->handler(irq, regs);
313 ack_irq(ack);
314 return;
315 }
316
317
318
319
320
321
322
323
324
325 mask_irq(ack);
326 ack_irq(ack);
327 if (!action->handler)
328 return;
329 action->handler(irq, regs);
330 unmask_irq(ack);
331 }
332
333
334
335
336 unsigned int probe_irq_on(void)
337 {
338 unsigned int i, irqs = 0, irqmask;
339 unsigned long delay;
340
341 for (i = 15; i > 0; i--) {
342 if (!irq_action[i].handler) {
343 enable_irq(i);
344 irqs |= (1 << i);
345 }
346 }
347
348
349 for (delay = jiffies + HZ/10; delay > jiffies; )
350 ;
351
352
353 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int) cache_21;
354 irqs &= ~irqmask;
355 return irqs;
356 }
357
358
359
360
361
362
363 int probe_irq_off(unsigned int irqs)
364 {
365 unsigned int i, irqmask;
366
367 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
368 irqs &= irqmask;
369 if (!irqs)
370 return 0;
371 i = ffz(~irqs);
372 if (irqs != (1 << i))
373 i = -i;
374 return i;
375 }
376
377 static void machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs)
378 {
379 printk("Machine check\n");
380 #ifdef LCA_MEM_ESR
381 printk("esr=%lx, ear=%lx, ioc_stat0=%lx, ioc_stat1=%lx\n",
382 *(unsigned long*)LCA_MEM_ESR, *(unsigned long*)LCA_MEM_EAR,
383 *(unsigned long*)LCA_IOC_STAT0, *(unsigned long*)LCA_IOC_STAT1);
384 #endif
385 }
386
387 asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
388 unsigned long a3, unsigned long a4, unsigned long a5,
389 struct pt_regs regs)
390 {
391 switch (type) {
392 case 0:
393 printk("Interprocessor interrupt? You must be kidding\n");
394 break;
395 case 1:
396
397 handle_irq(0, ®s);
398 return;
399 case 2:
400 machine_check(vector, la_ptr, ®s);
401 break;
402 case 3:
403 device_interrupt(vector, ®s);
404 return;
405 case 4:
406 printk("Performance counter interrupt\n");
407 break;;
408 default:
409 printk("Hardware intr %ld %lx? Huh?\n", type, vector);
410 }
411 printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
412 }
413
414 extern asmlinkage void entInt(void);
415
416 void init_IRQ(void)
417 {
418 wrent(entInt, 0);
419 dma_outb(0, DMA1_RESET_REG);
420 dma_outb(0, DMA2_RESET_REG);
421 dma_outb(0, DMA1_CLR_MASK_REG);
422 dma_outb(0, DMA2_CLR_MASK_REG);
423 }