@@ -184,4 +184,63 @@ impl EndpointHeader {
184184 pub fn header ( & self ) -> PciHeader {
185185 PciHeader ( self . 0 )
186186 }
187+
188+ /// Get the contents of a BAR in a given slot. Empty bars will return `None`.
189+ ///
190+ /// ### Note
191+ /// 64-bit memory BARs use two slots, so if one is decoded in e.g. slot #0, this method should not be called
192+ /// for slot #1
193+ pub fn bar ( & self , slot : u8 , access : & impl ConfigRegionAccess ) -> Option < Bar > {
194+ let offset = 0x10 + ( slot as u16 ) * 4 ;
195+ let bar = unsafe { access. read ( self . 0 , offset) } ;
196+
197+ /*
198+ * If bit 0 is `0`, the BAR is in memory. If it's `1`, it's in I/O.
199+ */
200+ if bar. get_bit ( 0 ) == false {
201+ let prefetchable = bar. get_bit ( 3 ) ;
202+ let address = bar. get_bits ( 4 ..32 ) << 4 ;
203+
204+ // TODO: if the bar is 64-bits, do we need to do this on both BARs?
205+ let size = unsafe {
206+ access. write ( self . 0 , offset, 0xffffffff ) ;
207+ let mut readback = access. read ( self . 0 , offset) ;
208+ access. write ( self . 0 , offset, address) ;
209+
210+ /*
211+ * If the entire readback value is zero, the BAR is not implemented, so we return `None`.
212+ */
213+ if readback == 0x0 {
214+ return None ;
215+ }
216+
217+ readback. set_bits ( 0 ..4 , 0 ) ;
218+ 1 << readback. trailing_zeros ( )
219+ } ;
220+
221+ match bar. get_bits ( 1 ..3 ) {
222+ 0b00 => Some ( Bar :: Memory32 { address, size, prefetchable } ) ,
223+ 0b10 => {
224+ let address = {
225+ let mut address = address as u64 ;
226+ // TODO: do we need to mask off the lower bits on this?
227+ address. set_bits ( 32 ..64 , unsafe { access. read ( self . 0 , offset + 4 ) } as u64 ) ;
228+ address
229+ } ;
230+ Some ( Bar :: Memory64 { address, size : size as u64 , prefetchable } )
231+ }
232+ // TODO: should we bother to return an error here?
233+ _ => panic ! ( "BAR Memory type is reserved!" ) ,
234+ }
235+ } else {
236+ Some ( Bar :: Io { port : bar. get_bits ( 2 ..32 ) } )
237+ }
238+ }
239+ }
240+
241+ #[ derive( Clone , Copy , Debug ) ]
242+ pub enum Bar {
243+ Memory32 { address : u32 , size : u32 , prefetchable : bool } ,
244+ Memory64 { address : u64 , size : u64 , prefetchable : bool } ,
245+ Io { port : u32 } ,
187246}
0 commit comments