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