31#define ACPI_WINDOW ARCH_ACPI_BASE
32#define ACPI_WINDOW_SIZE 0x00400000UL
38#define FADT_SMI_CMD 48
39#define FADT_ACPI_ENABLE 52
40#define FADT_PM1A_CNT 64
41#define FADT_PM1B_CNT 68
43#define PM1_SCI_EN 0x0001
44#define PM1_SLP_EN 0x2000
48#define AML_BYTE_PREFIX 0x0A
49#define AML_PACKAGE 0x12
56 for (
size_t i = 0; i < size; ++i)
57 sum += ((
const uint8_t *) p)[i];
74 if (!entry)
return NULL;
87 return (
void *) (entry->
base + (
paddr - page));
109 uintptr_t areas[][2] = {{ebda, ebda + 0x400}, {0xE0000, 0x100000}};
111 for (
int i = 0; i < 2; ++i) {
112 for (
uintptr_t p = areas[i][0]; p +
sizeof(
struct acpi_rsdp) <= areas[i][1]; p += 16) {
123#define ACPI_TABLES_MAX 32
138 printk(
"acpi: no RSDP\n");
143 if (rsdp->
rev >= 2 && !
checksum(rsdp2,
sizeof(*rsdp2)) && rsdp2->
xsdt &&
223 for (
const uint8_t *p = aml +
sizeof(*dsdt); p + 8 < end; ++p) {
234 q += ((*q >> 6) & 3) + 1;
270 printk(
"acpi: no FADT\n");
281 if (!dsdt || !pm1a_cnt || (typa =
acpi_s5(dsdt, &typb)) < 0) {
282 printk(
"acpi: no S5 sleep state\n");
297 if (pm1b_cnt && typb >= 0)
301 for (
volatile int i = 0; i < 10000000; ++i)
304 printk(
"acpi: S5 sleep state didn't power off\n");
static struct acpi_sdt_header * acpi_table(uintptr_t paddr)
Maps a table, as long as its header says it is.
static void pm1_write(uint32_t port, uint16_t val)
Writes a PM1 control register.
static uint16_t pm1_read(uint32_t port)
Reads a PM1 control register.
static void * acpi_map(uintptr_t paddr, size_t size)
Maps a range of physical memory, read-only, in the tables' window.
static struct acpi_sdt_header * tables[ACPI_TABLES_MAX]
static int aml_int(const uint8_t **p, const uint8_t *end)
Reads an integer element of an AML package: BytePrefix n, or ZeroOp or OneOp.
static void acpi_tables(void)
Maps every table that the XSDT (or the RSDT) lists, and records them in tables.
static uintptr_t window_next
static int checksum(const void *p, size_t size)
Returns the 8-bit sum of size bytes, which is 0 for a valid table.
static int acpi_s5(struct acpi_sdt_header *dsdt, int *typb)
Finds S5's sleep types in the DSDT: Name (_S5, Package () {a, b, ...}).
static void io_out16(struct ioaddr *io, uintptr_t off, uint16_t val)
static uint16_t io_in16(struct ioaddr *io, uintptr_t off)
static void io_out8(struct ioaddr *io, uintptr_t off, uint8_t val)
Writes an 8-, 16- or 32-bit register.
#define MALLOC_DEFINE(type, _name, _desc)
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
void kfree(void *)
Frees an object that kmalloc() gave.
int memcmp(const void *a, const void *b, size_t n)
Compares n bytes.
void * x86_acpi_table(const char *signature)
Finds one of ACPI's tables, by its signature.
void x86_acpi_poweroff(void)
Powers the machine off, by entering ACPI's S5 sleep state.
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
unsigned long long int uint64_t
unsigned short int uint16_t
ACPI 2.0's RSDP (revision 2 or more), which also says where the XSDT is, with 64-bit addresses.
The Root System Description Pointer, which says where the RSDT is.
The RSDT: the other tables' 32-bit addresses.
struct acpi_sdt_header header
The XSDT: the other tables' 64-bit addresses.
struct acpi_sdt_header header
Where a device's registers are.
A mapping (map entry): a range of an address space, its permissions, and where its pages come from.
uint32_t flags
its permissions and flags (VM_*)
paddr_t paddr
physical memory to map all at once (vm_map()), or 0 for pages that come in on page faults
vaddr_t base
where the mapping starts in its address space
int vm_map(struct vm_space *vm_space, struct vm_entry *vm_entry)
Maps a map entry's whole range at once: its physical memory (paddr), or new pages of memory if it has...
struct vm_space kvm_space