This source file includes following definitions.
- disable_irq
- enable_irq
- get_irq_list
- do_IRQ
- do_fast_IRQ
- request_irq
- free_irq
- math_error_irq
- no_action
- probe_irq_on
- probe_irq_off
- init_IRQ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <linux/ptrace.h>
19 #include <linux/errno.h>
20 #include <linux/kernel_stat.h>
21 #include <linux/signal.h>
22 #include <linux/sched.h>
23 #include <linux/ioport.h>
24 #include <linux/interrupt.h>
25 #include <linux/timex.h>
26 #include <linux/random.h>
27
28 #include <asm/system.h>
29 #include <asm/io.h>
30 #include <asm/irq.h>
31 #include <asm/bitops.h>
32
33 #define CR0_NE 32
34
35 static unsigned char cache_21 = 0xff;
36 static unsigned char cache_A1 = 0xff;
37
38 void disable_irq(unsigned int irq_nr)
39 {
40 unsigned long flags;
41 unsigned char mask;
42
43 mask = 1 << (irq_nr & 7);
44 save_flags(flags);
45 if (irq_nr < 8) {
46 cli();
47 cache_21 |= mask;
48 outb(cache_21,0x21);
49 restore_flags(flags);
50 return;
51 }
52 cli();
53 cache_A1 |= mask;
54 outb(cache_A1,0xA1);
55 restore_flags(flags);
56 }
57
58 void enable_irq(unsigned int irq_nr)
59 {
60 unsigned long flags;
61 unsigned char mask;
62
63 mask = ~(1 << (irq_nr & 7));
64 save_flags(flags);
65 if (irq_nr < 8) {
66 cli();
67 cache_21 &= mask;
68 outb(cache_21,0x21);
69 restore_flags(flags);
70 return;
71 }
72 cli();
73 cache_A1 &= mask;
74 outb(cache_A1,0xA1);
75 restore_flags(flags);
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 BUILD_IRQ(FIRST,0,0x01)
94 BUILD_IRQ(FIRST,1,0x02)
95 BUILD_IRQ(FIRST,2,0x04)
96 BUILD_IRQ(FIRST,3,0x08)
97 BUILD_IRQ(FIRST,4,0x10)
98 BUILD_IRQ(FIRST,5,0x20)
99 BUILD_IRQ(FIRST,6,0x40)
100 BUILD_IRQ(FIRST,7,0x80)
101 BUILD_IRQ(SECOND,8,0x01)
102 BUILD_IRQ(SECOND,9,0x02)
103 BUILD_IRQ(SECOND,10,0x04)
104 BUILD_IRQ(SECOND,11,0x08)
105 BUILD_IRQ(SECOND,12,0x10)
106 BUILD_IRQ(SECOND,13,0x20)
107 BUILD_IRQ(SECOND,14,0x40)
108 BUILD_IRQ(SECOND,15,0x80)
109
110
111
112
113
114 static void (*interrupt[16])(void) = {
115 IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt,
116 IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
117 IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
118 IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt
119 };
120
121 static void (*fast_interrupt[16])(void) = {
122 fast_IRQ0_interrupt, fast_IRQ1_interrupt,
123 fast_IRQ2_interrupt, fast_IRQ3_interrupt,
124 fast_IRQ4_interrupt, fast_IRQ5_interrupt,
125 fast_IRQ6_interrupt, fast_IRQ7_interrupt,
126 fast_IRQ8_interrupt, fast_IRQ9_interrupt,
127 fast_IRQ10_interrupt, fast_IRQ11_interrupt,
128 fast_IRQ12_interrupt, fast_IRQ13_interrupt,
129 fast_IRQ14_interrupt, fast_IRQ15_interrupt
130 };
131
132 static void (*bad_interrupt[16])(void) = {
133 bad_IRQ0_interrupt, bad_IRQ1_interrupt,
134 bad_IRQ2_interrupt, bad_IRQ3_interrupt,
135 bad_IRQ4_interrupt, bad_IRQ5_interrupt,
136 bad_IRQ6_interrupt, bad_IRQ7_interrupt,
137 bad_IRQ8_interrupt, bad_IRQ9_interrupt,
138 bad_IRQ10_interrupt, bad_IRQ11_interrupt,
139 bad_IRQ12_interrupt, bad_IRQ13_interrupt,
140 bad_IRQ14_interrupt, bad_IRQ15_interrupt
141 };
142
143
144
145
146 struct irqaction {
147 void (*handler)(int, struct pt_regs *);
148 unsigned long flags;
149 unsigned long mask;
150 const char *name;
151 };
152
153 static struct irqaction irq_action[16] = {
154 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
155 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
156 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
157 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
158 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
159 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
160 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
161 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
162 };
163
164 int get_irq_list(char *buf)
165 {
166 int i, len = 0;
167 struct irqaction * action = irq_action;
168
169 for (i = 0 ; i < 16 ; i++, action++) {
170 if (!action->handler)
171 continue;
172 len += sprintf(buf+len, "%2d: %8d %c %s\n",
173 i, kstat.interrupts[i],
174 (action->flags & SA_INTERRUPT) ? '+' : ' ',
175 action->name);
176 }
177 return len;
178 }
179
180
181
182
183
184
185
186
187 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
188 {
189 struct irqaction * action = irq + irq_action;
190
191 kstat.interrupts[irq]++;
192 #ifdef CONFIG_RANDOM
193 if (action->flags & SA_SAMPLE_RANDOM)
194 add_interrupt_randomness(irq);
195 #endif
196 action->handler(irq, regs);
197 }
198
199
200
201
202
203
204 asmlinkage void do_fast_IRQ(int irq)
205 {
206 struct irqaction * action = irq + irq_action;
207
208 kstat.interrupts[irq]++;
209 #ifdef CONFIG_RANDOM
210 if (action->flags & SA_SAMPLE_RANDOM)
211 add_interrupt_randomness(irq);
212 #endif
213 action->handler(irq, NULL);
214 }
215
216 #define SA_PROBE SA_ONESHOT
217
218 int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
219 unsigned long irqflags, const char * devname)
220 {
221 struct irqaction * action;
222 unsigned long flags;
223
224 if (irq > 15)
225 return -EINVAL;
226 action = irq + irq_action;
227 if (action->handler)
228 return -EBUSY;
229 if (!handler)
230 return -EINVAL;
231 save_flags(flags);
232 cli();
233 action->handler = handler;
234 action->flags = irqflags;
235 action->mask = 0;
236 action->name = devname;
237 if (!(action->flags & SA_PROBE)) {
238 if (action->flags & SA_INTERRUPT)
239 set_intr_gate(0x20+irq,fast_interrupt[irq]);
240 else
241 set_intr_gate(0x20+irq,interrupt[irq]);
242 }
243 if (irq < 8) {
244 cache_21 &= ~(1<<irq);
245 outb(cache_21,0x21);
246 } else {
247 cache_21 &= ~(1<<2);
248 cache_A1 &= ~(1<<(irq-8));
249 outb(cache_21,0x21);
250 outb(cache_A1,0xA1);
251 }
252 restore_flags(flags);
253 return 0;
254 }
255
256 void free_irq(unsigned int irq)
257 {
258 struct irqaction * action = irq + irq_action;
259 unsigned long flags;
260
261 if (irq > 15) {
262 printk("Trying to free IRQ%d\n",irq);
263 return;
264 }
265 if (!action->handler) {
266 printk("Trying to free free IRQ%d\n",irq);
267 return;
268 }
269 save_flags(flags);
270 cli();
271 if (irq < 8) {
272 cache_21 |= 1 << irq;
273 outb(cache_21,0x21);
274 } else {
275 cache_A1 |= 1 << (irq-8);
276 outb(cache_A1,0xA1);
277 }
278 set_intr_gate(0x20+irq,bad_interrupt[irq]);
279 action->handler = NULL;
280 action->flags = 0;
281 action->mask = 0;
282 action->name = NULL;
283 restore_flags(flags);
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297 static void math_error_irq(int cpl, struct pt_regs *regs)
298 {
299 outb(0,0xF0);
300 if (ignore_irq13 || !hard_math)
301 return;
302 math_error();
303 }
304
305 static void no_action(int cpl, struct pt_regs * regs) { }
306
307 unsigned long probe_irq_on (void)
308 {
309 unsigned int i, irqs = 0, irqmask;
310 unsigned long delay;
311
312
313 for (i = 15; i > 0; i--) {
314 if (!request_irq(i, no_action, SA_PROBE, "probe")) {
315 enable_irq(i);
316 irqs |= (1 << i);
317 }
318 }
319
320
321 for (delay = jiffies + 2; delay > jiffies; );
322
323
324 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
325 for (i = 15; i > 0; i--) {
326 if (irqs & (1 << i) & irqmask) {
327 irqs ^= (1 << i);
328 free_irq(i);
329 }
330 }
331 #ifdef DEBUG
332 printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
333 #endif
334 return irqs;
335 }
336
337 int probe_irq_off (unsigned long irqs)
338 {
339 unsigned int i, irqmask;
340
341 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
342 for (i = 15; i > 0; i--) {
343 if (irqs & (1 << i)) {
344 free_irq(i);
345 }
346 }
347 #ifdef DEBUG
348 printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
349 #endif
350 irqs &= irqmask;
351 if (!irqs)
352 return 0;
353 i = ffz(~irqs);
354 if (irqs != (irqs & (1 << i)))
355 i = -i;
356 return i;
357 }
358
359 void init_IRQ(void)
360 {
361 int i;
362
363
364 outb_p(0x34,0x43);
365 outb_p(LATCH & 0xff , 0x40);
366 outb(LATCH >> 8 , 0x40);
367 for (i = 0; i < 16 ; i++)
368 set_intr_gate(0x20+i,bad_interrupt[i]);
369 if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
370 printk("Unable to get IRQ2 for cascade\n");
371 if (request_irq(13,math_error_irq, 0, "math error"))
372 printk("Unable to get IRQ13 for math-error handler\n");
373 request_region(0x20,0x20,"pic1");
374 request_region(0xa0,0x20,"pic2");
375 }