From b027a0a2f750e957f109e9e872662aca67b4336f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 24 Jun 2013 19:12:41 +0200 Subject: [PATCH] pci: change offset type to uint16 in config space API. * The config space is larger than 255, we need to use an uint16 to access offsets superior or equal to 256. The current API only proposes an uint8 for this. This change switches the offset parameter to the uint16 type. Axel hinted that the used values are the same with such a change (the doc says sign extended to 2 or 4 bytes). I checked with GCC2 and it's indeed the case when inspecting the memory. With GCC4, instructions are the same on function call. * prints info about extended capabilities. * struct pci_module_info and struct pci_device_module_info are extended with pci_find_extended_capability(). --- headers/os/drivers/PCI.h | 28 +++-- headers/os/drivers/bus/PCI.h | 6 +- src/add-ons/kernel/bus_managers/pci/pci.cpp | 4 +- src/add-ons/kernel/bus_managers/pci/pci.h | 4 +- .../kernel/bus_managers/pci/pci_device.cpp | 15 ++- .../kernel/bus_managers/pci/pci_info.cpp | 109 ++++++++++++++++++ .../kernel/bus_managers/pci/pci_module.cpp | 3 +- .../kernel/bus_managers/pci/pci_private.h | 4 +- 8 files changed, 151 insertions(+), 22 deletions(-) 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;