xref: /DragonOS/kernel/src/driver/acpi/mod.rs (revision 06d5e247267cb65b84a80f219853ccd0f384b16e)
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 
177ae679ddSLoGin mod c_adapter;
18*06d5e247SLoGin pub mod glue;
197ae679ddSLoGin pub mod old;
207ae679ddSLoGin 
217ae679ddSLoGin extern crate acpi;
227ae679ddSLoGin 
237ae679ddSLoGin static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
247ae679ddSLoGin 
257ae679ddSLoGin #[derive(Debug)]
267ae679ddSLoGin pub struct AcpiManager;
277ae679ddSLoGin 
287ae679ddSLoGin impl AcpiManager {
297ae679ddSLoGin     pub fn init(rsdp_paddr: PhysAddr) {
307ae679ddSLoGin         static INIT: Once = Once::new();
317ae679ddSLoGin         INIT.call_once(|| {
327ae679ddSLoGin             kinfo!("Initializing Acpi Manager...");
337ae679ddSLoGin             let acpi_table: acpi::AcpiTables<AcpiHandlerImpl> =
347ae679ddSLoGin                 unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }
357ae679ddSLoGin                     .unwrap_or_else(|e| {
367ae679ddSLoGin                         panic!("acpi_init(): failed to parse acpi tables, error: {:?}", e)
377ae679ddSLoGin                     });
387ae679ddSLoGin 
397ae679ddSLoGin             unsafe {
407ae679ddSLoGin                 __ACPI_TABLE = Some(acpi_table);
417ae679ddSLoGin             }
427ae679ddSLoGin             kinfo!("Acpi Manager initialized.");
437ae679ddSLoGin         });
447ae679ddSLoGin     }
457ae679ddSLoGin 
467ae679ddSLoGin     #[allow(dead_code)]
477ae679ddSLoGin     pub fn tables() -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
487ae679ddSLoGin         unsafe { __ACPI_TABLE.as_ref() }
497ae679ddSLoGin     }
507ae679ddSLoGin }
517ae679ddSLoGin 
527ae679ddSLoGin #[derive(Debug, Clone, Copy)]
537ae679ddSLoGin pub struct AcpiHandlerImpl;
547ae679ddSLoGin 
557ae679ddSLoGin impl AcpiHandler for AcpiHandlerImpl {
567ae679ddSLoGin     unsafe fn map_physical_region<T>(
577ae679ddSLoGin         &self,
587ae679ddSLoGin         physical_address: usize,
597ae679ddSLoGin         size: usize,
607ae679ddSLoGin     ) -> acpi::PhysicalMapping<Self, T> {
617ae679ddSLoGin         let offset = physical_address - page_align_down(physical_address);
627ae679ddSLoGin         let size_fix = page_align_up(size + offset);
637ae679ddSLoGin 
647ae679ddSLoGin         let mmio_guard = mmio_pool()
657ae679ddSLoGin             .create_mmio(size_fix)
667ae679ddSLoGin             .expect("AcpiHandlerImpl::map_physical_region(): failed to create mmio");
677ae679ddSLoGin 
687ae679ddSLoGin         mmio_guard
697ae679ddSLoGin             .map_phys(PhysAddr::new(page_align_down(physical_address)), size_fix)
707ae679ddSLoGin             .expect("AcpiHandlerImpl::map_physical_region(): failed to map phys");
717ae679ddSLoGin         let virtual_start = mmio_guard.vaddr().data() + offset;
727ae679ddSLoGin 
737ae679ddSLoGin         let virtual_start = NonNull::new(virtual_start as *mut T).unwrap();
747ae679ddSLoGin 
757ae679ddSLoGin         let result: acpi::PhysicalMapping<AcpiHandlerImpl, T> = acpi::PhysicalMapping::new(
767ae679ddSLoGin             physical_address,
777ae679ddSLoGin             virtual_start,
787ae679ddSLoGin             size,
797ae679ddSLoGin             mmio_guard.size(),
807ae679ddSLoGin             AcpiHandlerImpl,
817ae679ddSLoGin         );
827ae679ddSLoGin 
837ae679ddSLoGin         MMIOSpaceGuard::leak(mmio_guard);
847ae679ddSLoGin 
857ae679ddSLoGin         return result;
867ae679ddSLoGin     }
877ae679ddSLoGin 
887ae679ddSLoGin     fn unmap_physical_region<T>(region: &acpi::PhysicalMapping<Self, T>) {
897ae679ddSLoGin         let mmio_guard = unsafe {
907ae679ddSLoGin             MMIOSpaceGuard::from_raw(
917ae679ddSLoGin                 VirtAddr::new(page_align_down(
927ae679ddSLoGin                     region.virtual_start().as_ref() as *const T as usize
937ae679ddSLoGin                 )),
947ae679ddSLoGin                 region.mapped_length(),
957ae679ddSLoGin                 true,
967ae679ddSLoGin             )
977ae679ddSLoGin         };
987ae679ddSLoGin         drop(mmio_guard);
997ae679ddSLoGin     }
1007ae679ddSLoGin }
101