/// An IO request for a specific device and resource. pubstruct IoRequest<'a> {
device: &'a Device<Bound>,
resource: &'a Resource,
}
impl<'a> IoRequest<'a> { /// Creates a new [`IoRequest`] instance. /// /// # Safety /// /// Callers must ensure that `resource` is valid for `device` during the /// lifetime `'a`. pub(crate) unsafefn new(device: &'a Device<Bound>, resource: &'n>a Resource) -> Self {
IoRequest { device, resource }
}
/// Maps an [`IoRequest`] where the size is known at compile time. /// /// This uses the [`ioremap()`] C API. /// /// [`ioremap()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device /// /// # Examples /// /// The following example uses a [`kernel::platform::Device`] for /// illustration purposes. /// /// ```no_run /// use kernel::{bindings, c_str, platform, of, device::Core}; /// struct SampleDriver; /// /// impl platform::Driver for SampleDriver { /// # type IdInfo = (); /// /// fn probe( /// pdev: &platform::Device<Core>, /// info: Option<&Self::IdInfo>, /// ) -> Result<Pin<KBox<Self>>> { /// let offset = 0; // Some offset. /// /// // If the size is known at compile time, use [`Self::iomap_sized`]. /// // /// // No runtime checks will apply when reading and writing. /// let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; /// let iomem = request.iomap_sized::<42>(); /// let iomem = KBox::pin_init(iomem, GFP_KERNEL)?; /// /// let io = iomem.access(pdev.as_ref())?; /// /// // Read and write a 32-bit value at `offset`. /// let data = io.read32_relaxed(offset); /// /// io.write32_relaxed(data, offset); /// /// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) /// } /// } /// ``` pubfn iomap_sized<const SIZE: usize>(self) -> impl PinInit<Devres<IoMem<SIZE>>, Error> + 'a {
IoMem::new(self)
}
/// Same as [`Self::iomap_sized`] but with exclusive access to the /// underlying region. /// /// This uses the [`ioremap()`] C API. /// /// [`ioremap()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device pubfn iomap_exclusive_sized<const SIZE: usize>( self,
) -> impl PinInit<Devres<ExclusiveIoMem<SIZE>>, Error> + 'a {
ExclusiveIoMem::new(self)
}
/// Maps an [`IoRequest`] where the size is not known at compile time, /// /// This uses the [`ioremap()`] C API. /// /// [`ioremap()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device /// /// # Examples /// /// The following example uses a [`kernel::platform::Device`] for /// illustration purposes. /// /// ```no_run /// use kernel::{bindings, c_str, platform, of, device::Core}; /// struct SampleDriver; /// /// impl platform::Driver for SampleDriver { /// # type IdInfo = (); /// /// fn probe( /// pdev: &platform::Device<Core>, /// info: Option<&Self::IdInfo>, /// ) -> Result<Pin<KBox<Self>>> { /// let offset = 0; // Some offset. /// /// // Unlike [`Self::iomap_sized`], here the size of the memory region /// // is not known at compile time, so only the `try_read*` and `try_write*` /// // family of functions should be used, leading to runtime checks on every /// // access. /// let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; /// let iomem = request.iomap(); /// let iomem = KBox::pin_init(iomem, GFP_KERNEL)?; /// /// let io = iomem.access(pdev.as_ref())?; /// /// let data = io.try_read32_relaxed(offset)?; /// /// io.try_write32_relaxed(data, offset)?; /// /// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) /// } /// } /// ``` pubfn iomap(self) -> impl PinInit<Devres<IoMem<0>>, Error> + 'a { Self::iomap_sized::<0>(self)
}
/// Same as [`Self::iomap`] but with exclusive access to the underlying /// region. pubfn iomap_exclusive(self) -> impl PinInit<Devres<ExclusiveIoMem<0>>, Error> + 'a { Self::iomap_exclusive_sized::<0>(self)
}
}
/// An exclusive memory-mapped IO region. /// /// # Invariants /// /// - [`ExclusiveIoMem`] has exclusive access to the underlying [`IoMem`]. pubstruct ExclusiveIoMem<const SIZE: usize> { /// The underlying `IoMem` instance.
iomem: IoMem<SIZE>,
/// The region abstraction. This represents exclusive access to the /// range represented by the underlying `iomem`. /// /// This field is needed for ownership of the region.
_region: Region,
}
impl<const SIZE: usize> ExclusiveIoMem<SIZE> { /// Creates a new `ExclusiveIoMem` instance. fn ioremap(resource: &Resource) -> Result<Self> { let start = resource.start(); let size = resource.size(); let name = resource.name().unwrap_or(c_str!(""));
let region = resource
.request_region(
start,
size,
name.to_cstring()?,
io::resource::Flags::IORESOURCE_MEM,
)
.ok_or(EBUSY)?;
let iomem = IoMem::ioremap(resource)?;
let iomem = ExclusiveIoMem {
iomem,
_region: region,
};
Ok(iomem)
}
/// Creates a new `ExclusiveIoMem` instance from a previously acquired [`IoRequest`]. pubfn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> + 'a { let dev = io_request.device; let res = io_request.resource;
Devres::new(dev, Self::ioremap(res))
}
}
impl<const SIZE: usize> Deref for ExclusiveIoMem<SIZE> { type Target = Io<SIZE>;
/// A generic memory-mapped IO region. /// /// Accesses to the underlying region is checked either at compile time, if the /// region's size is known at that point, or at runtime otherwise. /// /// # Invariants /// /// [`IoMem`] always holds an [`IoRaw`] instance that holds a valid pointer to the /// start of the I/O memory mapped region. pubstruct IoMem<const SIZE: usize = 0> {
io: IoRaw<SIZE>,
}
impl<const SIZE: usize> IoMem<SIZE> { fn ioremap(resource: &Resource) -> Result<Self> { // Note: Some ioremap() implementations use types that depend on the CPU // word width rather than the bus address width. // // TODO: Properly address this in the C code to avoid this `try_into`. let size = resource.size().try_into()?; if size == 0 { return Err(EINVAL);
}
let res_start = resource.start();
let addr = if resource
.flags()
.contains(io::resource::Flags::IORESOURCE_MEM_NONPOSTED)
{ // SAFETY: // - `res_start` and `size` are read from a presumably valid `struct resource`. // - `size` is known not to be zero at this point. unsafe { bindings::ioremap_np(res_start, size) }
} else { // SAFETY: // - `res_start` and `size` are read from a presumably valid `struct resource`. // - `size` is known not to be zero at this point. unsafe { bindings::ioremap(res_start, size) }
};
if addr.is_null() { return Err(ENOMEM);
}
let io = IoRaw::new(addr as usize, size)?; let io = IoMem { io };
Ok(io)
}
/// Creates a new `IoMem` instance from a previously acquired [`IoRequest`]. pubfn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> + 'a { let dev = io_request.device; let res = io_request.resource;
Devres::new(dev, Self::ioremap(res))
}
}
impl<const SIZE: usize> Drop for IoMem<SIZE> { fn drop(&mutself) { // SAFETY: Safe as by the invariant of `Io`. unsafe { bindings::iounmap(self.io.addr() as *mut c_void) }
}
}
impl<const SIZE: usize> Deref for IoMem<SIZE> { type Target = Io<SIZE>;
fn deref(&self) -> &Self::Target { // SAFETY: Safe as by the invariant of `IoMem`. unsafe { Io::from_raw(&self.io) }
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-20)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.