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