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