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