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