• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /// An MMIO register which can only be read from.
2 #[derive(Default)]
3 #[repr(transparent)]
4 pub struct ReadOnly<T: Copy>(pub(crate) T);
5 
6 impl<T: Copy> ReadOnly<T> {
7     /// Construct a new instance for testing.
new(value: T) -> Self8     pub const fn new(value: T) -> Self {
9         Self(value)
10     }
11 }
12 
13 /// An MMIO register which can only be written to.
14 #[derive(Default)]
15 #[repr(transparent)]
16 pub struct WriteOnly<T: Copy>(pub(crate) T);
17 
18 /// An MMIO register which may be both read and written.
19 #[derive(Default)]
20 #[repr(transparent)]
21 pub struct Volatile<T: Copy>(T);
22 
23 impl<T: Copy> Volatile<T> {
24     /// Construct a new instance for testing.
new(value: T) -> Self25     pub const fn new(value: T) -> Self {
26         Self(value)
27     }
28 }
29 
30 /// A trait implemented by MMIO registers which may be read from.
31 pub trait VolatileReadable<T> {
32     /// Performs a volatile read from the MMIO register.
vread(self) -> T33     unsafe fn vread(self) -> T;
34 }
35 
36 impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> {
vread(self) -> T37     unsafe fn vread(self) -> T {
38         self.read_volatile().0
39     }
40 }
41 
42 impl<T: Copy> VolatileReadable<T> for *const Volatile<T> {
vread(self) -> T43     unsafe fn vread(self) -> T {
44         self.read_volatile().0
45     }
46 }
47 
48 /// A trait implemented by MMIO registers which may be written to.
49 pub trait VolatileWritable<T> {
50     /// Performs a volatile write to the MMIO register.
vwrite(self, value: T)51     unsafe fn vwrite(self, value: T);
52 }
53 
54 impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> {
vwrite(self, value: T)55     unsafe fn vwrite(self, value: T) {
56         (self as *mut T).write_volatile(value)
57     }
58 }
59 
60 impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> {
vwrite(self, value: T)61     unsafe fn vwrite(self, value: T) {
62         (self as *mut T).write_volatile(value)
63     }
64 }
65 
66 /// Performs a volatile read from the given field of pointer to a struct representing an MMIO region.
67 ///
68 /// # Usage
69 /// ```compile_fail
70 /// # use core::ptr::NonNull;
71 /// # use virtio_drivers_and_devices::volatile::{ReadOnly, volread};
72 /// struct MmioDevice {
73 ///   field: ReadOnly<u32>,
74 /// }
75 ///
76 /// let device: NonNull<MmioDevice> = NonNull::new(0x1234 as *mut MmioDevice).unwrap();
77 /// let value = unsafe { volread!(device, field) };
78 /// ```
79 macro_rules! volread {
80     ($nonnull:expr, $field:ident) => {
81         $crate::volatile::VolatileReadable::vread((&raw const (*$nonnull.as_ptr()).$field))
82     };
83 }
84 
85 /// Performs a volatile write to the given field of pointer to a struct representing an MMIO region.
86 ///
87 /// # Usage
88 /// ```compile_fail
89 /// # use core::ptr::NonNull;
90 /// # use virtio_drivers_and_devices::volatile::{WriteOnly, volread};
91 /// struct MmioDevice {
92 ///   field: WriteOnly<u32>,
93 /// }
94 ///
95 /// let device: NonNull<MmioDevice> = NonNull::new(0x1234 as *mut MmioDevice).unwrap();
96 /// unsafe { volwrite!(device, field, 42); }
97 /// ```
98 macro_rules! volwrite {
99     ($nonnull:expr, $field:ident, $value:expr) => {
100         $crate::volatile::VolatileWritable::vwrite((&raw mut (*$nonnull.as_ptr()).$field), $value)
101     };
102 }
103 
104 pub(crate) use volread;
105 pub(crate) use volwrite;
106