hpet.rs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  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. event_timer_block_id: u32,
  16. base_address: usize,
  17. hpet_number: u8,
  18. /// The minimum number of clock ticks that can be set without losing interrupts (for timers in
  19. /// Periodic Mode)
  20. clock_tick_unit: u16,
  21. page_protection: PageProtection,
  22. }
  23. #[repr(C, packed)]
  24. pub(crate) struct HpetTable {
  25. header: SdtHeader,
  26. event_timer_block_id: u32,
  27. base_address: GenericAddress,
  28. hpet_number: u8,
  29. clock_tick_unit: u16,
  30. page_protection_oem: u8,
  31. }
  32. pub(crate) fn parse_hpet(acpi: &mut Acpi, mapping: &PhysicalMapping<HpetTable>) -> Result<(), AcpiError> {
  33. (*mapping).header.validate(crate::sdt::Signature::HPET)?;
  34. let hpet = &*mapping;
  35. // Make sure the HPET's in system memory
  36. assert_eq!(hpet.base_address.address_space, 0);
  37. acpi.hpet = Some(HpetInfo {
  38. event_timer_block_id: hpet.event_timer_block_id,
  39. base_address: hpet.base_address.address as usize,
  40. hpet_number: hpet.hpet_number,
  41. clock_tick_unit: hpet.clock_tick_unit,
  42. page_protection: match hpet.page_protection_oem.get_bits(0..5) {
  43. 0 => PageProtection::None,
  44. 1 => PageProtection::Protected4K,
  45. 2 => PageProtection::Protected64K,
  46. 3..=15 => PageProtection::Other,
  47. _ => unreachable!(),
  48. },
  49. });
  50. Ok(())
  51. }