diff --git a/headers/os/drivers/PCI.h b/headers/os/drivers/PCI.h index ef0b50653c..bff025f708 100644 --- a/headers/os/drivers/PCI.h +++ b/headers/os/drivers/PCI.h @@ -196,6 +196,7 @@ struct pci_module_info { #define PCI_header_type 0x0e /* (1 byte) header type */ #define PCI_bist 0x0f /* (1 byte) built-in self-test */ +#define PCI_extended_capability 0x100 /* (4 bytes) extended capability */ /* --- @@ -690,6 +691,41 @@ struct pci_module_info { #define PCI_cap_id_sata 0x12 /* Serial ATA Capability */ #define PCI_cap_id_pciaf 0x13 /* PCI Advanced Features */ +/** PCI Extended Capabilities */ +#define PCI_extcap_id(x) (x & 0x0000ffff) +#define PCI_extcap_version(x) ((x & 0x000f0000) >> 16) +#define PCI_extcap_next_ptr(x) ((x & 0xfff00000) >> 20) + +#define PCI_extcap_id_aer 0x0001 /* Advanced Error Reporting */ +#define PCI_extcap_id_vc 0x0002 /* Virtual Channel */ +#define PCI_extcap_id_serial 0x0003 /* Serial Number */ +#define PCI_extcap_id_power_budget 0x0004 /* Power Budgeting */ +#define PCI_extcap_id_rcl_decl 0x0005 /* Root Complex Link Declaration */ +#define PCI_extcap_id_rcil_ctl 0x0006 /* Root Complex Internal Link Control */ +#define PCI_extcap_id_rcec_assoc 0x0007 /* Root Complex Event Collector Association */ +#define PCI_extcap_id_mfvc 0x0008 /* MultiFunction Virtual Channel */ +#define PCI_extcap_id_vc2 0x0009 /* Virtual Channel 2 */ +#define PCI_extcap_id_rcrb_header 0x000a /* RCRB Header */ +#define PCI_extcap_id_vendor 0x000b /* Vendor Unique */ +#define PCI_extcap_id_acs 0x000d /* Access Control Services */ +#define PCI_extcap_id_ari 0x000e /* Alternative Routing Id Interpretation */ +#define PCI_extcap_id_ats 0x000f /* Address Translation Services */ +#define PCI_extcap_id_srio_virtual 0x0010 /* Single Root I/O Virtualization */ +#define PCI_extcap_id_mrio_virtual 0x0011 /* Multiple Root I/O Virtual */ +#define PCI_extcap_id_multicast 0x0012 /* Multicast */ +#define PCI_extcap_id_page_request 0x0013 /* Page Request */ +#define PCI_extcap_id_amd 0x0014 /* AMD Reserved */ +#define PCI_extcap_id_resizable_bar 0x0015 /* Resizable Bar */ +#define PCI_extcap_id_dyn_power_alloc 0x0016 /* Dynamic Power Allocation */ +#define PCI_extcap_id_tph_requester 0x0017 /* TPH Requester */ +#define PCI_extcap_id_latency_tolerance 0x0018 /* Latency Tolerance Reporting */ +#define PCI_extcap_id_2ndpcie 0x0019 /* Secondary PCIe */ +#define PCI_extcap_id_pmux 0x001a /* Protocol Multiplexing */ +#define PCI_extcap_id_pasid 0x001b /* Process Address Space Id */ +#define PCI_extcap_id_ln_requester 0x001c /* LN Requester */ +#define PCI_extcap_id_dpc 0x001d /* Downstream Porto Containment */ +#define PCI_extcap_id_l1pm 0x001e /* L1 Power Management Substates */ + /** Power Management Control Status Register settings */ #define PCI_pm_mask 0x03 #define PCI_pm_ctrl 0x02 diff --git a/src/add-ons/kernel/bus_managers/pci/pci.cpp b/src/add-ons/kernel/bus_managers/pci/pci.cpp index fc3f5dc23a..1b8a1c00dd 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci.cpp @@ -75,8 +75,8 @@ pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, status_t -pci_find_capability(uchar virtualBus, uchar device, uchar function, - uchar capID, uchar *offset) +pci_find_capability(uint8 virtualBus, uint8 device, uint8 function, + uint8 capID, uint8 *offset) { uint8 bus; uint8 domain; @@ -87,6 +87,20 @@ pci_find_capability(uchar virtualBus, uchar device, uchar function, } +status_t +pci_find_extended_capability(uint8 virtualBus, uint8 device, uint8 function, + uint16 capID, uint16 *offset) +{ + uint8 bus; + uint8 domain; + if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) + return B_ERROR; + + return gPCI->FindExtendedCapability(domain, bus, device, function, capID, + offset); +} + + status_t pci_reserve_device(uchar virtualBus, uchar device, uchar function, const char *driverName, void *nodeCookie) @@ -1548,14 +1562,10 @@ status_t PCI::FindCapability(uint8 domain, uint8 bus, uint8 device, uint8 function, uint8 capID, uint8 *offset) { - if (offset == NULL) { - TRACE_CAP("PCI: FindCapability() ERROR %u:%u:%u capability %#02x offset NULL pointer\n", bus, device, function, capID); - return B_BAD_VALUE; - } - uint16 status = ReadConfig(domain, bus, device, function, PCI_status, 2); if (!(status & PCI_status_capabilities)) { - TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x not supported\n", bus, device, function, capID); + FLOW("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x " + "not supported\n", bus, device, function, capID); return B_ERROR; } @@ -1566,27 +1576,29 @@ PCI::FindCapability(uint8 domain, uint8 bus, uint8 device, uint8 function, switch (headerType & PCI_header_type_mask) { case PCI_header_type_generic: case PCI_header_type_PCI_to_PCI_bridge: - capPointer = ReadConfig(domain, bus, device, function, - PCI_capabilities_ptr, 1); + capPointer = PCI_capabilities_ptr; break; case PCI_header_type_cardbus: - capPointer = ReadConfig(domain, bus, device, function, - PCI_capabilities_ptr_2, 1); + capPointer = PCI_capabilities_ptr_2; break; default: - TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x unknown header type\n", bus, device, function, capID); + TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability " + "%#02x unknown header type\n", bus, device, function, capID); return B_ERROR; } + capPointer = ReadConfig(domain, bus, device, function, capPointer, 1); capPointer &= ~3; if (capPointer == 0) { - TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x empty list\n", bus, device, function, capID); + TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x " + "empty list\n", bus, device, function, capID); return B_NAME_NOT_FOUND; } for (int i = 0; i < 48; i++) { if (ReadConfig(domain, bus, device, function, capPointer, 1) == capID) { - *offset = capPointer; + if (offset != NULL) + *offset = capPointer; return B_OK; } @@ -1611,6 +1623,51 @@ PCI::FindCapability(PCIDev *device, uint8 capID, uint8 *offset) } +status_t +PCI::FindExtendedCapability(uint8 domain, uint8 bus, uint8 device, + uint8 function, uint16 capID, uint16 *offset) +{ + if (FindCapability(domain, bus, device, function, PCI_cap_id_pcie) + != B_OK) { + FLOW("PCI:FindExtendedCapability ERROR %u:%u:%u capability %#02x " + "not supported\n", bus, device, function, capID); + return B_ERROR; + } + uint16 capPointer = PCI_extended_capability; + uint32 capability = ReadConfig(domain, bus, device, function, + capPointer, 4); + + if (capability == 0 || capability == 0xffffffff) + return B_NAME_NOT_FOUND; + + for (int i = 0; i < 48; i++) { + if (PCI_extcap_id(capability) == capID) { + if (offset != NULL) + *offset = capPointer; + return B_OK; + } + + capPointer = PCI_extcap_next_ptr(capability) & ~3; + if (capPointer < PCI_extended_capability) + return B_NAME_NOT_FOUND; + capability = ReadConfig(domain, bus, device, function, + capPointer, 4); + } + + TRACE_CAP("PCI:FindExtendedCapability ERROR %u:%u:%u capability %#04x " + "circular list\n", bus, device, function, capID); + return B_ERROR; +} + + +status_t +PCI::FindExtendedCapability(PCIDev *device, uint16 capID, uint16 *offset) +{ + return FindExtendedCapability(device->domain, device->bus, device->device, + device->function, capID, offset); +} + + PCIDev * PCI::FindDevice(uint8 domain, uint8 bus, uint8 device, uint8 function) { diff --git a/src/add-ons/kernel/bus_managers/pci/pci.h b/src/add-ons/kernel/bus_managers/pci/pci.h index bb7f9dce11..5ec5da50a7 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.h +++ b/src/add-ons/kernel/bus_managers/pci/pci.h @@ -92,9 +92,14 @@ public: status_t FindCapability(uint8 domain, uint8 bus, uint8 device, uint8 function, uint8 capID, - uint8 *offset); + uint8 *offset = NULL); status_t FindCapability(PCIDev *device, uint8 capID, - uint8 *offset); + uint8 *offset = NULL); + status_t FindExtendedCapability(uint8 domain, uint8 bus, + uint8 device, uint8 function, uint16 capID, + uint16 *offset = NULL); + status_t FindExtendedCapability(PCIDev *device, + uint16 capID, uint16 *offset = NULL); status_t ResolveVirtualBus(uint8 virtualBus, uint8 *domain, uint8 *bus); 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 973dc417b8..a58220e7f4 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_private.h +++ b/src/add-ons/kernel/bus_managers/pci/pci_private.h @@ -46,7 +46,10 @@ extern "C" { void * pci_ram_address(const void *physical_address_in_system_memory); -status_t pci_find_capability(uchar bus, uchar device, uchar function, uchar cap_id, uchar *offset); +status_t pci_find_capability(uint8 bus, uint8 device, uint8 function, + uint8 cap_id, uint8 *offset = NULL); +status_t pci_find_extended_capability(uint8 bus, uint8 device, uint8 function, + uint16 cap_id, uint16 *offset = NULL); status_t pci_reserve_device(uchar virtualBus, uchar device, uchar function, const char *driverName, void *nodeCookie);