Skip to main content

PciConfigSpace

Trait PciConfigSpace 

Source
pub trait PciConfigSpace: ChipsetDevice {
    // Required methods
    fn pci_cfg_read(
        &mut self,
        byte_offset: u16,
        value: ByteEnabledDwordRead<'_>,
    ) -> IoResult;
    fn pci_cfg_write(
        &mut self,
        byte_offset: u16,
        value: ByteEnabledDwordWrite,
    ) -> IoResult;

    // Provided methods
    fn pci_cfg_read_with_routing(
        &mut self,
        access_type: PciConfigAccessType,
        address: PciConfigAddress,
        value: ByteEnabledDwordRead<'_>,
    ) -> IoResult { ... }
    fn pci_cfg_write_with_routing(
        &mut self,
        access_type: PciConfigAccessType,
        address: PciConfigAddress,
        value: ByteEnabledDwordWrite,
    ) -> IoResult { ... }
    fn suggested_bdf(&mut self) -> Option<(u8, u8, u8)> { ... }
}
Expand description

Implemented by devices which have a PCI config space.

Required Methods§

Source

fn pci_cfg_read( &mut self, byte_offset: u16, value: ByteEnabledDwordRead<'_>, ) -> IoResult

Dispatch a PCI config space read to the device with the given address.

This function serves as a shorthand that single-function endpoint devices can implement directly. More advanced routing components (switches, bridges) and multi-function devices should instead implement pci_cfg_read_with_routing for full routing context.

byte_offset is guaranteed to be aligned to a 4-byte boundary.

Source

fn pci_cfg_write( &mut self, byte_offset: u16, value: ByteEnabledDwordWrite, ) -> IoResult

Dispatch a PCI config space write to the device with the given address.

This function serves as a shorthand that single-function endpoint devices can implement directly. More advanced routing components (switches, bridges) and multi-function devices should instead implement pci_cfg_write_with_routing for full routing context.

byte_offset is guaranteed to be aligned to a 4-byte boundary.

Provided Methods§

Source

fn pci_cfg_read_with_routing( &mut self, access_type: PciConfigAccessType, address: PciConfigAddress, value: ByteEnabledDwordRead<'_>, ) -> IoResult

Dispatch a PCI configuration space read with full routing context.

This method receives configuration space read with the access type, target bus, target device/function number, and DWORD offset.

The default implementation dispatches type 0 access to function 0 to pci_cfg_read and returns all-1s for other functions (the standard “no device present” response). Routing components (switches, bridges) and multi-function devices should override this method.

§Parameters
  • access_type: The type of PCI configuration space access (Type 0 or Type 1)
  • address: The target address (BDF + offset) being accessed
  • value: Byte-enabled DWORD value to receive the read
Source

fn pci_cfg_write_with_routing( &mut self, access_type: PciConfigAccessType, address: PciConfigAddress, value: ByteEnabledDwordWrite, ) -> IoResult

Dispatch a PCI configuration space write with full routing context.

This method receives configuration space write with the access type, target bus, target device/function number, and DWORD offset.

The default implementation dispatches type 0 access to function 0 to pci_cfg_write and silently drops writes to other functions. Routing components (switches, bridges) and multi-function devices should override this method.

§Parameters
  • access_type: The type of PCI configuration space access (Type 0 or Type 1)
  • address: The target address (BDF + offset) being accessed
  • value: Byte-enabled DWORD value to write
Source

fn suggested_bdf(&mut self) -> Option<(u8, u8, u8)>

Check if the device has a suggested (bus, device, function) it expects to be located at.

The term “suggested” is important here, as it’s important to note that one of the major selling points of PCI was that PCI devices shouldn’t need to care about about what PCI address they are initialized at. i.e: on a physical machine, it shouldn’t matter that your fancy GTX 4090 is plugged into the first vs. second PCI slot.

..that said, there are some instances where it makes sense for an emulated device to declare its suggested PCI address:

  1. Devices that emulate bespoke PCI devices part of a particular system’s chipset.
  • e.g: the PIIX4 chipset includes several bespoke PCI devices that are required to have specific PCI addresses. While it would be possible to relocate them to a different address, it may break OSes that assume they exist at those spec-declared addresses.
  1. Multi-function PCI devices
  • In an unfortunate case of inverted responsibilities, there is a single bit in the PCI configuration space’s Header register that denotes if a particular PCI card includes multiple functions.
  • Since multi-function devices are pretty rare, ChipsetDevice opted to model each function as its own device, which in turn implies that in order to correctly init a multi-function PCI card, the ChipsetDevice with function 0 must report if there are other functions at the same bus and device.

Implementors§