diff --git a/src/address.rs b/src/address.rs index 0bb3eeb3..701d18ad 100644 --- a/src/address.rs +++ b/src/address.rs @@ -216,6 +216,32 @@ where } } } + + /// Ignores the GAS access size and does a 16-bit read. + pub fn read_u16(&self, byte_offset: u64) -> u16 { + match self.gas.address_space { + AddressSpace::SystemMemory => { + let addr = self.mapping.as_ref().unwrap().virtual_start.cast::(); + unsafe { addr.byte_offset(byte_offset as isize).read_unaligned() } + } + AddressSpace::SystemIo => self.handler.read_io_u16(self.gas.address as u16 + byte_offset as u16), + address_space => todo!("{address_space:?}"), + } + } + + /// Ignores the GAS access size and does a 16-bit write. + pub fn write_u16(&self, byte_offset: u64, value: u16) { + match self.gas.address_space { + AddressSpace::SystemMemory => { + let addr = self.mapping.as_ref().unwrap().virtual_start.cast::(); + unsafe { addr.byte_offset(byte_offset as isize).write_unaligned(value) } + } + AddressSpace::SystemIo => { + self.handler.write_io_u16(self.gas.address as u16 + byte_offset as u16, value) + } + address_space => todo!("{address_space:?}"), + } + } } /// Returns the access size that should be made for a given `GenericAddress`, in bits. diff --git a/src/registers.rs b/src/registers.rs index 58701805..ecf2f597 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -1,5 +1,6 @@ use crate::{AcpiError, Handler, address::MappedGas, sdt::fadt::Fadt}; use bit_field::BitField; +use bitflags::{Flags, bitflags}; pub struct FixedRegisters { pub pm1_event_registers: Pm1EventRegisterBlock, @@ -58,6 +59,19 @@ pub enum Pm1Event { Wake = 15, } +bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct Pm1EventFlags: u16 { + const TIMER = 1 << 0; + const GLOBAL_LOCK = 1 << 5; + const POWER_BUTTON = 1 << 8; + const SLEEP_BUTTON = 1 << 9; + const RTC = 1 << 10; + const PCIE_WAKE = 1 << 14; + const WAKE = 1 << 15; + } +} + impl Pm1EventRegisterBlock where H: Handler, @@ -95,6 +109,25 @@ where Ok(pm1a | pm1b) } + + pub fn pending_events(&self) -> Pm1EventFlags { + let bits = { + let mut bits = self.pm1a.read_u16(0); + if let Some(pm1b) = &self.pm1b { + bits |= pm1b.read_u16(0); + } + bits + }; + Pm1EventFlags::from_bits_retain(bits) + } + + pub fn clear_events(&self, events: Pm1EventFlags) { + let bits = events.known_bits(); + self.pm1a.write_u16(0, bits); + if let Some(pm1b) = &self.pm1b { + pm1b.write_u16(0, bits); + } + } } pub struct Pm1ControlRegisterBlock {