pci: added pci_find_extended_capability().

* added PCI Extended Capabilities definitions.
* pci_find_capability() parameter offset is now optional.
This commit is contained in:
Jérôme Duval 2013-06-22 19:43:00 +02:00
parent e1c44764ef
commit 26a4510e59
4 changed files with 119 additions and 18 deletions

View File

@ -196,6 +196,7 @@ struct pci_module_info {
#define PCI_header_type 0x0e /* (1 byte) header type */ #define PCI_header_type 0x0e /* (1 byte) header type */
#define PCI_bist 0x0f /* (1 byte) built-in self-test */ #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_sata 0x12 /* Serial ATA Capability */
#define PCI_cap_id_pciaf 0x13 /* PCI Advanced Features */ #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 */ /** Power Management Control Status Register settings */
#define PCI_pm_mask 0x03 #define PCI_pm_mask 0x03
#define PCI_pm_ctrl 0x02 #define PCI_pm_ctrl 0x02

View File

@ -75,8 +75,8 @@ pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset,
status_t status_t
pci_find_capability(uchar virtualBus, uchar device, uchar function, pci_find_capability(uint8 virtualBus, uint8 device, uint8 function,
uchar capID, uchar *offset) uint8 capID, uint8 *offset)
{ {
uint8 bus; uint8 bus;
uint8 domain; 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 status_t
pci_reserve_device(uchar virtualBus, uchar device, uchar function, pci_reserve_device(uchar virtualBus, uchar device, uchar function,
const char *driverName, void *nodeCookie) const char *driverName, void *nodeCookie)
@ -1548,14 +1562,10 @@ status_t
PCI::FindCapability(uint8 domain, uint8 bus, uint8 device, uint8 function, PCI::FindCapability(uint8 domain, uint8 bus, uint8 device, uint8 function,
uint8 capID, uint8 *offset) 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); uint16 status = ReadConfig(domain, bus, device, function, PCI_status, 2);
if (!(status & PCI_status_capabilities)) { 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; return B_ERROR;
} }
@ -1566,27 +1576,29 @@ PCI::FindCapability(uint8 domain, uint8 bus, uint8 device, uint8 function,
switch (headerType & PCI_header_type_mask) { switch (headerType & PCI_header_type_mask) {
case PCI_header_type_generic: case PCI_header_type_generic:
case PCI_header_type_PCI_to_PCI_bridge: case PCI_header_type_PCI_to_PCI_bridge:
capPointer = ReadConfig(domain, bus, device, function, capPointer = PCI_capabilities_ptr;
PCI_capabilities_ptr, 1);
break; break;
case PCI_header_type_cardbus: case PCI_header_type_cardbus:
capPointer = ReadConfig(domain, bus, device, function, capPointer = PCI_capabilities_ptr_2;
PCI_capabilities_ptr_2, 1);
break; break;
default: 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; return B_ERROR;
} }
capPointer = ReadConfig(domain, bus, device, function, capPointer, 1);
capPointer &= ~3; capPointer &= ~3;
if (capPointer == 0) { 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; return B_NAME_NOT_FOUND;
} }
for (int i = 0; i < 48; i++) { for (int i = 0; i < 48; i++) {
if (ReadConfig(domain, bus, device, function, capPointer, 1) == capID) { if (ReadConfig(domain, bus, device, function, capPointer, 1) == capID) {
*offset = capPointer; if (offset != NULL)
*offset = capPointer;
return B_OK; 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 * PCIDev *
PCI::FindDevice(uint8 domain, uint8 bus, uint8 device, uint8 function) PCI::FindDevice(uint8 domain, uint8 bus, uint8 device, uint8 function)
{ {

View File

@ -92,9 +92,14 @@ public:
status_t FindCapability(uint8 domain, uint8 bus, status_t FindCapability(uint8 domain, uint8 bus,
uint8 device, uint8 function, uint8 capID, uint8 device, uint8 function, uint8 capID,
uint8 *offset); uint8 *offset = NULL);
status_t FindCapability(PCIDev *device, uint8 capID, 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, status_t ResolveVirtualBus(uint8 virtualBus, uint8 *domain,
uint8 *bus); uint8 *bus);

View File

@ -46,7 +46,10 @@ extern "C" {
void * pci_ram_address(const void *physical_address_in_system_memory); 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, status_t pci_reserve_device(uchar virtualBus, uchar device, uchar function,
const char *driverName, void *nodeCookie); const char *driverName, void *nodeCookie);