diff --git a/headers/os/drivers/PCI.h b/headers/os/drivers/PCI.h index bff025f708..1210349995 100644 --- a/headers/os/drivers/PCI.h +++ b/headers/os/drivers/PCI.h @@ -131,18 +131,18 @@ struct pci_module_info { pci_info *info /* caller-supplied buffer for info */ ); uint32 (*read_pci_config) ( - uchar bus, /* bus number */ - uchar device, /* device # on bus */ - uchar function, /* function # in device */ - uchar offset, /* offset in configuration space */ - uchar size /* # bytes to read (1, 2 or 4) */ + uint8 bus, /* bus number */ + uint8 device, /* device # on bus */ + uint8 function, /* function # in device */ + uint16 offset, /* offset in configuration space */ + uint8 size /* # bytes to read (1, 2 or 4) */ ); void (*write_pci_config) ( - uchar bus, /* bus number */ - uchar device, /* device # on bus */ - uchar function, /* function # in device */ - uchar offset, /* offset in configuration space */ - uchar size, /* # bytes to write (1, 2 or 4) */ + uint8 bus, /* bus number */ + uint8 device, /* device # on bus */ + uint8 function, /* function # in device */ + uint16 offset, /* offset in configuration space */ + uint8 size, /* # bytes to write (1, 2 or 4) */ uint32 value /* value to write */ ); @@ -174,6 +174,14 @@ struct pci_module_info { uchar device, uchar function, uchar newInterruptLineValue); + + status_t (*find_pci_extended_capability) ( + uint8 bus, + uint8 device, + uint8 function, + uint16 cap_id, + uint16 *offset + ); }; #define B_PCI_MODULE_NAME "bus_managers/pci/v1" diff --git a/headers/os/drivers/bus/PCI.h b/headers/os/drivers/bus/PCI.h index fa362c7bc7..f0816d3361 100644 --- a/headers/os/drivers/bus/PCI.h +++ b/headers/os/drivers/bus/PCI.h @@ -27,13 +27,15 @@ typedef struct pci_device_module_info { void *(*ram_address)(pci_device *device, const void *physicalAddress); - uint32 (*read_pci_config)(pci_device *device, uint8 offset, + uint32 (*read_pci_config)(pci_device *device, uint16 offset, uint8 size); - void (*write_pci_config)(pci_device *device, uint8 offset, + void (*write_pci_config)(pci_device *device, uint16 offset, uint8 size, uint32 value); status_t (*find_pci_capability)(pci_device *device, uint8 capID, uint8 *offset); void (*get_pci_info)(pci_device *device, struct pci_info *info); + status_t (*find_pci_extended_capability)(pci_device *device, uint16 capID, + uint16 *offset); } pci_device_module_info; diff --git a/src/add-ons/kernel/bus_managers/pci/pci.cpp b/src/add-ons/kernel/bus_managers/pci/pci.cpp index 1b8a1c00dd..f13d492e62 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci.cpp @@ -43,7 +43,7 @@ pci_get_nth_pci_info(long index, pci_info *outInfo) uint32 -pci_read_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, +pci_read_config(uint8 virtualBus, uint8 device, uint8 function, uint16 offset, uint8 size) { uint8 bus; @@ -62,7 +62,7 @@ pci_read_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, void -pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, +pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint16 offset, uint8 size, uint32 value) { uint8 bus; diff --git a/src/add-ons/kernel/bus_managers/pci/pci.h b/src/add-ons/kernel/bus_managers/pci/pci.h index 5ec5da50a7..2b5f57eabc 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.h +++ b/src/add-ons/kernel/bus_managers/pci/pci.h @@ -186,9 +186,9 @@ void pci_uninit(void); long pci_get_nth_pci_info(long index, pci_info *outInfo); uint32 pci_read_config(uint8 virtualBus, uint8 device, uint8 function, - uint8 offset, uint8 size); + uint16 offset, uint8 size); void pci_write_config(uint8 virtualBus, uint8 device, uint8 function, - uint8 offset, uint8 size, uint32 value); + uint16 offset, uint8 size, uint32 value); void __pci_resolve_virtual_bus(uint8 virtualBus, uint8 *domain, uint8 *bus); diff --git a/src/add-ons/kernel/bus_managers/pci/pci_device.cpp b/src/add-ons/kernel/bus_managers/pci/pci_device.cpp index 32a885de71..3d6f8e16f6 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_device.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci_device.cpp @@ -66,14 +66,14 @@ pci_device_write_io_32(pci_device* device, addr_t mappedIOAddress, uint32 value) static uint32 -pci_device_read_pci_config(pci_device* device, uint8 offset, uint8 size) +pci_device_read_pci_config(pci_device* device, uint16 offset, uint8 size) { return gPCI->ReadConfig(device->device, offset, size); } static void -pci_device_write_pci_config(pci_device* device, uint8 offset, uint8 size, +pci_device_write_pci_config(pci_device* device, uint16 offset, uint8 size, uint32 value) { gPCI->WriteConfig(device->device, offset, size, value); @@ -94,6 +94,14 @@ pci_device_find_capability(pci_device* device, uint8 capID, uint8* offset) } +static status_t +pci_device_find_extended_capability(pci_device* device, uint16 capID, + uint16* offset) +{ + return gPCI->FindExtendedCapability(device->device, capID, offset); +} + + static void pci_device_get_pci_info(pci_device* device, struct pci_info* info) { @@ -187,5 +195,6 @@ pci_device_module_info gPCIDeviceModule = { pci_device_read_pci_config, pci_device_write_pci_config, pci_device_find_capability, - pci_device_get_pci_info + pci_device_get_pci_info, + pci_device_find_extended_capability }; diff --git a/src/add-ons/kernel/bus_managers/pci/pci_info.cpp b/src/add-ons/kernel/bus_managers/pci/pci_info.cpp index ccc7ecfa1d..3ff68d47ac 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_info.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci_info.cpp @@ -26,6 +26,7 @@ #endif const char *get_capability_name(uint8 cap_id); +const char *get_extended_capability_name(uint16 cap_id); static void @@ -176,6 +177,45 @@ print_capabilities(const pci_info *info) } +static void +print_extended_capabilities(const pci_info *info) +{ + if (pci_find_capability(info->bus, info->device, info->function, + PCI_cap_id_pcie, NULL) != B_OK) + return; + + uint16 capPointer = PCI_extended_capability; + uint32 capability = pci_read_config(info->bus, info->device, + info->function, capPointer, 4); + TRACE(("PCI: Extended capabilities: ")); + if (capability == 0 || capability == 0xffffffff) { + TRACE(("(empty list)\n")); + return; + } + + for (int i = 0; i < 48; i++) { + if (i) { + TRACE((", ")); + } + const char *name = get_extended_capability_name( + PCI_extcap_id(capability)); + if (name) { + TRACE(("%s", name)); + } else { + TRACE(("0x%04" B_PRIx32, PCI_extcap_id(capability))); + } + + capPointer = PCI_extcap_next_ptr(capability) & ~3; + if (capPointer < PCI_extended_capability) + break; + capability = pci_read_config(info->bus, info->device, info->function, + capPointer, 4); + } + + TRACE(("\n")); +} + + static void print_info_basic(const pci_info *info, bool verbose) { @@ -236,6 +276,7 @@ print_info_basic(const pci_info *info, bool verbose) } print_capabilities(info); + print_extended_capabilities(info); } @@ -298,3 +339,71 @@ get_capability_name(uint8 cap_id) } } + +const char * +get_extended_capability_name(uint16 cap_id) +{ + switch (cap_id) { + case PCI_extcap_id_aer: + return "Advanced Error Reporting"; + case PCI_extcap_id_vc: + return "Virtual Channel"; + case PCI_extcap_id_serial: + return "Serial Number"; + case PCI_extcap_id_power_budget: + return "Power Budgeting"; + case PCI_extcap_id_rcl_decl: + return "Root Complex Link Declaration"; + case PCI_extcap_id_rcil_ctl: + return "Root Complex Internal Link Control"; + case PCI_extcap_id_rcec_assoc: + return "Root Complex Event Collector Association"; + case PCI_extcap_id_mfvc: + return "MultiFunction Virtual Channel"; + case PCI_extcap_id_vc2: + return "Virtual Channel 2"; + case PCI_extcap_id_rcrb_header: + return "RCRB Header"; + case PCI_extcap_id_vendor: + return "Vendor Unique"; + case PCI_extcap_id_acs: + return "Access Control Services"; + case PCI_extcap_id_ari: + return "Alternative Routing Id Interpretation"; + case PCI_extcap_id_ats: + return "Address Translation Services"; + case PCI_extcap_id_srio_virtual: + return "Single Root I/O Virtualization"; + case PCI_extcap_id_mrio_virtual: + return "Multiple Root I/O Virtual"; + case PCI_extcap_id_multicast: + return "Multicast"; + case PCI_extcap_id_page_request: + return "Page Request"; + case PCI_extcap_id_amd: + return "AMD Reserved"; + case PCI_extcap_id_resizable_bar: + return "Resizable Bar"; + case PCI_extcap_id_dyn_power_alloc: + return "Dynamic Power Allocation"; + case PCI_extcap_id_tph_requester: + return "TPH Requester"; + case PCI_extcap_id_latency_tolerance: + return "Latency Tolerance Reporting"; + case PCI_extcap_id_2ndpcie: + return "Secondary PCIe"; + case PCI_extcap_id_pmux: + return "Protocol Multiplexing"; + case PCI_extcap_id_pasid: + return "Process Address Space Id"; + case PCI_extcap_id_ln_requester: + return "LN Requester"; + case PCI_extcap_id_dpc: + return "Downstream Porto Containment"; + case PCI_extcap_id_l1pm: + return "L1 Power Management Substates"; + default: + return NULL; + } +} + diff --git a/src/add-ons/kernel/bus_managers/pci/pci_module.cpp b/src/add-ons/kernel/bus_managers/pci/pci_module.cpp index fc71f6c2f8..41227b1746 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_module.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci_module.cpp @@ -67,7 +67,8 @@ static struct pci_module_info sOldPCIModule = { &pci_find_capability, &pci_reserve_device, &pci_unreserve_device, - &pci_update_interrupt_line + &pci_update_interrupt_line, + &pci_find_extended_capability }; module_dependency module_dependencies[] = { diff --git a/src/add-ons/kernel/bus_managers/pci/pci_private.h b/src/add-ons/kernel/bus_managers/pci/pci_private.h index 8804848623..306b3d854c 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_private.h +++ b/src/add-ons/kernel/bus_managers/pci/pci_private.h @@ -29,11 +29,11 @@ typedef struct pci_root_module_info { // read PCI config space uint32 (*read_pci_config)(uint8 bus, uint8 device, uint8 function, - uint8 offset, uint8 size); + uint16 offset, uint8 size); // write PCI config space void (*write_pci_config)(uint8 bus, uint8 device, uint8 function, - uint8 offset, uint8 size, uint32 value); + uint16 offset, uint8 size, uint32 value); } pci_root_module_info; extern pci_root_module_info gPCIRootModule;