This source file includes following definitions.
- disable_irq
- enable_irq
- get_irq_list
- handle_IRQ
- check_irq
- request_irq
- free_irq
- no_action
- probe_irq_on
- probe_irq_off
- init_IRQ
- PCI_irq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <linux/ptrace.h>
20 #include <linux/errno.h>
21 #include <linux/kernel_stat.h>
22 #include <linux/signal.h>
23 #include <linux/sched.h>
24 #include <linux/ioport.h>
25 #include <linux/interrupt.h>
26 #include <linux/timex.h>
27 #include <linux/malloc.h>
28
29 #include <asm/system.h>
30 #include <asm/io.h>
31 #include <asm/irq.h>
32 #include <asm/bitops.h>
33
34 #define CR0_NE 32
35
36 static unsigned char cache_21 = 0xff;
37 static unsigned char cache_A1 = 0xff;
38
39 void disable_irq(unsigned int irq_nr)
40 {
41 unsigned char mask;
42 int s = _disable_interrupts();
43
44 mask = 1 << (irq_nr & 7);
45 if (irq_nr < 8) {
46 cache_21 |= mask;
47 outb(cache_21,0x21);
48 _enable_interrupts(s);
49 return;
50 }
51 cache_A1 |= mask;
52 outb(cache_A1,0xA1);
53 _enable_interrupts(s);
54 }
55
56 void enable_irq(unsigned int irq_nr)
57 {
58 unsigned char mask;
59 int s = _disable_interrupts();
60
61 mask = ~(1 << (irq_nr & 7));
62 if (irq_nr < 8) {
63 cache_21 &= mask;
64 outb(cache_21,0x21);
65 _enable_interrupts(s);
66 return;
67 }
68 cache_A1 &= mask;
69 outb(cache_A1,0xA1);
70 _enable_interrupts(s);
71 }
72
73
74
75
76 static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
77 static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL};
78 static struct irqaction math_irq = { NULL, 0, 0, NULL, NULL, NULL};
79
80 static struct irqaction *irq_action[16] = {
81 NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
82 NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
83 };
84
85 int get_irq_list(char *buf)
86 {
87 int i, len = 0;
88 struct irqaction * action;
89
90 for (i = 0 ; i < 16 ; i++) {
91 action = *(i + irq_action);
92 if (!action)
93 continue;
94 len += sprintf(buf+len, "%2d: %8d %c %s",
95 i, kstat.interrupts[i],
96 (action->flags & SA_INTERRUPT) ? '+' : ' ',
97 action->name);
98 for (action=action->next; action; action = action->next) {
99 len += sprintf(buf+len, ",%s %s",
100 (action->flags & SA_INTERRUPT) ? " +" : "",
101 action->name);
102 }
103 len += sprintf(buf+len, "\n");
104 }
105 return len;
106 }
107
108 asmlinkage void handle_IRQ(struct pt_regs *regs)
109 {
110 int irq, s;
111 struct irqaction * action;
112 intr_count++;
113
114 outb(0x0C, 0x20);
115 irq = inb(0x20);
116 irq &= 0x07;
117 if (irq == 2)
118 {
119 outb(0x0C, 0xA0);
120 irq = inb(0xA0) & 0x07;
121 irq += 8;
122 }
123
124 if (irq > 7)
125 {
126 outb(cache_A1 | (1<<(irq-7)), 0xA1);
127 outb(0x20, 0xA0);
128
129 outb(0x20, 0x20);
130 } else
131 {
132 outb(cache_21 | (1<<irq), 0x21);
133 outb(0x20, 0x20);
134 }
135 action = *(irq + irq_action);
136 kstat.interrupts[irq]++;
137 while (action) {
138 if (action->handler)
139 {
140 action->handler(irq, action->dev_id, regs);
141 } else
142 {
143 _printk("Bogus interrupt #%d\n", irq);
144 }
145 action = action->next;
146 }
147 if (_disable_interrupts() && !action->notified)
148 {
149 action->notified = 1;
150 printk("*** WARNING! %s handler [IRQ %d] turned interrupts on!\n", action->name, irq);
151 }
152
153 if (irq > 7)
154 {
155 outb(cache_A1, 0xA1);
156 } else
157 {
158 outb(cache_21, 0x21);
159 }
160 intr_count--;
161 }
162
163
164
165
166
167
168
169
170
171
172 void check_irq(void )
173 {
174 int s = _disable_interrupts();
175 unsigned char _a0, _a1, _20, _21;
176 _a1 = inb(0xA1);
177 _21 = inb(0x21);
178 outb(0x0C, 0x20); _20 = inb(0x20);
179 outb(0x0C, 0xA0); _a0 = inb(0xA0);
180 #if 0
181 printk("IRQ 0x20 = %x, 0x21 = %x/%x, 0xA0 = %x, 0xA1 = %x/%x\n",
182 _20, _21, cache_21, _a0, _a1, cache_A1);
183 #endif
184
185
186 outb(0x11, 0x20);
187 outb(0x40, 0x21);
188 outb(0x04, 0x21);
189 outb(0x01, 0x21);
190 outb(0xFF, 0x21);
191 outb(0x00, 0x4D0);
192 outb(0x11, 0xA0);
193 outb(0x48, 0xA1);
194 outb(0x02, 0xA1);
195 outb(0x01, 0xA1);
196 outb(0xFF, 0xA1);
197 outb(0xCF, 0x4D1);
198 outb(cache_A1, 0xA1);
199 outb(cache_21, 0x21);
200 enable_irq(2);
201 _enable_interrupts(s);
202 }
203
204 #define SA_PROBE SA_ONESHOT
205
206 int request_irq(unsigned int irq,
207 void (*handler)(int, void *, struct pt_regs *),
208 unsigned long irqflags,
209 const char * devname,
210 void *dev_id)
211 {
212 struct irqaction * action, *tmp = NULL;
213 unsigned long flags;
214
215 #if 0
216 _printk("Request IRQ #%d, Handler: %x\n", irq, handler);
217 cnpause();
218 #endif
219 if (irq > 15)
220 return -EINVAL;
221 if (!handler)
222 return -EINVAL;
223 action = *(irq + irq_action);
224 if (action) {
225 if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
226 for (tmp = action; tmp->next; tmp = tmp->next);
227 } else {
228 return -EBUSY;
229 }
230 if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
231 printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
232 return -EBUSY;
233 }
234 }
235 save_flags(flags);
236 cli();
237 if (irq == 2)
238 action = &cascade_irq;
239 else if (irq == 13)
240 action = &math_irq;
241 else if (irq == TIMER_IRQ)
242 action = &timer_irq;
243 else
244 action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
245
246 if (!action) {
247 restore_flags(flags);
248 return -ENOMEM;
249 }
250
251 action->handler = handler;
252 action->flags = irqflags;
253 action->mask = 0;
254 action->name = devname;
255 action->next = NULL;
256 action->dev_id = dev_id;
257
258 if (tmp) {
259 tmp->next = action;
260 } else {
261 *(irq + irq_action) = action;
262 #if 0
263 if (!(action->flags & SA_PROBE)) {
264 if (action->flags & SA_INTERRUPT)
265 set_intr_gate(0x20+irq,fast_interrupt[irq]);
266 else
267 set_intr_gate(0x20+irq,interrupt[irq]);
268 }
269 #endif
270 if (irq < 8) {
271 cache_21 &= ~(1<<irq);
272 outb(cache_21,0x21);
273 } else {
274 cache_21 &= ~(1<<2);
275 cache_A1 &= ~(1<<(irq-8));
276 outb(cache_21,0x21);
277 outb(cache_A1,0xA1);
278 }
279 }
280 restore_flags(flags);
281 return 0;
282 }
283
284 void free_irq(unsigned int irq, void *dev_id)
285 {
286 struct irqaction * action = *(irq + irq_action);
287 struct irqaction * tmp = NULL;
288 unsigned long flags;
289
290 if (irq > 15) {
291 printk("Trying to free IRQ%d\n",irq);
292 return;
293 }
294 if (!action->handler) {
295 printk("Trying to free free IRQ%d\n",irq);
296 return;
297 }
298 if (dev_id) {
299 for (; action; action = action->next) {
300 if (action->dev_id == dev_id) break;
301 tmp = action;
302 }
303 if (!action) {
304 printk("Trying to free free shared IRQ%d\n",irq);
305 return;
306 }
307 } else if (action->flags & SA_SHIRQ) {
308 printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
309 return;
310 }
311 save_flags(flags);
312 cli();
313 if (action && tmp) {
314 tmp->next = action->next;
315 } else {
316 *(irq + irq_action) = action->next;
317 }
318
319 if ((irq == 2) || (irq == 13) | (irq == TIMER_IRQ))
320 memset(action, 0, sizeof(struct irqaction));
321 else
322 kfree_s(action, sizeof(struct irqaction));
323
324 if (!(*(irq + irq_action))) {
325 if (irq < 8) {
326 cache_21 |= 1 << irq;
327 outb(cache_21,0x21);
328 } else {
329 cache_A1 |= 1 << (irq-8);
330 outb(cache_A1,0xA1);
331 }
332 #if 0
333 set_intr_gate(0x20+irq,bad_interrupt[irq]);
334 #endif
335 }
336
337 restore_flags(flags);
338 }
339
340 static void no_action(int cpl, void *dev_id, struct pt_regs * regs) { }
341
342 unsigned long probe_irq_on (void)
343 {
344 unsigned int i, irqs = 0, irqmask;
345 unsigned long delay;
346
347
348 for (i = 15; i > 0; i--) {
349 if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) {
350 enable_irq(i);
351 irqs |= (1 << i);
352 }
353 }
354
355
356 for (delay = jiffies + 2; delay > jiffies; );
357
358
359 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
360 for (i = 15; i > 0; i--) {
361 if (irqs & (1 << i) & irqmask) {
362 irqs ^= (1 << i);
363 free_irq(i, NULL);
364 }
365 }
366 #ifdef DEBUG
367 printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
368 #endif
369 return irqs;
370 }
371
372 int probe_irq_off (unsigned long irqs)
373 {
374 unsigned int i, irqmask;
375
376 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
377 for (i = 15; i > 0; i--) {
378 if (irqs & (1 << i)) {
379 free_irq(i, NULL);
380 }
381 }
382 #ifdef DEBUG
383 printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
384 #endif
385 irqs &= irqmask;
386 if (!irqs)
387 return 0;
388 i = ffz(~irqs);
389 if (irqs != (irqs & (1 << i)))
390 i = -i;
391 return i;
392 }
393
394 void init_IRQ(void)
395 {
396 unsigned long *vme2_ie = (unsigned long *)0xFEFF006C;
397 unsigned long *vme2_ic = (unsigned long *)0xFEFF0074;
398 unsigned long *vme2_il2 = (unsigned long *)0xFEFF007C;
399 unsigned long *vme2_ioc = (unsigned long *)0xFEFF0088;
400 unsigned char *vme2pci_ic = (unsigned char *)0x80802050;
401 unsigned char *ibc_pirq = (unsigned char *)0x80800860;
402 unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
403 int i;
404
405
406 outb_p(0x34,0x43);
407 outb_p(LATCH & 0xff , 0x40);
408 outb(LATCH >> 8 , 0x40);
409 if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
410 printk("Unable to get IRQ2 for cascade\n");
411 request_region(0x20,0x20,"pic1");
412 request_region(0xa0,0x20,"pic2");
413 #if 0
414
415 *vme2_ie = (*vme2_ie & 0xFFFBFFFF) | 0x00040000;
416
417 *vme2_ic = 0xFFFFFFFF;
418
419 *vme2_il2 = (*vme2_il2 & 0xFFFFF0FF) | 0x00000500;
420
421 *vme2_ioc |= 0x00800000;
422 #endif
423
424 *vme2pci_ic |= 0x08;
425
426 ibc_pirq[0] = 0x0A;
427 ibc_pirq[1] = 0x0B;
428 ibc_pirq[2] = 0x0E;
429 ibc_pirq[3] = 0x0F;
430
431 *ibc_pcicon |= 0x20;
432 }
433
434 PCI_irq(int irq)
435 {
436 static short _irq[] = {10, 11, 14, 15};
437 int res = _irq[(irq-1)&0x03];
438 #if 0
439 _printk("PCI IRQ #%d = %d\n", irq, res);
440 #endif
441 return (res);
442 }