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