This source file includes following definitions.
- disable_irq
- enable_irq
- get_irq_list
- do_IRQ
- do_fast_IRQ
- request_irq
- free_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 #include <linux/timex.h>
32
33 #include <asm/system.h>
34 #include <asm/io.h>
35 #include <asm/irq.h>
36 #include <asm/bitops.h>
37
38 unsigned char cache_21 = 0xff;
39 unsigned char cache_A1 = 0xff;
40
41 unsigned long spurious_count = 0;
42
43 void disable_irq(unsigned int irq_nr)
44 {
45 unsigned long flags;
46 unsigned char mask;
47
48 mask = 1 << (irq_nr & 7);
49 save_flags(flags);
50 if (irq_nr < 8) {
51 cli();
52 cache_21 |= mask;
53 outb(cache_21,0x21);
54 restore_flags(flags);
55 return;
56 }
57 cli();
58 cache_A1 |= mask;
59 outb(cache_A1,0xA1);
60 restore_flags(flags);
61 }
62
63 void enable_irq(unsigned int irq_nr)
64 {
65 unsigned long flags;
66 unsigned char mask;
67
68 mask = ~(1 << (irq_nr & 7));
69 save_flags(flags);
70 if (irq_nr < 8) {
71 cli();
72 cache_21 &= mask;
73 outb(cache_21,0x21);
74 restore_flags(flags);
75 return;
76 }
77 cli();
78 cache_A1 &= mask;
79 outb(cache_A1,0xA1);
80 restore_flags(flags);
81 }
82
83
84
85
86
87 extern void interrupt(void);
88 extern void fast_interrupt(void);
89 extern void bad_interrupt(void);
90
91
92
93
94 struct irqaction {
95 void (*handler)(int, struct pt_regs *);
96 unsigned long flags;
97 unsigned long mask;
98 const char *name;
99 };
100
101 static struct irqaction irq_action[16] = {
102 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
103 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
104 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
105 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
106 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
107 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
108 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
109 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
110 };
111
112 int get_irq_list(char *buf)
113 {
114 int i, len = 0;
115 struct irqaction * action = irq_action;
116
117 for (i = 0 ; i < 16 ; i++, action++) {
118 if (!action->handler)
119 continue;
120 len += sprintf(buf+len, "%2d: %8d %c %s\n",
121 i, kstat.interrupts[i],
122 (action->flags & SA_INTERRUPT) ? '+' : ' ',
123 action->name);
124 }
125 return len;
126 }
127
128
129
130
131
132
133
134
135 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
136 {
137 struct irqaction * action = irq + irq_action;
138
139 kstat.interrupts[irq]++;
140 action->handler(irq, regs);
141 }
142
143
144
145
146
147
148 asmlinkage void do_fast_IRQ(int irq)
149 {
150 struct irqaction * action = irq + irq_action;
151
152 kstat.interrupts[irq]++;
153 action->handler(irq, NULL);
154 }
155
156 #define SA_PROBE SA_ONESHOT
157
158 int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
159 unsigned long irqflags, const char * devname)
160 {
161 struct irqaction * action;
162 unsigned long flags;
163
164 if (irq > 15)
165 return -EINVAL;
166 action = irq + irq_action;
167 if (action->handler)
168 return -EBUSY;
169 if (!handler)
170 return -EINVAL;
171 save_flags(flags);
172 cli();
173 action->handler = handler;
174 action->flags = irqflags;
175 action->mask = 0;
176 action->name = devname;
177 if (!(action->flags & SA_PROBE)) {
178
179
180
181 if (action->flags & SA_INTERRUPT)
182 set_intr_gate(irq,fast_interrupt);
183 else
184 set_intr_gate(irq,interrupt);
185 }
186 if (irq < 8) {
187 cache_21 &= ~(1<<irq);
188 outb(cache_21,0x21);
189 } else {
190 cache_21 &= ~(1<<2);
191 cache_A1 &= ~(1<<(irq-8));
192 outb(cache_21,0x21);
193 outb(cache_A1,0xA1);
194 }
195 restore_flags(flags);
196 return 0;
197 }
198
199 void free_irq(unsigned int irq)
200 {
201 struct irqaction * action = irq + irq_action;
202 unsigned long flags;
203
204 if (irq > 15) {
205 printk("Trying to free IRQ%d\n",irq);
206 return;
207 }
208 if (!action->handler) {
209 printk("Trying to free free IRQ%d\n",irq);
210 return;
211 }
212 save_flags(flags);
213 cli();
214 if (irq < 8) {
215 cache_21 |= 1 << irq;
216 outb(cache_21,0x21);
217 } else {
218 cache_A1 |= 1 << (irq-8);
219 outb(cache_A1,0xA1);
220 }
221 set_intr_gate(irq,bad_interrupt);
222 action->handler = NULL;
223 action->flags = 0;
224 action->mask = 0;
225 action->name = NULL;
226 restore_flags(flags);
227 }
228
229 static void no_action(int cpl, struct pt_regs * regs) { }
230
231 unsigned int probe_irq_on (void)
232 {
233 unsigned int i, irqs = 0, irqmask;
234 unsigned long delay;
235
236
237 for (i = 15; i > 0; i--) {
238 if (!request_irq(i, no_action, SA_PROBE, "probe")) {
239 enable_irq(i);
240 irqs |= (1 << i);
241 }
242 }
243
244
245 for (delay = jiffies + 2; delay > jiffies; );
246
247
248 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
249 for (i = 15; i > 0; i--) {
250 if (irqs & (1 << i) & irqmask) {
251 irqs ^= (1 << i);
252 free_irq(i);
253 }
254 }
255 #ifdef DEBUG
256 printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
257 #endif
258 return irqs;
259 }
260
261 int probe_irq_off (unsigned int irqs)
262 {
263 unsigned int i, irqmask;
264
265 irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
266 for (i = 15; i > 0; i--) {
267 if (irqs & (1 << i)) {
268 free_irq(i);
269 }
270 }
271 #ifdef DEBUG
272 printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
273 #endif
274 irqs &= irqmask;
275 if (!irqs)
276 return 0;
277 i = ffz(~irqs);
278 if (irqs != (irqs & (1 << i)))
279 i = -i;
280 return i;
281 }
282
283 void init_IRQ(void)
284 {
285 int i;
286
287
288 outb_p(0x34,0x43);
289 outb_p(LATCH & 0xff , 0x40);
290 outb(LATCH >> 8 , 0x40);
291 for (i = 0; i < 16 ; i++)
292 set_intr_gate(i, bad_interrupt);
293 if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
294 printk("Unable to get IRQ2 for cascade\n");
295
296
297 for (i = 0; i < 32; i++) {
298 bh_base[i].routine = NULL;
299 bh_base[i].data = NULL;
300 }
301 bh_active = 0;
302 intr_count = 0;
303 }