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