1 use core::{fmt::Debug, ptr::NonNull}; 2 3 use acpi::AcpiHandler; 4 5 use crate::{ 6 kinfo, 7 libs::{ 8 align::{page_align_down, page_align_up}, 9 once::Once, 10 }, 11 mm::{ 12 mmio_buddy::{mmio_pool, MMIOSpaceGuard}, 13 PhysAddr, VirtAddr, 14 }, 15 }; 16 17 mod c_adapter; 18 pub mod old; 19 20 extern crate acpi; 21 22 static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None; 23 24 #[derive(Debug)] 25 pub struct AcpiManager; 26 27 impl AcpiManager { 28 pub fn init(rsdp_paddr: PhysAddr) { 29 static INIT: Once = Once::new(); 30 INIT.call_once(|| { 31 kinfo!("Initializing Acpi Manager..."); 32 let acpi_table: acpi::AcpiTables<AcpiHandlerImpl> = 33 unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) } 34 .unwrap_or_else(|e| { 35 panic!("acpi_init(): failed to parse acpi tables, error: {:?}", e) 36 }); 37 38 unsafe { 39 __ACPI_TABLE = Some(acpi_table); 40 } 41 kinfo!("Acpi Manager initialized."); 42 }); 43 } 44 45 #[allow(dead_code)] 46 pub fn tables() -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> { 47 unsafe { __ACPI_TABLE.as_ref() } 48 } 49 } 50 51 #[derive(Debug, Clone, Copy)] 52 pub struct AcpiHandlerImpl; 53 54 impl AcpiHandler for AcpiHandlerImpl { 55 unsafe fn map_physical_region<T>( 56 &self, 57 physical_address: usize, 58 size: usize, 59 ) -> acpi::PhysicalMapping<Self, T> { 60 let offset = physical_address - page_align_down(physical_address); 61 let size_fix = page_align_up(size + offset); 62 63 let mmio_guard = mmio_pool() 64 .create_mmio(size_fix) 65 .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio"); 66 67 mmio_guard 68 .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix) 69 .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys"); 70 let virtual_start = mmio_guard.vaddr().data() + offset; 71 72 let virtual_start = NonNull::new(virtual_start as *mut T).unwrap(); 73 74 let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new( 75 physical_address, 76 virtual_start, 77 size, 78 mmio_guard.size(), 79 AcpiHandlerImpl, 80 ); 81 82 MMIOSpaceGuard::leak(mmio_guard); 83 84 return result; 85 } 86 87 fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) { 88 let mmio_guard = unsafe { 89 MMIOSpaceGuard::from_raw( 90 VirtAddr::new(page_align_down( 91 region.virtual_start().as_ref() as *const T as usize 92 )), 93 region.mapped_length(), 94 true, 95 ) 96 }; 97 drop(mmio_guard); 98 } 99 } 100