// SPDX-License-Identifier: GPL-2.0-or-later #pragma once // ACPI, in two layers. // // kernel/arch/x86_64/acpi.c reads the static tables at boot, before anything // else can run: the MADT for the processors and the I/O APIC and its // interrupt source overrides, the FADT for the PM timer. // // kernel/acpi/ is everything that needs AML, which is the firmware's own code // and has to be interpreted: uACPI (ports/uacpi) runs it, and aml.c uses it // for PCI interrupt routing, the power button, power-off and reset. Every // function below that depends on it does nothing, and says so by returning // -1, on a machine whose AML could not be loaded. // The RSDP's physical address, or 0 if there is none. uint64 acpi_rsdp_phys(void); // The GSI an ISA IRQ is wired to, after the MADT's interrupt source // overrides, and its trigger mode (an IRQ_* from irq.h) in *mode. `dflt` is // the mode when the override says "conforms to the bus" or there is none: // edge/high for an ISA device, level/low for the SCI. int acpi_isa_gsi(int isa, int dflt, int *mode); // Load and initialize the namespace. After kinit, before pci_init. void acpi_aml_init(void); // The worker thread that runs AML on behalf of interrupts. After sinit. void acpi_thread_start(void); // Route every PCI device's INTx through _PRT. From pci_init, before binding. void acpi_pci_route(void); int acpi_poweroff(void); // S5; returns only on failure void acpi_poweroff_now(void); // S5 from a panic, no AML; returns only on failure int acpi_reboot(void); // the FADT reset register; ditto // Batteries and AC adapters, for /sys/class/power_supply. Units are the // battery's own: unit 0 is mW/mWh, 1 is mA/mAh; ACPI_UNKNOWN where the // firmware does not say. #define ACPI_UNKNOWN 0xFFFFFFFFu struct acpi_psu { int battery; // else an AC adapter int present; // battery: in the bay int online; // adapter: plugged in int unit; uint32 state; // _BST: 1 discharging, 2 charging, 4 critical uint32 rate, remaining, voltage; // _BST, voltage in mV uint32 design, full, design_voltage, cycles; int technology; // 0 primary, 1 rechargeable char model[32], serial[32], kind[16], oem[32]; }; int acpi_psu_count(void); int acpi_psu_get(int i, struct acpi_psu *out); // How an idle CPU sleeps: kernel/acpi/aml.c reads it from _CST, and the // scheduler's idle path in kernel/proc/proc.c acts on it. #define ACPI_IDLE_HLT 0 #define ACPI_IDLE_IO 1 // read a port #define ACPI_IDLE_MWAIT 2 // MWAIT with a hint struct acpi_idle { int kind; uint64 addr; // the port, or the MWAIT hint uint latency; // microseconds }; extern struct acpi_idle acpi_idle;