RT-Thread RTOS
An open source embedded real-time operating system
PCI config space access

Config space (<tt>access.c</tt>, <tt>rt_pci_ops</tt>)

All enumeration and drivers reach hardware through **struct rt_pci_ops** on each **rt_pci_bus**.

Sources: **components/drivers/pci/access.c**, **ecam.c** (typical **ops** implementation).


<tt>struct rt_pci_ops</tt>

Callback Role
**map(bus, devfn, reg)** Optional MMIO pointer to config dword (ECAM)
**read(bus, devfn, reg, width, &value)** Config read
**write(bus, devfn, reg, width, value)** Config write
**add / remove** Bus hook (optional)

Host bridge sets **host_bridge->ops**; child buses inherit or use **child_ops**.


Locked accessors (<tt>access.c</tt>)

API Role
**rt_pci_bus_read_config_u8/u16/u32** Bus-level read
**rt_pci_bus_write_config_u8/u16/u32** Bus-level write
**rt_pci_bus_read_config_uxx** Width 1/2/4; uses **map** if implemented
**rt_pci_read_config_* (pdev, …)** Inline wrappers using **pdev->devfn**

Global **rt_pci_lock** serializes config unless **RT_PCI_LOCKLESS=y**.

On read error, typed helpers may return **~0** — check **rt_err_t** from **bus->ops->read** when critical.


ECAM fast path

**pci_ecam_map** computes:

win + (bus_offset | devfn_offset | reg_offset)

**rt_pci_bus_read_config_uxx** reads via **HWREG8/16/32** when **map** is non-NULL.

See PCI host controllers for **pci_generic_ecam_ops** and DesignWare **bus_shift** variants.


Config space size

**pdev->cfg_size** set in **rt_pci_setup_device**:

  • Standard 256 bytes, or extended 4 KiB if extended capability present.

Use **rt_pci_find_capability** only within valid size.


MMIO from BAR (not config)

API Role
**rt_pci_iomap(pdev, bar_idx)** **rt_ioremap(resource[bar].base, size)**

BAR CPU addresses come from enumeration — do not confuse with ECAM config window.


Pitfalls

Issue Mitigation
Config during IRQ Lock held by **access.c** — avoid long callbacks under lock
**map returns NULL** Fall back to **read/write** ops only
Wrong **devfn** on secondary bus Always use **pdev->devfn** on device's bus
Byte enables on IO Use correct width API for register layout

See also