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