Linux Audio

Check our new training course

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