xref: /DragonOS/kernel/src/driver/acpi/mod.rs (revision 06d5e247267cb65b84a80f219853ccd0f384b16e)
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