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 fn map(addr: NonNull<u8>, size: usize, direction: Direction) -> u64;
26 fn unmap(addr: NonNull<u8>, size: usize);
28 fn flush(addr: NonNull<u8>, size: usize);
30 fn invalidate(addr: NonNull<u8>, size: usize);
32
33 #[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 #[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}