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