pci - PCI bus scan + driver binding
Header: kernel/include/kernel/pci.h
Source: arch/i386/drivers/pci.c
Legacy PCI configuration-space access via I/O ports (PCI_ADDR_PORT 0xCF8 /
PCI_DATA_PORT 0xCFC). pci_init() enumerates the bus into a flat table
(pci_devices[], up to PCI_MAX_DEVICES = 128); pci_probe_all() then walks it
once and offers each device to the registered drivers. This is the bind point
for the NICs (networking), the SVGA II display backend
(video), and bus-master IDE DMA (ide).
Driver model
A pci_driver_t matches either by vendor/device id (match_class = 0,
device = PCI_MATCH_ANY to match any device of a vendor) or by
class/subclass (match_class = 1). pci_probe_all() calls each matched
driver’s probe(dev); returning 0 claims the device (sets dev->driver).
void pci_register_driver(const pci_driver_t *drv); /* register before pci_probe_all */
int pci_probe_all(void); /* returns devices bound */
Boot order: drivers register (ide_pci_register, virtio_net_register,
rtl8139_register, e1000_register, pcnet_register), then pci_init() scans,
then pci_probe_all() binds.
Config + BAR helpers (for bound drivers)
| Function | Role |
|---|---|
pci_read8/16/32, pci_write32(bus,dev,func,off,…) |
Raw config-space access. |
pci_enable_bus_master(d) |
Set the bus-master bit (DMA-capable devices). |
pci_bar_io(d,idx) |
I/O base (BAR & ~0x3). |
pci_bar_mem(d,idx) |
MMIO base (BAR & ~0xF). |
pci_class_name / pci_vendor_name / pci_device_name |
Human names for lspci / boot logs. |
pci_device_t
bus/dev/func, vendor_id, device_id, class_code, subclass, prog_if,
revision_id, header_type, irq_line, bar[6], and driver (the bound
driver’s name, NULL if unclaimed). The userspace lspci tool formats this
table.