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