Skip to content

PCI

include/drivers/pci.h View source View on GitHub
struct pci_device {
    struct device  device;
    uint8_t        bus;
    uint8_t        dev;
    uint8_t        function;
    uint16_t       vendor_id;
    uint16_t       device_id;
    uint8_t        class_code;
    uint8_t        subclass;
    uint8_t        prog_if;
    uint8_t        revision;
};
struct pci_driver {
    struct device_driver  driver;
    uint8_t               class_code;
    uint8_t               subclass;
    uint8_t               prog_if;
    uint16_t              vendor_id;
};
struct pci_msix_table_entry {
    uint32_t  msg_addr_low;
    uint32_t  msg_addr_high;
    uint32_t  msg_data;
    uint32_t  vector_ctrl;
};
struct pci_msix_cap {
    uint8_t   cap_id;
    uint8_t   next_ptr;
    uint16_t  msg_ctl;
    uint32_t  table_offset_bir;
    uint32_t  pba_offset_bir;
};
union pci_command_reg {
    uint16_t  value;
    struct {
        uint16_t  io_space : 1;
        uint16_t  memory_space : 1;
        uint16_t  bus_master : 1;
        uint16_t  special_cycles : 1;
        uint16_t  mem_write_inv : 1;
        uint16_t  vga_snoop : 1;
        uint16_t  parity_error : 1;
        uint16_t  reserved0 : 1;
        uint16_t  serr_enable : 1;
        uint16_t  fast_back : 1;
        uint16_t  interrupt_disable : 1;
        uint16_t  reserved1 : 5;
    };
};
uint16_t pci_read_config16(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset);
uint8_t pci_read_config8(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset);
void pci_write_config16(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint16_t value);
uint32_t pci_config_address(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset);
uint32_t pci_read(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset);
uint16_t pci_read_word(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset);
uint8_t pci_read_byte(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset);
void pci_write(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint32_t value);
void pci_write_word(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint16_t value);
void pci_write_byte(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint8_t value);
const char * pci_class_name(uint8_t class_code, uint8_t subclass);
void pci_scan_devices(struct pci_device **devices_out, uint64_t *count_out);
uint32_t pci_read_bar(uint8_t bus, uint8_t device, uint8_t function, uint8_t bar_index);
void pci_enable_msix(uint8_t bus, uint8_t slot, uint8_t func);
void pci_enable_msix_on_core(uint8_t bus, uint8_t slot, uint8_t func, uint8_t vector, uint8_t core);
void pci_init_devices(struct pci_device *devices, uint64_t count);
uint8_t pci_find_capability(uint8_t bus, uint8_t slot, uint8_t func, uint8_t cap_id);
void pci_program_msix_entry(uint8_t bus, uint8_t slot, uint8_t func, uint32_t table_index, uint8_t vector, uint8_t apic_id);
#define PCI_CLASS_MASS_STORAGE 0x01
#define PCI_SUBCLASS_NVM 0x08
#define PCI_PROGIF_NVME 0x02
#define PCI_DEV_REGISTER(n, cc, sc, pi, vi, init) \
    LINKER_SECTION_OBJECT(struct pci_driver, pci_devices) \
    pci_device_##n = {.driver.name = #n, \
                      .class_code = cc, \
                      .subclass = sc, \
                      .prog_if = pi, \
                      .vendor_id = vi, \
                      .driver.probe = init};
#define PCI_BAR0 0x10
#define PCI_BAR1 0x14
#define PCI_BAR2 0x18
#define PCI_BAR3 0x1C
#define PCI_BAR4 0x20
#define PCI_BAR5 0x24
#define PCI_CAP_PTR 0x34
#define PCI_CAP_ID_MSIX 0x11
#define PCI_CONFIG_ADDRESS 0xCF8
#define PCI_CONFIG_DATA 0xCFC
#define PCI_INTERRUPT_LINE 0x3C
#define PCI_PROG_IF 0x09
#define pci_log(log_level, fmt, ...) \
    log(LOG_SITE(pci), LOG_HANDLE(pci), log_level, fmt, ##__VA_ARGS__)