acpi.c
来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 780 行 · 第 1/2 页
C
780 行
extern int mp_irqs_alloc(void);/* * acpi_boot_init() * called from setup_arch(), always. * 1. maps ACPI tables for later use * 2. enumerates lapics * 3. enumerates io-apics * * side effects: * acpi_lapic = 1 if LAPIC found * acpi_ioapic = 1 if IOAPIC found * if (acpi_lapic && acpi_ioapic) smp_found_config = 1; * if acpi_blacklisted() disable_acpi() * acpi_irq_model=... * ... * * return value: (currently ignored) * 0: success * !0: failure */int __initacpi_boot_init (void){ int result = 0; if (acpi_disabled && !acpi_ht) return(1); /* * The default interrupt routing model is PIC (8259). This gets * overriden if IOAPICs are enumerated (below). */ acpi_irq_model = ACPI_IRQ_MODEL_PIC; /* * Initialize the ACPI boot-time table parser. */ result = acpi_table_init(); if (result) { disable_acpi(); return result; } result = acpi_blacklisted(); if (result) { printk(KERN_NOTICE PREFIX "BIOS listed in blacklist, disabling ACPI support\n"); disable_acpi(); return result; }#ifdef CONFIG_ACPI_MMCONFIG result = acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); if (result < 0) { printk(KERN_ERR PREFIX "Error %d parsing MCFG\n", result); } else if (result > 1) { printk(KERN_WARNING PREFIX "Multiple MCFG tables exist\n"); }#endif#ifdef CONFIG_X86_LOCAL_APIC /* * MADT * ---- * Parse the Multiple APIC Description Table (MADT), if exists. * Note that this table provides platform SMP configuration * information -- the successor to MPS tables. */ result = acpi_table_parse(ACPI_APIC, acpi_parse_madt); if (!result) { return 0; } else if (result < 0) { printk(KERN_ERR PREFIX "Error parsing MADT\n"); return result; } else if (result > 1) printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n"); /* * Local APIC * ---------- * Note that the LAPIC address is obtained from the MADT (32-bit value) * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). */ result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr); if (result < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); return result; } mp_register_lapic_address(acpi_lapic_addr); result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic); if (!result) { printk(KERN_ERR PREFIX "No LAPIC entries present\n"); /* TBD: Cleanup to allow fallback to MPS */ return -ENODEV; } else if (result < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); /* TBD: Cleanup to allow fallback to MPS */ return result; } result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); if (result < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); /* TBD: Cleanup to allow fallback to MPS */ return result; } acpi_lapic = 1;#endif /*CONFIG_X86_LOCAL_APIC*/#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER) /* * I/O APIC * -------- */ /* * ACPI interpreter is required to complete interrupt setup, * so if it is off, don't enumerate the io-apics with ACPI. * If MPS is present, it will handle them, * otherwise the system will stay in PIC mode */ if (acpi_disabled || acpi_noirq) { return 1; } /* * if "noapic" boot option, don't look for IO-APICs */ if (ioapic_setup_disabled()) { printk(KERN_INFO PREFIX "Skipping IOAPIC probe " "due to 'noapic' option.\n"); return 1; } result = mp_irqs_alloc(); /* Dynamically allocate mp_irqs[] */ if (result < 0) { acpi_noirq = 1; return result; } result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic); if (!result) { printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); return -ENODEV; } else if (result < 0) { printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); return result; } /* Record sci_int for use when looking for MADT sci_int override */ acpi_table_parse(ACPI_FADT, acpi_parse_fadt); result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr); if (result < 0) { printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); /* TBD: Cleanup to allow fallback to MPS */ return result; } /* * If BIOS did not supply an INT_SRC_OVR for the SCI * pretend we got one so we can set the SCI flags. */ if (!acpi_sci_override_gsi) acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0); /* Fill in identity legacy mapings where no override */ mp_config_acpi_legacy_irqs(); result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src); if (result < 0) { printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); /* TBD: Cleanup to allow fallback to MPS */ return result; } acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; acpi_irq_balance_set(NULL); acpi_ioapic = 1; if (acpi_lapic && acpi_ioapic) smp_found_config = 1;#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/ return 0;}#ifdef CONFIG_ACPI_BUS/* * acpi_pic_sci_set_trigger() * * use ELCR to set PIC-mode trigger type for SCI * * If a PIC-mode SCI is not recognized or gives spurious IRQ7's * it may require Edge Trigger -- use "acpi_sci=edge" * * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge. * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) */void __initacpi_pic_sci_set_trigger(unsigned int irq, u16 trigger){ unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); unsigned char val = inb(port); printk(PREFIX "IRQ%d SCI:", irq); if (!(val & mask)) { printk(" Edge"); if (trigger == 3) { printk(" set to Level"); outb(val | mask, port); } } else { printk(" Level"); if (trigger == 1) { printk(" set to Edge"); outb(val & ~mask, port); } } printk(" Trigger.\n");}#endif /* CONFIG_ACPI_BUS */#ifndef __HAVE_ARCH_CMPXCHG#warning ACPI uses CMPXCHG, i486 and later hardware#endif/* -------------------------------------------------------------------------- Low-Level Sleep Support -------------------------------------------------------------------------- */#ifdef CONFIG_ACPI_SLEEP#define DEBUG#ifdef DEBUG#include <linux/serial.h>#endif/* address in low memory of the wakeup routine. */unsigned long acpi_wakeup_address = 0;/* new page directory that we will be using */static pmd_t *pmd;/* saved page directory */static pmd_t saved_pmd;/* page which we'll use for the new page directory */static pte_t *ptep;extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));/* * acpi_create_identity_pmd * * Create a new, identity mapped pmd. * * Do this by creating new page directory, and marking all the pages as R/W * Then set it as the new Page Middle Directory. * And, of course, flush the TLB so it takes effect. * * We save the address of the old one, for later restoration. */static void acpi_create_identity_pmd (void){ pgd_t *pgd; int i; ptep = (pte_t*)__get_free_page(GFP_KERNEL); /* fill page with low mapping */ for (i = 0; i < PTRS_PER_PTE; i++) set_pte(ptep + i, mk_pte_phys(i << PAGE_SHIFT, PAGE_SHARED)); pgd = pgd_offset(current->active_mm, 0); pmd = pmd_alloc(current->mm,pgd, 0); /* save the old pmd */ saved_pmd = *pmd; /* set the new one */ set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(ptep))); /* flush the TLB */ local_flush_tlb();}/* * acpi_restore_pmd * * Restore the old pmd saved by acpi_create_identity_pmd and * free the page that said function alloc'd */static void acpi_restore_pmd (void){ set_pmd(pmd, saved_pmd); local_flush_tlb(); free_page((unsigned long)ptep);}/** * acpi_save_state_mem - save kernel state * * Create an identity mapped page table and copy the wakeup routine to * low memory. */int acpi_save_state_mem (void){ acpi_create_identity_pmd(); acpi_copy_wakeup_routine(acpi_wakeup_address); return 0;}/** * acpi_save_state_disk - save kernel state to disk * */int acpi_save_state_disk (void){ return 1;}/* * acpi_restore_state */void acpi_restore_state_mem (void){ acpi_restore_pmd();}/** * acpi_reserve_bootmem - do _very_ early ACPI initialisation * * We allocate a page in low memory for the wakeup * routine for when we come back from a sleep state. The * runtime allocator allows specification of <16M pages, but not * <1M pages. */void __init acpi_reserve_bootmem(void){ acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); if (!acpi_wakeup_address) printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");}void do_suspend_lowlevel_s4bios(int resume){ if (!resume) { save_processor_context(); acpi_save_register_state((unsigned long)&&acpi_sleep_done); acpi_enter_sleep_state_s4bios(); return; }acpi_sleep_done: restore_processor_context();}#endif /*CONFIG_ACPI_SLEEP*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?