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