twizzler_driver/dma/
object.rs

1use std::sync::{Arc, Mutex};
2
3use twizzler::object::{ObjID, Object, RawObject};
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].
15#[derive(Clone)]
16pub struct DmaObject {
17    obj: Object<()>,
18    pub(crate) releasable_pins: Arc<Mutex<Vec<u32>>>,
19}
20
21impl DmaObject {
22    /// Create a [DmaSliceRegion] from the base of this object, where the region represents memory
23    /// of type `[T; len]`.
24    pub fn slice_region<T: DeviceSync>(
25        &self,
26        offset: usize,
27        len: usize,
28        access: Access,
29        options: DmaOptions,
30    ) -> DmaSliceRegion<T> {
31        let nr_bytes = core::mem::size_of::<T>()
32            .checked_mul(len)
33            .expect("Value of len too large");
34        assert!(nr_bytes + offset < MAX_SIZE - NULLPAGE_SIZE * 2);
35        let virt = self.obj.lea_mut(offset, nr_bytes).unwrap();
36        DmaSliceRegion::new_with_virt(
37            core::mem::size_of::<T>() * len,
38            access,
39            options,
40            offset,
41            len,
42            virt,
43            self.clone(),
44        )
45    }
46
47    /// Create a [DmaRegion] from the base of this object, where the region represents memory
48    /// of type `T`.
49    fn _region<T: DeviceSync>(&self, access: Access, options: DmaOptions) -> DmaRegion<T> {
50        DmaRegion::new(
51            core::mem::size_of::<T>(),
52            access,
53            options,
54            NULLPAGE_SIZE,
55            None,
56        )
57    }
58
59    /// Get a reference to the object handle.
60    pub fn object(&self) -> &Object<()> {
61        &self.obj
62    }
63
64    /// Create a new [DmaObject] from an existing object handle.
65    pub fn new<T>(obj: Object<T>) -> Self {
66        Self {
67            obj: unsafe { obj.cast() },
68            releasable_pins: Arc::new(Mutex::new(Vec::new())),
69        }
70    }
71}
72
73pub(crate) fn release_pin(id: ObjID, token: u32) {
74    let _ = sys_kaction(
75        KactionCmd::Generic(KactionGenericCmd::ReleasePin),
76        Some(id),
77        token as u64,
78        0,
79        KactionFlags::empty(),
80    );
81}
82
83impl Drop for DmaObject {
84    fn drop(&mut self) {
85        let pins = self.releasable_pins.lock().unwrap();
86        for pin in &*pins {
87            release_pin(self.object().id(), *pin);
88        }
89    }
90}
91
92impl<T> From<Object<T>> for DmaObject {
93    fn from(obj: Object<T>) -> Self {
94        Self::new(obj)
95    }
96}