aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/io_apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r--arch/i386/kernel/io_apic.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 350192d6ab98..eb10bd5da64e 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -91,6 +91,46 @@ static struct irq_pin_list {
91 int apic, pin, next; 91 int apic, pin, next;
92} irq_2_pin[PIN_MAP_SIZE]; 92} irq_2_pin[PIN_MAP_SIZE];
93 93
94struct io_apic {
95 unsigned int index;
96 unsigned int unused[3];
97 unsigned int data;
98};
99
100static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
101{
102 return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
103 + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK);
104}
105
106static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
107{
108 struct io_apic __iomem *io_apic = io_apic_base(apic);
109 writel(reg, &io_apic->index);
110 return readl(&io_apic->data);
111}
112
113static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
114{
115 struct io_apic __iomem *io_apic = io_apic_base(apic);
116 writel(reg, &io_apic->index);
117 writel(value, &io_apic->data);
118}
119
120/*
121 * Re-write a value: to be used for read-modify-write
122 * cycles where the read already set up the index register.
123 *
124 * Older SiS APIC requires we rewrite the index register
125 */
126static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
127{
128 volatile struct io_apic *io_apic = io_apic_base(apic);
129 if (sis_apic_bug)
130 writel(reg, &io_apic->index);
131 writel(value, &io_apic->data);
132}
133
94union entry_union { 134union entry_union {
95 struct { u32 w1, w2; }; 135 struct { u32 w1, w2; };
96 struct IO_APIC_route_entry entry; 136 struct IO_APIC_route_entry entry;