twizzler_driver/device/
mmio.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use twizzler_abi::{
    device::{MmioInfo, SubObjectType, MMIO_OFFSET},
    object::NULLPAGE_SIZE,
};
use twizzler_object::{ObjID, Object, ObjectInitError, ObjectInitFlags, Protections};
use volatile::access::{ReadOnly, ReadWrite};

use super::Device;

/// A handle to an MMIO subobject.
pub struct MmioObject {
    obj: Object<MmioInfo>,
}

impl MmioObject {
    pub(crate) fn new(id: ObjID) -> Result<Self, ObjectInitError> {
        Ok(Self {
            obj: Object::init_id(
                id,
                Protections::READ | Protections::WRITE,
                ObjectInitFlags::empty(),
            )?,
        })
    }

    /// Get a reference to an MMIO subobject's info data.
    pub fn get_info(&self) -> &MmioInfo {
        self.obj.base().unwrap()
    }

    /// Get the base of the memory mapped IO region.
    /// # Safety
    /// The type this returns is not verified in any way, so the caller must ensure that T is
    /// the correct type for the underlying data.
    pub unsafe fn get_mmio_offset<T>(
        &self,
        offset: usize,
    ) -> volatile::VolatileRef<'_, T, ReadOnly> {
        let ptr = self.obj.base().unwrap() as *const MmioInfo as *const u8;
        volatile::VolatileRef::from_ref(
            (ptr.add(MMIO_OFFSET + offset).sub(NULLPAGE_SIZE) as *mut T)
                .as_mut()
                .unwrap(),
        )
    }

    /// Get the base of the memory mapped IO region.
    /// # Safety
    /// The type this returns is not verified in any way, so the caller must ensure that T is
    /// the correct type for the underlying data.
    pub unsafe fn get_mmio_offset_mut<T>(
        &self,
        offset: usize,
    ) -> volatile::VolatileRef<'_, T, ReadWrite> {
        let ptr = self.obj.base().unwrap() as *const MmioInfo as *const u8;
        volatile::VolatileRef::from_mut_ref(
            (ptr.add(MMIO_OFFSET + offset).sub(NULLPAGE_SIZE) as *mut T)
                .as_mut()
                .unwrap(),
        )
    }
}

impl Device {
    /// Get a handle to a MMIO type subobject.
    pub fn get_mmio(&self, idx: u8) -> Option<MmioObject> {
        let id = self.get_subobj(SubObjectType::Mmio.into(), idx)?;
        MmioObject::new(id).ok()
    }
}