use core::ffi::c_void;
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use uefi_raw::table::boot::PAGE_SIZE;
use crate::proto::dma::iommu::Iommu;
pub mod iommu;
#[must_use]
#[derive(Debug)]
pub struct DmaBuffer<'a> {
ptr: *mut c_void,
pages: usize,
iommu: &'a Iommu,
}
impl<'a> DmaBuffer<'a> {
pub const unsafe fn from_raw(ptr: *mut c_void, pages: usize, iommu: &'a Iommu) -> Self {
Self { ptr, pages, iommu }
}
#[must_use]
pub const fn as_ptr(&self) -> *const c_void {
self.ptr.cast_const()
}
#[must_use]
pub const fn as_mut_ptr(&mut self) -> *mut c_void {
self.ptr
}
#[must_use]
pub const fn pages(&self) -> usize {
self.pages
}
#[must_use]
pub const fn size(&self) -> usize {
self.pages * PAGE_SIZE
}
}
impl<'a> Deref for DmaBuffer<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { core::slice::from_raw_parts(self.ptr.cast(), self.pages * PAGE_SIZE) }
}
}
impl<'a> DerefMut for DmaBuffer<'a> {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe { core::slice::from_raw_parts_mut(self.ptr.cast::<u8>(), self.pages * PAGE_SIZE) }
}
}
impl<'a> Drop for DmaBuffer<'a> {
fn drop(&mut self) {
if let Err(e) = self.iommu.free_buffer_raw(self.ptr, self.pages) {
log::error!("IOMMU free_buffer failed: {e:?}");
}
}
}
#[must_use]
#[derive(Debug)]
pub struct Mapping<'a, 'buf> {
ptr: *mut c_void,
iommu: &'a Iommu,
_buffer: PhantomData<&'buf mut DmaBuffer<'a>>,
}
impl<'a, 'buf> Mapping<'a, 'buf> {
pub const unsafe fn from_raw(
ptr: *mut c_void,
iommu: &'a Iommu,
_buffer: &'buf mut DmaBuffer<'a>,
) -> Self {
Self {
ptr,
iommu,
_buffer: PhantomData,
}
}
#[must_use]
pub const fn as_ptr(&self) -> *const c_void {
self.ptr.cast_const()
}
#[must_use]
pub const fn as_mut_ptr(&mut self) -> *mut c_void {
self.ptr
}
}
impl<'a, 'buf> Drop for Mapping<'a, 'buf> {
fn drop(&mut self) {
if let Err(e) = self.iommu.unmap_raw(self.as_mut_ptr()) {
log::error!("IOMMU unmap failed: {e:?}");
}
}
}