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 static void local_device_interrupt(unsigned long vector, struct pt_regs * regs)
236 {
237 switch (vector) {
238
239 case 0x900:
240 handle_irq(4, regs);
241 return;
242
243
244 case 0x920:
245 handle_irq(3, regs);
246 return;
247
248
249 case 0x980:
250 handle_irq(1, regs);
251 return;
252
253
254 case 0x990:
255 handle_irq(12, regs);
256 return;
257 default:
258 printk("Unknown local interrupt %lx\n", vector);
259 }
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284 static void device_interrupt(unsigned long vector, struct pt_regs * regs)
285 {
286 int irq, ack;
287 struct irqaction * action;
288
289 if (vector == 0x660) {
290 handle_nmi(regs);
291 return;
292 }
293
294 ack = irq = (vector - 0x800) >> 4;
295 #ifndef CONFIG_PCI
296 if (vector >= 0x900) {
297 local_device_interrupt(vector, regs);
298 return;
299 }
300
301 if (irq == 1)
302 irq = 7;
303 #endif
304 kstat.interrupts[irq]++;
305 action = irq_action + irq;
306
307 if (action->flags & SA_INTERRUPT) {
308 action->handler(irq, regs);
309 ack_irq(ack);
310 return;
311 }
312
313
314
315
316
317
318
319
320
321 mask_irq(ack);
322 ack_irq(ack);
323 if (!action->handler)
324 return;
325 action->handler(irq, regs);
326 unmask_irq(ack);
327 }
328
329
330
331
332 unsigned int probe_irq_on(void)
333 {
334 unsigned int i, irqs = 0, irqmask;
335 unsigned long delay;
336
337 for (i = 15; i > 0; i--) {
338 if (!irq_action[i].handler) {
339 enable_irq(i);
340 irqs |= (1 << i);
341 }
342 }
343
344
345 for (delay = jiffies + HZ/10; delay > jiffies; )
346 ;
347
348
349 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int) cache_21;
350 irqs &= ~irqmask;
351 return irqs;
352 }
353
354
355
356
357
358
359 int probe_irq_off(unsigned int irqs)
360 {
361 unsigned int i, irqmask;
362
363 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
364 irqs &= irqmask;
365 if (!irqs)
366 return 0;
367 i = ffz(~irqs);
368 if (irqs != (1 << i))
369 i = -i;
370 return i;
371 }
372
373 static void machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs)
374 {
375 printk("Machine check\n");
376 }
377
378 asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
379 unsigned long a3, unsigned long a4, unsigned long a5,
380 struct pt_regs regs)
381 {
382 switch (type) {
383 case 0:
384 printk("Interprocessor interrupt? You must be kidding\n");
385 break;
386 case 1:
387
388 handle_irq(0, ®s);
389 return;
390 case 2:
391 machine_check(vector, la_ptr, ®s);
392 break;
393 case 3:
394 device_interrupt(vector, ®s);
395 return;
396 case 4:
397 printk("Performance counter interrupt\n");
398 break;;
399 default:
400 printk("Hardware intr %ld %lx? Huh?\n", type, vector);
401 }
402 printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
403 }
404
405 extern asmlinkage void entInt(void);
406
407 void init_IRQ(void)
408 {
409 wrent(entInt, 0);
410 dma_outb(0, DMA1_RESET_REG);
411 dma_outb(0, DMA2_RESET_REG);
412 dma_outb(0, DMA1_CLR_MASK_REG);
413 dma_outb(0, DMA2_CLR_MASK_REG);
414 }