dma_api/dma/
slice.rs

1use core::{
2    marker::PhantomData,
3    mem::{size_of, size_of_val},
4    ops::Index,
5    ptr::NonNull,
6};
7
8use crate::{flush, map, unmap, Direction};
9
10#[repr(transparent)]
11pub struct DSlice<'a, T> {
12    inner: DSliceCommon<'a, T>,
13}
14
15impl<'a, T> DSlice<'a, T> {
16    pub fn len(&self) -> usize {
17        self.inner.len()
18    }
19
20    pub fn bus_addr(&self) -> u64 {
21        self.inner.bus_addr
22    }
23
24    pub fn is_empty(&self) -> bool {
25        self.len() == 0
26    }
27
28    pub fn from(value: &'a [T], direction: Direction) -> Self {
29        Self {
30            inner: DSliceCommon::new(value, direction),
31        }
32    }
33
34    pub fn preper_read_all(&self) {
35        self.inner.preper_read_all();
36    }
37
38    pub fn confirm_write_all(&self) {
39        self.inner.confirm_write_all();
40    }
41}
42
43impl<T> Index<usize> for DSlice<'_, T> {
44    type Output = T;
45
46    fn index(&self, index: usize) -> &Self::Output {
47        self.inner.index(index)
48    }
49}
50
51impl<T> AsRef<[T]> for DSlice<'_, T> {
52    fn as_ref(&self) -> &[T] {
53        self.inner.as_ref()
54    }
55}
56
57#[repr(transparent)]
58pub struct DSliceMut<'a, T> {
59    inner: DSliceCommon<'a, T>,
60}
61
62impl<'a, T> DSliceMut<'a, T> {
63    pub fn from(value: &'a mut [T], direction: Direction) -> Self {
64        Self {
65            inner: DSliceCommon::new(value, direction),
66        }
67    }
68
69    pub fn bus_addr(&self) -> u64 {
70        self.inner.bus_addr
71    }
72
73    pub fn len(&self) -> usize {
74        self.inner.len()
75    }
76
77    pub fn is_empty(&self) -> bool {
78        self.len() == 0
79    }
80
81    pub fn set(&self, index: usize, value: T) {
82        assert!(index < self.len());
83
84        unsafe {
85            let ptr = self.inner.addr.add(index);
86
87            ptr.write_volatile(value);
88
89            self.inner
90                .direction
91                .confirm_write(ptr.cast(), size_of::<T>());
92        }
93    }
94
95    pub fn preper_read_all(&self) {
96        self.inner.preper_read_all();
97    }
98
99    pub fn confirm_write_all(&self) {
100        self.inner.confirm_write_all();
101    }
102}
103
104impl<T> Index<usize> for DSliceMut<'_, T> {
105    type Output = T;
106
107    fn index(&self, index: usize) -> &Self::Output {
108        self.inner.index(index)
109    }
110}
111
112impl<T> AsRef<[T]> for DSliceMut<'_, T> {
113    fn as_ref(&self) -> &[T] {
114        self.inner.as_ref()
115    }
116}
117
118struct DSliceCommon<'a, T> {
119    addr: NonNull<T>,
120    size: usize,
121    bus_addr: u64,
122    direction: Direction,
123    _marker: PhantomData<&'a T>,
124}
125
126impl<'a, T> DSliceCommon<'a, T> {
127    fn new(s: &'a [T], direction: Direction) -> Self {
128        let size = size_of_val(s);
129        let ptr = unsafe { NonNull::new_unchecked(s.as_ptr() as usize as *mut T) };
130        let bus_addr = map(ptr.cast(), size, direction);
131
132        flush(ptr.cast(), size);
133
134        Self {
135            addr: ptr,
136            size,
137            bus_addr,
138            direction,
139            _marker: PhantomData,
140        }
141    }
142
143    fn len(&self) -> usize {
144        self.size / size_of::<T>()
145    }
146
147    fn index(&self, index: usize) -> &T {
148        assert!(index < self.len());
149
150        let ptr = unsafe { self.addr.add(index) };
151
152        self.direction.preper_read(ptr.cast(), size_of::<T>());
153
154        unsafe { ptr.as_ref() }
155    }
156
157    fn preper_read_all(&self) {
158        self.direction
159            .preper_read(self.addr.cast(), self.size * size_of::<T>());
160    }
161
162    fn confirm_write_all(&self) {
163        self.direction
164            .confirm_write(self.addr.cast(), self.size * size_of::<T>());
165    }
166}
167
168impl<T> Drop for DSliceCommon<'_, T> {
169    fn drop(&mut self) {
170        unmap(self.addr.cast(), self.size);
171    }
172}
173
174impl<T> AsRef<[T]> for DSliceCommon<'_, T> {
175    fn as_ref(&self) -> &[T] {
176        self.preper_read_all();
177        unsafe { core::slice::from_raw_parts_mut(self.addr.as_ptr(), self.len()) }
178    }
179}