1 use core::{ 2 ffi::c_void, 3 intrinsics::unlikely, 4 mem::size_of, 5 ptr::NonNull, 6 sync::atomic::{AtomicBool, Ordering}, 7 }; 8 9 use acpi::HpetInfo; 10 use system_error::SystemError; 11 12 use crate::{ 13 arch::CurrentIrqArch, 14 driver::{ 15 acpi::acpi_manager, 16 timers::hpet::{HpetRegisters, HpetTimerRegisters}, 17 }, 18 exception::{ 19 softirq::{softirq_vectors, SoftirqNumber}, 20 InterruptArch, 21 }, 22 kdebug, kerror, kinfo, 23 libs::{ 24 rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, 25 volatile::volwrite, 26 }, 27 mm::{ 28 mmio_buddy::{mmio_pool, MMIOSpaceGuard}, 29 PhysAddr, 30 }, 31 time::timer::{clock, timer_get_first_expire, update_timer_jiffies}, 32 }; 33 34 extern "C" { 35 fn c_hpet_register_irq() -> c_void; 36 } 37 38 static mut HPET_INSTANCE: Option<Hpet> = None; 39 40 #[inline(always)] 41 pub fn hpet_instance() -> &'static Hpet { 42 unsafe { HPET_INSTANCE.as_ref().unwrap() } 43 } 44 45 pub struct Hpet { 46 info: HpetInfo, 47 _mmio_guard: MMIOSpaceGuard, 48 inner: RwLock<InnerHpet>, 49 enabled: AtomicBool, 50 } 51 52 struct InnerHpet { 53 registers_ptr: NonNull<HpetRegisters>, 54 timer_registers_ptr: NonNull<HpetTimerRegisters>, 55 } 56 57 impl Hpet { 58 /// HPET0 中断间隔为 10ms 59 pub const HPET0_INTERVAL_USEC: u64 = 10000; 60 61 fn new(mut hpet_info: HpetInfo) -> Result<Self, SystemError> { 62 let paddr = PhysAddr::new(hpet_info.base_address); 63 let map_size = size_of::<HpetRegisters>(); 64 let mmio = mmio_pool().create_mmio(map_size)?; 65 unsafe { mmio.map_phys(paddr, map_size)? }; 66 let hpet = unsafe { 67 (mmio.vaddr().data() as *const HpetRegisters) 68 .as_ref() 69 .unwrap() 70 }; 71 let tm_num = hpet.timers_num(); 72 kinfo!("HPET has {} timers", tm_num); 73 hpet_info.hpet_number = tm_num as u8; 74 75 drop(mmio); 76 if tm_num == 0 { 77 return Err(SystemError::ENODEV); 78 } 79 80 let bytes_to_map = size_of::<HpetRegisters>() 81 + hpet_info.hpet_number as usize * size_of::<HpetTimerRegisters>(); 82 let mmio = mmio_pool().create_mmio(bytes_to_map)?; 83 84 unsafe { mmio.map_phys(paddr, bytes_to_map)? }; 85 let ptr = NonNull::new(mmio.vaddr().data() as *mut HpetRegisters).unwrap(); 86 let timer_ptr = NonNull::new( 87 (mmio.vaddr().data() + size_of::<HpetRegisters>()) as *mut HpetTimerRegisters, 88 ) 89 .unwrap(); 90 91 let hpet = Hpet { 92 info: hpet_info, 93 _mmio_guard: mmio, 94 inner: RwLock::new(InnerHpet { 95 registers_ptr: ptr, 96 timer_registers_ptr: timer_ptr, 97 }), 98 enabled: AtomicBool::new(false), 99 }; 100 101 return Ok(hpet); 102 } 103 104 pub fn enabled(&self) -> bool { 105 self.enabled.load(Ordering::SeqCst) 106 } 107 108 /// 使能HPET 109 pub fn hpet_enable(&self) -> Result<(), SystemError> { 110 // !!!这里是临时糊代码的,需要在apic重构的时候修改!!! 111 let (inner_guard, regs) = unsafe { self.hpet_regs_mut() }; 112 let freq = regs.frequency(); 113 kdebug!("HPET frequency: {} Hz", freq); 114 let ticks = Self::HPET0_INTERVAL_USEC * freq / 1000000; 115 if ticks <= 0 || ticks > freq * 8 { 116 kerror!("HPET enable: ticks '{ticks}' is invalid"); 117 return Err(SystemError::EINVAL); 118 } 119 if unlikely(regs.timers_num() == 0) { 120 return Err(SystemError::ENODEV); 121 } 122 123 unsafe { regs.write_main_counter_value(0) }; 124 125 drop(inner_guard); 126 127 let (inner_guard, timer_reg) = unsafe { self.timer_mut(0).ok_or(SystemError::ENODEV) }?; 128 129 let timer_reg = NonNull::new(timer_reg as *mut HpetTimerRegisters).unwrap(); 130 131 unsafe { 132 // 设置定时器0为周期定时,边沿触发,默认投递到IO APIC的2号引脚(看conf寄存器的高32bit,哪一位被置1,则可以投递到哪一个I/O apic引脚) 133 volwrite!(timer_reg, config, 0x004c); 134 volwrite!(timer_reg, comparator_value, ticks); 135 } 136 drop(inner_guard); 137 138 // todo!("register irq in C"); 139 unsafe { c_hpet_register_irq() }; 140 self.enabled.store(true, Ordering::SeqCst); 141 142 let (inner_guard, regs) = unsafe { self.hpet_regs_mut() }; 143 144 // 置位旧设备中断路由兼容标志位、定时器组使能标志位 145 unsafe { regs.write_general_config(3) }; 146 147 drop(inner_guard); 148 149 kinfo!("HPET enabled"); 150 return Ok(()); 151 } 152 153 fn inner(&self) -> RwLockReadGuard<InnerHpet> { 154 self.inner.read() 155 } 156 157 fn inner_mut(&self) -> RwLockWriteGuard<InnerHpet> { 158 self.inner.write() 159 } 160 161 #[allow(dead_code)] 162 fn timer(&self, index: u8) -> Option<(RwLockReadGuard<InnerHpet>, &HpetTimerRegisters)> { 163 let inner = self.inner(); 164 if index >= self.info.hpet_number { 165 return None; 166 } 167 let timer_regs = unsafe { 168 inner 169 .timer_registers_ptr 170 .as_ptr() 171 .add(index as usize) 172 .as_ref() 173 .unwrap() 174 }; 175 return Some((inner, timer_regs)); 176 } 177 178 unsafe fn timer_mut( 179 &self, 180 index: u8, 181 ) -> Option<(RwLockWriteGuard<InnerHpet>, &mut HpetTimerRegisters)> { 182 let inner = self.inner_mut(); 183 if index >= self.info.hpet_number { 184 return None; 185 } 186 let timer_regs = unsafe { 187 inner 188 .timer_registers_ptr 189 .as_ptr() 190 .add(index as usize) 191 .as_mut() 192 .unwrap() 193 }; 194 return Some((inner, timer_regs)); 195 } 196 197 unsafe fn hpet_regs(&self) -> (RwLockReadGuard<InnerHpet>, &HpetRegisters) { 198 let inner = self.inner(); 199 let regs = unsafe { inner.registers_ptr.as_ref() }; 200 return (inner, regs); 201 } 202 203 unsafe fn hpet_regs_mut(&self) -> (RwLockWriteGuard<InnerHpet>, &mut HpetRegisters) { 204 let mut inner = self.inner_mut(); 205 let regs = unsafe { inner.registers_ptr.as_mut() }; 206 return (inner, regs); 207 } 208 209 pub fn main_counter_value(&self) -> u64 { 210 let (inner_guard, regs) = unsafe { self.hpet_regs() }; 211 let value = regs.main_counter_value(); 212 213 drop(inner_guard); 214 return value; 215 } 216 217 pub fn period(&self) -> u64 { 218 let (inner_guard, regs) = unsafe { self.hpet_regs() }; 219 let period = regs.counter_clock_period(); 220 kdebug!("HPET period: {}", period); 221 222 drop(inner_guard); 223 return period; 224 } 225 226 /// 处理HPET的中断 227 pub(super) fn handle_irq(&self, timer_num: u32) { 228 if timer_num == 0 { 229 assert!(CurrentIrqArch::is_irq_enabled() == false); 230 update_timer_jiffies(Self::HPET0_INTERVAL_USEC, Self::HPET0_INTERVAL_USEC as i64); 231 232 if let Ok(first_expire) = timer_get_first_expire() { 233 if first_expire <= clock() { 234 softirq_vectors().raise_softirq(SoftirqNumber::TIMER); 235 } 236 } 237 } 238 } 239 } 240 241 pub fn hpet_init() -> Result<(), SystemError> { 242 let hpet_info = HpetInfo::new(acpi_manager().tables().unwrap()).map_err(|e| { 243 kerror!("Failed to get HPET info: {:?}", e); 244 SystemError::ENODEV 245 })?; 246 247 let hpet_instance = Hpet::new(hpet_info)?; 248 unsafe { 249 HPET_INSTANCE = Some(hpet_instance); 250 } 251 252 return Ok(()); 253 } 254