This source file includes following definitions.
- do_IRQ
- do_fast_IRQ
- irqaction
- request_irq
- free_irq
- math_error_irq
- no_action
- 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/signal.h>
28 #include <linux/sched.h>
29
30 #include <asm/system.h>
31 #include <asm/io.h>
32 #include <asm/irq.h>
33
34 void irq13(void);
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 BUILD_IRQ(FIRST,0,0x01)
52 BUILD_IRQ(FIRST,1,0x02)
53 BUILD_IRQ(FIRST,2,0x04)
54 BUILD_IRQ(FIRST,3,0x08)
55 BUILD_IRQ(FIRST,4,0x10)
56 BUILD_IRQ(FIRST,5,0x20)
57 BUILD_IRQ(FIRST,6,0x40)
58 BUILD_IRQ(FIRST,7,0x80)
59 BUILD_IRQ(SECOND,8,0x01)
60 BUILD_IRQ(SECOND,9,0x02)
61 BUILD_IRQ(SECOND,10,0x04)
62 BUILD_IRQ(SECOND,11,0x08)
63 BUILD_IRQ(SECOND,12,0x10)
64 BUILD_IRQ(SECOND,13,0x20)
65 BUILD_IRQ(SECOND,14,0x40)
66 BUILD_IRQ(SECOND,15,0x80)
67
68
69
70
71
72 static void (*interrupt[16])(void) = {
73 IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt,
74 IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
75 IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
76 IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt
77 };
78
79 static void (*fast_interrupt[16])(void) = {
80 fast_IRQ0_interrupt, fast_IRQ1_interrupt,
81 fast_IRQ2_interrupt, fast_IRQ3_interrupt,
82 fast_IRQ4_interrupt, fast_IRQ5_interrupt,
83 fast_IRQ6_interrupt, fast_IRQ7_interrupt,
84 fast_IRQ8_interrupt, fast_IRQ9_interrupt,
85 fast_IRQ10_interrupt, fast_IRQ11_interrupt,
86 fast_IRQ12_interrupt, fast_IRQ13_interrupt,
87 fast_IRQ14_interrupt, fast_IRQ15_interrupt
88 };
89
90 static void (*bad_interrupt[16])(void) = {
91 bad_IRQ0_interrupt, bad_IRQ1_interrupt,
92 bad_IRQ2_interrupt, bad_IRQ3_interrupt,
93 bad_IRQ4_interrupt, bad_IRQ5_interrupt,
94 bad_IRQ6_interrupt, bad_IRQ7_interrupt,
95 bad_IRQ8_interrupt, bad_IRQ9_interrupt,
96 bad_IRQ10_interrupt, bad_IRQ11_interrupt,
97 bad_IRQ12_interrupt, bad_IRQ13_interrupt,
98 bad_IRQ14_interrupt, bad_IRQ15_interrupt
99 };
100
101
102
103
104 static struct sigaction irq_sigaction[16] = {
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 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
111 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
112 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
113 };
114
115
116
117
118
119
120
121
122 int do_IRQ(int irq, struct pt_regs * regs)
123 {
124 struct sigaction * sa = irq + irq_sigaction;
125
126 sa->sa_handler((int) regs);
127 return 0;
128 }
129
130
131
132
133
134
135 int do_fast_IRQ(int irq)
136 {
137 struct sigaction * sa = irq + irq_sigaction;
138
139 sa->sa_handler(0);
140 return 0;
141 }
142
143 int irqaction(unsigned int irq, struct sigaction * new)
144 {
145 struct sigaction * sa;
146 unsigned long flags;
147
148 if (irq > 15)
149 return -EINVAL;
150 sa = irq + irq_sigaction;
151 if (sa->sa_mask)
152 return -EBUSY;
153 if (!new->sa_handler)
154 return -EINVAL;
155 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
156 *sa = *new;
157 sa->sa_mask = 1;
158 if (sa->sa_flags & SA_INTERRUPT)
159 set_intr_gate(0x20+irq,fast_interrupt[irq]);
160 else
161 set_intr_gate(0x20+irq,interrupt[irq]);
162 if (irq < 8)
163 outb(inb_p(0x21) & ~(1<<irq),0x21);
164 else {
165 outb(inb_p(0x21) & ~(1<<2),0x21);
166 outb(inb_p(0xA1) & ~(1<<(irq-8)),0xA1);
167 }
168 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
169 return 0;
170 }
171
172 int request_irq(unsigned int irq, void (*handler)(int))
173 {
174 struct sigaction sa;
175
176 sa.sa_handler = handler;
177 sa.sa_flags = 0;
178 sa.sa_mask = 0;
179 sa.sa_restorer = NULL;
180 return irqaction(irq,&sa);
181 }
182
183 void free_irq(unsigned int irq)
184 {
185 struct sigaction * sa = irq + irq_sigaction;
186 unsigned long flags;
187
188 if (irq > 15) {
189 printk("Trying to free IRQ%d\n",irq);
190 return;
191 }
192 if (!sa->sa_mask) {
193 printk("Trying to free free IRQ%d\n",irq);
194 return;
195 }
196 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
197 if (irq < 8)
198 outb(inb_p(0x21) | (1<<irq),0x21);
199 else
200 outb(inb_p(0xA1) | (1<<(irq-8)),0xA1);
201 set_intr_gate(0x20+irq,bad_interrupt[irq]);
202 sa->sa_handler = NULL;
203 sa->sa_flags = 0;
204 sa->sa_mask = 0;
205 sa->sa_restorer = NULL;
206 __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
207 }
208
209 extern void do_coprocessor_error(long,long);
210
211 static void math_error_irq(int cpl)
212 {
213 outb(0,0xF0);
214 do_coprocessor_error(0,0);
215 }
216
217 static void no_action(int cpl) { }
218
219 static struct sigaction ignore_IRQ = {
220 no_action,
221 0,
222 SA_INTERRUPT,
223 NULL
224 };
225
226 void init_IRQ(void)
227 {
228 int i;
229
230 for (i = 0; i < 16 ; i++)
231 set_intr_gate(0x20+i,bad_interrupt[i]);
232 if (irqaction(2,&ignore_IRQ))
233 printk("Unable to get IRQ2 for cascade\n");
234 if (request_irq(13,math_error_irq))
235 printk("Unable to get IRQ13 for math-error handler\n");
236 }