Print this page
acpica-unix2-20130823
PANKOVs restructure
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/acpica/hardware/hwpci.c
+++ new/usr/src/common/acpica/components/hardware/hwpci.c
1 1 /*******************************************************************************
2 2 *
3 3 * Module Name: hwpci - Obtain PCI bus, device, and function numbers
4 4 *
5 5 ******************************************************************************/
6 6
7 7 /*
8 - * Copyright (C) 2000 - 2011, Intel Corp.
8 + * Copyright (C) 2000 - 2013, Intel Corp.
9 9 * All rights reserved.
10 10 *
11 11 * Redistribution and use in source and binary forms, with or without
12 12 * modification, are permitted provided that the following conditions
13 13 * are met:
14 14 * 1. Redistributions of source code must retain the above copyright
15 15 * notice, this list of conditions, and the following disclaimer,
16 16 * without modification.
17 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 18 * substantially similar to the "NO WARRANTY" disclaimer below
19 19 * ("Disclaimer") and any redistribution must be conditioned upon
20 20 * including a substantially similar Disclaimer requirement for further
21 21 * binary redistribution.
22 22 * 3. Neither the names of the above-listed copyright holders nor the names
23 23 * of any contributors may be used to endorse or promote products derived
24 24 * from this software without specific prior written permission.
25 25 *
26 26 * Alternatively, this software may be distributed under the terms of the
27 27 * GNU General Public License ("GPL") version 2 as published by the Free
28 28 * Software Foundation.
29 29 *
30 30 * NO WARRANTY
31 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 41 * POSSIBILITY OF SUCH DAMAGES.
42 42 */
43 43
44 44 #define __HWPCI_C__
45 45
46 46 #include "acpi.h"
47 47 #include "accommon.h"
48 48
49 49
50 50 #define _COMPONENT ACPI_NAMESPACE
51 51 ACPI_MODULE_NAME ("hwpci")
52 52
53 53
54 54 /* PCI configuration space values */
55 55
56 56 #define PCI_CFG_HEADER_TYPE_REG 0x0E
57 57 #define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18
58 58 #define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19
59 59
60 60 /* PCI header values */
61 61
62 62 #define PCI_HEADER_TYPE_MASK 0x7F
63 63 #define PCI_TYPE_BRIDGE 0x01
64 64 #define PCI_TYPE_CARDBUS_BRIDGE 0x02
65 65
66 66 typedef struct acpi_pci_device
67 67 {
68 68 ACPI_HANDLE Device;
69 69 struct acpi_pci_device *Next;
70 70
71 71 } ACPI_PCI_DEVICE;
72 72
73 73
74 74 /* Local prototypes */
75 75
76 76 static ACPI_STATUS
77 77 AcpiHwBuildPciList (
78 78 ACPI_HANDLE RootPciDevice,
79 79 ACPI_HANDLE PciRegion,
80 80 ACPI_PCI_DEVICE **ReturnListHead);
81 81
82 82 static ACPI_STATUS
83 83 AcpiHwProcessPciList (
84 84 ACPI_PCI_ID *PciId,
85 85 ACPI_PCI_DEVICE *ListHead);
86 86
87 87 static void
88 88 AcpiHwDeletePciList (
89 89 ACPI_PCI_DEVICE *ListHead);
90 90
91 91 static ACPI_STATUS
92 92 AcpiHwGetPciDeviceInfo (
93 93 ACPI_PCI_ID *PciId,
94 94 ACPI_HANDLE PciDevice,
95 95 UINT16 *BusNumber,
96 96 BOOLEAN *IsBridge);
97 97
98 98
99 99 /*******************************************************************************
100 100 *
101 101 * FUNCTION: AcpiHwDerivePciId
102 102 *
103 103 * PARAMETERS: PciId - Initial values for the PCI ID. May be
104 104 * modified by this function.
105 105 * RootPciDevice - A handle to a PCI device object. This
106 106 * object must be a PCI Root Bridge having a
107 107 * _HID value of either PNP0A03 or PNP0A08
108 108 * PciRegion - A handle to a PCI configuration space
109 109 * Operation Region being initialized
110 110 *
111 111 * RETURN: Status
112 112 *
113 113 * DESCRIPTION: This function derives a full PCI ID for a PCI device,
114 114 * consisting of a Segment number, Bus number, Device number,
115 115 * and function code.
116 116 *
117 117 * The PCI hardware dynamically configures PCI bus numbers
118 118 * depending on the bus topology discovered during system
119 119 * initialization. This function is invoked during configuration
120 120 * of a PCI_Config Operation Region in order to (possibly) update
121 121 * the Bus/Device/Function numbers in the PciId with the actual
122 122 * values as determined by the hardware and operating system
123 123 * configuration.
124 124 *
125 125 * The PciId parameter is initially populated during the Operation
126 126 * Region initialization. This function is then called, and is
127 127 * will make any necessary modifications to the Bus, Device, or
128 128 * Function number PCI ID subfields as appropriate for the
129 129 * current hardware and OS configuration.
130 130 *
131 131 * NOTE: Created 08/2010. Replaces the previous OSL AcpiOsDerivePciId
132 132 * interface since this feature is OS-independent. This module
133 133 * specifically avoids any use of recursion by building a local
134 134 * temporary device list.
135 135 *
136 136 ******************************************************************************/
137 137
138 138 ACPI_STATUS
139 139 AcpiHwDerivePciId (
140 140 ACPI_PCI_ID *PciId,
141 141 ACPI_HANDLE RootPciDevice,
142 142 ACPI_HANDLE PciRegion)
143 143 {
144 144 ACPI_STATUS Status;
145 145 ACPI_PCI_DEVICE *ListHead = NULL;
146 146
147 147
148 148 ACPI_FUNCTION_TRACE (HwDerivePciId);
149 149
150 150
151 151 if (!PciId)
152 152 {
153 153 return_ACPI_STATUS (AE_BAD_PARAMETER);
154 154 }
155 155
156 156 /* Build a list of PCI devices, from PciRegion up to RootPciDevice */
157 157
158 158 Status = AcpiHwBuildPciList (RootPciDevice, PciRegion, &ListHead);
159 159 if (ACPI_SUCCESS (Status))
160 160 {
161 161 /* Walk the list, updating the PCI device/function/bus numbers */
162 162
163 163 Status = AcpiHwProcessPciList (PciId, ListHead);
164 164 }
165 165
166 166 /* Always delete the list */
167 167
168 168 AcpiHwDeletePciList (ListHead);
169 169 return_ACPI_STATUS (Status);
170 170 }
171 171
172 172
173 173 /*******************************************************************************
174 174 *
175 175 * FUNCTION: AcpiHwBuildPciList
176 176 *
177 177 * PARAMETERS: RootPciDevice - A handle to a PCI device object. This
178 178 * object is guaranteed to be a PCI Root
179 179 * Bridge having a _HID value of either
180 180 * PNP0A03 or PNP0A08
181 181 * PciRegion - A handle to the PCI configuration space
182 182 * Operation Region
183 183 * ReturnListHead - Where the PCI device list is returned
184 184 *
185 185 * RETURN: Status
186 186 *
187 187 * DESCRIPTION: Builds a list of devices from the input PCI region up to the
188 188 * Root PCI device for this namespace subtree.
189 189 *
190 190 ******************************************************************************/
191 191
192 192 static ACPI_STATUS
193 193 AcpiHwBuildPciList (
194 194 ACPI_HANDLE RootPciDevice,
195 195 ACPI_HANDLE PciRegion,
196 196 ACPI_PCI_DEVICE **ReturnListHead)
197 197 {
198 198 ACPI_HANDLE CurrentDevice;
199 199 ACPI_HANDLE ParentDevice;
200 200 ACPI_STATUS Status;
201 201 ACPI_PCI_DEVICE *ListElement;
202 202 ACPI_PCI_DEVICE *ListHead = NULL;
203 203
204 204
205 205 /*
206 206 * Ascend namespace branch until the RootPciDevice is reached, building
207 207 * a list of device nodes. Loop will exit when either the PCI device is
208 208 * found, or the root of the namespace is reached.
209 209 */
210 210 CurrentDevice = PciRegion;
211 211 while (1)
212 212 {
213 213 Status = AcpiGetParent (CurrentDevice, &ParentDevice);
214 214 if (ACPI_FAILURE (Status))
215 215 {
216 216 return (Status);
217 217 }
218 218
219 219 /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */
220 220
221 221 if (ParentDevice == RootPciDevice)
222 222 {
223 223 *ReturnListHead = ListHead;
224 224 return (AE_OK);
225 225 }
226 226
227 227 ListElement = ACPI_ALLOCATE (sizeof (ACPI_PCI_DEVICE));
228 228 if (!ListElement)
229 229 {
230 230 return (AE_NO_MEMORY);
231 231 }
232 232
233 233 /* Put new element at the head of the list */
234 234
235 235 ListElement->Next = ListHead;
236 236 ListElement->Device = ParentDevice;
237 237 ListHead = ListElement;
238 238
239 239 CurrentDevice = ParentDevice;
240 240 }
241 241 }
242 242
243 243
244 244 /*******************************************************************************
245 245 *
246 246 * FUNCTION: AcpiHwProcessPciList
247 247 *
248 248 * PARAMETERS: PciId - Initial values for the PCI ID. May be
249 249 * modified by this function.
250 250 * ListHead - Device list created by
251 251 * AcpiHwBuildPciList
252 252 *
253 253 * RETURN: Status
254 254 *
255 255 * DESCRIPTION: Walk downward through the PCI device list, getting the device
256 256 * info for each, via the PCI configuration space and updating
257 257 * the PCI ID as necessary. Deletes the list during traversal.
258 258 *
259 259 ******************************************************************************/
260 260
261 261 static ACPI_STATUS
262 262 AcpiHwProcessPciList (
263 263 ACPI_PCI_ID *PciId,
264 264 ACPI_PCI_DEVICE *ListHead)
265 265 {
266 266 ACPI_STATUS Status = AE_OK;
267 267 ACPI_PCI_DEVICE *Info;
268 268 UINT16 BusNumber;
269 269 BOOLEAN IsBridge = TRUE;
270 270
271 271
272 272 ACPI_FUNCTION_NAME (HwProcessPciList);
273 273
274 274
275 275 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
276 276 "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
277 277 PciId->Segment, PciId->Bus, PciId->Device, PciId->Function));
278 278
279 279 BusNumber = PciId->Bus;
280 280
281 281 /*
282 282 * Descend down the namespace tree, collecting PCI device, function,
283 283 * and bus numbers. BusNumber is only important for PCI bridges.
284 284 * Algorithm: As we descend the tree, use the last valid PCI device,
↓ open down ↓ |
266 lines elided |
↑ open up ↑ |
285 285 * function, and bus numbers that are discovered, and assign them
286 286 * to the PCI ID for the target device.
287 287 */
288 288 Info = ListHead;
289 289 while (Info)
290 290 {
291 291 Status = AcpiHwGetPciDeviceInfo (PciId, Info->Device,
292 292 &BusNumber, &IsBridge);
293 293 if (ACPI_FAILURE (Status))
294 294 {
295 - return_ACPI_STATUS (Status);
295 + return (Status);
296 296 }
297 297
298 298 Info = Info->Next;
299 299 }
300 300
301 301 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
302 302 "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X "
303 303 "Status %X BusNumber %X IsBridge %X\n",
304 304 PciId->Segment, PciId->Bus, PciId->Device, PciId->Function,
305 305 Status, BusNumber, IsBridge));
306 306
307 - return_ACPI_STATUS (AE_OK);
307 + return (AE_OK);
308 308 }
309 309
310 310
311 311 /*******************************************************************************
312 312 *
313 313 * FUNCTION: AcpiHwDeletePciList
314 314 *
315 315 * PARAMETERS: ListHead - Device list created by
316 316 * AcpiHwBuildPciList
317 317 *
318 318 * RETURN: None
319 319 *
320 320 * DESCRIPTION: Free the entire PCI list.
321 321 *
322 322 ******************************************************************************/
323 323
324 324 static void
325 325 AcpiHwDeletePciList (
326 326 ACPI_PCI_DEVICE *ListHead)
327 327 {
328 328 ACPI_PCI_DEVICE *Next;
329 329 ACPI_PCI_DEVICE *Previous;
330 330
331 331
332 332 Next = ListHead;
333 333 while (Next)
334 334 {
335 335 Previous = Next;
336 336 Next = Previous->Next;
337 337 ACPI_FREE (Previous);
338 338 }
339 339 }
340 340
341 341
342 342 /*******************************************************************************
343 343 *
344 344 * FUNCTION: AcpiHwGetPciDeviceInfo
345 345 *
346 346 * PARAMETERS: PciId - Initial values for the PCI ID. May be
347 347 * modified by this function.
348 348 * PciDevice - Handle for the PCI device object
349 349 * BusNumber - Where a PCI bridge bus number is returned
350 350 * IsBridge - Return value, indicates if this PCI
351 351 * device is a PCI bridge
352 352 *
353 353 * RETURN: Status
354 354 *
355 355 * DESCRIPTION: Get the device info for a single PCI device object. Get the
356 356 * _ADR (contains PCI device and function numbers), and for PCI
357 357 * bridge devices, get the bus number from PCI configuration
358 358 * space.
359 359 *
360 360 ******************************************************************************/
361 361
362 362 static ACPI_STATUS
363 363 AcpiHwGetPciDeviceInfo (
364 364 ACPI_PCI_ID *PciId,
365 365 ACPI_HANDLE PciDevice,
366 366 UINT16 *BusNumber,
367 367 BOOLEAN *IsBridge)
368 368 {
369 369 ACPI_STATUS Status;
370 370 ACPI_OBJECT_TYPE ObjectType;
371 371 UINT64 ReturnValue;
372 372 UINT64 PciValue;
373 373
374 374
375 375 /* We only care about objects of type Device */
376 376
377 377 Status = AcpiGetType (PciDevice, &ObjectType);
378 378 if (ACPI_FAILURE (Status))
379 379 {
380 380 return (Status);
381 381 }
382 382
383 383 if (ObjectType != ACPI_TYPE_DEVICE)
384 384 {
385 385 return (AE_OK);
386 386 }
387 387
388 388 /* We need an _ADR. Ignore device if not present */
389 389
390 390 Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR,
391 391 PciDevice, &ReturnValue);
392 392 if (ACPI_FAILURE (Status))
393 393 {
394 394 return (AE_OK);
395 395 }
396 396
397 397 /*
398 398 * From _ADR, get the PCI Device and Function and
399 399 * update the PCI ID.
400 400 */
401 401 PciId->Device = ACPI_HIWORD (ACPI_LODWORD (ReturnValue));
402 402 PciId->Function = ACPI_LOWORD (ACPI_LODWORD (ReturnValue));
403 403
404 404 /*
405 405 * If the previous device was a bridge, use the previous
406 406 * device bus number
407 407 */
408 408 if (*IsBridge)
409 409 {
410 410 PciId->Bus = *BusNumber;
411 411 }
412 412
413 413 /*
414 414 * Get the bus numbers from PCI Config space:
415 415 *
416 416 * First, get the PCI HeaderType
417 417 */
418 418 *IsBridge = FALSE;
419 419 Status = AcpiOsReadPciConfiguration (PciId,
420 420 PCI_CFG_HEADER_TYPE_REG, &PciValue, 8);
421 421 if (ACPI_FAILURE (Status))
422 422 {
423 423 return (Status);
424 424 }
425 425
426 426 /* We only care about bridges (1=PciBridge, 2=CardBusBridge) */
427 427
428 428 PciValue &= PCI_HEADER_TYPE_MASK;
429 429
430 430 if ((PciValue != PCI_TYPE_BRIDGE) &&
431 431 (PciValue != PCI_TYPE_CARDBUS_BRIDGE))
432 432 {
433 433 return (AE_OK);
434 434 }
435 435
436 436 /* Bridge: Get the Primary BusNumber */
437 437
438 438 Status = AcpiOsReadPciConfiguration (PciId,
439 439 PCI_CFG_PRIMARY_BUS_NUMBER_REG, &PciValue, 8);
440 440 if (ACPI_FAILURE (Status))
441 441 {
442 442 return (Status);
443 443 }
444 444
445 445 *IsBridge = TRUE;
446 446 PciId->Bus = (UINT16) PciValue;
447 447
448 448 /* Bridge: Get the Secondary BusNumber */
449 449
450 450 Status = AcpiOsReadPciConfiguration (PciId,
451 451 PCI_CFG_SECONDARY_BUS_NUMBER_REG, &PciValue, 8);
452 452 if (ACPI_FAILURE (Status))
453 453 {
454 454 return (Status);
455 455 }
456 456
457 457 *BusNumber = (UINT16) PciValue;
458 458 return (AE_OK);
459 459 }
↓ open down ↓ |
142 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX