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}