1 use core::{fmt::Debug, ptr::NonNull}; 2 3 use acpi::{AcpiHandler, PlatformInfo}; 4 use alloc::{string::ToString, sync::Arc}; 5 6 use crate::{ 7 driver::base::firmware::sys_firmware_kset, 8 kinfo, 9 libs::align::{page_align_down, page_align_up}, 10 mm::{ 11 mmio_buddy::{mmio_pool, MMIOSpaceGuard}, 12 PhysAddr, VirtAddr, 13 }, 14 syscall::SystemError, 15 }; 16 17 use super::base::kset::KSet; 18 19 extern crate acpi; 20 21 pub mod bus; 22 mod c_adapter; 23 pub mod glue; 24 pub mod pmtmr; 25 mod sysfs; 26 27 static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None; 28 /// `/sys/firmware/acpi`的kset 29 static mut ACPI_KSET_INSTANCE: Option<Arc<KSet>> = None; 30 31 #[inline(always)] 32 pub fn acpi_manager() -> &'static AcpiManager { 33 &AcpiManager 34 } 35 36 #[inline(always)] 37 pub fn acpi_kset() -> Arc<KSet> { 38 unsafe { ACPI_KSET_INSTANCE.clone().unwrap() } 39 } 40 41 #[derive(Debug)] 42 pub struct AcpiManager; 43 44 impl AcpiManager { 45 /// 初始化ACPI 46 /// 47 /// ## 参数 48 /// 49 /// - `rsdp_paddr`: RSDP的物理地址 50 /// 51 /// 52 /// ## 参考资料 53 /// 54 /// https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1390 55 pub fn init(&self, rsdp_paddr: PhysAddr) -> Result<(), SystemError> { 56 kinfo!("Initializing Acpi Manager..."); 57 58 // 初始化`/sys/firmware/acpi`的kset 59 let kset = KSet::new("acpi".to_string()); 60 kset.register(Some(sys_firmware_kset()))?; 61 unsafe { 62 ACPI_KSET_INSTANCE = Some(kset.clone()); 63 } 64 self.map_tables(rsdp_paddr)?; 65 self.bus_init()?; 66 kinfo!("Acpi Manager initialized."); 67 return Ok(()); 68 } 69 70 fn map_tables(&self, rsdp_paddr: PhysAddr) -> Result<(), SystemError> { 71 let acpi_table: acpi::AcpiTables<AcpiHandlerImpl> = 72 unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }.map_err( 73 |e| { 74 kerror!("acpi_init(): failed to parse acpi tables, error: {:?}", e); 75 SystemError::ENOMEM 76 }, 77 )?; 78 79 unsafe { 80 __ACPI_TABLE = Some(acpi_table); 81 } 82 83 return Ok(()); 84 } 85 86 #[allow(dead_code)] 87 pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> { 88 unsafe { __ACPI_TABLE.as_ref() } 89 } 90 91 /// 从acpi获取平台的信息 92 /// 93 /// 包括: 94 /// 95 /// - PowerProfile 96 /// - InterruptModel 97 /// - ProcessorInfo 98 /// - PmTimer 99 pub fn platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>> { 100 let r = self.tables()?.platform_info(); 101 if let Err(ref e) = r { 102 kerror!( 103 "AcpiManager::platform_info(): failed to get platform info, error: {:?}", 104 e 105 ); 106 return None; 107 } 108 109 return Some(r.unwrap()); 110 } 111 } 112 113 #[derive(Debug, Clone, Copy)] 114 pub struct AcpiHandlerImpl; 115 116 impl AcpiHandler for AcpiHandlerImpl { 117 unsafe fn map_physical_region<T>( 118 &self, 119 physical_address: usize, 120 size: usize, 121 ) -> acpi::PhysicalMapping<Self, T> { 122 let offset = physical_address - page_align_down(physical_address); 123 let size_fix = page_align_up(size + offset); 124 125 let mmio_guard = mmio_pool() 126 .create_mmio(size_fix) 127 .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio"); 128 129 mmio_guard 130 .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix) 131 .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys"); 132 let virtual_start = mmio_guard.vaddr().data() + offset; 133 134 let virtual_start = NonNull::new(virtual_start as *mut T).unwrap(); 135 136 let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new( 137 physical_address, 138 virtual_start, 139 size, 140 mmio_guard.size(), 141 AcpiHandlerImpl, 142 ); 143 144 MMIOSpaceGuard::leak(mmio_guard); 145 146 return result; 147 } 148 149 fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) { 150 let mmio_guard = unsafe { 151 MMIOSpaceGuard::from_raw( 152 VirtAddr::new(page_align_down( 153 region.virtual_start().as_ref() as *const T as usize 154 )), 155 region.mapped_length(), 156 true, 157 ) 158 }; 159 drop(mmio_guard); 160 } 161 } 162