66
77use crate :: {
88 bindings, build_assert, device,
9- device:: Bound ,
10- error:: code :: * ,
11- error :: Result ,
9+ device:: { Bound , Core } ,
10+ error:: { to_result , Result } ,
11+ prelude :: * ,
1212 transmute:: { AsBytes , FromBytes } ,
1313 types:: ARef ,
1414} ;
@@ -18,7 +18,142 @@ use crate::{
1818/// The [`dma::Device`](Device) trait should be implemented by bus specific device representations,
1919/// where the underlying bus is DMA capable, such as [`pci::Device`](::kernel::pci::Device) or
2020/// [`platform::Device`](::kernel::platform::Device).
21- pub trait Device : AsRef < device:: Device < Core > > { }
21+ pub trait Device : AsRef < device:: Device < Core > > {
22+ /// Set up the device's DMA streaming addressing capabilities.
23+ ///
24+ /// This method is usually called once from `probe()` as soon as the device capabilities are
25+ /// known.
26+ ///
27+ /// # Safety
28+ ///
29+ /// This method must not be called concurrently with any DMA allocation or mapping primitives,
30+ /// such as [`CoherentAllocation::alloc_attrs`].
31+ unsafe fn dma_set_mask ( & self , mask : DmaMask ) -> Result {
32+ // SAFETY:
33+ // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
34+ // - The safety requirement of this function guarantees that there are no concurrent calls
35+ // to DMA allocation and mapping primitives using this mask.
36+ to_result ( unsafe { bindings:: dma_set_mask ( self . as_ref ( ) . as_raw ( ) , mask. value ( ) ) } )
37+ }
38+
39+ /// Set up the device's DMA coherent addressing capabilities.
40+ ///
41+ /// This method is usually called once from `probe()` as soon as the device capabilities are
42+ /// known.
43+ ///
44+ /// # Safety
45+ ///
46+ /// This method must not be called concurrently with any DMA allocation or mapping primitives,
47+ /// such as [`CoherentAllocation::alloc_attrs`].
48+ unsafe fn dma_set_coherent_mask ( & self , mask : DmaMask ) -> Result {
49+ // SAFETY:
50+ // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
51+ // - The safety requirement of this function guarantees that there are no concurrent calls
52+ // to DMA allocation and mapping primitives using this mask.
53+ to_result ( unsafe { bindings:: dma_set_coherent_mask ( self . as_ref ( ) . as_raw ( ) , mask. value ( ) ) } )
54+ }
55+
56+ /// Set up the device's DMA addressing capabilities.
57+ ///
58+ /// This is a combination of [`Device::dma_set_mask`] and [`Device::dma_set_coherent_mask`].
59+ ///
60+ /// This method is usually called once from `probe()` as soon as the device capabilities are
61+ /// known.
62+ ///
63+ /// # Safety
64+ ///
65+ /// This method must not be called concurrently with any DMA allocation or mapping primitives,
66+ /// such as [`CoherentAllocation::alloc_attrs`].
67+ unsafe fn dma_set_mask_and_coherent ( & self , mask : DmaMask ) -> Result {
68+ // SAFETY:
69+ // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
70+ // - The safety requirement of this function guarantees that there are no concurrent calls
71+ // to DMA allocation and mapping primitives using this mask.
72+ to_result ( unsafe {
73+ bindings:: dma_set_mask_and_coherent ( self . as_ref ( ) . as_raw ( ) , mask. value ( ) )
74+ } )
75+ }
76+ }
77+
78+ /// A DMA mask that holds a bitmask with the lowest `n` bits set.
79+ ///
80+ /// Use [`DmaMask::new`] or [`DmaMask::try_new`] to construct a value. Values
81+ /// are guaranteed to never exceed the bit width of `u64`.
82+ ///
83+ /// This is the Rust equivalent of the C macro `DMA_BIT_MASK()`.
84+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
85+ pub struct DmaMask ( u64 ) ;
86+
87+ impl DmaMask {
88+ /// Constructs a `DmaMask` with the lowest `n` bits set to `1`.
89+ ///
90+ /// For `n <= 64`, sets exactly the lowest `n` bits.
91+ /// For `n > 64`, results in a build error.
92+ ///
93+ /// # Examples
94+ ///
95+ /// ```
96+ /// use kernel::dma::DmaMask;
97+ ///
98+ /// let mask0 = DmaMask::new::<0>();
99+ /// assert_eq!(mask0.value(), 0);
100+ ///
101+ /// let mask1 = DmaMask::new::<1>();
102+ /// assert_eq!(mask1.value(), 0b1);
103+ ///
104+ /// let mask64 = DmaMask::new::<64>();
105+ /// assert_eq!(mask64.value(), u64::MAX);
106+ ///
107+ /// // Build failure.
108+ /// // let mask_overflow = DmaMask::new::<100>();
109+ /// ```
110+ #[ inline]
111+ pub const fn new < const N : u32 > ( ) -> Self {
112+ let Ok ( mask) = Self :: try_new ( N ) else {
113+ build_error ! ( "Invalid DMA Mask." ) ;
114+ } ;
115+
116+ mask
117+ }
118+
119+ /// Constructs a `DmaMask` with the lowest `n` bits set to `1`.
120+ ///
121+ /// For `n <= 64`, sets exactly the lowest `n` bits.
122+ /// For `n > 64`, returns [`EINVAL`].
123+ ///
124+ /// # Examples
125+ ///
126+ /// ```
127+ /// use kernel::dma::DmaMask;
128+ ///
129+ /// let mask0 = DmaMask::try_new(0)?;
130+ /// assert_eq!(mask0.value(), 0);
131+ ///
132+ /// let mask1 = DmaMask::try_new(1)?;
133+ /// assert_eq!(mask1.value(), 0b1);
134+ ///
135+ /// let mask64 = DmaMask::try_new(64)?;
136+ /// assert_eq!(mask64.value(), u64::MAX);
137+ ///
138+ /// let mask_overflow = DmaMask::try_new(100);
139+ /// assert!(mask_overflow.is_err());
140+ /// # Ok::<(), Error>(())
141+ /// ```
142+ #[ inline]
143+ pub const fn try_new ( n : u32 ) -> Result < Self > {
144+ Ok ( Self ( match n {
145+ 0 => 0 ,
146+ 1 ..=64 => u64:: MAX >> ( 64 - n) ,
147+ _ => return Err ( EINVAL ) ,
148+ } ) )
149+ }
150+
151+ /// Returns the underlying `u64` bitmask value.
152+ #[ inline]
153+ pub const fn value ( & self ) -> u64 {
154+ self . 0
155+ }
156+ }
22157
23158/// Possible attributes associated with a DMA mapping.
24159///
0 commit comments