2
0

hpet.rs 2.9 KB

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