@@ -244,6 +244,74 @@ pub mod attrs {
244244 pub const DMA_ATTR_PRIVILEGED : Attrs = Attrs ( bindings:: DMA_ATTR_PRIVILEGED ) ;
245245}
246246
247+ /// DMA data direction.
248+ ///
249+ /// Corresponds to the C [`enum dma_data_direction`].
250+ ///
251+ /// [`enum dma_data_direction`]: srctree/include/linux/dma-direction.h
252+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
253+ #[ repr( u32 ) ]
254+ pub enum DataDirection {
255+ /// The DMA mapping is for bidirectional data transfer.
256+ ///
257+ /// This is used when the buffer can be both read from and written to by the device.
258+ /// The cache for the corresponding memory region is both flushed and invalidated.
259+ Bidirectional = Self :: const_cast ( bindings:: dma_data_direction_DMA_BIDIRECTIONAL) ,
260+
261+ /// The DMA mapping is for data transfer from memory to the device (write).
262+ ///
263+ /// The CPU has prepared data in the buffer, and the device will read it.
264+ /// The cache for the corresponding memory region is flushed before device access.
265+ ToDevice = Self :: const_cast ( bindings:: dma_data_direction_DMA_TO_DEVICE) ,
266+
267+ /// The DMA mapping is for data transfer from the device to memory (read).
268+ ///
269+ /// The device will write data into the buffer for the CPU to read.
270+ /// The cache for the corresponding memory region is invalidated before CPU access.
271+ FromDevice = Self :: const_cast ( bindings:: dma_data_direction_DMA_FROM_DEVICE) ,
272+
273+ /// The DMA mapping is not for data transfer.
274+ ///
275+ /// This is primarily for debugging purposes. With this direction, the DMA mapping API
276+ /// will not perform any cache coherency operations.
277+ None = Self :: const_cast ( bindings:: dma_data_direction_DMA_NONE) ,
278+ }
279+
280+ impl DataDirection {
281+ /// Casts the bindgen-generated enum type to a `u32` at compile time.
282+ ///
283+ /// This function will cause a compile-time error if the underlying value of the
284+ /// C enum is out of bounds for `u32`.
285+ const fn const_cast ( val : bindings:: dma_data_direction ) -> u32 {
286+ // CAST: The C standard allows compilers to choose different integer types for enums.
287+ // To safely check the value, we cast it to a wide signed integer type (`i128`)
288+ // which can hold any standard C integer enum type without truncation.
289+ let wide_val = val as i128 ;
290+
291+ // Check if the value is outside the valid range for the target type `u32`.
292+ // CAST: `u32::MAX` is cast to `i128` to match the type of `wide_val` for the comparison.
293+ if wide_val < 0 || wide_val > u32:: MAX as i128 {
294+ // Trigger a compile-time error in a const context.
295+ build_error ! ( "C enum value is out of bounds for the target type `u32`." ) ;
296+ }
297+
298+ // CAST: This cast is valid because the check above guarantees that `wide_val`
299+ // is within the representable range of `u32`.
300+ wide_val as u32
301+ }
302+ }
303+
304+ impl From < DataDirection > for bindings:: dma_data_direction {
305+ /// Returns the raw representation of [`enum dma_data_direction`].
306+ fn from ( direction : DataDirection ) -> Self {
307+ // CAST: `direction as u32` gets the underlying representation of our `#[repr(u32)]` enum.
308+ // The subsequent cast to `Self` (the bindgen type) assumes the C enum is compatible
309+ // with the enum variants of `DataDirection`, which is a valid assumption given our
310+ // compile-time checks.
311+ direction as u32 as Self
312+ }
313+ }
314+
247315/// An abstraction of the `dma_alloc_coherent` API.
248316///
249317/// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map
0 commit comments