/root/src/xen/xen/arch/x86/i8259.c
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * i8259.c |
3 | | * |
4 | | * Well, this is required for SMP systems as well, as it build interrupt |
5 | | * tables for IO APICS as well as uniprocessor 8259-alikes. |
6 | | */ |
7 | | |
8 | | #include <xen/init.h> |
9 | | #include <xen/types.h> |
10 | | #include <asm/regs.h> |
11 | | #include <xen/errno.h> |
12 | | #include <xen/sched.h> |
13 | | #include <xen/irq.h> |
14 | | #include <asm/atomic.h> |
15 | | #include <asm/system.h> |
16 | | #include <asm/io.h> |
17 | | #include <asm/desc.h> |
18 | | #include <xen/bitops.h> |
19 | | #include <xen/delay.h> |
20 | | #include <asm/apic.h> |
21 | | #include <asm/asm_defns.h> |
22 | | #include <io_ports.h> |
23 | | |
24 | | /* |
25 | | * This is the 'legacy' 8259A Programmable Interrupt Controller, |
26 | | * present in the majority of PC/AT boxes. |
27 | | * plus some generic x86 specific things if generic specifics makes |
28 | | * any sense at all. |
29 | | * this file should become arch/i386/kernel/irq.c when the old irq.c |
30 | | * moves to arch independent land |
31 | | */ |
32 | | |
33 | | static DEFINE_SPINLOCK(i8259A_lock); |
34 | | |
35 | | static bool _mask_and_ack_8259A_irq(unsigned int irq); |
36 | | |
37 | | bool bogus_8259A_irq(unsigned int irq) |
38 | 0 | { |
39 | 0 | return _mask_and_ack_8259A_irq(irq); |
40 | 0 | } |
41 | | |
42 | | static void mask_and_ack_8259A_irq(struct irq_desc *desc) |
43 | 9 | { |
44 | 9 | _mask_and_ack_8259A_irq(desc->irq); |
45 | 9 | } |
46 | | |
47 | | static unsigned int startup_8259A_irq(struct irq_desc *desc) |
48 | 1 | { |
49 | 1 | enable_8259A_irq(desc); |
50 | 1 | return 0; /* never anything pending */ |
51 | 1 | } |
52 | | |
53 | | static void end_8259A_irq(struct irq_desc *desc, u8 vector) |
54 | 9 | { |
55 | 9 | if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
56 | 9 | enable_8259A_irq(desc); |
57 | 9 | } |
58 | | |
59 | | static struct hw_interrupt_type __read_mostly i8259A_irq_type = { |
60 | | .typename = "XT-PIC", |
61 | | .startup = startup_8259A_irq, |
62 | | .shutdown = disable_8259A_irq, |
63 | | .enable = enable_8259A_irq, |
64 | | .disable = disable_8259A_irq, |
65 | | .ack = mask_and_ack_8259A_irq, |
66 | | .end = end_8259A_irq |
67 | | }; |
68 | | |
69 | | /* |
70 | | * 8259A PIC functions to handle ISA devices: |
71 | | */ |
72 | | |
73 | 9 | #define aeoi_mode (i8259A_irq_type.ack == disable_8259A_irq) |
74 | | |
75 | | /* |
76 | | * This contains the irq mask for both 8259A irq controllers, |
77 | | */ |
78 | | static unsigned int cached_irq_mask = 0xffff; |
79 | | |
80 | 47 | #define __byte(x,y) (((unsigned char *)&(y))[x]) |
81 | 33 | #define cached_21 (__byte(0,cached_irq_mask)) |
82 | 14 | #define cached_A1 (__byte(1,cached_irq_mask)) |
83 | | |
84 | | /* |
85 | | * Not all IRQs can be routed through the IO-APIC, eg. on certain (older) |
86 | | * boards the timer interrupt is not really connected to any IO-APIC pin, |
87 | | * it's fed to the master 8259A's IR0 line only. |
88 | | * |
89 | | * Any '1' bit in this mask means the IRQ is routed through the IO-APIC. |
90 | | * this 'mixed mode' IRQ handling costs nothing because it's only used |
91 | | * at IRQ setup time. |
92 | | */ |
93 | | unsigned int __read_mostly io_apic_irqs; |
94 | | |
95 | | static void _disable_8259A_irq(unsigned int irq) |
96 | 22 | { |
97 | 22 | unsigned int mask = 1 << irq; |
98 | 22 | unsigned long flags; |
99 | 22 | |
100 | 22 | spin_lock_irqsave(&i8259A_lock, flags); |
101 | 22 | cached_irq_mask |= mask; |
102 | 22 | if (irq & 8) |
103 | 11 | outb(cached_A1,0xA1); |
104 | 22 | else |
105 | 11 | outb(cached_21,0x21); |
106 | 22 | per_cpu(vector_irq, 0)[LEGACY_VECTOR(irq)] = ~irq; |
107 | 22 | spin_unlock_irqrestore(&i8259A_lock, flags); |
108 | 22 | } |
109 | | |
110 | | void disable_8259A_irq(struct irq_desc *desc) |
111 | 22 | { |
112 | 22 | _disable_8259A_irq(desc->irq); |
113 | 22 | } |
114 | | |
115 | | void enable_8259A_irq(struct irq_desc *desc) |
116 | 10 | { |
117 | 10 | unsigned int mask = ~(1 << desc->irq); |
118 | 10 | unsigned long flags; |
119 | 10 | |
120 | 10 | spin_lock_irqsave(&i8259A_lock, flags); |
121 | 10 | cached_irq_mask &= mask; |
122 | 10 | per_cpu(vector_irq, 0)[LEGACY_VECTOR(desc->irq)] = desc->irq; |
123 | 10 | if (desc->irq & 8) |
124 | 0 | outb(cached_A1,0xA1); |
125 | 10 | else |
126 | 10 | outb(cached_21,0x21); |
127 | 10 | spin_unlock_irqrestore(&i8259A_lock, flags); |
128 | 10 | } |
129 | | |
130 | | int i8259A_irq_pending(unsigned int irq) |
131 | 3 | { |
132 | 3 | unsigned int mask = 1<<irq; |
133 | 3 | unsigned long flags; |
134 | 3 | int ret; |
135 | 3 | |
136 | 3 | spin_lock_irqsave(&i8259A_lock, flags); |
137 | 3 | if (irq < 8) |
138 | 2 | ret = inb(0x20) & mask; |
139 | 3 | else |
140 | 1 | ret = inb(0xA0) & (mask >> 8); |
141 | 3 | spin_unlock_irqrestore(&i8259A_lock, flags); |
142 | 3 | |
143 | 3 | return ret; |
144 | 3 | } |
145 | | |
146 | | void mask_8259A(void) |
147 | 1 | { |
148 | 1 | unsigned long flags; |
149 | 1 | |
150 | 1 | spin_lock_irqsave(&i8259A_lock, flags); |
151 | 1 | outb(0xff, 0xA1); |
152 | 1 | outb(0xff, 0x21); |
153 | 1 | spin_unlock_irqrestore(&i8259A_lock, flags); |
154 | 1 | } |
155 | | |
156 | | void unmask_8259A(void) |
157 | 1 | { |
158 | 1 | unsigned long flags; |
159 | 1 | |
160 | 1 | spin_lock_irqsave(&i8259A_lock, flags); |
161 | 1 | outb(cached_A1, 0xA1); |
162 | 1 | outb(cached_21, 0x21); |
163 | 1 | spin_unlock_irqrestore(&i8259A_lock, flags); |
164 | 1 | } |
165 | | |
166 | | /* |
167 | | * This function assumes to be called rarely. Switching between |
168 | | * 8259A registers is slow. |
169 | | * This has to be protected by the irq controller spinlock |
170 | | * before being called. |
171 | | */ |
172 | | static inline int i8259A_irq_real(unsigned int irq) |
173 | 0 | { |
174 | 0 | int value; |
175 | 0 | int irqmask = 1<<irq; |
176 | 0 |
|
177 | 0 | if (irq < 8) { |
178 | 0 | outb(0x0B,0x20); /* ISR register */ |
179 | 0 | value = inb(0x20) & irqmask; |
180 | 0 | outb(0x0A,0x20); /* back to the IRR register */ |
181 | 0 | return value; |
182 | 0 | } |
183 | 0 | outb(0x0B,0xA0); /* ISR register */ |
184 | 0 | value = inb(0xA0) & (irqmask >> 8); |
185 | 0 | outb(0x0A,0xA0); /* back to the IRR register */ |
186 | 0 | return value; |
187 | 0 | } |
188 | | |
189 | | /* |
190 | | * Careful! The 8259A is a fragile beast, it pretty |
191 | | * much _has_ to be done exactly like this (mask it |
192 | | * first, _then_ send the EOI, and the order of EOI |
193 | | * to the two 8259s is important! Return a boolean |
194 | | * indicating whether the irq was genuine or spurious. |
195 | | */ |
196 | | static bool _mask_and_ack_8259A_irq(unsigned int irq) |
197 | 9 | { |
198 | 9 | unsigned int irqmask = 1 << irq; |
199 | 9 | unsigned long flags; |
200 | 9 | bool is_real_irq = true; /* Assume real unless spurious */ |
201 | 9 | |
202 | 9 | spin_lock_irqsave(&i8259A_lock, flags); |
203 | 9 | |
204 | 9 | /* |
205 | 9 | * Lightweight spurious IRQ detection. We do not want |
206 | 9 | * to overdo spurious IRQ handling - it's usually a sign |
207 | 9 | * of hardware problems, so we only do the checks we can |
208 | 9 | * do without slowing down good hardware unnecesserily. |
209 | 9 | * |
210 | 9 | * Note that IRQ7 and IRQ15 (the two spurious IRQs |
211 | 9 | * usually resulting from the 8259A-1|2 PICs) occur |
212 | 9 | * even if the IRQ is masked in the 8259A. Thus we |
213 | 9 | * can check spurious 8259A IRQs without doing the |
214 | 9 | * quite slow i8259A_irq_real() call for every IRQ. |
215 | 9 | * This does not cover 100% of spurious interrupts, |
216 | 9 | * but should be enough to warn the user that there |
217 | 9 | * is something bad going on ... |
218 | 9 | */ |
219 | 9 | if ((cached_irq_mask & irqmask) && !i8259A_irq_real(irq)) { |
220 | 0 | static int spurious_irq_mask; |
221 | 0 | is_real_irq = false; |
222 | 0 | /* Report spurious IRQ, once per IRQ line. */ |
223 | 0 | if (!(spurious_irq_mask & irqmask)) { |
224 | 0 | printk("spurious 8259A interrupt: IRQ%d.\n", irq); |
225 | 0 | spurious_irq_mask |= irqmask; |
226 | 0 | } |
227 | 0 | /* |
228 | 0 | * Theoretically we do not have to handle this IRQ, |
229 | 0 | * but in Linux this does not cause problems and is |
230 | 0 | * simpler for us. |
231 | 0 | */ |
232 | 0 | } |
233 | 9 | |
234 | 9 | cached_irq_mask |= irqmask; |
235 | 9 | |
236 | 9 | if (irq & 8) { |
237 | 0 | inb(0xA1); /* DUMMY - (do we need this?) */ |
238 | 0 | outb(cached_A1,0xA1); |
239 | 0 | if (!aeoi_mode) { |
240 | 0 | outb(0x60 + (irq & 7), 0xA0);/* 'Specific EOI' to slave */ |
241 | 0 | outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */ |
242 | 0 | } |
243 | 9 | } else { |
244 | 9 | inb(0x21); /* DUMMY - (do we need this?) */ |
245 | 9 | outb(cached_21,0x21); |
246 | 9 | if (!aeoi_mode) |
247 | 9 | outb(0x60 + irq, 0x20);/* 'Specific EOI' to master */ |
248 | 9 | } |
249 | 9 | |
250 | 9 | spin_unlock_irqrestore(&i8259A_lock, flags); |
251 | 9 | |
252 | 9 | return is_real_irq; |
253 | 9 | } |
254 | | |
255 | | static char irq_trigger[2]; |
256 | | /** |
257 | | * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ |
258 | | */ |
259 | | static void restore_ELCR(char *trigger) |
260 | 0 | { |
261 | 0 | outb(trigger[0], 0x4d0); |
262 | 0 | outb(trigger[1], 0x4d1); |
263 | 0 | } |
264 | | |
265 | | static void save_ELCR(char *trigger) |
266 | 0 | { |
267 | 0 | /* IRQ 0,1,2,8,13 are marked as reserved */ |
268 | 0 | trigger[0] = inb(0x4d0) & 0xF8; |
269 | 0 | trigger[1] = inb(0x4d1) & 0xDE; |
270 | 0 | } |
271 | | |
272 | | int i8259A_resume(void) |
273 | 0 | { |
274 | 0 | init_8259A(aeoi_mode); |
275 | 0 | restore_ELCR(irq_trigger); |
276 | 0 | return 0; |
277 | 0 | } |
278 | | |
279 | | int i8259A_suspend(void) |
280 | 0 | { |
281 | 0 | save_ELCR(irq_trigger); |
282 | 0 | return 0; |
283 | 0 | } |
284 | | |
285 | | void init_8259A(int auto_eoi) |
286 | 2 | { |
287 | 2 | unsigned long flags; |
288 | 2 | |
289 | 2 | spin_lock_irqsave(&i8259A_lock, flags); |
290 | 2 | |
291 | 2 | outb(0xff, 0x21); /* mask all of 8259A-1 */ |
292 | 2 | outb(0xff, 0xA1); /* mask all of 8259A-2 */ |
293 | 2 | |
294 | 2 | /* |
295 | 2 | * outb_p - this has to work on a wide range of PC hardware. |
296 | 2 | */ |
297 | 2 | outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ |
298 | 2 | outb_p(FIRST_LEGACY_VECTOR + 0, 0x21); /* ICW2: 8259A-1 IR0-7 */ |
299 | 2 | outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ |
300 | 2 | if (auto_eoi) |
301 | 1 | outb_p(0x03, 0x21); /* master does Auto EOI */ |
302 | 2 | else |
303 | 1 | outb_p(0x01, 0x21); /* master expects normal EOI */ |
304 | 2 | |
305 | 2 | outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ |
306 | 2 | outb_p(FIRST_LEGACY_VECTOR + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 */ |
307 | 2 | outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ |
308 | 2 | outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode |
309 | 2 | is to be investigated) */ |
310 | 2 | |
311 | 2 | if (auto_eoi) |
312 | 2 | /* |
313 | 2 | * in AEOI mode we just have to mask the interrupt |
314 | 2 | * when acking. |
315 | 2 | */ |
316 | 1 | i8259A_irq_type.ack = disable_8259A_irq; |
317 | 2 | else |
318 | 1 | i8259A_irq_type.ack = mask_and_ack_8259A_irq; |
319 | 2 | |
320 | 2 | udelay(100); /* wait for 8259A to initialize */ |
321 | 2 | |
322 | 2 | outb(cached_21, 0x21); /* restore master IRQ mask */ |
323 | 2 | outb(cached_A1, 0xA1); /* restore slave IRQ mask */ |
324 | 2 | |
325 | 2 | spin_unlock_irqrestore(&i8259A_lock, flags); |
326 | 2 | } |
327 | | |
328 | | void __init make_8259A_irq(unsigned int irq) |
329 | 0 | { |
330 | 0 | io_apic_irqs &= ~(1 << irq); |
331 | 0 | irq_to_desc(irq)->handler = &i8259A_irq_type; |
332 | 0 | } |
333 | | |
334 | | static struct irqaction __read_mostly cascade = { no_action, "cascade", NULL}; |
335 | | |
336 | | void __init init_IRQ(void) |
337 | 1 | { |
338 | 1 | int irq, cpu = smp_processor_id(); |
339 | 1 | |
340 | 1 | init_bsp_APIC(); |
341 | 1 | |
342 | 1 | init_8259A(0); |
343 | 1 | |
344 | 1 | BUG_ON(init_irq_data() < 0); |
345 | 1 | |
346 | 17 | for (irq = 0; platform_legacy_irq(irq); irq++) { |
347 | 16 | struct irq_desc *desc = irq_to_desc(irq); |
348 | 16 | |
349 | 16 | if ( irq == 2 ) /* IRQ2 doesn't exist */ |
350 | 1 | continue; |
351 | 15 | desc->handler = &i8259A_irq_type; |
352 | 15 | per_cpu(vector_irq, cpu)[FIRST_LEGACY_VECTOR + irq] = irq; |
353 | 15 | cpumask_copy(desc->arch.cpu_mask, cpumask_of(cpu)); |
354 | 15 | desc->arch.vector = FIRST_LEGACY_VECTOR + irq; |
355 | 15 | } |
356 | 1 | |
357 | 1 | per_cpu(vector_irq, cpu)[IRQ0_VECTOR] = 0; |
358 | 1 | |
359 | 1 | apic_intr_init(); |
360 | 1 | |
361 | 1 | setup_irq(2, 0, &cascade); |
362 | 1 | } |
363 | | |