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