PCI Bus Operations

Relevant source files

This document covers the PCI (Peripheral Component Interconnect) bus operations provided by the axdriver_pci crate. This crate serves as a bridge between the ArceOS driver framework and PCI device discovery and management functionality. It provides the foundational infrastructure for PCI device enumeration, configuration space access, and memory-mapped I/O (MMIO) region allocation needed by hardware device drivers.

For information about specific device driver implementations that use PCI operations, see Network Drivers and Block Storage Drivers. For VirtIO device integration over PCI transport, see VirtIO Integration.

Architecture Overview

The PCI bus operations layer sits between the hardware abstraction and device-specific drivers, providing standardized access to PCI configuration and memory management.

PCI Integration Architecture

flowchart TD
subgraph subGraph3["Device Drivers"]
    NETDRIVERS["Network Drivers(ixgbe, VirtIO-Net)"]
    BLOCKDRIVERS["Block Drivers(VirtIO-Block)"]
    DISPLAYDRIVERS["Display Drivers(VirtIO-GPU)"]
end
subgraph subGraph2["virtio-drivers Foundation"]
    VIRTIOPCI["virtio_drivers::transport::pci::bus"]
    PCITYPES["PCI Types & Operations"]
end
subgraph subGraph1["axdriver_pci Layer"]
    PCIROOT["PciRootBus enumeration"]
    DEVICEFUNC["DeviceFunctionDevice access"]
    ALLOCATOR["PciRangeAllocatorMMIO allocation"]
    BARINFO["BarInfoMemory region info"]
end
subgraph subGraph0["Hardware Layer"]
    PCIHW["PCI Hardware Bus"]
    DEVICES["PCI Devices(Network, Storage, Display)"]
end

ALLOCATOR --> BLOCKDRIVERS
ALLOCATOR --> DISPLAYDRIVERS
ALLOCATOR --> NETDRIVERS
DEVICEFUNC --> BLOCKDRIVERS
DEVICEFUNC --> DISPLAYDRIVERS
DEVICEFUNC --> NETDRIVERS
DEVICES --> VIRTIOPCI
PCIHW --> VIRTIOPCI
PCIROOT --> BLOCKDRIVERS
PCIROOT --> DISPLAYDRIVERS
PCIROOT --> NETDRIVERS
PCITYPES --> ALLOCATOR
VIRTIOPCI --> BARINFO
VIRTIOPCI --> DEVICEFUNC
VIRTIOPCI --> PCIROOT

Sources: axdriver_pci/src/lib.rs(L1 - L14)  axdriver_pci/Cargo.toml(L14 - L15) 

Core PCI Types and Operations

The axdriver_pci crate primarily re-exports essential PCI types from the virtio-drivers crate, providing a consistent interface for PCI device management across the ArceOS ecosystem.

Device Discovery and Access

TypePurposeKey Operations
PciRootRoot PCI bus controllerDevice enumeration and scanning
DeviceFunctionIndividual PCI device/functionConfiguration space access
DeviceFunctionInfoDevice metadataVendor ID, device ID, class codes
CapabilityInfoPCI capabilitiesExtended feature discovery

Memory and I/O Management

TypePurposeUsage
BarInfoBase Address Register infoMemory region mapping
MemoryBarTypeMemory BAR classification32-bit vs 64-bit addressing
CommandPCI command registerBus mastering, memory enable
StatusPCI status registerCapability support, error status

PCI Type Relationships

flowchart TD
subgraph Configuration["Configuration"]
    COMMAND["Command"]
    STATUS["Status"]
    CAPINFO["CapabilityInfo"]
end
subgraph subGraph1["Memory Management"]
    BARINFO["BarInfo"]
    MEMBARTYPE["MemoryBarType"]
    ALLOCATOR["PciRangeAllocator"]
end
subgraph subGraph0["Device Discovery"]
    PCIROOT["PciRoot"]
    DEVICEFUNC["DeviceFunction"]
    DEVINFO["DeviceFunctionInfo"]
end

BARINFO --> ALLOCATOR
BARINFO --> MEMBARTYPE
DEVICEFUNC --> BARINFO
DEVICEFUNC --> CAPINFO
DEVICEFUNC --> COMMAND
DEVICEFUNC --> DEVINFO
DEVICEFUNC --> STATUS
PCIROOT --> DEVICEFUNC

Sources: axdriver_pci/src/lib.rs(L11 - L14) 

MMIO Range Allocation

The PciRangeAllocator provides a custom memory allocation system specifically designed for PCI Base Address Register (BAR) allocation. This allocator ensures proper alignment and prevents memory region conflicts.

Allocator Structure

The PciRangeAllocator maintains a simple linear allocation strategy:

pub struct PciRangeAllocator {
    _start: u64,    // Base address of allocatable region
    end: u64,       // End boundary of allocatable region  
    current: u64,   // Current allocation pointer
}

Allocation Algorithm

The allocator implements power-of-2 aligned allocation with the following constraints:

PropertyRequirementRationale
Size alignmentMust be power of 2PCI BAR size requirements
Address alignmentMultiple of sizeHardware addressing constraints
Boundary checkingWithin allocated rangeMemory safety

MMIO Allocation Flow

flowchart TD
START["alloc(size: u64)"]
CHECK_POW2["size.is_power_of_two()"]
ALIGN["ret = align_up(current, size)"]
CHECK_BOUNDS["ret + size > end?"]
UPDATE["current = ret + size"]
RETURN_ADDR["return Some(ret)"]
RETURN_NONE["return None"]

ALIGN --> CHECK_BOUNDS
CHECK_BOUNDS --> RETURN_NONE
CHECK_BOUNDS --> UPDATE
CHECK_POW2 --> ALIGN
CHECK_POW2 --> RETURN_NONE
START --> CHECK_POW2
UPDATE --> RETURN_ADDR

Usage Example

The typical allocation pattern for PCI BARs:

  1. Create allocator with memory range: PciRangeAllocator::new(base, size)
  2. Request aligned memory: allocator.alloc(bar_size)
  3. Map returned address to device BAR

Sources: axdriver_pci/src/lib.rs(L17 - L53) 

Integration with Device Drivers

The PCI operations integrate with device drivers through standardized patterns for device discovery, configuration, and memory mapping.

Typical Driver Integration Pattern

sequenceDiagram
    participant DeviceDriver as "Device Driver"
    participant PciRoot as "PciRoot"
    participant DeviceFunction as "DeviceFunction"
    participant PciRangeAllocator as "PciRangeAllocator"

    DeviceDriver ->> PciRoot: Enumerate devices
    PciRoot ->> DeviceDriver: Found matching device
    DeviceDriver ->> DeviceFunction: Read configuration
    DeviceFunction ->> DeviceDriver: Device info & BARs
    DeviceDriver ->> PciRangeAllocator: Request MMIO region
    PciRangeAllocator ->> DeviceDriver: Allocated address
    DeviceDriver ->> DeviceFunction: Configure BAR mapping
    DeviceFunction ->> DeviceDriver: Device ready

Error Handling

PCI operations use the PciError type for consistent error reporting across device initialization and configuration operations.

Sources: axdriver_pci/src/lib.rs(L11) 

Dependencies and External Integration

The axdriver_pci crate builds upon the virtio-drivers crate version 0.7.4, specifically leveraging its PCI transport layer. This dependency provides:

  • Low-level PCI configuration space access
  • Standard PCI type definitions
  • Cross-platform PCI hardware abstraction

The integration allows ArceOS drivers to benefit from the mature PCI implementation in virtio-drivers while maintaining the consistent ArceOS driver interface patterns.

Sources: axdriver_pci/Cargo.toml(L15)  axdriver_pci/src/lib.rs(L3 - L7)