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