volatile.rs 2.9 KB

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