1diff --git a/src/transport/pci/bus.rs b/src/transport/pci/bus.rs 2index ac6e30da..0629b2cc 100644 3--- a/src/transport/pci/bus.rs 4+++ b/src/transport/pci/bus.rs 5@@ -357,7 +357,19 @@ impl ConfigurationAccess for MmioCam { 6 // resulting pointer is within the MMIO range of the CAM. 7 unsafe { 8 // Right shift to convert from byte offset to word offset. 9- (self.mmio_base.add((address >> 2) as usize)).write_volatile(data) 10+ let ptr = self.mmio_base.add((address >> 2) as usize); 11+ #[cfg(not(target_arch = "aarch64"))] 12+ { 13+ ptr.write_volatile(data) 14+ } 15+ #[cfg(target_arch = "aarch64")] 16+ { 17+ core::arch::asm!( 18+ "str {value:w}, [{ptr}]", 19+ value = in(reg) data, 20+ ptr = in(reg) ptr, 21+ ) 22+ } 23 } 24 } 25 26diff --git a/src/volatile.rs b/src/volatile.rs 27index 74f527b3..caa58e23 100644 28--- a/src/volatile.rs 29+++ b/src/volatile.rs 30@@ -33,12 +33,14 @@ pub trait VolatileReadable<T> { 31 unsafe fn vread(self) -> T; 32 } 33 34+#[cfg(not(target_arch = "aarch64"))] 35 impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> { 36 unsafe fn vread(self) -> T { 37 self.read_volatile().0 38 } 39 } 40 41+#[cfg(not(target_arch = "aarch64"))] 42 impl<T: Copy> VolatileReadable<T> for *const Volatile<T> { 43 unsafe fn vread(self) -> T { 44 self.read_volatile().0 45@@ -51,18 +53,135 @@ pub trait VolatileWritable<T> { 46 unsafe fn vwrite(self, value: T); 47 } 48 49+#[cfg(not(target_arch = "aarch64"))] 50 impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> { 51 unsafe fn vwrite(self, value: T) { 52 (self as *mut T).write_volatile(value) 53 } 54 } 55 56+#[cfg(not(target_arch = "aarch64"))] 57 impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> { 58 unsafe fn vwrite(self, value: T) { 59 (self as *mut T).write_volatile(value) 60 } 61 } 62 63+#[cfg(target_arch = "aarch64")] 64+mod aarch64_mmio { 65+ use super::{ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly}; 66+ use crate::transport::DeviceStatus; 67+ use core::arch::asm; 68+ 69+ macro_rules! asm_mmio_write { 70+ ($t:ty, $assembly:literal) => { 71+ impl VolatileWritable<$t> for *mut WriteOnly<$t> { 72+ unsafe fn vwrite(self, value: $t) { 73+ asm!( 74+ $assembly, 75+ value = in(reg) value, 76+ ptr = in(reg) (self as *mut $t), 77+ ); 78+ } 79+ } 80+ 81+ impl VolatileWritable<$t> for *mut Volatile<$t> { 82+ unsafe fn vwrite(self, value: $t) { 83+ asm!( 84+ $assembly, 85+ value = in(reg) value, 86+ ptr = in(reg) (self as *mut $t), 87+ ); 88+ } 89+ } 90+ }; 91+ } 92+ 93+ macro_rules! asm_mmio_read { 94+ ($t:ty, $assembly:literal) => { 95+ impl VolatileReadable<$t> for *const ReadOnly<$t> { 96+ unsafe fn vread(self) -> $t { 97+ let value; 98+ asm!( 99+ $assembly, 100+ value = out(reg) value, 101+ ptr = in(reg) (self as *const $t), 102+ ); 103+ value 104+ } 105+ } 106+ 107+ impl VolatileReadable<$t> for *const Volatile<$t> { 108+ unsafe fn vread(self) -> $t { 109+ let value; 110+ asm!( 111+ $assembly, 112+ value = out(reg) value, 113+ ptr = in(reg) (self as *const $t), 114+ ); 115+ value 116+ } 117+ } 118+ }; 119+ } 120+ 121+ asm_mmio_write!(u8, "strb {value:w}, [{ptr}]"); 122+ asm_mmio_write!(u16, "strh {value:w}, [{ptr}]"); 123+ asm_mmio_write!(u32, "str {value:w}, [{ptr}]"); 124+ asm_mmio_write!(u64, "str {value:x}, [{ptr}]"); 125+ 126+ impl VolatileWritable<DeviceStatus> for *mut WriteOnly<DeviceStatus> { 127+ unsafe fn vwrite(self, value: DeviceStatus) { 128+ let value: u32 = value.bits(); 129+ asm!( 130+ "str {value:w}, [{ptr}]", 131+ value = in(reg) value, 132+ ptr = in(reg) (self as *mut u32), 133+ ); 134+ } 135+ } 136+ 137+ impl VolatileWritable<DeviceStatus> for *mut Volatile<DeviceStatus> { 138+ unsafe fn vwrite(self, value: DeviceStatus) { 139+ let value: u32 = value.bits(); 140+ asm!( 141+ "str {value:w}, [{ptr}]", 142+ value = in(reg) value, 143+ ptr = in(reg) (self as *mut u32), 144+ ); 145+ } 146+ } 147+ 148+ asm_mmio_read!(u8, "ldrb {value:w}, [{ptr}]"); 149+ asm_mmio_read!(u16, "ldrh {value:w}, [{ptr}]"); 150+ asm_mmio_read!(u32, "ldr {value:w}, [{ptr}]"); 151+ asm_mmio_read!(u64, "ldr {value:x}, [{ptr}]"); 152+ 153+ impl VolatileReadable<DeviceStatus> for *const ReadOnly<DeviceStatus> { 154+ unsafe fn vread(self) -> DeviceStatus { 155+ let value: u32; 156+ asm!( 157+ "ldr {value:w}, [{ptr}]", 158+ value = out(reg) value, 159+ ptr = in(reg) (self as *const u32), 160+ ); 161+ DeviceStatus::from_bits_retain(value) 162+ } 163+ } 164+ 165+ impl VolatileReadable<DeviceStatus> for *const Volatile<DeviceStatus> { 166+ unsafe fn vread(self) -> DeviceStatus { 167+ let value: u32; 168+ asm!( 169+ "ldr {value:w}, [{ptr}]", 170+ value = out(reg) value, 171+ ptr = in(reg) (self as *const u32), 172+ ); 173+ DeviceStatus::from_bits_retain(value) 174+ } 175+ } 176+} 177+ 178 /// Performs a volatile read from the given field of pointer to a struct representing an MMIO region. 179 /// 180 /// # Usage 181