aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorPavel Machek <pavel@suse.cz>2008-05-21 05:44:02 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-05-24 10:44:26 -0400
commit21fd5132b223a10bdf17713dd0bf321cbd6471d2 (patch)
tree32e851b6310535e5a61f5398d80d0b07aeac0844 /arch/x86
parent403d8efc94cd02ae36e7db13c4edf1d06d7b7fac (diff)
x86: automatical unification of i8259.c
Make conversion of i8259 very mechanical -- i8259 was generated by diff -D, with too different parts left in i8259_32 and i8259_64.c. Only "by hand" changes were removal of #ifdef from middle of the comment (prevented compilation) and removal of one static to allow splitting into files. Of course, it will need some cleanups now, and those will follow. Signed-of-by: Pavel Machek <pavel@suse.cz>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/i8259.c368
-rw-r--r--arch/x86/kernel/i8259_32.c295
-rw-r--r--arch/x86/kernel/i8259_64.c309
4 files changed, 369 insertions, 605 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 5e618c3b4720..f71a76ef2596 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -18,7 +18,7 @@ CFLAGS_tsc_64.o := $(nostackp)
18obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o 18obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o
19obj-y += traps_$(BITS).o irq_$(BITS).o 19obj-y += traps_$(BITS).o irq_$(BITS).o
20obj-y += time_$(BITS).o ioport.o ldt.o 20obj-y += time_$(BITS).o ioport.o ldt.o
21obj-y += setup_$(BITS).o i8259_$(BITS).o setup.o 21obj-y += setup_$(BITS).o i8259.o i8259_$(BITS).o setup.o
22obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o 22obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
23obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o 23obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
24obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o setup64.o 24obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o setup64.o
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
new file mode 100644
index 000000000000..2decba6b0101
--- /dev/null
+++ b/arch/x86/kernel/i8259.c
@@ -0,0 +1,368 @@
1#ifdef CONFIG_X86_64
2#include <linux/linkage.h>
3#endif /* CONFIG_X86_64 */
4#include <linux/errno.h>
5#include <linux/signal.h>
6#include <linux/sched.h>
7#include <linux/ioport.h>
8#include <linux/interrupt.h>
9#ifdef CONFIG_X86_64
10#include <linux/timex.h>
11#endif /* CONFIG_X86_64 */
12#include <linux/slab.h>
13#include <linux/random.h>
14#include <linux/init.h>
15#include <linux/kernel_stat.h>
16#include <linux/sysdev.h>
17#include <linux/bitops.h>
18
19#ifdef CONFIG_X86_64
20#include <asm/acpi.h>
21#endif /* CONFIG_X86_64 */
22#include <asm/atomic.h>
23#include <asm/system.h>
24#include <asm/io.h>
25#ifndef CONFIG_X86_64
26#include <asm/timer.h>
27#else /* CONFIG_X86_64 */
28#include <asm/hw_irq.h>
29#endif /* CONFIG_X86_64 */
30#include <asm/pgtable.h>
31#include <asm/delay.h>
32#include <asm/desc.h>
33#include <asm/apic.h>
34#ifndef CONFIG_X86_64
35#include <asm/arch_hooks.h>
36#endif /* ! CONFIG_X86_64 */
37#include <asm/i8259.h>
38
39/*
40 * This is the 'legacy' 8259A Programmable Interrupt Controller,
41 * present in the majority of PC/AT boxes.
42 * plus some generic x86 specific things if generic specifics makes
43 * any sense at all.
44 */
45
46static int i8259A_auto_eoi;
47DEFINE_SPINLOCK(i8259A_lock);
48static void mask_and_ack_8259A(unsigned int);
49
50struct irq_chip i8259A_chip = {
51 .name = "XT-PIC",
52 .mask = disable_8259A_irq,
53 .disable = disable_8259A_irq,
54 .unmask = enable_8259A_irq,
55 .mask_ack = mask_and_ack_8259A,
56};
57
58/*
59 * 8259A PIC functions to handle ISA devices:
60 */
61
62/*
63 * This contains the irq mask for both 8259A irq controllers,
64 */
65unsigned int cached_irq_mask = 0xffff;
66
67/*
68 * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
69 * boards the timer interrupt is not really connected to any IO-APIC pin,
70 * it's fed to the master 8259A's IR0 line only.
71 *
72 * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
73 * this 'mixed mode' IRQ handling costs nothing because it's only used
74 * at IRQ setup time.
75 */
76unsigned long io_apic_irqs;
77
78void disable_8259A_irq(unsigned int irq)
79{
80 unsigned int mask = 1 << irq;
81 unsigned long flags;
82
83 spin_lock_irqsave(&i8259A_lock, flags);
84 cached_irq_mask |= mask;
85 if (irq & 8)
86 outb(cached_slave_mask, PIC_SLAVE_IMR);
87 else
88 outb(cached_master_mask, PIC_MASTER_IMR);
89 spin_unlock_irqrestore(&i8259A_lock, flags);
90}
91
92void enable_8259A_irq(unsigned int irq)
93{
94 unsigned int mask = ~(1 << irq);
95 unsigned long flags;
96
97 spin_lock_irqsave(&i8259A_lock, flags);
98 cached_irq_mask &= mask;
99 if (irq & 8)
100 outb(cached_slave_mask, PIC_SLAVE_IMR);
101 else
102 outb(cached_master_mask, PIC_MASTER_IMR);
103 spin_unlock_irqrestore(&i8259A_lock, flags);
104}
105
106int i8259A_irq_pending(unsigned int irq)
107{
108 unsigned int mask = 1<<irq;
109 unsigned long flags;
110 int ret;
111
112 spin_lock_irqsave(&i8259A_lock, flags);
113 if (irq < 8)
114 ret = inb(PIC_MASTER_CMD) & mask;
115 else
116 ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
117 spin_unlock_irqrestore(&i8259A_lock, flags);
118
119 return ret;
120}
121
122void make_8259A_irq(unsigned int irq)
123{
124 disable_irq_nosync(irq);
125 io_apic_irqs &= ~(1<<irq);
126 set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
127 "XT");
128 enable_irq(irq);
129}
130
131/*
132 * This function assumes to be called rarely. Switching between
133 * 8259A registers is slow.
134 * This has to be protected by the irq controller spinlock
135 * before being called.
136 */
137static inline int i8259A_irq_real(unsigned int irq)
138{
139 int value;
140 int irqmask = 1<<irq;
141
142 if (irq < 8) {
143 outb(0x0B,PIC_MASTER_CMD); /* ISR register */
144 value = inb(PIC_MASTER_CMD) & irqmask;
145 outb(0x0A,PIC_MASTER_CMD); /* back to the IRR register */
146 return value;
147 }
148 outb(0x0B,PIC_SLAVE_CMD); /* ISR register */
149 value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
150 outb(0x0A,PIC_SLAVE_CMD); /* back to the IRR register */
151 return value;
152}
153
154/*
155 * Careful! The 8259A is a fragile beast, it pretty
156 * much _has_ to be done exactly like this (mask it
157 * first, _then_ send the EOI, and the order of EOI
158 * to the two 8259s is important!
159 */
160static void mask_and_ack_8259A(unsigned int irq)
161{
162 unsigned int irqmask = 1 << irq;
163 unsigned long flags;
164
165 spin_lock_irqsave(&i8259A_lock, flags);
166 /*
167 * Lightweight spurious IRQ detection. We do not want
168 * to overdo spurious IRQ handling - it's usually a sign
169 * of hardware problems, so we only do the checks we can
170 * do without slowing down good hardware unnecessarily.
171 *
172 * Note that IRQ7 and IRQ15 (the two spurious IRQs
173 * usually resulting from the 8259A-1|2 PICs) occur
174 * even if the IRQ is masked in the 8259A. Thus we
175 * can check spurious 8259A IRQs without doing the
176 * quite slow i8259A_irq_real() call for every IRQ.
177 * This does not cover 100% of spurious interrupts,
178 * but should be enough to warn the user that there
179 * is something bad going on ...
180 */
181 if (cached_irq_mask & irqmask)
182 goto spurious_8259A_irq;
183 cached_irq_mask |= irqmask;
184
185handle_real_irq:
186 if (irq & 8) {
187 inb(PIC_SLAVE_IMR); /* DUMMY - (do we need this?) */
188 outb(cached_slave_mask, PIC_SLAVE_IMR);
189#ifndef CONFIG_X86_64
190 outb(0x60+(irq&7),PIC_SLAVE_CMD);/* 'Specific EOI' to slave */
191 outb(0x60+PIC_CASCADE_IR,PIC_MASTER_CMD); /* 'Specific EOI' to master-IRQ2 */
192#else /* CONFIG_X86_64 */
193 /* 'Specific EOI' to slave */
194 outb(0x60+(irq&7),PIC_SLAVE_CMD);
195 /* 'Specific EOI' to master-IRQ2 */
196 outb(0x60+PIC_CASCADE_IR,PIC_MASTER_CMD);
197#endif /* CONFIG_X86_64 */
198 } else {
199 inb(PIC_MASTER_IMR); /* DUMMY - (do we need this?) */
200 outb(cached_master_mask, PIC_MASTER_IMR);
201#ifndef CONFIG_X86_64
202 outb(0x60+irq,PIC_MASTER_CMD); /* 'Specific EOI to master */
203#else /* CONFIG_X86_64 */
204 /* 'Specific EOI' to master */
205 outb(0x60+irq,PIC_MASTER_CMD);
206#endif /* CONFIG_X86_64 */
207 }
208 spin_unlock_irqrestore(&i8259A_lock, flags);
209 return;
210
211spurious_8259A_irq:
212 /*
213 * this is the slow path - should happen rarely.
214 */
215 if (i8259A_irq_real(irq))
216 /*
217 * oops, the IRQ _is_ in service according to the
218 * 8259A - not spurious, go handle it.
219 */
220 goto handle_real_irq;
221
222 {
223 static int spurious_irq_mask;
224 /*
225 * At this point we can be sure the IRQ is spurious,
226 * lets ACK and report it. [once per IRQ]
227 */
228 if (!(spurious_irq_mask & irqmask)) {
229#ifndef CONFIG_X86_64
230 printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
231#else /* CONFIG_X86_64 */
232 printk(KERN_DEBUG
233 "spurious 8259A interrupt: IRQ%d.\n", irq);
234#endif /* CONFIG_X86_64 */
235 spurious_irq_mask |= irqmask;
236 }
237 atomic_inc(&irq_err_count);
238 /*
239 * Theoretically we do not have to handle this IRQ,
240 * but in Linux this does not cause problems and is
241 * simpler for us.
242 */
243 goto handle_real_irq;
244 }
245}
246
247static char irq_trigger[2];
248/**
249 * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
250 */
251static void restore_ELCR(char *trigger)
252{
253 outb(trigger[0], 0x4d0);
254 outb(trigger[1], 0x4d1);
255}
256
257static void save_ELCR(char *trigger)
258{
259 /* IRQ 0,1,2,8,13 are marked as reserved */
260 trigger[0] = inb(0x4d0) & 0xF8;
261 trigger[1] = inb(0x4d1) & 0xDE;
262}
263
264static int i8259A_resume(struct sys_device *dev)
265{
266 init_8259A(i8259A_auto_eoi);
267 restore_ELCR(irq_trigger);
268 return 0;
269}
270
271static int i8259A_suspend(struct sys_device *dev, pm_message_t state)
272{
273 save_ELCR(irq_trigger);
274 return 0;
275}
276
277static int i8259A_shutdown(struct sys_device *dev)
278{
279 /* Put the i8259A into a quiescent state that
280 * the kernel initialization code can get it
281 * out of.
282 */
283 outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
284 outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */
285 return 0;
286}
287
288static struct sysdev_class i8259_sysdev_class = {
289 .name = "i8259",
290 .suspend = i8259A_suspend,
291 .resume = i8259A_resume,
292 .shutdown = i8259A_shutdown,
293};
294
295static struct sys_device device_i8259A = {
296 .id = 0,
297 .cls = &i8259_sysdev_class,
298};
299
300static int __init i8259A_init_sysfs(void)
301{
302 int error = sysdev_class_register(&i8259_sysdev_class);
303 if (!error)
304 error = sysdev_register(&device_i8259A);
305 return error;
306}
307
308device_initcall(i8259A_init_sysfs);
309
310void init_8259A(int auto_eoi)
311{
312 unsigned long flags;
313
314 i8259A_auto_eoi = auto_eoi;
315
316 spin_lock_irqsave(&i8259A_lock, flags);
317
318 outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
319 outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
320
321 /*
322 * outb_pic - this has to work on a wide range of PC hardware.
323 */
324 outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
325#ifndef CONFIG_X86_64
326 outb_pic(0x20 + 0, PIC_MASTER_IMR); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
327 outb_pic(1U << PIC_CASCADE_IR, PIC_MASTER_IMR); /* 8259A-1 (the master) has a slave on IR2 */
328#else /* CONFIG_X86_64 */
329 /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */
330 outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);
331 /* 8259A-1 (the master) has a slave on IR2 */
332 outb_pic(0x04, PIC_MASTER_IMR);
333#endif /* CONFIG_X86_64 */
334 if (auto_eoi) /* master does Auto EOI */
335 outb_pic(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
336 else /* master expects normal EOI */
337 outb_pic(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
338
339 outb_pic(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */
340#ifndef CONFIG_X86_64
341 outb_pic(0x20 + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
342 outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR); /* 8259A-2 is a slave on master's IR2 */
343 outb_pic(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */
344#else /* CONFIG_X86_64 */
345 /* ICW2: 8259A-2 IR0-7 mapped to 0x38-0x3f */
346 outb_pic(IRQ8_VECTOR, PIC_SLAVE_IMR);
347 /* 8259A-2 is a slave on master's IR2 */
348 outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR);
349 /* (slave's support for AEOI in flat mode is to be investigated) */
350 outb_pic(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR);
351
352#endif /* CONFIG_X86_64 */
353 if (auto_eoi)
354 /*
355 * In AEOI mode we just have to mask the interrupt
356 * when acking.
357 */
358 i8259A_chip.mask_ack = disable_8259A_irq;
359 else
360 i8259A_chip.mask_ack = mask_and_ack_8259A;
361
362 udelay(100); /* wait for 8259A to initialize */
363
364 outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
365 outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */
366
367 spin_unlock_irqrestore(&i8259A_lock, flags);
368}
diff --git a/arch/x86/kernel/i8259_32.c b/arch/x86/kernel/i8259_32.c
index fe631967d625..d66914287ee1 100644
--- a/arch/x86/kernel/i8259_32.c
+++ b/arch/x86/kernel/i8259_32.c
@@ -21,302 +21,7 @@
21#include <asm/arch_hooks.h> 21#include <asm/arch_hooks.h>
22#include <asm/i8259.h> 22#include <asm/i8259.h>
23 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 */
30
31static int i8259A_auto_eoi;
32DEFINE_SPINLOCK(i8259A_lock);
33static void mask_and_ack_8259A(unsigned int);
34
35static struct irq_chip i8259A_chip = {
36 .name = "XT-PIC",
37 .mask = disable_8259A_irq,
38 .disable = disable_8259A_irq,
39 .unmask = enable_8259A_irq,
40 .mask_ack = mask_and_ack_8259A,
41};
42
43/*
44 * 8259A PIC functions to handle ISA devices:
45 */
46
47/*
48 * This contains the irq mask for both 8259A irq controllers,
49 */
50unsigned int cached_irq_mask = 0xffff;
51
52/*
53 * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
54 * boards the timer interrupt is not really connected to any IO-APIC pin,
55 * it's fed to the master 8259A's IR0 line only.
56 *
57 * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
58 * this 'mixed mode' IRQ handling costs nothing because it's only used
59 * at IRQ setup time.
60 */
61unsigned long io_apic_irqs;
62
63void disable_8259A_irq(unsigned int irq)
64{
65 unsigned int mask = 1 << irq;
66 unsigned long flags;
67
68 spin_lock_irqsave(&i8259A_lock, flags);
69 cached_irq_mask |= mask;
70 if (irq & 8)
71 outb(cached_slave_mask, PIC_SLAVE_IMR);
72 else
73 outb(cached_master_mask, PIC_MASTER_IMR);
74 spin_unlock_irqrestore(&i8259A_lock, flags);
75}
76
77void enable_8259A_irq(unsigned int irq)
78{
79 unsigned int mask = ~(1 << irq);
80 unsigned long flags;
81
82 spin_lock_irqsave(&i8259A_lock, flags);
83 cached_irq_mask &= mask;
84 if (irq & 8)
85 outb(cached_slave_mask, PIC_SLAVE_IMR);
86 else
87 outb(cached_master_mask, PIC_MASTER_IMR);
88 spin_unlock_irqrestore(&i8259A_lock, flags);
89}
90
91int i8259A_irq_pending(unsigned int irq)
92{
93 unsigned int mask = 1<<irq;
94 unsigned long flags;
95 int ret;
96
97 spin_lock_irqsave(&i8259A_lock, flags);
98 if (irq < 8)
99 ret = inb(PIC_MASTER_CMD) & mask;
100 else
101 ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
102 spin_unlock_irqrestore(&i8259A_lock, flags);
103
104 return ret;
105}
106
107void make_8259A_irq(unsigned int irq)
108{
109 disable_irq_nosync(irq);
110 io_apic_irqs &= ~(1<<irq);
111 set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
112 "XT");
113 enable_irq(irq);
114}
115
116/*
117 * This function assumes to be called rarely. Switching between
118 * 8259A registers is slow.
119 * This has to be protected by the irq controller spinlock
120 * before being called.
121 */
122static inline int i8259A_irq_real(unsigned int irq)
123{
124 int value;
125 int irqmask = 1<<irq;
126
127 if (irq < 8) {
128 outb(0x0B,PIC_MASTER_CMD); /* ISR register */
129 value = inb(PIC_MASTER_CMD) & irqmask;
130 outb(0x0A,PIC_MASTER_CMD); /* back to the IRR register */
131 return value;
132 }
133 outb(0x0B,PIC_SLAVE_CMD); /* ISR register */
134 value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
135 outb(0x0A,PIC_SLAVE_CMD); /* back to the IRR register */
136 return value;
137}
138
139/*
140 * Careful! The 8259A is a fragile beast, it pretty
141 * much _has_ to be done exactly like this (mask it
142 * first, _then_ send the EOI, and the order of EOI
143 * to the two 8259s is important!
144 */
145static void mask_and_ack_8259A(unsigned int irq)
146{
147 unsigned int irqmask = 1 << irq;
148 unsigned long flags;
149
150 spin_lock_irqsave(&i8259A_lock, flags);
151 /*
152 * Lightweight spurious IRQ detection. We do not want
153 * to overdo spurious IRQ handling - it's usually a sign
154 * of hardware problems, so we only do the checks we can
155 * do without slowing down good hardware unnecessarily.
156 *
157 * Note that IRQ7 and IRQ15 (the two spurious IRQs
158 * usually resulting from the 8259A-1|2 PICs) occur
159 * even if the IRQ is masked in the 8259A. Thus we
160 * can check spurious 8259A IRQs without doing the
161 * quite slow i8259A_irq_real() call for every IRQ.
162 * This does not cover 100% of spurious interrupts,
163 * but should be enough to warn the user that there
164 * is something bad going on ...
165 */
166 if (cached_irq_mask & irqmask)
167 goto spurious_8259A_irq;
168 cached_irq_mask |= irqmask;
169 24
170handle_real_irq:
171 if (irq & 8) {
172 inb(PIC_SLAVE_IMR); /* DUMMY - (do we need this?) */
173 outb(cached_slave_mask, PIC_SLAVE_IMR);
174 outb(0x60+(irq&7),PIC_SLAVE_CMD);/* 'Specific EOI' to slave */
175 outb(0x60+PIC_CASCADE_IR,PIC_MASTER_CMD); /* 'Specific EOI' to master-IRQ2 */
176 } else {
177 inb(PIC_MASTER_IMR); /* DUMMY - (do we need this?) */
178 outb(cached_master_mask, PIC_MASTER_IMR);
179 outb(0x60+irq,PIC_MASTER_CMD); /* 'Specific EOI to master */
180 }
181 spin_unlock_irqrestore(&i8259A_lock, flags);
182 return;
183
184spurious_8259A_irq:
185 /*
186 * this is the slow path - should happen rarely.
187 */
188 if (i8259A_irq_real(irq))
189 /*
190 * oops, the IRQ _is_ in service according to the
191 * 8259A - not spurious, go handle it.
192 */
193 goto handle_real_irq;
194
195 {
196 static int spurious_irq_mask;
197 /*
198 * At this point we can be sure the IRQ is spurious,
199 * lets ACK and report it. [once per IRQ]
200 */
201 if (!(spurious_irq_mask & irqmask)) {
202 printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
203 spurious_irq_mask |= irqmask;
204 }
205 atomic_inc(&irq_err_count);
206 /*
207 * Theoretically we do not have to handle this IRQ,
208 * but in Linux this does not cause problems and is
209 * simpler for us.
210 */
211 goto handle_real_irq;
212 }
213}
214
215static char irq_trigger[2];
216/**
217 * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
218 */
219static void restore_ELCR(char *trigger)
220{
221 outb(trigger[0], 0x4d0);
222 outb(trigger[1], 0x4d1);
223}
224
225static void save_ELCR(char *trigger)
226{
227 /* IRQ 0,1,2,8,13 are marked as reserved */
228 trigger[0] = inb(0x4d0) & 0xF8;
229 trigger[1] = inb(0x4d1) & 0xDE;
230}
231
232static int i8259A_resume(struct sys_device *dev)
233{
234 init_8259A(i8259A_auto_eoi);
235 restore_ELCR(irq_trigger);
236 return 0;
237}
238
239static int i8259A_suspend(struct sys_device *dev, pm_message_t state)
240{
241 save_ELCR(irq_trigger);
242 return 0;
243}
244
245static int i8259A_shutdown(struct sys_device *dev)
246{
247 /* Put the i8259A into a quiescent state that
248 * the kernel initialization code can get it
249 * out of.
250 */
251 outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
252 outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */
253 return 0;
254}
255
256static struct sysdev_class i8259_sysdev_class = {
257 .name = "i8259",
258 .suspend = i8259A_suspend,
259 .resume = i8259A_resume,
260 .shutdown = i8259A_shutdown,
261};
262
263static struct sys_device device_i8259A = {
264 .id = 0,
265 .cls = &i8259_sysdev_class,
266};
267
268static int __init i8259A_init_sysfs(void)
269{
270 int error = sysdev_class_register(&i8259_sysdev_class);
271 if (!error)
272 error = sysdev_register(&device_i8259A);
273 return error;
274}
275
276device_initcall(i8259A_init_sysfs);
277
278void init_8259A(int auto_eoi)
279{
280 unsigned long flags;
281
282 i8259A_auto_eoi = auto_eoi;
283
284 spin_lock_irqsave(&i8259A_lock, flags);
285
286 outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
287 outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
288
289 /*
290 * outb_pic - this has to work on a wide range of PC hardware.
291 */
292 outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
293 outb_pic(0x20 + 0, PIC_MASTER_IMR); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
294 outb_pic(1U << PIC_CASCADE_IR, PIC_MASTER_IMR); /* 8259A-1 (the master) has a slave on IR2 */
295 if (auto_eoi) /* master does Auto EOI */
296 outb_pic(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
297 else /* master expects normal EOI */
298 outb_pic(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
299
300 outb_pic(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */
301 outb_pic(0x20 + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
302 outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR); /* 8259A-2 is a slave on master's IR2 */
303 outb_pic(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */
304 if (auto_eoi)
305 /*
306 * In AEOI mode we just have to mask the interrupt
307 * when acking.
308 */
309 i8259A_chip.mask_ack = disable_8259A_irq;
310 else
311 i8259A_chip.mask_ack = mask_and_ack_8259A;
312
313 udelay(100); /* wait for 8259A to initialize */
314
315 outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
316 outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */
317
318 spin_unlock_irqrestore(&i8259A_lock, flags);
319}
320 25
321/* 26/*
322 * Note that on a 486, we don't want to do a SIGFPE on an irq13 27 * Note that on a 486, we don't want to do a SIGFPE on an irq13
diff --git a/arch/x86/kernel/i8259_64.c b/arch/x86/kernel/i8259_64.c
index 1870e0e86559..b44095efcf83 100644
--- a/arch/x86/kernel/i8259_64.c
+++ b/arch/x86/kernel/i8259_64.c
@@ -101,315 +101,6 @@ static void (*__initdata interrupt[NR_VECTORS - FIRST_EXTERNAL_VECTOR])(void) =
101#undef IRQ 101#undef IRQ
102#undef IRQLIST_16 102#undef IRQLIST_16
103 103
104/*
105 * This is the 'legacy' 8259A Programmable Interrupt Controller,
106 * present in the majority of PC/AT boxes.
107 * plus some generic x86 specific things if generic specifics makes
108 * any sense at all.
109 * this file should become arch/i386/kernel/irq.c when the old irq.c
110 * moves to arch independent land
111 */
112
113static int i8259A_auto_eoi;
114DEFINE_SPINLOCK(i8259A_lock);
115static void mask_and_ack_8259A(unsigned int);
116
117static struct irq_chip i8259A_chip = {
118 .name = "XT-PIC",
119 .mask = disable_8259A_irq,
120 .disable = disable_8259A_irq,
121 .unmask = enable_8259A_irq,
122 .mask_ack = mask_and_ack_8259A,
123};
124
125/*
126 * 8259A PIC functions to handle ISA devices:
127 */
128
129/*
130 * This contains the irq mask for both 8259A irq controllers,
131 */
132unsigned int cached_irq_mask = 0xffff;
133
134/*
135 * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
136 * boards the timer interrupt is not really connected to any IO-APIC pin,
137 * it's fed to the master 8259A's IR0 line only.
138 *
139 * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
140 * this 'mixed mode' IRQ handling costs nothing because it's only used
141 * at IRQ setup time.
142 */
143unsigned long io_apic_irqs;
144
145void disable_8259A_irq(unsigned int irq)
146{
147 unsigned int mask = 1 << irq;
148 unsigned long flags;
149
150 spin_lock_irqsave(&i8259A_lock, flags);
151 cached_irq_mask |= mask;
152 if (irq & 8)
153 outb(cached_slave_mask, PIC_SLAVE_IMR);
154 else
155 outb(cached_master_mask, PIC_MASTER_IMR);
156 spin_unlock_irqrestore(&i8259A_lock, flags);
157}
158
159void enable_8259A_irq(unsigned int irq)
160{
161 unsigned int mask = ~(1 << irq);
162 unsigned long flags;
163
164 spin_lock_irqsave(&i8259A_lock, flags);
165 cached_irq_mask &= mask;
166 if (irq & 8)
167 outb(cached_slave_mask, PIC_SLAVE_IMR);
168 else
169 outb(cached_master_mask, PIC_MASTER_IMR);
170 spin_unlock_irqrestore(&i8259A_lock, flags);
171}
172
173int i8259A_irq_pending(unsigned int irq)
174{
175 unsigned int mask = 1<<irq;
176 unsigned long flags;
177 int ret;
178
179 spin_lock_irqsave(&i8259A_lock, flags);
180 if (irq < 8)
181 ret = inb(PIC_MASTER_CMD) & mask;
182 else
183 ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
184 spin_unlock_irqrestore(&i8259A_lock, flags);
185
186 return ret;
187}
188
189void make_8259A_irq(unsigned int irq)
190{
191 disable_irq_nosync(irq);
192 io_apic_irqs &= ~(1<<irq);
193 set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
194 "XT");
195 enable_irq(irq);
196}
197
198/*
199 * This function assumes to be called rarely. Switching between
200 * 8259A registers is slow.
201 * This has to be protected by the irq controller spinlock
202 * before being called.
203 */
204static inline int i8259A_irq_real(unsigned int irq)
205{
206 int value;
207 int irqmask = 1<<irq;
208
209 if (irq < 8) {
210 outb(0x0B,PIC_MASTER_CMD); /* ISR register */
211 value = inb(PIC_MASTER_CMD) & irqmask;
212 outb(0x0A,PIC_MASTER_CMD); /* back to the IRR register */
213 return value;
214 }
215 outb(0x0B,PIC_SLAVE_CMD); /* ISR register */
216 value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
217 outb(0x0A,PIC_SLAVE_CMD); /* back to the IRR register */
218 return value;
219}
220
221/*
222 * Careful! The 8259A is a fragile beast, it pretty
223 * much _has_ to be done exactly like this (mask it
224 * first, _then_ send the EOI, and the order of EOI
225 * to the two 8259s is important!
226 */
227static void mask_and_ack_8259A(unsigned int irq)
228{
229 unsigned int irqmask = 1 << irq;
230 unsigned long flags;
231
232 spin_lock_irqsave(&i8259A_lock, flags);
233 /*
234 * Lightweight spurious IRQ detection. We do not want
235 * to overdo spurious IRQ handling - it's usually a sign
236 * of hardware problems, so we only do the checks we can
237 * do without slowing down good hardware unnecessarily.
238 *
239 * Note that IRQ7 and IRQ15 (the two spurious IRQs
240 * usually resulting from the 8259A-1|2 PICs) occur
241 * even if the IRQ is masked in the 8259A. Thus we
242 * can check spurious 8259A IRQs without doing the
243 * quite slow i8259A_irq_real() call for every IRQ.
244 * This does not cover 100% of spurious interrupts,
245 * but should be enough to warn the user that there
246 * is something bad going on ...
247 */
248 if (cached_irq_mask & irqmask)
249 goto spurious_8259A_irq;
250 cached_irq_mask |= irqmask;
251
252handle_real_irq:
253 if (irq & 8) {
254 inb(PIC_SLAVE_IMR); /* DUMMY - (do we need this?) */
255 outb(cached_slave_mask, PIC_SLAVE_IMR);
256 /* 'Specific EOI' to slave */
257 outb(0x60+(irq&7),PIC_SLAVE_CMD);
258 /* 'Specific EOI' to master-IRQ2 */
259 outb(0x60+PIC_CASCADE_IR,PIC_MASTER_CMD);
260 } else {
261 inb(PIC_MASTER_IMR); /* DUMMY - (do we need this?) */
262 outb(cached_master_mask, PIC_MASTER_IMR);
263 /* 'Specific EOI' to master */
264 outb(0x60+irq,PIC_MASTER_CMD);
265 }
266 spin_unlock_irqrestore(&i8259A_lock, flags);
267 return;
268
269spurious_8259A_irq:
270 /*
271 * this is the slow path - should happen rarely.
272 */
273 if (i8259A_irq_real(irq))
274 /*
275 * oops, the IRQ _is_ in service according to the
276 * 8259A - not spurious, go handle it.
277 */
278 goto handle_real_irq;
279
280 {
281 static int spurious_irq_mask;
282 /*
283 * At this point we can be sure the IRQ is spurious,
284 * lets ACK and report it. [once per IRQ]
285 */
286 if (!(spurious_irq_mask & irqmask)) {
287 printk(KERN_DEBUG
288 "spurious 8259A interrupt: IRQ%d.\n", irq);
289 spurious_irq_mask |= irqmask;
290 }
291 atomic_inc(&irq_err_count);
292 /*
293 * Theoretically we do not have to handle this IRQ,
294 * but in Linux this does not cause problems and is
295 * simpler for us.
296 */
297 goto handle_real_irq;
298 }
299}
300
301static char irq_trigger[2];
302/**
303 * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
304 */
305static void restore_ELCR(char *trigger)
306{
307 outb(trigger[0], 0x4d0);
308 outb(trigger[1], 0x4d1);
309}
310
311static void save_ELCR(char *trigger)
312{
313 /* IRQ 0,1,2,8,13 are marked as reserved */
314 trigger[0] = inb(0x4d0) & 0xF8;
315 trigger[1] = inb(0x4d1) & 0xDE;
316}
317
318static int i8259A_resume(struct sys_device *dev)
319{
320 init_8259A(i8259A_auto_eoi);
321 restore_ELCR(irq_trigger);
322 return 0;
323}
324
325static int i8259A_suspend(struct sys_device *dev, pm_message_t state)
326{
327 save_ELCR(irq_trigger);
328 return 0;
329}
330
331static int i8259A_shutdown(struct sys_device *dev)
332{
333 /* Put the i8259A into a quiescent state that
334 * the kernel initialization code can get it
335 * out of.
336 */
337 outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
338 outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */
339 return 0;
340}
341
342static struct sysdev_class i8259_sysdev_class = {
343 .name = "i8259",
344 .suspend = i8259A_suspend,
345 .resume = i8259A_resume,
346 .shutdown = i8259A_shutdown,
347};
348
349static struct sys_device device_i8259A = {
350 .id = 0,
351 .cls = &i8259_sysdev_class,
352};
353
354static int __init i8259A_init_sysfs(void)
355{
356 int error = sysdev_class_register(&i8259_sysdev_class);
357 if (!error)
358 error = sysdev_register(&device_i8259A);
359 return error;
360}
361
362device_initcall(i8259A_init_sysfs);
363
364void init_8259A(int auto_eoi)
365{
366 unsigned long flags;
367
368 i8259A_auto_eoi = auto_eoi;
369
370 spin_lock_irqsave(&i8259A_lock, flags);
371
372 outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
373 outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
374
375 /*
376 * outb_pic - this has to work on a wide range of PC hardware.
377 */
378 outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
379 /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */
380 outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);
381 /* 8259A-1 (the master) has a slave on IR2 */
382 outb_pic(0x04, PIC_MASTER_IMR);
383 if (auto_eoi) /* master does Auto EOI */
384 outb_pic(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
385 else /* master expects normal EOI */
386 outb_pic(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
387
388 outb_pic(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */
389 /* ICW2: 8259A-2 IR0-7 mapped to 0x38-0x3f */
390 outb_pic(IRQ8_VECTOR, PIC_SLAVE_IMR);
391 /* 8259A-2 is a slave on master's IR2 */
392 outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR);
393 /* (slave's support for AEOI in flat mode is to be investigated) */
394 outb_pic(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR);
395
396 if (auto_eoi)
397 /*
398 * In AEOI mode we just have to mask the interrupt
399 * when acking.
400 */
401 i8259A_chip.mask_ack = disable_8259A_irq;
402 else
403 i8259A_chip.mask_ack = mask_and_ack_8259A;
404
405 udelay(100); /* wait for 8259A to initialize */
406
407 outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
408 outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */
409
410 spin_unlock_irqrestore(&i8259A_lock, flags);
411}
412
413 104
414 105
415 106