dma_api/
common.rs

1use core::{alloc::Layout, num::NonZeroUsize, ptr::NonNull};
2
3use crate::{DeviceDma, Direction, DmaError, DmaHandle};
4
5pub struct DCommon<T> {
6    pub handle: DmaHandle,
7    pub osal: DeviceDma,
8    pub direction: Direction,
9    _phantom: core::marker::PhantomData<T>,
10}
11
12unsafe impl<T: Send> Send for DCommon<T> {}
13
14impl<T> DCommon<T> {
15    pub fn new(
16        os: &DeviceDma,
17        size: usize,
18        align: usize,
19        direction: Direction,
20    ) -> Result<Self, DmaError> {
21        let layout = Layout::from_size_align(size, align)?;
22        let handle = unsafe { os.alloc_coherent(layout) }.ok_or(DmaError::NoMemory)?;
23        let dma_mask = os.dma_mask();
24        if handle.dma_addr > dma_mask {
25            unsafe {
26                os.dealloc_coherent(handle);
27            }
28            return Err(DmaError::DmaMaskNotMatch {
29                addr: handle.dma_addr,
30                mask: dma_mask,
31            });
32        }
33
34        Ok(Self {
35            handle,
36            osal: os.clone(),
37            direction,
38            _phantom: core::marker::PhantomData,
39        })
40    }
41
42    pub fn as_mut_slice(&mut self) -> &mut [u8] {
43        unsafe {
44            core::slice::from_raw_parts_mut(self.handle.dma_virt().as_ptr(), self.handle.size())
45        }
46    }
47
48    pub fn prepare_read(&self, offset: usize, size: usize) {
49        self.osal
50            .prepare_read(&self.handle, offset, size, self.direction);
51    }
52
53    pub fn confirm_write(&self, offset: usize, size: usize) {
54        self.osal
55            .confirm_write(&self.handle, offset, size, self.direction);
56    }
57
58    pub fn get_ptr(&self, offset: usize) -> *mut u8 {
59        let ptr = unsafe { self.handle.dma_virt().add(offset) };
60        ptr.as_ptr()
61    }
62
63    pub fn confirm_write_all(&self) {
64        self.osal
65            .confirm_write(&self.handle, 0, self.handle.size(), self.direction);
66    }
67}
68
69impl<T> Drop for DCommon<T> {
70    fn drop(&mut self) {
71        if self.handle.size() > 0 {
72            unsafe {
73                self.osal.dealloc_coherent(self.handle);
74            }
75        }
76    }
77}
78
79pub struct SingleMapping {
80    pub handle: DmaHandle,
81    osal: DeviceDma,
82    pub direction: Direction,
83}
84
85impl SingleMapping {
86    pub(crate) fn new(
87        os: &DeviceDma,
88        addr: NonNull<u8>,
89        size: NonZeroUsize,
90        align: usize,
91        direction: Direction,
92    ) -> Result<Self, DmaError> {
93        let handle = unsafe { os._map_single(addr, size, align, direction)? };
94        let dma_mask = os.dma_mask();
95        if handle.dma_addr > dma_mask {
96            unsafe {
97                os.unmap_single(handle);
98            }
99            return Err(DmaError::DmaMaskNotMatch {
100                addr: handle.dma_addr,
101                mask: dma_mask,
102            });
103        }
104
105        Ok(Self {
106            handle,
107            osal: os.clone(),
108            direction,
109        })
110    }
111
112    pub fn len(&self) -> usize {
113        self.handle.size()
114    }
115
116    pub fn is_empty(&self) -> bool {
117        self.len() == 0
118    }
119
120    pub fn prepare_read_all(&self) {
121        self.osal
122            .prepare_read(&self.handle, 0, self.len(), self.direction);
123    }
124
125    pub fn confirm_write_all(&self) {
126        self.osal
127            .confirm_write(&self.handle, 0, self.len(), self.direction);
128    }
129}
130
131impl Drop for SingleMapping {
132    fn drop(&mut self) {
133        self.confirm_write_all();
134        self.prepare_read_all();
135        unsafe {
136            self.osal.unmap_single(self.handle);
137        }
138    }
139}