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