@@ -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