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