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 + -
显示快捷键?