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, sync::atomic::AtomicBool};
8
9mod dma;
10mod osal;
11
12#[cfg(feature = "alloc")]
13pub use dma::alloc::{pool::*, r#box::DBox, vec::DVec, DError};
14
15pub use dma::slice::{DSlice, DSliceMut};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18#[repr(C)]
19pub enum Direction {
20 ToDevice,
21 FromDevice,
22 Bidirectional,
23}
24
25pub trait Osal {
26 fn map(&self, addr: NonNull<u8>, size: usize, direction: Direction) -> u64;
28
29 fn unmap(&self, addr: NonNull<u8>, size: usize);
31
32 fn flush(&self, addr: NonNull<u8>, size: usize) {
34 osal::arch::flush(addr, size)
35 }
36
37 fn invalidate(&self, addr: NonNull<u8>, size: usize) {
39 osal::arch::invalidate(addr, size)
40 }
41
42 #[cfg(feature = "alloc")]
51 unsafe fn alloc(&self, dma_mask: u64, layout: core::alloc::Layout) -> *mut u8 {
52 let _ = dma_mask;
53 alloc::alloc::alloc(layout)
54 }
55
56 #[cfg(feature = "alloc")]
63 unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
64 alloc::alloc::dealloc(ptr, layout)
65 }
66}
67
68static mut OSAL: &'static dyn Osal = &osal::NopOsal;
69static INIT: AtomicBool = AtomicBool::new(false);
70
71pub fn init(osal: &'static dyn Osal) {
72 if INIT.load(core::sync::atomic::Ordering::Acquire) {
73 return;
74 }
75
76 unsafe {
77 OSAL = osal;
78 }
79 INIT.store(true, core::sync::atomic::Ordering::Release);
80}
81
82fn get_osal() -> &'static dyn Osal {
83 if !INIT.load(core::sync::atomic::Ordering::Acquire) {
84 panic!("dma-api not initialized");
85 }
86 unsafe { OSAL }
87}
88
89fn map(addr: NonNull<u8>, size: usize, direction: Direction) -> u64 {
90 get_osal().map(addr, size, direction)
91}
92
93fn unmap(addr: NonNull<u8>, size: usize) {
94 get_osal().unmap(addr, size)
95}
96
97fn invalidate(addr: NonNull<u8>, size: usize) {
98 get_osal().invalidate(addr, size)
99}
100
101fn flush(addr: NonNull<u8>, size: usize) {
102 get_osal().flush(addr, size)
103}
104
105#[cfg(feature = "alloc")]
106fn alloc(dma_mask: u64, layout: core::alloc::Layout) -> *mut u8 {
107 unsafe { get_osal().alloc(dma_mask, layout) }
108}
109
110#[cfg(feature = "alloc")]
111fn dealloc(ptr: *mut u8, layout: core::alloc::Layout) {
112 unsafe { get_osal().dealloc(ptr, layout) }
113}