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