diff options
Diffstat (limited to 'arch/i386/kernel/apic.c')
-rw-r--r-- | arch/i386/kernel/apic.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index cf45bed96d08..93df90bbb87e 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c | |||
@@ -211,7 +211,7 @@ void __init connect_bsp_APIC(void) | |||
211 | enable_apic_mode(); | 211 | enable_apic_mode(); |
212 | } | 212 | } |
213 | 213 | ||
214 | void disconnect_bsp_APIC(void) | 214 | void disconnect_bsp_APIC(int virt_wire_setup) |
215 | { | 215 | { |
216 | if (pic_mode) { | 216 | if (pic_mode) { |
217 | /* | 217 | /* |
@@ -225,6 +225,42 @@ void disconnect_bsp_APIC(void) | |||
225 | outb(0x70, 0x22); | 225 | outb(0x70, 0x22); |
226 | outb(0x00, 0x23); | 226 | outb(0x00, 0x23); |
227 | } | 227 | } |
228 | else { | ||
229 | /* Go back to Virtual Wire compatibility mode */ | ||
230 | unsigned long value; | ||
231 | |||
232 | /* For the spurious interrupt use vector F, and enable it */ | ||
233 | value = apic_read(APIC_SPIV); | ||
234 | value &= ~APIC_VECTOR_MASK; | ||
235 | value |= APIC_SPIV_APIC_ENABLED; | ||
236 | value |= 0xf; | ||
237 | apic_write_around(APIC_SPIV, value); | ||
238 | |||
239 | if (!virt_wire_setup) { | ||
240 | /* For LVT0 make it edge triggered, active high, external and enabled */ | ||
241 | value = apic_read(APIC_LVT0); | ||
242 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
243 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
244 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED ); | ||
245 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
246 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); | ||
247 | apic_write_around(APIC_LVT0, value); | ||
248 | } | ||
249 | else { | ||
250 | /* Disable LVT0 */ | ||
251 | apic_write_around(APIC_LVT0, APIC_LVT_MASKED); | ||
252 | } | ||
253 | |||
254 | /* For LVT1 make it edge triggered, active high, nmi and enabled */ | ||
255 | value = apic_read(APIC_LVT1); | ||
256 | value &= ~( | ||
257 | APIC_MODE_MASK | APIC_SEND_PENDING | | ||
258 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
259 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
260 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
261 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | ||
262 | apic_write_around(APIC_LVT1, value); | ||
263 | } | ||
228 | } | 264 | } |
229 | 265 | ||
230 | void disable_local_APIC(void) | 266 | void disable_local_APIC(void) |