debuggers.hg

view xen/arch/x86/i8259.c @ 3136:f1c44a4d4998

bitkeeper revision 1.1159.1.446 (41a48ee42Omqs3zoJHTZPhLlPx5LUw)

Merge arcadians.cl.cam.ac.uk:/auto/groups/xeno/BK/xen-unstable.bk
into arcadians.cl.cam.ac.uk:/auto/groups/xeno/users/cl349/BK/xen.bk-smp
author cl349@arcadians.cl.cam.ac.uk
date Wed Nov 24 13:38:44 2004 +0000 (2004-11-24)
parents 61a55dee09d8 2754a2ed61c3
children 0a4b76b6b5a0
line source
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 */
8 #include <xen/config.h>
9 #include <xen/init.h>
10 #include <xen/types.h>
11 #include <asm/regs.h>
12 #include <xen/errno.h>
13 #include <xen/sched.h>
14 #include <xen/irq.h>
15 #include <asm/atomic.h>
16 #include <asm/system.h>
17 #include <asm/io.h>
18 #include <asm/desc.h>
19 #include <asm/bitops.h>
20 #include <xen/delay.h>
21 #include <asm/apic.h>
24 /*
25 * Common place to define all x86 IRQ vectors
26 *
27 * This builds up the IRQ handler stubs using some ugly macros in irq.h
28 *
29 * These macros create the low-level assembly IRQ routines that save
30 * register context and call do_IRQ(). do_IRQ() then does all the
31 * operations that are needed to keep the AT (or SMP IOAPIC)
32 * interrupt-controller happy.
33 */
35 BUILD_COMMON_IRQ()
37 #define BI(x,y) \
38 BUILD_IRQ(x##y)
40 #define BUILD_16_IRQS(x) \
41 BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
42 BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
43 BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
44 BI(x,c) BI(x,d) BI(x,e) BI(x,f)
46 /*
47 * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
48 * (these are usually mapped to vectors 0x30-0x3f)
49 */
50 BUILD_16_IRQS(0x0)
52 #ifdef CONFIG_X86_IO_APIC
53 /*
54 * The IO-APIC gives us many more interrupt sources. Most of these
55 * are unused but an SMP system is supposed to have enough memory ...
56 * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
57 * across the spectrum, so we really want to be prepared to get all
58 * of these. Plus, more powerful systems might have more than 64
59 * IO-APIC registers.
60 *
61 * (these are usually mapped into the 0x30-0xff vector range)
62 */
63 BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
64 BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
65 BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
66 BUILD_16_IRQS(0xc)
67 #endif
69 #undef BUILD_16_IRQS
70 #undef BI
73 /*
74 * The following vectors are part of the Linux architecture, there
75 * is no hardware IRQ pin equivalent for them, they are triggered
76 * through the ICC by us (IPIs)
77 */
78 #ifdef CONFIG_SMP
79 BUILD_SMP_INTERRUPT(event_check_interrupt,EVENT_CHECK_VECTOR)
80 BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
81 BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
82 #endif
84 /*
85 * Every pentium local APIC has two 'local interrupts', with a
86 * soft-definable vector attached to both interrupts, one of
87 * which is a timer interrupt, the other one is error counter
88 * overflow. Linux uses the local APIC timer interrupt to get
89 * a much simpler SMP time architecture:
90 */
91 BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
92 BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
93 BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
95 #define IRQ(x,y) \
96 IRQ##x##y##_interrupt
98 #define IRQLIST_16(x) \
99 IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
100 IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
101 IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
102 IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
104 void *interrupt[NR_IRQS] = {
105 IRQLIST_16(0x0),
107 #ifdef CONFIG_X86_IO_APIC
108 IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
109 IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
110 IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
111 IRQLIST_16(0xc)
112 #endif
113 };
115 #undef IRQ
116 #undef IRQLIST_16
118 /*
119 * This is the 'legacy' 8259A Programmable Interrupt Controller,
120 * present in the majority of PC/AT boxes.
121 * plus some generic x86 specific things if generic specifics makes
122 * any sense at all.
123 * this file should become arch/i386/kernel/irq.c when the old irq.c
124 * moves to arch independent land
125 */
127 spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
129 static void end_8259A_irq (unsigned int irq)
130 {
131 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
132 enable_8259A_irq(irq);
133 }
135 #define shutdown_8259A_irq disable_8259A_irq
137 void mask_and_ack_8259A(unsigned int);
139 static unsigned int startup_8259A_irq(unsigned int irq)
140 {
141 enable_8259A_irq(irq);
142 return 0; /* never anything pending */
143 }
145 static struct hw_interrupt_type i8259A_irq_type = {
146 "XT-PIC",
147 startup_8259A_irq,
148 shutdown_8259A_irq,
149 enable_8259A_irq,
150 disable_8259A_irq,
151 mask_and_ack_8259A,
152 end_8259A_irq,
153 NULL
154 };
156 /*
157 * 8259A PIC functions to handle ISA devices:
158 */
160 /*
161 * This contains the irq mask for both 8259A irq controllers,
162 */
163 static unsigned int cached_irq_mask = 0xffff;
165 #define __byte(x,y) (((unsigned char *)&(y))[x])
166 #define cached_21 (__byte(0,cached_irq_mask))
167 #define cached_A1 (__byte(1,cached_irq_mask))
169 /*
170 * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
171 * boards the timer interrupt is not really connected to any IO-APIC pin,
172 * it's fed to the master 8259A's IR0 line only.
173 *
174 * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
175 * this 'mixed mode' IRQ handling costs nothing because it's only used
176 * at IRQ setup time.
177 */
178 unsigned long io_apic_irqs;
180 void disable_8259A_irq(unsigned int irq)
181 {
182 unsigned int mask = 1 << irq;
183 unsigned long flags;
185 spin_lock_irqsave(&i8259A_lock, flags);
186 cached_irq_mask |= mask;
187 if (irq & 8)
188 outb(cached_A1,0xA1);
189 else
190 outb(cached_21,0x21);
191 spin_unlock_irqrestore(&i8259A_lock, flags);
192 }
194 void enable_8259A_irq(unsigned int irq)
195 {
196 unsigned int mask = ~(1 << irq);
197 unsigned long flags;
199 spin_lock_irqsave(&i8259A_lock, flags);
200 cached_irq_mask &= mask;
201 if (irq & 8)
202 outb(cached_A1,0xA1);
203 else
204 outb(cached_21,0x21);
205 spin_unlock_irqrestore(&i8259A_lock, flags);
206 }
208 int i8259A_irq_pending(unsigned int irq)
209 {
210 unsigned int mask = 1<<irq;
211 unsigned long flags;
212 int ret;
214 spin_lock_irqsave(&i8259A_lock, flags);
215 if (irq < 8)
216 ret = inb(0x20) & mask;
217 else
218 ret = inb(0xA0) & (mask >> 8);
219 spin_unlock_irqrestore(&i8259A_lock, flags);
221 return ret;
222 }
224 void make_8259A_irq(unsigned int irq)
225 {
226 disable_irq_nosync(irq);
227 io_apic_irqs &= ~(1<<irq);
228 irq_desc[irq].handler = &i8259A_irq_type;
229 enable_irq(irq);
230 }
232 /*
233 * This function assumes to be called rarely. Switching between
234 * 8259A registers is slow.
235 * This has to be protected by the irq controller spinlock
236 * before being called.
237 */
238 static inline int i8259A_irq_real(unsigned int irq)
239 {
240 int value;
241 int irqmask = 1<<irq;
243 if (irq < 8) {
244 outb(0x0B,0x20); /* ISR register */
245 value = inb(0x20) & irqmask;
246 outb(0x0A,0x20); /* back to the IRR register */
247 return value;
248 }
249 outb(0x0B,0xA0); /* ISR register */
250 value = inb(0xA0) & (irqmask >> 8);
251 outb(0x0A,0xA0); /* back to the IRR register */
252 return value;
253 }
255 /*
256 * Careful! The 8259A is a fragile beast, it pretty
257 * much _has_ to be done exactly like this (mask it
258 * first, _then_ send the EOI, and the order of EOI
259 * to the two 8259s is important!
260 */
261 void mask_and_ack_8259A(unsigned int irq)
262 {
263 unsigned int irqmask = 1 << irq;
264 unsigned long flags;
266 spin_lock_irqsave(&i8259A_lock, flags);
267 /*
268 * Lightweight spurious IRQ detection. We do not want
269 * to overdo spurious IRQ handling - it's usually a sign
270 * of hardware problems, so we only do the checks we can
271 * do without slowing down good hardware unnecesserily.
272 *
273 * Note that IRQ7 and IRQ15 (the two spurious IRQs
274 * usually resulting from the 8259A-1|2 PICs) occur
275 * even if the IRQ is masked in the 8259A. Thus we
276 * can check spurious 8259A IRQs without doing the
277 * quite slow i8259A_irq_real() call for every IRQ.
278 * This does not cover 100% of spurious interrupts,
279 * but should be enough to warn the user that there
280 * is something bad going on ...
281 */
282 if (cached_irq_mask & irqmask)
283 goto spurious_8259A_irq;
284 cached_irq_mask |= irqmask;
286 handle_real_irq:
287 if (irq & 8) {
288 inb(0xA1); /* DUMMY - (do we need this?) */
289 outb(cached_A1,0xA1);
290 outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
291 outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */
292 } else {
293 inb(0x21); /* DUMMY - (do we need this?) */
294 outb(cached_21,0x21);
295 outb(0x60+irq,0x20); /* 'Specific EOI' to master */
296 }
297 spin_unlock_irqrestore(&i8259A_lock, flags);
298 return;
300 spurious_8259A_irq:
301 /*
302 * this is the slow path - should happen rarely.
303 */
304 if (i8259A_irq_real(irq))
305 /*
306 * oops, the IRQ _is_ in service according to the
307 * 8259A - not spurious, go handle it.
308 */
309 goto handle_real_irq;
311 {
312 static int spurious_irq_mask;
313 /*
314 * At this point we can be sure the IRQ is spurious,
315 * lets ACK and report it. [once per IRQ]
316 */
317 if (!(spurious_irq_mask & irqmask)) {
318 printk("spurious 8259A interrupt: IRQ%d.\n", irq);
319 spurious_irq_mask |= irqmask;
320 }
321 atomic_inc(&irq_err_count);
322 /*
323 * Theoretically we do not have to handle this IRQ,
324 * but in Linux this does not cause problems and is
325 * simpler for us.
326 */
327 goto handle_real_irq;
328 }
329 }
331 void __init init_8259A(int auto_eoi)
332 {
333 unsigned long flags;
335 spin_lock_irqsave(&i8259A_lock, flags);
337 outb(0xff, 0x21); /* mask all of 8259A-1 */
338 outb(0xff, 0xA1); /* mask all of 8259A-2 */
340 /*
341 * outb_p - this has to work on a wide range of PC hardware.
342 */
343 outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */
344 outb_p(0x30 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */
345 outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */
346 if (auto_eoi)
347 outb_p(0x03, 0x21); /* master does Auto EOI */
348 else
349 outb_p(0x01, 0x21); /* master expects normal EOI */
351 outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */
352 outb_p(0x30 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x38-0x3f */
353 outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */
354 outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode
355 is to be investigated) */
357 if (auto_eoi)
358 /*
359 * in AEOI mode we just have to mask the interrupt
360 * when acking.
361 */
362 i8259A_irq_type.ack = disable_8259A_irq;
363 else
364 i8259A_irq_type.ack = mask_and_ack_8259A;
366 udelay(100); /* wait for 8259A to initialize */
368 outb(cached_21, 0x21); /* restore master IRQ mask */
369 outb(cached_A1, 0xA1); /* restore slave IRQ mask */
371 spin_unlock_irqrestore(&i8259A_lock, flags);
372 }
374 static struct irqaction cascade = { no_action, "cascade", NULL};
376 void __init init_IRQ(void)
377 {
378 int i;
380 init_bsp_APIC();
382 init_8259A(0);
384 for ( i = 0; i < NR_IRQS; i++ )
385 {
386 irq_desc[i].status = IRQ_DISABLED;
387 irq_desc[i].handler = (i<16) ? &i8259A_irq_type : &no_irq_type;
388 irq_desc[i].action = NULL;
389 irq_desc[i].depth = 1;
390 spin_lock_init(&irq_desc[i].lock);
391 set_intr_gate(FIRST_EXTERNAL_VECTOR+i, interrupt[i]);
392 }
394 #ifdef CONFIG_SMP
395 /*
396 * IRQ0 must be given a fixed assignment and initialized,
397 * because it's used before the IO-APIC is set up.
398 */
399 set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
401 /* Various IPI functions. */
402 set_intr_gate(EVENT_CHECK_VECTOR, event_check_interrupt);
403 set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
404 set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
405 #endif
407 /* Self-generated IPI for local APIC timer. */
408 set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
410 /* IPI vectors for APIC spurious and error interrupts. */
411 set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
412 set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
414 /* Set the clock to HZ Hz */
415 #define CLOCK_TICK_RATE 1193180 /* crystal freq (Hz) */
416 #define LATCH (((CLOCK_TICK_RATE)+(HZ/2))/HZ)
417 outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
418 outb_p(LATCH & 0xff , 0x40); /* LSB */
419 outb(LATCH >> 8 , 0x40); /* MSB */
421 setup_irq(2, &cascade);
422 }