Struct Io

Source
pub struct Io<const SIZE: usize = 0>(/* private fields */);
Expand description

IO-mapped memory, starting at the base address @addr and spanning @maxlen bytes.

The creator (usually a subsystem / bus such as PCI) is responsible for creating the mapping, performing an additional region request etc.

§Invariant

addr is the start and maxsize the length of valid I/O mapped memory region of size maxsize.

§Examples


// See also [`pci::Bar`] for a real example.
struct IoMem<const SIZE: usize>(IoRaw<SIZE>);

impl<const SIZE: usize> IoMem<SIZE> {
    /// # Safety
    ///
    /// [`paddr`, `paddr` + `SIZE`) must be a valid MMIO region that is mappable into the CPUs
    /// virtual address space.
    unsafe fn new(paddr: usize) -> Result<Self>{
        // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
        // valid for `ioremap`.
        let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
        if addr.is_null() {
            return Err(ENOMEM);
        }

        Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
    }
}

impl<const SIZE: usize> Drop for IoMem<SIZE> {
    fn drop(&mut self) {
        // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
        unsafe { bindings::iounmap(self.0.addr() as _); };
    }
}

impl<const SIZE: usize> Deref for IoMem<SIZE> {
   type Target = Io<SIZE>;

   fn deref(&self) -> &Self::Target {
        // SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`.
        unsafe { Io::from_raw(&self.0) }
   }
}

// SAFETY: Invalid usage for example purposes.
let iomem = unsafe { IoMem::<{ core::mem::size_of::<u32>() }>::new(0xBAAAAAAD)? };
iomem.write32(0x42, 0x0);
assert!(iomem.try_write32(0x42, 0x0).is_ok());
assert!(iomem.try_write32(0x42, 0x4).is_err());

Implementations§

Source§

impl<const SIZE: usize> Io<SIZE>

Source

pub unsafe fn from_raw(raw: &IoRaw<SIZE>) -> &Self

Converts an IoRaw into an Io instance, providing the accessors to the MMIO mapping.

§Safety

Callers must ensure that addr is the start of a valid I/O mapped memory region of size maxsize.

Source

pub fn addr(&self) -> usize

Returns the base address of this mapping.

Source

pub fn maxsize(&self) -> usize

Returns the maximum size of this mapping.

Source

pub fn read8(&self, offset: usize) -> u8

Read IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_read8(&self, offset: usize) -> Result<u8>

Read IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn read16(&self, offset: usize) -> u16

Read IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_read16(&self, offset: usize) -> Result<u16>

Read IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn read32(&self, offset: usize) -> u32

Read IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_read32(&self, offset: usize) -> Result<u32>

Read IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn read64(&self, offset: usize) -> u64

Read IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_read64(&self, offset: usize) -> Result<u64>

Read IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn read8_relaxed(&self, offset: usize) -> u8

Read IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_read8_relaxed(&self, offset: usize) -> Result<u8>

Read IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn read16_relaxed(&self, offset: usize) -> u16

Read IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_read16_relaxed(&self, offset: usize) -> Result<u16>

Read IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn read32_relaxed(&self, offset: usize) -> u32

Read IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_read32_relaxed(&self, offset: usize) -> Result<u32>

Read IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn read64_relaxed(&self, offset: usize) -> u64

Read IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_read64_relaxed(&self, offset: usize) -> Result<u64>

Read IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn write8(&self, value: u8, offset: usize)

Write IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_write8(&self, value: u8, offset: usize) -> Result

Write IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn write16(&self, value: u16, offset: usize)

Write IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_write16(&self, value: u16, offset: usize) -> Result

Write IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn write32(&self, value: u32, offset: usize)

Write IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_write32(&self, value: u32, offset: usize) -> Result

Write IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn write64(&self, value: u64, offset: usize)

Write IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_write64(&self, value: u64, offset: usize) -> Result

Write IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn write8_relaxed(&self, value: u8, offset: usize)

Write IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_write8_relaxed(&self, value: u8, offset: usize) -> Result

Write IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn write16_relaxed(&self, value: u16, offset: usize)

Write IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_write16_relaxed(&self, value: u16, offset: usize) -> Result

Write IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn write32_relaxed(&self, value: u32, offset: usize)

Write IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_write32_relaxed(&self, value: u32, offset: usize) -> Result

Write IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Source

pub fn write64_relaxed(&self, value: u64, offset: usize)

Write IO data from a given offset known at compile time.

Bound checks are performed on compile time, hence if the offset is not known at compile time, the build will fail.

Source

pub fn try_write64_relaxed(&self, value: u64, offset: usize) -> Result

Write IO data from a given offset.

Bound checks are performed on runtime, it fails if the offset (plus the type size) is out of bounds.

Auto Trait Implementations§

§

impl<const SIZE: usize> Freeze for Io<SIZE>

§

impl<const SIZE: usize> RefUnwindSafe for Io<SIZE>

§

impl<const SIZE: usize> Send for Io<SIZE>

§

impl<const SIZE: usize> Sync for Io<SIZE>

§

impl<const SIZE: usize> Unpin for Io<SIZE>

§

impl<const SIZE: usize> UnwindSafe for Io<SIZE>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, E> Init<T, E> for T

Source§

unsafe fn __init(self, slot: *mut T) -> Result<(), E>

Initializes slot. Read more
Source§

fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
where F: FnOnce(&mut T) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, E> PinInit<T, E> for T

Source§

unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E>

Initializes slot. Read more
Source§

fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
where F: FnOnce(Pin<&mut T>) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.