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