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 && irq) {
160 cache_21 &= ~(1<<irq);
161 outb(cache_21,0x21);
162 } else {
163 cache_21 &= ~(1<<2);
164 cache_A1 &= ~(1<<(irq-8));
165 outb(cache_21,0x21);
166 outb(cache_A1,0xA1);
167 }
168 restore_flags(flags);
169 return 0;
170 }
171
172 void free_irq(unsigned int irq)
173 {
174 struct irqaction * action = irq + irq_action;
175 unsigned long flags;
176
177 if (irq > 15) {
178 printk("Trying to free IRQ%d\n", irq);
179 return;
180 }
181 if (!action->handler) {
182 printk("Trying to free free IRQ%d\n", irq);
183 return;
184 }
185 save_flags(flags);
186 cli();
187 mask_irq(irq);
188 action->handler = NULL;
189 action->flags = 0;
190 action->mask = 0;
191 action->name = NULL;
192 restore_flags(flags);
193 }
194
195 static void handle_nmi(struct pt_regs * regs)
196 {
197 printk("Whee.. NMI received. Probable hardware error\n");
198 printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
199 }
200
201 static void unexpected_irq(int irq, struct pt_regs * regs)
202 {
203 int i;
204
205 printk("IO device interrupt, irq = %d\n", irq);
206 printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
207 printk("Expecting: ");
208 for (i = 0; i < 16; i++)
209 if (irq_action[i].handler)
210 printk("[%s:%d] ", irq_action[i].name, i);
211 printk("\n");
212 printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
213 inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
214 outb(0x0c, 0x3fc);
215 outb(0x0c, 0x2fc);
216 outb(0,0x61);
217 outb(0,0x461);
218 }
219
220 static inline void handle_irq(int irq, struct pt_regs * regs)
221 {
222 struct irqaction * action = irq + irq_action;
223
224 kstat.interrupts[irq]++;
225 if (!action->handler) {
226 unexpected_irq(irq, regs);
227 return;
228 }
229 action->handler(irq, regs);
230 }
231
232 static void local_device_interrupt(unsigned long vector, struct pt_regs * regs)
233 {
234 switch (vector) {
235
236 case 0x900:
237 handle_irq(4, regs);
238 return;
239
240
241 case 0x920:
242 handle_irq(3, regs);
243 return;
244
245
246 case 0x980:
247 handle_irq(1, regs);
248 return;
249
250
251 case 0x990:
252 handle_irq(12, regs);
253 return;
254 default:
255 printk("Unknown local interrupt %lx\n", vector);
256 }
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281 static void device_interrupt(unsigned long vector, struct pt_regs * regs)
282 {
283 int irq, ack;
284 struct irqaction * action;
285
286 if (vector == 0x660) {
287 handle_nmi(regs);
288 return;
289 }
290
291 ack = irq = (vector - 0x800) >> 4;
292 #ifndef CONFIG_PCI
293 if (vector >= 0x900) {
294 local_device_interrupt(vector, regs);
295 return;
296 }
297
298 if (irq == 1)
299 irq = 7;
300 #endif
301 printk("%d%d", irq, ack);
302 kstat.interrupts[irq]++;
303 action = irq_action + irq;
304
305 if (action->flags & SA_INTERRUPT) {
306 action->handler(irq, regs);
307 ack_irq(ack);
308 return;
309 }
310
311
312
313
314
315
316
317
318
319 mask_irq(ack);
320 ack_irq(ack);
321 if (!action->handler)
322 return;
323 action->handler(irq, regs);
324 unmask_irq(ack);
325 }
326
327
328
329
330 unsigned int probe_irq_on(void)
331 {
332 unsigned int i, irqs = 0, irqmask;
333 unsigned long delay;
334
335 for (i = 15; i > 0; i--) {
336 if (!irq_action[i].handler) {
337 enable_irq(i);
338 irqs |= (1 << i);
339 }
340 }
341
342
343 for (delay = jiffies + HZ/10; delay > jiffies; )
344 ;
345
346
347 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int) cache_21;
348 irqs &= ~irqmask;
349 return irqs;
350 }
351
352
353
354
355
356
357 int probe_irq_off(unsigned int irqs)
358 {
359 unsigned int i, irqmask;
360
361 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
362 irqs &= irqmask;
363 if (!irqs)
364 return 0;
365 i = ffz(~irqs);
366 if (irqs != (1 << i))
367 i = -i;
368 return i;
369 }
370
371 static void machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs)
372 {
373 printk("Machine check\n");
374 }
375
376 asmlinkage void do_entInt(unsigned long type, unsigned long vector,
377 unsigned long la_ptr, struct pt_regs *regs)
378 {
379 switch (type) {
380 case 0:
381 printk("Interprocessor interrupt? You must be kidding\n");
382 break;
383 case 1:
384
385 handle_irq(0, regs);
386 return;
387 case 2:
388 machine_check(vector, la_ptr, regs);
389 break;
390 case 3:
391 device_interrupt(vector, regs);
392 return;
393 case 4:
394 printk("Performance counter interrupt\n");
395 break;;
396 default:
397 printk("Hardware intr %ld %lx? Huh?\n", type, vector);
398 }
399 printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
400 }
401
402 extern asmlinkage void entInt(void);
403
404 void init_IRQ(void)
405 {
406 wrent(entInt, 0);
407 }