162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/******************************************************************************* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: hwpci - Obtain PCI bus, device, and function numbers 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci ******************************************************************************/ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <acpi/acpi.h> 962306a36Sopenharmony_ci#include "accommon.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define _COMPONENT ACPI_NAMESPACE 1262306a36Sopenharmony_ciACPI_MODULE_NAME("hwpci") 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* PCI configuration space values */ 1562306a36Sopenharmony_ci#define PCI_CFG_HEADER_TYPE_REG 0x0E 1662306a36Sopenharmony_ci#define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18 1762306a36Sopenharmony_ci#define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19 1862306a36Sopenharmony_ci/* PCI header values */ 1962306a36Sopenharmony_ci#define PCI_HEADER_TYPE_MASK 0x7F 2062306a36Sopenharmony_ci#define PCI_TYPE_BRIDGE 0x01 2162306a36Sopenharmony_ci#define PCI_TYPE_CARDBUS_BRIDGE 0x02 2262306a36Sopenharmony_citypedef struct acpi_pci_device { 2362306a36Sopenharmony_ci acpi_handle device; 2462306a36Sopenharmony_ci struct acpi_pci_device *next; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci} acpi_pci_device; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* Local prototypes */ 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic acpi_status 3162306a36Sopenharmony_ciacpi_hw_build_pci_list(acpi_handle root_pci_device, 3262306a36Sopenharmony_ci acpi_handle pci_region, 3362306a36Sopenharmony_ci struct acpi_pci_device **return_list_head); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic acpi_status 3662306a36Sopenharmony_ciacpi_hw_process_pci_list(struct acpi_pci_id *pci_id, 3762306a36Sopenharmony_ci struct acpi_pci_device *list_head); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic acpi_status 4262306a36Sopenharmony_ciacpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id, 4362306a36Sopenharmony_ci acpi_handle pci_device, 4462306a36Sopenharmony_ci u16 *bus_number, u8 *is_bridge); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/******************************************************************************* 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * FUNCTION: acpi_hw_derive_pci_id 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * PARAMETERS: pci_id - Initial values for the PCI ID. May be 5162306a36Sopenharmony_ci * modified by this function. 5262306a36Sopenharmony_ci * root_pci_device - A handle to a PCI device object. This 5362306a36Sopenharmony_ci * object must be a PCI Root Bridge having a 5462306a36Sopenharmony_ci * _HID value of either PNP0A03 or PNP0A08 5562306a36Sopenharmony_ci * pci_region - A handle to a PCI configuration space 5662306a36Sopenharmony_ci * Operation Region being initialized 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * RETURN: Status 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * DESCRIPTION: This function derives a full PCI ID for a PCI device, 6162306a36Sopenharmony_ci * consisting of a Segment number, Bus number, Device number, 6262306a36Sopenharmony_ci * and function code. 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci * The PCI hardware dynamically configures PCI bus numbers 6562306a36Sopenharmony_ci * depending on the bus topology discovered during system 6662306a36Sopenharmony_ci * initialization. This function is invoked during configuration 6762306a36Sopenharmony_ci * of a PCI_Config Operation Region in order to (possibly) update 6862306a36Sopenharmony_ci * the Bus/Device/Function numbers in the pci_id with the actual 6962306a36Sopenharmony_ci * values as determined by the hardware and operating system 7062306a36Sopenharmony_ci * configuration. 7162306a36Sopenharmony_ci * 7262306a36Sopenharmony_ci * The pci_id parameter is initially populated during the Operation 7362306a36Sopenharmony_ci * Region initialization. This function is then called, and is 7462306a36Sopenharmony_ci * will make any necessary modifications to the Bus, Device, or 7562306a36Sopenharmony_ci * Function number PCI ID subfields as appropriate for the 7662306a36Sopenharmony_ci * current hardware and OS configuration. 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci * NOTE: Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id 7962306a36Sopenharmony_ci * interface since this feature is OS-independent. This module 8062306a36Sopenharmony_ci * specifically avoids any use of recursion by building a local 8162306a36Sopenharmony_ci * temporary device list. 8262306a36Sopenharmony_ci * 8362306a36Sopenharmony_ci ******************************************************************************/ 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ciacpi_status 8662306a36Sopenharmony_ciacpi_hw_derive_pci_id(struct acpi_pci_id *pci_id, 8762306a36Sopenharmony_ci acpi_handle root_pci_device, acpi_handle pci_region) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci acpi_status status; 9062306a36Sopenharmony_ci struct acpi_pci_device *list_head; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(hw_derive_pci_id); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if (!pci_id) { 9562306a36Sopenharmony_ci return_ACPI_STATUS(AE_BAD_PARAMETER); 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci /* Build a list of PCI devices, from pci_region up to root_pci_device */ 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci status = 10162306a36Sopenharmony_ci acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head); 10262306a36Sopenharmony_ci if (ACPI_SUCCESS(status)) { 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Walk the list, updating the PCI device/function/bus numbers */ 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci status = acpi_hw_process_pci_list(pci_id, list_head); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* Delete the list */ 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci acpi_hw_delete_pci_list(list_head); 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci return_ACPI_STATUS(status); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/******************************************************************************* 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * FUNCTION: acpi_hw_build_pci_list 11962306a36Sopenharmony_ci * 12062306a36Sopenharmony_ci * PARAMETERS: root_pci_device - A handle to a PCI device object. This 12162306a36Sopenharmony_ci * object is guaranteed to be a PCI Root 12262306a36Sopenharmony_ci * Bridge having a _HID value of either 12362306a36Sopenharmony_ci * PNP0A03 or PNP0A08 12462306a36Sopenharmony_ci * pci_region - A handle to the PCI configuration space 12562306a36Sopenharmony_ci * Operation Region 12662306a36Sopenharmony_ci * return_list_head - Where the PCI device list is returned 12762306a36Sopenharmony_ci * 12862306a36Sopenharmony_ci * RETURN: Status 12962306a36Sopenharmony_ci * 13062306a36Sopenharmony_ci * DESCRIPTION: Builds a list of devices from the input PCI region up to the 13162306a36Sopenharmony_ci * Root PCI device for this namespace subtree. 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci ******************************************************************************/ 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic acpi_status 13662306a36Sopenharmony_ciacpi_hw_build_pci_list(acpi_handle root_pci_device, 13762306a36Sopenharmony_ci acpi_handle pci_region, 13862306a36Sopenharmony_ci struct acpi_pci_device **return_list_head) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci acpi_handle current_device; 14162306a36Sopenharmony_ci acpi_handle parent_device; 14262306a36Sopenharmony_ci acpi_status status; 14362306a36Sopenharmony_ci struct acpi_pci_device *list_element; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci /* 14662306a36Sopenharmony_ci * Ascend namespace branch until the root_pci_device is reached, building 14762306a36Sopenharmony_ci * a list of device nodes. Loop will exit when either the PCI device is 14862306a36Sopenharmony_ci * found, or the root of the namespace is reached. 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_ci *return_list_head = NULL; 15162306a36Sopenharmony_ci current_device = pci_region; 15262306a36Sopenharmony_ci while (1) { 15362306a36Sopenharmony_ci status = acpi_get_parent(current_device, &parent_device); 15462306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* Must delete the list before exit */ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci acpi_hw_delete_pci_list(*return_list_head); 15962306a36Sopenharmony_ci return (status); 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (parent_device == root_pci_device) { 16562306a36Sopenharmony_ci return (AE_OK); 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device)); 16962306a36Sopenharmony_ci if (!list_element) { 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci /* Must delete the list before exit */ 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci acpi_hw_delete_pci_list(*return_list_head); 17462306a36Sopenharmony_ci return (AE_NO_MEMORY); 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* Put new element at the head of the list */ 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci list_element->next = *return_list_head; 18062306a36Sopenharmony_ci list_element->device = parent_device; 18162306a36Sopenharmony_ci *return_list_head = list_element; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci current_device = parent_device; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/******************************************************************************* 18862306a36Sopenharmony_ci * 18962306a36Sopenharmony_ci * FUNCTION: acpi_hw_process_pci_list 19062306a36Sopenharmony_ci * 19162306a36Sopenharmony_ci * PARAMETERS: pci_id - Initial values for the PCI ID. May be 19262306a36Sopenharmony_ci * modified by this function. 19362306a36Sopenharmony_ci * list_head - Device list created by 19462306a36Sopenharmony_ci * acpi_hw_build_pci_list 19562306a36Sopenharmony_ci * 19662306a36Sopenharmony_ci * RETURN: Status 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci * DESCRIPTION: Walk downward through the PCI device list, getting the device 19962306a36Sopenharmony_ci * info for each, via the PCI configuration space and updating 20062306a36Sopenharmony_ci * the PCI ID as necessary. Deletes the list during traversal. 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci ******************************************************************************/ 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic acpi_status 20562306a36Sopenharmony_ciacpi_hw_process_pci_list(struct acpi_pci_id *pci_id, 20662306a36Sopenharmony_ci struct acpi_pci_device *list_head) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci acpi_status status = AE_OK; 20962306a36Sopenharmony_ci struct acpi_pci_device *info; 21062306a36Sopenharmony_ci u16 bus_number; 21162306a36Sopenharmony_ci u8 is_bridge = TRUE; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci ACPI_FUNCTION_NAME(hw_process_pci_list); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 21662306a36Sopenharmony_ci "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n", 21762306a36Sopenharmony_ci pci_id->segment, pci_id->bus, pci_id->device, 21862306a36Sopenharmony_ci pci_id->function)); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci bus_number = pci_id->bus; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* 22362306a36Sopenharmony_ci * Descend down the namespace tree, collecting PCI device, function, 22462306a36Sopenharmony_ci * and bus numbers. bus_number is only important for PCI bridges. 22562306a36Sopenharmony_ci * Algorithm: As we descend the tree, use the last valid PCI device, 22662306a36Sopenharmony_ci * function, and bus numbers that are discovered, and assign them 22762306a36Sopenharmony_ci * to the PCI ID for the target device. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_ci info = list_head; 23062306a36Sopenharmony_ci while (info) { 23162306a36Sopenharmony_ci status = acpi_hw_get_pci_device_info(pci_id, info->device, 23262306a36Sopenharmony_ci &bus_number, &is_bridge); 23362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 23462306a36Sopenharmony_ci return (status); 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci info = info->next; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 24162306a36Sopenharmony_ci "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X " 24262306a36Sopenharmony_ci "Status %X BusNumber %X IsBridge %X\n", 24362306a36Sopenharmony_ci pci_id->segment, pci_id->bus, pci_id->device, 24462306a36Sopenharmony_ci pci_id->function, status, bus_number, is_bridge)); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci return (AE_OK); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci/******************************************************************************* 25062306a36Sopenharmony_ci * 25162306a36Sopenharmony_ci * FUNCTION: acpi_hw_delete_pci_list 25262306a36Sopenharmony_ci * 25362306a36Sopenharmony_ci * PARAMETERS: list_head - Device list created by 25462306a36Sopenharmony_ci * acpi_hw_build_pci_list 25562306a36Sopenharmony_ci * 25662306a36Sopenharmony_ci * RETURN: None 25762306a36Sopenharmony_ci * 25862306a36Sopenharmony_ci * DESCRIPTION: Free the entire PCI list. 25962306a36Sopenharmony_ci * 26062306a36Sopenharmony_ci ******************************************************************************/ 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci struct acpi_pci_device *next; 26562306a36Sopenharmony_ci struct acpi_pci_device *previous; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci next = list_head; 26862306a36Sopenharmony_ci while (next) { 26962306a36Sopenharmony_ci previous = next; 27062306a36Sopenharmony_ci next = previous->next; 27162306a36Sopenharmony_ci ACPI_FREE(previous); 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci} 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/******************************************************************************* 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * FUNCTION: acpi_hw_get_pci_device_info 27862306a36Sopenharmony_ci * 27962306a36Sopenharmony_ci * PARAMETERS: pci_id - Initial values for the PCI ID. May be 28062306a36Sopenharmony_ci * modified by this function. 28162306a36Sopenharmony_ci * pci_device - Handle for the PCI device object 28262306a36Sopenharmony_ci * bus_number - Where a PCI bridge bus number is returned 28362306a36Sopenharmony_ci * is_bridge - Return value, indicates if this PCI 28462306a36Sopenharmony_ci * device is a PCI bridge 28562306a36Sopenharmony_ci * 28662306a36Sopenharmony_ci * RETURN: Status 28762306a36Sopenharmony_ci * 28862306a36Sopenharmony_ci * DESCRIPTION: Get the device info for a single PCI device object. Get the 28962306a36Sopenharmony_ci * _ADR (contains PCI device and function numbers), and for PCI 29062306a36Sopenharmony_ci * bridge devices, get the bus number from PCI configuration 29162306a36Sopenharmony_ci * space. 29262306a36Sopenharmony_ci * 29362306a36Sopenharmony_ci ******************************************************************************/ 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic acpi_status 29662306a36Sopenharmony_ciacpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id, 29762306a36Sopenharmony_ci acpi_handle pci_device, 29862306a36Sopenharmony_ci u16 *bus_number, u8 *is_bridge) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci acpi_status status; 30162306a36Sopenharmony_ci acpi_object_type object_type; 30262306a36Sopenharmony_ci u64 return_value; 30362306a36Sopenharmony_ci u64 pci_value; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* We only care about objects of type Device */ 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci status = acpi_get_type(pci_device, &object_type); 30862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 30962306a36Sopenharmony_ci return (status); 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (object_type != ACPI_TYPE_DEVICE) { 31362306a36Sopenharmony_ci return (AE_OK); 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* We need an _ADR. Ignore device if not present */ 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, 31962306a36Sopenharmony_ci pci_device, &return_value); 32062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 32162306a36Sopenharmony_ci return (AE_OK); 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* 32562306a36Sopenharmony_ci * From _ADR, get the PCI Device and Function and 32662306a36Sopenharmony_ci * update the PCI ID. 32762306a36Sopenharmony_ci */ 32862306a36Sopenharmony_ci pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value)); 32962306a36Sopenharmony_ci pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value)); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* 33262306a36Sopenharmony_ci * If the previous device was a bridge, use the previous 33362306a36Sopenharmony_ci * device bus number 33462306a36Sopenharmony_ci */ 33562306a36Sopenharmony_ci if (*is_bridge) { 33662306a36Sopenharmony_ci pci_id->bus = *bus_number; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci /* 34062306a36Sopenharmony_ci * Get the bus numbers from PCI Config space: 34162306a36Sopenharmony_ci * 34262306a36Sopenharmony_ci * First, get the PCI header_type 34362306a36Sopenharmony_ci */ 34462306a36Sopenharmony_ci *is_bridge = FALSE; 34562306a36Sopenharmony_ci status = acpi_os_read_pci_configuration(pci_id, 34662306a36Sopenharmony_ci PCI_CFG_HEADER_TYPE_REG, 34762306a36Sopenharmony_ci &pci_value, 8); 34862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 34962306a36Sopenharmony_ci return (status); 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */ 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci pci_value &= PCI_HEADER_TYPE_MASK; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if ((pci_value != PCI_TYPE_BRIDGE) && 35762306a36Sopenharmony_ci (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) { 35862306a36Sopenharmony_ci return (AE_OK); 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /* Bridge: Get the Primary bus_number */ 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci status = acpi_os_read_pci_configuration(pci_id, 36462306a36Sopenharmony_ci PCI_CFG_PRIMARY_BUS_NUMBER_REG, 36562306a36Sopenharmony_ci &pci_value, 8); 36662306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 36762306a36Sopenharmony_ci return (status); 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci *is_bridge = TRUE; 37162306a36Sopenharmony_ci pci_id->bus = (u16)pci_value; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* Bridge: Get the Secondary bus_number */ 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci status = acpi_os_read_pci_configuration(pci_id, 37662306a36Sopenharmony_ci PCI_CFG_SECONDARY_BUS_NUMBER_REG, 37762306a36Sopenharmony_ci &pci_value, 8); 37862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 37962306a36Sopenharmony_ci return (status); 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci *bus_number = (u16)pci_value; 38362306a36Sopenharmony_ci return (AE_OK); 38462306a36Sopenharmony_ci} 385