blob: 2cf725f7228cb37a579670923ea7fff15ff4cd96 [file] [log] [blame] [edit]
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