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