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