xref: /DragonOS/kernel/src/arch/x86_64/driver/hpet.rs (revision 0d6cf65aa124ee55bfee44cbb5196917ea6522fa)
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