hpet.rs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. use crate::{sdt::SdtHeader, Acpi, AcpiError, GenericAddress, PhysicalMapping};
  2. use bit_field::BitField;
  3. #[derive(Debug)]
  4. pub enum PageProtection {
  5. None,
  6. /// Access to the adjacent 3KB to the base address will not generate a fault.
  7. Protected4K,
  8. /// Access to the adjacent 64KB to the base address will not generate a fault.
  9. Protected64K,
  10. Other,
  11. }
  12. /// Information about the High Precision Event Timer
  13. #[derive(Debug)]
  14. pub struct HpetInfo {
  15. pub event_timer_block_id: u32,
  16. pub base_address: usize,
  17. pub hpet_number: u8,
  18. /// The minimum number of clock ticks that can be set without losing interrupts (for timers in Periodic Mode)
  19. pub clock_tick_unit: u16,
  20. pub page_protection: PageProtection,
  21. }
  22. #[repr(C, packed)]
  23. pub(crate) struct HpetTable {
  24. header: SdtHeader,
  25. event_timer_block_id: u32,
  26. base_address: GenericAddress,
  27. hpet_number: u8,
  28. clock_tick_unit: u16,
  29. page_protection_oem: u8,
  30. }
  31. pub(crate) fn parse_hpet(acpi: &mut Acpi, mapping: &PhysicalMapping<HpetTable>) -> Result<(), AcpiError> {
  32. (*mapping).header.validate(crate::sdt::Signature::HPET)?;
  33. let hpet = &*mapping;
  34. // Make sure the HPET's in system memory
  35. assert_eq!(hpet.base_address.address_space, 0);
  36. acpi.hpet = Some(HpetInfo {
  37. event_timer_block_id: hpet.event_timer_block_id,
  38. base_address: hpet.base_address.address as usize,
  39. hpet_number: hpet.hpet_number,
  40. clock_tick_unit: hpet.clock_tick_unit,
  41. page_protection: match hpet.page_protection_oem.get_bits(0..5) {
  42. 0 => PageProtection::None,
  43. 1 => PageProtection::Protected4K,
  44. 2 => PageProtection::Protected64K,
  45. 3..=15 => PageProtection::Other,
  46. _ => unreachable!(),
  47. },
  48. });
  49. Ok(())
  50. }