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
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 char mask;
41 int s = _disable_interrupts();
42
43 mask = 1 << (irq_nr & 7);
44 if (irq_nr < 8) {
45 cache_21 |= mask;
46 outb(cache_21,0x21);
47 _enable_interrupts(s);
48 return;
49 }
50 cache_A1 |= mask;
51 outb(cache_A1,0xA1);
52 _enable_interrupts(s);
53 }
54
55 void enable_irq(unsigned int irq_nr)
56 {
57 unsigned char mask;
58 int s = _disable_interrupts();
59
60 mask = ~(1 << (irq_nr & 7));
61 if (irq_nr < 8) {
62 cache_21 &= mask;
63 outb(cache_21,0x21);
64 _enable_interrupts(s);
65 return;
66 }
67 cache_A1 &= mask;
68 outb(cache_A1,0xA1);
69 _enable_interrupts(s);
70 }
71
72
73
74
75 struct irqaction {
76 void (*handler)(int, struct pt_regs *);
77 unsigned long flags;
78 unsigned long mask;
79 const char *name;
80 int notified;
81 };
82
83 static struct irqaction irq_action[16] = {
84 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
85 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
86 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
87 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
88 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
89 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
90 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
91 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
92 };
93
94 int get_irq_list(char *buf)
95 {
96 int i, len = 0;
97 struct irqaction * action = irq_action;
98
99 for (i = 0 ; i < 16 ; i++, action++) {
100 if (!action->handler)
101 continue;
102 len += sprintf(buf+len, "%2d: %8d %c %s\n",
103 i, kstat.interrupts[i],
104 (action->flags & SA_INTERRUPT) ? '+' : ' ',
105 action->name);
106 }
107 return len;
108 }
109
110 asmlinkage void handle_IRQ(struct pt_regs *regs)
111 {
112 int irq, s;
113 struct irqaction *action;
114 intr_count++;
115
116 outb(0x0C, 0x20);
117 irq = inb(0x20);
118 irq &= 0x07;
119 if (irq == 2)
120 {
121 outb(0x0C, 0xA0);
122 irq = inb(0xA0) & 0x07;
123 irq += 8;
124 }
125
126 if (irq > 7)
127 {
128 outb(cache_A1 | (1<<(irq-7)), 0xA1);
129 outb(0x20, 0xA0);
130
131 outb(0x20, 0x20);
132 } else
133 {
134 outb(cache_21 | (1<<irq), 0x21);
135 outb(0x20, 0x20);
136 }
137 action = irq + irq_action;
138 kstat.interrupts[irq]++;
139 if (action->handler)
140 {
141 action->handler(irq, regs);
142 } else
143 {
144 _printk("Bogus interrupt #%d\n", irq);
145 }
146 if (_disable_interrupts() && !action->notified)
147 {
148 action->notified = 1;
149 printk("*** WARNING! %s handler [IRQ %d] turned interrupts on!\n", action->name, irq);
150 }
151
152 if (irq > 7)
153 {
154 outb(cache_A1, 0xA1);
155 } else
156 {
157 outb(cache_21, 0x21);
158 }
159 intr_count--;
160 }
161
162
163
164
165
166
167
168
169
170
171 void check_irq(void )
172 {
173 int s = _disable_interrupts();
174 unsigned char _a0, _a1, _20, _21;
175 _a1 = inb(0xA1);
176 _21 = inb(0x21);
177 outb(0x0C, 0x20); _20 = inb(0x20);
178 outb(0x0C, 0xA0); _a0 = inb(0xA0);
179 #if 0
180 printk("IRQ 0x20 = %x, 0x21 = %x/%x, 0xA0 = %x, 0xA1 = %x/%x\n",
181 _20, _21, cache_21, _a0, _a1, cache_A1);
182 #endif
183
184
185 outb(0x11, 0x20);
186 outb(0x40, 0x21);
187 outb(0x04, 0x21);
188 outb(0x01, 0x21);
189 outb(0xFF, 0x21);
190 outb(0x00, 0x4D0);
191 outb(0x11, 0xA0);
192 outb(0x48, 0xA1);
193 outb(0x02, 0xA1);
194 outb(0x01, 0xA1);
195 outb(0xFF, 0xA1);
196 outb(0xCF, 0x4D1);
197 outb(cache_A1, 0xA1);
198 outb(cache_21, 0x21);
199 enable_irq(2);
200 _enable_interrupts(s);
201 }
202
203 #define SA_PROBE SA_ONESHOT
204
205 int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
206 unsigned long irqflags, const char * devname)
207 {
208 struct irqaction * action;
209 unsigned long flags;
210
211 #if 0
212 _printk("Request IRQ #%d, Handler: %x\n", irq, handler);
213 cnpause();
214 #endif
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 0
229 if (!(action->flags & SA_PROBE)) {
230 if (action->flags & SA_INTERRUPT)
231 set_intr_gate(0x20+irq,fast_interrupt[irq]);
232 else
233 set_intr_gate(0x20+irq,interrupt[irq]);
234 }
235 #endif
236 if (irq < 8) {
237 cache_21 &= ~(1<<irq);
238 outb(cache_21,0x21);
239 } else {
240 cache_21 &= ~(1<<2);
241 cache_A1 &= ~(1<<(irq-8));
242 outb(cache_21,0x21);
243 outb(cache_A1,0xA1);
244 }
245 restore_flags(flags);
246 return 0;
247 }
248
249 void free_irq(unsigned int irq)
250 {
251 struct irqaction * action = irq + irq_action;
252 unsigned long flags;
253
254 if (irq > 15) {
255 printk("Trying to free IRQ%d\n",irq);
256 return;
257 }
258 if (!action->handler) {
259 printk("Trying to free free IRQ%d\n",irq);
260 return;
261 }
262 save_flags(flags);
263 cli();
264 if (irq < 8) {
265 cache_21 |= 1 << irq;
266 outb(cache_21,0x21);
267 } else {
268 cache_A1 |= 1 << (irq-8);
269 outb(cache_A1,0xA1);
270 }
271 #if 0
272 set_intr_gate(0x20+irq,bad_interrupt[irq]);
273 #endif
274 action->handler = NULL;
275 action->flags = 0;
276 action->mask = 0;
277 action->name = NULL;
278 restore_flags(flags);
279 }
280
281 static void no_action(int cpl, struct pt_regs * regs) { }
282
283 unsigned long probe_irq_on (void)
284 {
285 unsigned int i, irqs = 0, irqmask;
286 unsigned long delay;
287
288
289 for (i = 15; i > 0; i--) {
290 if (!request_irq(i, no_action, SA_PROBE, "probe")) {
291 enable_irq(i);
292 irqs |= (1 << i);
293 }
294 }
295
296
297 for (delay = jiffies + 2; delay > jiffies; );
298
299
300 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
301 for (i = 15; i > 0; i--) {
302 if (irqs & (1 << i) & irqmask) {
303 irqs ^= (1 << i);
304 free_irq(i);
305 }
306 }
307 #ifdef DEBUG
308 printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
309 #endif
310 return irqs;
311 }
312
313 int probe_irq_off (unsigned long irqs)
314 {
315 unsigned int i, irqmask;
316
317 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
318 for (i = 15; i > 0; i--) {
319 if (irqs & (1 << i)) {
320 free_irq(i);
321 }
322 }
323 #ifdef DEBUG
324 printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
325 #endif
326 irqs &= irqmask;
327 if (!irqs)
328 return 0;
329 i = ffz(~irqs);
330 if (irqs != (irqs & (1 << i)))
331 i = -i;
332 return i;
333 }
334
335 void init_IRQ(void)
336 {
337 unsigned long *vme2_ie = (unsigned long *)0xFEFF006C;
338 unsigned long *vme2_ic = (unsigned long *)0xFEFF0074;
339 unsigned long *vme2_il2 = (unsigned long *)0xFEFF007C;
340 unsigned long *vme2_ioc = (unsigned long *)0xFEFF0088;
341 unsigned char *vme2pci_ic = (unsigned char *)0x80802050;
342 unsigned char *ibc_pirq = (unsigned char *)0x80800860;
343 unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
344 int i;
345
346
347 outb_p(0x34,0x43);
348 outb_p(LATCH & 0xff , 0x40);
349 outb(LATCH >> 8 , 0x40);
350 if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
351 printk("Unable to get IRQ2 for cascade\n");
352 request_region(0x20,0x20,"pic1");
353 request_region(0xa0,0x20,"pic2");
354 #if 0
355
356 *vme2_ie = (*vme2_ie & 0xFFFBFFFF) | 0x00040000;
357
358 *vme2_ic = 0xFFFFFFFF;
359
360 *vme2_il2 = (*vme2_il2 & 0xFFFFF0FF) | 0x00000500;
361
362 *vme2_ioc |= 0x00800000;
363 #endif
364
365 *vme2pci_ic |= 0x08;
366
367 ibc_pirq[0] = 0x0A;
368 ibc_pirq[1] = 0x0B;
369 ibc_pirq[2] = 0x0E;
370 ibc_pirq[3] = 0x0F;
371
372 *ibc_pcicon |= 0x20;
373 }
374
375 PCI_irq(int irq)
376 {
377 static short _irq[] = {10, 11, 14, 15};
378 int res = _irq[(irq-1)&0x03];
379 #if 0
380 _printk("PCI IRQ #%d = %d\n", irq, res);
381 #endif
382 return (res);
383 }