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