⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acpitable.c

📁 上传linux-jx2410的源代码
💻 C
字号:
/* *  acpitable.c - IA32-specific ACPI boot-time initialization (Revision: 1) * *  Copyright (C) 1999 Andrew Henroid *  Copyright (C) 2001 Richard Schaal *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com> *  Copyright (C) 2001 Arjan van de Ven <arjanv@redhat.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 * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * $Id: acpitable.c,v 1.1.1.1 2004/02/04 12:55:29 laputa Exp $ */#include <linux/config.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/types.h>#include <linux/stddef.h>#include <linux/slab.h>#include <linux/pci.h>#include <asm/mpspec.h>#include <asm/io.h>#include <asm/apic.h>#include <asm/apicdef.h>#include <asm/page.h>#include <asm/pgtable.h>#include "acpitable.h"static acpi_table_handler acpi_boot_ops[ACPI_TABLE_COUNT];static unsigned char __initacpi_checksum(void *buffer, int length){	int i;	unsigned char *bytebuffer;	unsigned char sum = 0;	if (!buffer || length <= 0)		return 0;	bytebuffer = (unsigned char *) buffer;	for (i = 0; i < length; i++)		sum += *(bytebuffer++);	return sum;}static void __initacpi_print_table_header(acpi_table_header * header){	if (!header)		return;	printk(KERN_INFO "ACPI table found: %.4s v%d [%.6s %.8s %d.%d]\n",	       header->signature, header->revision, header->oem_id,	       header->oem_table_id, header->oem_revision >> 16,	       header->oem_revision & 0xffff);	return;}/******************************************************************************* * * FUNCTION:    acpi_tb_scan_memory_for_rsdp * * PARAMETERS:  address       - Starting pointer for search *              length        - Maximum length to search * * RETURN:      Pointer to the RSDP if found and valid, otherwise NULL. * * DESCRIPTION: Search a block of memory for the RSDP signature * ******************************************************************************/static void *__initacpi_tb_scan_memory_for_rsdp(void *address, int length){	u32 offset;	if (length <= 0)		return NULL;	/* Search from given start addr for the requested length  */	offset = 0;	while (offset < length) {		/* The signature must match and the checksum must be correct */		if (strncmp(address, RSDP_SIG, sizeof(RSDP_SIG) - 1) == 0 &&		    acpi_checksum(address, RSDP_CHECKSUM_LENGTH) == 0) {			/* If so, we have found the RSDP */			printk(KERN_INFO "ACPI: RSDP located at physical address %p\n",			       address);			return address;		}		offset += RSDP_SCAN_STEP;		address += RSDP_SCAN_STEP;	}	/* Searched entire block, no RSDP was found */	printk(KERN_INFO "ACPI: Searched entire block, no RSDP was found.\n");	return NULL;}/******************************************************************************* * * FUNCTION:    acpi_find_root_pointer * * PARAMETERS:  none * * RETURN:      physical address of the RSDP  * * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor *              pointer structure.  If it is found, set *RSDP to point to it. * *              NOTE: The RSDP must be either in the first 1_k of the Extended *              BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section *              5.2.2; assertion #421). * ******************************************************************************/static struct acpi_table_rsdp * __initacpi_find_root_pointer(void){	struct acpi_table_rsdp * rsdp;	/*	 * Physical address is given	 */	/*	 * Region 1) Search EBDA (low memory) paragraphs	 */	rsdp = acpi_tb_scan_memory_for_rsdp(__va(LO_RSDP_WINDOW_BASE),					 LO_RSDP_WINDOW_SIZE);	if (rsdp)		return rsdp;	/*	 * Region 2) Search upper memory: 16-byte boundaries in E0000h-F0000h	 */	rsdp = acpi_tb_scan_memory_for_rsdp(__va(HI_RSDP_WINDOW_BASE),					       HI_RSDP_WINDOW_SIZE);						     	if (rsdp)		return rsdp;	printk(KERN_ERR "ACPI: System description tables not found\n");	return NULL;}/* * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_0, * to map the target physical address. The problem is that set_fixmap() * provides a single page, and it is possible that the page is not * sufficient. * By using this area, we can map up to MAX_IO_APICS pages temporarily, * i.e. until the next __va_range() call. */static __inline__ char *__va_range(unsigned long phys, unsigned long size){	unsigned long base, offset, mapped_size, mapped_phys = phys;	int idx = FIX_IO_APIC_BASE_0;	offset = phys & (PAGE_SIZE - 1);	mapped_size = PAGE_SIZE - offset;	set_fixmap(idx, mapped_phys);	base = fix_to_virt(FIX_IO_APIC_BASE_0);	/*	 * Most cases can be covered by the below.	 */	if (mapped_size >= size)		return ((unsigned char *) base + offset);	dprintk("__va_range: mapping more than a single page, size = 0x%lx\n",		size);	do {		if (idx++ == FIX_IO_APIC_BASE_END)			return 0;	/* cannot handle this */		mapped_phys = mapped_phys + PAGE_SIZE;		set_fixmap(idx, mapped_phys);		mapped_size = mapped_size + PAGE_SIZE;	} while (mapped_size < size);	return ((unsigned char *) base + offset);}static int __init acpi_tables_init(void){	int result = -ENODEV;	acpi_table_header *header = NULL;	struct acpi_table_rsdp *rsdp = NULL;	struct acpi_table_rsdt *rsdt = NULL;	struct acpi_table_rsdt saved_rsdt;	int tables = 0;	int type = 0;	int i = 0;	rsdp = (struct acpi_table_rsdp *) acpi_find_root_pointer();	if (!rsdp)		return -ENODEV;			printk(KERN_INFO "%.8s v%d [%.6s]\n", rsdp->signature, rsdp->revision,	       rsdp->oem_id);	       	if (strncmp(rsdp->signature, RSDP_SIG,strlen(RSDP_SIG))) {		printk(KERN_WARNING "RSDP table signature incorrect\n");		return -EINVAL;	}	rsdt = (struct acpi_table_rsdt *)	    __va_range(rsdp->rsdt_address, sizeof(struct acpi_table_rsdt));	if (!rsdt) {		printk(KERN_WARNING "ACPI: Invalid root system description tables (RSDT)\n");		return -ENODEV;	}		header = & rsdt->header;	acpi_print_table_header(header);		if (strncmp(header->signature, RSDT_SIG, strlen(RSDT_SIG))) {		printk(KERN_WARNING "ACPI: RSDT signature incorrect\n");		return -ENODEV;	}			/* 	 * The number of tables is computed by taking the 	 * size of all entries (header size minus total 	 * size of RSDT) divided by the size of each entry	 * (4-byte table pointers).	 */	tables = (header->length - sizeof(acpi_table_header)) / 4;		    	memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt));	if (saved_rsdt.header.length > sizeof(saved_rsdt)) {		printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n", saved_rsdt.header.length);		return -ENODEV;	}	for (i = 0; i < tables; i++) {		header = (acpi_table_header *)			    __va_range(saved_rsdt.entry[i],				       sizeof(acpi_table_header));		if (!header)			break;		acpi_print_table_header(header);				if (acpi_checksum(header,header->length)) {			printk(KERN_WARNING "ACPI %s has invalid checksum\n", 				acpi_table_signatures[i]);			continue;		}				for (type = 0; type < ACPI_TABLE_COUNT; type++)			if (!strncmp((char *) &header->signature,			     acpi_table_signatures[type],strlen(acpi_table_signatures[type])))				break;		if (type >= ACPI_TABLE_COUNT) {			printk(KERN_WARNING "ACPI: Unsupported table %.4s\n",			       header->signature);			continue;		}		if (!acpi_boot_ops[type])			continue;					result = acpi_boot_ops[type] (header,						 (unsigned long) saved_rsdt.						 entry[i]);	}	return result;}static int total_cpus __initdata = 0;int have_acpi_tables;extern void __init MP_processor_info(struct mpc_config_processor *);static void __initacpi_parse_lapic(struct acpi_table_lapic *local_apic){	struct mpc_config_processor proc_entry;	int ix = 0;	if (!local_apic)		return;	printk(KERN_INFO "LAPIC (acpi_id[0x%04x] id[0x%x] enabled[%d])\n",		local_apic->acpi_id, local_apic->id, local_apic->flags.enabled);	printk(KERN_INFO "CPU %d (0x%02x00)", total_cpus, local_apic->id);	if (local_apic->flags.enabled) {		printk(" enabled");		ix = local_apic->id;		if (ix >= MAX_APICS) {			printk(KERN_WARNING			       "Processor #%d INVALID - (Max ID: %d).\n", ix,			       MAX_APICS);			return;		}		/* 		 * Fill in the info we want to save.  Not concerned about 		 * the processor ID.  Processor features aren't present in 		 * the table.		 */		proc_entry.mpc_type = MP_PROCESSOR;		proc_entry.mpc_apicid = local_apic->id;		proc_entry.mpc_cpuflag = CPU_ENABLED;		if (proc_entry.mpc_apicid == boot_cpu_physical_apicid) {			printk(" (BSP)");			proc_entry.mpc_cpuflag |= CPU_BOOTPROCESSOR;		}		proc_entry.mpc_cpufeature =		    (boot_cpu_data.x86 << 8) | 		    (boot_cpu_data.x86_model << 4) | 		     boot_cpu_data.x86_mask;		proc_entry.mpc_featureflag = boot_cpu_data.x86_capability[0];		proc_entry.mpc_reserved[0] = 0;		proc_entry.mpc_reserved[1] = 0;		proc_entry.mpc_apicver = 0x10;	/* integrated APIC */		MP_processor_info(&proc_entry);	} else {		printk(" disabled");	}	printk("\n");	total_cpus++;	return;}static void __initacpi_parse_ioapic(struct acpi_table_ioapic *ioapic){	if (!ioapic)		return;	printk(KERN_INFO	       "IOAPIC (id[0x%x] address[0x%x] global_irq_base[0x%x])\n",	       ioapic->id, ioapic->address, ioapic->global_irq_base);	if (nr_ioapics >= MAX_IO_APICS) {		printk(KERN_WARNING		       "Max # of I/O APICs (%d) exceeded (found %d).\n",		       MAX_IO_APICS, nr_ioapics);/*		panic("Recompile kernel with bigger MAX_IO_APICS!\n");   */	}}/* Interrupt source overrides inform the machine about exceptions   to the normal "PIC" mode interrupt routing */   static void __initacpi_parse_int_src_ovr(struct acpi_table_int_src_ovr *intsrc){	if (!intsrc)		return;	printk(KERN_INFO	       "INT_SRC_OVR (bus[%d] irq[0x%x] global_irq[0x%x] polarity[0x%x] trigger[0x%x])\n",	       intsrc->bus, intsrc->bus_irq, intsrc->global_irq,	       intsrc->flags.polarity, intsrc->flags.trigger);}/* * At this point, we look at the interrupt assignment entries in the MPS * table. */  static void __init acpi_parse_nmi_src(struct acpi_table_nmi_src *nmisrc){	if (!nmisrc)		return;	printk(KERN_INFO	       "NMI_SRC (polarity[0x%x] trigger[0x%x] global_irq[0x%x])\n",	       nmisrc->flags.polarity, nmisrc->flags.trigger,	       nmisrc->global_irq);}static void __initacpi_parse_lapic_nmi(struct acpi_table_lapic_nmi *localnmi){	if (!localnmi)		return;	printk(KERN_INFO	       "LAPIC_NMI (acpi_id[0x%04x] polarity[0x%x] trigger[0x%x] lint[0x%x])\n",	       localnmi->acpi_id, localnmi->flags.polarity,	       localnmi->flags.trigger, localnmi->lint);}static void __initacpi_parse_lapic_addr_ovr(struct acpi_table_lapic_addr_ovr *lapic_addr_ovr){	if (!lapic_addr_ovr)		return;	printk(KERN_INFO "LAPIC_ADDR_OVR (address[0x%lx])\n",	       (unsigned long) lapic_addr_ovr->address);}static void __initacpi_parse_plat_int_src(struct acpi_table_plat_int_src *plintsrc){	if (!plintsrc)		return;	printk(KERN_INFO	       "PLAT_INT_SRC (polarity[0x%x] trigger[0x%x] type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",	       plintsrc->flags.polarity, plintsrc->flags.trigger,	       plintsrc->type, plintsrc->id, plintsrc->eid,	       plintsrc->iosapic_vector, plintsrc->global_irq);}static int __initacpi_parse_madt(acpi_table_header * header, unsigned long phys){	struct acpi_table_madt *madt;	    	acpi_madt_entry_header *entry_header;	int table_size;		madt = (struct acpi_table_madt *) __va_range(phys, header->length);	if (!madt)		return -EINVAL;	table_size = (int) (header->length - sizeof(*madt));	entry_header =	    (acpi_madt_entry_header *) ((void *) madt + sizeof(*madt));	while (entry_header && (table_size > 0)) {		switch (entry_header->type) {		case ACPI_MADT_LAPIC:			acpi_parse_lapic((struct acpi_table_lapic *)					 entry_header);			break;		case ACPI_MADT_IOAPIC:			acpi_parse_ioapic((struct acpi_table_ioapic *)					  entry_header);			break;		case ACPI_MADT_INT_SRC_OVR:			acpi_parse_int_src_ovr((struct acpi_table_int_src_ovr *)					       entry_header);			break;		case ACPI_MADT_NMI_SRC:			acpi_parse_nmi_src((struct acpi_table_nmi_src *)					   entry_header);			break;		case ACPI_MADT_LAPIC_NMI:			acpi_parse_lapic_nmi((struct acpi_table_lapic_nmi *)					     entry_header);			break;		case ACPI_MADT_LAPIC_ADDR_OVR:			acpi_parse_lapic_addr_ovr((struct						   acpi_table_lapic_addr_ovr *)						  entry_header);			break;		case ACPI_MADT_PLAT_INT_SRC:			acpi_parse_plat_int_src((struct acpi_table_plat_int_src						 *) entry_header);			break;		default:			printk(KERN_WARNING			       "Unsupported MADT entry type 0x%x\n",			       entry_header->type);			break;		}		table_size -= entry_header->length;		entry_header =		    (acpi_madt_entry_header *) ((void *) entry_header +						entry_header->length);	}	if (!total_cpus) {		printk("ACPI: No Processors found in the APCI table.\n");		return -EINVAL;	}	printk(KERN_INFO "%d CPUs total\n", total_cpus);	if (madt->lapic_address)		mp_lapic_addr = madt->lapic_address;	else		mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;	printk(KERN_INFO "Local APIC address %x\n", madt->lapic_address);	return 0;}extern int enable_acpi_smp_table;/* * Configure the processor info using MADT in the ACPI tables. If we fail to * configure that, then we use the MPS tables. */void __initconfig_acpi_tables(void){	memset(&acpi_boot_ops, 0, sizeof(acpi_boot_ops));	acpi_boot_ops[ACPI_APIC] = acpi_parse_madt;	/*	 * Only do this when requested, either because of CPU/Bios type or from the command line	 */	if (enable_acpi_smp_table && !acpi_tables_init()) {		have_acpi_tables = 1;		printk("Enabling the CPU's according to the ACPI table\n");	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -