Added documentation for the dma, logger, and sgl modules
This commit is contained in:
@@ -8,6 +8,10 @@ use syscall::PAGE_SIZE;
|
||||
|
||||
use crate::MemoryType;
|
||||
|
||||
/// Defines the platform-specific memory type for DMA operations
|
||||
///
|
||||
/// - On x86 systems, DMA uses Write-back memory ([MemoryType::Writeback])
|
||||
/// - On aarch64 systems, DMA uses uncacheable memory ([MemoryType::Uncacheable])
|
||||
const DMA_MEMTY: MemoryType = {
|
||||
if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
|
||||
// x86 ensures cache coherence with DMA memory
|
||||
@@ -20,6 +24,19 @@ const DMA_MEMTY: MemoryType = {
|
||||
}
|
||||
};
|
||||
|
||||
/// Returns a file descriptor for zeroized physically-contiguous DMA memory.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A [Result] containing:
|
||||
/// - '[Ok]' - A [Fd] (file descriptor) to zeroized, physically continuous DMA usable memory
|
||||
/// - '[Err]' - The error returned by the provider of the /scheme/memory/zeroed scheme.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function can return an error in the following case:
|
||||
///
|
||||
/// - The request for the physical memory fails.
|
||||
pub(crate) fn phys_contiguous_fd() -> Result<Fd> {
|
||||
Fd::open(
|
||||
&format!("/scheme/memory/zeroed@{DMA_MEMTY}?phys_contiguous"),
|
||||
@@ -28,6 +45,26 @@ pub(crate) fn phys_contiguous_fd() -> Result<Fd> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Allocates a chunk of physical memory for DMA, and then maps it to virtual memory.
|
||||
///
|
||||
/// # Arguments
|
||||
/// 'length: [usize]' - The length of the memory region. Must be a multiple of [PAGE_SIZE]
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// This function returns a [Result] containing the following:
|
||||
/// - A '[Ok]([usize], *[mut] ())' containing a Tuple of the physical address of the region, and a raw pointer to that region in virtual memory.
|
||||
/// - An '[Err]' - containing the error for the operation.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function asserts if:
|
||||
/// - length is not a multiple of [PAGE_SIZE]
|
||||
///
|
||||
/// This function returns an error if:
|
||||
/// - A file descriptor to physically contiguous memory of type [DMA_MEMTY] could not be acquired
|
||||
/// - A virtual mapping for the physically contiguous memory could not be created
|
||||
/// - The virtual address returned by the memory manager was invalid.
|
||||
fn alloc_and_map(length: usize) -> Result<(usize, *mut ())> {
|
||||
assert_eq!(length % PAGE_SIZE, 0);
|
||||
unsafe {
|
||||
@@ -52,13 +89,29 @@ fn alloc_and_map(length: usize) -> Result<(usize, *mut ())> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A safe accessor for DMA memory.
|
||||
pub struct Dma<T: ?Sized> {
|
||||
/// The physical address of the memory
|
||||
phys: usize,
|
||||
/// The page-aligned length of the memory. Will be a multiple of [PAGE_SIZE]
|
||||
aligned_len: usize,
|
||||
/// The pointer to the Dma memory in the virtual address space.
|
||||
virt: *mut T,
|
||||
}
|
||||
|
||||
impl<T> Dma<T> {
|
||||
/// [Dma] constructor that allocates and initializes a region of DMA memory with the page-aligned
|
||||
/// size and initial value of some T
|
||||
///
|
||||
/// # Arguments
|
||||
/// 'value: T' - The initial value to write to the allocated region
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// This function returns a [Result] containing the following:
|
||||
///
|
||||
/// - A '[Ok] (`[Dma]<T>`)' containing the initialized region
|
||||
/// - An '[Err]' containing an error.
|
||||
pub fn new(value: T) -> Result<Self> {
|
||||
unsafe {
|
||||
let mut zeroed = Self::zeroed()?;
|
||||
@@ -66,6 +119,15 @@ impl<T> Dma<T> {
|
||||
Ok(zeroed.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// [Dma] constructor that allocates and zeroizes a memory region of the page-aligned size of T
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// This function returns a [Result] containing the following:
|
||||
///
|
||||
/// - A '[Ok] (`[Dma]<[MaybeUninit]<T>>`)' containing the allocated and zeroized memory
|
||||
/// - An '[Err]' containing an error.
|
||||
pub fn zeroed() -> Result<Dma<MaybeUninit<T>>> {
|
||||
let aligned_len = size_of::<T>().next_multiple_of(PAGE_SIZE);
|
||||
let (phys, virt) = alloc_and_map(aligned_len)?;
|
||||
@@ -78,6 +140,16 @@ impl<T> Dma<T> {
|
||||
}
|
||||
|
||||
impl<T> Dma<MaybeUninit<T>> {
|
||||
/// Assumes that possibly uninitialized DMA memory has been initialized, and returns a new
|
||||
/// instance of an object of type `[Dma]<T>`.
|
||||
///
|
||||
/// # Returns
|
||||
/// - `[Dma]<T>` - The original structure without the [MaybeUninit] wrapper around its contents.
|
||||
///
|
||||
/// # Notes
|
||||
/// - This is unsafe because it assumes that the memory stored within the `[Dma]<T>` is a valid
|
||||
/// instance of T. If it isn't (for example -- if it was initialized with [Dma::zeroed]),
|
||||
/// then the underlying memory may not contain the expected T structure.
|
||||
pub unsafe fn assume_init(self) -> Dma<T> {
|
||||
let Dma {
|
||||
phys,
|
||||
@@ -94,12 +166,23 @@ impl<T> Dma<MaybeUninit<T>> {
|
||||
}
|
||||
}
|
||||
impl<T: ?Sized> Dma<T> {
|
||||
/// Returns the physical address of the physical memory that this [Dma] structure references.
|
||||
///
|
||||
/// # Returns
|
||||
/// [usize] - The physical address of the memory.
|
||||
pub fn physical(&self) -> usize {
|
||||
self.phys
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Dma<[T]> {
|
||||
/// Returns a [Dma] object containing a zeroized slice of T with a given count.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - 'count: [usize]' - The number of elements of type T in the allocated slice.
|
||||
///
|
||||
///
|
||||
pub fn zeroed_slice(count: usize) -> Result<Dma<[MaybeUninit<T>]>> {
|
||||
let aligned_len = count
|
||||
.checked_mul(size_of::<T>())
|
||||
@@ -113,6 +196,11 @@ impl<T> Dma<[T]> {
|
||||
virt: ptr::slice_from_raw_parts_mut(virt.cast(), count),
|
||||
})
|
||||
}
|
||||
|
||||
/// Casts the slice from type T to type U.
|
||||
///
|
||||
/// # Returns
|
||||
/// '`[DMA]<U>`' - A cast handle to the Dma memory.
|
||||
pub unsafe fn cast_slice<U>(self) -> Dma<[U]> {
|
||||
let Dma {
|
||||
phys,
|
||||
@@ -129,6 +217,7 @@ impl<T> Dma<[T]> {
|
||||
}
|
||||
}
|
||||
impl<T> Dma<[MaybeUninit<T>]> {
|
||||
/// See [`Dma<MaybeUninit<T>>::assume_init`]
|
||||
pub unsafe fn assume_init(self) -> Dma<[T]> {
|
||||
let &Dma {
|
||||
phys,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use redox_log::{OutputBuilder, RedoxLogger};
|
||||
|
||||
/// Configures logging for a single driver.
|
||||
#[cfg_attr(not(target_os = "redox"), allow(unused_variables, unused_mut))]
|
||||
pub fn setup_logging(
|
||||
category: &str,
|
||||
|
||||
@@ -8,21 +8,38 @@ use syscall::{MAP_FIXED, PAGE_SIZE};
|
||||
|
||||
use crate::dma::phys_contiguous_fd;
|
||||
|
||||
/// A Scatter-Gather List data structure
|
||||
///
|
||||
/// See: https://en.wikipedia.org/wiki/Gather/scatter_(vector_addressing)
|
||||
#[derive(Debug)]
|
||||
pub struct Sgl {
|
||||
/// A raw pointer to the SGL in virtual memory
|
||||
virt: *mut u8,
|
||||
/// The length of the allocated memory. This value is NOT guaranteed to be a multiple of [PAGE_SIZE]
|
||||
unaligned_length: NonZeroUsize,
|
||||
/// The vector of chunks tracked by this [Sgl] object. This is the sparsely-populated vector in the SGL algorithm.
|
||||
chunks: Vec<Chunk>,
|
||||
}
|
||||
|
||||
/// A structure representing a chunk of memory in the sparsely-populated vector of the SGL
|
||||
#[derive(Debug)]
|
||||
pub struct Chunk {
|
||||
/// The offset of the chunk in the sparsely-populated vector.
|
||||
pub offset: usize,
|
||||
/// The physical address of the chunk
|
||||
pub phys: usize,
|
||||
/// A raw pointer to the chunk in virtual memory
|
||||
pub virt: *mut u8,
|
||||
/// The length of the chunk in bytes.
|
||||
pub length: usize,
|
||||
}
|
||||
|
||||
impl Sgl {
|
||||
/// Constructor for the scatter/gather list.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// 'unaligned_length: [usize]' - The length of the SGL, not aligned to the nearest page.
|
||||
pub fn new(unaligned_length: usize) -> Result<Self> {
|
||||
let unaligned_length = NonZeroUsize::new(unaligned_length).ok_or(Error::new(EINVAL))?;
|
||||
|
||||
@@ -77,12 +94,16 @@ impl Sgl {
|
||||
Ok(this)
|
||||
}
|
||||
}
|
||||
/// Returns an immutable reference to the vector of chunks
|
||||
pub fn chunks(&self) -> &[Chunk] {
|
||||
&self.chunks
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to the vector of chunks in virtual memory
|
||||
pub fn as_ptr(&self) -> *mut u8 {
|
||||
self.virt
|
||||
}
|
||||
/// Returns the length of the scatter-gather list.
|
||||
pub fn len(&self) -> usize {
|
||||
self.unaligned_length.get()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user