Skip to main content

Mmio

Struct Mmio 

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

IO-mapped memory region.

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

use kernel::{
    bindings,
    ffi::c_void,
    io::{
        Io,
        IoKnownSize,
        Mmio,
        MmioRaw,
        PhysAddr,
    },
};
use core::ops::Deref;

// See also `pci::Bar` for a real example.
struct IoMem<const SIZE: usize>(MmioRaw<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 PhysAddr, SIZE) };
        if addr.is_null() {
            return Err(ENOMEM);
        }

        Ok(IoMem(MmioRaw::new(addr as usize, 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 *mut c_void); };
    }
}

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

   fn deref(&self) -> &Self::Target {
        // SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`.
        unsafe { Mmio::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> Mmio<SIZE>

Source

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

Converts an MmioRaw into an Mmio 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 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 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 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 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_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 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 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 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_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 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 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 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_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 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 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 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.

Trait Implementations§

Source§

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

Source§

fn addr(&self) -> usize

Returns the base address of this mapping.

Source§

fn maxsize(&self) -> usize

Returns the maximum size of this mapping.

Source§

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§

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§

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§

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§

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§

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§

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§

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§

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§

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§

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§

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§

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§

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§

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§

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§

fn io_addr<U>(&self, offset: usize) -> Result<usize>

Returns the absolute I/O address for a given offset, performing runtime bound checks.
Source§

impl<const SIZE: usize> IoKnownSize for Mmio<SIZE>

Source§

const MIN_SIZE: usize = SIZE

Minimum usable size of this region.
Source§

fn io_addr_assert<U>(&self, offset: usize) -> usize

Returns the absolute I/O address for a given offset, performing compile-time bound checks.
Source§

impl<const SIZE: usize> IoCapable<u16> for Mmio<SIZE>

Source§

impl<const SIZE: usize> IoCapable<u32> for Mmio<SIZE>

Source§

impl<const SIZE: usize> IoCapable<u64> for Mmio<SIZE>

Available on CONFIG_64BIT only.
Source§

impl<const SIZE: usize> IoCapable<u8> for Mmio<SIZE>

Auto Trait Implementations§

§

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

§

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

§

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

§

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

§

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

§

impl<const SIZE: usize> UnwindSafe for Mmio<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> Init<T> for T

Source§

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

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> PinInit<T> for T

Source§

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

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.
Source§

impl<T, U, const N: u32> TryIntoBounded<T, N> for U
where T: Integer, U: TryInto<T>,

Source§

fn try_into_bounded(self) -> Option<Bounded<T, N>>

Attempts to convert self into a Bounded using N bits. Read more