52 lines
2.1 KiB
Zig
52 lines
2.1 KiB
Zig
//! Machine reboot: restart via the FADT reset register, with legacy fallbacks.
|
|
//!
|
|
//! Built on the register map `acpi` extracted from the FADT, driven through the
|
|
//! injected `Hal` (port I/O and MMIO). Soft-off (ACPI S5) and suspend (S3) are
|
|
//! **not** here: they need the AML sleep-state (`_Sx`) values, which the kernel no
|
|
//! longer parses — the ring-3 acpi service owns power management (it re-parses the
|
|
//! blobs and writes the PM1 control register itself). See docs/power.md. Reboot
|
|
//! stays in the kernel because it needs no AML — only the FADT reset register and
|
|
//! the well-known legacy fallbacks — so it survives as a last-resort restart.
|
|
|
|
const acpi = @import("acpi.zig");
|
|
const device_model = @import("device-model.zig");
|
|
const Hal = device_model.Hal;
|
|
|
|
/// Restart the machine. Tries the ACPI reset register first, then the two legacy
|
|
/// fallbacks. Returns only if every method failed (very unlikely).
|
|
pub fn reboot(hal: Hal) void {
|
|
const pi = acpi.power_information;
|
|
|
|
// 1. The FADT reset register, when the firmware advertises support.
|
|
if (pi.reset_supported and pi.reset.present()) {
|
|
writeRegister(hal, pi.reset, pi.reset_value);
|
|
delay();
|
|
}
|
|
// 2. The PCI reset-control register at port 0xCF9 (RST_CPU | SYSTEM_RST).
|
|
hal.pioWrite(1, 0xCF9, 0x0E);
|
|
hal.pioWrite(1, 0xCF9, 0x06);
|
|
delay();
|
|
// 3. Pulse the 8042 keyboard controller's reset line.
|
|
hal.pioWrite(1, 0x64, 0xFE);
|
|
delay();
|
|
}
|
|
|
|
fn writeRegister(hal: Hal, register: acpi.RegisterAccess, value: u32) void {
|
|
if (register.mmio) {
|
|
const p: *align(1) volatile u32 = @ptrFromInt(hal.mapMmio(register.address, 4, true));
|
|
p.* = value;
|
|
} else {
|
|
hal.pioWrite(register.width, @intCast(register.address), value);
|
|
}
|
|
}
|
|
|
|
/// A short busy-wait so a reset takes effect before we fall through to the next
|
|
/// method. The empty asm is an architecture-neutral barrier that keeps the loop
|
|
/// from being optimised away.
|
|
fn delay() void {
|
|
var i: usize = 0;
|
|
while (i < 50_000_000) : (i += 1) {
|
|
asm volatile ("" ::: .{ .memory = true });
|
|
}
|
|
}
|