1diff --git a/src/device/net/mod.rs b/src/device/net/mod.rs 2index fa13b44..8375946 100644 3--- a/src/device/net/mod.rs 4+++ b/src/device/net/mod.rs 5@@ -82,7 +82,7 @@ bitflags! { 6 7 bitflags! { 8 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 9- struct Status: u16 { 10+ pub(crate) struct Status: u16 { 11 const LINK_UP = 1; 12 const ANNOUNCE = 2; 13 } 14diff --git a/src/transport/pci/bus.rs b/src/transport/pci/bus.rs 15index 0a3014b..52f861e 100644 16--- a/src/transport/pci/bus.rs 17+++ b/src/transport/pci/bus.rs 18@@ -202,7 +202,19 @@ impl PciRoot { 19 // resulting pointer is within the MMIO range of the CAM. 20 unsafe { 21 // Right shift to convert from byte offset to word offset. 22- (self.mmio_base.add((address >> 2) as usize)).write_volatile(data) 23+ let ptr = self.mmio_base.add((address >> 2) as usize); 24+ #[cfg(not(target_arch = "aarch64"))] 25+ { 26+ ptr.write_volatile(data) 27+ } 28+ #[cfg(target_arch = "aarch64")] 29+ { 30+ core::arch::asm!( 31+ "str {value:w}, [{ptr}]", 32+ value = in(reg) data, 33+ ptr = in(reg) ptr, 34+ ) 35+ } 36 } 37 } 38 39diff --git a/src/volatile.rs b/src/volatile.rs 40index b7059d1..67ebba3 100644 41--- a/src/volatile.rs 42+++ b/src/volatile.rs 43@@ -33,12 +33,14 @@ pub trait VolatileReadable<T> { 44 unsafe fn vread(self) -> T; 45 } 46 47+#[cfg(not(target_arch = "aarch64"))] 48 impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> { 49 unsafe fn vread(self) -> T { 50 self.read_volatile().0 51 } 52 } 53 54+#[cfg(not(target_arch = "aarch64"))] 55 impl<T: Copy> VolatileReadable<T> for *const Volatile<T> { 56 unsafe fn vread(self) -> T { 57 self.read_volatile().0 58@@ -51,18 +53,173 @@ pub trait VolatileWritable<T> { 59 unsafe fn vwrite(self, value: T); 60 } 61 62+#[cfg(not(target_arch = "aarch64"))] 63 impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> { 64 unsafe fn vwrite(self, value: T) { 65 (self as *mut T).write_volatile(value) 66 } 67 } 68 69+#[cfg(not(target_arch = "aarch64"))] 70 impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> { 71 unsafe fn vwrite(self, value: T) { 72 (self as *mut T).write_volatile(value) 73 } 74 } 75 76+#[cfg(target_arch = "aarch64")] 77+mod aarch64_mmio { 78+ use super::{ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly}; 79+ use crate::{device::net::Status, transport::DeviceStatus}; 80+ use core::arch::asm; 81+ 82+ macro_rules! asm_mmio_write { 83+ ($t:ty, $assembly:literal) => { 84+ impl VolatileWritable<$t> for *mut WriteOnly<$t> { 85+ unsafe fn vwrite(self, value: $t) { 86+ asm!( 87+ $assembly, 88+ value = in(reg) value, 89+ ptr = in(reg) (self as *mut $t), 90+ ); 91+ } 92+ } 93+ 94+ impl VolatileWritable<$t> for *mut Volatile<$t> { 95+ unsafe fn vwrite(self, value: $t) { 96+ asm!( 97+ $assembly, 98+ value = in(reg) value, 99+ ptr = in(reg) (self as *mut $t), 100+ ); 101+ } 102+ } 103+ }; 104+ } 105+ 106+ macro_rules! asm_mmio_read { 107+ ($t:ty, $assembly:literal) => { 108+ impl VolatileReadable<$t> for *const ReadOnly<$t> { 109+ unsafe fn vread(self) -> $t { 110+ let value; 111+ asm!( 112+ $assembly, 113+ value = out(reg) value, 114+ ptr = in(reg) (self as *const $t), 115+ ); 116+ value 117+ } 118+ } 119+ 120+ impl VolatileReadable<$t> for *const Volatile<$t> { 121+ unsafe fn vread(self) -> $t { 122+ let value; 123+ asm!( 124+ $assembly, 125+ value = out(reg) value, 126+ ptr = in(reg) (self as *const $t), 127+ ); 128+ value 129+ } 130+ } 131+ }; 132+ } 133+ 134+ asm_mmio_write!(u8, "strb {value:w}, [{ptr}]"); 135+ asm_mmio_write!(u16, "strh {value:w}, [{ptr}]"); 136+ asm_mmio_write!(u32, "str {value:w}, [{ptr}]"); 137+ asm_mmio_write!(u64, "str {value:x}, [{ptr}]"); 138+ 139+ impl VolatileWritable<DeviceStatus> for *mut WriteOnly<DeviceStatus> { 140+ unsafe fn vwrite(self, value: DeviceStatus) { 141+ let value: u32 = value.bits(); 142+ asm!( 143+ "str {value:w}, [{ptr}]", 144+ value = in(reg) value, 145+ ptr = in(reg) (self as *mut u32), 146+ ); 147+ } 148+ } 149+ 150+ impl VolatileWritable<DeviceStatus> for *mut Volatile<DeviceStatus> { 151+ unsafe fn vwrite(self, value: DeviceStatus) { 152+ let value: u32 = value.bits(); 153+ asm!( 154+ "str {value:w}, [{ptr}]", 155+ value = in(reg) value, 156+ ptr = in(reg) (self as *mut u32), 157+ ); 158+ } 159+ } 160+ 161+ asm_mmio_read!(u8, "ldrb {value:w}, [{ptr}]"); 162+ asm_mmio_read!(u16, "ldrh {value:w}, [{ptr}]"); 163+ asm_mmio_read!(u32, "ldr {value:w}, [{ptr}]"); 164+ asm_mmio_read!(u64, "ldr {value:x}, [{ptr}]"); 165+ 166+ impl VolatileReadable<DeviceStatus> for *const ReadOnly<DeviceStatus> { 167+ unsafe fn vread(self) -> DeviceStatus { 168+ let value: u32; 169+ asm!( 170+ "ldr {value:w}, [{ptr}]", 171+ value = out(reg) value, 172+ ptr = in(reg) (self as *const u32), 173+ ); 174+ DeviceStatus::from_bits_retain(value) 175+ } 176+ } 177+ 178+ impl VolatileReadable<DeviceStatus> for *const Volatile<DeviceStatus> { 179+ unsafe fn vread(self) -> DeviceStatus { 180+ let value: u32; 181+ asm!( 182+ "ldr {value:w}, [{ptr}]", 183+ value = out(reg) value, 184+ ptr = in(reg) (self as *const u32), 185+ ); 186+ DeviceStatus::from_bits_retain(value) 187+ } 188+ } 189+ 190+ impl VolatileReadable<Status> for *const ReadOnly<Status> { 191+ unsafe fn vread(self) -> Status { 192+ let value: u16; 193+ asm!( 194+ "ldrh {value:w}, [{ptr}]", 195+ value = out(reg) value, 196+ ptr = in(reg) (self as *const u16), 197+ ); 198+ Status::from_bits_retain(value) 199+ } 200+ } 201+ 202+ impl VolatileReadable<Status> for *const Volatile<Status> { 203+ unsafe fn vread(self) -> Status { 204+ let value: u16; 205+ asm!( 206+ "ldrh {value:w}, [{ptr}]", 207+ value = out(reg) value, 208+ ptr = in(reg) (self as *const u16), 209+ ); 210+ Status::from_bits_retain(value) 211+ } 212+ } 213+ 214+ impl<const SIZE: usize> VolatileReadable<[u8; SIZE]> for *const ReadOnly<[u8; SIZE]> { 215+ unsafe fn vread(self) -> [u8; SIZE] { 216+ let mut value = [0; SIZE]; 217+ for i in 0..SIZE { 218+ asm!( 219+ "ldrb {value:w}, [{ptr}]", 220+ value = out(reg) value[i], 221+ ptr = in(reg) (self as *const u8).add(i), 222+ ); 223+ } 224+ value 225+ } 226+ } 227+} 228+ 229 /// Performs a volatile read from the given field of pointer to a struct representing an MMIO region. 230 /// 231 /// # Usage 232