1use core::marker::PhantomData;
4
5use volatile::access::{Readable, Writable};
6use volatile::VolatilePtr;
7
8use crate::{be32, be64, le16, le32, le64, DeviceStatus, Id};
9
10pub struct WideVolatilePtr<'a, T, A>
15where
16 T: ?Sized,
17{
18 low: VolatilePtr<'a, T, A>,
19 high: VolatilePtr<'a, T, A>,
20}
21
22impl<'a, T, A> Copy for WideVolatilePtr<'a, T, A> where T: ?Sized {}
23
24impl<'a, T, A> Clone for WideVolatilePtr<'a, T, A>
25where
26 T: ?Sized,
27{
28 fn clone(&self) -> Self {
29 *self
30 }
31}
32
33impl<'a, T, A> WideVolatilePtr<'a, T, A> {
34 pub fn from_low_high(low: VolatilePtr<'a, T, A>, high: VolatilePtr<'a, T, A>) -> Self {
36 Self { low, high }
37 }
38}
39
40impl<'a, A> WideVolatilePtr<'a, le32, A> {
41 pub fn read(self) -> le64
45 where
46 A: Readable,
47 {
48 let low = self.low.read();
49 let high = self.high.read();
50 le64::from([low, high])
51 }
52
53 pub fn write(self, value: le64)
57 where
58 A: Writable,
59 {
60 let [low, high] = value.into();
61 self.low.write(low);
62 self.high.write(high);
63 }
64
65 pub fn update(self, f: impl FnOnce(le64) -> le64)
69 where
70 A: Readable + Writable,
71 {
72 let new = f(self.read());
73 self.write(new);
74 }
75}
76
77impl<'a, A> WideVolatilePtr<'a, be32, A> {
78 pub fn read(self) -> be64
82 where
83 A: Readable,
84 {
85 let low = self.low.read();
86 let high = self.high.read();
87 be64::from([low, high])
88 }
89
90 pub fn write(self, value: be64)
94 where
95 A: Writable,
96 {
97 let [low, high] = value.into();
98 self.low.write(low);
99 self.high.write(high);
100 }
101
102 pub fn update(self, f: impl FnOnce(be64) -> be64)
106 where
107 A: Readable + Writable,
108 {
109 let new = f(self.read());
110 self.write(new);
111 }
112}
113
114#[cfg(any(feature = "mmio", feature = "pci"))]
115macro_rules! impl_wide_field_access {
116 (
117 $(#[$outer:meta])*
118 $vis:vis trait $Trait:ident<'a, A>: $T:ty {
119 $(
120 $(#[doc = $doc:literal])*
121 $(#[doc(alias = $alias:literal)])?
122 #[access($Access:ty)]
123 $field:ident: $field_low:ident, $field_high:ident;
124 )*
125 }
126 ) => {
127 $(#[$outer])*
128 $vis trait $Trait<'a, A> {
129 $(
130 $(#[doc = $doc])*
131 $(#[doc(alias = $alias)])?
132 fn $field(self) -> WideVolatilePtr<'a, le32, A::Restricted>
133 where
134 A: RestrictAccess<$Access>;
135 )*
136 }
137
138 impl<'a, A> $Trait<'a, A> for VolatilePtr<'a, $T, A> {
139 $(
140 fn $field(self) -> WideVolatilePtr<'a, le32, A::Restricted>
141 where
142 A: RestrictAccess<$Access>,
143 {
144 WideVolatilePtr::from_low_high(self.$field_low(), self.$field_high())
145 }
146 )*
147 }
148 };
149}
150
151pub struct OveralignedVolatilePtr<'a, T, F, A>
157where
158 T: ?Sized,
159 F: ?Sized,
160{
161 ptr: VolatilePtr<'a, F, A>,
162 ty: PhantomData<VolatilePtr<'a, T, A>>,
163}
164
165impl<'a, T, F, A> Copy for OveralignedVolatilePtr<'a, T, F, A>
166where
167 T: ?Sized,
168 F: ?Sized,
169{
170}
171
172impl<'a, T, F, A> Clone for OveralignedVolatilePtr<'a, T, F, A>
173where
174 T: ?Sized,
175 F: ?Sized,
176{
177 fn clone(&self) -> Self {
178 *self
179 }
180}
181
182impl<'a, T, F, A> OveralignedVolatilePtr<'a, T, F, A>
183where
184 T: OveralignedField<F>,
185 F: Copy,
186{
187 pub fn new(ptr: VolatilePtr<'a, F, A>) -> Self {
189 Self {
190 ptr,
191 ty: PhantomData,
192 }
193 }
194
195 pub fn read(self) -> T
199 where
200 A: Readable,
201 {
202 T::from_field(self.ptr.read())
203 }
204
205 pub fn write(self, value: T)
209 where
210 A: Writable,
211 {
212 self.ptr.write(value.into_field())
213 }
214
215 pub fn update(self, f: impl FnOnce(T) -> T)
219 where
220 A: Readable + Writable,
221 {
222 let new = f(self.read());
223 self.write(new);
224 }
225}
226
227pub trait OveralignedField<F>: private::Sealed<F> {
229 fn from_field(field: F) -> Self;
231
232 fn into_field(self) -> F;
234}
235
236impl OveralignedField<le32> for le16 {
237 fn from_field(field: le32) -> Self {
238 field.try_into().unwrap()
239 }
240
241 fn into_field(self) -> le32 {
242 self.into()
243 }
244}
245
246impl OveralignedField<le32> for bool {
247 fn from_field(field: le32) -> Self {
248 field.to_ne() == 1
249 }
250
251 fn into_field(self) -> le32 {
252 le32::from_ne(self as u32)
253 }
254}
255
256impl OveralignedField<le32> for u8 {
257 fn from_field(field: le32) -> Self {
258 field.to_ne().try_into().unwrap()
259 }
260
261 fn into_field(self) -> le32 {
262 le32::from_ne(self.into())
263 }
264}
265
266impl OveralignedField<le32> for Id {
267 fn from_field(field: le32) -> Self {
268 Self::from(u8::from_field(field))
269 }
270
271 fn into_field(self) -> le32 {
272 u8::from(self).into_field()
273 }
274}
275
276impl OveralignedField<le32> for DeviceStatus {
277 fn from_field(field: le32) -> Self {
278 Self::from_bits_retain(u8::from_field(field))
279 }
280
281 fn into_field(self) -> le32 {
282 self.bits().into_field()
283 }
284}
285
286#[cfg(feature = "mmio")]
287impl OveralignedField<le32> for crate::mmio::InterruptStatus {
288 fn from_field(field: le32) -> Self {
289 Self::from_bits_retain(u8::from_field(field))
290 }
291
292 fn into_field(self) -> le32 {
293 self.bits().into_field()
294 }
295}
296
297mod private {
298 use crate::{le16, le32, DeviceStatus, Id};
299
300 pub trait Sealed<T> {}
301
302 impl Sealed<le32> for bool {}
303 impl Sealed<le32> for u8 {}
304 impl Sealed<le32> for le16 {}
305 impl Sealed<le32> for Id {}
306 impl Sealed<le32> for DeviceStatus {}
307 #[cfg(feature = "mmio")]
308 impl Sealed<le32> for crate::mmio::InterruptStatus {}
309}