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