diff options
author | Stefan Reinauer <stepan@openbios.org> | 2004-02-03 16:11:35 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2004-02-03 16:11:35 +0000 |
commit | 06feb88cc60f78c2b3c7036208da68c4c1dc05e1 (patch) | |
tree | e635ec683d74d49767135d4c5c2a5a691d738379 /src/arch/i386/boot/acpi.c | |
parent | a7648c2942448bdbb2813868ac305df24a69fcd0 (diff) |
create MADT tables, too.
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1366 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch/i386/boot/acpi.c')
-rw-r--r-- | src/arch/i386/boot/acpi.c | 113 |
1 files changed, 112 insertions, 1 deletions
diff --git a/src/arch/i386/boot/acpi.c b/src/arch/i386/boot/acpi.c index 271de845de..ca9b66f744 100644 --- a/src/arch/i386/boot/acpi.c +++ b/src/arch/i386/boot/acpi.c @@ -13,8 +13,11 @@ #define RSDT_NAME "RSDT" #define HPET_NAME "HPET" -#define RSDT_TABLE " RSDT " +#define MADT_NAME "APIC" + +#define RSDT_TABLE "RSDT " #define HPET_TABLE "AMD64 " +#define MADT_TABLE "MADT " #define OEM_ID "LXBIOS" #define ASLC "NONE" @@ -29,6 +32,10 @@ static u8 acpi_checksum(u8 *table, u32 length) return -ret; } +/* + * add an acpi table to rsdt structure, and recalculate checksum + */ + static void acpi_add_table(acpi_rsdt_t *rsdt, void *table) { int i; @@ -50,6 +57,99 @@ static void acpi_add_table(acpi_rsdt_t *rsdt, void *table) printk_warning("ACPI: could not ACPI table. failed.\n"); } + +static int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic) +{ + lapic->type=0; + lapic->length=sizeof(acpi_madt_lapic_t); + lapic->flags=1; + + lapic->processor_id=cpu; + lapic->apic_id=apic; + + return(lapic->length); +} + +static int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr) +{ + ioapic->type=1; + ioapic->length=sizeof(acpi_madt_ioapic_t); + ioapic->reserved=0x00; + ioapic->gsi_base=0x00000000; + + ioapic->ioapic_id=id; + ioapic->ioapic_addr=addr; + + return(ioapic->length); +} + +static int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride, + u8 bus, u8 source, u32 gsirq, u16 flags) +{ + irqoverride->type=2; + irqoverride->length=sizeof(acpi_madt_irqoverride_t); + irqoverride->flags=0x0001; + + irqoverride->bus=bus; + irqoverride->source=source; + irqoverride->gsirq=gsirq; + irqoverride->flags=flags; + + return(irqoverride->length); +} + +static int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu, + u16 flags, u8 lint) +{ + lapic_nmi->type=4; + lapic_nmi->length=sizeof(acpi_madt_lapic_nmi_t); + + lapic_nmi->flags=flags; + lapic_nmi->processor_id=cpu; + lapic_nmi->lint=lint; + + return(lapic_nmi->length); +} + +static void acpi_create_madt(acpi_madt_t *madt) +{ +#define LOCAL_APIC_ADDR 0xfee00000ULL +#define IO_APIC_ADDR 0xfec00000UL + acpi_header_t *header=&(madt->header); + unsigned long current=(unsigned long)madt+sizeof(acpi_madt_t); + + memset((void *)madt, 0, sizeof(acpi_madt_t)); + + /* fill out header fields */ + memcpy(header->signature, MADT_NAME, 4); + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, MADT_TABLE, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + + header->length = sizeof(acpi_madt_t); + header->revision = 1; + + madt->lapic_addr= LOCAL_APIC_ADDR; + madt->flags = 0x1; /* PCAT_COMPAT */ + + /* create all subtables for 1p */ + current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, 0, 0); + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *)current, 2, + IO_APIC_ADDR); + current += acpi_create_madt_irqoverride( (acpi_madt_irqoverride_t *) + current, 0, 0, 2, 1 /* active high */); + current += acpi_create_madt_irqoverride( (acpi_madt_irqoverride_t *) + current, 0, 9, 9, 0xf /* active low, level triggered */); + current += acpi_create_madt_lapic_nmi( (acpi_madt_lapic_nmi_t *) + current, 0, 5, 1); + + /* recalculate length */ + header->length= current - (unsigned long)madt; + + header->checksum = acpi_checksum((void *)madt, header->length); +} + + static void acpi_create_hpet(acpi_hpet_t *hpet) { #define HPET_ADDR 0xfed00000ULL @@ -121,6 +221,7 @@ unsigned long write_acpi_tables(unsigned long start) acpi_rsdp_t *rsdp; acpi_rsdt_t *rsdt; acpi_hpet_t *hpet; + acpi_madt_t *madt; /* Align ACPI tables to 16byte */ start = ( start + 0x0f ) & -0x10; @@ -151,6 +252,16 @@ unsigned long write_acpi_tables(unsigned long start) current += sizeof(acpi_hpet_t); acpi_create_hpet(hpet); acpi_add_table(rsdt,hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk_debug("ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current+=madt->header.length; + acpi_add_table(rsdt,madt); + + #endif printk_info("ACPI: done.\n"); return current; |