mod mmio;
#[cfg(any(target_arch = "x86", target_arch = "x86_64", doc))]
mod pio;
pub use mmio::{MmioAddress, MmioBackend};
#[cfg(any(target_arch = "x86", target_arch = "x86_64", doc))]
pub use pio::{PioBackend, PortIoAddress};
use crate::spec::NUM_REGISTERS;
use core::fmt::Debug;
use core::num::NonZeroU8;
mod private {
pub trait Sealed {}
}
pub trait RegisterAddress: Copy + Clone + Debug + Sized + private::Sealed {
fn add_offset(self, offset: u8) -> Self;
}
#[track_caller]
fn assert_offset(offset: u8) {
assert!(
offset < NUM_REGISTERS as u8,
"the offset should be within the expected range: expected {offset} to be less than {NUM_REGISTERS}",
);
}
pub trait Backend: Send + private::Sealed {
type Address: RegisterAddress;
#[inline(always)]
unsafe fn read(&mut self, offset: u8) -> u8 {
assert_offset(offset);
let address_offset = offset
.checked_mul(u8::from(self.stride()))
.expect("offset * stride overflows u8; reduce stride");
let addr = self.base().add_offset(address_offset);
unsafe { self._read_register(addr) }
}
#[inline(always)]
unsafe fn write(&mut self, offset: u8, value: u8) {
assert_offset(offset);
let address_offset = offset
.checked_mul(u8::from(self.stride()))
.expect("offset * stride overflows u8; reduce stride");
let addr = self.base().add_offset(address_offset);
unsafe { self._write_register(addr, value) }
}
fn base(&self) -> Self::Address;
fn stride(&self) -> NonZeroU8;
#[doc(hidden)]
unsafe fn _read_register(&mut self, address: Self::Address) -> u8;
#[doc(hidden)]
unsafe fn _write_register(&mut self, address: Self::Address, value: u8);
}