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)]
hpet_instance() -> &'static Hpet39 pub fn hpet_instance() -> &'static Hpet {
40 unsafe { HPET_INSTANCE.as_ref().unwrap() }
41 }
42
43 #[inline(always)]
is_hpet_enabled() -> bool44 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
new(mut hpet_info: HpetInfo) -> Result<Self, SystemError>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
enabled(&self) -> bool113 pub fn enabled(&self) -> bool {
114 self.enabled.load(Ordering::SeqCst)
115 }
116
117 /// 使能HPET
hpet_enable(&self) -> Result<(), SystemError>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
inner(&self) -> RwLockReadGuard<InnerHpet>172 fn inner(&self) -> RwLockReadGuard<InnerHpet> {
173 self.inner.read()
174 }
175
inner_mut(&self) -> RwLockWriteGuard<InnerHpet>176 fn inner_mut(&self) -> RwLockWriteGuard<InnerHpet> {
177 self.inner.write()
178 }
179
180 #[allow(dead_code)]
timer(&self, index: u8) -> Option<(RwLockReadGuard<InnerHpet>, &HpetTimerRegisters)>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
timer_mut( &self, index: u8, ) -> Option<(RwLockWriteGuard<InnerHpet>, &mut HpetTimerRegisters)>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
hpet_regs(&self) -> (RwLockReadGuard<InnerHpet>, &HpetRegisters)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
hpet_regs_mut(&self) -> (RwLockWriteGuard<InnerHpet>, &mut HpetRegisters)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
main_counter_value(&self) -> u64228 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
period(&self) -> u64236 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的中断
handle_irq(&self, timer_num: u32)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
hpet_init() -> Result<(), SystemError>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 {
handle( &self, _irq: IrqNumber, _static_data: Option<&dyn IrqHandlerData>, _dynamic_data: Option<Arc<dyn IrqHandlerData>>, ) -> Result<IrqReturn, SystemError>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