diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/i386/kernel/acpi/boot.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/i386/kernel/acpi/boot.c')
-rw-r--r-- | arch/i386/kernel/acpi/boot.c | 908 |
1 files changed, 908 insertions, 0 deletions
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c new file mode 100644 index 000000000000..9ba0b957d11f --- /dev/null +++ b/arch/i386/kernel/acpi/boot.c | |||
@@ -0,0 +1,908 @@ | |||
1 | /* | ||
2 | * boot.c - Architecture-Specific Low-Level ACPI Boot Support | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | ||
5 | * Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com> | ||
6 | * | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/config.h> | ||
28 | #include <linux/acpi.h> | ||
29 | #include <linux/efi.h> | ||
30 | #include <linux/irq.h> | ||
31 | #include <linux/module.h> | ||
32 | |||
33 | #include <asm/pgtable.h> | ||
34 | #include <asm/io_apic.h> | ||
35 | #include <asm/apic.h> | ||
36 | #include <asm/io.h> | ||
37 | #include <asm/irq.h> | ||
38 | #include <asm/mpspec.h> | ||
39 | |||
40 | #ifdef CONFIG_X86_64 | ||
41 | |||
42 | static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) { } | ||
43 | extern void __init clustered_apic_check(void); | ||
44 | static inline int ioapic_setup_disabled(void) { return 0; } | ||
45 | #include <asm/proto.h> | ||
46 | |||
47 | #else /* X86 */ | ||
48 | |||
49 | #ifdef CONFIG_X86_LOCAL_APIC | ||
50 | #include <mach_apic.h> | ||
51 | #include <mach_mpparse.h> | ||
52 | #endif /* CONFIG_X86_LOCAL_APIC */ | ||
53 | |||
54 | #endif /* X86 */ | ||
55 | |||
56 | #define BAD_MADT_ENTRY(entry, end) ( \ | ||
57 | (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ | ||
58 | ((acpi_table_entry_header *)entry)->length != sizeof(*entry)) | ||
59 | |||
60 | #define PREFIX "ACPI: " | ||
61 | |||
62 | #ifdef CONFIG_ACPI_PCI | ||
63 | int acpi_noirq __initdata; /* skip ACPI IRQ initialization */ | ||
64 | int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */ | ||
65 | #else | ||
66 | int acpi_noirq __initdata = 1; | ||
67 | int acpi_pci_disabled __initdata = 1; | ||
68 | #endif | ||
69 | int acpi_ht __initdata = 1; /* enable HT */ | ||
70 | |||
71 | int acpi_lapic; | ||
72 | int acpi_ioapic; | ||
73 | int acpi_strict; | ||
74 | EXPORT_SYMBOL(acpi_strict); | ||
75 | |||
76 | acpi_interrupt_flags acpi_sci_flags __initdata; | ||
77 | int acpi_sci_override_gsi __initdata; | ||
78 | int acpi_skip_timer_override __initdata; | ||
79 | |||
80 | #ifdef CONFIG_X86_LOCAL_APIC | ||
81 | static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; | ||
82 | #endif | ||
83 | |||
84 | #ifndef __HAVE_ARCH_CMPXCHG | ||
85 | #warning ACPI uses CMPXCHG, i486 and later hardware | ||
86 | #endif | ||
87 | |||
88 | #define MAX_MADT_ENTRIES 256 | ||
89 | u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] = | ||
90 | { [0 ... MAX_MADT_ENTRIES-1] = 0xff }; | ||
91 | EXPORT_SYMBOL(x86_acpiid_to_apicid); | ||
92 | |||
93 | /* -------------------------------------------------------------------------- | ||
94 | Boot-time Configuration | ||
95 | -------------------------------------------------------------------------- */ | ||
96 | |||
97 | /* | ||
98 | * The default interrupt routing model is PIC (8259). This gets | ||
99 | * overriden if IOAPICs are enumerated (below). | ||
100 | */ | ||
101 | enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; | ||
102 | |||
103 | #ifdef CONFIG_X86_64 | ||
104 | |||
105 | /* rely on all ACPI tables being in the direct mapping */ | ||
106 | char *__acpi_map_table(unsigned long phys_addr, unsigned long size) | ||
107 | { | ||
108 | if (!phys_addr || !size) | ||
109 | return NULL; | ||
110 | |||
111 | if (phys_addr < (end_pfn_map << PAGE_SHIFT)) | ||
112 | return __va(phys_addr); | ||
113 | |||
114 | return NULL; | ||
115 | } | ||
116 | |||
117 | #else | ||
118 | |||
119 | /* | ||
120 | * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, | ||
121 | * to map the target physical address. The problem is that set_fixmap() | ||
122 | * provides a single page, and it is possible that the page is not | ||
123 | * sufficient. | ||
124 | * By using this area, we can map up to MAX_IO_APICS pages temporarily, | ||
125 | * i.e. until the next __va_range() call. | ||
126 | * | ||
127 | * Important Safety Note: The fixed I/O APIC page numbers are *subtracted* | ||
128 | * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and | ||
129 | * count idx down while incrementing the phys address. | ||
130 | */ | ||
131 | char *__acpi_map_table(unsigned long phys, unsigned long size) | ||
132 | { | ||
133 | unsigned long base, offset, mapped_size; | ||
134 | int idx; | ||
135 | |||
136 | if (phys + size < 8*1024*1024) | ||
137 | return __va(phys); | ||
138 | |||
139 | offset = phys & (PAGE_SIZE - 1); | ||
140 | mapped_size = PAGE_SIZE - offset; | ||
141 | set_fixmap(FIX_ACPI_END, phys); | ||
142 | base = fix_to_virt(FIX_ACPI_END); | ||
143 | |||
144 | /* | ||
145 | * Most cases can be covered by the below. | ||
146 | */ | ||
147 | idx = FIX_ACPI_END; | ||
148 | while (mapped_size < size) { | ||
149 | if (--idx < FIX_ACPI_BEGIN) | ||
150 | return NULL; /* cannot handle this */ | ||
151 | phys += PAGE_SIZE; | ||
152 | set_fixmap(idx, phys); | ||
153 | mapped_size += PAGE_SIZE; | ||
154 | } | ||
155 | |||
156 | return ((unsigned char *) base + offset); | ||
157 | } | ||
158 | #endif | ||
159 | |||
160 | #ifdef CONFIG_PCI_MMCONFIG | ||
161 | static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) | ||
162 | { | ||
163 | struct acpi_table_mcfg *mcfg; | ||
164 | |||
165 | if (!phys_addr || !size) | ||
166 | return -EINVAL; | ||
167 | |||
168 | mcfg = (struct acpi_table_mcfg *) __acpi_map_table(phys_addr, size); | ||
169 | if (!mcfg) { | ||
170 | printk(KERN_WARNING PREFIX "Unable to map MCFG\n"); | ||
171 | return -ENODEV; | ||
172 | } | ||
173 | |||
174 | if (mcfg->base_reserved) { | ||
175 | printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n"); | ||
176 | return -ENODEV; | ||
177 | } | ||
178 | |||
179 | pci_mmcfg_base_addr = mcfg->base_address; | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | #else | ||
184 | #define acpi_parse_mcfg NULL | ||
185 | #endif /* !CONFIG_PCI_MMCONFIG */ | ||
186 | |||
187 | #ifdef CONFIG_X86_LOCAL_APIC | ||
188 | static int __init | ||
189 | acpi_parse_madt ( | ||
190 | unsigned long phys_addr, | ||
191 | unsigned long size) | ||
192 | { | ||
193 | struct acpi_table_madt *madt = NULL; | ||
194 | |||
195 | if (!phys_addr || !size) | ||
196 | return -EINVAL; | ||
197 | |||
198 | madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size); | ||
199 | if (!madt) { | ||
200 | printk(KERN_WARNING PREFIX "Unable to map MADT\n"); | ||
201 | return -ENODEV; | ||
202 | } | ||
203 | |||
204 | if (madt->lapic_address) { | ||
205 | acpi_lapic_addr = (u64) madt->lapic_address; | ||
206 | |||
207 | printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n", | ||
208 | madt->lapic_address); | ||
209 | } | ||
210 | |||
211 | acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | |||
217 | static int __init | ||
218 | acpi_parse_lapic ( | ||
219 | acpi_table_entry_header *header, const unsigned long end) | ||
220 | { | ||
221 | struct acpi_table_lapic *processor = NULL; | ||
222 | |||
223 | processor = (struct acpi_table_lapic*) header; | ||
224 | |||
225 | if (BAD_MADT_ENTRY(processor, end)) | ||
226 | return -EINVAL; | ||
227 | |||
228 | acpi_table_print_madt_entry(header); | ||
229 | |||
230 | /* no utility in registering a disabled processor */ | ||
231 | if (processor->flags.enabled == 0) | ||
232 | return 0; | ||
233 | |||
234 | x86_acpiid_to_apicid[processor->acpi_id] = processor->id; | ||
235 | |||
236 | mp_register_lapic ( | ||
237 | processor->id, /* APIC ID */ | ||
238 | processor->flags.enabled); /* Enabled? */ | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int __init | ||
244 | acpi_parse_lapic_addr_ovr ( | ||
245 | acpi_table_entry_header *header, const unsigned long end) | ||
246 | { | ||
247 | struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; | ||
248 | |||
249 | lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header; | ||
250 | |||
251 | if (BAD_MADT_ENTRY(lapic_addr_ovr, end)) | ||
252 | return -EINVAL; | ||
253 | |||
254 | acpi_lapic_addr = lapic_addr_ovr->address; | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int __init | ||
260 | acpi_parse_lapic_nmi ( | ||
261 | acpi_table_entry_header *header, const unsigned long end) | ||
262 | { | ||
263 | struct acpi_table_lapic_nmi *lapic_nmi = NULL; | ||
264 | |||
265 | lapic_nmi = (struct acpi_table_lapic_nmi*) header; | ||
266 | |||
267 | if (BAD_MADT_ENTRY(lapic_nmi, end)) | ||
268 | return -EINVAL; | ||
269 | |||
270 | acpi_table_print_madt_entry(header); | ||
271 | |||
272 | if (lapic_nmi->lint != 1) | ||
273 | printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | |||
279 | #endif /*CONFIG_X86_LOCAL_APIC*/ | ||
280 | |||
281 | #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER) | ||
282 | |||
283 | static int __init | ||
284 | acpi_parse_ioapic ( | ||
285 | acpi_table_entry_header *header, const unsigned long end) | ||
286 | { | ||
287 | struct acpi_table_ioapic *ioapic = NULL; | ||
288 | |||
289 | ioapic = (struct acpi_table_ioapic*) header; | ||
290 | |||
291 | if (BAD_MADT_ENTRY(ioapic, end)) | ||
292 | return -EINVAL; | ||
293 | |||
294 | acpi_table_print_madt_entry(header); | ||
295 | |||
296 | mp_register_ioapic ( | ||
297 | ioapic->id, | ||
298 | ioapic->address, | ||
299 | ioapic->global_irq_base); | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * Parse Interrupt Source Override for the ACPI SCI | ||
306 | */ | ||
307 | static void | ||
308 | acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) | ||
309 | { | ||
310 | if (trigger == 0) /* compatible SCI trigger is level */ | ||
311 | trigger = 3; | ||
312 | |||
313 | if (polarity == 0) /* compatible SCI polarity is low */ | ||
314 | polarity = 3; | ||
315 | |||
316 | /* Command-line over-ride via acpi_sci= */ | ||
317 | if (acpi_sci_flags.trigger) | ||
318 | trigger = acpi_sci_flags.trigger; | ||
319 | |||
320 | if (acpi_sci_flags.polarity) | ||
321 | polarity = acpi_sci_flags.polarity; | ||
322 | |||
323 | /* | ||
324 | * mp_config_acpi_legacy_irqs() already setup IRQs < 16 | ||
325 | * If GSI is < 16, this will update its flags, | ||
326 | * else it will create a new mp_irqs[] entry. | ||
327 | */ | ||
328 | mp_override_legacy_irq(gsi, polarity, trigger, gsi); | ||
329 | |||
330 | /* | ||
331 | * stash over-ride to indicate we've been here | ||
332 | * and for later update of acpi_fadt | ||
333 | */ | ||
334 | acpi_sci_override_gsi = gsi; | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | static int __init | ||
339 | acpi_parse_int_src_ovr ( | ||
340 | acpi_table_entry_header *header, const unsigned long end) | ||
341 | { | ||
342 | struct acpi_table_int_src_ovr *intsrc = NULL; | ||
343 | |||
344 | intsrc = (struct acpi_table_int_src_ovr*) header; | ||
345 | |||
346 | if (BAD_MADT_ENTRY(intsrc, end)) | ||
347 | return -EINVAL; | ||
348 | |||
349 | acpi_table_print_madt_entry(header); | ||
350 | |||
351 | if (intsrc->bus_irq == acpi_fadt.sci_int) { | ||
352 | acpi_sci_ioapic_setup(intsrc->global_irq, | ||
353 | intsrc->flags.polarity, intsrc->flags.trigger); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | if (acpi_skip_timer_override && | ||
358 | intsrc->bus_irq == 0 && intsrc->global_irq == 2) { | ||
359 | printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | mp_override_legacy_irq ( | ||
364 | intsrc->bus_irq, | ||
365 | intsrc->flags.polarity, | ||
366 | intsrc->flags.trigger, | ||
367 | intsrc->global_irq); | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | |||
373 | static int __init | ||
374 | acpi_parse_nmi_src ( | ||
375 | acpi_table_entry_header *header, const unsigned long end) | ||
376 | { | ||
377 | struct acpi_table_nmi_src *nmi_src = NULL; | ||
378 | |||
379 | nmi_src = (struct acpi_table_nmi_src*) header; | ||
380 | |||
381 | if (BAD_MADT_ENTRY(nmi_src, end)) | ||
382 | return -EINVAL; | ||
383 | |||
384 | acpi_table_print_madt_entry(header); | ||
385 | |||
386 | /* TBD: Support nimsrc entries? */ | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | #endif /* CONFIG_X86_IO_APIC */ | ||
392 | |||
393 | #ifdef CONFIG_ACPI_BUS | ||
394 | |||
395 | /* | ||
396 | * acpi_pic_sci_set_trigger() | ||
397 | * | ||
398 | * use ELCR to set PIC-mode trigger type for SCI | ||
399 | * | ||
400 | * If a PIC-mode SCI is not recognized or gives spurious IRQ7's | ||
401 | * it may require Edge Trigger -- use "acpi_sci=edge" | ||
402 | * | ||
403 | * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers | ||
404 | * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge. | ||
405 | * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) | ||
406 | * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) | ||
407 | */ | ||
408 | |||
409 | void __init | ||
410 | acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) | ||
411 | { | ||
412 | unsigned int mask = 1 << irq; | ||
413 | unsigned int old, new; | ||
414 | |||
415 | /* Real old ELCR mask */ | ||
416 | old = inb(0x4d0) | (inb(0x4d1) << 8); | ||
417 | |||
418 | /* | ||
419 | * If we use ACPI to set PCI irq's, then we should clear ELCR | ||
420 | * since we will set it correctly as we enable the PCI irq | ||
421 | * routing. | ||
422 | */ | ||
423 | new = acpi_noirq ? old : 0; | ||
424 | |||
425 | /* | ||
426 | * Update SCI information in the ELCR, it isn't in the PCI | ||
427 | * routing tables.. | ||
428 | */ | ||
429 | switch (trigger) { | ||
430 | case 1: /* Edge - clear */ | ||
431 | new &= ~mask; | ||
432 | break; | ||
433 | case 3: /* Level - set */ | ||
434 | new |= mask; | ||
435 | break; | ||
436 | } | ||
437 | |||
438 | if (old == new) | ||
439 | return; | ||
440 | |||
441 | printk(PREFIX "setting ELCR to %04x (from %04x)\n", new, old); | ||
442 | outb(new, 0x4d0); | ||
443 | outb(new >> 8, 0x4d1); | ||
444 | } | ||
445 | |||
446 | |||
447 | #endif /* CONFIG_ACPI_BUS */ | ||
448 | |||
449 | int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | ||
450 | { | ||
451 | #ifdef CONFIG_X86_IO_APIC | ||
452 | if (use_pci_vector() && !platform_legacy_irq(gsi)) | ||
453 | *irq = IO_APIC_VECTOR(gsi); | ||
454 | else | ||
455 | #endif | ||
456 | *irq = gsi; | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low) | ||
461 | { | ||
462 | unsigned int irq; | ||
463 | unsigned int plat_gsi = gsi; | ||
464 | |||
465 | #ifdef CONFIG_PCI | ||
466 | /* | ||
467 | * Make sure all (legacy) PCI IRQs are set as level-triggered. | ||
468 | */ | ||
469 | if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { | ||
470 | extern void eisa_set_level_irq(unsigned int irq); | ||
471 | |||
472 | if (edge_level == ACPI_LEVEL_SENSITIVE) | ||
473 | eisa_set_level_irq(gsi); | ||
474 | } | ||
475 | #endif | ||
476 | |||
477 | #ifdef CONFIG_X86_IO_APIC | ||
478 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { | ||
479 | plat_gsi = mp_register_gsi(gsi, edge_level, active_high_low); | ||
480 | } | ||
481 | #endif | ||
482 | acpi_gsi_to_irq(plat_gsi, &irq); | ||
483 | return irq; | ||
484 | } | ||
485 | EXPORT_SYMBOL(acpi_register_gsi); | ||
486 | |||
487 | /* | ||
488 | * ACPI based hotplug support for CPU | ||
489 | */ | ||
490 | #ifdef CONFIG_ACPI_HOTPLUG_CPU | ||
491 | int | ||
492 | acpi_map_lsapic(acpi_handle handle, int *pcpu) | ||
493 | { | ||
494 | /* TBD */ | ||
495 | return -EINVAL; | ||
496 | } | ||
497 | EXPORT_SYMBOL(acpi_map_lsapic); | ||
498 | |||
499 | |||
500 | int | ||
501 | acpi_unmap_lsapic(int cpu) | ||
502 | { | ||
503 | /* TBD */ | ||
504 | return -EINVAL; | ||
505 | } | ||
506 | EXPORT_SYMBOL(acpi_unmap_lsapic); | ||
507 | #endif /* CONFIG_ACPI_HOTPLUG_CPU */ | ||
508 | |||
509 | static unsigned long __init | ||
510 | acpi_scan_rsdp ( | ||
511 | unsigned long start, | ||
512 | unsigned long length) | ||
513 | { | ||
514 | unsigned long offset = 0; | ||
515 | unsigned long sig_len = sizeof("RSD PTR ") - 1; | ||
516 | |||
517 | /* | ||
518 | * Scan all 16-byte boundaries of the physical memory region for the | ||
519 | * RSDP signature. | ||
520 | */ | ||
521 | for (offset = 0; offset < length; offset += 16) { | ||
522 | if (strncmp((char *) (start + offset), "RSD PTR ", sig_len)) | ||
523 | continue; | ||
524 | return (start + offset); | ||
525 | } | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size) | ||
531 | { | ||
532 | struct acpi_table_sbf *sb; | ||
533 | |||
534 | if (!phys_addr || !size) | ||
535 | return -EINVAL; | ||
536 | |||
537 | sb = (struct acpi_table_sbf *) __acpi_map_table(phys_addr, size); | ||
538 | if (!sb) { | ||
539 | printk(KERN_WARNING PREFIX "Unable to map SBF\n"); | ||
540 | return -ENODEV; | ||
541 | } | ||
542 | |||
543 | sbf_port = sb->sbf_cmos; /* Save CMOS port */ | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | |||
549 | #ifdef CONFIG_HPET_TIMER | ||
550 | |||
551 | static int __init acpi_parse_hpet(unsigned long phys, unsigned long size) | ||
552 | { | ||
553 | struct acpi_table_hpet *hpet_tbl; | ||
554 | |||
555 | if (!phys || !size) | ||
556 | return -EINVAL; | ||
557 | |||
558 | hpet_tbl = (struct acpi_table_hpet *) __acpi_map_table(phys, size); | ||
559 | if (!hpet_tbl) { | ||
560 | printk(KERN_WARNING PREFIX "Unable to map HPET\n"); | ||
561 | return -ENODEV; | ||
562 | } | ||
563 | |||
564 | if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) { | ||
565 | printk(KERN_WARNING PREFIX "HPET timers must be located in " | ||
566 | "memory.\n"); | ||
567 | return -1; | ||
568 | } | ||
569 | |||
570 | #ifdef CONFIG_X86_64 | ||
571 | vxtime.hpet_address = hpet_tbl->addr.addrl | | ||
572 | ((long) hpet_tbl->addr.addrh << 32); | ||
573 | |||
574 | printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", | ||
575 | hpet_tbl->id, vxtime.hpet_address); | ||
576 | #else /* X86 */ | ||
577 | { | ||
578 | extern unsigned long hpet_address; | ||
579 | |||
580 | hpet_address = hpet_tbl->addr.addrl; | ||
581 | printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", | ||
582 | hpet_tbl->id, hpet_address); | ||
583 | } | ||
584 | #endif /* X86 */ | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | #else | ||
589 | #define acpi_parse_hpet NULL | ||
590 | #endif | ||
591 | |||
592 | #ifdef CONFIG_X86_PM_TIMER | ||
593 | extern u32 pmtmr_ioport; | ||
594 | #endif | ||
595 | |||
596 | static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) | ||
597 | { | ||
598 | struct fadt_descriptor_rev2 *fadt = NULL; | ||
599 | |||
600 | fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size); | ||
601 | if(!fadt) { | ||
602 | printk(KERN_WARNING PREFIX "Unable to map FADT\n"); | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | #ifdef CONFIG_ACPI_INTERPRETER | ||
607 | /* initialize sci_int early for INT_SRC_OVR MADT parsing */ | ||
608 | acpi_fadt.sci_int = fadt->sci_int; | ||
609 | #endif | ||
610 | |||
611 | #ifdef CONFIG_X86_PM_TIMER | ||
612 | /* detect the location of the ACPI PM Timer */ | ||
613 | if (fadt->revision >= FADT2_REVISION_ID) { | ||
614 | /* FADT rev. 2 */ | ||
615 | if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO) | ||
616 | return 0; | ||
617 | |||
618 | pmtmr_ioport = fadt->xpm_tmr_blk.address; | ||
619 | } else { | ||
620 | /* FADT rev. 1 */ | ||
621 | pmtmr_ioport = fadt->V1_pm_tmr_blk; | ||
622 | } | ||
623 | if (pmtmr_ioport) | ||
624 | printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport); | ||
625 | #endif | ||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | |||
630 | unsigned long __init | ||
631 | acpi_find_rsdp (void) | ||
632 | { | ||
633 | unsigned long rsdp_phys = 0; | ||
634 | |||
635 | if (efi_enabled) { | ||
636 | if (efi.acpi20) | ||
637 | return __pa(efi.acpi20); | ||
638 | else if (efi.acpi) | ||
639 | return __pa(efi.acpi); | ||
640 | } | ||
641 | /* | ||
642 | * Scan memory looking for the RSDP signature. First search EBDA (low | ||
643 | * memory) paragraphs and then search upper memory (E0000-FFFFF). | ||
644 | */ | ||
645 | rsdp_phys = acpi_scan_rsdp (0, 0x400); | ||
646 | if (!rsdp_phys) | ||
647 | rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF); | ||
648 | |||
649 | return rsdp_phys; | ||
650 | } | ||
651 | |||
652 | #ifdef CONFIG_X86_LOCAL_APIC | ||
653 | /* | ||
654 | * Parse LAPIC entries in MADT | ||
655 | * returns 0 on success, < 0 on error | ||
656 | */ | ||
657 | static int __init | ||
658 | acpi_parse_madt_lapic_entries(void) | ||
659 | { | ||
660 | int count; | ||
661 | |||
662 | /* | ||
663 | * Note that the LAPIC address is obtained from the MADT (32-bit value) | ||
664 | * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). | ||
665 | */ | ||
666 | |||
667 | count = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0); | ||
668 | if (count < 0) { | ||
669 | printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); | ||
670 | return count; | ||
671 | } | ||
672 | |||
673 | mp_register_lapic_address(acpi_lapic_addr); | ||
674 | |||
675 | count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic, | ||
676 | MAX_APICS); | ||
677 | if (!count) { | ||
678 | printk(KERN_ERR PREFIX "No LAPIC entries present\n"); | ||
679 | /* TBD: Cleanup to allow fallback to MPS */ | ||
680 | return -ENODEV; | ||
681 | } | ||
682 | else if (count < 0) { | ||
683 | printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); | ||
684 | /* TBD: Cleanup to allow fallback to MPS */ | ||
685 | return count; | ||
686 | } | ||
687 | |||
688 | count = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0); | ||
689 | if (count < 0) { | ||
690 | printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); | ||
691 | /* TBD: Cleanup to allow fallback to MPS */ | ||
692 | return count; | ||
693 | } | ||
694 | return 0; | ||
695 | } | ||
696 | #endif /* CONFIG_X86_LOCAL_APIC */ | ||
697 | |||
698 | #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER) | ||
699 | /* | ||
700 | * Parse IOAPIC related entries in MADT | ||
701 | * returns 0 on success, < 0 on error | ||
702 | */ | ||
703 | static int __init | ||
704 | acpi_parse_madt_ioapic_entries(void) | ||
705 | { | ||
706 | int count; | ||
707 | |||
708 | /* | ||
709 | * ACPI interpreter is required to complete interrupt setup, | ||
710 | * so if it is off, don't enumerate the io-apics with ACPI. | ||
711 | * If MPS is present, it will handle them, | ||
712 | * otherwise the system will stay in PIC mode | ||
713 | */ | ||
714 | if (acpi_disabled || acpi_noirq) { | ||
715 | return -ENODEV; | ||
716 | } | ||
717 | |||
718 | /* | ||
719 | * if "noapic" boot option, don't look for IO-APICs | ||
720 | */ | ||
721 | if (skip_ioapic_setup) { | ||
722 | printk(KERN_INFO PREFIX "Skipping IOAPIC probe " | ||
723 | "due to 'noapic' option.\n"); | ||
724 | return -ENODEV; | ||
725 | } | ||
726 | |||
727 | count = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS); | ||
728 | if (!count) { | ||
729 | printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); | ||
730 | return -ENODEV; | ||
731 | } | ||
732 | else if (count < 0) { | ||
733 | printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); | ||
734 | return count; | ||
735 | } | ||
736 | |||
737 | count = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS); | ||
738 | if (count < 0) { | ||
739 | printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); | ||
740 | /* TBD: Cleanup to allow fallback to MPS */ | ||
741 | return count; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * If BIOS did not supply an INT_SRC_OVR for the SCI | ||
746 | * pretend we got one so we can set the SCI flags. | ||
747 | */ | ||
748 | if (!acpi_sci_override_gsi) | ||
749 | acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0); | ||
750 | |||
751 | /* Fill in identity legacy mapings where no override */ | ||
752 | mp_config_acpi_legacy_irqs(); | ||
753 | |||
754 | count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS); | ||
755 | if (count < 0) { | ||
756 | printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); | ||
757 | /* TBD: Cleanup to allow fallback to MPS */ | ||
758 | return count; | ||
759 | } | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | #else | ||
764 | static inline int acpi_parse_madt_ioapic_entries(void) | ||
765 | { | ||
766 | return -1; | ||
767 | } | ||
768 | #endif /* !(CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER) */ | ||
769 | |||
770 | |||
771 | static void __init | ||
772 | acpi_process_madt(void) | ||
773 | { | ||
774 | #ifdef CONFIG_X86_LOCAL_APIC | ||
775 | int count, error; | ||
776 | |||
777 | count = acpi_table_parse(ACPI_APIC, acpi_parse_madt); | ||
778 | if (count >= 1) { | ||
779 | |||
780 | /* | ||
781 | * Parse MADT LAPIC entries | ||
782 | */ | ||
783 | error = acpi_parse_madt_lapic_entries(); | ||
784 | if (!error) { | ||
785 | acpi_lapic = 1; | ||
786 | |||
787 | /* | ||
788 | * Parse MADT IO-APIC entries | ||
789 | */ | ||
790 | error = acpi_parse_madt_ioapic_entries(); | ||
791 | if (!error) { | ||
792 | acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; | ||
793 | acpi_irq_balance_set(NULL); | ||
794 | acpi_ioapic = 1; | ||
795 | |||
796 | smp_found_config = 1; | ||
797 | clustered_apic_check(); | ||
798 | } | ||
799 | } | ||
800 | if (error == -EINVAL) { | ||
801 | /* | ||
802 | * Dell Precision Workstation 410, 610 come here. | ||
803 | */ | ||
804 | printk(KERN_ERR PREFIX "Invalid BIOS MADT, disabling ACPI\n"); | ||
805 | disable_acpi(); | ||
806 | } | ||
807 | } | ||
808 | #endif | ||
809 | return; | ||
810 | } | ||
811 | |||
812 | /* | ||
813 | * acpi_boot_table_init() and acpi_boot_init() | ||
814 | * called from setup_arch(), always. | ||
815 | * 1. checksums all tables | ||
816 | * 2. enumerates lapics | ||
817 | * 3. enumerates io-apics | ||
818 | * | ||
819 | * acpi_table_init() is separate to allow reading SRAT without | ||
820 | * other side effects. | ||
821 | * | ||
822 | * side effects of acpi_boot_init: | ||
823 | * acpi_lapic = 1 if LAPIC found | ||
824 | * acpi_ioapic = 1 if IOAPIC found | ||
825 | * if (acpi_lapic && acpi_ioapic) smp_found_config = 1; | ||
826 | * if acpi_blacklisted() acpi_disabled = 1; | ||
827 | * acpi_irq_model=... | ||
828 | * ... | ||
829 | * | ||
830 | * return value: (currently ignored) | ||
831 | * 0: success | ||
832 | * !0: failure | ||
833 | */ | ||
834 | |||
835 | int __init | ||
836 | acpi_boot_table_init(void) | ||
837 | { | ||
838 | int error; | ||
839 | |||
840 | /* | ||
841 | * If acpi_disabled, bail out | ||
842 | * One exception: acpi=ht continues far enough to enumerate LAPICs | ||
843 | */ | ||
844 | if (acpi_disabled && !acpi_ht) | ||
845 | return 1; | ||
846 | |||
847 | /* | ||
848 | * Initialize the ACPI boot-time table parser. | ||
849 | */ | ||
850 | error = acpi_table_init(); | ||
851 | if (error) { | ||
852 | disable_acpi(); | ||
853 | return error; | ||
854 | } | ||
855 | |||
856 | #ifdef __i386__ | ||
857 | check_acpi_pci(); | ||
858 | #endif | ||
859 | |||
860 | acpi_table_parse(ACPI_BOOT, acpi_parse_sbf); | ||
861 | |||
862 | /* | ||
863 | * blacklist may disable ACPI entirely | ||
864 | */ | ||
865 | error = acpi_blacklisted(); | ||
866 | if (error) { | ||
867 | extern int acpi_force; | ||
868 | |||
869 | if (acpi_force) { | ||
870 | printk(KERN_WARNING PREFIX "acpi=force override\n"); | ||
871 | } else { | ||
872 | printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); | ||
873 | disable_acpi(); | ||
874 | return error; | ||
875 | } | ||
876 | } | ||
877 | |||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | |||
882 | int __init acpi_boot_init(void) | ||
883 | { | ||
884 | /* | ||
885 | * If acpi_disabled, bail out | ||
886 | * One exception: acpi=ht continues far enough to enumerate LAPICs | ||
887 | */ | ||
888 | if (acpi_disabled && !acpi_ht) | ||
889 | return 1; | ||
890 | |||
891 | acpi_table_parse(ACPI_BOOT, acpi_parse_sbf); | ||
892 | |||
893 | /* | ||
894 | * set sci_int and PM timer address | ||
895 | */ | ||
896 | acpi_table_parse(ACPI_FADT, acpi_parse_fadt); | ||
897 | |||
898 | /* | ||
899 | * Process the Multiple APIC Description Table (MADT), if present | ||
900 | */ | ||
901 | acpi_process_madt(); | ||
902 | |||
903 | acpi_table_parse(ACPI_HPET, acpi_parse_hpet); | ||
904 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | ||
905 | |||
906 | return 0; | ||
907 | } | ||
908 | |||