diff --git a/drivers/acpid/src/acpi.rs b/drivers/acpid/src/acpi.rs index e7b947597d..095cc1b25d 100644 --- a/drivers/acpid/src/acpi.rs +++ b/drivers/acpid/src/acpi.rs @@ -128,84 +128,6 @@ impl Drop for PhysmapGuard { let _ = libredox::call::munmap(self.virt as *mut (), self.size); } } - - /// Suspend-to-RAM (S3 sleep state) - /// See ACPI 6.1 spec for SLP_TYPa/SLP_TYPb encoding - pub fn suspend_to_ram(&self) { - log::info!("ACPI: attempting suspend-to-RAM (S3)"); - let fadt = match self.fadt() { - Some(f) => f, - None => { log::error!("ACPI S3: missing FADT"); return; } - }; - let pm1a = fadt.pm1a_control_block as u16; - if pm1a == 0 { - log::error!("ACPI S3: PM1a port is zero"); - return; - } - let aml_symbols = self.aml_symbols.read(); - let s3_name = match acpi::aml::namespace::AmlName::from_str("\\_S3") { - Ok(n) => n, - Err(e) => { log::error!("ACPI S3: \\_S3 name error: {:?}", e); return; } - }; - let s3 = match &aml_symbols.aml_context { - Some(ctx) => match ctx.namespace.lock().get(s3_name) { - Ok(s) => s, - Err(e) => { log::error!("ACPI S3: \\_S3 not found: {:?}", e); return; } - }, - None => { log::error!("ACPI S3: AML context missing"); return; } - }; - let pkg = match s3.deref() { - acpi::aml::object::Object::Package(p) => p, - _ => { log::error!("ACPI S3: \\_S3 not a package"); return; } - }; - let slp_typa = match pkg[0].deref() { - acpi::aml::object::Object::Integer(i) => *i as u16, - _ => { log::error!("ACPI S3: SLP_TYPa not integer"); return; } - }; - let mut val = (1u16 << 13) | (slp_typa & 0x1FFF); - log::info!("ACPI S3: writing PM1a=0x{:04X} val=0x{:04X}", pm1a, val); - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - { Pio::::new(pm1a).write(val); } - } - - - /// Query ACPI battery via \\_SB_.BAT0._BST - /// Returns (remaining_capacity_mAh, present_voltage_mV) if available - pub fn read_battery_status(&self) -> Option<(u32, u32)> { - let aml_symbols = self.aml_symbols.read(); - let ctx = aml_symbols.aml_context.as_ref()?; - let mut ns = ctx.namespace.lock(); - let bst_name = acpi::aml::namespace::AmlName::from_str("\\_SB_.BAT0._BST").ok()?; - let bst = ns.get(bst_name).ok()?; - match bst.deref() { - acpi::aml::object::Object::Package(p) if p.len() >= 4 => { - let cap = match p[1].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; - let volt = match p[2].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; - Some((cap, volt)) - } - _ => { log::warn!("ACPI: _BST not a valid battery package"); None } - } - } - - /// Query ACPI battery info via \\_SB_.BAT0._BIF - /// Returns (design_capacity_mAh, last_full_capacity_mAh, design_voltage_mV) if available - pub fn read_battery_info(&self) -> Option<(u32, u32, u32)> { - let aml_symbols = self.aml_symbols.read(); - let ctx = aml_symbols.aml_context.as_ref()?; - let mut ns = ctx.namespace.lock(); - let bif_name = acpi::aml::namespace::AmlName::from_str("\\_SB_.BAT0._BIF").ok()?; - let bif = ns.get(bif_name).ok()?; - match bif.deref() { - acpi::aml::object::Object::Package(p) if p.len() >= 13 => { - let design = match p[1].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; - let last = match p[2].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; - let volt = match p[4].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; - Some((design, last, volt)) - } - _ => { log::warn!("ACPI: _BIF not a valid battery package"); None } - } - } - } #[derive(Clone)] @@ -1385,6 +1307,85 @@ impl AcpiContext { Err(e) => Err(AmlEvalError::from(e)), } } + + /// Suspend-to-RAM (S3 sleep state) + /// See ACPI 6.1 spec for SLP_TYPa/SLP_TYPb encoding + pub fn suspend_to_ram(&self) { + log::info!("ACPI: attempting suspend-to-RAM (S3)"); + let fadt = match self.fadt.as_ref() { + Some(f) => f, + None => { log::error!("ACPI S3: missing FADT"); return; } + }; + let pm1a = fadt.pm1a_control_block as u16; + if pm1a == 0 { + log::error!("ACPI S3: PM1a port is zero"); + return; + } + let aml_symbols = self.aml_symbols.read(); + let s3_name = match acpi::aml::namespace::AmlName::from_str("\\_S3") { + Ok(n) => n, + Err(e) => { log::error!("ACPI S3: \\_S3 name error: {:?}", e); return; } + }; + let s3 = match &aml_symbols.aml_context { + Some(ctx) => match ctx.namespace.lock().get(s3_name) { + Ok(s) => s, + Err(e) => { log::error!("ACPI S3: \\_S3 not found: {:?}", e); return; } + }, + None => { log::error!("ACPI S3: AML context missing"); return; } + }; + use std::ops::Deref; + let pkg = match s3.deref() { + acpi::aml::object::Object::Package(p) => p, + _ => { log::error!("ACPI S3: \\_S3 not a package"); return; } + }; + let slp_typa = match pkg[0].deref() { + acpi::aml::object::Object::Integer(i) => *i as u16, + _ => { log::error!("ACPI S3: SLP_TYPa not integer"); return; } + }; + let val = (1u16 << 13) | (slp_typa & 0x1FFF); + log::info!("ACPI S3: writing PM1a=0x{:04X} val=0x{:04X}", pm1a, val); + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { Pio::::new(pm1a).write(val); } + } + + /// Query ACPI battery via \\_SB_.BAT0._BST + /// Returns (remaining_capacity_mAh, present_voltage_mV) if available + pub fn read_battery_status(&self) -> Option<(u32, u32)> { + let aml_symbols = self.aml_symbols.read(); + let ctx = aml_symbols.aml_context.as_ref()?; + let mut ns = ctx.namespace.lock(); + let bst_name = acpi::aml::namespace::AmlName::from_str("\\_SB_.BAT0._BST").ok()?; + let bst = ns.get(bst_name).ok()?; + use std::ops::Deref; + match bst.deref() { + acpi::aml::object::Object::Package(p) if p.len() >= 4 => { + let cap = match p[1].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; + let volt = match p[2].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; + Some((cap, volt)) + } + _ => { log::warn!("ACPI: _BST not a valid battery package"); None } + } + } + + /// Query ACPI battery info via \\_SB_.BAT0._BIF + /// Returns (design_capacity_mAh, last_full_capacity_mAh, design_voltage_mV) if available + pub fn read_battery_info(&self) -> Option<(u32, u32, u32)> { + let aml_symbols = self.aml_symbols.read(); + let ctx = aml_symbols.aml_context.as_ref()?; + let mut ns = ctx.namespace.lock(); + let bif_name = acpi::aml::namespace::AmlName::from_str("\\_SB_.BAT0._BIF").ok()?; + let bif = ns.get(bif_name).ok()?; + use std::ops::Deref; + match bif.deref() { + acpi::aml::object::Object::Package(p) if p.len() >= 13 => { + let design = match p[1].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; + let last = match p[2].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; + let volt = match p[4].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None }; + Some((design, last, volt)) + } + _ => { log::warn!("ACPI: _BIF not a valid battery package"); None } + } + } } fn power_object_path(name: &str, method: &str) -> String {