diff --git a/src/io/dma.rs b/src/io/dma.rs index f2a9a12..d3ffbb9 100644 --- a/src/io/dma.rs +++ b/src/io/dma.rs @@ -24,7 +24,7 @@ impl Drop for PhysBox { } } -pub struct Dma { +pub struct Dma { phys: PhysBox, virt: *mut T } @@ -49,28 +49,48 @@ impl Dma { virt: virt }) } - +} +impl Dma { pub fn physical(&self) -> usize { self.phys.address } } -impl Deref for Dma { +impl Dma<[T]> { + /// Crates a new DMA buffer with a size only known at runtime. + /// ## Safety + /// * `T` must be properly aligned. + /// * `T` must be valid as zeroed (i.e. no NonNull pointers). + pub unsafe fn zeroed_unsized(count: usize) -> Result { + let phys = PhysBox::new(mem::size_of::() * count)?; + let virt_ptr = crate::physmap(phys.address, phys.size, crate::PHYSMAP_WRITE)? as *mut T; + ptr::write_bytes(virt_ptr, 0, count); + + let virt = core::slice::from_raw_parts_mut(virt_ptr, count); + + Ok(Dma { + phys, + virt, + }) + } +} + +impl Deref for Dma { type Target = T; fn deref(&self) -> &T { unsafe { &*self.virt } } } -impl DerefMut for Dma { +impl DerefMut for Dma { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.virt } } } -impl Drop for Dma { +impl Drop for Dma { fn drop(&mut self) { - unsafe { drop(ptr::read(self.virt)); } - let _ = unsafe { crate::physunmap(self.virt as usize) }; + unsafe { ptr::drop_in_place(self.virt) } + let _ = unsafe { crate::physunmap(self.virt as *mut u8 as usize) }; } }