@@ -235,3 +235,125 @@ impl IoManager {
235235        } 
236236    } 
237237} 
238+ 
239+ #[ cfg( test) ]  
240+ mod  tests { 
241+     use  super :: * ; 
242+     use  std:: sync:: Mutex ; 
243+ 
244+     const  PIO_ADDRESS_SIZE :  u16  = 4 ; 
245+     const  PIO_ADDRESS_BASE :  u16  = 0x40 ; 
246+     const  MMIO_ADDRESS_SIZE :  u64  = 0x8765_4321 ; 
247+     const  MMIO_ADDRESS_BASE :  u64  = 0x1234_5678 ; 
248+     const  LEGACY_IRQ :  u32  = 4 ; 
249+     const  CONFIG_DATA :  u32  = 0x1234 ; 
250+ 
251+     struct  DummyDevice  { 
252+         config :  Mutex < u32 > , 
253+     } 
254+ 
255+     impl  DummyDevice  { 
256+         fn  new ( config :  u32 )  -> Self  { 
257+             DummyDevice  { 
258+                 config :  Mutex :: new ( config) , 
259+             } 
260+         } 
261+     } 
262+ 
263+     impl  DeviceIo  for  DummyDevice  { 
264+         fn  read ( & self ,  _addr :  IoAddress ,  data :  & mut  [ u8 ] )  { 
265+             if  data. len ( )  > 4  { 
266+                 return ; 
267+             } 
268+             for  ( idx,  iter)  in  data. iter_mut ( ) . enumerate ( )  { 
269+                 let  config = self . config . lock ( ) . expect ( "failed to acquire lock" ) ; 
270+                 * iter = ( * config >> ( idx *  8 )  &  0xff )  as  u8 ; 
271+             } 
272+         } 
273+ 
274+         fn  write ( & self ,  _addr :  IoAddress ,  data :  & [ u8 ] )  { 
275+             let  mut  config = self . config . lock ( ) . expect ( "failed to acquire lock" ) ; 
276+             * config = u32:: from ( data[ 0 ] )  &  0xff ; 
277+         } 
278+     } 
279+ 
280+     #[ test]  
281+     fn  test_register_unregister_device_io ( )  { 
282+         let  mut  io_mgr = IoManager :: new ( ) ; 
283+         let  dummy = DummyDevice :: new ( 0 ) ; 
284+         let  dum = Arc :: new ( dummy) ; 
285+ 
286+         let  mut  resource:  Vec < Resource >  = Vec :: new ( ) ; 
287+         let  mmio = Resource :: MmioAddressRange  { 
288+             base :  MMIO_ADDRESS_BASE , 
289+             size :  MMIO_ADDRESS_SIZE , 
290+         } ; 
291+         let  irq = Resource :: LegacyIrq ( LEGACY_IRQ ) ; 
292+ 
293+         resource. push ( mmio) ; 
294+         resource. push ( irq) ; 
295+ 
296+         assert ! ( io_mgr. register_device_io( dum. clone( ) ,  & resource) . is_ok( ) ) ; 
297+         assert ! ( io_mgr. unregister_device_io( & resource) . is_ok( ) ) 
298+     } 
299+ 
300+     #[ test]  
301+     fn  test_mmio_read_write ( )  { 
302+         let  mut  io_mgr:  IoManager  = Default :: default ( ) ; 
303+         let  dum = Arc :: new ( DummyDevice :: new ( CONFIG_DATA ) ) ; 
304+         let  mut  resource:  Vec < Resource >  = Vec :: new ( ) ; 
305+ 
306+         let  mmio = Resource :: MmioAddressRange  { 
307+             base :  MMIO_ADDRESS_BASE , 
308+             size :  MMIO_ADDRESS_SIZE , 
309+         } ; 
310+         resource. push ( mmio) ; 
311+         assert ! ( io_mgr. register_device_io( dum. clone( ) ,  & resource) . is_ok( ) ) ; 
312+ 
313+         let  mut  data = [ 0 ;  4 ] ; 
314+         assert ! ( io_mgr. mmio_read( MMIO_ADDRESS_BASE ,  & mut  data) . is_ok( ) ) ; 
315+         assert_eq ! ( data,  [ 0x34 ,  0x12 ,  0 ,  0 ] ) ; 
316+ 
317+         assert ! ( io_mgr
318+             . mmio_read( MMIO_ADDRESS_BASE  + MMIO_ADDRESS_SIZE ,  & mut  data) 
319+             . is_err( ) ) ; 
320+ 
321+         data = [ 0 ;  4 ] ; 
322+         assert ! ( io_mgr. mmio_write( MMIO_ADDRESS_BASE ,  & data) . is_ok( ) ) ; 
323+         assert_eq ! ( * dum. config. lock( ) . unwrap( ) ,  0 ) ; 
324+ 
325+         assert ! ( io_mgr
326+             . mmio_write( MMIO_ADDRESS_BASE  + MMIO_ADDRESS_SIZE ,  & data) 
327+             . is_err( ) ) ; 
328+     } 
329+ 
330+     #[ test]  
331+     fn  test_pio_read_write ( )  { 
332+         let  mut  io_mgr:  IoManager  = Default :: default ( ) ; 
333+         let  dum = Arc :: new ( DummyDevice :: new ( CONFIG_DATA ) ) ; 
334+         let  mut  resource:  Vec < Resource >  = Vec :: new ( ) ; 
335+ 
336+         let  pio = Resource :: PioAddressRange  { 
337+             base :  PIO_ADDRESS_BASE , 
338+             size :  PIO_ADDRESS_SIZE , 
339+         } ; 
340+         resource. push ( pio) ; 
341+         assert ! ( io_mgr. register_device_io( dum. clone( ) ,  & resource) . is_ok( ) ) ; 
342+ 
343+         let  mut  data = [ 0 ;  4 ] ; 
344+         assert ! ( io_mgr. pio_read( PIO_ADDRESS_BASE ,  & mut  data) . is_ok( ) ) ; 
345+         assert_eq ! ( data,  [ 0x34 ,  0x12 ,  0 ,  0 ] ) ; 
346+ 
347+         assert ! ( io_mgr
348+             . pio_read( PIO_ADDRESS_BASE  + PIO_ADDRESS_SIZE ,  & mut  data) 
349+             . is_err( ) ) ; 
350+ 
351+         data = [ 0 ;  4 ] ; 
352+         assert ! ( io_mgr. pio_write( PIO_ADDRESS_BASE ,  & data) . is_ok( ) ) ; 
353+         assert_eq ! ( * dum. config. lock( ) . unwrap( ) ,  0 ) ; 
354+ 
355+         assert ! ( io_mgr
356+             . pio_write( PIO_ADDRESS_BASE  + PIO_ADDRESS_SIZE ,  & data) 
357+             . is_err( ) ) ; 
358+     } 
359+ } 
0 commit comments