twizzler_driver/dma/
object.rs

1use std::sync::Mutex;
2
3use twizzler::object::{ObjID, Object};
4use twizzler_abi::{
5    kso::{KactionCmd, KactionFlags, KactionGenericCmd},
6    object::{MAX_SIZE, NULLPAGE_SIZE},
7    syscall::sys_kaction,
8};
9
10use super::{Access, DeviceSync, DmaOptions, DmaRegion, DmaSliceRegion};
11
12/// A handle for an object that can be used to perform DMA, and is most useful directly as a way to
13/// perform DMA operations on a specific object. For an allocator-like DMA interface, see
14/// [crate::dma::DmaPool].
15pub struct DmaObject {
16    obj: Object<()>,
17    pub(crate) releasable_pins: Mutex<Vec<u32>>,
18}
19
20impl DmaObject {
21    /// TODO: support
22    /// Create a [DmaSliceRegion] from the base of this object, where the region represents memory
23    /// of type `[T; len]`.
24    fn _slice_region<T: DeviceSync>(
25        &self,
26        len: usize,
27        access: Access,
28        options: DmaOptions,
29    ) -> DmaSliceRegion<T> {
30        let nr_bytes = core::mem::size_of::<T>()
31            .checked_mul(len)
32            .expect("Value of len too large");
33        assert!(nr_bytes < MAX_SIZE - NULLPAGE_SIZE * 2);
34        DmaSliceRegion::new(
35            core::mem::size_of::<T>() * len,
36            access,
37            options,
38            NULLPAGE_SIZE,
39            len,
40            None,
41        )
42    }
43
44    /// TODO: support
45    /// Create a [DmaRegion] from the base of this object, where the region represents memory
46    /// of type `T`.
47    fn _region<T: DeviceSync>(&self, access: Access, options: DmaOptions) -> DmaRegion<T> {
48        DmaRegion::new(
49            core::mem::size_of::<T>(),
50            access,
51            options,
52            NULLPAGE_SIZE,
53            None,
54        )
55    }
56
57    /// Get a reference to the object handle.
58    pub fn object(&self) -> &Object<()> {
59        &self.obj
60    }
61
62    /// Create a new [DmaObject] from an existing object handle.
63    pub fn new<T>(obj: Object<T>) -> Self {
64        Self {
65            obj: unsafe { obj.cast() },
66            releasable_pins: Mutex::new(Vec::new()),
67        }
68    }
69}
70
71pub(crate) fn release_pin(id: ObjID, token: u32) {
72    let _ = sys_kaction(
73        KactionCmd::Generic(KactionGenericCmd::ReleasePin),
74        Some(id),
75        token as u64,
76        0,
77        KactionFlags::empty(),
78    );
79}
80
81impl Drop for DmaObject {
82    fn drop(&mut self) {
83        let pins = self.releasable_pins.lock().unwrap();
84        for pin in &*pins {
85            release_pin(self.object().id(), *pin);
86        }
87    }
88}
89
90impl<T> From<Object<T>> for DmaObject {
91    fn from(obj: Object<T>) -> Self {
92        Self::new(obj)
93    }
94}