| diff --git a/src/device/net/mod.rs b/src/device/net/mod.rs |
| index fa13b44..8375946 100644 |
| --- a/src/device/net/mod.rs |
| +++ b/src/device/net/mod.rs |
| @@ -82,7 +82,7 @@ bitflags! { |
| |
| bitflags! { |
| #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] |
| - struct Status: u16 { |
| + pub(crate) struct Status: u16 { |
| const LINK_UP = 1; |
| const ANNOUNCE = 2; |
| } |
| diff --git a/src/transport/pci/bus.rs b/src/transport/pci/bus.rs |
| index 0a3014b..52f861e 100644 |
| --- a/src/transport/pci/bus.rs |
| +++ b/src/transport/pci/bus.rs |
| @@ -202,7 +202,19 @@ impl PciRoot { |
| // resulting pointer is within the MMIO range of the CAM. |
| unsafe { |
| // Right shift to convert from byte offset to word offset. |
| - (self.mmio_base.add((address >> 2) as usize)).write_volatile(data) |
| + let ptr = self.mmio_base.add((address >> 2) as usize); |
| + #[cfg(not(target_arch = "aarch64"))] |
| + { |
| + ptr.write_volatile(data) |
| + } |
| + #[cfg(target_arch = "aarch64")] |
| + { |
| + core::arch::asm!( |
| + "str {value:w}, [{ptr}]", |
| + value = in(reg) data, |
| + ptr = in(reg) ptr, |
| + ) |
| + } |
| } |
| } |
| |
| diff --git a/src/volatile.rs b/src/volatile.rs |
| index b7059d1..67ebba3 100644 |
| --- a/src/volatile.rs |
| +++ b/src/volatile.rs |
| @@ -33,12 +33,14 @@ pub trait VolatileReadable<T> { |
| unsafe fn vread(self) -> T; |
| } |
| |
| +#[cfg(not(target_arch = "aarch64"))] |
| impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> { |
| unsafe fn vread(self) -> T { |
| self.read_volatile().0 |
| } |
| } |
| |
| +#[cfg(not(target_arch = "aarch64"))] |
| impl<T: Copy> VolatileReadable<T> for *const Volatile<T> { |
| unsafe fn vread(self) -> T { |
| self.read_volatile().0 |
| @@ -51,18 +53,173 @@ pub trait VolatileWritable<T> { |
| unsafe fn vwrite(self, value: T); |
| } |
| |
| +#[cfg(not(target_arch = "aarch64"))] |
| impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> { |
| unsafe fn vwrite(self, value: T) { |
| (self as *mut T).write_volatile(value) |
| } |
| } |
| |
| +#[cfg(not(target_arch = "aarch64"))] |
| impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> { |
| unsafe fn vwrite(self, value: T) { |
| (self as *mut T).write_volatile(value) |
| } |
| } |
| |
| +#[cfg(target_arch = "aarch64")] |
| +mod aarch64_mmio { |
| + use super::{ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly}; |
| + use crate::{device::net::Status, transport::DeviceStatus}; |
| + use core::arch::asm; |
| + |
| + macro_rules! asm_mmio_write { |
| + ($t:ty, $assembly:literal) => { |
| + impl VolatileWritable<$t> for *mut WriteOnly<$t> { |
| + unsafe fn vwrite(self, value: $t) { |
| + asm!( |
| + $assembly, |
| + value = in(reg) value, |
| + ptr = in(reg) (self as *mut $t), |
| + ); |
| + } |
| + } |
| + |
| + impl VolatileWritable<$t> for *mut Volatile<$t> { |
| + unsafe fn vwrite(self, value: $t) { |
| + asm!( |
| + $assembly, |
| + value = in(reg) value, |
| + ptr = in(reg) (self as *mut $t), |
| + ); |
| + } |
| + } |
| + }; |
| + } |
| + |
| + macro_rules! asm_mmio_read { |
| + ($t:ty, $assembly:literal) => { |
| + impl VolatileReadable<$t> for *const ReadOnly<$t> { |
| + unsafe fn vread(self) -> $t { |
| + let value; |
| + asm!( |
| + $assembly, |
| + value = out(reg) value, |
| + ptr = in(reg) (self as *const $t), |
| + ); |
| + value |
| + } |
| + } |
| + |
| + impl VolatileReadable<$t> for *const Volatile<$t> { |
| + unsafe fn vread(self) -> $t { |
| + let value; |
| + asm!( |
| + $assembly, |
| + value = out(reg) value, |
| + ptr = in(reg) (self as *const $t), |
| + ); |
| + value |
| + } |
| + } |
| + }; |
| + } |
| + |
| + asm_mmio_write!(u8, "strb {value:w}, [{ptr}]"); |
| + asm_mmio_write!(u16, "strh {value:w}, [{ptr}]"); |
| + asm_mmio_write!(u32, "str {value:w}, [{ptr}]"); |
| + asm_mmio_write!(u64, "str {value:x}, [{ptr}]"); |
| + |
| + impl VolatileWritable<DeviceStatus> for *mut WriteOnly<DeviceStatus> { |
| + unsafe fn vwrite(self, value: DeviceStatus) { |
| + let value: u32 = value.bits(); |
| + asm!( |
| + "str {value:w}, [{ptr}]", |
| + value = in(reg) value, |
| + ptr = in(reg) (self as *mut u32), |
| + ); |
| + } |
| + } |
| + |
| + impl VolatileWritable<DeviceStatus> for *mut Volatile<DeviceStatus> { |
| + unsafe fn vwrite(self, value: DeviceStatus) { |
| + let value: u32 = value.bits(); |
| + asm!( |
| + "str {value:w}, [{ptr}]", |
| + value = in(reg) value, |
| + ptr = in(reg) (self as *mut u32), |
| + ); |
| + } |
| + } |
| + |
| + asm_mmio_read!(u8, "ldrb {value:w}, [{ptr}]"); |
| + asm_mmio_read!(u16, "ldrh {value:w}, [{ptr}]"); |
| + asm_mmio_read!(u32, "ldr {value:w}, [{ptr}]"); |
| + asm_mmio_read!(u64, "ldr {value:x}, [{ptr}]"); |
| + |
| + impl VolatileReadable<DeviceStatus> for *const ReadOnly<DeviceStatus> { |
| + unsafe fn vread(self) -> DeviceStatus { |
| + let value: u32; |
| + asm!( |
| + "ldr {value:w}, [{ptr}]", |
| + value = out(reg) value, |
| + ptr = in(reg) (self as *const u32), |
| + ); |
| + DeviceStatus::from_bits_retain(value) |
| + } |
| + } |
| + |
| + impl VolatileReadable<DeviceStatus> for *const Volatile<DeviceStatus> { |
| + unsafe fn vread(self) -> DeviceStatus { |
| + let value: u32; |
| + asm!( |
| + "ldr {value:w}, [{ptr}]", |
| + value = out(reg) value, |
| + ptr = in(reg) (self as *const u32), |
| + ); |
| + DeviceStatus::from_bits_retain(value) |
| + } |
| + } |
| + |
| + impl VolatileReadable<Status> for *const ReadOnly<Status> { |
| + unsafe fn vread(self) -> Status { |
| + let value: u16; |
| + asm!( |
| + "ldrh {value:w}, [{ptr}]", |
| + value = out(reg) value, |
| + ptr = in(reg) (self as *const u16), |
| + ); |
| + Status::from_bits_retain(value) |
| + } |
| + } |
| + |
| + impl VolatileReadable<Status> for *const Volatile<Status> { |
| + unsafe fn vread(self) -> Status { |
| + let value: u16; |
| + asm!( |
| + "ldrh {value:w}, [{ptr}]", |
| + value = out(reg) value, |
| + ptr = in(reg) (self as *const u16), |
| + ); |
| + Status::from_bits_retain(value) |
| + } |
| + } |
| + |
| + impl<const SIZE: usize> VolatileReadable<[u8; SIZE]> for *const ReadOnly<[u8; SIZE]> { |
| + unsafe fn vread(self) -> [u8; SIZE] { |
| + let mut value = [0; SIZE]; |
| + for i in 0..SIZE { |
| + asm!( |
| + "ldrb {value:w}, [{ptr}]", |
| + value = out(reg) value[i], |
| + ptr = in(reg) (self as *const u8).add(i), |
| + ); |
| + } |
| + value |
| + } |
| + } |
| +} |
| + |
| /// Performs a volatile read from the given field of pointer to a struct representing an MMIO region. |
| /// |
| /// # Usage |