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