dma_api/
lib.rs

1#![cfg_attr(not(test), no_std)]
2#![doc = include_str!("../README.md")]
3
4// #[cfg(feature = "alloc")]
5extern crate alloc;
6
7use core::{alloc::Layout, ptr::NonNull};
8
9mod dma;
10
11pub use dma::alloc::{r#box::DBox, vec::DVec};
12pub use dma::slice::{DSlice, DSliceMut};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum Direction {
16    ToDevice,
17    FromDevice,
18    Bidirectional,
19}
20
21pub trait Impl {
22    /// map virt address to physical address
23    fn map(addr: NonNull<u8>, size: usize, direction: Direction) -> u64;
24    /// unmap virt address
25    fn unmap(addr: NonNull<u8>, size: usize);
26    /// write cache back to memory
27    fn flush(addr: NonNull<u8>, size: usize);
28    /// invalidate cache
29    fn invalidate(addr: NonNull<u8>, size: usize);
30
31    /// alloc memory.
32    ///
33    /// # Safety
34    ///
35    /// layout must have non-zero size. Attempting to allocate for a zero-sized layout may result in undefined behavior.
36    #[allow(unused_variables)]
37    unsafe fn alloc(layout: Layout) -> *mut u8 {
38        #[cfg(feature = "alloc")]
39        unsafe {
40            alloc::alloc::alloc(layout)
41        }
42        #[cfg(not(feature = "alloc"))]
43        core::ptr::null_mut()
44    }
45
46    /// Deallocates the block of memory at the given `ptr` pointer with the given `layout`.
47    ///
48    /// # Safety
49    ///
50    /// The caller must ensure:
51    ///
52    /// * `ptr` is a block of memory currently allocated via this allocator and,
53    ///
54    /// * `layout` is the same layout that was used to allocate that block of
55    ///   memory.
56    ///
57    /// Otherwise undefined behavior can result.
58    #[allow(unused_variables)]
59    unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
60        #[cfg(feature = "alloc")]
61        unsafe {
62            alloc::alloc::dealloc(ptr, layout)
63        }
64    }
65}
66
67extern "Rust" {
68    fn __dma_api_map(addr: NonNull<u8>, size: usize, direction: Direction) -> u64;
69    fn __dma_api_unmap(addr: NonNull<u8>, size: usize);
70    fn __dma_api_flush(addr: NonNull<u8>, size: usize);
71    fn __dma_api_invalidate(addr: NonNull<u8>, size: usize);
72    fn __dma_api_alloc(layout: Layout) -> *mut u8;
73    fn __dma_api_dealloc(ptr: *mut u8, layout: Layout);
74}
75
76fn map(addr: NonNull<u8>, size: usize, direction: Direction) -> u64 {
77    unsafe { __dma_api_map(addr, size, direction) }
78}
79
80fn unmap(addr: NonNull<u8>, size: usize) {
81    unsafe { __dma_api_unmap(addr, size) }
82}
83
84fn flush(addr: NonNull<u8>, size: usize) {
85    unsafe { __dma_api_flush(addr, size) }
86}
87
88fn invalidate(addr: NonNull<u8>, size: usize) {
89    unsafe { __dma_api_invalidate(addr, size) }
90}
91
92unsafe fn alloc(layout: Layout) -> *mut u8 {
93    unsafe { __dma_api_alloc(layout) }
94}
95
96unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
97    unsafe { __dma_api_dealloc(ptr, layout) }
98}
99
100#[macro_export]
101macro_rules! set_impl {
102    ($t: ty) => {
103        #[no_mangle]
104        fn __dma_api_map(
105            addr: core::ptr::NonNull<u8>,
106            size: usize,
107            direction: $crate::Direction,
108        ) -> u64 {
109            <$t as $crate::Impl>::map(addr, size, direction)
110        }
111        #[no_mangle]
112        fn __dma_api_unmap(addr: core::ptr::NonNull<u8>, size: usize) {
113            <$t as $crate::Impl>::unmap(addr, size)
114        }
115        #[no_mangle]
116        fn __dma_api_flush(addr: core::ptr::NonNull<u8>, size: usize) {
117            <$t as $crate::Impl>::flush(addr, size)
118        }
119        #[no_mangle]
120        fn __dma_api_invalidate(addr: core::ptr::NonNull<u8>, size: usize) {
121            <$t as $crate::Impl>::invalidate(addr, size)
122        }
123        #[no_mangle]
124        fn __dma_api_alloc(layout: core::alloc::Layout) -> *mut u8 {
125            unsafe { <$t as $crate::Impl>::alloc(layout) }
126        }
127        #[no_mangle]
128        fn __dma_api_dealloc(ptr: *mut u8, layout: core::alloc::Layout) {
129            unsafe { <$t as $crate::Impl>::dealloc(ptr, layout) }
130        }
131    };
132}