debuggers.hg

view xen/arch/ia64/acpi.c @ 4615:58efb3448933

bitkeeper revision 1.1327.1.1 (426536d2PUqtjTi2v06bzD10RFwarg)

Merge bk://xen.bkbits.net/xeno-unstable.bk
into bkbits.net:/repos/x/xen-ia64/xeno-unstable-ia64.bk
author xen-ia64.adm@bkbits.net
date Tue Apr 19 16:50:26 2005 +0000 (2005-04-19)
parents 73f9c9685211 a8466d0e2992
children 5b9e241131fb
line source
1 /*
2 * acpi.c - Architecture-Specific Low-Level ACPI 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 * Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 */
27 #include <xen/config.h>
28 #include <xen/kernel.h>
29 #include <xen/init.h>
30 #include <xen/types.h>
31 /*#include <xen/stddef.h>*/
32 #include <xen/slab.h>
33 #include <xen/pci.h>
34 /*#include <xen/bootmem.h>*/
35 #include <xen/irq.h>
36 #include <xen/acpi.h>
37 //#include <asm/mpspec.h>
38 #include <asm/io.h>
39 //#include <asm/apic.h>
40 //#include <asm/apicdef.h>
41 #include <asm/page.h>
42 /*#include <asm/pgtable.h>*/
43 #include <asm/pgalloc.h>
44 //#include <asm/io_apic.h>
45 #include <asm/acpi.h>
46 /*#include <asm/save_state.h>*/
47 //#include <asm/smpboot.h>
50 #define PREFIX "ACPI: "
52 int acpi_lapic = 0;
53 int acpi_ioapic = 0;
55 /* --------------------------------------------------------------------------
56 Boot-time Configuration
57 -------------------------------------------------------------------------- */
59 #ifdef CONFIG_ACPI_BOOT
60 //int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */
61 int acpi_ht __initdata = 1; /* enable HT */
63 enum acpi_irq_model_id acpi_irq_model;
66 /*
67 * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
68 * to map the target physical address. The problem is that set_fixmap()
69 * provides a single page, and it is possible that the page is not
70 * sufficient.
71 * By using this area, we can map up to MAX_IO_APICS pages temporarily,
72 * i.e. until the next __va_range() call.
73 *
74 * Important Safety Note: The fixed I/O APIC page numbers are *subtracted*
75 * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and
76 * count idx down while incrementing the phys address.
77 */
78 char *__acpi_map_table(unsigned long phys, unsigned long size)
79 {
80 unsigned long base, offset, mapped_size;
81 int idx;
83 if (phys + size < 8*1024*1024)
84 return __va(phys);
86 offset = phys & (PAGE_SIZE - 1);
87 mapped_size = PAGE_SIZE - offset;
88 #ifndef XEN
89 // where is FIX_ACPI_*? hack for now, FIXME later
90 set_fixmap(FIX_ACPI_END, phys);
91 base = fix_to_virt(FIX_ACPI_END);
93 /*
94 * Most cases can be covered by the below.
95 */
96 idx = FIX_ACPI_END;
97 while (mapped_size < size) {
98 if (--idx < FIX_ACPI_BEGIN)
99 return 0; /* cannot handle this */
100 phys += PAGE_SIZE;
101 set_fixmap(idx, phys);
102 mapped_size += PAGE_SIZE;
103 }
104 #endif
106 return ((unsigned char *) base + offset);
107 }
110 #ifdef CONFIG_X86_LOCAL_APIC
112 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
115 static int __init
116 acpi_parse_madt (
117 unsigned long phys_addr,
118 unsigned long size)
119 {
120 struct acpi_table_madt *madt = NULL;
122 if (!phys_addr || !size)
123 return -EINVAL;
125 madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size);
126 if (!madt) {
127 printk(KERN_WARNING PREFIX "Unable to map MADT\n");
128 return -ENODEV;
129 }
131 if (madt->lapic_address)
132 acpi_lapic_addr = (u64) madt->lapic_address;
134 printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n",
135 madt->lapic_address);
137 detect_clustered_apic(madt->header.oem_id, madt->header.oem_table_id);
139 return 0;
140 }
143 static int __init
144 acpi_parse_lapic (
145 acpi_table_entry_header *header)
146 {
147 struct acpi_table_lapic *processor = NULL;
149 processor = (struct acpi_table_lapic*) header;
150 if (!processor)
151 return -EINVAL;
153 acpi_table_print_madt_entry(header);
155 mp_register_lapic (
156 processor->id, /* APIC ID */
157 processor->flags.enabled); /* Enabled? */
159 return 0;
160 }
163 static int __init
164 acpi_parse_lapic_addr_ovr (
165 acpi_table_entry_header *header)
166 {
167 struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
169 lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
170 if (!lapic_addr_ovr)
171 return -EINVAL;
173 acpi_lapic_addr = lapic_addr_ovr->address;
175 return 0;
176 }
178 static int __init
179 acpi_parse_lapic_nmi (
180 acpi_table_entry_header *header)
181 {
182 struct acpi_table_lapic_nmi *lapic_nmi = NULL;
184 lapic_nmi = (struct acpi_table_lapic_nmi*) header;
185 if (!lapic_nmi)
186 return -EINVAL;
188 acpi_table_print_madt_entry(header);
190 if (lapic_nmi->lint != 1)
191 printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
193 return 0;
194 }
196 #endif /*CONFIG_X86_LOCAL_APIC*/
198 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
200 static int __init
201 acpi_parse_ioapic (
202 acpi_table_entry_header *header)
203 {
204 struct acpi_table_ioapic *ioapic = NULL;
206 ioapic = (struct acpi_table_ioapic*) header;
207 if (!ioapic)
208 return -EINVAL;
210 acpi_table_print_madt_entry(header);
212 mp_register_ioapic (
213 ioapic->id,
214 ioapic->address,
215 ioapic->global_irq_base);
217 return 0;
218 }
221 static int __init
222 acpi_parse_int_src_ovr (
223 acpi_table_entry_header *header)
224 {
225 struct acpi_table_int_src_ovr *intsrc = NULL;
227 intsrc = (struct acpi_table_int_src_ovr*) header;
228 if (!intsrc)
229 return -EINVAL;
231 acpi_table_print_madt_entry(header);
233 mp_override_legacy_irq (
234 intsrc->bus_irq,
235 intsrc->flags.polarity,
236 intsrc->flags.trigger,
237 intsrc->global_irq);
239 return 0;
240 }
243 static int __init
244 acpi_parse_nmi_src (
245 acpi_table_entry_header *header)
246 {
247 struct acpi_table_nmi_src *nmi_src = NULL;
249 nmi_src = (struct acpi_table_nmi_src*) header;
250 if (!nmi_src)
251 return -EINVAL;
253 acpi_table_print_madt_entry(header);
255 /* TBD: Support nimsrc entries? */
257 return 0;
258 }
260 #endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
263 static unsigned long __init
264 acpi_scan_rsdp (
265 unsigned long start,
266 unsigned long length)
267 {
268 unsigned long offset = 0;
269 unsigned long sig_len = sizeof("RSD PTR ") - 1;
271 /*
272 * Scan all 16-byte boundaries of the physical memory region for the
273 * RSDP signature.
274 */
275 for (offset = 0; offset < length; offset += 16) {
276 if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
277 continue;
278 return (start + offset);
279 }
281 return 0;
282 }
285 unsigned long __init
286 acpi_find_rsdp (void)
287 {
288 unsigned long rsdp_phys = 0;
290 /*
291 * Scan memory looking for the RSDP signature. First search EBDA (low
292 * memory) paragraphs and then search upper memory (E0000-FFFFF).
293 */
294 rsdp_phys = acpi_scan_rsdp (0, 0x400);
295 if (!rsdp_phys)
296 rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF);
298 return rsdp_phys;
299 }
302 /*
303 * acpi_boot_init()
304 * called from setup_arch(), always.
305 * 1. maps ACPI tables for later use
306 * 2. enumerates lapics
307 * 3. enumerates io-apics
308 *
309 * side effects:
310 * acpi_lapic = 1 if LAPIC found
311 * acpi_ioapic = 1 if IOAPIC found
312 * if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
313 * if acpi_blacklisted() acpi_disabled = 1;
314 * acpi_irq_model=...
315 * ...
316 *
317 * return value: (currently ignored)
318 * 0: success
319 * !0: failure
320 */
321 int __init
322 acpi_boot_init (void)
323 {
324 int result = 0;
326 if (acpi_disabled && !acpi_ht)
327 return(1);
329 /*
330 * The default interrupt routing model is PIC (8259). This gets
331 * overriden if IOAPICs are enumerated (below).
332 */
333 acpi_irq_model = ACPI_IRQ_MODEL_PIC;
335 /*
336 * Initialize the ACPI boot-time table parser.
337 */
338 result = acpi_table_init();
339 if (result) {
340 #ifndef XEN
341 // hack for now, FIXME later
342 acpi_disabled = 1;
343 #endif
344 return result;
345 }
347 result = acpi_blacklisted();
348 if (result) {
349 printk(KERN_NOTICE PREFIX "BIOS listed in blacklist, disabling ACPI support\n");
350 #ifndef XEN
351 // hack for now, FIXME later
352 acpi_disabled = 1;
353 #endif
354 return result;
355 }
357 #ifdef CONFIG_X86_LOCAL_APIC
359 /*
360 * MADT
361 * ----
362 * Parse the Multiple APIC Description Table (MADT), if exists.
363 * Note that this table provides platform SMP configuration
364 * information -- the successor to MPS tables.
365 */
367 result = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
368 if (!result) {
369 return 0;
370 }
371 else if (result < 0) {
372 printk(KERN_ERR PREFIX "Error parsing MADT\n");
373 return result;
374 }
375 else if (result > 1)
376 printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n");
378 /*
379 * Local APIC
380 * ----------
381 * Note that the LAPIC address is obtained from the MADT (32-bit value)
382 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
383 */
385 result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr);
386 if (result < 0) {
387 printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
388 return result;
389 }
391 mp_register_lapic_address(acpi_lapic_addr);
393 result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic);
394 if (!result) {
395 printk(KERN_ERR PREFIX "No LAPIC entries present\n");
396 /* TBD: Cleanup to allow fallback to MPS */
397 return -ENODEV;
398 }
399 else if (result < 0) {
400 printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
401 /* TBD: Cleanup to allow fallback to MPS */
402 return result;
403 }
405 result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi);
406 if (result < 0) {
407 printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
408 /* TBD: Cleanup to allow fallback to MPS */
409 return result;
410 }
412 acpi_lapic = 1;
414 #endif /*CONFIG_X86_LOCAL_APIC*/
416 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
418 /*
419 * I/O APIC
420 * --------
421 */
423 /*
424 * ACPI interpreter is required to complete interrupt setup,
425 * so if it is off, don't enumerate the io-apics with ACPI.
426 * If MPS is present, it will handle them,
427 * otherwise the system will stay in PIC mode
428 */
429 if (acpi_disabled || acpi_noirq) {
430 return 1;
431 }
433 /*
434 * if "noapic" boot option, don't look for IO-APICs
435 */
436 if (ioapic_setup_disabled()) {
437 printk(KERN_INFO PREFIX "Skipping IOAPIC probe "
438 "due to 'noapic' option.\n");
439 return 1;
440 }
443 result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic);
444 if (!result) {
445 printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
446 return -ENODEV;
447 }
448 else if (result < 0) {
449 printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
450 return result;
451 }
453 /* Build a default routing table for legacy (ISA) interrupts. */
454 mp_config_acpi_legacy_irqs();
456 result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr);
457 if (result < 0) {
458 printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
459 /* TBD: Cleanup to allow fallback to MPS */
460 return result;
461 }
463 result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
464 if (result < 0) {
465 printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
466 /* TBD: Cleanup to allow fallback to MPS */
467 return result;
468 }
470 acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
472 acpi_irq_balance_set(NULL);
474 acpi_ioapic = 1;
476 if (acpi_lapic && acpi_ioapic)
477 smp_found_config = 1;
479 #endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
481 return 0;
482 }
484 #endif /*CONFIG_ACPI_BOOT*/
486 #ifdef CONFIG_ACPI_BUS
487 /*
488 * "acpi_pic_sci=level" (current default)
489 * programs the PIC-mode SCI to Level Trigger.
490 * (NO-OP if the BIOS set Level Trigger already)
491 *
492 * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's
493 * it may require Edge Trigger -- use "acpi_pic_sci=edge"
494 * (NO-OP if the BIOS set Edge Trigger already)
495 *
496 * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
497 * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge.
498 * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
499 * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
500 */
502 static __initdata int acpi_pic_sci_trigger; /* 0: level, 1: edge */
504 void __init
505 acpi_pic_sci_set_trigger(unsigned int irq)
506 {
507 unsigned char mask = 1 << (irq & 7);
508 unsigned int port = 0x4d0 + (irq >> 3);
509 unsigned char val = inb(port);
512 printk(PREFIX "IRQ%d SCI:", irq);
513 if (!(val & mask)) {
514 printk(" Edge");
516 if (!acpi_pic_sci_trigger) {
517 printk(" set to Level");
518 outb(val | mask, port);
519 }
520 } else {
521 printk(" Level");
523 if (acpi_pic_sci_trigger) {
524 printk(" set to Edge");
525 outb(val | mask, port);
526 }
527 }
528 printk(" Trigger.\n");
529 }
531 int __init
532 acpi_pic_sci_setup(char *str)
533 {
534 while (str && *str) {
535 if (strncmp(str, "level", 5) == 0)
536 acpi_pic_sci_trigger = 0; /* force level trigger */
537 if (strncmp(str, "edge", 4) == 0)
538 acpi_pic_sci_trigger = 1; /* force edge trigger */
539 str = strchr(str, ',');
540 if (str)
541 str += strspn(str, ", \t");
542 }
543 return 1;
544 }
546 __setup("acpi_pic_sci=", acpi_pic_sci_setup);
548 #endif /* CONFIG_ACPI_BUS */
552 /* --------------------------------------------------------------------------
553 Low-Level Sleep Support
554 -------------------------------------------------------------------------- */
556 #ifdef CONFIG_ACPI_SLEEP
558 #define DEBUG
560 #ifdef DEBUG
561 #include <xen/serial.h>
562 #endif
564 /* address in low memory of the wakeup routine. */
565 unsigned long acpi_wakeup_address = 0;
567 /* new page directory that we will be using */
568 static pmd_t *pmd;
570 /* saved page directory */
571 static pmd_t saved_pmd;
573 /* page which we'll use for the new page directory */
574 static pte_t *ptep;
576 extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
578 /*
579 * acpi_create_identity_pmd
580 *
581 * Create a new, identity mapped pmd.
582 *
583 * Do this by creating new page directory, and marking all the pages as R/W
584 * Then set it as the new Page Middle Directory.
585 * And, of course, flush the TLB so it takes effect.
586 *
587 * We save the address of the old one, for later restoration.
588 */
589 static void acpi_create_identity_pmd (void)
590 {
591 pgd_t *pgd;
592 int i;
594 ptep = (pte_t*)__get_free_page(GFP_KERNEL);
596 /* fill page with low mapping */
597 for (i = 0; i < PTRS_PER_PTE; i++)
598 set_pte(ptep + i, mk_pte_phys(i << PAGE_SHIFT, PAGE_SHARED));
600 pgd = pgd_offset(current->active_mm, 0);
601 pmd = pmd_alloc(current->mm,pgd, 0);
603 /* save the old pmd */
604 saved_pmd = *pmd;
606 /* set the new one */
607 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(ptep)));
609 /* flush the TLB */
610 local_flush_tlb();
611 }
613 /*
614 * acpi_restore_pmd
615 *
616 * Restore the old pmd saved by acpi_create_identity_pmd and
617 * free the page that said function alloc'd
618 */
619 static void acpi_restore_pmd (void)
620 {
621 set_pmd(pmd, saved_pmd);
622 local_flush_tlb();
623 free_page((unsigned long)ptep);
624 }
626 /**
627 * acpi_save_state_mem - save kernel state
628 *
629 * Create an identity mapped page table and copy the wakeup routine to
630 * low memory.
631 */
632 int acpi_save_state_mem (void)
633 {
634 acpi_create_identity_pmd();
635 acpi_copy_wakeup_routine(acpi_wakeup_address);
637 return 0;
638 }
640 /**
641 * acpi_save_state_disk - save kernel state to disk
642 *
643 */
644 int acpi_save_state_disk (void)
645 {
646 return 1;
647 }
649 /*
650 * acpi_restore_state
651 */
652 void acpi_restore_state_mem (void)
653 {
654 acpi_restore_pmd();
655 }
657 /**
658 * acpi_reserve_bootmem - do _very_ early ACPI initialisation
659 *
660 * We allocate a page in low memory for the wakeup
661 * routine for when we come back from a sleep state. The
662 * runtime allocator allows specification of <16M pages, but not
663 * <1M pages.
664 */
665 void __init acpi_reserve_bootmem(void)
666 {
667 acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
668 printk(KERN_DEBUG "ACPI: have wakeup address 0x%8.8lx\n", acpi_wakeup_address);
669 }
671 void do_suspend_lowlevel_s4bios(int resume)
672 {
673 if (!resume) {
674 save_processor_context();
675 acpi_save_register_state((unsigned long)&&acpi_sleep_done);
676 acpi_enter_sleep_state_s4bios();
677 return;
678 }
679 acpi_sleep_done:
680 restore_processor_context();
681 }
684 #endif /*CONFIG_ACPI_SLEEP*/