diff options
author | Peter Jones <pjones@redhat.com> | 2006-02-17 22:13:42 +0000 |
---|---|---|
committer | Peter Jones <pjones@redhat.com> | 2006-02-17 22:13:42 +0000 |
commit | 63cb13ec9b76efb7f8debf9ba7ae509efdc83397 (patch) | |
tree | bedc07847544d7aaec5a1d06aa6689f3d07ee8e4 | |
parent | 0fd2d39e599daadb1d0c83e76330311386993f1e (diff) | |
download | anaconda-63cb13ec9b76efb7f8debf9ba7ae509efdc83397.tar.gz anaconda-63cb13ec9b76efb7f8debf9ba7ae509efdc83397.tar.xz anaconda-63cb13ec9b76efb7f8debf9ba7ae509efdc83397.zip |
- library to count cpus by probing acpi for local APICs
-rw-r--r-- | isys/acpi.c | 1161 | ||||
-rw-r--r-- | isys/acpi.h | 6 | ||||
-rw-r--r-- | isys/acpi/actbl.h | 316 | ||||
-rw-r--r-- | isys/acpi/actbl1.h | 135 | ||||
-rw-r--r-- | isys/acpi/actbl2.h | 277 |
5 files changed, 1895 insertions, 0 deletions
diff --git a/isys/acpi.c b/isys/acpi.c new file mode 100644 index 000000000..e74db2886 --- /dev/null +++ b/isys/acpi.c @@ -0,0 +1,1161 @@ + +#include <sys/types.h> +#include <sys/mman.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <inttypes.h> +#include <stdio.h> +#include <ctype.h> + +#if defined(__x86_64__) || defined(__i386__) + +#define APIC_DEFAULT_PHYS_BASE 0xfee00000 + +#ifdef DIET +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; +#else +typedef u_int64_t u64; +typedef u_int32_t u32; +typedef u_int16_t u16; +typedef u_int8_t u8; +#endif + +#define phys_to_virt(a) (a) +#define __va(a) ((void *)a) +#define __pa(a) ((void *)a) + +#define __init +#define __initdata +#define printk(format, ...) +#define KERN_WARNING "" +#define KERN_ERR "" +#define KERN_DEBUG "" +#define KERN_INFO + +static const int efi_enabled = 0; +static const struct { + unsigned long acpi20; + unsigned long acpi; +} efi = {0,0}; + +static struct acpi_table_rsdp *rsdp = NULL; + +static void mp_register_lapic(u8 id, u8 enabled); + +static void *mem_chunk(size_t base, size_t len, const char *devmem) +{ + void *p; + int fd; + size_t mmoffset; + void *mmp; + size_t pgsz; + +#ifdef _SC_PAGESIZE + pgsz = sysconf(_SC_PAGESIZE); +#else + pgsz = getpagesize(); +#endif /* _SC_PAGESIZE */ + + len = (len + (pgsz-1)) & ~(pgsz-1); + + if((fd=open(devmem, O_RDONLY))==-1) + { + //perror(devmem); + return NULL; + } + + if((p=malloc(len))==NULL) + { + //perror("malloc"); + return NULL; + } + + mmoffset = base % pgsz; + /* + * Please note that we don't use mmap() for performance reasons here, + * but to workaround problems many people encountered when trying + * to read from /dev/mem using regular read() calls. + */ + mmp=mmap(0, mmoffset+len, PROT_READ, MAP_SHARED, fd, base-mmoffset); + if(mmp==MAP_FAILED) + { + free(p); + return NULL; + } + + memcpy(p, (u8 *)mmp+mmoffset, len); + + munmap(mmp, mmoffset+len); + + close(fd); + + return p; +} + +#include "acpi/actbl.h" + +/* Root System Description Pointer (RSDP) */ + +struct acpi_table_rsdp { + char signature[8]; + u8 checksum; + char oem_id[6]; + u8 revision; + u32 rsdt_address; +} __attribute__ ((packed)); + +struct acpi20_table_rsdp { + char signature[8]; + u8 checksum; + char oem_id[6]; + u8 revision; + u32 rsdt_address; + u32 length; + u64 xsdt_address; + u8 ext_checksum; + u8 reserved[3]; +} __attribute__ ((packed)); + +typedef struct { + u8 type; + u8 length; +} __attribute__ ((packed)) acpi_table_entry_header; + +/* Root System Description Table (RSDT) */ + +struct acpi_table_rsdt { + struct acpi_table_header header; + u32 entry[8]; +} __attribute__ ((packed)); + +/* Extended System Description Table (XSDT) */ + +struct acpi_table_xsdt { + struct acpi_table_header header; + u64 entry[1]; +} __attribute__ ((packed)); + +/* Fixed ACPI Description Table (FADT) */ + +struct acpi_table_fadt { + struct acpi_table_header header; + u32 facs_addr; + u32 dsdt_addr; + /* ... */ +} __attribute__ ((packed)); + +/* Multiple APIC Description Table (MADT) */ + +struct acpi_table_madt { + struct acpi_table_header header; + u32 lapic_address; + struct { + u32 pcat_compat:1; + u32 reserved:31; + } flags; +} __attribute__ ((packed)); + +enum acpi_madt_entry_id { + 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 +}; + +typedef struct { + u16 polarity:2; + u16 trigger:2; + u16 reserved:12; +} __attribute__ ((packed)) acpi_interrupt_flags; + +struct acpi_table_lapic { + acpi_table_entry_header header; + u8 acpi_id; + u8 id; + struct { + u32 enabled:1; + u32 reserved:31; + } flags; +} __attribute__ ((packed)); + +struct acpi_table_ioapic { + acpi_table_entry_header header; + u8 id; + u8 reserved; + u32 address; + u32 global_irq_base; +} __attribute__ ((packed)); + +struct acpi_table_int_src_ovr { + acpi_table_entry_header header; + u8 bus; + u8 bus_irq; + u32 global_irq; + acpi_interrupt_flags flags; +} __attribute__ ((packed)); + +struct acpi_table_nmi_src { + acpi_table_entry_header header; + acpi_interrupt_flags flags; + u32 global_irq; +} __attribute__ ((packed)); + +struct acpi_table_lapic_nmi { + acpi_table_entry_header header; + u8 acpi_id; + acpi_interrupt_flags flags; + u8 lint; +} __attribute__ ((packed)); + +struct acpi_table_lapic_addr_ovr { + acpi_table_entry_header header; + u8 reserved[2]; + u64 address; +} __attribute__ ((packed)); + +struct acpi_table_iosapic { + acpi_table_entry_header header; + u8 id; + u8 reserved; + u32 global_irq_base; + u64 address; +} __attribute__ ((packed)); + +struct acpi_table_lsapic { + acpi_table_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_table_entry_header header; + acpi_interrupt_flags flags; + u8 type; /* See acpi_interrupt_type */ + u8 id; + u8 eid; + u8 iosapic_vector; + u32 global_irq; + struct { + u32 cpei_override_flag:1; + u32 reserved:31; + } plint_flags; +} __attribute__ ((packed)); + +enum acpi_interrupt_id { + ACPI_INTERRUPT_PMI = 1, + ACPI_INTERRUPT_INIT, + ACPI_INTERRUPT_CPEI, + ACPI_INTERRUPT_COUNT +}; + +#define ACPI_SPACE_MEM 0 + +struct acpi_gen_regaddr { + u8 space_id; + u8 bit_width; + u8 bit_offset; + u8 resv; + u32 addrl; + u32 addrh; +} __attribute__ ((packed)); + +struct acpi_table_hpet { + struct acpi_table_header header; + u32 id; + struct acpi_gen_regaddr addr; + u8 number; + u16 min_tick; + u8 page_protect; +} __attribute__ ((packed)); + +/* + * Simple Boot Flags + * http://www.microsoft.com/whdc/hwdev/resources/specs/simp_bios.mspx + */ +struct acpi_table_sbf +{ + u8 sbf_signature[4]; + u32 sbf_len; + u8 sbf_revision; + u8 sbf_csum; + u8 sbf_oemid[6]; + u8 sbf_oemtable[8]; + u8 sbf_revdata[4]; + u8 sbf_creator[4]; + u8 sbf_crearev[4]; + u8 sbf_cmos; + u8 sbf_spare[3]; +} __attribute__ ((packed)); + +/* + * System Resource Affinity Table (SRAT) + * http://www.microsoft.com/whdc/hwdev/platform/proc/SRAT.mspx + */ + +struct acpi_table_srat { + struct acpi_table_header header; + u32 table_revision; + u64 reserved; +} __attribute__ ((packed)); + +enum acpi_srat_entry_id { + ACPI_SRAT_PROCESSOR_AFFINITY = 0, + ACPI_SRAT_MEMORY_AFFINITY, + ACPI_SRAT_ENTRY_COUNT +}; + +struct acpi_table_processor_affinity { + acpi_table_entry_header header; + u8 proximity_domain; + u8 apic_id; + struct { + u32 enabled:1; + u32 reserved:31; + } flags; + u8 lsapic_eid; + u8 reserved[7]; +} __attribute__ ((packed)); + +struct acpi_table_memory_affinity { + acpi_table_entry_header header; + u8 proximity_domain; + u8 reserved1[5]; + u32 base_addr_lo; + u32 base_addr_hi; + u32 length_lo; + u32 length_hi; + u32 memory_type; /* See acpi_address_range_id */ + struct { + u32 enabled:1; + u32 hot_pluggable:1; + u32 reserved:30; + } flags; + u64 reserved2; +} __attribute__ ((packed)); + +enum acpi_address_range_id { + ACPI_ADDRESS_RANGE_MEMORY = 1, + ACPI_ADDRESS_RANGE_RESERVED = 2, + ACPI_ADDRESS_RANGE_ACPI = 3, + ACPI_ADDRESS_RANGE_NVS = 4, + ACPI_ADDRESS_RANGE_COUNT +}; + +/* + * System Locality Information Table (SLIT) + * see http://devresource.hp.com/devresource/docs/techpapers/ia64/slit.pdf + */ + +struct acpi_table_slit { + struct acpi_table_header header; + u64 localities; + u8 entry[1]; /* real size = localities^2 */ +} __attribute__ ((packed)); + +/* Smart Battery Description Table (SBST) */ + +struct acpi_table_sbst { + struct acpi_table_header header; + u32 warning; /* Warn user */ + u32 low; /* Critical sleep */ + u32 critical; /* Critical shutdown */ +} __attribute__ ((packed)); + +/* Embedded Controller Boot Resources Table (ECDT) */ + +struct acpi_table_ecdt { + struct acpi_table_header header; + struct acpi_generic_address ec_control; + struct acpi_generic_address ec_data; + u32 uid; + u8 gpe_bit; + char ec_id[0]; +} __attribute__ ((packed)); + +/* PCI MMCONFIG */ + +/* Defined in PCI Firmware Specification 3.0 */ +struct acpi_table_mcfg_config { + u32 base_address; + u32 base_reserved; + u16 pci_segment_group_number; + u8 start_bus_number; + u8 end_bus_number; + u8 reserved[4]; +} __attribute__ ((packed)); +struct acpi_table_mcfg { + struct acpi_table_header header; + u8 reserved[8]; + struct acpi_table_mcfg_config config[0]; +} __attribute__ ((packed)); + +/* Table Handlers */ + +enum acpi_table_id { + ACPI_TABLE_UNKNOWN = 0, + ACPI_APIC, + ACPI_BOOT, + ACPI_DBGP, + ACPI_DSDT, + ACPI_ECDT, + ACPI_ETDT, + ACPI_FADT, + ACPI_FACS, + ACPI_OEMX, + ACPI_PSDT, + ACPI_SBST, + ACPI_SLIT, + ACPI_SPCR, + ACPI_SRAT, + ACPI_SSDT, + ACPI_SPMI, + ACPI_HPET, + ACPI_MCFG, + ACPI_TABLE_COUNT +}; + +typedef int (*acpi_table_handler) (unsigned long phys_addr, unsigned long size); + +extern acpi_table_handler acpi_table_ops[ACPI_TABLE_COUNT]; + +typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header, const unsigned long end); + +static char * __acpi_map_table (unsigned long phys_addr, unsigned long size); +static void *acpi_find_rsdp (void); +int acpi_boot_init (void); +int acpi_boot_table_init (void); +int acpi_numa_init (void); + +static int acpi_table_init (void); +int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler); +static int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header); +static int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); +int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); +int acpi_parse_mcfg (unsigned long phys_addr, unsigned long size); + +/* from mpspec.h */ +#define MAX_APICS 255 + +/* below here from drivers/acpi/tables.c */ + +#define PREFIX "ACPI: " + +#define ACPI_MAX_TABLES 128 + +static char *acpi_table_signatures[ACPI_TABLE_COUNT] = { + [ACPI_TABLE_UNKNOWN] = "????", + [ACPI_APIC] = "APIC", + [ACPI_BOOT] = "BOOT", + [ACPI_DBGP] = "DBGP", + [ACPI_DSDT] = "DSDT", + [ACPI_ECDT] = "ECDT", + [ACPI_ETDT] = "ETDT", + [ACPI_FADT] = "FACP", + [ACPI_FACS] = "FACS", + [ACPI_OEMX] = "OEM", + [ACPI_PSDT] = "PSDT", + [ACPI_SBST] = "SBST", + [ACPI_SLIT] = "SLIT", + [ACPI_SPCR] = "SPCR", + [ACPI_SRAT] = "SRAT", + [ACPI_SSDT] = "SSDT", + [ACPI_SPMI] = "SPMI", + [ACPI_HPET] = "HPET", + [ACPI_MCFG] = "MCFG", +}; + +/* System Description Table (RSDT/XSDT) */ +struct acpi_table_sdt { + unsigned long pa; + enum acpi_table_id id; + unsigned long size; +} __attribute__ ((packed)); + +static unsigned long sdt_count; /* Table count */ + +static struct acpi_table_xsdt *mapped_xsdt = NULL; +static struct acpi_table_rsdt *mapped_rsdt = NULL; + +static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES] __initdata; + + +/* + * acpi_get_table_header_early() + * for acpi_blacklisted(), acpi_table_get_sdt() + */ +static int __init +acpi_get_table_header_early(enum acpi_table_id id, + struct acpi_table_header **header) +{ + unsigned int i; + enum acpi_table_id temp_id; + + /* DSDT is different from the rest */ + if (id == ACPI_DSDT) + temp_id = ACPI_FADT; + else + temp_id = id; + + /* Locate the table. */ + + for (i = 0; i < sdt_count; i++) { + if (sdt_entry[i].id != temp_id) + continue; + *header = (void *) + __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); + if (!*header) { + printk(KERN_WARNING PREFIX "Unable to map %s\n", + acpi_table_signatures[temp_id]); + return -ENODEV; + } + break; + } + + if (!*header) { + printk(KERN_WARNING PREFIX "%s not present\n", + acpi_table_signatures[id]); + return -ENODEV; + } + + /* Map the DSDT header via the pointer in the FADT */ + if (id == ACPI_DSDT) { + struct fadt_descriptor_rev2 *fadt = + (struct fadt_descriptor_rev2 *)*header; + + if (fadt->revision == 3 && fadt->Xdsdt) { + *header = (void *)__acpi_map_table(fadt->Xdsdt, + sizeof(struct + acpi_table_header)); + } else if (fadt->V1_dsdt) { + *header = (void *)__acpi_map_table(fadt->V1_dsdt, + sizeof(struct + acpi_table_header)); + } else + *header = NULL; + + if (!*header) { + printk(KERN_WARNING PREFIX "Unable to map DSDT\n"); + return -ENODEV; + } + } + + return 0; +} + +static int __init +acpi_table_parse_madt_family(enum acpi_table_id id, + unsigned long madt_size, + int entry_id, + acpi_madt_entry_handler handler, + unsigned int max_entries) +{ + void *madt = NULL; + acpi_table_entry_header *entry; + unsigned int count = 0; + unsigned long madt_end; + unsigned int i; + + if (!handler) + return -EINVAL; + + /* Locate the MADT (if exists). There should only be one. */ + + for (i = 0; i < sdt_count; i++) { + if (sdt_entry[i].id != id) + continue; + madt = (void *) + __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); + if (!madt) { + printk(KERN_WARNING PREFIX "Unable to map %s\n", + acpi_table_signatures[id]); + return -ENODEV; + } + break; + } + + if (!madt) { + printk(KERN_WARNING PREFIX "%s not present\n", + acpi_table_signatures[id]); + return -ENODEV; + } + + madt_end = (unsigned long)madt + sdt_entry[i].size; + + /* Parse all entries looking for a match. */ + + entry = (acpi_table_entry_header *) + ((unsigned long)madt + madt_size); + + while (((unsigned long)entry) + sizeof(acpi_table_entry_header) < + madt_end) { + if (entry->type == entry_id + && (!max_entries || count++ < max_entries)) + if (handler(entry, madt_end)) + return -EINVAL; + + entry = (acpi_table_entry_header *) + ((unsigned long)entry + entry->length); + } + if (max_entries && count > max_entries) { + printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of " + "%i found\n", acpi_table_signatures[id], entry_id, + count - max_entries, count); + } + + return count; +} + +static int __init +acpi_table_parse_madt(enum acpi_madt_entry_id id, + acpi_madt_entry_handler handler, unsigned int max_entries) +{ + return acpi_table_parse_madt_family(ACPI_APIC, + sizeof(struct acpi_table_madt), id, + handler, max_entries); +} + +static int +acpi_table_compute_checksum(void *table_pointer, unsigned long length) +{ + u8 *p = (u8 *) table_pointer; + unsigned long remains = length; + unsigned long sum = 0; + + if (!p || !length) + return -EINVAL; + + while (remains--) + sum += *p++; + + return (sum & 0xFF); +} + + +/* from arch/i386/kernel/acpi/boot.c */ +static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; + +#define MAX_MADT_ENTRIES 256 +u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] = + {[0 ... MAX_MADT_ENTRIES - 1] = 0xff }; + +#define BAD_MADT_ENTRY(entry, end) ( \ + (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ + ((acpi_table_entry_header *)entry)->length != sizeof(*entry)) + +static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { + return 0; +} + +static void acpi_table_print(struct acpi_table_header *header, unsigned long phys_addr) +{ + char *name = NULL; + + if (!header) + return; + + /* Some table signatures aren't good table names */ + + if (!strncmp((char *)&header->signature, + acpi_table_signatures[ACPI_APIC], + sizeof(header->signature))) { + name = "MADT"; + } else if (!strncmp((char *)&header->signature, + acpi_table_signatures[ACPI_FADT], + sizeof(header->signature))) { + name = "FADT"; + } else + name = header->signature; + + printk(KERN_DEBUG PREFIX + "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", name, + header->revision, header->oem_id, header->oem_table_id, + header->oem_revision, header->asl_compiler_id, + header->asl_compiler_revision, (void *)phys_addr); +} + +#if 0 +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_DEBUG PREFIX "Local APIC address 0x%08x\n", + madt->lapic_address); + } + + acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id); + + return 0; +} +#endif + +static int __init +acpi_parse_lapic(acpi_table_entry_header * header, const unsigned long end) +{ + struct acpi_table_lapic *processor = NULL; + + processor = (struct acpi_table_lapic *)header; + + if (BAD_MADT_ENTRY(processor, end)) + return -EINVAL; + + /* Record local apic id only when enabled */ + if (processor->flags.enabled) + x86_acpiid_to_apicid[processor->acpi_id] = processor->id; + + /* + * We need to register disabled CPU as well to permit + * counting disabled CPUs. This allows us to size + * cpus_possible_map more accurately, to permit + * to not preallocating memory for all NR_CPUS + * when we use CPU hotplug. + */ + 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, + const unsigned long end) +{ + struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; + + lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr *)header; + + if (BAD_MADT_ENTRY(lapic_addr_ovr, end)) + return -EINVAL; + + acpi_lapic_addr = lapic_addr_ovr->address; + + return 0; +} + +static int __init +acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end) +{ + struct acpi_table_lapic_nmi *lapic_nmi = NULL; + + lapic_nmi = (struct acpi_table_lapic_nmi *)header; + + if (BAD_MADT_ENTRY(lapic_nmi, end)) + return -EINVAL; + + if (lapic_nmi->lint != 1) + printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); + + return 0; +} + +static void *__init +acpi_scan_rsdp(unsigned long start, unsigned long length) +{ + unsigned long offset = 0; + unsigned long sig_len = sizeof("RSD PTR ") - 1; + char *ptr; + + + /* + * Scan all 16-byte boundaries of the physical memory region for the + * RSDP signature. + */ + ptr = mem_chunk(0, 4096 * 4096, "/dev/mem"); + if (!ptr) + return 0; + + for (offset = 0; offset < length; offset += 16) { + if (strncmp(ptr+start+offset, "RSD PTR ", sig_len)) + continue; + free(ptr); + return (void *)start + offset; + } + + return 0; +} + +static void * __init acpi_find_rsdp(void) +{ + void *rsdp_phys = 0; + + if (efi_enabled) { + if (efi.acpi20) + return __pa(efi.acpi20); + else if (efi.acpi) + return __pa(efi.acpi); + } + /* + * 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, 0x20000); + + return rsdp_phys; +} + +static int __init acpi_parse_madt_lapic_entries(void) +{ + int count; + + /* + * 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). + */ + + count = + acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, + acpi_parse_lapic_addr_ovr, 0); + if (count < 0) { + printk(KERN_ERR PREFIX + "Error parsing LAPIC address override entry\n"); + return count; + } + +#if 0 + mp_register_lapic_address(acpi_lapic_addr); +#endif + + count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic, + MAX_APICS); + if (!count) { + printk(KERN_ERR PREFIX "No LAPIC entries present\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return -ENODEV; + } else if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return count; + } + + count = + acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0); + if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return count; + } + return 0; +} + +static int __init acpi_table_get_sdt(struct acpi_table_rsdp *rsdp) +{ + struct acpi_table_header *header = NULL; + unsigned int i, id = 0; + unsigned long sdt_pa; /* Physical Address */ + + if (!rsdp) + return -EINVAL; + + /* First check XSDT (but only on ACPI 2.0-compatible systems) */ + + if ((rsdp->revision >= 2) && + (((struct acpi20_table_rsdp *)rsdp)->xsdt_address)) { + + struct acpi_table_xsdt *mapped_xsdt = NULL; + + sdt_pa = ((struct acpi20_table_rsdp *)rsdp)->xsdt_address; + + /* map in just the header */ + header = (struct acpi_table_header *) + __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); + + if (!header) { + printk(KERN_WARNING PREFIX + "Unable to map XSDT header\n"); + free(header); + return -ENODEV; + } + + /* remap in the entire table before processing */ + mapped_xsdt = (struct acpi_table_xsdt *) + __acpi_map_table(sdt_pa, header->length); + free(header); + if (!mapped_xsdt) { + printk(KERN_WARNING PREFIX "Unable to map XSDT\n"); + free(mapped_xsdt); + mapped_xsdt = NULL; + return -ENODEV; + } + header = &mapped_xsdt->header; + + if (strncmp(header->signature, "XSDT", 4)) { + printk(KERN_WARNING PREFIX + "XSDT signature incorrect\n"); + free(header); + free(mapped_xsdt); + mapped_xsdt = NULL; + return -ENODEV; + } + + if (acpi_table_compute_checksum(header, header->length)) { + printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n"); + free(header); + free(mapped_xsdt); + mapped_xsdt = NULL; + return -ENODEV; + } + + sdt_count = + (header->length - sizeof(struct acpi_table_header)) >> 3; + if (sdt_count > ACPI_MAX_TABLES) { + printk(KERN_WARNING PREFIX + "Truncated %lu XSDT entries\n", + (sdt_count - ACPI_MAX_TABLES)); + sdt_count = ACPI_MAX_TABLES; + } + + for (i = 0; i < sdt_count; i++) + sdt_entry[i].pa = (unsigned long)mapped_xsdt->entry[i]; + free(header); + } + + /* Then check RSDT */ + + else if (rsdp->rsdt_address) { + + sdt_pa = rsdp->rsdt_address; + + /* map in just the header */ + header = (struct acpi_table_header *) + __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); + if (!header) { + printk(KERN_WARNING PREFIX + "Unable to map RSDT header\n"); + free(header); + return -ENODEV; + } + + /* remap in the entire table before processing */ + mapped_rsdt = (struct acpi_table_rsdt *) + __acpi_map_table((unsigned long)sdt_pa, header->length); + free(header); + if (!mapped_rsdt) { + printk(KERN_WARNING PREFIX "Unable to map RSDT\n"); + free(mapped_rsdt); + mapped_rsdt = NULL; + return -ENODEV; + } + header = &mapped_rsdt->header; + + if (strncmp(header->signature, "RSDT", 4)) { + printk(KERN_WARNING PREFIX + "RSDT signature incorrect\n"); + free(header); + free(mapped_rsdt); + mapped_rsdt = NULL; + return -ENODEV; + } + + if (acpi_table_compute_checksum(header, header->length)) { + printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n"); + free(header); + free(mapped_rsdt); + mapped_rsdt = NULL; + return -ENODEV; + } + + sdt_count = + (header->length - sizeof(struct acpi_table_header)) >> 2; + if (sdt_count > ACPI_MAX_TABLES) { + printk(KERN_WARNING PREFIX + "Truncated %lu RSDT entries\n", + (sdt_count - ACPI_MAX_TABLES)); + sdt_count = ACPI_MAX_TABLES; + } + + for (i = 0; i < sdt_count; i++) + sdt_entry[i].pa = (unsigned long)mapped_rsdt->entry[i]; + free(header); + } + + else { + printk(KERN_WARNING PREFIX + "No System Description Table (RSDT/XSDT) specified in RSDP\n"); + return -ENODEV; + } + + acpi_table_print(header, sdt_pa); + + for (i = 0; i < sdt_count; i++) { + struct acpi_table_header *h1; + + /* map in just the header */ + header = (struct acpi_table_header *) + __acpi_map_table(sdt_entry[i].pa, + sizeof(struct acpi_table_header)); + if (!header) + continue; + + /* remap in the entire table before processing */ + h1 = header; + header = (struct acpi_table_header *) + __acpi_map_table(sdt_entry[i].pa, header->length); + free(h1); + if (!header) + continue; + + acpi_table_print(header, sdt_entry[i].pa); + + if (acpi_table_compute_checksum(header, header->length)) { + printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); + continue; + } + + sdt_entry[i].size = header->length; + + for (id = 0; id < ACPI_TABLE_COUNT; id++) { + if (!strncmp((char *)&header->signature, + acpi_table_signatures[id], + sizeof(header->signature))) { + sdt_entry[i].id = id; + } + } + } + + /* + * The DSDT is *not* in the RSDT (why not? no idea.) but we want + * to print its info, because this is what people usually blacklist + * against. Unfortunately, we don't know the phys_addr, so just + * print 0. Maybe no one will notice. + */ + if (!acpi_get_table_header_early(ACPI_DSDT, &header)) + acpi_table_print(header, 0); + + free(header); + return 0; +} + +/* + * acpi_table_init() + * + * find RSDP, find and checksum SDT/XSDT. + * checksum all tables, print SDT/XSDT + * + * result: sdt_entry[] is initialized + */ + +static int acpi_table_init(void) +{ + void *rsdp_phys = 0; + int result = 0; + + /* Locate and map the Root System Description Table (RSDP) */ + + rsdp_phys = acpi_find_rsdp(); + if (!rsdp_phys) { + printk(KERN_ERR PREFIX "Unable to locate RSDP\n"); + return -ENODEV; + } + + rsdp = mem_chunk((unsigned long)rsdp_phys, sizeof (*rsdp), "/dev/mem"); + if (!rsdp) { + printk(KERN_WARNING PREFIX "Unable to map RSDP\n"); + return -ENODEV; + } + + printk(KERN_DEBUG PREFIX + "RSDP (v%3.3d %6.6s ) @ 0x%p\n", + rsdp->revision, rsdp->oem_id, (void *)rsdp_phys); + + if (rsdp->revision < 2) + result = + acpi_table_compute_checksum(rsdp, + sizeof(struct acpi_table_rsdp)); + else + result = + acpi_table_compute_checksum(rsdp, + ((struct acpi20_table_rsdp *) + rsdp)->length); + + if (result) { + printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); + free(rsdp); + rsdp = NULL; + return -ENODEV; + } + + /* Locate and map the System Description table (RSDT/XSDT) */ + + result = acpi_table_get_sdt(rsdp); + if (result) { + free(rsdp); + rsdp = NULL; + return -ENODEV; + } + + return 0; +} + +/* original code */ + +/* not actually from arch/i386/kernel/acpi/boot.c... */ +static char *__acpi_map_table(unsigned long phys, unsigned long size) +{ + char *ret = mem_chunk(phys, size, "/dev/mem"); + + return ret; +} + +static int ncpus=0; + +static void mp_register_lapic(u8 id, u8 enabled) +{ + ncpus++; +} + +int detectAcpiCpusAvailable(void) +{ + int result; + + result = acpi_table_init(); + if (result < 0) { + return 0; + } + acpi_parse_madt_lapic_entries(); + if (mapped_xsdt) + free(mapped_xsdt); + if (mapped_rsdt) + free(mapped_rsdt); + free(rsdp); + + return ncpus; +} +#else /* !defined(__i386__) && !defined(__x86_64__) */ + +int detectAcpiCpusAvailable(void) +{ + return 0; +} + +#endif diff --git a/isys/acpi.h b/isys/acpi.h new file mode 100644 index 000000000..f7a731177 --- /dev/null +++ b/isys/acpi.h @@ -0,0 +1,6 @@ +#ifndef ISYS_ACPI_H +#define ISYS_ACPI_H 1 + +extern int detectAcpiCpusAvailable(void); + +#endif /* ISYS_ACPI_H */ diff --git a/isys/acpi/actbl.h b/isys/acpi/actbl.h new file mode 100644 index 000000000..ed53f842d --- /dev/null +++ b/isys/acpi/actbl.h @@ -0,0 +1,316 @@ +/****************************************************************************** + * + * Name: actbl.h - Table data structures defined in ACPI specification + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTBL_H__ +#define __ACTBL_H__ + +/* + * Note about bitfields: The u8 type is used for bitfields in ACPI tables. + * This is the only type that is even remotely portable. Anything else is not + * portable, so do not use any other bitfield types. + */ + +/* + * Values for description table header signatures + */ +#define RSDP_NAME "RSDP" +#define RSDP_SIG "RSD PTR " /* RSDT Pointer signature */ +#define APIC_SIG "APIC" /* Multiple APIC Description Table */ +#define DSDT_SIG "DSDT" /* Differentiated System Description Table */ +#define FADT_SIG "FACP" /* Fixed ACPI Description Table */ +#define FACS_SIG "FACS" /* Firmware ACPI Control Structure */ +#define PSDT_SIG "PSDT" /* Persistent System Description Table */ +#define RSDT_SIG "RSDT" /* Root System Description Table */ +#define XSDT_SIG "XSDT" /* Extended System Description Table */ +#define SSDT_SIG "SSDT" /* Secondary System Description Table */ +#define SBST_SIG "SBST" /* Smart Battery Specification Table */ +#define SPIC_SIG "SPIC" /* IOSAPIC table */ +#define BOOT_SIG "BOOT" /* Boot table */ + +#define GL_OWNED 0x02 /* Ownership of global lock is bit 1 */ + +/* + * Common table types. The base code can remain + * constant if the underlying tables are changed + */ +#define RSDT_DESCRIPTOR struct rsdt_descriptor_rev2 +#define XSDT_DESCRIPTOR struct xsdt_descriptor_rev2 +#define FACS_DESCRIPTOR struct facs_descriptor_rev2 +#define FADT_DESCRIPTOR struct fadt_descriptor_rev2 + +#pragma pack(1) + +/* + * ACPI Version-independent tables + * + * NOTE: The tables that are specific to ACPI versions (1.0, 2.0, etc.) + * are in separate files. + */ +struct rsdp_descriptor { /* Root System Descriptor Pointer */ + char signature[8]; /* ACPI signature, contains "RSD PTR " */ + u8 checksum; /* ACPI 1.0 checksum */ + char oem_id[6]; /* OEM identification */ + u8 revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */ + u32 rsdt_physical_address; /* 32-bit physical address of the RSDT */ + u32 length; /* XSDT Length in bytes, including header */ + u64 xsdt_physical_address; /* 64-bit physical address of the XSDT */ + u8 extended_checksum; /* Checksum of entire table (ACPI 2.0) */ + char reserved[3]; /* Reserved, must be zero */ +}; + +struct acpi_common_facs { /* Common FACS for internal use */ + u32 *global_lock; + u64 *firmware_waking_vector; + u8 vector_width; +}; + +#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ + char signature[4]; /* ASCII table signature */\ + u32 length; /* Length of table in bytes, including this header */\ + u8 revision; /* ACPI Specification minor version # */\ + u8 checksum; /* To make sum of entire table == 0 */\ + char oem_id[6]; /* ASCII OEM identification */\ + char oem_table_id[8]; /* ASCII OEM table identification */\ + u32 oem_revision; /* OEM revision number */\ + char asl_compiler_id [4]; /* ASCII ASL compiler vendor ID */\ + u32 asl_compiler_revision; /* ASL compiler version */ + +struct acpi_table_header { /* ACPI common table header */ +ACPI_TABLE_HEADER_DEF}; + +/* + * MADT values and structures + */ + +/* Values for MADT PCATCompat */ + +#define DUAL_PIC 0 +#define MULTIPLE_APIC 1 + +/* Master MADT */ + +struct multiple_apic_table { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u32 local_apic_address; /* Physical address of local APIC */ + + /* Flags (32 bits) */ + + u8 PCATcompat:1; /* 00: System also has dual 8259s */ + u8:7; /* 01-07: Reserved, must be zero */ + u8 reserved1[3]; /* 08-31: Reserved, must be zero */ +}; + +/* Values for Type in APIC_HEADER_DEF */ + +#define APIC_PROCESSOR 0 +#define APIC_IO 1 +#define APIC_XRUPT_OVERRIDE 2 +#define APIC_NMI 3 +#define APIC_LOCAL_NMI 4 +#define APIC_ADDRESS_OVERRIDE 5 +#define APIC_IO_SAPIC 6 +#define APIC_LOCAL_SAPIC 7 +#define APIC_XRUPT_SOURCE 8 +#define APIC_RESERVED 9 /* 9 and greater are reserved */ + +/* + * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) + */ +#define APIC_HEADER_DEF /* Common APIC sub-structure header */\ + u8 type; \ + u8 length; + +struct apic_header { +APIC_HEADER_DEF}; + +/* Values for MPS INTI flags */ + +#define POLARITY_CONFORMS 0 +#define POLARITY_ACTIVE_HIGH 1 +#define POLARITY_RESERVED 2 +#define POLARITY_ACTIVE_LOW 3 + +#define TRIGGER_CONFORMS 0 +#define TRIGGER_EDGE 1 +#define TRIGGER_RESERVED 2 +#define TRIGGER_LEVEL 3 + +/* Common flag definitions (16 bits each) */ + +#define MPS_INTI_FLAGS \ + u8 polarity : 2; /* 00-01: Polarity of APIC I/O input signals */\ + u8 trigger_mode : 2; /* 02-03: Trigger mode of APIC input signals */\ + u8 : 4; /* 04-07: Reserved, must be zero */\ + u8 reserved1; /* 08-15: Reserved, must be zero */ + +#define LOCAL_APIC_FLAGS \ + u8 processor_enabled: 1; /* 00: Processor is usable if set */\ + u8 : 7; /* 01-07: Reserved, must be zero */\ + u8 reserved2; /* 08-15: Reserved, must be zero */ + +/* Sub-structures for MADT */ + +struct madt_processor_apic { + APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ + u8 local_apic_id; /* Processor's local APIC id */ + LOCAL_APIC_FLAGS}; + +struct madt_io_apic { + APIC_HEADER_DEF u8 io_apic_id; /* I/O APIC ID */ + u8 reserved; /* Reserved - must be zero */ + u32 address; /* APIC physical address */ + u32 interrupt; /* Global system interrupt where INTI + * lines start */ +}; + +struct madt_interrupt_override { + APIC_HEADER_DEF u8 bus; /* 0 - ISA */ + u8 source; /* Interrupt source (IRQ) */ + u32 interrupt; /* Global system interrupt */ + MPS_INTI_FLAGS}; + +struct madt_nmi_source { + APIC_HEADER_DEF MPS_INTI_FLAGS u32 interrupt; /* Global system interrupt */ +}; + +struct madt_local_apic_nmi { + APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ + MPS_INTI_FLAGS u8 lint; /* LINTn to which NMI is connected */ +}; + +struct madt_address_override { + APIC_HEADER_DEF u16 reserved; /* Reserved, must be zero */ + u64 address; /* APIC physical address */ +}; + +struct madt_io_sapic { + APIC_HEADER_DEF u8 io_sapic_id; /* I/O SAPIC ID */ + u8 reserved; /* Reserved, must be zero */ + u32 interrupt_base; /* Glocal interrupt for SAPIC start */ + u64 address; /* SAPIC physical address */ +}; + +struct madt_local_sapic { + APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ + u8 local_sapic_id; /* SAPIC ID */ + u8 local_sapic_eid; /* SAPIC EID */ + u8 reserved[3]; /* Reserved, must be zero */ + LOCAL_APIC_FLAGS u32 processor_uID; /* Numeric UID - ACPI 3.0 */ + char processor_uIDstring[1]; /* String UID - ACPI 3.0 */ +}; + +struct madt_interrupt_source { + APIC_HEADER_DEF MPS_INTI_FLAGS u8 interrupt_type; /* 1=PMI, 2=INIT, 3=corrected */ + u8 processor_id; /* Processor ID */ + u8 processor_eid; /* Processor EID */ + u8 io_sapic_vector; /* Vector value for PMI interrupts */ + u32 interrupt; /* Global system interrupt */ + u32 flags; /* Interrupt Source Flags */ +}; + +/* + * Smart Battery + */ +struct smart_battery_table { + ACPI_TABLE_HEADER_DEF u32 warning_level; + u32 low_level; + u32 critical_level; +}; + +#pragma pack() + +/* + * ACPI Table information. We save the table address, length, + * and type of memory allocation (mapped or allocated) for each + * table for 1) when we exit, and 2) if a new table is installed + */ +#define ACPI_MEM_NOT_ALLOCATED 0 +#define ACPI_MEM_ALLOCATED 1 +#define ACPI_MEM_MAPPED 2 + +/* Definitions for the Flags bitfield member of struct acpi_table_support */ + +#define ACPI_TABLE_SINGLE 0x00 +#define ACPI_TABLE_MULTIPLE 0x01 +#define ACPI_TABLE_EXECUTABLE 0x02 + +#define ACPI_TABLE_ROOT 0x00 +#define ACPI_TABLE_PRIMARY 0x10 +#define ACPI_TABLE_SECONDARY 0x20 +#define ACPI_TABLE_ALL 0x30 +#define ACPI_TABLE_TYPE_MASK 0x30 + +/* Data about each known table type */ + +struct acpi_table_support { + char *name; + char *signature; + void **global_ptr; + u8 sig_length; + u8 flags; +}; + +/* + * Get the ACPI version-specific tables + */ +#include "actbl1.h" /* Acpi 1.0 table definitions */ +#include "actbl2.h" /* Acpi 2.0 table definitions */ + +extern u8 acpi_fadt_is_v1; /* is set to 1 if FADT is revision 1, + * needed for certain workarounds */ + +#pragma pack(1) +/* + * High performance timer + */ +struct hpet_table { + ACPI_TABLE_HEADER_DEF u32 hardware_id; + struct acpi_generic_address base_address; + u8 hpet_number; + u16 clock_tick; + u8 attributes; +}; + +#pragma pack() + +#endif /* __ACTBL_H__ */ diff --git a/isys/acpi/actbl1.h b/isys/acpi/actbl1.h new file mode 100644 index 000000000..cd428d57a --- /dev/null +++ b/isys/acpi/actbl1.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * + * Name: actbl1.h - ACPI 1.0 tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTBL1_H__ +#define __ACTBL1_H__ + +#pragma pack(1) + +/* + * ACPI 1.0 Root System Description Table (RSDT) + */ +struct rsdt_descriptor_rev1 { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */ +}; + +/* + * ACPI 1.0 Firmware ACPI Control Structure (FACS) + */ +struct facs_descriptor_rev1 { + char signature[4]; /* ASCII table signature */ + u32 length; /* Length of structure in bytes */ + u32 hardware_signature; /* Hardware configuration signature */ + u32 firmware_waking_vector; /* ACPI OS waking vector */ + u32 global_lock; /* Global Lock */ + + /* Flags (32 bits) */ + + u8 S4bios_f:1; /* 00: S4BIOS support is present */ + u8:7; /* 01-07: Reserved, must be zero */ + u8 reserved1[3]; /* 08-31: Reserved, must be zero */ + + u8 reserved2[40]; /* Reserved, must be zero */ +}; + +/* + * ACPI 1.0 Fixed ACPI Description Table (FADT) + */ +struct fadt_descriptor_rev1 { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u32 firmware_ctrl; /* Physical address of FACS */ + u32 dsdt; /* Physical address of DSDT */ + u8 model; /* System Interrupt Model */ + u8 reserved1; /* Reserved, must be zero */ + u16 sci_int; /* System vector of SCI interrupt */ + u32 smi_cmd; /* Port address of SMI command port */ + u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ + u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ + u8 reserved2; /* Reserved, must be zero */ + u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ + u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ + u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ + u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ + u8 reserved3; /* Reserved, must be zero */ + u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ + u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ + u16 flush_size; /* Size of area read to flush caches */ + u16 flush_stride; /* Stride used in flushing caches */ + u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */ + u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */ + u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ + u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ + u8 century; /* Index to century in RTC CMOS RAM */ + u8 reserved4[3]; /* Reserved, must be zero */ + + /* Flags (32 bits) */ + + u8 wb_invd:1; /* 00: The wbinvd instruction works properly */ + u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */ + u8 proc_c1:1; /* 02: All processors support C1 state */ + u8 plvl2_up:1; /* 03: C2 state works on MP system */ + u8 pwr_button:1; /* 04: Power button is handled as a generic feature */ + u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */ + u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */ + u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */ + u8 tmr_val_ext:1; /* 08: tmr_val width is 32 bits (0 = 24 bits) */ + u8:7; /* 09-15: Reserved, must be zero */ + u8 reserved5[2]; /* 16-31: Reserved, must be zero */ +}; + +#pragma pack() + +#endif /* __ACTBL1_H__ */ diff --git a/isys/acpi/actbl2.h b/isys/acpi/actbl2.h new file mode 100644 index 000000000..dfc7ac109 --- /dev/null +++ b/isys/acpi/actbl2.h @@ -0,0 +1,277 @@ +/****************************************************************************** + * + * Name: actbl2.h - ACPI Specification Revision 2.0 Tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTBL2_H__ +#define __ACTBL2_H__ + +/* + * Prefered Power Management Profiles + */ +#define PM_UNSPECIFIED 0 +#define PM_DESKTOP 1 +#define PM_MOBILE 2 +#define PM_WORKSTATION 3 +#define PM_ENTERPRISE_SERVER 4 +#define PM_SOHO_SERVER 5 +#define PM_APPLIANCE_PC 6 + +/* + * ACPI Boot Arch Flags + */ +#define BAF_LEGACY_DEVICES 0x0001 +#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 + +#define FADT2_REVISION_ID 3 +#define FADT2_MINUS_REVISION_ID 2 + +#pragma pack(1) + +/* + * ACPI 2.0 Root System Description Table (RSDT) + */ +struct rsdt_descriptor_rev2 { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */ +}; + +/* + * ACPI 2.0 Extended System Description Table (XSDT) + */ +struct xsdt_descriptor_rev2 { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u64 table_offset_entry[1]; /* Array of pointers to ACPI tables */ +}; + +/* + * ACPI 2.0 Firmware ACPI Control Structure (FACS) + */ +struct facs_descriptor_rev2 { + char signature[4]; /* ASCII table signature */ + u32 length; /* Length of structure, in bytes */ + u32 hardware_signature; /* Hardware configuration signature */ + u32 firmware_waking_vector; /* 32-bit physical address of the Firmware Waking Vector. */ + u32 global_lock; /* Global Lock used to synchronize access to shared hardware resources */ + + /* Flags (32 bits) */ + + u8 S4bios_f:1; /* 00: S4BIOS support is present */ + u8:7; /* 01-07: Reserved, must be zero */ + u8 reserved1[3]; /* 08-31: Reserved, must be zero */ + + u64 xfirmware_waking_vector; /* 64-bit physical address of the Firmware Waking Vector. */ + u8 version; /* Version of this table */ + u8 reserved3[31]; /* Reserved, must be zero */ +}; + +/* + * ACPI 2.0+ Generic Address Structure (GAS) + */ +struct acpi_generic_address { + u8 address_space_id; /* Address space where struct or register exists. */ + u8 register_bit_width; /* Size in bits of given register */ + u8 register_bit_offset; /* Bit offset within the register */ + u8 access_width; /* Minimum Access size (ACPI 3.0) */ + u64 address; /* 64-bit address of struct or register */ +}; + +#define FADT_REV2_COMMON \ + u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ \ + u32 V1_dsdt; /* 32-bit physical address of DSDT */ \ + u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \ + u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ \ + u16 sci_int; /* System vector of SCI interrupt */ \ + u32 smi_cmd; /* Port address of SMI command port */ \ + u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \ + u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \ + u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ \ + u8 pstate_cnt; /* Processor performance state control*/ \ + u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ \ + u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ \ + u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \ + u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \ + u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \ + u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \ + u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \ + u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \ + u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ \ + u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ \ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \ + u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \ + u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ \ + u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ \ + u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \ + u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \ + u16 flush_size; /* Number of flush strides that need to be read */ \ + u16 flush_stride; /* Processor's memory cache line width, in bytes */ \ + u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/ \ + u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/ \ + u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \ + u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \ + u8 century; /* Index to century in RTC CMOS RAM */ \ + u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ + +/* + * ACPI 2.0+ Fixed ACPI Description Table (FADT) + */ +struct fadt_descriptor_rev2 { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + FADT_REV2_COMMON u8 reserved2; /* Reserved, must be zero */ + + /* Flags (32 bits) */ + + u8 wb_invd:1; /* 00: The wbinvd instruction works properly */ + u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */ + u8 proc_c1:1; /* 02: All processors support C1 state */ + u8 plvl2_up:1; /* 03: C2 state works on MP system */ + u8 pwr_button:1; /* 04: Power button is handled as a generic feature */ + u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */ + u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */ + u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */ + u8 tmr_val_ext:1; /* 08: tmr_val is 32 bits 0=24-bits */ + u8 dock_cap:1; /* 09: Docking supported */ + u8 reset_reg_sup:1; /* 10: System reset via the FADT RESET_REG supported */ + u8 sealed_case:1; /* 11: No internal expansion capabilities and case is sealed */ + u8 headless:1; /* 12: No local video capabilities or local input devices */ + u8 cpu_sw_sleep:1; /* 13: Must execute native instruction after writing SLP_TYPx register */ + + u8 pci_exp_wak:1; /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */ + u8 use_platform_clock:1; /* 15: OSPM should use platform-provided timer (ACPI 3.0) */ + u8 S4rtc_sts_valid:1; /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */ + u8 remote_power_on_capable:1; /* 17: System is compatible with remote power on (ACPI 3.0) */ + u8 force_apic_cluster_model:1; /* 18: All local APICs must use cluster model (ACPI 3.0) */ + u8 force_apic_physical_destination_mode:1; /* 19: all local x_aPICs must use physical dest mode (ACPI 3.0) */ + u8:4; /* 20-23: Reserved, must be zero */ + u8 reserved3; /* 24-31: Reserved, must be zero */ + + struct acpi_generic_address reset_register; /* Reset register address in GAS format */ + u8 reset_value; /* Value to write to the reset_register port to reset the system */ + u8 reserved4[3]; /* These three bytes must be zero */ + u64 xfirmware_ctrl; /* 64-bit physical address of FACS */ + u64 Xdsdt; /* 64-bit physical address of DSDT */ + struct acpi_generic_address xpm1a_evt_blk; /* Extended Power Mgt 1a acpi_event Reg Blk address */ + struct acpi_generic_address xpm1b_evt_blk; /* Extended Power Mgt 1b acpi_event Reg Blk address */ + struct acpi_generic_address xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */ + struct acpi_generic_address xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */ + struct acpi_generic_address xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */ + struct acpi_generic_address xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */ + struct acpi_generic_address xgpe0_blk; /* Extended General Purpose acpi_event 0 Reg Blk address */ + struct acpi_generic_address xgpe1_blk; /* Extended General Purpose acpi_event 1 Reg Blk address */ +}; + +/* "Down-revved" ACPI 2.0 FADT descriptor */ + +struct fadt_descriptor_rev2_minus { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + FADT_REV2_COMMON u8 reserved2; /* Reserved, must be zero */ + u32 flags; + struct acpi_generic_address reset_register; /* Reset register address in GAS format */ + u8 reset_value; /* Value to write to the reset_register port to reset the system. */ + u8 reserved7[3]; /* Reserved, must be zero */ +}; + +/* ECDT - Embedded Controller Boot Resources Table */ + +struct ec_boot_resources { + ACPI_TABLE_HEADER_DEF struct acpi_generic_address ec_control; /* Address of EC command/status register */ + struct acpi_generic_address ec_data; /* Address of EC data register */ + u32 uid; /* Unique ID - must be same as the EC _UID method */ + u8 gpe_bit; /* The GPE for the EC */ + u8 ec_id[1]; /* Full namepath of the EC in the ACPI namespace */ +}; + +/* SRAT - System Resource Affinity Table */ + +struct static_resource_alloc { + u8 type; + u8 length; + u8 proximity_domain_lo; + u8 apic_id; + + /* Flags (32 bits) */ + + u8 enabled:1; /* 00: Use affinity structure */ + u8:7; /* 01-07: Reserved, must be zero */ + u8 reserved3[3]; /* 08-31: Reserved, must be zero */ + + u8 local_sapic_eid; + u8 proximity_domain_hi[3]; + u32 reserved4; /* Reserved, must be zero */ +}; + +struct memory_affinity { + u8 type; + u8 length; + u32 proximity_domain; + u16 reserved3; + u64 base_address; + u64 address_length; + u32 reserved4; + + /* Flags (32 bits) */ + + u8 enabled:1; /* 00: Use affinity structure */ + u8 hot_pluggable:1; /* 01: Memory region is hot pluggable */ + u8 non_volatile:1; /* 02: Memory is non-volatile */ + u8:5; /* 03-07: Reserved, must be zero */ + u8 reserved5[3]; /* 08-31: Reserved, must be zero */ + + u64 reserved6; /* Reserved, must be zero */ +}; + +struct system_resource_affinity { + ACPI_TABLE_HEADER_DEF u32 reserved1; /* Must be value '1' */ + u64 reserved2; /* Reserved, must be zero */ +}; + +/* SLIT - System Locality Distance Information Table */ + +struct system_locality_info { + ACPI_TABLE_HEADER_DEF u64 locality_count; + u8 entry[1][1]; +}; + +#pragma pack() + +#endif /* __ACTBL2_H__ */ |