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