use core::{ops::Deref, ptr::NonNull};
#[derive(Debug)]
pub struct PhysicalMapping<H, T>
where
H: AcpiHandler,
{
physical_start: usize,
virtual_start: NonNull<T>,
region_length: usize, mapped_length: usize, handler: H,
}
impl<H, T> PhysicalMapping<H, T>
where
H: AcpiHandler,
{
pub unsafe fn new(
physical_start: usize,
virtual_start: NonNull<T>,
region_length: usize,
mapped_length: usize,
handler: H,
) -> Self {
Self { physical_start, virtual_start, region_length, mapped_length, handler }
}
pub fn physical_start(&self) -> usize {
self.physical_start
}
pub fn virtual_start(&self) -> NonNull<T> {
self.virtual_start
}
pub fn region_length(&self) -> usize {
self.region_length
}
pub fn mapped_length(&self) -> usize {
self.mapped_length
}
pub fn handler(&self) -> &H {
&self.handler
}
}
unsafe impl<H: AcpiHandler + Send, T: Send> Send for PhysicalMapping<H, T> {}
impl<H, T> Deref for PhysicalMapping<H, T>
where
H: AcpiHandler,
{
type Target = T;
fn deref(&self) -> &T {
unsafe { self.virtual_start.as_ref() }
}
}
impl<H, T> Drop for PhysicalMapping<H, T>
where
H: AcpiHandler,
{
fn drop(&mut self) {
H::unmap_physical_region(self)
}
}
pub trait AcpiHandler: Clone {
unsafe fn map_physical_region<T>(&self, physical_address: usize, size: usize) -> PhysicalMapping<Self, T>;
fn unmap_physical_region<T>(region: &PhysicalMapping<Self, T>);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[allow(dead_code)]
fn test_send_sync() {
fn test_send_sync<T: Send>() {}
fn caller<H: AcpiHandler + Send, T: Send>() {
test_send_sync::<PhysicalMapping<H, T>>();
}
}
}