📄 acpi.c
字号:
/* * acpi.c - Architecture-Specific Low-Level ACPI Support * * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com> * Copyright (C) 2000, 2002 Hewlett-Packard Co. * David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 2000 Intel Corp. * Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com> * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */#include <linux/config.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/smp.h>#include <linux/string.h>#include <linux/types.h>#include <linux/irq.h>#include <linux/acpi.h>#include <linux/efi.h>#include <asm/io.h>#include <asm/iosapic.h>#include <asm/machvec.h>#include <asm/page.h>#include <asm/system.h>#define PREFIX "ACPI: "asm (".weak iosapic_register_intr");asm (".weak iosapic_override_isa_irq");asm (".weak iosapic_register_platform_intr");asm (".weak iosapic_init");asm (".weak iosapic_version");void (*pm_idle) (void);void (*pm_power_off) (void);unsigned char acpi_kbd_controller_present = 1;const char *acpi_get_sysname (void){#ifdef CONFIG_IA64_GENERIC unsigned long rsdp_phys; struct acpi20_table_rsdp *rsdp; struct acpi_table_xsdt *xsdt; struct acpi_table_header *hdr; rsdp_phys = acpi_find_rsdp(); if (!rsdp_phys) { printk("ACPI 2.0 RSDP not found, default to \"dig\"\n"); return "dig"; } rsdp = (struct acpi20_table_rsdp *) __va(rsdp_phys); if (strncmp(rsdp->signature, RSDP_SIG, sizeof(RSDP_SIG) - 1)) { printk("ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n"); return "dig"; } xsdt = (struct acpi_table_xsdt *) __va(rsdp->xsdt_address); hdr = &xsdt->header; if (strncmp(hdr->signature, XSDT_SIG, sizeof(XSDT_SIG) - 1)) { printk("ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n"); return "dig"; } if (!strcmp(hdr->oem_id, "HP")) { return "hpzx1"; } return "dig";#else# if defined (CONFIG_IA64_HP_SIM) return "hpsim";# elif defined (CONFIG_IA64_HP_ZX1) return "hpzx1";# elif defined (CONFIG_IA64_SGI_SN1) return "sn1";# elif defined (CONFIG_IA64_SGI_SN2) return "sn2";# elif defined (CONFIG_IA64_DIG) return "dig";# else# error Unknown platform. Fix acpi.c.# endif#endif}#ifdef CONFIG_ACPIstatic acpi_resource *acpi_get_crs_next (acpi_buffer *buf, int *offset){ acpi_resource *res; if (*offset >= buf->length) return NULL; res = (acpi_resource *)((char *) buf->pointer + *offset); *offset += res->length; return res;}static acpi_resource_data *acpi_get_crs_type (acpi_buffer *buf, int *offset, int type){ for (;;) { acpi_resource *res = acpi_get_crs_next(buf, offset); if (!res) return NULL; if (res->id == type) return &res->data; }}static voidacpi_get_crs_addr (acpi_buffer *buf, int type, u64 *base, u64 *length, u64 *tra){ int offset = 0; acpi_resource_address16 *addr16; acpi_resource_address32 *addr32; acpi_resource_address64 *addr64; for (;;) { acpi_resource *res = acpi_get_crs_next(buf, &offset); if (!res) return; switch (res->id) { case ACPI_RSTYPE_ADDRESS16: addr16 = (acpi_resource_address16 *) &res->data; if (type == addr16->resource_type) { *base = addr16->min_address_range; *length = addr16->address_length; *tra = addr16->address_translation_offset; return; } break; case ACPI_RSTYPE_ADDRESS32: addr32 = (acpi_resource_address32 *) &res->data; if (type == addr32->resource_type) { *base = addr32->min_address_range; *length = addr32->address_length; *tra = addr32->address_translation_offset; return; } break; case ACPI_RSTYPE_ADDRESS64: addr64 = (acpi_resource_address64 *) &res->data; if (type == addr64->resource_type) { *base = addr64->min_address_range; *length = addr64->address_length; *tra = addr64->address_translation_offset; return; } break; case ACPI_RSTYPE_END_TAG: return; break; } }}acpi_statusacpi_get_addr_space(acpi_handle obj, u8 type, u64 *base, u64 *length, u64 *tra){ acpi_status status; acpi_buffer buf = { .length = ACPI_ALLOCATE_BUFFER, .pointer = NULL }; *base = 0; *length = 0; *tra = 0; status = acpi_get_current_resources(obj, &buf); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); return status; } acpi_get_crs_addr(&buf, type, base, length, tra); acpi_os_free(buf.pointer); return AE_OK;}typedef struct { u8 guid_id; u8 guid[16]; u8 csr_base[8]; u8 csr_length[8];} acpi_hp_vendor_long;#define HP_CCSR_LENGTH 0x21#define HP_CCSR_TYPE 0x2#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \ 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)acpi_statusacpi_hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length){ int i, offset = 0; acpi_status status; acpi_buffer buf = { .length = ACPI_ALLOCATE_BUFFER, .pointer = NULL }; acpi_resource_vendor *res; acpi_hp_vendor_long *hp_res; efi_guid_t vendor_guid; *csr_base = 0; *csr_length = 0; status = acpi_get_current_resources(obj, &buf); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); return status; } status = AE_NOT_FOUND; res = (acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR); if (!res) { printk(KERN_ERR PREFIX "Failed to find config space for device\n"); goto out; } status = AE_TYPE; /* Revisit error? */ hp_res = (acpi_hp_vendor_long *)(res->reserved); if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) { printk(KERN_ERR PREFIX "Unknown Vendor data\n"); goto out; } memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t)); if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) { printk(KERN_ERR PREFIX "Vendor GUID does not match\n"); goto out; } /* It's probably unaligned, so use memcpy */ memcpy(csr_base, hp_res->csr_base, 8); memcpy(csr_length, hp_res->csr_length, 8); status = AE_OK; out: acpi_os_free(buf.pointer); return status;}#endif /* CONFIG_ACPI */#ifdef CONFIG_ACPI_BOOT#define ACPI_MAX_PLATFORM_INTERRUPTS 256/* Array to record platform interrupt vectors for generic interrupt routing. */int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 };enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;/* * Interrupt routing API for device drivers. Provides interrupt vector for * a generic platform event. Currently only CPEI is implemented. */intacpi_request_vector (u32 int_type){ int vector = -1; if (int_type < ACPI_MAX_PLATFORM_INTERRUPTS) { /* correctable platform error interrupt */ vector = platform_intr_list[int_type]; } else printk("acpi_request_vector(): invalid interrupt type\n"); return vector;}char *__acpi_map_table (unsigned long phys_addr, unsigned long size){ return __va(phys_addr);}/* -------------------------------------------------------------------------- Boot-time Table Parsing -------------------------------------------------------------------------- */static int total_cpus __initdata;static int available_cpus __initdata;struct acpi_table_madt * acpi_madt __initdata;static u8 has_8259;static int __initacpi_parse_lapic_addr_ovr (acpi_table_entry_header *header){ struct acpi_table_lapic_addr_ovr *lapic; lapic = (struct acpi_table_lapic_addr_ovr *) header; if (!lapic) return -EINVAL; acpi_table_print_madt_entry(header); if (lapic->address) { iounmap((void *) ipi_base_addr); ipi_base_addr = (unsigned long) ioremap(lapic->address, 0); } return 0;}static int __initacpi_parse_lsapic (acpi_table_entry_header *header){ struct acpi_table_lsapic *lsapic; int phys_id; lsapic = (struct acpi_table_lsapic *) header; if (!lsapic) return -EINVAL; acpi_table_print_madt_entry(header); phys_id = (lsapic->id << 8) | lsapic->eid; if (total_cpus == NR_CPUS) { printk(KERN_ERR PREFIX "Ignoring CPU (0x%04x) (NR_CPUS == %d)\n", phys_id, NR_CPUS); return 0; } printk("CPU %d (0x%04x)", total_cpus, phys_id); if (lsapic->flags.enabled) { available_cpus++; printk(" enabled");#ifdef CONFIG_SMP smp_boot_data.cpu_phys_id[total_cpus] = phys_id; if (hard_smp_processor_id() == smp_boot_data.cpu_phys_id[total_cpus]) printk(" (BSP)");#endif } else { printk(" disabled");#ifdef CONFIG_SMP smp_boot_data.cpu_phys_id[total_cpus] = -1;#endif } printk("\n"); total_cpus++; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -