103 lines
2.9 KiB
D
103 lines
2.9 KiB
D
/**
|
|
* ACPI (Advanced Configuration and Power Interface) functionality.
|
|
*/
|
|
module hulk.acpi;
|
|
|
|
import hulk.hurl;
|
|
import hulk.klog;
|
|
import hulk.memory;
|
|
|
|
struct acpi
|
|
{
|
|
enum uint APIC_SIGNATURE = 0x43495041u;
|
|
enum uint XSDT_SIGNATURE = 0x54445358u;
|
|
|
|
static struct XsdtHeader
|
|
{
|
|
uint signature;
|
|
uint length;
|
|
ubyte revision;
|
|
ubyte checksum;
|
|
char[6] oemid;
|
|
ulong oemtableid;
|
|
uint oem_revision;
|
|
uint creator_id;
|
|
uint creator_revision;
|
|
}
|
|
|
|
static struct Xsdt
|
|
{
|
|
XsdtHeader header;
|
|
uint _pad;
|
|
ulong[0] tables;
|
|
}
|
|
|
|
static struct MadtHeader
|
|
{
|
|
uint signature;
|
|
uint length;
|
|
ubyte revision;
|
|
ubyte checksum;
|
|
char[6] oemid;
|
|
ulong oemtableid;
|
|
uint oem_revision;
|
|
uint creator_id;
|
|
uint creator_revision;
|
|
uint local_apic_address;
|
|
uint flags;
|
|
}
|
|
|
|
static struct MadtEntry
|
|
{
|
|
ubyte type;
|
|
ubyte length;
|
|
}
|
|
|
|
public static __gshared ulong apic_address;
|
|
|
|
public static void initialize(ulong acpi_xsdt_phys)
|
|
{
|
|
/* Map the XSDT header. */
|
|
hurl.identity_map_range(acpi_xsdt_phys, Xsdt.sizeof, 0u);
|
|
const(Xsdt) * xsdt = cast(const(Xsdt) *)acpi_xsdt_phys;
|
|
if (xsdt.header.signature != XSDT_SIGNATURE)
|
|
{
|
|
klog.writef("XSDT signature invalid\n");
|
|
return;
|
|
}
|
|
/* Map the entire XSDT. */
|
|
hurl.identity_map_range(acpi_xsdt_phys, xsdt.header.length, 0u);
|
|
size_t n_entries = (xsdt.header.length - xsdt.header.sizeof) / xsdt.tables[0].sizeof;
|
|
for (size_t i = 0u; i < n_entries; i++)
|
|
{
|
|
ulong address = xsdt.tables[i];
|
|
hurl.identity_map_range(address, 4u, 0u);
|
|
uint signature = *cast(const(uint) *)address;
|
|
if (signature == APIC_SIGNATURE)
|
|
{
|
|
parse_apic_table(address);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static parse_apic_table(ulong address)
|
|
{
|
|
const(MadtHeader) * madt_header = cast(const(MadtHeader) *)address;
|
|
hurl.identity_map_range(address, madt_header.length, 0u);
|
|
apic_address = madt_header.local_apic_address;
|
|
klog.writefln("Found 32-bit APIC address: 0x%x", apic_address);
|
|
const(void) * madt_end = cast(const(void) *)(address + madt_header.length);
|
|
const(MadtEntry) * madt_entry = cast(const(MadtEntry) *)(address + 0x2Cu);
|
|
while (madt_entry < madt_end)
|
|
{
|
|
madt_entry = cast(const(MadtEntry) *)(cast(size_t)madt_entry + madt_entry.length);
|
|
if (madt_entry.type == 5u)
|
|
{
|
|
/* Found a 64-bit Local APIC Address Override entry. */
|
|
memcpy(cast(void *)&apic_address, cast(const(void) *)madt_entry + 4u, 8u);
|
|
klog.writefln("Found 64-bit APIC address: 0x%x", apic_address);
|
|
}
|
|
}
|
|
}
|
|
}
|