![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
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).
| 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**.
| 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.
**pci_ecam_map** computes:
**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.
**pdev->cfg_size** set in **rt_pci_setup_device**:
Use **rt_pci_find_capability** only within valid size.
| 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.
| 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 |