1 /*******************************************************************************
3 * Module Name: hwpci - Obtain PCI bus, device, and function numbers
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2014, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
44 #include <acpi/acpi.h>
47 #define _COMPONENT ACPI_NAMESPACE
48 ACPI_MODULE_NAME("hwpci")
50 /* PCI configuration space values */
51 #define PCI_CFG_HEADER_TYPE_REG 0x0E
52 #define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18
53 #define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19
54 /* PCI header values */
55 #define PCI_HEADER_TYPE_MASK 0x7F
56 #define PCI_TYPE_BRIDGE 0x01
57 #define PCI_TYPE_CARDBUS_BRIDGE 0x02
58 typedef struct acpi_pci_device
{
60 struct acpi_pci_device
*next
;
64 /* Local prototypes */
67 acpi_hw_build_pci_list(acpi_handle root_pci_device
,
68 acpi_handle pci_region
,
69 struct acpi_pci_device
**return_list_head
);
72 acpi_hw_process_pci_list(struct acpi_pci_id
*pci_id
,
73 struct acpi_pci_device
*list_head
);
75 static void acpi_hw_delete_pci_list(struct acpi_pci_device
*list_head
);
78 acpi_hw_get_pci_device_info(struct acpi_pci_id
*pci_id
,
79 acpi_handle pci_device
,
80 u16
*bus_number
, u8
*is_bridge
);
82 /*******************************************************************************
84 * FUNCTION: acpi_hw_derive_pci_id
86 * PARAMETERS: pci_id - Initial values for the PCI ID. May be
87 * modified by this function.
88 * root_pci_device - A handle to a PCI device object. This
89 * object must be a PCI Root Bridge having a
90 * _HID value of either PNP0A03 or PNP0A08
91 * pci_region - A handle to a PCI configuration space
92 * Operation Region being initialized
96 * DESCRIPTION: This function derives a full PCI ID for a PCI device,
97 * consisting of a Segment number, Bus number, Device number,
100 * The PCI hardware dynamically configures PCI bus numbers
101 * depending on the bus topology discovered during system
102 * initialization. This function is invoked during configuration
103 * of a PCI_Config Operation Region in order to (possibly) update
104 * the Bus/Device/Function numbers in the pci_id with the actual
105 * values as determined by the hardware and operating system
108 * The pci_id parameter is initially populated during the Operation
109 * Region initialization. This function is then called, and is
110 * will make any necessary modifications to the Bus, Device, or
111 * Function number PCI ID subfields as appropriate for the
112 * current hardware and OS configuration.
114 * NOTE: Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id
115 * interface since this feature is OS-independent. This module
116 * specifically avoids any use of recursion by building a local
117 * temporary device list.
119 ******************************************************************************/
122 acpi_hw_derive_pci_id(struct acpi_pci_id
*pci_id
,
123 acpi_handle root_pci_device
, acpi_handle pci_region
)
126 struct acpi_pci_device
*list_head
= NULL
;
128 ACPI_FUNCTION_TRACE(hw_derive_pci_id
);
131 return_ACPI_STATUS(AE_BAD_PARAMETER
);
134 /* Build a list of PCI devices, from pci_region up to root_pci_device */
137 acpi_hw_build_pci_list(root_pci_device
, pci_region
, &list_head
);
138 if (ACPI_SUCCESS(status
)) {
140 /* Walk the list, updating the PCI device/function/bus numbers */
142 status
= acpi_hw_process_pci_list(pci_id
, list_head
);
144 /* Delete the list */
146 acpi_hw_delete_pci_list(list_head
);
149 return_ACPI_STATUS(status
);
152 /*******************************************************************************
154 * FUNCTION: acpi_hw_build_pci_list
156 * PARAMETERS: root_pci_device - A handle to a PCI device object. This
157 * object is guaranteed to be a PCI Root
158 * Bridge having a _HID value of either
160 * pci_region - A handle to the PCI configuration space
162 * return_list_head - Where the PCI device list is returned
166 * DESCRIPTION: Builds a list of devices from the input PCI region up to the
167 * Root PCI device for this namespace subtree.
169 ******************************************************************************/
172 acpi_hw_build_pci_list(acpi_handle root_pci_device
,
173 acpi_handle pci_region
,
174 struct acpi_pci_device
**return_list_head
)
176 acpi_handle current_device
;
177 acpi_handle parent_device
;
179 struct acpi_pci_device
*list_element
;
180 struct acpi_pci_device
*list_head
= NULL
;
183 * Ascend namespace branch until the root_pci_device is reached, building
184 * a list of device nodes. Loop will exit when either the PCI device is
185 * found, or the root of the namespace is reached.
187 current_device
= pci_region
;
189 status
= acpi_get_parent(current_device
, &parent_device
);
190 if (ACPI_FAILURE(status
)) {
192 /* Must delete the list before exit */
194 acpi_hw_delete_pci_list(*return_list_head
);
198 /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */
200 if (parent_device
== root_pci_device
) {
201 *return_list_head
= list_head
;
205 list_element
= ACPI_ALLOCATE(sizeof(struct acpi_pci_device
));
208 /* Must delete the list before exit */
210 acpi_hw_delete_pci_list(*return_list_head
);
211 return (AE_NO_MEMORY
);
214 /* Put new element at the head of the list */
216 list_element
->next
= list_head
;
217 list_element
->device
= parent_device
;
218 list_head
= list_element
;
220 current_device
= parent_device
;
224 /*******************************************************************************
226 * FUNCTION: acpi_hw_process_pci_list
228 * PARAMETERS: pci_id - Initial values for the PCI ID. May be
229 * modified by this function.
230 * list_head - Device list created by
231 * acpi_hw_build_pci_list
235 * DESCRIPTION: Walk downward through the PCI device list, getting the device
236 * info for each, via the PCI configuration space and updating
237 * the PCI ID as necessary. Deletes the list during traversal.
239 ******************************************************************************/
242 acpi_hw_process_pci_list(struct acpi_pci_id
*pci_id
,
243 struct acpi_pci_device
*list_head
)
245 acpi_status status
= AE_OK
;
246 struct acpi_pci_device
*info
;
250 ACPI_FUNCTION_NAME(hw_process_pci_list
);
252 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION
,
253 "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
254 pci_id
->segment
, pci_id
->bus
, pci_id
->device
,
257 bus_number
= pci_id
->bus
;
260 * Descend down the namespace tree, collecting PCI device, function,
261 * and bus numbers. bus_number is only important for PCI bridges.
262 * Algorithm: As we descend the tree, use the last valid PCI device,
263 * function, and bus numbers that are discovered, and assign them
264 * to the PCI ID for the target device.
268 status
= acpi_hw_get_pci_device_info(pci_id
, info
->device
,
269 &bus_number
, &is_bridge
);
270 if (ACPI_FAILURE(status
)) {
277 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION
,
278 "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X "
279 "Status %X BusNumber %X IsBridge %X\n",
280 pci_id
->segment
, pci_id
->bus
, pci_id
->device
,
281 pci_id
->function
, status
, bus_number
, is_bridge
));
286 /*******************************************************************************
288 * FUNCTION: acpi_hw_delete_pci_list
290 * PARAMETERS: list_head - Device list created by
291 * acpi_hw_build_pci_list
295 * DESCRIPTION: Free the entire PCI list.
297 ******************************************************************************/
299 static void acpi_hw_delete_pci_list(struct acpi_pci_device
*list_head
)
301 struct acpi_pci_device
*next
;
302 struct acpi_pci_device
*previous
;
307 next
= previous
->next
;
312 /*******************************************************************************
314 * FUNCTION: acpi_hw_get_pci_device_info
316 * PARAMETERS: pci_id - Initial values for the PCI ID. May be
317 * modified by this function.
318 * pci_device - Handle for the PCI device object
319 * bus_number - Where a PCI bridge bus number is returned
320 * is_bridge - Return value, indicates if this PCI
321 * device is a PCI bridge
325 * DESCRIPTION: Get the device info for a single PCI device object. Get the
326 * _ADR (contains PCI device and function numbers), and for PCI
327 * bridge devices, get the bus number from PCI configuration
330 ******************************************************************************/
333 acpi_hw_get_pci_device_info(struct acpi_pci_id
*pci_id
,
334 acpi_handle pci_device
,
335 u16
*bus_number
, u8
*is_bridge
)
338 acpi_object_type object_type
;
342 /* We only care about objects of type Device */
344 status
= acpi_get_type(pci_device
, &object_type
);
345 if (ACPI_FAILURE(status
)) {
349 if (object_type
!= ACPI_TYPE_DEVICE
) {
353 /* We need an _ADR. Ignore device if not present */
355 status
= acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR
,
356 pci_device
, &return_value
);
357 if (ACPI_FAILURE(status
)) {
362 * From _ADR, get the PCI Device and Function and
365 pci_id
->device
= ACPI_HIWORD(ACPI_LODWORD(return_value
));
366 pci_id
->function
= ACPI_LOWORD(ACPI_LODWORD(return_value
));
369 * If the previous device was a bridge, use the previous
373 pci_id
->bus
= *bus_number
;
377 * Get the bus numbers from PCI Config space:
379 * First, get the PCI header_type
382 status
= acpi_os_read_pci_configuration(pci_id
,
383 PCI_CFG_HEADER_TYPE_REG
,
385 if (ACPI_FAILURE(status
)) {
389 /* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */
391 pci_value
&= PCI_HEADER_TYPE_MASK
;
393 if ((pci_value
!= PCI_TYPE_BRIDGE
) &&
394 (pci_value
!= PCI_TYPE_CARDBUS_BRIDGE
)) {
398 /* Bridge: Get the Primary bus_number */
400 status
= acpi_os_read_pci_configuration(pci_id
,
401 PCI_CFG_PRIMARY_BUS_NUMBER_REG
,
403 if (ACPI_FAILURE(status
)) {
408 pci_id
->bus
= (u16
)pci_value
;
410 /* Bridge: Get the Secondary bus_number */
412 status
= acpi_os_read_pci_configuration(pci_id
,
413 PCI_CFG_SECONDARY_BUS_NUMBER_REG
,
415 if (ACPI_FAILURE(status
)) {
419 *bus_number
= (u16
)pci_value
;