twizzler_driver/device/
mmio.rs

1use twizzler::object::{ObjID, Object, RawObject};
2use twizzler_abi::{
3    device::{MmioInfo, SubObjectType, MMIO_OFFSET},
4    object::NULLPAGE_SIZE,
5};
6use twizzler_rt_abi::{object::MapFlags, Result};
7use volatile::access::{ReadOnly, ReadWrite};
8
9use super::Device;
10
11/// A handle to an MMIO subobject.
12pub struct MmioObject {
13    obj: Object<MmioInfo>,
14}
15
16impl MmioObject {
17    pub(crate) fn new(id: ObjID) -> Result<Self> {
18        Ok(Self {
19            obj: unsafe { Object::map_unchecked(id, MapFlags::READ | MapFlags::WRITE) }?,
20        })
21    }
22
23    /// Get a reference to an MMIO subobject's info data.
24    pub fn get_info(&self) -> &MmioInfo {
25        unsafe { self.obj.base_ptr::<MmioInfo>().as_ref().unwrap() }
26    }
27
28    /// Get the base of the memory mapped IO region.
29    /// # Safety
30    /// The type this returns is not verified in any way, so the caller must ensure that T is
31    /// the correct type for the underlying data.
32    pub unsafe fn get_mmio_offset<T>(
33        &self,
34        offset: usize,
35    ) -> volatile::VolatileRef<'_, T, ReadOnly> {
36        let ptr = self.obj.base_ptr::<u8>();
37        volatile::VolatileRef::from_ref(
38            (ptr.add(MMIO_OFFSET + offset).sub(NULLPAGE_SIZE) as *mut T)
39                .as_mut()
40                .unwrap(),
41        )
42    }
43
44    /// Get the base of the memory mapped IO region.
45    /// # Safety
46    /// The type this returns is not verified in any way, so the caller must ensure that T is
47    /// the correct type for the underlying data.
48    pub unsafe fn get_mmio_offset_mut<T>(
49        &self,
50        offset: usize,
51    ) -> volatile::VolatileRef<'_, T, ReadWrite> {
52        let ptr = self.obj.base_ptr::<u8>();
53        volatile::VolatileRef::from_mut_ref(
54            (ptr.add(MMIO_OFFSET + offset).sub(NULLPAGE_SIZE) as *mut T)
55                .as_mut()
56                .unwrap(),
57        )
58    }
59}
60
61impl Device {
62    /// Get a handle to a MMIO type subobject.
63    pub fn get_mmio(&self, idx: u8) -> Option<MmioObject> {
64        let id = self.get_subobj(SubObjectType::Mmio.into(), idx)?;
65        MmioObject::new(id).ok()
66    }
67}