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