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