xref: /DragonOS/kernel/src/arch/x86_64/driver/hpet.rs (revision 111c5407ccb7774695c8047cf895481d3387fda9)
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 
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(inner_guard);
122 
123         let (inner_guard, timer_reg) = unsafe { self.timer_mut(0).ok_or(SystemError::ENODEV) }?;
124 
125         let timer_reg = NonNull::new(timer_reg as *mut HpetTimerRegisters).unwrap();
126 
127         unsafe {
128             // 设置定时器0为周期定时,边沿触发,默认投递到IO APIC的2号引脚(看conf寄存器的高32bit,哪一位被置1,则可以投递到哪一个I/O apic引脚)
129             volwrite!(timer_reg, config, 0x004c);
130             volwrite!(timer_reg, comparator_value, ticks);
131         }
132         drop(inner_guard);
133 
134         // todo!("register irq in C");
135         unsafe { c_hpet_register_irq() };
136         self.enabled.store(true, Ordering::SeqCst);
137 
138         let (inner_guard, regs) = unsafe { self.hpet_regs_mut() };
139 
140         // 置位旧设备中断路由兼容标志位、定时器组使能标志位
141         unsafe { regs.write_general_config(3) };
142 
143         drop(inner_guard);
144 
145         kinfo!("HPET enabled");
146         return Ok(());
147     }
148 
149     fn inner(&self) -> RwLockReadGuard<InnerHpet> {
150         self.inner.read()
151     }
152 
153     fn inner_mut(&self) -> RwLockWriteGuard<InnerHpet> {
154         self.inner.write()
155     }
156 
157     #[allow(dead_code)]
158     fn timer(&self, index: u8) -> Option<(RwLockReadGuard<InnerHpet>, &HpetTimerRegisters)> {
159         let inner = self.inner();
160         if index >= self.info.hpet_number {
161             return None;
162         }
163         let timer_regs = unsafe {
164             inner
165                 .timer_registers_ptr
166                 .as_ptr()
167                 .add(index as usize)
168                 .as_ref()
169                 .unwrap()
170         };
171         return Some((inner, timer_regs));
172     }
173 
174     unsafe fn timer_mut(
175         &self,
176         index: u8,
177     ) -> Option<(RwLockWriteGuard<InnerHpet>, &mut HpetTimerRegisters)> {
178         let inner = self.inner_mut();
179         if index >= self.info.hpet_number {
180             return None;
181         }
182         let timer_regs = unsafe {
183             inner
184                 .timer_registers_ptr
185                 .as_ptr()
186                 .add(index as usize)
187                 .as_mut()
188                 .unwrap()
189         };
190         return Some((inner, timer_regs));
191     }
192 
193     unsafe fn hpet_regs(&self) -> (RwLockReadGuard<InnerHpet>, &HpetRegisters) {
194         let inner = self.inner();
195         let regs = unsafe { inner.registers_ptr.as_ref() };
196         return (inner, regs);
197     }
198 
199     unsafe fn hpet_regs_mut(&self) -> (RwLockWriteGuard<InnerHpet>, &mut HpetRegisters) {
200         let mut inner = self.inner_mut();
201         let regs = unsafe { inner.registers_ptr.as_mut() };
202         return (inner, regs);
203     }
204 
205     pub fn main_counter_value(&self) -> u64 {
206         let (inner_guard, regs) = unsafe { self.hpet_regs() };
207         let value = regs.main_counter_value();
208 
209         drop(inner_guard);
210         return value;
211     }
212 
213     pub fn period(&self) -> u64 {
214         let (inner_guard, regs) = unsafe { self.hpet_regs() };
215         let period = regs.counter_clock_period();
216         kdebug!("HPET period: {}", period);
217 
218         drop(inner_guard);
219         return period;
220     }
221 
222     /// 处理HPET的中断
223     pub(super) fn handle_irq(&self, timer_num: u32) {
224         if timer_num == 0 {
225             update_timer_jiffies(Self::HPET0_INTERVAL_USEC);
226 
227             if let Ok(first_expire) = timer_get_first_expire() {
228                 if first_expire <= clock() {
229                     softirq_vectors().raise_softirq(SoftirqNumber::TIMER);
230                 }
231             }
232         }
233     }
234 }
235 
236 pub fn hpet_init() -> Result<(), SystemError> {
237     let hpet_info = HpetInfo::new(acpi_manager().tables().unwrap()).map_err(|e| {
238         kerror!("Failed to get HPET info: {:?}", e);
239         SystemError::ENODEV
240     })?;
241 
242     let hpet_instance = Hpet::new(hpet_info)?;
243     unsafe {
244         HPET_INSTANCE = Some(hpet_instance);
245     }
246 
247     return Ok(());
248 }
249