hpet.rs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. use crate::{platform::address::RawGenericAddress, sdt::SdtHeader, AcpiError, AcpiHandler, AcpiTable, AcpiTables};
  2. use bit_field::BitField;
  3. #[derive(Debug)]
  4. pub enum PageProtection {
  5. None,
  6. /// Access to the rest of the 4KiB, relative to the base address, will not generate a fault.
  7. Protected4K,
  8. /// Access to the rest of the 64KiB, relative to the base address, will not generate a fault.
  9. Protected64K,
  10. Other,
  11. }
  12. /// Information about the High Precision Event Timer (HPET)
  13. #[derive(Debug)]
  14. pub struct HpetInfo {
  15. // TODO(3.0.0): unpack these fields directly, and get rid of methods
  16. pub event_timer_block_id: u32,
  17. pub base_address: usize,
  18. pub hpet_number: u8,
  19. /// The minimum number of clock ticks that can be set without losing interrupts (for timers in Periodic Mode)
  20. pub clock_tick_unit: u16,
  21. pub page_protection: PageProtection,
  22. }
  23. impl HpetInfo {
  24. pub fn new<H>(tables: &AcpiTables<H>) -> Result<HpetInfo, AcpiError>
  25. where
  26. H: AcpiHandler,
  27. {
  28. let hpet = unsafe {
  29. tables
  30. .get_sdt::<HpetTable>(crate::sdt::Signature::HPET)?
  31. .ok_or(AcpiError::TableMissing(crate::sdt::Signature::HPET))?
  32. };
  33. // Make sure the HPET's in system memory
  34. assert_eq!(hpet.base_address.address_space, 0);
  35. Ok(HpetInfo {
  36. event_timer_block_id: hpet.event_timer_block_id,
  37. base_address: hpet.base_address.address as usize,
  38. hpet_number: hpet.hpet_number,
  39. clock_tick_unit: hpet.clock_tick_unit,
  40. page_protection: match hpet.page_protection_and_oem.get_bits(0..4) {
  41. 0 => PageProtection::None,
  42. 1 => PageProtection::Protected4K,
  43. 2 => PageProtection::Protected64K,
  44. 3..=15 => PageProtection::Other,
  45. _ => unreachable!(),
  46. },
  47. })
  48. }
  49. pub fn hardware_rev(&self) -> u8 {
  50. self.event_timer_block_id.get_bits(0..8) as u8
  51. }
  52. pub fn num_comparators(&self) -> u8 {
  53. self.event_timer_block_id.get_bits(8..13) as u8
  54. }
  55. pub fn main_counter_is_64bits(&self) -> bool {
  56. self.event_timer_block_id.get_bit(13)
  57. }
  58. pub fn legacy_irq_capable(&self) -> bool {
  59. self.event_timer_block_id.get_bit(15)
  60. }
  61. pub fn pci_vendor_id(&self) -> u16 {
  62. self.event_timer_block_id.get_bits(16..32) as u16
  63. }
  64. }
  65. #[repr(C, packed)]
  66. pub struct HpetTable {
  67. /// The contents of the HPET's 'General Capabilities and ID register'
  68. header: SdtHeader,
  69. event_timer_block_id: u32,
  70. base_address: RawGenericAddress,
  71. hpet_number: u8,
  72. clock_tick_unit: u16,
  73. /// Bits `0..4` specify the page protection guarantee. Bits `4..8` are reserved for OEM attributes.
  74. page_protection_and_oem: u8,
  75. }
  76. impl AcpiTable for HpetTable {
  77. fn header(&self) -> &SdtHeader {
  78. &self.header
  79. }
  80. }