xref: /DragonOS/kernel/src/driver/acpi/mod.rs (revision a03c4f9dee5705207325c56629c0ccd219168f10)
17ae679ddSLoGin use core::{fmt::Debug, ptr::NonNull};
27ae679ddSLoGin 
37ae679ddSLoGin use acpi::AcpiHandler;
47ae679ddSLoGin 
57ae679ddSLoGin use crate::{
67ae679ddSLoGin     kinfo,
77ae679ddSLoGin     libs::{
87ae679ddSLoGin         align::{page_align_down, page_align_up},
97ae679ddSLoGin         once::Once,
107ae679ddSLoGin     },
117ae679ddSLoGin     mm::{
127ae679ddSLoGin         mmio_buddy::{mmio_pool, MMIOSpaceGuard},
137ae679ddSLoGin         PhysAddr, VirtAddr,
147ae679ddSLoGin     },
157ae679ddSLoGin };
167ae679ddSLoGin 
17*a03c4f9dSLoGin pub mod bus;
187ae679ddSLoGin mod c_adapter;
1906d5e247SLoGin pub mod glue;
207ae679ddSLoGin pub mod old;
217ae679ddSLoGin 
227ae679ddSLoGin extern crate acpi;
237ae679ddSLoGin 
247ae679ddSLoGin static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
257ae679ddSLoGin 
26*a03c4f9dSLoGin #[inline(always)]
27*a03c4f9dSLoGin pub fn acpi_manager() -> &'static AcpiManager {
28*a03c4f9dSLoGin     &AcpiManager
29*a03c4f9dSLoGin }
30*a03c4f9dSLoGin 
317ae679ddSLoGin #[derive(Debug)]
327ae679ddSLoGin pub struct AcpiManager;
337ae679ddSLoGin 
347ae679ddSLoGin impl AcpiManager {
357ae679ddSLoGin     pub fn init(rsdp_paddr: PhysAddr) {
367ae679ddSLoGin         static INIT: Once = Once::new();
377ae679ddSLoGin         INIT.call_once(|| {
387ae679ddSLoGin             kinfo!("Initializing Acpi Manager...");
397ae679ddSLoGin             let acpi_table: acpi::AcpiTables<AcpiHandlerImpl> =
407ae679ddSLoGin                 unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }
417ae679ddSLoGin                     .unwrap_or_else(|e| {
427ae679ddSLoGin                         panic!("acpi_init(): failed to parse acpi tables, error: {:?}", e)
437ae679ddSLoGin                     });
447ae679ddSLoGin 
457ae679ddSLoGin             unsafe {
467ae679ddSLoGin                 __ACPI_TABLE = Some(acpi_table);
477ae679ddSLoGin             }
487ae679ddSLoGin             kinfo!("Acpi Manager initialized.");
497ae679ddSLoGin         });
507ae679ddSLoGin     }
517ae679ddSLoGin 
527ae679ddSLoGin     #[allow(dead_code)]
537ae679ddSLoGin     pub fn tables() -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
547ae679ddSLoGin         unsafe { __ACPI_TABLE.as_ref() }
557ae679ddSLoGin     }
567ae679ddSLoGin }
577ae679ddSLoGin 
587ae679ddSLoGin #[derive(Debug, Clone, Copy)]
597ae679ddSLoGin pub struct AcpiHandlerImpl;
607ae679ddSLoGin 
617ae679ddSLoGin impl AcpiHandler for AcpiHandlerImpl {
627ae679ddSLoGin     unsafe fn map_physical_region<T>(
637ae679ddSLoGin         &self,
647ae679ddSLoGin         physical_address: usize,
657ae679ddSLoGin         size: usize,
667ae679ddSLoGin     ) -> acpi::PhysicalMapping<Self, T> {
677ae679ddSLoGin         let offset = physical_address - page_align_down(physical_address);
687ae679ddSLoGin         let size_fix = page_align_up(size + offset);
697ae679ddSLoGin 
707ae679ddSLoGin         let mmio_guard = mmio_pool()
717ae679ddSLoGin             .create_mmio(size_fix)
727ae679ddSLoGin             .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio");
737ae679ddSLoGin 
747ae679ddSLoGin         mmio_guard
757ae679ddSLoGin             .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix)
767ae679ddSLoGin             .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys");
777ae679ddSLoGin         let virtual_start = mmio_guard.vaddr().data() + offset;
787ae679ddSLoGin 
797ae679ddSLoGin         let virtual_start = NonNull::new(virtual_start as *mut T).unwrap();
807ae679ddSLoGin 
817ae679ddSLoGin         let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new(
827ae679ddSLoGin             physical_address,
837ae679ddSLoGin             virtual_start,
847ae679ddSLoGin             size,
857ae679ddSLoGin             mmio_guard.size(),
867ae679ddSLoGin             AcpiHandlerImpl,
877ae679ddSLoGin         );
887ae679ddSLoGin 
897ae679ddSLoGin         MMIOSpaceGuard::leak(mmio_guard);
907ae679ddSLoGin 
917ae679ddSLoGin         return result;
927ae679ddSLoGin     }
937ae679ddSLoGin 
947ae679ddSLoGin     fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) {
957ae679ddSLoGin         let mmio_guard = unsafe {
967ae679ddSLoGin             MMIOSpaceGuard::from_raw(
977ae679ddSLoGin                 VirtAddr::new(page_align_down(
987ae679ddSLoGin                     region.virtual_start().as_ref() as *const T as usize
997ae679ddSLoGin                 )),
1007ae679ddSLoGin                 region.mapped_length(),
1017ae679ddSLoGin                 true,
1027ae679ddSLoGin             )
1037ae679ddSLoGin         };
1047ae679ddSLoGin         drop(mmio_guard);
1057ae679ddSLoGin     }
1067ae679ddSLoGin }
107