1use num_traits::{PrimInt, Unsigned};
6use std::convert::TryInto;
7use std::fmt::{self, Binary, Debug, LowerHex, UpperHex};
8use std::io::{self, ErrorKind};
9use std::marker::PhantomData;
10
11use crate::regions::{AsPciSubregion, BackedByPciSubregion, PciRegion};
12
13use private::Sealed;
16mod private {
17 pub trait Sealed {}
19}
20
21pub trait PciRegisterValue:
27 PrimInt + Unsigned + Debug + LowerHex + UpperHex + Binary + Sealed
28{
29 fn read(region: &dyn PciRegion, offset: u64) -> io::Result<Self>;
32
33 fn write(self, region: &dyn PciRegion, offset: u64) -> io::Result<()>;
36}
37
38impl Sealed for u8 {}
39impl PciRegisterValue for u8 {
40 fn read(region: &dyn PciRegion, offset: u64) -> io::Result<Self> {
41 region.read_u8(offset)
42 }
43
44 fn write(self, region: &dyn PciRegion, offset: u64) -> io::Result<()> {
45 region.write_u8(offset, self)
46 }
47}
48
49impl Sealed for u16 {}
50impl PciRegisterValue for u16 {
51 fn read(region: &dyn PciRegion, offset: u64) -> io::Result<Self> {
52 region.read_le_u16(offset)
53 }
54
55 fn write(self, region: &dyn PciRegion, offset: u64) -> io::Result<()> {
56 region.write_le_u16(offset, self)
57 }
58}
59
60impl Sealed for u32 {}
61impl PciRegisterValue for u32 {
62 fn read(region: &dyn PciRegion, offset: u64) -> io::Result<Self> {
63 region.read_le_u32(offset)
64 }
65
66 fn write(self, region: &dyn PciRegion, offset: u64) -> io::Result<()> {
67 region.write_le_u32(offset, self)
68 }
69}
70
71fn print_debug_hex<T: Debug + LowerHex>(
72 value: io::Result<T>,
73 f: &mut fmt::Formatter,
74) -> fmt::Result {
75 if let Ok(v) = value {
76 write!(f, "Ok({:#x})", v)
78 } else {
79 Debug::fmt(&value, f)
80 }
81}
82
83fn print_debug_bool(value: io::Result<bool>, f: &mut fmt::Formatter) -> fmt::Result {
84 if let Ok(v) = value {
85 write!(f, "Ok({})", v)
87 } else {
88 Debug::fmt(&value, f)
89 }
90}
91
92#[derive(Clone, Copy)]
98pub struct PciRegisterRo<'a, T: PciRegisterValue> {
99 region: &'a dyn PciRegion,
100 offset: u64,
101 phantom: PhantomData<T>,
102}
103
104impl<'a, T: PciRegisterValue> PciRegisterRo<'a, T> {
105 pub fn read(&self) -> io::Result<T> {
107 T::read(self.region, self.offset)
108 }
109}
110
111impl<'a, T: PciRegisterValue> BackedByPciSubregion<'a> for PciRegisterRo<'a, T> {
112 fn backed_by(as_subregion: impl AsPciSubregion<'a>) -> Self {
113 let subregion = as_subregion.as_subregion();
114 PciRegisterRo {
115 region: subregion.underlying_region(),
116 offset: subregion.offset_in_underlying_region(),
117 phantom: PhantomData,
118 }
119 }
120}
121
122impl<T: PciRegisterValue> Debug for PciRegisterRo<'_, T> {
123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124 print_debug_hex(self.read(), f)
125 }
126}
127
128#[derive(Clone, Copy)]
132pub struct PciRegisterRw<'a, T: PciRegisterValue> {
133 region: &'a dyn PciRegion,
134 offset: u64,
135 phantom: PhantomData<T>,
136}
137
138impl<'a, T: PciRegisterValue> PciRegisterRw<'a, T> {
139 pub fn read(&self) -> io::Result<T> {
141 T::read(self.region, self.offset)
142 }
143
144 pub fn write(&self, value: T) -> io::Result<()> {
146 value.write(self.region, self.offset)
147 }
148}
149
150impl<'a, T: PciRegisterValue> BackedByPciSubregion<'a> for PciRegisterRw<'a, T> {
151 fn backed_by(as_subregion: impl AsPciSubregion<'a>) -> Self {
152 let subregion = as_subregion.as_subregion();
153 PciRegisterRw {
154 region: subregion.underlying_region(),
155 offset: subregion.offset_in_underlying_region(),
156 phantom: PhantomData,
157 }
158 }
159}
160
161impl<T: PciRegisterValue> Debug for PciRegisterRw<'_, T> {
162 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
163 print_debug_hex(self.read(), f)
164 }
165}
166
167pub trait PciBitFieldReadable: Debug {
173 type Type: PciRegisterValue;
175
176 fn read(&self) -> io::Result<Self::Type>;
178}
179
180pub trait PciBitFieldWriteable: PciBitFieldReadable {
182 const WRITE_MASK: Self::Type;
199
200 fn write(&self, value: Self::Type) -> io::Result<()>;
202}
203
204#[derive(Clone, Copy)]
211pub struct PciBitsReadOnly<'a, T, U>
212where
213 T: PciRegisterValue + TryInto<U>,
214 T::Error: Debug,
215 U: PciRegisterValue,
216{
217 region: &'a dyn PciRegion,
218 offset: u64,
219 mask: T,
220 shift: u8,
221 phantom: PhantomData<U>,
222}
223
224impl<'a, T, U> PciBitsReadOnly<'a, T, U>
225where
226 T: PciRegisterValue + TryInto<U>,
227 T::Error: Debug,
228 U: PciRegisterValue,
229{
230 pub fn backed_by(region: &'a dyn PciRegion, offset: u64, mask: T, shift: u8) -> Self {
231 PciBitsReadOnly {
232 region,
233 offset,
234 mask,
235 shift,
236 phantom: PhantomData,
237 }
238 }
239
240 pub fn read(&self) -> io::Result<U> {
244 let value = (T::read(self.region, self.offset)? & self.mask) >> self.shift.into();
245 Ok(value.try_into().unwrap())
247 }
248}
249
250impl<T, U> Debug for PciBitsReadOnly<'_, T, U>
251where
252 T: PciRegisterValue + TryInto<U>,
253 T::Error: Debug,
254 U: PciRegisterValue,
255{
256 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
257 print_debug_hex(self.read(), f)
258 }
259}
260
261#[derive(Clone, Copy)]
265pub struct PciBitsReadWrite<'a, T, U>
266where
267 T: PciRegisterValue + TryInto<U>,
268 T::Error: Debug,
269 U: PciRegisterValue + Into<T>,
270{
271 region: &'a dyn PciRegion,
272 offset: u64,
273 mask: T,
274 shift: u8,
275 write_mask: T, phantom: PhantomData<U>,
277}
278
279impl<'a, T, U> PciBitsReadWrite<'a, T, U>
280where
281 T: PciRegisterValue + TryInto<U>,
282 T::Error: Debug,
283 U: PciRegisterValue + Into<T>,
284{
285 pub fn backed_by(
286 region: &'a dyn PciRegion,
287 offset: u64,
288 mask: T,
289 shift: u8,
290 write_mask: T,
291 ) -> Self {
292 PciBitsReadWrite {
293 region,
294 offset,
295 mask,
296 shift,
297 write_mask,
298 phantom: PhantomData,
299 }
300 }
301
302 pub fn read(&self) -> io::Result<U> {
306 let value = (T::read(self.region, self.offset)? & self.mask) >> self.shift.into();
307 Ok(value.try_into().unwrap())
309 }
310
311 pub fn write(&self, value: U) -> io::Result<()> {
316 let shifted = value.into() << self.shift.into();
317
318 if shifted >> self.shift.into() != value.into() || shifted & !self.mask != T::zero() {
319 return Err(io::Error::new(ErrorKind::InvalidInput, "Value is too big"));
320 }
321
322 let to_write = (T::read(self.region, self.offset)? & self.write_mask) | shifted;
323 to_write.write(self.region, self.offset)
324 }
325}
326
327impl<T, U> Debug for PciBitsReadWrite<'_, T, U>
328where
329 T: PciRegisterValue + TryInto<U>,
330 T::Error: Debug,
331 U: PciRegisterValue + Into<T>,
332{
333 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
334 print_debug_hex(self.read(), f)
335 }
336}
337
338#[derive(Clone, Copy)]
342pub struct PciBitReadOnly<'a, T: PciRegisterValue> {
343 region: &'a dyn PciRegion,
344 offset: u64,
345 mask: T,
346}
347
348impl<'a, T: PciRegisterValue> PciBitReadOnly<'a, T> {
349 pub fn backed_by(region: &'a dyn PciRegion, offset: u64, mask: T) -> Self {
350 PciBitReadOnly {
351 region,
352 offset,
353 mask,
354 }
355 }
356
357 pub fn read(&self) -> io::Result<bool> {
361 Ok(T::read(self.region, self.offset)? & self.mask != T::zero())
362 }
363}
364
365impl<T: PciRegisterValue> Debug for PciBitReadOnly<'_, T> {
366 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
367 print_debug_bool(self.read(), f)
368 }
369}
370
371#[derive(Clone, Copy)]
375pub struct PciBitReadWrite<'a, T: PciRegisterValue> {
376 region: &'a dyn PciRegion,
377 offset: u64,
378 mask: T,
379 write_mask: T, }
381
382impl<'a, T: PciRegisterValue> PciBitReadWrite<'a, T> {
383 pub fn backed_by(region: &'a dyn PciRegion, offset: u64, mask: T, write_mask: T) -> Self {
384 PciBitReadWrite {
385 region,
386 offset,
387 mask,
388 write_mask,
389 }
390 }
391
392 pub fn read(&self) -> io::Result<bool> {
396 Ok(T::read(self.region, self.offset)? & self.mask != T::zero())
397 }
398
399 pub fn write(&self, value: bool) -> io::Result<()> {
403 let old = T::read(self.region, self.offset)? & self.write_mask;
404
405 let new = if value {
406 old | self.mask
407 } else {
408 old & !self.mask
409 };
410
411 new.write(self.region, self.offset)
412 }
413}
414
415impl<T: PciRegisterValue> Debug for PciBitReadWrite<'_, T> {
416 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
417 print_debug_bool(self.read(), f)
418 }
419}
420
421#[derive(Clone, Copy)]
425pub struct PciBitReadClear<'a, T: PciRegisterValue> {
426 rw: PciBitReadWrite<'a, T>,
427}
428
429impl<'a, T: PciRegisterValue> PciBitReadClear<'a, T> {
430 pub fn backed_by(region: &'a dyn PciRegion, offset: u64, mask: T, write_mask: T) -> Self {
431 PciBitReadClear {
432 rw: PciBitReadWrite {
433 region,
434 offset,
435 mask,
436 write_mask,
437 },
438 }
439 }
440
441 pub fn read(&self) -> io::Result<bool> {
445 self.rw.read()
446 }
447
448 pub fn clear(&self) -> io::Result<()> {
452 self.rw.write(true)
453 }
454}
455
456impl<T: PciRegisterValue> Debug for PciBitReadClear<'_, T> {
457 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
458 print_debug_bool(self.read(), f)
459 }
460}
461
462