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