dma_api/dma/
slice.rs

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