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