@@ -266,6 +266,50 @@ impl<const SIZE: usize> IoMem<SIZE> {
266
266
) ;
267
267
}
268
268
269
+ /// Copy memory block from IO memory into buffer.
270
+ ///
271
+ /// # Examples
272
+ /// ```
273
+ /// use kernel::io_mem::{self, IoMem, Resource};
274
+ ///
275
+ /// fn test(res: Resource) -> Result {
276
+ /// // Create an io mem block of at least 100 bytes.
277
+ /// let mem = unsafe { IoMem::<100>::try_new(res) }?;
278
+ ///
279
+ /// let buffer: [i8; 32] = [0; 32];
280
+ ///
281
+ /// // Memcpy 16 bytes from offset 10 of io mem block into the buffer.
282
+ /// io_mem::try_memcpy_fromio(mem, buffer, 10, 16)?;
283
+ ///
284
+ /// Ok(())
285
+ /// ```
286
+ pub fn try_memcpy_fromio < const SIZE : usize > (
287
+ iomem : & IoMem < SIZE > ,
288
+ data : & mut [ i8 ] ,
289
+ offset : usize ,
290
+ count : usize ,
291
+ ) -> Result {
292
+ if !IoMem :: < SIZE > :: offset_ok :: < u8 > ( offset) {
293
+ return Err ( Error :: EINVAL ) ;
294
+ }
295
+
296
+ // Check if memory block can be copied from io region
297
+ // and also whether it will fit into data buffer.
298
+ if count > data. len ( ) || count > SIZE - offset {
299
+ return Err ( Error :: EINVAL ) ;
300
+ }
301
+
302
+ let ptr = iomem. ptr . wrapping_add ( offset) ;
303
+
304
+ // SAFETY:
305
+ // - The type invariants guarantee that `ptr` is a valid pointer.
306
+ // - The `offset_ok` check returns an error if `offset` would make the write
307
+ // go out of bounds (including the type size).
308
+ // - the sizes of from/to buffers are asserted whether they match `count` above.
309
+ unsafe { bindings:: memcpy_fromio ( data. as_mut_ptr ( ) as _ , ptr as _ , count. try_into ( ) ?) } ;
310
+ Ok ( ( ) )
311
+ }
312
+
269
313
impl < const SIZE : usize > Drop for IoMem < SIZE > {
270
314
fn drop ( & mut self ) {
271
315
// SAFETY: By the type invariant, `self.ptr` is a value returned by a previous successful
0 commit comments