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 unsigned char cache_21 = 0xff;
38 unsigned char cache_A1 = 0xff;
39
40 unsigned long spurious_count = 0;
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 extern void interrupt(void);
87 extern void fast_interrupt(void);
88 extern void bad_interrupt(void);
89
90
91
92
93 static struct sigaction irq_sigaction[16] = {
94 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
95 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
96 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
97 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
98 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
99 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
100 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
101 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
102 };
103
104 int get_irq_list(char *buf)
105 {
106 int i, len = 0;
107 struct sigaction * sa = irq_sigaction;
108
109 for (i = 0 ; i < 16 ; i++, sa++) {
110 if (!sa->sa_handler)
111 continue;
112 len += sprintf(buf+len, "%2d: %8d %c %s\n",
113 i, kstat.interrupts[i],
114 (sa->sa_flags & SA_INTERRUPT) ? '+' : ' ',
115 (char *) sa->sa_mask);
116 }
117 return len;
118 }
119
120
121
122
123
124
125
126
127 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
128 {
129 struct sigaction * sa = irq + irq_sigaction;
130
131 kstat.interrupts[irq]++;
132 sa->sa_handler((int) regs);
133 }
134
135
136
137
138
139
140 asmlinkage void do_fast_IRQ(int irq)
141 {
142 struct sigaction * sa = irq + irq_sigaction;
143
144 kstat.interrupts[irq]++;
145 sa->sa_handler(irq);
146 }
147
148 #define SA_PROBE SA_ONESHOT
149
150
151
152
153
154 static int irqaction(unsigned int irq, struct sigaction * new_sa)
155 {
156 struct sigaction * sa;
157 unsigned long flags;
158
159 if (irq > 15)
160 return -EINVAL;
161 sa = irq + irq_sigaction;
162 if (sa->sa_handler)
163 return -EBUSY;
164 if (!new_sa->sa_handler)
165 return -EINVAL;
166 save_flags(flags);
167 cli();
168 *sa = *new_sa;
169
170
171
172 if (!(sa->sa_flags & SA_PROBE)) {
173 if (sa->sa_flags & SA_INTERRUPT)
174 set_intr_gate(irq,fast_interrupt);
175 else
176 set_intr_gate(irq,interrupt);
177 }
178 if (irq < 8) {
179 cache_21 &= ~(1<<irq);
180 outb(cache_21,0x21);
181 } else {
182 cache_21 &= ~(1<<2);
183 cache_A1 &= ~(1<<(irq-8));
184 outb(cache_21,0x21);
185 outb(cache_A1,0xA1);
186 }
187 restore_flags(flags);
188 return 0;
189 }
190
191 int request_irq(unsigned int irq, void (*handler)(int),
192 unsigned long flags, const char * devname)
193 {
194 struct sigaction sa;
195
196 sa.sa_handler = handler;
197 sa.sa_flags = flags;
198 sa.sa_mask = (unsigned long) devname;
199 sa.sa_restorer = NULL;
200 return irqaction(irq,&sa);
201 }
202
203 void free_irq(unsigned int irq)
204 {
205 struct sigaction * sa = irq + irq_sigaction;
206 unsigned long flags;
207
208 if (irq > 15) {
209 printk("Trying to free IRQ%d\n",irq);
210 return;
211 }
212 if (!sa->sa_handler) {
213 printk("Trying to free free IRQ%d\n",irq);
214 return;
215 }
216 save_flags(flags);
217 cli();
218 if (irq < 8) {
219 cache_21 |= 1 << irq;
220 outb(cache_21,0x21);
221 } else {
222 cache_A1 |= 1 << (irq-8);
223 outb(cache_A1,0xA1);
224 }
225 set_intr_gate(irq,bad_interrupt);
226 sa->sa_handler = NULL;
227 sa->sa_flags = 0;
228 sa->sa_mask = 0;
229 sa->sa_restorer = NULL;
230 restore_flags(flags);
231 }
232
233 #if 0
234
235
236
237 static void math_error_irq(int cpl)
238 {
239 if (!hard_math)
240 return;
241 handle_fpe();
242 }
243 #endif
244
245 static void no_action(int cpl) { }
246
247 unsigned int probe_irq_on (void)
248 {
249 unsigned int i, irqs = 0, irqmask;
250 unsigned long delay;
251
252
253 for (i = 15; i > 0; i--) {
254 if (!request_irq(i, no_action, SA_PROBE, "probe")) {
255 enable_irq(i);
256 irqs |= (1 << i);
257 }
258 }
259
260
261 for (delay = jiffies + 2; delay > jiffies; );
262
263
264 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
265 for (i = 15; i > 0; i--) {
266 if (irqs & (1 << i) & irqmask) {
267 irqs ^= (1 << i);
268 free_irq(i);
269 }
270 }
271 #ifdef DEBUG
272 printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
273 #endif
274 return irqs;
275 }
276
277 int probe_irq_off (unsigned int irqs)
278 {
279 unsigned int i, irqmask;
280
281 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
282 for (i = 15; i > 0; i--) {
283 if (irqs & (1 << i)) {
284 free_irq(i);
285 }
286 }
287 #ifdef DEBUG
288 printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
289 #endif
290 irqs &= irqmask;
291 if (!irqs)
292 return 0;
293 i = ffz(~irqs);
294 if (irqs != (irqs & (1 << i)))
295 i = -i;
296 return i;
297 }
298
299 void init_IRQ(void)
300 {
301 int i;
302
303 for (i = 0; i < 16 ; i++)
304 set_intr_gate(i, bad_interrupt);
305 if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
306 printk("Unable to get IRQ2 for cascade\n");
307
308
309 for (i = 0; i < 32; i++) {
310 bh_base[i].routine = NULL;
311 bh_base[i].data = NULL;
312 }
313 bh_active = 0;
314 intr_count = 0;
315 }