@@ -15,11 +15,11 @@ use crate::migrate::*;
1515use crate :: util:: regmap:: { Flags , RegMap } ;
1616
1717use lazy_static:: lazy_static;
18+ use strum:: IntoEnumIterator ;
1819
1920pub trait Device : Send + Sync + ' static {
2021 fn device_state ( & self ) -> & DeviceState ;
2122
22- #[ allow( unused_variables) ]
2323 fn bar_rw ( & self , bar : BarN , rwo : RWOp ) {
2424 match rwo {
2525 RWOp :: Read ( ro) => {
@@ -30,7 +30,6 @@ pub trait Device: Send + Sync + 'static {
3030 }
3131 }
3232 }
33- #[ allow( unused_variables) ]
3433 fn cfg_rw ( & self , region : u8 , rwo : RWOp ) {
3534 match rwo {
3635 RWOp :: Read ( ro) => {
@@ -46,6 +45,13 @@ pub trait Device: Send + Sync + 'static {
4645 fn interrupt_mode_change ( & self , mode : IntrMode ) { }
4746 #[ allow( unused_variables) ]
4847 fn msi_update ( & self , info : MsiUpdate ) { }
48+
49+ /// Notification that configuration of BAR(s) has changed, either due to
50+ /// writes to the BARs themselves, or an overall status change (via the
51+ /// Command register or a device reset).
52+ #[ allow( unused_variables) ]
53+ fn bar_update ( & self , bstate : BarState ) { }
54+
4955 // TODO
5056 // fn cap_read(&self);
5157 // fn cap_write(&self);
@@ -181,6 +187,18 @@ impl State {
181187 fn attached ( & self ) -> & bus:: Attachment {
182188 self . attach . as_ref ( ) . unwrap ( )
183189 }
190+ /// Is MMIO access decoding enabled?
191+ fn mmio_en ( & self ) -> bool {
192+ self . reg_command . contains ( RegCmd :: MMIO_EN )
193+ }
194+ /// Is PIO access decoding enabled?
195+ fn pio_en ( & self ) -> bool {
196+ self . reg_command . contains ( RegCmd :: IO_EN )
197+ }
198+ /// Given the device state, is decoding enabled for a specified [BarDefine]
199+ fn decoding_active ( & self , bar : & BarDefine ) -> bool {
200+ ( bar. is_pio ( ) && self . pio_en ( ) ) || ( bar. is_mmio ( ) && self . mmio_en ( ) )
201+ }
184202}
185203
186204pub ( super ) struct Cap {
@@ -375,15 +393,17 @@ impl DeviceState {
375393 StdCfgReg :: Bar ( bar) => {
376394 let val = wo. read_u32 ( ) ;
377395 let mut state = self . state . lock ( ) . unwrap ( ) ;
378- if let Some ( ( def, _old, new) ) = state. bars . reg_write ( * bar, val)
379- {
380- let pio_en = state. reg_command . contains ( RegCmd :: IO_EN ) ;
381- let mmio_en = state. reg_command . contains ( RegCmd :: MMIO_EN ) ;
382-
396+ if let Some ( res) = state. bars . reg_write ( * bar, val) {
383397 let attach = state. attached ( ) ;
384- if ( pio_en && def. is_pio ( ) ) || ( mmio_en && def. is_mmio ( ) ) {
385- attach. bar_unregister ( * bar) ;
386- attach. bar_register ( * bar, def, new) ;
398+ if state. decoding_active ( & res. def ) {
399+ attach. bar_unregister ( res. id ) ;
400+ attach. bar_register ( res. id , res. def , res. val_new ) ;
401+ dev. bar_update ( BarState {
402+ id : res. id ,
403+ def : res. def ,
404+ value : res. val_new ,
405+ decode_en : true ,
406+ } ) ;
387407 }
388408 }
389409 }
@@ -425,6 +445,8 @@ impl DeviceState {
425445
426446 // Update BAR registrations
427447 if diff. intersects ( RegCmd :: IO_EN | RegCmd :: MMIO_EN ) {
448+ let pio_en = val. contains ( RegCmd :: IO_EN ) ;
449+ let mmio_en = val. contains ( RegCmd :: MMIO_EN ) ;
428450 for n in BarN :: iter ( ) {
429451 let bar = state. bars . get ( n) ;
430452 if bar. is_none ( ) {
@@ -433,18 +455,30 @@ impl DeviceState {
433455 let ( def, v) = bar. unwrap ( ) ;
434456
435457 if diff. contains ( RegCmd :: IO_EN ) && def. is_pio ( ) {
436- if val . contains ( RegCmd :: IO_EN ) {
458+ if pio_en {
437459 attach. bar_register ( n, def, v) ;
438460 } else {
439461 attach. bar_unregister ( n) ;
440462 }
463+ dev. bar_update ( BarState {
464+ id : n,
465+ def,
466+ value : v,
467+ decode_en : pio_en,
468+ } ) ;
441469 }
442470 if diff. contains ( RegCmd :: MMIO_EN ) && def. is_mmio ( ) {
443- if val . contains ( RegCmd :: MMIO_EN ) {
471+ if mmio_en {
444472 attach. bar_register ( n, def, v) ;
445473 } else {
446474 attach. bar_unregister ( n) ;
447475 }
476+ dev. bar_update ( BarState {
477+ id : n,
478+ def,
479+ value : v,
480+ decode_en : mmio_en,
481+ } ) ;
448482 }
449483 }
450484 }
@@ -482,6 +516,17 @@ impl DeviceState {
482516 self . which_intr_mode ( & state)
483517 }
484518
519+ pub ( crate ) fn bar ( & self , id : BarN ) -> Option < BarState > {
520+ let state = self . state . lock ( ) . unwrap ( ) ;
521+ state. bars . get ( id) . map ( |( def, value) | {
522+ let decode_en = match def {
523+ BarDefine :: Pio ( _) => state. pio_en ( ) ,
524+ BarDefine :: Mmio ( _) | BarDefine :: Mmio64 ( _) => state. mmio_en ( ) ,
525+ } ;
526+ BarState { id, def, value, decode_en }
527+ } )
528+ }
529+
485530 fn cfg_cap_rw ( & self , dev : & dyn Device , id : & CfgReg , rwo : RWOp ) {
486531 match id {
487532 CfgReg :: CapId ( i) => {
@@ -608,10 +653,7 @@ impl DeviceState {
608653 let attach = inner. attached ( ) ;
609654 for n in BarN :: iter ( ) {
610655 if let Some ( ( def, addr) ) = inner. bars . get ( n) {
611- let pio_en = inner. reg_command . contains ( RegCmd :: IO_EN ) ;
612- let mmio_en = inner. reg_command . contains ( RegCmd :: MMIO_EN ) ;
613-
614- if ( pio_en && def. is_pio ( ) ) || ( mmio_en && def. is_mmio ( ) ) {
656+ if inner. decoding_active ( & def) {
615657 attach. bar_register ( n, def, addr) ;
616658 }
617659 }
@@ -1093,6 +1135,15 @@ impl Clone for MsixHdl {
10931135 }
10941136}
10951137
1138+ /// Describes the state of a BAR
1139+ pub struct BarState {
1140+ pub id : BarN ,
1141+ pub def : BarDefine ,
1142+ pub value : u64 ,
1143+ /// Is decoding for this BAR enabled in the device control?
1144+ pub decode_en : bool ,
1145+ }
1146+
10961147pub struct Builder {
10971148 ident : Ident ,
10981149 lintr_support : bool ,
0 commit comments