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