浏览代码

Merge pull request #83 from toku-sa-n/implement_acpi_pm_timer

feat: add `PmTimer`
Isaac Woods 4 年之前
父节点
当前提交
9d4bba2e15
共有 2 个文件被更改,包括 51 次插入3 次删除
  1. 25 2
      acpi/src/fadt.rs
  2. 26 1
      acpi/src/platform/mod.rs

+ 25 - 2
acpi/src/fadt.rs

@@ -1,5 +1,5 @@
 use crate::{
-    platform::address::RawGenericAddress,
+    platform::address::{GenericAddress, RawGenericAddress},
     sdt::{ExtendedField, SdtHeader},
     AcpiError,
     AcpiTable,
@@ -70,7 +70,7 @@ pub struct Fadt {
     century: u8,
     iapc_boot_arch: u16,
     _reserved2: u8, // must be 0
-    flags: u32,
+    pub flags: u32,
     reset_reg: RawGenericAddress,
     reset_value: u8,
     arm_boot_arch: u16,
@@ -127,4 +127,27 @@ impl Fadt {
             other => PowerProfile::Reserved(other),
         }
     }
+
+    pub fn pm_timer_block(&self) -> Result<Option<GenericAddress>, AcpiError> {
+        let raw = unsafe {
+            self.x_pm_timer_block.access(self.header().revision).or_else(|| {
+                if self.pm_timer_block != 0 {
+                    Some(RawGenericAddress {
+                        address_space: 1,
+                        bit_width: 0,
+                        bit_offset: 0,
+                        access_size: self.pm_timer_length,
+                        address: self.pm_timer_block.into(),
+                    })
+                } else {
+                    None
+                }
+            })
+        };
+
+        match raw {
+            Some(raw) => Ok(Some(GenericAddress::from_raw(raw)?)),
+            None => Ok(None),
+        }
+    }
 }

+ 26 - 1
acpi/src/platform/mod.rs

@@ -1,6 +1,8 @@
 pub mod address;
 pub mod interrupt;
 
+use address::GenericAddress;
+use bit_field::BitField;
 pub use interrupt::{
     Apic,
     InterruptModel,
@@ -51,6 +53,27 @@ pub struct ProcessorInfo {
     pub application_processors: Vec<Processor>,
 }
 
+/// Information about the ACPI Power Management Timer (ACPI PM Timer).
+pub struct PmTimer {
+    /// A generic address to the register block of ACPI PM Timer.
+    pub base: GenericAddress,
+    /// This field is true if the hardware supports 32-bit timer, and false if the hardware
+    /// supports 24-bit timer.
+    pub supports_32bit: bool,
+}
+impl PmTimer {
+    /// Creates a new instance of `PmTimer`.
+    pub fn new(fadt: &Fadt) -> Result<Option<PmTimer>, AcpiError> {
+        let base = fadt.pm_timer_block()?;
+        let flags = fadt.flags;
+
+        match base {
+            Some(base) => Ok(Some(PmTimer { base, supports_32bit: flags.get_bit(8) })),
+            None => Ok(None),
+        }
+    }
+}
+
 /// `PlatformInfo` allows the collection of some basic information about the platform from some of the fixed-size
 /// tables in a nice way. It requires access to the `FADT` and `MADT`. It is the easiest way to get information
 /// about the processors and interrupt controllers on a platform.
@@ -60,6 +83,7 @@ pub struct PlatformInfo {
     /// On `x86_64` platforms that support the APIC, the processor topology must also be inferred from the
     /// interrupt model. That information is stored here, if present.
     pub processor_info: Option<ProcessorInfo>,
+    pub pm_timer: Option<PmTimer>,
     /*
      * TODO: we could provide a nice view of the hardware register blocks in the FADT here.
      */
@@ -82,7 +106,8 @@ impl PlatformInfo {
             Some(madt) => madt.parse_interrupt_model()?,
             None => (InterruptModel::Unknown, None),
         };
+        let pm_timer = PmTimer::new(&fadt)?;
 
-        Ok(PlatformInfo { power_profile, interrupt_model, processor_info })
+        Ok(PlatformInfo { power_profile, interrupt_model, processor_info, pm_timer })
     }
 }