diff -Naur -X /root/bin/dontdiff a/arch/i386/config.in b/arch/i386/config.in --- a/arch/i386/config.in 2002-12-12 16:52:23.000000000 -0800 +++ b/arch/i386/config.in 2002-12-12 16:57:24.000000000 -0800 @@ -309,14 +309,6 @@ bool 'Power Management support' CONFIG_PM -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_bool ' ACPI support' CONFIG_ACPI $CONFIG_PM - - if [ "$CONFIG_ACPI" != "n" ]; then - source drivers/acpi/Config.in - fi -fi - dep_tristate ' Advanced Power Management BIOS support' CONFIG_APM $CONFIG_PM if [ "$CONFIG_APM" != "n" ]; then bool ' Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND @@ -328,6 +320,8 @@ bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF fi +source drivers/acpi/Config.in + endmenu source drivers/mtd/Config.in diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c --- a/arch/i386/kernel/acpi.c 1969-12-31 16:00:00.000000000 -0800 +++ b/arch/i386/kernel/acpi.c 2002-12-12 16:57:22.000000000 -0800 @@ -0,0 +1,564 @@ +/* + * acpi.c - Architecture-Specific Low-Level ACPI Support + * + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * Copyright (C) 2001 Jun Nakajima + * Copyright (C) 2001 Patrick Mochel + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PREFIX "ACPI: " + +extern int acpi_disabled; + +/* -------------------------------------------------------------------------- + Boot-time Configuration + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_BOOT + +enum acpi_irq_model_id acpi_irq_model; + + +/* + * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, + * 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. + * + * Important Safety Note: The fixed I/O APIC page numbers are *subtracted* + * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and + * count idx down while incrementing the phys address. + */ +char *__acpi_map_table(unsigned long phys, unsigned long size) +{ + unsigned long base, offset, mapped_size; + int idx; + + if (phys + size < 8*1024*1024) + return __va(phys); + + offset = phys & (PAGE_SIZE - 1); + mapped_size = PAGE_SIZE - offset; + set_fixmap(FIX_ACPI_END, phys); + base = fix_to_virt(FIX_ACPI_END); + + /* + * Most cases can be covered by the below. + */ + idx = FIX_ACPI_END; + while (mapped_size < size) { + if (--idx < FIX_ACPI_BEGIN) + return 0; /* cannot handle this */ + phys += PAGE_SIZE; + set_fixmap(idx, phys); + mapped_size += PAGE_SIZE; + } + + return ((unsigned char *) base + offset); +} + + +#ifdef CONFIG_X86_LOCAL_APIC + +int acpi_lapic; + +static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; + + +static int __init +acpi_parse_madt ( + unsigned long phys_addr, + unsigned long size) +{ + struct acpi_table_madt *madt = NULL; + + if (!phys_addr || !size) + return -EINVAL; + + madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size); + if (!madt) { + printk(KERN_WARNING PREFIX "Unable to map MADT\n"); + return -ENODEV; + } + + if (madt->lapic_address) + acpi_lapic_addr = (u64) madt->lapic_address; + + printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", + madt->lapic_address); + + return 0; +} + + +static int __init +acpi_parse_lapic ( + acpi_table_entry_header *header) +{ + struct acpi_table_lapic *processor = NULL; + + processor = (struct acpi_table_lapic*) header; + if (!processor) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + mp_register_lapic ( + processor->id, /* APIC ID */ + processor->flags.enabled); /* Enabled? */ + + return 0; +} + + +static int __init +acpi_parse_lapic_addr_ovr ( + acpi_table_entry_header *header) +{ + struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; + + lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header; + if (!lapic_addr_ovr) + return -EINVAL; + + acpi_lapic_addr = lapic_addr_ovr->address; + + return 0; +} + +#ifndef CONFIG_ACPI_HT_ONLY + +static int __init +acpi_parse_lapic_nmi ( + acpi_table_entry_header *header) +{ + struct acpi_table_lapic_nmi *lapic_nmi = NULL; + + lapic_nmi = (struct acpi_table_lapic_nmi*) header; + if (!lapic_nmi) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + if (lapic_nmi->lint != 1) + printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); + + return 0; +} + +#endif /*CONFIG_ACPI_HT_ONLY*/ + +#endif /*CONFIG_X86_LOCAL_APIC*/ + +#ifdef CONFIG_X86_IO_APIC + +int acpi_ioapic; + +#ifndef CONFIG_ACPI_HT_ONLY + +static int __init +acpi_parse_ioapic ( + acpi_table_entry_header *header) +{ + struct acpi_table_ioapic *ioapic = NULL; + + ioapic = (struct acpi_table_ioapic*) header; + if (!ioapic) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + mp_register_ioapic ( + ioapic->id, + ioapic->address, + ioapic->global_irq_base); + + return 0; +} + + +static int __init +acpi_parse_int_src_ovr ( + acpi_table_entry_header *header) +{ + struct acpi_table_int_src_ovr *intsrc = NULL; + + intsrc = (struct acpi_table_int_src_ovr*) header; + if (!intsrc) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + mp_override_legacy_irq ( + intsrc->bus_irq, + intsrc->flags.polarity, + intsrc->flags.trigger, + intsrc->global_irq); + + return 0; +} + + +static int __init +acpi_parse_nmi_src ( + acpi_table_entry_header *header) +{ + struct acpi_table_nmi_src *nmi_src = NULL; + + nmi_src = (struct acpi_table_nmi_src*) header; + if (!nmi_src) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + /* TBD: Support nimsrc entries? */ + + return 0; +} + +#endif /*!CONFIG_ACPI_HT_ONLY*/ +#endif /*CONFIG_X86_IO_APIC*/ + + +static unsigned long __init +acpi_scan_rsdp ( + unsigned long start, + unsigned long length) +{ + unsigned long offset = 0; + unsigned long sig_len = sizeof("RSD PTR ") - 1; + + /* + * Scan all 16-byte boundaries of the physical memory region for the + * RSDP signature. + */ + for (offset = 0; offset < length; offset += 16) { + if (strncmp((char *) (start + offset), "RSD PTR ", sig_len)) + continue; + return (start + offset); + } + + return 0; +} + + +unsigned long __init +acpi_find_rsdp (void) +{ + unsigned long rsdp_phys = 0; + + /* + * Scan memory looking for the RSDP signature. First search EBDA (low + * memory) paragraphs and then search upper memory (E0000-FFFFF). + */ + rsdp_phys = acpi_scan_rsdp (0, 0x400); + if (!rsdp_phys) + rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF); + + return rsdp_phys; +} + + +int __init +acpi_boot_init ( + char *cmdline) +{ + int result = 0; + + /* + * 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(cmdline); + if (result) + return result; + + result = acpi_blacklisted(); + if (result) { + acpi_disabled = 1; + return result; + } + else + printk(KERN_NOTICE PREFIX "BIOS passes blacklist\n"); + +#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) { + printk(KERN_WARNING PREFIX "MADT not present\n"); + 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; + } + +#ifndef CONFIG_ACPI_HT_ONLY + 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; + } +#endif /*!CONFIG_ACPI_HT_ONLY*/ + + acpi_lapic = 1; + +#endif /*CONFIG_X86_LOCAL_APIC*/ + +#ifdef CONFIG_X86_IO_APIC +#ifndef CONFIG_ACPI_HT_ONLY + + /* + * I/O APIC + * -------- + */ + + 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; + } + + /* Build a default routing table for legacy (ISA) interrupts. */ + mp_config_acpi_legacy_irqs(); + + 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; + } + + 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_ioapic = 1; + +#endif /*!CONFIG_ACPI_HT_ONLY*/ +#endif /*CONFIG_X86_IO_APIC*/ + +#ifdef CONFIG_X86_LOCAL_APIC + if (acpi_lapic && acpi_ioapic) + smp_found_config = 1; +#endif + + return 0; +} + +#endif /*CONFIG_ACPI_BOOT*/ + + +/* -------------------------------------------------------------------------- + Low-Level Sleep Support + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_SLEEP + +#define DEBUG + +#ifdef DEBUG +#include +#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); + printk(KERN_DEBUG "ACPI: have wakeup address 0x%8.8lx\n", acpi_wakeup_address); +} + +#endif /*CONFIG_ACPI_SLEEP*/ + diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/acpitable.c b/arch/i386/kernel/acpitable.c --- a/arch/i386/kernel/acpitable.c 2002-12-12 16:53:31.000000000 -0800 +++ b/arch/i386/kernel/acpitable.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,554 +0,0 @@ -/* - * 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 - * Copyright (C) 2001 Jun Nakajima - * Copyright (C) 2001 Arjan van de Ven - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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.7 2001/11/04 12:21:18 fenrus Exp $ - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "acpitable.h" - -static acpi_table_handler acpi_boot_ops[ACPI_TABLE_COUNT]; - - -static unsigned char __init -acpi_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 __init -acpi_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 *__init -acpi_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 * __init -acpi_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_END, - * 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. - * - * Important Safety Note: The fixed I/O APIC page numbers are *subtracted* - * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and - * count idx down while incrementing the phys address. - */ -static __init char * -__va_range(unsigned long phys, unsigned long size) -{ - unsigned long base, offset, mapped_size; - int idx; - - offset = phys & (PAGE_SIZE - 1); - mapped_size = PAGE_SIZE - offset; - set_fixmap(FIX_IO_APIC_BASE_END, phys); - base = fix_to_virt(FIX_IO_APIC_BASE_END); - dprintk("__va_range(0x%lx, 0x%lx): idx=%d mapped at %lx\n", phys, size, - FIX_IO_APIC_BASE_END, base); - - /* - * Most cases can be covered by the below. - */ - idx = FIX_IO_APIC_BASE_END; - while (mapped_size < size) { - if (--idx < FIX_IO_APIC_BASE_0) - return 0; /* cannot handle this */ - phys += PAGE_SIZE; - set_fixmap(idx, phys); - mapped_size += PAGE_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++) { - /* Map in header, then map in full table length. */ - header = (acpi_table_header *) - __va_range(saved_rsdt.entry[i], - sizeof(acpi_table_header)); - if (!header) - break; - header = (acpi_table_header *) - __va_range(saved_rsdt.entry[i], header->length); - 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 __init -acpi_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 __init -acpi_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 __init -acpi_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 __init -acpi_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 __init -acpi_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 __init -acpi_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 __init -acpi_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 __init -config_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"); - } -} diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/acpitable.h b/arch/i386/kernel/acpitable.h --- a/arch/i386/kernel/acpitable.h 2002-12-12 16:52:29.000000000 -0800 +++ b/arch/i386/kernel/acpitable.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,260 +0,0 @@ -/* - * 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 - * Copyright (C) 2001 Jun Nakajima - * Copyright (C) 2001 Arjan van de Ven - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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.h,v 1.3 2001/11/03 22:41:34 fenrus Exp $ - */ - -/* - * The following codes are cut&pasted from drivers/acpi. Part of the code - * there can be not updated or delivered yet. - * To avoid conflicts when CONFIG_ACPI is defined, the following codes are - * modified so that they are self-contained in this file. - * -- jun - */ - -#ifndef _HEADER_ACPITABLE_H_ -#define _HEADER_ACPITABLE_H_ - -#define dprintk printk -typedef unsigned int ACPI_TBLPTR; - -typedef struct { /* ACPI common table header */ - char signature[4]; /* identifies type of table */ - u32 length; /* length of table, - in bytes, * including header */ - u8 revision; /* specification minor version # */ - u8 checksum; /* to make sum of entire table == 0 */ - char oem_id[6]; /* OEM identification */ - char oem_table_id[8]; /* OEM table identification */ - u32 oem_revision; /* OEM revision number */ - char asl_compiler_id[4]; /* ASL compiler vendor ID */ - u32 asl_compiler_revision; /* ASL compiler revision number */ -} acpi_table_header __attribute__ ((packed));; - -enum { - ACPI_APIC = 0, - ACPI_BOOT, - ACPI_DBGP, - ACPI_DSDT, - ACPI_ECDT, - ACPI_ETDT, - ACPI_FACP, - ACPI_FACS, - ACPI_OEMX, - ACPI_PSDT, - ACPI_SBST, - ACPI_SLIT, - ACPI_SPCR, - ACPI_SRAT, - ACPI_SSDT, - ACPI_SPMI, - ACPI_XSDT, - ACPI_TABLE_COUNT -}; - -static char *acpi_table_signatures[ACPI_TABLE_COUNT] = { - "APIC", - "BOOT", - "DBGP", - "DSDT", - "ECDT", - "ETDT", - "FACP", - "FACS", - "OEM", - "PSDT", - "SBST", - "SLIT", - "SPCR", - "SRAT", - "SSDT", - "SPMI", - "XSDT" -}; - -struct acpi_table_madt { - acpi_table_header header; - u32 lapic_address; - struct { - u32 pcat_compat:1; - u32 reserved:31; - } flags __attribute__ ((packed)); -} __attribute__ ((packed));; - -enum { - ACPI_MADT_LAPIC = 0, - ACPI_MADT_IOAPIC, - ACPI_MADT_INT_SRC_OVR, - ACPI_MADT_NMI_SRC, - ACPI_MADT_LAPIC_NMI, - ACPI_MADT_LAPIC_ADDR_OVR, - ACPI_MADT_IOSAPIC, - ACPI_MADT_LSAPIC, - ACPI_MADT_PLAT_INT_SRC, - ACPI_MADT_ENTRY_COUNT -}; - -#define RSDP_SIG "RSD PTR " -#define RSDT_SIG "RSDT" - -#define ACPI_DEBUG_PRINT(pl) - -#define ACPI_MEMORY_MODE 0x01 -#define ACPI_LOGICAL_ADDRESSING 0x00 -#define ACPI_PHYSICAL_ADDRESSING 0x01 - -#define LO_RSDP_WINDOW_BASE 0 /* Physical Address */ -#define HI_RSDP_WINDOW_BASE 0xE0000 /* Physical Address */ -#define LO_RSDP_WINDOW_SIZE 0x400 -#define HI_RSDP_WINDOW_SIZE 0x20000 -#define RSDP_SCAN_STEP 16 -#define RSDP_CHECKSUM_LENGTH 20 - -typedef int (*acpi_table_handler) (acpi_table_header * header, unsigned long); - -struct acpi_table_rsdp { - char signature[8]; - u8 checksum; - char oem_id[6]; - u8 revision; - u32 rsdt_address; -} __attribute__ ((packed)); - -struct acpi_table_rsdt { - acpi_table_header header; - u32 entry[ACPI_TABLE_COUNT]; -} __attribute__ ((packed)); - -typedef struct { - u8 type; - u8 length; -} acpi_madt_entry_header __attribute__ ((packed)); - -typedef struct { - u16 polarity:2; - u16 trigger:2; - u16 reserved:12; -} acpi_madt_int_flags __attribute__ ((packed)); - -struct acpi_table_lapic { - acpi_madt_entry_header header; - u8 acpi_id; - u8 id; - struct { - u32 enabled:1; - u32 reserved:31; - } flags __attribute__ ((packed)); -} __attribute__ ((packed)); - -struct acpi_table_ioapic { - acpi_madt_entry_header header; - u8 id; - u8 reserved; - u32 address; - u32 global_irq_base; -} __attribute__ ((packed)); - -struct acpi_table_int_src_ovr { - acpi_madt_entry_header header; - u8 bus; - u8 bus_irq; - u32 global_irq; - acpi_madt_int_flags flags; -} __attribute__ ((packed)); - -struct acpi_table_nmi_src { - acpi_madt_entry_header header; - acpi_madt_int_flags flags; - u32 global_irq; -} __attribute__ ((packed)); - -struct acpi_table_lapic_nmi { - acpi_madt_entry_header header; - u8 acpi_id; - acpi_madt_int_flags flags; - u8 lint; -} __attribute__ ((packed)); - -struct acpi_table_lapic_addr_ovr { - acpi_madt_entry_header header; - u8 reserved[2]; - u64 address; -} __attribute__ ((packed)); - -struct acpi_table_iosapic { - acpi_madt_entry_header header; - u8 id; - u8 reserved; - u32 global_irq_base; - u64 address; -} __attribute__ ((packed)); - -struct acpi_table_lsapic { - acpi_madt_entry_header header; - u8 acpi_id; - u8 id; - u8 eid; - u8 reserved[3]; - struct { - u32 enabled:1; - u32 reserved:31; - } flags; -} __attribute__ ((packed)); - -struct acpi_table_plat_int_src { - acpi_madt_entry_header header; - acpi_madt_int_flags flags; - u8 type; - u8 id; - u8 eid; - u8 iosapic_vector; - u32 global_irq; - u32 reserved; -} __attribute__ ((packed)); - -/* - * ACPI Table Descriptor. One per ACPI table - */ -typedef struct acpi_table_desc { - struct acpi_table_desc *prev; - struct acpi_table_desc *next; - struct acpi_table_desc *installed_desc; - acpi_table_header *pointer; - void *base_pointer; - u8 *aml_pointer; - u64 physical_address; - u32 aml_length; - u32 length; - u32 count; - u16 table_id; - u8 type; - u8 allocation; - u8 loaded_into_namespace; - -} acpi_table_desc __attribute__ ((packed));; - -#endif diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/acpi_wakeup.S b/arch/i386/kernel/acpi_wakeup.S --- a/arch/i386/kernel/acpi_wakeup.S 1969-12-31 16:00:00.000000000 -0800 +++ b/arch/i386/kernel/acpi_wakeup.S 2002-12-12 16:57:33.000000000 -0800 @@ -0,0 +1,139 @@ + +.text +#include +#include + + +ALIGN +wakeup_start: +wakeup_code: + wakeup_code_start = . + .code16 + + cli + cld + + # setup data segment + movw %cs, %ax + + addw $(wakeup_data - wakeup_code) >> 4, %ax + movw %ax, %ds + movw %ax, %ss + mov $(wakeup_stack - wakeup_data), %sp # Private stack is needed for ASUS board + + # set up page table + movl (real_save_cr3 - wakeup_data), %eax + movl %eax, %cr3 + + # make sure %cr4 is set correctly (features, etc) + movl (real_save_cr4 - wakeup_data), %eax + movl %eax, %cr4 + + # need a gdt + lgdt real_save_gdt - wakeup_data + + movl %cr0, %eax + orl $0x80000001, %eax + movl %eax, %cr0 + + ljmpl $__KERNEL_CS,$SYMBOL_NAME(wakeup_pmode_return) + + .code32 + ALIGN + +.org 0x100 +wakeup_data: + .word 0 +real_save_gdt: .word 0 + .long 0 +real_save_cr3: .long 0 +real_save_cr4: .long 0 + +.org 0x300 +wakeup_stack: +wakeup_end: + +wakeup_pmode_return: + # restore data segment + movl $__KERNEL_DS, %eax + movw %ax, %ds + movw %ax, %es + + # and restore the stack + movw %ax, %ss + movl saved_esp, %esp + + # restore other segment registers + xorl %eax, %eax + movw %ax, %fs + movw %ax, %gs + + # reload the gdt, as we need the full 32 bit address + lgdt saved_gdt + lidt saved_idt + lldt saved_ldt + + # restore the other general registers + movl saved_ebx, %ebx + movl saved_edi, %edi + movl saved_esi, %esi + movl saved_ebp, %ebp + + # jump to place where we left off + movl saved_eip,%eax + jmp *%eax + +## +# acpi_copy_wakeup_routine +# +# Copy the above routine to low memory. +# +# Parameters: +# %eax: place to copy wakeup routine to +# +# Returned address is location of code in low memory (past data and stack) +# +ENTRY(acpi_copy_wakeup_routine) + + pushl %esi + pushl %edi + + sgdt saved_gdt + sidt saved_idt + sldt saved_ldt + str saved_tss + + movl %eax, %edi + leal wakeup_start, %esi + movl $(wakeup_end - wakeup_start) >> 2, %ecx + + rep ; movsl + + movl %cr3, %edx + movl %edx, real_save_cr3 - wakeup_start (%eax) + movl %cr4, %edx + movl %edx, real_save_cr4 - wakeup_start (%eax) + sgdt real_save_gdt - wakeup_start (%eax) + + # restore the regs we used + popl %edi + popl %esi + ret + + +.data +ALIGN +# saved registers +saved_gdt: .long 0,0 +saved_idt: .long 0,0 +saved_ldt: .long 0 +saved_tss: .long 0 +saved_cr0: .long 0 + +ENTRY(saved_ebp) .long 0 +ENTRY(saved_esi) .long 0 +ENTRY(saved_edi) .long 0 +ENTRY(saved_ebx) .long 0 + +ENTRY(saved_eip) .long 0 +ENTRY(saved_esp) .long 0 diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c 2002-12-12 16:52:24.000000000 -0800 +++ b/arch/i386/kernel/io_apic.c 2002-12-12 16:57:25.000000000 -0800 @@ -17,6 +17,7 @@ * thanks to Eric Gilmore * and Rolf G. Tews * for testing these extensively + * Paul Diefenbaugh : Added full ACPI support */ #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include @@ -1052,6 +1054,10 @@ unsigned char old_id; unsigned long flags; + if (acpi_ioapic) + /* This gets done during IOAPIC enumeration for ACPI. */ + return; + if (clustered_apic_mode) /* We don't have a good way to do this yet - hack */ phys_id_present_map = (u_long) 0xf; @@ -1652,8 +1658,7 @@ printk("ENABLING IO-APIC IRQs\n"); /* - * Set up the IO-APIC IRQ routing table by parsing the MP-BIOS - * mptable: + * Set up IO-APIC IRQ routing. */ setup_ioapic_ids_from_mpc(); sync_Arb_IDs(); @@ -1662,3 +1667,159 @@ check_timer(); print_IO_APIC(); } + + +/* -------------------------------------------------------------------------- + ACPI-based IOAPIC Configuration + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_BOOT + +#define IO_APIC_MAX_ID 15 + +int __init io_apic_get_unique_id (int ioapic, int apic_id) +{ + struct IO_APIC_reg_00 reg_00; + static unsigned long apic_id_map = 0; + unsigned long flags; + int i = 0; + + /* + * The P4 platform supports up to 256 APIC IDs on two separate APIC + * buses (one for LAPICs, one for IOAPICs), where predecessors only + * supports up to 16 on one shared APIC bus. + * + * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full + * advantage of new APIC bus architecture. + */ + + if (!apic_id_map) + apic_id_map = phys_cpu_present_map; + + spin_lock_irqsave(&ioapic_lock, flags); + *(int *)®_00 = io_apic_read(ioapic, 0); + spin_unlock_irqrestore(&ioapic_lock, flags); + + if (apic_id >= IO_APIC_MAX_ID) { + printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " + "%d\n", ioapic, apic_id, reg_00.ID); + apic_id = reg_00.ID; + } + + /* + * Every APIC in a system must have a unique ID or we get lots of nice + * 'stuck on smp_invalidate_needed IPI wait' messages. + */ + if (apic_id_map & (1 << apic_id)) { + + for (i = 0; i < IO_APIC_MAX_ID; i++) { + if (!(apic_id_map & (1 << i))) + break; + } + + if (i == IO_APIC_MAX_ID) + panic("Max apic_id exceeded!\n"); + + printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " + "trying %d\n", ioapic, apic_id, i); + + apic_id = i; + } + + apic_id_map |= (1 << apic_id); + + if (reg_00.ID != apic_id) { + reg_00.ID = apic_id; + + spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(ioapic, 0, *(int *)®_00); + *(int *)®_00 = io_apic_read(ioapic, 0); + spin_unlock_irqrestore(&ioapic_lock, flags); + + /* Sanity check */ + if (reg_00.ID != apic_id) + panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); + } + + printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); + + return apic_id; +} + + +int __init io_apic_get_version (int ioapic) +{ + struct IO_APIC_reg_01 reg_01; + unsigned long flags; + + spin_lock_irqsave(&ioapic_lock, flags); + *(int *)®_01 = io_apic_read(ioapic, 1); + spin_unlock_irqrestore(&ioapic_lock, flags); + + return reg_01.version; +} + + +int __init io_apic_get_redir_entries (int ioapic) +{ + struct IO_APIC_reg_01 reg_01; + unsigned long flags; + + spin_lock_irqsave(&ioapic_lock, flags); + *(int *)®_01 = io_apic_read(ioapic, 1); + spin_unlock_irqrestore(&ioapic_lock, flags); + + return reg_01.entries; +} + + +int io_apic_set_pci_routing (int ioapic, int pin, int irq) +{ + struct IO_APIC_route_entry entry; + unsigned long flags; + + if (!IO_APIC_IRQ(irq)) { + printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0/n", + ioapic); + return -EINVAL; + } + + /* + * Generate a PCI IRQ routing entry and program the IOAPIC accordingly. + * Note that we mask (disable) IRQs now -- these get enabled when the + * corresponding device driver registers for this IRQ. + */ + + memset(&entry,0,sizeof(entry)); + + entry.delivery_mode = dest_LowestPrio; + entry.dest_mode = INT_DELIVERY_MODE; + entry.dest.logical.logical_dest = target_cpus(); + entry.mask = 1; /* Disabled (masked) */ + entry.trigger = 1; /* Level sensitive */ + entry.polarity = 1; /* Low active */ + + add_pin_to_irq(irq, ioapic, pin); + + entry.vector = assign_irq_vector(irq); + + printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " + "IRQ %d)\n", ioapic, + mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq); + + irq_desc[irq].handler = &ioapic_level_irq_type; + + set_intr_gate(entry.vector, interrupt[irq]); + + if (!ioapic && (irq < 16)) + disable_8259A_irq(irq); + + spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); + spin_unlock_irqrestore(&ioapic_lock, flags); + + return 0; +} + +#endif /*CONFIG_ACPI_BOOT*/ diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile 2002-12-12 16:52:10.000000000 -0800 +++ b/arch/i386/kernel/Makefile 2002-12-12 16:57:20.000000000 -0800 @@ -36,9 +36,11 @@ obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_APM) += apm.o +obj-$(CONFIG_ACPI) += acpi.o +obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o -obj-$(CONFIG_X86_IO_APIC) += io_apic.o acpitable.o +obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o include $(TOPDIR)/Rules.make diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c 2002-12-12 16:52:22.000000000 -0800 +++ b/arch/i386/kernel/mpparse.c 2002-12-12 16:57:24.000000000 -0800 @@ -9,12 +9,14 @@ * Erich Boleyn : MP v1.4 and additional changes. * Alan Cox : Added EBDA scanning * Ingo Molnar : various cleanups and rewrites - * Maciej W. Rozycki : Bits for default MP configurations + * Maciej W. Rozycki: Bits for default MP configurations + * Paul Diefenbaugh: Added full ACPI support */ #include #include #include +#include #include #include #include @@ -23,10 +25,12 @@ #include #include +#include #include #include #include #include +#include /* Have we found an MP table */ int smp_found_config; @@ -133,12 +137,6 @@ return n; } -#ifdef CONFIG_X86_IO_APIC -extern int have_acpi_tables; /* set by acpitable.c */ -#else -#define have_acpi_tables (0) -#endif - /* * Have to match translation table entries to main table entries by counter * hence the mpc_record variable .... can't see a less disgusting way of @@ -440,10 +438,11 @@ printk("APIC at: 0x%lX\n",mpc->mpc_lapic); - /* save the local APIC address, it might be non-default, - * but only if we're not using the ACPI tables + /* + * Save the local APIC address (it might be non-default) -- but only + * if we're not using ACPI. */ - if (!have_acpi_tables) + if (!acpi_lapic) mp_lapic_addr = mpc->mpc_lapic; if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ) && mpc->mpc_oemptr) { @@ -462,9 +461,8 @@ { struct mpc_config_processor *m= (struct mpc_config_processor *)mpt; - - /* ACPI may already have provided this one for us */ - if (!have_acpi_tables) + /* ACPI may have already provided this data */ + if (!acpi_lapic) MP_processor_info(m); mpt += sizeof(*m); count += sizeof(*m); @@ -693,7 +691,6 @@ } static struct intel_mp_floating *mpf_found; -extern void config_acpi_tables(void); /* * Scan the memory blocks for an SMP configuration block. @@ -702,17 +699,19 @@ { struct intel_mp_floating *mpf = mpf_found; -#ifdef CONFIG_X86_IO_APIC /* - * Check if the ACPI tables are provided. Use them only to get - * the processor information, mainly because it provides - * the info on the logical processor(s), rather than the physical - * processor(s) that are provided by the MPS. We attempt to - * check only if the user provided a commandline override + * ACPI may be used to obtain the entire SMP configuration or just to + * enumerate/configure processors (CONFIG_ACPI_HT_ONLY). Note that + * ACPI supports both logical (e.g. Hyper-Threading) and physical + * processors, where MPS only supports physical. */ - config_acpi_tables(); -#endif - + if (acpi_lapic && acpi_ioapic) { + printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n"); + return; + } + else if (acpi_lapic) + printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n"); + printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); if (mpf->mpf_feature2 & (1<<7)) { printk(" IMCR and PIC compatibility mode.\n"); @@ -873,3 +872,358 @@ #endif } + +/* -------------------------------------------------------------------------- + ACPI-based MP Configuration + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_BOOT + +void __init mp_register_lapic_address ( + u64 address) +{ + mp_lapic_addr = (unsigned long) address; + + set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); + + if (boot_cpu_physical_apicid == -1U) + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); + + Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid); +} + + +void __init mp_register_lapic ( + u8 id, + u8 enabled) +{ + struct mpc_config_processor processor; + int boot_cpu = 0; + + if (id >= MAX_APICS) { + printk(KERN_WARNING "Processor #%d invalid (max %d)\n", + id, MAX_APICS); + return; + } + + if (id == boot_cpu_physical_apicid) + boot_cpu = 1; + + processor.mpc_type = MP_PROCESSOR; + processor.mpc_apicid = id; + processor.mpc_apicver = 0x10; /* TBD: lapic version */ + processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0); + processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0); + processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | + (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; + processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; + processor.mpc_reserved[0] = 0; + processor.mpc_reserved[1] = 0; + + MP_processor_info(&processor); +} + +#ifdef CONFIG_X86_IO_APIC + +#define MP_ISA_BUS 0 +#define MP_MAX_IOAPIC_PIN 127 + +struct mp_ioapic_routing { + int apic_id; + int irq_start; + int irq_end; + u32 pin_programmed[4]; +} mp_ioapic_routing[MAX_IO_APICS]; + + +static int __init mp_find_ioapic ( + int irq) +{ + int i = 0; + + /* Find the IOAPIC that manages this IRQ. */ + for (i = 0; i < nr_ioapics; i++) { + if ((irq >= mp_ioapic_routing[i].irq_start) + && (irq <= mp_ioapic_routing[i].irq_end)) + return i; + } + + printk(KERN_ERR "ERROR: Unable to locate IOAPIC for IRQ %d/n", irq); + + return -1; +} + + +void __init mp_register_ioapic ( + u8 id, + u32 address, + u32 irq_base) +{ + int idx = 0; + + if (nr_ioapics >= MAX_IO_APICS) { + printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " + "(found %d)\n", MAX_IO_APICS, nr_ioapics); + panic("Recompile kernel with bigger MAX_IO_APICS!\n"); + } + if (!address) { + printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" + " found in MADT table, skipping!\n"); + return; + } + + idx = nr_ioapics++; + + mp_ioapics[idx].mpc_type = MP_IOAPIC; + mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; + mp_ioapics[idx].mpc_apicaddr = address; + + set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); + mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); + mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); + + /* + * Build basic IRQ lookup table to facilitate irq->io_apic lookups + * and to prevent reprogramming of IOAPIC pins (PCI IRQs). + */ + mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; + mp_ioapic_routing[idx].irq_start = irq_base; + mp_ioapic_routing[idx].irq_end = irq_base + + io_apic_get_redir_entries(idx); + + printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, " + "IRQ %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, + mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, + mp_ioapic_routing[idx].irq_start, + mp_ioapic_routing[idx].irq_end); + + return; +} + + +void __init mp_override_legacy_irq ( + u8 bus_irq, + u8 polarity, + u8 trigger, + u32 global_irq) +{ + struct mpc_config_intsrc intsrc; + int i = 0; + int found = 0; + int ioapic = -1; + int pin = -1; + + /* + * Convert 'global_irq' to 'ioapic.pin'. + */ + ioapic = mp_find_ioapic(global_irq); + if (ioapic < 0) + return; + pin = global_irq - mp_ioapic_routing[ioapic].irq_start; + + /* + * TBD: This check is for faulty timer entries, where the override + * erroneously sets the trigger to level, resulting in a HUGE + * increase of timer interrupts! + */ + if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3)) + trigger = 1; + + intsrc.mpc_type = MP_INTSRC; + intsrc.mpc_irqtype = mp_INT; + intsrc.mpc_irqflag = (trigger << 2) | polarity; + intsrc.mpc_srcbus = MP_ISA_BUS; + intsrc.mpc_srcbusirq = bus_irq; /* IRQ */ + intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ + intsrc.mpc_dstirq = pin; /* INTIN# */ + + Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n", + intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, + (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, + intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq); + + /* + * If an existing [IOAPIC.PIN -> IRQ] routing entry exists we override it. + * Otherwise create a new entry (e.g. global_irq == 2). + */ + for (i = 0; i < mp_irq_entries; i++) { + if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) + && (mp_irqs[i].mpc_dstirq == intsrc.mpc_dstirq)) { + mp_irqs[i] = intsrc; + found = 1; + break; + } + } + if (!found) { + mp_irqs[mp_irq_entries] = intsrc; + if (++mp_irq_entries == MAX_IRQ_SOURCES) + panic("Max # of irq sources exceeded!\n"); + } + + return; +} + + +void __init mp_config_acpi_legacy_irqs (void) +{ + struct mpc_config_intsrc intsrc; + int i = 0; + int ioapic = -1; + + /* + * Fabricate the legacy ISA bus (bus #31). + */ + mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; + Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); + + /* + * Locate the IOAPIC that manages the ISA IRQs (0-15). + */ + ioapic = mp_find_ioapic(0); + if (ioapic < 0) + return; + + intsrc.mpc_type = MP_INTSRC; + intsrc.mpc_irqflag = 0; /* Conforming */ + intsrc.mpc_srcbus = MP_ISA_BUS; + intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; + + /* + * Use the default configuration for the IRQs 0-15. These may be + * overriden by (MADT) interrupt source override entries. + */ + for (i = 0; i < 16; i++) { + + if (i == 2) continue; /* Don't connect IRQ2 */ + + intsrc.mpc_irqtype = i ? mp_INT : mp_ExtINT; /* 8259A to #0 */ + intsrc.mpc_srcbusirq = i; /* Identity mapped */ + intsrc.mpc_dstirq = i; + + Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, " + "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, + (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, + intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, + intsrc.mpc_dstirq); + + mp_irqs[mp_irq_entries] = intsrc; + if (++mp_irq_entries == MAX_IRQ_SOURCES) + panic("Max # of irq sources exceeded!\n"); + } +} + +#ifndef CONFIG_ACPI_HT_ONLY + +/* Ensure the ACPI SCI interrupt level is active low, edge-triggered */ + +extern FADT_DESCRIPTOR acpi_fadt; + +void __init mp_config_ioapic_for_sci(int irq) +{ + int ioapic; + int ioapic_pin; + struct acpi_table_madt* madt; + struct acpi_table_int_src_ovr *entry = NULL; + void *madt_end; + acpi_status status; + + /* + * Ensure that if there is an interrupt source override entry + * for the ACPI SCI, we leave it as is. Unfortunately this involves + * walking the MADT again. + */ + status = acpi_get_firmware_table("APIC", 1, ACPI_LOGICAL_ADDRESSING, + (acpi_table_header **) &madt); + if (ACPI_SUCCESS(status)) { + madt_end = (void *) (unsigned long)madt + madt->header.length; + + entry = (struct acpi_table_int_src_ovr *) + ((unsigned long) madt + sizeof(struct acpi_table_madt)); + + while ((void *) entry < madt_end) { + if (entry->header.type == ACPI_MADT_INT_SRC_OVR && + acpi_fadt.sci_int == entry->global_irq) + return; + + entry = (struct acpi_table_int_src_ovr *) + ((unsigned long) entry + entry->header.length); + } + } + + ioapic = mp_find_ioapic(irq); + + ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; + + io_apic_set_pci_routing(ioapic, ioapic_pin, irq); +} + +#endif /*CONFIG_ACPI_HT_ONLY*/ + +#ifdef CONFIG_ACPI_PCI + +void __init mp_parse_prt (void) +{ + struct list_head *node = NULL; + struct acpi_prt_entry *entry = NULL; + int ioapic = -1; + int ioapic_pin = 0; + int irq = 0; + int idx, bit = 0; + + /* + * Parsing through the PCI Interrupt Routing Table (PRT) and program + * routing for all static (IOAPIC-direct) entries. + */ + list_for_each(node, &acpi_prt.entries) { + entry = list_entry(node, struct acpi_prt_entry, node); + + /* We're only interested in static (non-link) entries. */ + if (entry->link.handle) + continue; + + irq = entry->link.index; + ioapic = mp_find_ioapic(irq); + if (ioapic < 0) + continue; + ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; + + /* + * Avoid pin reprogramming. PRTs typically include entries + * with redundant pin->irq mappings (but unique PCI devices); + * we only only program the IOAPIC on the first. + */ + bit = ioapic_pin % 32; + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); + if (idx > 3) { + printk(KERN_ERR "Invalid reference to IOAPIC pin " + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, + ioapic_pin); + continue; + } + if ((1<irq = irq; + continue; + } + + mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<irq = irq; + + printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n", + entry->id.segment, entry->id.bus, + entry->id.device, ('A' + entry->pin), + mp_ioapic_routing[ioapic].apic_id, ioapic_pin, + entry->irq); + } + + return; +} + +#endif /*CONFIG_ACPI_PCI*/ + +#endif /*CONFIG_X86_IO_APIC*/ + +#endif /*CONFIG_ACPI_BOOT*/ diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c --- a/arch/i386/kernel/pci-irq.c 2002-12-12 16:53:39.000000000 -0800 +++ b/arch/i386/kernel/pci-irq.c 2002-12-12 16:58:01.000000000 -0800 @@ -115,7 +115,7 @@ * Code for querying and setting of IRQ routes on various interrupt routers. */ -static void eisa_set_level_irq(unsigned int irq) +void eisa_set_level_irq(unsigned int irq) { unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c --- a/arch/i386/kernel/pci-pc.c 2002-12-12 16:52:31.000000000 -0800 +++ b/arch/i386/kernel/pci-pc.c 2002-12-12 16:57:27.000000000 -0800 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,8 @@ int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL; int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL; +static int pci_using_acpi_prt = 0; + #ifdef CONFIG_MULTIQUAD #define BUS2QUAD(global) (mp_bus_id_to_node[global]) #define BUS2LOCAL(global) (mp_bus_id_to_local[global]) @@ -1353,6 +1356,23 @@ pci_read_bridge_bases(b); } +struct pci_bus * __devinit pcibios_scan_root(int busnum) +{ + struct list_head *list; + struct pci_bus *bus; + + list_for_each(list, &pci_root_buses) { + bus = pci_bus_b(list); + if (bus->number == busnum) { + /* Already scanned */ + return bus; + } + } + + printk("PCI: Probing PCI hardware (bus %02x)\n", busnum); + + return pci_scan_bus(busnum, pci_root_ops, NULL); +} void __devinit pcibios_config_init(void) { @@ -1394,6 +1414,8 @@ return; } +int use_acpi_pci __initdata = 1; + void __init pcibios_init(void) { int quad; @@ -1406,7 +1428,19 @@ } printk(KERN_INFO "PCI: Probing PCI hardware\n"); - pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); +#ifdef CONFIG_ACPI_PCI + if (use_acpi_pci && !acpi_pci_irq_init()) { + pci_using_acpi_prt = 1; + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); + printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi' or even 'acpi=off'\n"); + } +#endif + if (!pci_using_acpi_prt) { + pci_root_bus = pcibios_scan_root(0); + pcibios_irq_init(); + pcibios_fixup_peer_bridges(); + pcibios_fixup_irqs(); + } if (clustered_apic_mode && (numnodes > 1)) { for (quad = 1; quad < numnodes; ++quad) { printk("Scanning PCI bus %d for quad %d\n", @@ -1416,9 +1450,6 @@ } } - pcibios_irq_init(); - pcibios_fixup_peer_bridges(); - pcibios_fixup_irqs(); pcibios_resource_survey(); #ifdef CONFIG_PCI_BIOS @@ -1470,6 +1501,9 @@ } else if (!strncmp(str, "lastbus=", 8)) { pcibios_last_bus = simple_strtol(str+8, NULL, 0); return NULL; + } else if (!strncmp(str, "noacpi", 6)) { + use_acpi_pci = 0; + return NULL; } return str; } @@ -1485,6 +1519,15 @@ if ((err = pcibios_enable_resources(dev, mask)) < 0) return err; + +#ifdef CONFIG_ACPI_PCI + if (pci_using_acpi_prt) { + acpi_pci_irq_enable(dev); + return 0; + } +#endif + pcibios_enable_irq(dev); + return 0; } diff -Naur -X /root/bin/dontdiff a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c 2002-12-12 16:53:17.000000000 -0800 +++ b/arch/i386/kernel/setup.c 2002-12-12 16:57:29.000000000 -0800 @@ -92,6 +92,7 @@ #include #include #include +#include #include #ifdef CONFIG_BLK_DEV_RAM #include @@ -169,9 +170,10 @@ static int disable_x86_serial_nr __initdata = 1; static int disable_x86_ht __initdata = 0; static u32 disabled_x86_caps[NCAPINTS] __initdata = { 0 }; -extern int blk_nohighio; -int enable_acpi_smp_table; +int acpi_disabled __initdata = 0; + +extern int blk_nohighio; /* * This is set up by the setup-routine at boot-time @@ -788,9 +790,9 @@ set_bit(X86_FEATURE_HT, disabled_x86_caps); } - /* "acpismp=force" forces parsing and use of the ACPI SMP table */ - else if (!memcmp(from, "acpismp=force", 13)) - enable_acpi_smp_table = 1; + /* "acpi=off" disables both ACPI table parsing and interpreter init */ + else if (!memcmp(from, "acpi=off", 8)) + acpi_disabled = 1; /* * highmem=size forces highmem to be exactly 'size' bytes. @@ -1000,10 +1002,15 @@ */ reserve_bootmem(PAGE_SIZE, PAGE_SIZE); #endif - +#ifdef CONFIG_ACPI_SLEEP + /* + * Reserve low memory region for sleep support. + */ + acpi_reserve_bootmem(); +#endif #ifdef CONFIG_X86_LOCAL_APIC /* - * Find and reserve possible boot-time SMP configuration: + * Find and reserve possible boot-time SMP configuration. */ find_smp_config(); #endif @@ -1036,7 +1043,6 @@ { unsigned long low_mem_size; int i; - probe_roms(); for (i = 0; i < e820.nr_map; i++) { struct resource *res; @@ -1122,21 +1128,10 @@ max_low_pfn = setup_memory(); - /* - * If enable_acpi_smp_table and HT feature present, acpitable.c - * will find all logical cpus despite disable_x86_ht: so if both - * "noht" and "acpismp=force" are specified, let "noht" override - * "acpismp=force" cleanly. Why retain "acpismp=force"? because - * parsing ACPI SMP table might prove useful on some non-HT cpu. - */ if (disable_x86_ht) { clear_bit(X86_FEATURE_HT, &boot_cpu_data.x86_capability[0]); set_bit(X86_FEATURE_HT, disabled_x86_caps); - enable_acpi_smp_table = 0; } - if (test_bit(X86_FEATURE_HT, &boot_cpu_data.x86_capability[0])) - enable_acpi_smp_table = 1; - /* * NOTE: before this point _nobody_ is allowed to allocate @@ -1147,6 +1142,13 @@ smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ #endif paging_init(); +#ifdef CONFIG_ACPI_BOOT + /* + * Parse the ACPI tables for possible boot-time SMP configuration. + */ + if (!acpi_disabled) + acpi_boot_init(*cmdline_p); +#endif #ifdef CONFIG_X86_LOCAL_APIC /* * get boot-time SMP configuration: diff -Naur -X /root/bin/dontdiff a/Documentation/Configure.help b/Documentation/Configure.help --- a/Documentation/Configure.help 2002-12-12 16:53:36.000000000 -0800 +++ b/Documentation/Configure.help 2002-12-12 16:57:52.000000000 -0800 @@ -18492,6 +18492,30 @@ This driver handles overheating conditions on laptops. It is HIGHLY recommended, as your laptop CPU may be damaged without it. +ACPI Toshiba Laptop Extras +CONFIG_ACPI_TOSHIBA + This driver adds support for access to certain system settings + on "legacy free" Toshiba laptops. These laptops can be recognized by + their lack of a BIOS setup menu and APM support. + + On these machines, all system configuration is handled through the + ACPI. This driver is required for access to controls not covered + by the general ACPI drivers, such as LCD brightness, video output, + etc. + + This driver differs from the non-ACPI Toshiba laptop driver (located + under "Processor type and features") in several aspects. + Configuration is accessed by reading and writing text files in the + /proc tree instead of by program interface to /dev. Furthermore, no + power management functions are exposed, as those are handled by the + general ACPI drivers. + + More information about this driver is available at + . + + If you have a legacy free Toshiba laptop (such as the Libretto L1 + series), say Y. + Advanced Power Management BIOS support CONFIG_APM APM is a BIOS specification for saving power using several different diff -Naur -X /root/bin/dontdiff a/drivers/acpi/ac.c b/drivers/acpi/ac.c --- a/drivers/acpi/ac.c 1969-12-31 16:00:00.000000000 -0800 +++ b/drivers/acpi/ac.c 2002-12-12 16:57:41.000000000 -0800 @@ -0,0 +1,344 @@ +/* + * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 26 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_AC_COMPONENT +ACPI_MODULE_NAME ("acpi_ac") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +int acpi_ac_add (struct acpi_device *device); +int acpi_ac_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_ac_driver = { + .name = ACPI_AC_DRIVER_NAME, + .class = ACPI_AC_CLASS, + .ids = ACPI_AC_HID, + .ops = { + .add = acpi_ac_add, + .remove = acpi_ac_remove, + }, +}; + +struct acpi_ac { + acpi_handle handle; + unsigned long state; +}; + + +/* -------------------------------------------------------------------------- + AC Adapter Management + -------------------------------------------------------------------------- */ + +static int +acpi_ac_get_state ( + struct acpi_ac *ac) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_ac_get_state"); + + if (!ac) + return_VALUE(-EINVAL); + + status = acpi_evaluate_integer(ac->handle, "_PSR", NULL, &ac->state); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading AC Adapter state\n")); + ac->state = ACPI_AC_STATUS_UNKNOWN; + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +struct proc_dir_entry *acpi_ac_dir = NULL; + +static int +acpi_ac_read_state ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_ac *ac = (struct acpi_ac *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_ac_read_state"); + + if (!ac || (off != 0)) + goto end; + + if (acpi_ac_get_state(ac)) { + p += sprintf(p, "ERROR: Unable to read AC Adapter state\n"); + goto end; + } + + p += sprintf(p, "state: "); + switch (ac->state) { + case ACPI_AC_STATUS_OFFLINE: + p += sprintf(p, "off-line\n"); + break; + case ACPI_AC_STATUS_ONLINE: + p += sprintf(p, "on-line\n"); + break; + default: + p += sprintf(p, "unknown\n"); + break; + } + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_ac_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_add_fs"); + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_ac_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'state' [R] */ + entry = create_proc_entry(ACPI_AC_FILE_STATE, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_AC_FILE_STATE)); + else { + entry->read_proc = acpi_ac_read_state; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_ac_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_ac_remove_fs"); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Model + -------------------------------------------------------------------------- */ + +void +acpi_ac_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + struct acpi_ac *ac = (struct acpi_ac *) data; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_notify"); + + if (!ac) + return; + + if (acpi_bus_get_device(ac->handle, &device)) + return_VOID; + + switch (event) { + case ACPI_AC_NOTIFY_STATUS: + acpi_ac_get_state(ac); + acpi_bus_generate_event(device, event, (u32) ac->state); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +int +acpi_ac_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_ac *ac = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_add"); + + if (!device) + return_VALUE(-EINVAL); + + ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL); + if (!ac) + return_VALUE(-ENOMEM); + memset(ac, 0, sizeof(struct acpi_ac)); + + ac->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_AC_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_AC_CLASS); + acpi_driver_data(device) = ac; + + result = acpi_ac_get_state(ac); + if (result) + goto end; + + result = acpi_ac_add_fs(device); + if (result) + goto end; + + status = acpi_install_notify_handler(ac->handle, + ACPI_DEVICE_NOTIFY, acpi_ac_notify, ac); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", + acpi_device_name(device), acpi_device_bid(device), + ac->state?"on-line":"off-line"); + +end: + if (result) { + acpi_ac_remove_fs(device); + kfree(ac); + } + + return_VALUE(result); +} + + +int +acpi_ac_remove ( + struct acpi_device *device, + int type) +{ + acpi_status status = AE_OK; + struct acpi_ac *ac = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + ac = (struct acpi_ac *) acpi_driver_data(device); + + status = acpi_remove_notify_handler(ac->handle, + ACPI_DEVICE_NOTIFY, acpi_ac_notify); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + + acpi_ac_remove_fs(device); + + kfree(ac); + + return_VALUE(0); +} + + +int __init +acpi_ac_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ac_init"); + + acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); + if (!acpi_ac_dir) + return_VALUE(-ENODEV); + + result = acpi_bus_register_driver(&acpi_ac_driver); + if (result < 0) { + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +void __exit +acpi_ac_exit (void) +{ + ACPI_FUNCTION_TRACE("acpi_ac_exit"); + + acpi_bus_unregister_driver(&acpi_ac_driver); + + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_ac_init); +module_exit(acpi_ac_exit); diff -Naur -X /root/bin/dontdiff a/drivers/acpi/acpi_bus.h b/drivers/acpi/acpi_bus.h --- a/drivers/acpi/acpi_bus.h 1969-12-31 16:00:00.000000000 -0800 +++ b/drivers/acpi/acpi_bus.h 2002-12-12 16:57:24.000000000 -0800 @@ -0,0 +1,299 @@ +/* + * acpi_bus.h - ACPI Bus Driver ($Revision: 22 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#ifndef __ACPI_BUS_H__ +#define __ACPI_BUS_H__ + +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,4)) +#include +#define CONFIG_LDM +#endif + +#include "include/acpi.h" + + +/* TBD: Make dynamic */ +#define ACPI_MAX_HANDLES 10 +struct acpi_handle_list { + u32 count; + acpi_handle handles[ACPI_MAX_HANDLES]; +}; + + +/* acpi_utils.h */ +acpi_status acpi_extract_package (acpi_object *, acpi_buffer *, acpi_buffer *); +acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, acpi_object_list *, unsigned long *); +acpi_status acpi_evaluate_reference (acpi_handle, acpi_string, acpi_object_list *, struct acpi_handle_list *); + +#ifdef CONFIG_ACPI_BUS + +#include + +#define ACPI_BUS_FILE_ROOT "acpi" +extern struct proc_dir_entry *acpi_root_dir; +extern FADT_DESCRIPTOR acpi_fadt; + +enum acpi_bus_removal_type { + ACPI_BUS_REMOVAL_NORMAL = 0, + ACPI_BUS_REMOVAL_EJECT, + ACPI_BUS_REMOVAL_SUPRISE, + ACPI_BUS_REMOVAL_TYPE_COUNT +}; + +enum acpi_bus_device_type { + ACPI_BUS_TYPE_DEVICE = 0, + ACPI_BUS_TYPE_POWER, + ACPI_BUS_TYPE_PROCESSOR, + ACPI_BUS_TYPE_THERMAL, + ACPI_BUS_TYPE_SYSTEM, + ACPI_BUS_TYPE_POWER_BUTTON, + ACPI_BUS_TYPE_SLEEP_BUTTON, + ACPI_BUS_DEVICE_TYPE_COUNT +}; + +struct acpi_driver; +struct acpi_device; + + +/* + * ACPI Driver + * ----------- + */ + +typedef int (*acpi_op_add) (struct acpi_device *device); +typedef int (*acpi_op_remove) (struct acpi_device *device, int type); +typedef int (*acpi_op_lock) (struct acpi_device *device, int type); +typedef int (*acpi_op_start) (struct acpi_device *device); +typedef int (*acpi_op_stop) (struct acpi_device *device, int type); +typedef int (*acpi_op_suspend) (struct acpi_device *device, int state); +typedef int (*acpi_op_resume) (struct acpi_device *device, int state); +typedef int (*acpi_op_scan) (struct acpi_device *device); +typedef int (*acpi_op_bind) (struct acpi_device *device); + +struct acpi_device_ops { + acpi_op_add add; + acpi_op_remove remove; + acpi_op_lock lock; + acpi_op_start start; + acpi_op_stop stop; + acpi_op_suspend suspend; + acpi_op_resume resume; + acpi_op_scan scan; + acpi_op_bind bind; +}; + +struct acpi_driver { + struct list_head node; + char name[80]; + char class[80]; + int references; + char *ids; /* Supported Hardware IDs */ + struct acpi_device_ops ops; +}; + +/* + * ACPI Device + * ----------- + */ + +/* Status (_STA) */ + +struct acpi_device_status { + u32 present:1; + u32 enabled:1; + u32 show_in_ui:1; + u32 functional:1; + u32 battery_present:1; + u32 reserved:27; +}; + + +/* Flags */ + +struct acpi_device_flags { + u32 dynamic_status:1; + u32 hardware_id:1; + u32 compatible_ids:1; + u32 bus_address:1; + u32 unique_id:1; + u32 removable:1; + u32 ejectable:1; + u32 lockable:1; + u32 suprise_removal_ok:1; + u32 power_manageable:1; + u32 performance_manageable:1; + u32 reserved:21; +}; + + +/* File System */ + +struct acpi_device_dir { + struct proc_dir_entry *entry; +}; + +#define acpi_device_dir(d) ((d)->dir.entry) + + +/* Plug and Play */ + +typedef char acpi_bus_id[5]; +typedef unsigned long acpi_bus_address; +typedef char acpi_hardware_id[9]; +typedef char acpi_unique_id[9]; +typedef char acpi_device_name[40]; +typedef char acpi_device_class[20]; + +struct acpi_device_pnp { + acpi_bus_id bus_id; /* Object name */ + acpi_bus_address bus_address; /* _ADR */ + acpi_hardware_id hardware_id; /* _HID */ + acpi_unique_id unique_id; /* _UID */ + acpi_device_name device_name; /* Driver-determined */ + acpi_device_class device_class; /* " */ +}; + +#define acpi_device_bid(d) ((d)->pnp.bus_id) +#define acpi_device_adr(d) ((d)->pnp.bus_address) +#define acpi_device_hid(d) ((d)->pnp.hardware_id) +#define acpi_device_uid(d) ((d)->pnp.unique_id) +#define acpi_device_name(d) ((d)->pnp.device_name) +#define acpi_device_class(d) ((d)->pnp.device_class) + + +/* Power Management */ + +struct acpi_device_power_flags { + u32 explicit_get:1; /* _PSC present? */ + u32 power_resources:1; /* Power resources */ + u32 inrush_current:1; /* Serialize Dx->D0 */ + u32 wake_capable:1; /* Wakeup supported? */ + u32 wake_enabled:1; /* Enabled for wakeup */ + u32 power_removed:1; /* Optimize Dx->D0 */ + u32 reserved:26; +}; + +struct acpi_device_power_state { + struct { + u8 valid:1; + u8 explicit_set:1; /* _PSx present? */ + u8 reserved:6; + } flags; + int power; /* % Power (compared to D0) */ + int latency; /* Dx->D0 time (microseconds) */ + struct acpi_handle_list resources; /* Power resources referenced */ +}; + +struct acpi_device_power { + int state; /* Current state */ + struct acpi_device_power_flags flags; + struct acpi_device_power_state states[4]; /* Power states (D0-D3) */ +}; + + +/* Performance Management */ + +struct acpi_device_perf_flags { + u8 reserved:8; +}; + +struct acpi_device_perf_state { + struct { + u8 valid:1; + u8 reserved:7; + } flags; + u8 power; /* % Power (compared to P0) */ + u8 performance; /* % Performance ( " ) */ + int latency; /* Px->P0 time (microseconds) */ +}; + +struct acpi_device_perf { + int state; + struct acpi_device_perf_flags flags; + int state_count; + struct acpi_device_perf_state *states; +}; + + +/* Device */ + +struct acpi_device { + acpi_handle handle; + struct acpi_device *parent; + struct list_head children; + struct list_head node; + struct acpi_device_status status; + struct acpi_device_flags flags; + struct acpi_device_pnp pnp; + struct acpi_device_power power; + struct acpi_device_perf performance; + struct acpi_device_dir dir; + struct acpi_device_ops ops; + struct acpi_driver *driver; + void *driver_data; +#ifdef CONFIG_LDM + struct device dev; +#endif +}; + +#define acpi_driver_data(d) ((d)->driver_data) + + +/* + * Events + * ------ + */ + +struct acpi_bus_event { + struct list_head node; + acpi_device_class device_class; + acpi_bus_id bus_id; + u32 type; + u32 data; +}; + + +/* + * External Functions + */ + +int acpi_bus_get_device(acpi_handle, struct acpi_device **device); +int acpi_bus_get_status (struct acpi_device *device); +int acpi_bus_get_power (acpi_handle handle, int *state); +int acpi_bus_set_power (acpi_handle handle, int state); +int acpi_bus_generate_event (struct acpi_device *device, u8 type, int data); +int acpi_bus_receive_event (struct acpi_bus_event *event); +int acpi_bus_register_driver (struct acpi_driver *driver); +int acpi_bus_unregister_driver (struct acpi_driver *driver); +int acpi_bus_scan (struct acpi_device *device); +int acpi_init (void); +void acpi_exit (void); + + +#endif /*CONFIG_ACPI_BUS*/ + +#endif /*__ACPI_BUS_H__*/ diff -Naur -X /root/bin/dontdiff a/drivers/acpi/acpi_drivers.h b/drivers/acpi/acpi_drivers.h --- a/drivers/acpi/acpi_drivers.h 1969-12-31 16:00:00.000000000 -0800 +++ b/drivers/acpi/acpi_drivers.h 2002-12-12 16:57:19.000000000 -0800 @@ -0,0 +1,347 @@ +/* + * acpi_drivers.h ($Revision: 32 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#ifndef __ACPI_DRIVERS_H__ +#define __ACPI_DRIVERS_H__ + +#include +#include "acpi_bus.h" + + +#define ACPI_MAX_STRING 80 + + +/* -------------------------------------------------------------------------- + ACPI Bus + -------------------------------------------------------------------------- */ + +#define ACPI_BUS_COMPONENT 0x00010000 +#define ACPI_BUS_CLASS "system_bus" +#define ACPI_BUS_HID "ACPI_BUS" +#define ACPI_BUS_DRIVER_NAME "ACPI Bus Driver" +#define ACPI_BUS_DEVICE_NAME "System Bus" + + +/* -------------------------------------------------------------------------- + AC Adapter + -------------------------------------------------------------------------- */ + +#define ACPI_AC_COMPONENT 0x00020000 +#define ACPI_AC_CLASS "ac_adapter" +#define ACPI_AC_HID "ACPI0003" +#define ACPI_AC_DRIVER_NAME "ACPI AC Adapter Driver" +#define ACPI_AC_DEVICE_NAME "AC Adapter" +#define ACPI_AC_FILE_STATE "state" +#define ACPI_AC_NOTIFY_STATUS 0x80 +#define ACPI_AC_STATUS_OFFLINE 0x00 +#define ACPI_AC_STATUS_ONLINE 0x01 +#define ACPI_AC_STATUS_UNKNOWN 0xFF + + +/* -------------------------------------------------------------------------- + Battery + -------------------------------------------------------------------------- */ + +#define ACPI_BATTERY_COMPONENT 0x00040000 +#define ACPI_BATTERY_CLASS "battery" +#define ACPI_BATTERY_HID "PNP0C0A" +#define ACPI_BATTERY_DRIVER_NAME "ACPI Battery Driver" +#define ACPI_BATTERY_DEVICE_NAME "Battery" +#define ACPI_BATTERY_FILE_INFO "info" +#define ACPI_BATTERY_FILE_STATUS "state" +#define ACPI_BATTERY_FILE_ALARM "alarm" +#define ACPI_BATTERY_NOTIFY_STATUS 0x80 +#define ACPI_BATTERY_NOTIFY_INFO 0x81 +#define ACPI_BATTERY_UNITS_WATTS "mW" +#define ACPI_BATTERY_UNITS_AMPS "mA" + + +/* -------------------------------------------------------------------------- + Button + -------------------------------------------------------------------------- */ + +#define ACPI_BUTTON_COMPONENT 0x00080000 +#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" +#define ACPI_BUTTON_CLASS "button" +#define ACPI_BUTTON_FILE_INFO "info" +#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 +#define ACPI_BUTTON_NOTIFY_STATUS 0x80 + +#define ACPI_BUTTON_SUBCLASS_POWER "power" +#define ACPI_BUTTON_HID_POWER "PNP0C0C" +#define ACPI_BUTTON_HID_POWERF "ACPI_FPB" +#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)" +#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)" +#define ACPI_BUTTON_TYPE_POWER 0x01 +#define ACPI_BUTTON_TYPE_POWERF 0x02 + +#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep" +#define ACPI_BUTTON_HID_SLEEP "PNP0C0E" +#define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB" +#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button (CM)" +#define ACPI_BUTTON_DEVICE_NAME_SLEEPF "Sleep Button (FF)" +#define ACPI_BUTTON_TYPE_SLEEP 0x03 +#define ACPI_BUTTON_TYPE_SLEEPF 0x04 + +#define ACPI_BUTTON_SUBCLASS_LID "lid" +#define ACPI_BUTTON_HID_LID "PNP0C0D" +#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch" +#define ACPI_BUTTON_TYPE_LID 0x05 + + +/* -------------------------------------------------------------------------- + Embedded Controller + -------------------------------------------------------------------------- */ + +#define ACPI_EC_COMPONENT 0x00100000 +#define ACPI_EC_CLASS "embedded_controller" +#define ACPI_EC_HID "PNP0C09" +#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver" +#define ACPI_EC_DEVICE_NAME "Embedded Controller" +#define ACPI_EC_FILE_INFO "info" + +#ifdef CONFIG_ACPI_EC + +int acpi_ec_ecdt_probe (void); +int acpi_ec_init (void); +void acpi_ec_exit (void); + +#endif + + +/* -------------------------------------------------------------------------- + Fan + -------------------------------------------------------------------------- */ + +#define ACPI_FAN_COMPONENT 0x00200000 +#define ACPI_FAN_CLASS "fan" +#define ACPI_FAN_HID "PNP0C0B" +#define ACPI_FAN_DRIVER_NAME "ACPI Fan Driver" +#define ACPI_FAN_DEVICE_NAME "Fan" +#define ACPI_FAN_FILE_STATE "state" +#define ACPI_FAN_NOTIFY_STATUS 0x80 + + +/* -------------------------------------------------------------------------- + PCI + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_PCI + +#define ACPI_PCI_COMPONENT 0x00400000 + +/* ACPI PCI Root Bridge (pci_root.c) */ + +#define ACPI_PCI_ROOT_CLASS "pci_bridge" +#define ACPI_PCI_ROOT_HID "PNP0A03" +#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver" +#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" + +int acpi_pci_root_init (void); +void acpi_pci_root_exit (void); +void acpi_pci_get_translations (acpi_pci_id* id, u64* mem_tra, u64* io_tra); + +/* ACPI PCI Interrupt Link (pci_link.c) */ + +#define ACPI_PCI_LINK_CLASS "pci_irq_routing" +#define ACPI_PCI_LINK_HID "PNP0C0F" +#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver" +#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" +#define ACPI_PCI_LINK_FILE_INFO "info" +#define ACPI_PCI_LINK_FILE_STATUS "state" + +int acpi_pci_link_check (void); +int acpi_pci_link_get_irq (acpi_handle handle, int index); +int acpi_pci_link_init (void); +void acpi_pci_link_exit (void); + +/* ACPI PCI Interrupt Routing (pci_irq.c) */ + +int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus); + +/* ACPI PCI Device Binding (pci_bind.c) */ + +struct pci_bus; + +int acpi_pci_bind (struct acpi_device *device); +int acpi_pci_bind_root (struct acpi_device *device, acpi_pci_id *id, struct pci_bus *bus); + +#endif /*CONFIG_ACPI_PCI*/ + + +/* -------------------------------------------------------------------------- + Power Resource + -------------------------------------------------------------------------- */ + +#define ACPI_POWER_COMPONENT 0x00800000 +#define ACPI_POWER_CLASS "power_resource" +#define ACPI_POWER_HID "ACPI_PWR" +#define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver" +#define ACPI_POWER_DEVICE_NAME "Power Resource" +#define ACPI_POWER_FILE_INFO "info" +#define ACPI_POWER_FILE_STATUS "state" +#define ACPI_POWER_RESOURCE_STATE_OFF 0x00 +#define ACPI_POWER_RESOURCE_STATE_ON 0x01 +#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF + +#ifdef CONFIG_ACPI_POWER + +int acpi_power_get_inferred_state (struct acpi_device *device); +int acpi_power_transition (struct acpi_device *device, int state); +int acpi_power_init (void); +void acpi_power_exit (void); + +#endif + + +/* -------------------------------------------------------------------------- + Processor + -------------------------------------------------------------------------- */ + +#define ACPI_PROCESSOR_COMPONENT 0x01000000 +#define ACPI_PROCESSOR_CLASS "processor" +#define ACPI_PROCESSOR_HID "ACPI_CPU" +#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" +#define ACPI_PROCESSOR_DEVICE_NAME "Processor" +#define ACPI_PROCESSOR_FILE_INFO "info" +#define ACPI_PROCESSOR_FILE_POWER "power" +#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" +#define ACPI_PROCESSOR_FILE_THROTTLING "throttling" +#define ACPI_PROCESSOR_FILE_LIMIT "limit" +#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 +#define ACPI_PROCESSOR_NOTIFY_POWER 0x81 +#define ACPI_PROCESSOR_LIMIT_NONE 0x00 +#define ACPI_PROCESSOR_LIMIT_INCREMENT 0x01 +#define ACPI_PROCESSOR_LIMIT_DECREMENT 0x02 + +int acpi_processor_set_thermal_limit(acpi_handle handle, int type); + + +/* -------------------------------------------------------------------------- + System + -------------------------------------------------------------------------- */ + +#define ACPI_SYSTEM_COMPONENT 0x02000000 +#define ACPI_SYSTEM_CLASS "system" +#define ACPI_SYSTEM_HID "ACPI_SYS" +#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver" +#define ACPI_SYSTEM_DEVICE_NAME "System" +#define ACPI_SYSTEM_FILE_INFO "info" +#define ACPI_SYSTEM_FILE_EVENT "event" +#define ACPI_SYSTEM_FILE_ALARM "alarm" +#define ACPI_SYSTEM_FILE_DSDT "dsdt" +#define ACPI_SYSTEM_FILE_FADT "fadt" +#define ACPI_SYSTEM_FILE_SLEEP "sleep" +#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" +#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" + +#ifdef CONFIG_ACPI_SYSTEM + +int acpi_system_init (void); +void acpi_system_exit (void); + +#endif + + +/* -------------------------------------------------------------------------- + Thermal Zone + -------------------------------------------------------------------------- */ + +#define ACPI_THERMAL_COMPONENT 0x04000000 +#define ACPI_THERMAL_CLASS "thermal_zone" +#define ACPI_THERMAL_HID "ACPI_THM" +#define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver" +#define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" +#define ACPI_THERMAL_FILE_STATE "state" +#define ACPI_THERMAL_FILE_TEMPERATURE "temperature" +#define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points" +#define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode" +#define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency" +#define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80 +#define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81 +#define ACPI_THERMAL_NOTIFY_DEVICES 0x82 +#define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0 +#define ACPI_THERMAL_NOTIFY_HOT 0xF1 +#define ACPI_THERMAL_MODE_ACTIVE 0x00 +#define ACPI_THERMAL_MODE_PASSIVE 0x01 +#define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff" + + +/* -------------------------------------------------------------------------- + Debug Support + -------------------------------------------------------------------------- */ + +#define ACPI_DEBUG_RESTORE 0 +#define ACPI_DEBUG_LOW 1 +#define ACPI_DEBUG_MEDIUM 2 +#define ACPI_DEBUG_HIGH 3 +#define ACPI_DEBUG_DRIVERS 4 + +extern u32 acpi_dbg_level; +extern u32 acpi_dbg_layer; + +static inline void +acpi_set_debug ( + u32 flag) +{ + static u32 layer_save; + static u32 level_save; + + switch (flag) { + case ACPI_DEBUG_RESTORE: + acpi_dbg_layer = layer_save; + acpi_dbg_level = level_save; + break; + case ACPI_DEBUG_LOW: + case ACPI_DEBUG_MEDIUM: + case ACPI_DEBUG_HIGH: + case ACPI_DEBUG_DRIVERS: + layer_save = acpi_dbg_layer; + level_save = acpi_dbg_level; + break; + } + + switch (flag) { + case ACPI_DEBUG_LOW: + acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; + acpi_dbg_level = ACPI_DEBUG_DEFAULT; + break; + case ACPI_DEBUG_MEDIUM: + acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; + acpi_dbg_level = ACPI_LV_FUNCTIONS | ACPI_LV_ALL_EXCEPTIONS; + break; + case ACPI_DEBUG_HIGH: + acpi_dbg_layer = 0xFFFFFFFF; + acpi_dbg_level = 0xFFFFFFFF; + break; + case ACPI_DEBUG_DRIVERS: + acpi_dbg_layer = ACPI_ALL_DRIVERS; + acpi_dbg_level = 0xFFFFFFFF; + break; + } +} + + +#endif /*__ACPI_DRIVERS_H__*/ diff -Naur -X /root/bin/dontdiff a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c --- a/drivers/acpi/acpi_ksyms.c 2002-12-12 16:52:25.000000000 -0800 +++ b/drivers/acpi/acpi_ksyms.c 2002-12-12 16:57:25.000000000 -0800 @@ -1,64 +1,59 @@ /* - * ksyms.c - ACPI exported symbols + * acpi_ksyms.c - ACPI Kernel Symbols ($Revision: 15 $) * - * Copyright (C) 2000 Andrew Grover + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * 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. + * 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. * - * 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 + * 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 #include -#include -#include -#include #include -#include "acpi.h" -#include "acdebug.h" +#include "include/acpi.h" +#include "acpi_bus.h" + -extern int acpi_in_debugger; -extern FADT_DESCRIPTOR acpi_fadt; +#ifdef CONFIG_ACPI_INTERPRETER -#define _COMPONENT OS_DEPENDENT - MODULE_NAME ("symbols") +/* ACPI Debugger */ #ifdef ENABLE_DEBUGGER + +extern int acpi_in_debugger; + EXPORT_SYMBOL(acpi_in_debugger); EXPORT_SYMBOL(acpi_db_user_commands); -#endif -#ifdef ACPI_DEBUG +#endif /* ENABLE_DEBUGGER */ + +/* ACPI Core Subsystem */ + +#ifdef ACPI_DEBUG_OUTPUT +EXPORT_SYMBOL(acpi_dbg_layer); +EXPORT_SYMBOL(acpi_dbg_level); EXPORT_SYMBOL(acpi_ut_debug_print_raw); EXPORT_SYMBOL(acpi_ut_debug_print); EXPORT_SYMBOL(acpi_ut_status_exit); +EXPORT_SYMBOL(acpi_ut_value_exit); EXPORT_SYMBOL(acpi_ut_exit); EXPORT_SYMBOL(acpi_ut_trace); -#endif - -EXPORT_SYMBOL(acpi_gbl_FADT); - -EXPORT_SYMBOL(acpi_os_free); -EXPORT_SYMBOL(acpi_os_printf); -EXPORT_SYMBOL(acpi_os_callocate); -EXPORT_SYMBOL(acpi_os_sleep); -EXPORT_SYMBOL(acpi_os_stall); -EXPORT_SYMBOL(acpi_os_queue_for_execution); - -EXPORT_SYMBOL(acpi_dbg_layer); -EXPORT_SYMBOL(acpi_dbg_level); - -EXPORT_SYMBOL(acpi_format_exception); +#endif /*ACPI_DEBUG_OUTPUT*/ EXPORT_SYMBOL(acpi_get_handle); EXPORT_SYMBOL(acpi_get_parent); @@ -68,7 +63,7 @@ EXPORT_SYMBOL(acpi_get_next_object); EXPORT_SYMBOL(acpi_evaluate_object); EXPORT_SYMBOL(acpi_get_table); - +EXPORT_SYMBOL(acpi_get_firmware_table); EXPORT_SYMBOL(acpi_install_notify_handler); EXPORT_SYMBOL(acpi_remove_notify_handler); EXPORT_SYMBOL(acpi_install_gpe_handler); @@ -77,40 +72,83 @@ EXPORT_SYMBOL(acpi_remove_address_space_handler); EXPORT_SYMBOL(acpi_install_fixed_event_handler); EXPORT_SYMBOL(acpi_remove_fixed_event_handler); - EXPORT_SYMBOL(acpi_acquire_global_lock); EXPORT_SYMBOL(acpi_release_global_lock); - EXPORT_SYMBOL(acpi_get_current_resources); EXPORT_SYMBOL(acpi_get_possible_resources); EXPORT_SYMBOL(acpi_set_current_resources); - EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_clear_event); - EXPORT_SYMBOL(acpi_get_timer_duration); EXPORT_SYMBOL(acpi_get_timer); +EXPORT_SYMBOL(acpi_get_sleep_type_data); +EXPORT_SYMBOL(acpi_get_register); +EXPORT_SYMBOL(acpi_set_register); +EXPORT_SYMBOL(acpi_enter_sleep_state); +EXPORT_SYMBOL(acpi_get_system_info); +EXPORT_SYMBOL(acpi_get_devices); + +/* ACPI OS Services Layer (acpi_osl.c) */ +EXPORT_SYMBOL(acpi_os_free); +EXPORT_SYMBOL(acpi_os_printf); +EXPORT_SYMBOL(acpi_os_sleep); +EXPORT_SYMBOL(acpi_os_stall); +EXPORT_SYMBOL(acpi_os_signal); +EXPORT_SYMBOL(acpi_os_queue_for_execution); EXPORT_SYMBOL(acpi_os_signal_semaphore); EXPORT_SYMBOL(acpi_os_create_semaphore); EXPORT_SYMBOL(acpi_os_delete_semaphore); EXPORT_SYMBOL(acpi_os_wait_semaphore); -EXPORT_SYMBOL(acpi_os_read_port); -EXPORT_SYMBOL(acpi_os_write_port); +EXPORT_SYMBOL(acpi_os_read_pci_configuration); + +/* ACPI Utilities (acpi_utils.c) */ + +EXPORT_SYMBOL(acpi_extract_package); +EXPORT_SYMBOL(acpi_evaluate_integer); +EXPORT_SYMBOL(acpi_evaluate_reference); + +#endif /*CONFIG_ACPI_INTERPRETER*/ + + +/* ACPI Bus Driver (acpi_bus.c) */ + +#ifdef CONFIG_ACPI_BUS EXPORT_SYMBOL(acpi_fadt); -EXPORT_SYMBOL(acpi_hw_register_bit_access); -EXPORT_SYMBOL(acpi_hw_obtain_sleep_type_register_data); -EXPORT_SYMBOL(acpi_enter_sleep_state); -EXPORT_SYMBOL(acpi_get_system_info); -EXPORT_SYMBOL(acpi_leave_sleep_state); EXPORT_SYMBOL(acpi_walk_namespace); -/*EXPORT_SYMBOL(acpi_save_state_mem);*/ -/*EXPORT_SYMBOL(acpi_save_state_disk);*/ -EXPORT_SYMBOL(acpi_hw_register_read); -EXPORT_SYMBOL(acpi_set_firmware_waking_vector); -EXPORT_SYMBOL(acpi_subsystem_status); +EXPORT_SYMBOL(acpi_root_dir); +EXPORT_SYMBOL(acpi_bus_get_device); +EXPORT_SYMBOL(acpi_bus_get_status); +EXPORT_SYMBOL(acpi_bus_get_power); +EXPORT_SYMBOL(acpi_bus_set_power); +EXPORT_SYMBOL(acpi_bus_generate_event); +EXPORT_SYMBOL(acpi_bus_receive_event); +EXPORT_SYMBOL(acpi_bus_register_driver); +EXPORT_SYMBOL(acpi_bus_unregister_driver); +EXPORT_SYMBOL(acpi_bus_scan); +EXPORT_SYMBOL(acpi_init); + +#endif /*CONFIG_ACPI_BUS*/ + + +/* ACPI PCI Driver (pci_irq.c) */ + +#ifdef CONFIG_ACPI_PCI + +#include +extern int acpi_pci_irq_enable(struct pci_dev *dev); +EXPORT_SYMBOL(acpi_pci_irq_enable); +extern int acpi_pci_irq_lookup (int segment, int bus, int device, int pin); +EXPORT_SYMBOL(acpi_pci_irq_lookup); +#endif /*CONFIG_ACPI_PCI */ + +#ifdef CONFIG_ACPI_EC +/* ACPI EC driver (ec.c) */ + +EXPORT_SYMBOL(ec_read); +EXPORT_SYMBOL(ec_write); +#endif -EXPORT_SYMBOL(acpi_os_signal); diff -Naur -X /root/bin/dontdiff a/drivers/acpi/battery.c b/drivers/acpi/battery.c --- a/drivers/acpi/battery.c 1969-12-31 16:00:00.000000000 -0800 +++ b/drivers/acpi/battery.c 2002-12-12 16:57:22.000000000 -0800 @@ -0,0 +1,823 @@ +/* + * acpi_battery.c - ACPI Battery Driver ($Revision: 36 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_BATTERY_COMPONENT +ACPI_MODULE_NAME ("acpi_battery") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF + +#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" +#define ACPI_BATTERY_FORMAT_BST "NNNN" + +static int acpi_battery_add (struct acpi_device *device); +static int acpi_battery_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_battery_driver = { + .name = ACPI_BATTERY_DRIVER_NAME, + .class = ACPI_BATTERY_CLASS, + .ids = ACPI_BATTERY_HID, + .ops = { + .add = acpi_battery_add, + .remove = acpi_battery_remove, + }, +}; + +struct acpi_battery_status { + acpi_integer state; + acpi_integer present_rate; + acpi_integer remaining_capacity; + acpi_integer present_voltage; +}; + +struct acpi_battery_info { + acpi_integer power_unit; + acpi_integer design_capacity; + acpi_integer last_full_capacity; + acpi_integer battery_technology; + acpi_integer design_voltage; + acpi_integer design_capacity_warning; + acpi_integer design_capacity_low; + acpi_integer battery_capacity_granularity_1; + acpi_integer battery_capacity_granularity_2; + acpi_string model_number; + acpi_string serial_number; + acpi_string battery_type; + acpi_string oem_info; +}; + +struct acpi_battery_flags { + u8 present:1; /* Bay occupied? */ + u8 power_unit:1; /* 0=watts, 1=apms */ + u8 alarm:1; /* _BTP present? */ + u8 reserved:5; +}; + +struct acpi_battery_trips { + unsigned long warning; + unsigned long low; +}; + +struct acpi_battery { + acpi_handle handle; + struct acpi_battery_flags flags; + struct acpi_battery_trips trips; + unsigned long alarm; + struct acpi_battery_info *info; +}; + + +/* -------------------------------------------------------------------------- + Battery Management + -------------------------------------------------------------------------- */ + +static int +acpi_battery_get_info ( + struct acpi_battery *battery, + struct acpi_battery_info **bif) +{ + int result = 0; + acpi_status status = 0; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF), + ACPI_BATTERY_FORMAT_BIF}; + acpi_buffer data = {0, NULL}; + acpi_object *package = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_get_info"); + + if (!battery || !bif) + return_VALUE(-EINVAL); + + /* Evalute _BIF */ + + status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n")); + return_VALUE(-ENODEV); + } + + package = (acpi_object *) buffer.pointer; + + /* Extract Package Data */ + + status = acpi_extract_package(package, &format, &data); + if (status != AE_BUFFER_OVERFLOW) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); + result = -ENODEV; + goto end; + } + + data.pointer = kmalloc(data.length, GFP_KERNEL); + if (!data.pointer) { + result = -ENOMEM; + goto end; + } + memset(data.pointer, 0, data.length); + + status = acpi_extract_package(package, &format, &data); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); + kfree(data.pointer); + result = -ENODEV; + goto end; + } + +end: + acpi_os_free(buffer.pointer); + + if (!result) + (*bif) = (struct acpi_battery_info *) data.pointer; + + return_VALUE(result); +} + +static int +acpi_battery_get_status ( + struct acpi_battery *battery, + struct acpi_battery_status **bst) +{ + int result = 0; + acpi_status status = 0; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST), + ACPI_BATTERY_FORMAT_BST}; + acpi_buffer data = {0, NULL}; + acpi_object *package = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_get_status"); + + if (!battery || !bst) + return_VALUE(-EINVAL); + + /* Evalute _BST */ + + status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n")); + return_VALUE(-ENODEV); + } + + package = (acpi_object *) buffer.pointer; + + /* Extract Package Data */ + + status = acpi_extract_package(package, &format, &data); + if (status != AE_BUFFER_OVERFLOW) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); + result = -ENODEV; + goto end; + } + + data.pointer = kmalloc(data.length, GFP_KERNEL); + if (!data.pointer) { + result = -ENOMEM; + goto end; + } + memset(data.pointer, 0, data.length); + + status = acpi_extract_package(package, &format, &data); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); + kfree(data.pointer); + result = -ENODEV; + goto end; + } + +end: + acpi_os_free(buffer.pointer); + + if (!result) + (*bst) = (struct acpi_battery_status *) data.pointer; + + return_VALUE(result); +} + + +static int +acpi_battery_set_alarm ( + struct acpi_battery *battery, + unsigned long alarm) +{ + acpi_status status = 0; + acpi_object arg0 = {ACPI_TYPE_INTEGER}; + acpi_object_list arg_list = {1, &arg0}; + + ACPI_FUNCTION_TRACE("acpi_battery_set_alarm"); + + if (!battery) + return_VALUE(-EINVAL); + + if (!battery->flags.alarm) + return_VALUE(-ENODEV); + + arg0.integer.value = alarm; + + status = acpi_evaluate_object(battery->handle, "_BTP", &arg_list, NULL); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm)); + + battery->alarm = alarm; + + return_VALUE(0); +} + + +static int +acpi_battery_check ( + struct acpi_battery *battery) +{ + int result = 0; + acpi_status status = AE_OK; + acpi_handle handle = NULL; + struct acpi_device *device = NULL; + struct acpi_battery_info *bif = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_check"); + + if (!battery) + return_VALUE(-EINVAL); + + result = acpi_bus_get_device(battery->handle, &device); + if (result) + return_VALUE(result); + + result = acpi_bus_get_status(device); + if (result) + return_VALUE(result); + + /* Insertion? */ + + if (!battery->flags.present && device->status.battery_present) { + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); + + /* Evalute _BIF to get certain static information */ + + result = acpi_battery_get_info(battery, &bif); + if (result) + return_VALUE(result); + + battery->flags.power_unit = bif->power_unit; + battery->trips.warning = bif->design_capacity_warning; + battery->trips.low = bif->design_capacity_low; + kfree(bif); + + /* See if alarms are supported, and if so, set default */ + + status = acpi_get_handle(battery->handle, "_BTP", &handle); + if (ACPI_SUCCESS(status)) { + battery->flags.alarm = 1; + acpi_battery_set_alarm(battery, battery->trips.warning); + } + } + + /* Removal? */ + + else if (battery->flags.present && !device->status.battery_present) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); + } + + battery->flags.present = device->status.battery_present; + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +struct proc_dir_entry *acpi_battery_dir = NULL; + +static int +acpi_battery_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + int result = 0; + struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_battery_info *bif = NULL; + char *units = "?"; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_read_info"); + + if (!battery) + goto end; + + if (battery->flags.present) + p += sprintf(p, "present: yes\n"); + else { + p += sprintf(p, "present: no\n"); + goto end; + } + + /* Battery Info (_BIF) */ + + result = acpi_battery_get_info(battery, &bif); + if (result || !bif) { + p += sprintf(p, "ERROR: Unable to read battery information\n"); + goto end; + } + + units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + + if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "design capacity: unknown\n"); + else + p += sprintf(p, "design capacity: %d %sh\n", + (u32) bif->design_capacity, units); + + if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "last full capacity: unknown\n"); + else + p += sprintf(p, "last full capacity: %d %sh\n", + (u32) bif->last_full_capacity, units); + + switch ((u32) bif->battery_technology) { + case 0: + p += sprintf(p, "battery technology: non-rechargeable\n"); + break; + case 1: + p += sprintf(p, "battery technology: rechargeable\n"); + break; + default: + p += sprintf(p, "battery technology: unknown\n"); + break; + } + + if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "design voltage: unknown\n"); + else + p += sprintf(p, "design voltage: %d mV\n", + (u32) bif->design_voltage); + + p += sprintf(p, "design capacity warning: %d %sh\n", + (u32) bif->design_capacity_warning, units); + p += sprintf(p, "design capacity low: %d %sh\n", + (u32) bif->design_capacity_low, units); + p += sprintf(p, "capacity granularity 1: %d %sh\n", + (u32) bif->battery_capacity_granularity_1, units); + p += sprintf(p, "capacity granularity 2: %d %sh\n", + (u32) bif->battery_capacity_granularity_2, units); + p += sprintf(p, "model number: %s\n", + bif->model_number); + p += sprintf(p, "serial number: %s\n", + bif->serial_number); + p += sprintf(p, "battery type: %s\n", + bif->battery_type); + p += sprintf(p, "OEM info: %s\n", + bif->oem_info); + +end: + kfree(bif); + + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_battery_read_state ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + int result = 0; + struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_battery_status *bst = NULL; + char *units = "?"; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_read_state"); + + if (!battery) + goto end; + + if (battery->flags.present) + p += sprintf(p, "present: yes\n"); + else { + p += sprintf(p, "present: no\n"); + goto end; + } + + /* Battery Units */ + + units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + + /* Battery Status (_BST) */ + + result = acpi_battery_get_status(battery, &bst); + if (result || !bst) { + p += sprintf(p, "ERROR: Unable to read battery status\n"); + goto end; + } + + if (!(bst->state & 0x04)) + p += sprintf(p, "capacity state: ok\n"); + else + p += sprintf(p, "capacity state: critical\n"); + + if ((bst->state & 0x01) && (bst->state & 0x02)) + p += sprintf(p, "charging state: charging/discharging\n"); + else if (bst->state & 0x01) + p += sprintf(p, "charging state: discharging\n"); + else if (bst->state & 0x02) + p += sprintf(p, "charging state: charging\n"); + else + p += sprintf(p, "charging state: unknown\n"); + + if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "present rate: unknown\n"); + else + p += sprintf(p, "present rate: %d %s\n", + (u32) bst->present_rate, units); + + if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "remaining capacity: unknown\n"); + else + p += sprintf(p, "remaining capacity: %d %sh\n", + (u32) bst->remaining_capacity, units); + + if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "present voltage: unknown\n"); + else + p += sprintf(p, "present voltage: %d mV\n", + (u32) bst->present_voltage); + +end: + kfree(bst); + + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_battery_read_alarm ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_battery *battery = (struct acpi_battery *) data; + char *units = "?"; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_read_alarm"); + + if (!battery) + goto end; + + if (!battery->flags.present) { + p += sprintf(p, "present: no\n"); + goto end; + } + + /* Battery Units */ + + units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + + /* Battery Alarm */ + + p += sprintf(p, "alarm: "); + if (!battery->alarm) + p += sprintf(p, "unsupported\n"); + else + p += sprintf(p, "%d %sh\n", (u32) battery->alarm, units); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_battery_write_alarm ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_battery *battery = (struct acpi_battery *) data; + char alarm_string[12] = {'\0'}; + + ACPI_FUNCTION_TRACE("acpi_battery_write_alarm"); + + if (!battery || (count > sizeof(alarm_string) - 1)) + return_VALUE(-EINVAL); + + if (!battery->flags.present) + return_VALUE(-ENODEV); + + if (copy_from_user(alarm_string, buffer, count)) + return_VALUE(-EFAULT); + + alarm_string[count] = '\0'; + + result = acpi_battery_set_alarm(battery, + simple_strtoul(alarm_string, NULL, 0)); + if (result) + return_VALUE(result); + + return_VALUE(count); +} + + +static int +acpi_battery_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_add_fs"); + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_battery_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BATTERY_FILE_INFO)); + else { + entry->read_proc = acpi_battery_read_info; + entry->data = acpi_driver_data(device); + } + + /* 'status' [R] */ + entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BATTERY_FILE_STATUS)); + else { + entry->read_proc = acpi_battery_read_state; + entry->data = acpi_driver_data(device); + } + + /* 'alarm' [R/W] */ + entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BATTERY_FILE_ALARM)); + else { + entry->read_proc = acpi_battery_read_alarm; + entry->write_proc = acpi_battery_write_alarm; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_battery_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_battery_remove_fs"); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +static void +acpi_battery_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_notify"); + + if (!battery) + return_VOID; + + if (acpi_bus_get_device(handle, &device)) + return_VOID; + + switch (event) { + case ACPI_BATTERY_NOTIFY_STATUS: + case ACPI_BATTERY_NOTIFY_INFO: + acpi_battery_check(battery); + acpi_bus_generate_event(device, event, battery->flags.present); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +static int +acpi_battery_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = 0; + struct acpi_battery *battery = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_add"); + + if (!device) + return_VALUE(-EINVAL); + + battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL); + if (!battery) + return_VALUE(-ENOMEM); + memset(battery, 0, sizeof(struct acpi_battery)); + + battery->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_BATTERY_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_BATTERY_CLASS); + acpi_driver_data(device) = battery; + + result = acpi_battery_check(battery); + if (result) + goto end; + + result = acpi_battery_add_fs(device); + if (result) + goto end; + + status = acpi_install_notify_handler(battery->handle, + ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", + ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), + device->status.battery_present?"present":"absent"); + +end: + if (result) { + acpi_battery_remove_fs(device); + kfree(battery); + } + + return_VALUE(result); +} + + +static int +acpi_battery_remove ( + struct acpi_device *device, + int type) +{ + acpi_status status = 0; + struct acpi_battery *battery = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + battery = (struct acpi_battery *) acpi_driver_data(device); + + status = acpi_remove_notify_handler(battery->handle, + ACPI_DEVICE_NOTIFY, acpi_battery_notify); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + + acpi_battery_remove_fs(device); + + kfree(battery); + + return_VALUE(0); +} + + +static int __init +acpi_battery_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_init"); + + acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); + if (!acpi_battery_dir) + return_VALUE(-ENODEV); + + result = acpi_bus_register_driver(&acpi_battery_driver); + if (result < 0) { + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +static void __exit +acpi_battery_exit (void) +{ + ACPI_FUNCTION_TRACE("acpi_battery_exit"); + + acpi_bus_unregister_driver(&acpi_battery_driver); + + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_battery_init); +module_exit(acpi_battery_exit); diff -Naur -X /root/bin/dontdiff a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c --- a/drivers/acpi/blacklist.c 1969-12-31 16:00:00.000000000 -0800 +++ b/drivers/acpi/blacklist.c 2002-12-12 16:57:16.000000000 -0800 @@ -0,0 +1,141 @@ +/* + * blacklist.c + * + * Check to see if the given machine has a known bad ACPI BIOS + * + * Copyright (C) 2002 Andy Grover + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 +#include +#include +#include +#include "acpi_bus.h" + +#define PREFIX "ACPI: " + +enum acpi_blacklist_predicates +{ + all_versions, + less_than_or_equal, + equal, + greater_than_or_equal, +}; + +struct acpi_blacklist_item +{ + char oem_id[7]; + char oem_table_id[9]; + u32 oem_revision; + acpi_table_type table; + enum acpi_blacklist_predicates oem_revision_predicate; + char *reason; + u32 is_critical_error; +}; + +/* + * POLICY: If *anything* doesn't work, put it on the blacklist. + * If they are critical errors, mark it critical, and abort driver load. + */ +static struct acpi_blacklist_item acpi_blacklist[] __initdata = +{ + /* Portege 7020, BIOS 8.10 */ + {"TOSHIB", "7020CT ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0}, + /* Portege 4030 */ + {"TOSHIB", "4030 ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0}, + /* Portege 310/320, BIOS 7.1 */ + {"TOSHIB", "310 ", 0x19990511, ACPI_DSDT, all_versions, "Implicit Return", 0}, + /* Seattle 2, old bios rev. */ + {"INTEL ", "440BX ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0}, + /* ASUS K7M */ + {"ASUS ", "K7M ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0}, + /* Intel 810 Motherboard? */ + {"MNTRAL", "MO81010A", 0x00000012, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0}, + /* Compaq Presario 711FR */ + {"COMAPQ", "EAGLES", 0x06040000, ACPI_DSDT, less_than_or_equal, "SCI issues (C2 disabled)", 0}, + /* Compaq Presario 1700 */ + {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1}, + /* Sony FX120, FX140, FX150? */ + {"SONY ", "U0 ", 0x20010313, ACPI_DSDT, less_than_or_equal, "ACPI driver problem", 1}, + /* Compaq Presario 800, Insyde BIOS */ + {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1}, + /* IBM 600E - _ADR should return 7, but it returns 1 */ + {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal, "Incorrect _ADR", 1}, + {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1}, + + {""} +}; + + +int __init +acpi_blacklisted(void) +{ + int i = 0; + int blacklisted = 0; + struct acpi_table_header *table_header; + + while (acpi_blacklist[i].oem_id[0] != '\0') + { + if (acpi_get_table_header_early(acpi_blacklist[i].table, &table_header)) { + i++; + continue; + } + + if (strncmp(acpi_blacklist[i].oem_id, table_header->oem_id, 6)) { + i++; + continue; + } + + if (strncmp(acpi_blacklist[i].oem_table_id, table_header->oem_table_id, 8)) { + i++; + continue; + } + + if ((acpi_blacklist[i].oem_revision_predicate == all_versions) + || (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal + && table_header->oem_revision <= acpi_blacklist[i].oem_revision) + || (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal + && table_header->oem_revision >= acpi_blacklist[i].oem_revision) + || (acpi_blacklist[i].oem_revision_predicate == equal + && table_header->oem_revision == acpi_blacklist[i].oem_revision)) { + + printk(KERN_ERR PREFIX "Vendor \"%6.6s\" System \"%8.8s\" " + "Revision 0x%x has a known ACPI BIOS problem.\n", + acpi_blacklist[i].oem_id, + acpi_blacklist[i].oem_table_id, + acpi_blacklist[i].oem_revision); + + printk(KERN_ERR PREFIX "Reason: %s. This is a %s error\n", + acpi_blacklist[i].reason, + (acpi_blacklist[i].is_critical_error ? "non-recoverable" : "recoverable")); + + blacklisted = acpi_blacklist[i].is_critical_error; + break; + } + else { + i++; + } + } + + return blacklisted; +} + diff -Naur -X /root/bin/dontdiff a/drivers/acpi/bus.c b/drivers/acpi/bus.c --- a/drivers/acpi/bus.c 1969-12-31 16:00:00.000000000 -0800 +++ b/drivers/acpi/bus.c 2002-12-12 16:57:15.000000000 -0800 @@ -0,0 +1,2095 @@ +/* + * acpi_bus.c - ACPI Bus Driver ($Revision: 77 $) + * + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_X86 +#include +#endif +#include "acpi_bus.h" +#include "acpi_drivers.h" +#include "include/acinterp.h" /* for acpi_ex_eisa_id_to_string() */ + + +#define _COMPONENT ACPI_BUS_COMPONENT +ACPI_MODULE_NAME ("acpi_bus") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BUS_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + +extern void eisa_set_level_irq(unsigned int irq); + +extern int acpi_disabled; + +FADT_DESCRIPTOR acpi_fadt; +struct acpi_device *acpi_root; +struct proc_dir_entry *acpi_root_dir; + +#define STRUCT_TO_INT(s) (*((int*)&s)) + + +/* -------------------------------------------------------------------------- + Linux Driver Model (LDM) Support + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_LDM + +static int acpi_device_probe(struct device *dev); +static int acpi_device_remove(struct device *dev); +static int acpi_device_suspend(struct device *dev, u32 state, u32 stage); +static int acpi_device_resume(struct device *dev, u32 stage); + +static struct device_driver acpi_bus_driver = { + .probe = acpi_device_probe, + .remove = acpi_device_remove, + .suspend = acpi_device_suspend, + .resume = acpi_device_resume, +}; + + +static int +acpi_device_probe ( + struct device *dev) +{ + ACPI_FUNCTION_TRACE("acpi_device_probe"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */ + + return_VALUE(0); +} + + +static int +acpi_device_remove ( + struct device *dev) +{ + ACPI_FUNCTION_TRACE("acpi_device_remove"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */