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