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