xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/hwpci.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /*******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Module Name: hwpci - Obtain PCI bus, device, and function numbers
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  ******************************************************************************/
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <acpi/acpi.h>
9*4882a593Smuzhiyun #include "accommon.h"
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #define _COMPONENT          ACPI_NAMESPACE
12*4882a593Smuzhiyun ACPI_MODULE_NAME("hwpci")
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun /* PCI configuration space values */
15*4882a593Smuzhiyun #define PCI_CFG_HEADER_TYPE_REG             0x0E
16*4882a593Smuzhiyun #define PCI_CFG_PRIMARY_BUS_NUMBER_REG      0x18
17*4882a593Smuzhiyun #define PCI_CFG_SECONDARY_BUS_NUMBER_REG    0x19
18*4882a593Smuzhiyun /* PCI header values */
19*4882a593Smuzhiyun #define PCI_HEADER_TYPE_MASK                0x7F
20*4882a593Smuzhiyun #define PCI_TYPE_BRIDGE                     0x01
21*4882a593Smuzhiyun #define PCI_TYPE_CARDBUS_BRIDGE             0x02
22*4882a593Smuzhiyun typedef struct acpi_pci_device {
23*4882a593Smuzhiyun 	acpi_handle device;
24*4882a593Smuzhiyun 	struct acpi_pci_device *next;
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun } acpi_pci_device;
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /* Local prototypes */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun static acpi_status
31*4882a593Smuzhiyun acpi_hw_build_pci_list(acpi_handle root_pci_device,
32*4882a593Smuzhiyun 		       acpi_handle pci_region,
33*4882a593Smuzhiyun 		       struct acpi_pci_device **return_list_head);
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun static acpi_status
36*4882a593Smuzhiyun acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
37*4882a593Smuzhiyun 			 struct acpi_pci_device *list_head);
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head);
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun static acpi_status
42*4882a593Smuzhiyun acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
43*4882a593Smuzhiyun 			    acpi_handle pci_device,
44*4882a593Smuzhiyun 			    u16 *bus_number, u8 *is_bridge);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun /*******************************************************************************
47*4882a593Smuzhiyun  *
48*4882a593Smuzhiyun  * FUNCTION:    acpi_hw_derive_pci_id
49*4882a593Smuzhiyun  *
50*4882a593Smuzhiyun  * PARAMETERS:  pci_id              - Initial values for the PCI ID. May be
51*4882a593Smuzhiyun  *                                    modified by this function.
52*4882a593Smuzhiyun  *              root_pci_device     - A handle to a PCI device object. This
53*4882a593Smuzhiyun  *                                    object must be a PCI Root Bridge having a
54*4882a593Smuzhiyun  *                                    _HID value of either PNP0A03 or PNP0A08
55*4882a593Smuzhiyun  *              pci_region          - A handle to a PCI configuration space
56*4882a593Smuzhiyun  *                                    Operation Region being initialized
57*4882a593Smuzhiyun  *
58*4882a593Smuzhiyun  * RETURN:      Status
59*4882a593Smuzhiyun  *
60*4882a593Smuzhiyun  * DESCRIPTION: This function derives a full PCI ID for a PCI device,
61*4882a593Smuzhiyun  *              consisting of a Segment number, Bus number, Device number,
62*4882a593Smuzhiyun  *              and function code.
63*4882a593Smuzhiyun  *
64*4882a593Smuzhiyun  *              The PCI hardware dynamically configures PCI bus numbers
65*4882a593Smuzhiyun  *              depending on the bus topology discovered during system
66*4882a593Smuzhiyun  *              initialization. This function is invoked during configuration
67*4882a593Smuzhiyun  *              of a PCI_Config Operation Region in order to (possibly) update
68*4882a593Smuzhiyun  *              the Bus/Device/Function numbers in the pci_id with the actual
69*4882a593Smuzhiyun  *              values as determined by the hardware and operating system
70*4882a593Smuzhiyun  *              configuration.
71*4882a593Smuzhiyun  *
72*4882a593Smuzhiyun  *              The pci_id parameter is initially populated during the Operation
73*4882a593Smuzhiyun  *              Region initialization. This function is then called, and is
74*4882a593Smuzhiyun  *              will make any necessary modifications to the Bus, Device, or
75*4882a593Smuzhiyun  *              Function number PCI ID subfields as appropriate for the
76*4882a593Smuzhiyun  *              current hardware and OS configuration.
77*4882a593Smuzhiyun  *
78*4882a593Smuzhiyun  * NOTE:        Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id
79*4882a593Smuzhiyun  *              interface since this feature is OS-independent. This module
80*4882a593Smuzhiyun  *              specifically avoids any use of recursion by building a local
81*4882a593Smuzhiyun  *              temporary device list.
82*4882a593Smuzhiyun  *
83*4882a593Smuzhiyun  ******************************************************************************/
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun acpi_status
acpi_hw_derive_pci_id(struct acpi_pci_id * pci_id,acpi_handle root_pci_device,acpi_handle pci_region)86*4882a593Smuzhiyun acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
87*4882a593Smuzhiyun 		      acpi_handle root_pci_device, acpi_handle pci_region)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	acpi_status status;
90*4882a593Smuzhiyun 	struct acpi_pci_device *list_head;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(hw_derive_pci_id);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	if (!pci_id) {
95*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_BAD_PARAMETER);
96*4882a593Smuzhiyun 	}
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	/* Build a list of PCI devices, from pci_region up to root_pci_device */
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	status =
101*4882a593Smuzhiyun 	    acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head);
102*4882a593Smuzhiyun 	if (ACPI_SUCCESS(status)) {
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 		/* Walk the list, updating the PCI device/function/bus numbers */
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 		status = acpi_hw_process_pci_list(pci_id, list_head);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 		/* Delete the list */
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 		acpi_hw_delete_pci_list(list_head);
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun /*******************************************************************************
117*4882a593Smuzhiyun  *
118*4882a593Smuzhiyun  * FUNCTION:    acpi_hw_build_pci_list
119*4882a593Smuzhiyun  *
120*4882a593Smuzhiyun  * PARAMETERS:  root_pci_device     - A handle to a PCI device object. This
121*4882a593Smuzhiyun  *                                    object is guaranteed to be a PCI Root
122*4882a593Smuzhiyun  *                                    Bridge having a _HID value of either
123*4882a593Smuzhiyun  *                                    PNP0A03 or PNP0A08
124*4882a593Smuzhiyun  *              pci_region          - A handle to the PCI configuration space
125*4882a593Smuzhiyun  *                                    Operation Region
126*4882a593Smuzhiyun  *              return_list_head    - Where the PCI device list is returned
127*4882a593Smuzhiyun  *
128*4882a593Smuzhiyun  * RETURN:      Status
129*4882a593Smuzhiyun  *
130*4882a593Smuzhiyun  * DESCRIPTION: Builds a list of devices from the input PCI region up to the
131*4882a593Smuzhiyun  *              Root PCI device for this namespace subtree.
132*4882a593Smuzhiyun  *
133*4882a593Smuzhiyun  ******************************************************************************/
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun static acpi_status
acpi_hw_build_pci_list(acpi_handle root_pci_device,acpi_handle pci_region,struct acpi_pci_device ** return_list_head)136*4882a593Smuzhiyun acpi_hw_build_pci_list(acpi_handle root_pci_device,
137*4882a593Smuzhiyun 		       acpi_handle pci_region,
138*4882a593Smuzhiyun 		       struct acpi_pci_device **return_list_head)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	acpi_handle current_device;
141*4882a593Smuzhiyun 	acpi_handle parent_device;
142*4882a593Smuzhiyun 	acpi_status status;
143*4882a593Smuzhiyun 	struct acpi_pci_device *list_element;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	/*
146*4882a593Smuzhiyun 	 * Ascend namespace branch until the root_pci_device is reached, building
147*4882a593Smuzhiyun 	 * a list of device nodes. Loop will exit when either the PCI device is
148*4882a593Smuzhiyun 	 * found, or the root of the namespace is reached.
149*4882a593Smuzhiyun 	 */
150*4882a593Smuzhiyun 	*return_list_head = NULL;
151*4882a593Smuzhiyun 	current_device = pci_region;
152*4882a593Smuzhiyun 	while (1) {
153*4882a593Smuzhiyun 		status = acpi_get_parent(current_device, &parent_device);
154*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 			/* Must delete the list before exit */
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 			acpi_hw_delete_pci_list(*return_list_head);
159*4882a593Smuzhiyun 			return (status);
160*4882a593Smuzhiyun 		}
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 		/* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 		if (parent_device == root_pci_device) {
165*4882a593Smuzhiyun 			return (AE_OK);
166*4882a593Smuzhiyun 		}
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 		list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device));
169*4882a593Smuzhiyun 		if (!list_element) {
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 			/* Must delete the list before exit */
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 			acpi_hw_delete_pci_list(*return_list_head);
174*4882a593Smuzhiyun 			return (AE_NO_MEMORY);
175*4882a593Smuzhiyun 		}
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 		/* Put new element at the head of the list */
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 		list_element->next = *return_list_head;
180*4882a593Smuzhiyun 		list_element->device = parent_device;
181*4882a593Smuzhiyun 		*return_list_head = list_element;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 		current_device = parent_device;
184*4882a593Smuzhiyun 	}
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /*******************************************************************************
188*4882a593Smuzhiyun  *
189*4882a593Smuzhiyun  * FUNCTION:    acpi_hw_process_pci_list
190*4882a593Smuzhiyun  *
191*4882a593Smuzhiyun  * PARAMETERS:  pci_id              - Initial values for the PCI ID. May be
192*4882a593Smuzhiyun  *                                    modified by this function.
193*4882a593Smuzhiyun  *              list_head           - Device list created by
194*4882a593Smuzhiyun  *                                    acpi_hw_build_pci_list
195*4882a593Smuzhiyun  *
196*4882a593Smuzhiyun  * RETURN:      Status
197*4882a593Smuzhiyun  *
198*4882a593Smuzhiyun  * DESCRIPTION: Walk downward through the PCI device list, getting the device
199*4882a593Smuzhiyun  *              info for each, via the PCI configuration space and updating
200*4882a593Smuzhiyun  *              the PCI ID as necessary. Deletes the list during traversal.
201*4882a593Smuzhiyun  *
202*4882a593Smuzhiyun  ******************************************************************************/
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun static acpi_status
acpi_hw_process_pci_list(struct acpi_pci_id * pci_id,struct acpi_pci_device * list_head)205*4882a593Smuzhiyun acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
206*4882a593Smuzhiyun 			 struct acpi_pci_device *list_head)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	acpi_status status = AE_OK;
209*4882a593Smuzhiyun 	struct acpi_pci_device *info;
210*4882a593Smuzhiyun 	u16 bus_number;
211*4882a593Smuzhiyun 	u8 is_bridge = TRUE;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	ACPI_FUNCTION_NAME(hw_process_pci_list);
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
216*4882a593Smuzhiyun 			  "Input PciId:  Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
217*4882a593Smuzhiyun 			  pci_id->segment, pci_id->bus, pci_id->device,
218*4882a593Smuzhiyun 			  pci_id->function));
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	bus_number = pci_id->bus;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	/*
223*4882a593Smuzhiyun 	 * Descend down the namespace tree, collecting PCI device, function,
224*4882a593Smuzhiyun 	 * and bus numbers. bus_number is only important for PCI bridges.
225*4882a593Smuzhiyun 	 * Algorithm: As we descend the tree, use the last valid PCI device,
226*4882a593Smuzhiyun 	 * function, and bus numbers that are discovered, and assign them
227*4882a593Smuzhiyun 	 * to the PCI ID for the target device.
228*4882a593Smuzhiyun 	 */
229*4882a593Smuzhiyun 	info = list_head;
230*4882a593Smuzhiyun 	while (info) {
231*4882a593Smuzhiyun 		status = acpi_hw_get_pci_device_info(pci_id, info->device,
232*4882a593Smuzhiyun 						     &bus_number, &is_bridge);
233*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
234*4882a593Smuzhiyun 			return (status);
235*4882a593Smuzhiyun 		}
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 		info = info->next;
238*4882a593Smuzhiyun 	}
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
241*4882a593Smuzhiyun 			  "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X "
242*4882a593Smuzhiyun 			  "Status %X BusNumber %X IsBridge %X\n",
243*4882a593Smuzhiyun 			  pci_id->segment, pci_id->bus, pci_id->device,
244*4882a593Smuzhiyun 			  pci_id->function, status, bus_number, is_bridge));
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return (AE_OK);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun /*******************************************************************************
250*4882a593Smuzhiyun  *
251*4882a593Smuzhiyun  * FUNCTION:    acpi_hw_delete_pci_list
252*4882a593Smuzhiyun  *
253*4882a593Smuzhiyun  * PARAMETERS:  list_head           - Device list created by
254*4882a593Smuzhiyun  *                                    acpi_hw_build_pci_list
255*4882a593Smuzhiyun  *
256*4882a593Smuzhiyun  * RETURN:      None
257*4882a593Smuzhiyun  *
258*4882a593Smuzhiyun  * DESCRIPTION: Free the entire PCI list.
259*4882a593Smuzhiyun  *
260*4882a593Smuzhiyun  ******************************************************************************/
261*4882a593Smuzhiyun 
acpi_hw_delete_pci_list(struct acpi_pci_device * list_head)262*4882a593Smuzhiyun static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun 	struct acpi_pci_device *next;
265*4882a593Smuzhiyun 	struct acpi_pci_device *previous;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	next = list_head;
268*4882a593Smuzhiyun 	while (next) {
269*4882a593Smuzhiyun 		previous = next;
270*4882a593Smuzhiyun 		next = previous->next;
271*4882a593Smuzhiyun 		ACPI_FREE(previous);
272*4882a593Smuzhiyun 	}
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun /*******************************************************************************
276*4882a593Smuzhiyun  *
277*4882a593Smuzhiyun  * FUNCTION:    acpi_hw_get_pci_device_info
278*4882a593Smuzhiyun  *
279*4882a593Smuzhiyun  * PARAMETERS:  pci_id              - Initial values for the PCI ID. May be
280*4882a593Smuzhiyun  *                                    modified by this function.
281*4882a593Smuzhiyun  *              pci_device          - Handle for the PCI device object
282*4882a593Smuzhiyun  *              bus_number          - Where a PCI bridge bus number is returned
283*4882a593Smuzhiyun  *              is_bridge           - Return value, indicates if this PCI
284*4882a593Smuzhiyun  *                                    device is a PCI bridge
285*4882a593Smuzhiyun  *
286*4882a593Smuzhiyun  * RETURN:      Status
287*4882a593Smuzhiyun  *
288*4882a593Smuzhiyun  * DESCRIPTION: Get the device info for a single PCI device object. Get the
289*4882a593Smuzhiyun  *              _ADR (contains PCI device and function numbers), and for PCI
290*4882a593Smuzhiyun  *              bridge devices, get the bus number from PCI configuration
291*4882a593Smuzhiyun  *              space.
292*4882a593Smuzhiyun  *
293*4882a593Smuzhiyun  ******************************************************************************/
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun static acpi_status
acpi_hw_get_pci_device_info(struct acpi_pci_id * pci_id,acpi_handle pci_device,u16 * bus_number,u8 * is_bridge)296*4882a593Smuzhiyun acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
297*4882a593Smuzhiyun 			    acpi_handle pci_device,
298*4882a593Smuzhiyun 			    u16 *bus_number, u8 *is_bridge)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun 	acpi_status status;
301*4882a593Smuzhiyun 	acpi_object_type object_type;
302*4882a593Smuzhiyun 	u64 return_value;
303*4882a593Smuzhiyun 	u64 pci_value;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	/* We only care about objects of type Device */
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	status = acpi_get_type(pci_device, &object_type);
308*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
309*4882a593Smuzhiyun 		return (status);
310*4882a593Smuzhiyun 	}
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	if (object_type != ACPI_TYPE_DEVICE) {
313*4882a593Smuzhiyun 		return (AE_OK);
314*4882a593Smuzhiyun 	}
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	/* We need an _ADR. Ignore device if not present */
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
319*4882a593Smuzhiyun 						 pci_device, &return_value);
320*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
321*4882a593Smuzhiyun 		return (AE_OK);
322*4882a593Smuzhiyun 	}
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	/*
325*4882a593Smuzhiyun 	 * From _ADR, get the PCI Device and Function and
326*4882a593Smuzhiyun 	 * update the PCI ID.
327*4882a593Smuzhiyun 	 */
328*4882a593Smuzhiyun 	pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value));
329*4882a593Smuzhiyun 	pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value));
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	/*
332*4882a593Smuzhiyun 	 * If the previous device was a bridge, use the previous
333*4882a593Smuzhiyun 	 * device bus number
334*4882a593Smuzhiyun 	 */
335*4882a593Smuzhiyun 	if (*is_bridge) {
336*4882a593Smuzhiyun 		pci_id->bus = *bus_number;
337*4882a593Smuzhiyun 	}
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	/*
340*4882a593Smuzhiyun 	 * Get the bus numbers from PCI Config space:
341*4882a593Smuzhiyun 	 *
342*4882a593Smuzhiyun 	 * First, get the PCI header_type
343*4882a593Smuzhiyun 	 */
344*4882a593Smuzhiyun 	*is_bridge = FALSE;
345*4882a593Smuzhiyun 	status = acpi_os_read_pci_configuration(pci_id,
346*4882a593Smuzhiyun 						PCI_CFG_HEADER_TYPE_REG,
347*4882a593Smuzhiyun 						&pci_value, 8);
348*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
349*4882a593Smuzhiyun 		return (status);
350*4882a593Smuzhiyun 	}
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	/* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	pci_value &= PCI_HEADER_TYPE_MASK;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	if ((pci_value != PCI_TYPE_BRIDGE) &&
357*4882a593Smuzhiyun 	    (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) {
358*4882a593Smuzhiyun 		return (AE_OK);
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	/* Bridge: Get the Primary bus_number */
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	status = acpi_os_read_pci_configuration(pci_id,
364*4882a593Smuzhiyun 						PCI_CFG_PRIMARY_BUS_NUMBER_REG,
365*4882a593Smuzhiyun 						&pci_value, 8);
366*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
367*4882a593Smuzhiyun 		return (status);
368*4882a593Smuzhiyun 	}
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	*is_bridge = TRUE;
371*4882a593Smuzhiyun 	pci_id->bus = (u16)pci_value;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	/* Bridge: Get the Secondary bus_number */
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	status = acpi_os_read_pci_configuration(pci_id,
376*4882a593Smuzhiyun 						PCI_CFG_SECONDARY_BUS_NUMBER_REG,
377*4882a593Smuzhiyun 						&pci_value, 8);
378*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
379*4882a593Smuzhiyun 		return (status);
380*4882a593Smuzhiyun 	}
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	*bus_number = (u16)pci_value;
383*4882a593Smuzhiyun 	return (AE_OK);
384*4882a593Smuzhiyun }
385