blob: 6360486c4aa38f6c9dd851c1338351aaeb4f8b8a [file] [log] [blame] [edit]
use crate::{
address::RawGenericAddress,
sdt::{SdtHeader, Signature},
AcpiError,
AcpiHandler,
AcpiTable,
AcpiTables,
};
use bit_field::BitField;
#[derive(Debug)]
pub enum PageProtection {
None,
/// Access to the rest of the 4KiB, relative to the base address, will not generate a fault.
Protected4K,
/// Access to the rest of the 64KiB, relative to the base address, will not generate a fault.
Protected64K,
Other,
}
/// Information about the High Precision Event Timer (HPET)
#[derive(Debug)]
pub struct HpetInfo {
// TODO(3.0.0): unpack these fields directly, and get rid of methods
pub event_timer_block_id: u32,
pub base_address: usize,
pub hpet_number: u8,
/// The minimum number of clock ticks that can be set without losing interrupts (for timers in Periodic Mode)
pub clock_tick_unit: u16,
pub page_protection: PageProtection,
}
impl HpetInfo {
pub fn new<H>(tables: &AcpiTables<H>) -> Result<HpetInfo, AcpiError>
where
H: AcpiHandler,
{
let hpet = tables.find_table::<HpetTable>()?;
// Make sure the HPET is in system memory
assert_eq!(hpet.base_address.address_space, 0);
Ok(HpetInfo {
event_timer_block_id: hpet.event_timer_block_id,
base_address: hpet.base_address.address as usize,
hpet_number: hpet.hpet_number,
clock_tick_unit: hpet.clock_tick_unit,
page_protection: match hpet.page_protection_and_oem.get_bits(0..4) {
0 => PageProtection::None,
1 => PageProtection::Protected4K,
2 => PageProtection::Protected64K,
3..=15 => PageProtection::Other,
_ => unreachable!(),
},
})
}
pub fn hardware_rev(&self) -> u8 {
self.event_timer_block_id.get_bits(0..8) as u8
}
pub fn num_comparators(&self) -> u8 {
self.event_timer_block_id.get_bits(8..13) as u8 + 1
}
pub fn main_counter_is_64bits(&self) -> bool {
self.event_timer_block_id.get_bit(13)
}
pub fn legacy_irq_capable(&self) -> bool {
self.event_timer_block_id.get_bit(15)
}
pub fn pci_vendor_id(&self) -> u16 {
self.event_timer_block_id.get_bits(16..32) as u16
}
}
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct HpetTable {
/// The contents of the HPET's 'General Capabilities and ID register'
header: SdtHeader,
event_timer_block_id: u32,
base_address: RawGenericAddress,
hpet_number: u8,
clock_tick_unit: u16,
/// Bits `0..4` specify the page protection guarantee. Bits `4..8` are reserved for OEM attributes.
page_protection_and_oem: u8,
}
/// ### Safety: Implementation properly represents a valid HPET table.
unsafe impl AcpiTable for HpetTable {
const SIGNATURE: Signature = Signature::HPET;
fn header(&self) -> &SdtHeader {
&self.header
}
}