]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
Code scrub for PCI Bus module and PciIncompatibleDeviceSupportLib module.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciEnumerator.c
CommitLineData
97404058 1/** @file\r
8e8227d1 2 PCI eunmeration implementation on entire PCI bus system for PCI Bus module.\r
ead42efc 3\r
8e8227d1 4Copyright (c) 2006 - 2009, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
ead42efc 9\r
8e8227d1 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
ead42efc 12\r
8e8227d1 13**/\r
ead42efc 14\r
03417d8d 15#include "PciBus.h"\r
ead42efc 16\r
bcd70414 17/**\r
ead42efc 18 This routine is used to enumerate entire pci bus system\r
97404058 19 in a given platform.\r
ead42efc 20\r
97404058 21 @param Controller Parent controller handle.\r
8e8227d1 22\r
23 @retval EFI_SUCCESS PCI enumeration finished successfully.\r
24 @retval other Some error occurred when enumerating the pci bus system.\r
25\r
bcd70414 26**/\r
a3b8e257 27EFI_STATUS\r
28PciEnumerator (\r
29 IN EFI_HANDLE Controller\r
30 )\r
ead42efc 31{\r
32\r
33 EFI_HANDLE HostBridgeHandle;\r
34 EFI_STATUS Status;\r
35 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;\r
36 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
37\r
38 //\r
39 // If PCI bus has already done the full enumeration, never do it again\r
40 //\r
41 if (!gFullEnumeration) {\r
42 return PciEnumeratorLight (Controller);\r
43 }\r
44\r
ead42efc 45 //\r
46 // Get the rootbridge Io protocol to find the host bridge handle\r
47 //\r
48 Status = gBS->OpenProtocol (\r
49 Controller,\r
50 &gEfiPciRootBridgeIoProtocolGuid,\r
51 (VOID **) &PciRootBridgeIo,\r
52 gPciBusDriverBinding.DriverBindingHandle,\r
53 Controller,\r
54 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
55 );\r
56\r
57 if (EFI_ERROR (Status)) {\r
58 return Status;\r
59 }\r
60\r
61 //\r
62 // Get the host bridge handle\r
63 //\r
64 HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
65\r
66 //\r
67 // Get the pci host bridge resource allocation protocol\r
68 //\r
69 Status = gBS->OpenProtocol (\r
70 HostBridgeHandle,\r
71 &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
72 (VOID **) &PciResAlloc,\r
73 gPciBusDriverBinding.DriverBindingHandle,\r
74 Controller,\r
75 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
76 );\r
77\r
78 if (EFI_ERROR (Status)) {\r
79 return Status;\r
80 }\r
81\r
82 //\r
83 // Notify the pci bus enumeration is about to begin\r
84 //\r
85 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);\r
86\r
87 //\r
88 // Start the bus allocation phase\r
89 //\r
90 Status = PciHostBridgeEnumerator (PciResAlloc);\r
91\r
92 if (EFI_ERROR (Status)) {\r
93 return Status;\r
94 }\r
95\r
96 //\r
97 // Submit the resource request\r
98 //\r
99 Status = PciHostBridgeResourceAllocator (PciResAlloc);\r
100\r
101 if (EFI_ERROR (Status)) {\r
102 return Status;\r
103 }\r
104\r
105 //\r
106 // Process P2C\r
107 //\r
108 Status = PciHostBridgeP2CProcess (PciResAlloc);\r
109\r
110 if (EFI_ERROR (Status)) {\r
111 return Status;\r
112 }\r
113\r
114 //\r
115 // Process attributes for devices on this host bridge\r
116 //\r
117 Status = PciHostBridgeDeviceAttribute (PciResAlloc);\r
118 if (EFI_ERROR (Status)) {\r
119 return Status;\r
120 }\r
121\r
122 gFullEnumeration = FALSE;\r
123\r
124 return EFI_SUCCESS;\r
125}\r
126\r
a3b8e257 127/**\r
8e8227d1 128 Enumerate PCI root bridge.\r
129\r
97404058 130 @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
131 @param RootBridgeDev Instance of root bridge device.\r
8e8227d1 132\r
133 @retval EFI_SUCCESS Successfully enumerated root bridge.\r
134 @retval other Failed to enumerate root bridge.\r
135\r
a3b8e257 136**/\r
ead42efc 137EFI_STATUS\r
138PciRootBridgeEnumerator (\r
139 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
140 IN PCI_IO_DEVICE *RootBridgeDev\r
141 )\r
ead42efc 142{\r
143 EFI_STATUS Status;\r
5326528b 144 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
ead42efc 145 UINT8 SubBusNumber;\r
146 UINT8 StartBusNumber;\r
147 UINT8 PaddedBusRange;\r
148 EFI_HANDLE RootBridgeHandle;\r
149\r
150 SubBusNumber = 0;\r
151 StartBusNumber = 0;\r
152 PaddedBusRange = 0;\r
153\r
154 //\r
155 // Get the root bridge handle\r
156 //\r
157 RootBridgeHandle = RootBridgeDev->Handle;\r
158\r
159 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
160 EFI_PROGRESS_CODE,\r
161 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,\r
162 RootBridgeDev->DevicePath\r
163 );\r
164\r
165 //\r
166 // Get the Bus information\r
167 //\r
168 Status = PciResAlloc->StartBusEnumeration (\r
169 PciResAlloc,\r
170 RootBridgeHandle,\r
5326528b 171 (VOID **) &Configuration\r
ead42efc 172 );\r
173\r
174 if (EFI_ERROR (Status)) {\r
175 return Status;\r
176 }\r
177\r
178 //\r
179 // Get the bus number to start with\r
180 //\r
5326528b 181 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
182 PaddedBusRange = (UINT8) (Configuration->AddrRangeMax);\r
ead42efc 183\r
184 //\r
185 // Initialize the subordinate bus number\r
186 //\r
187 SubBusNumber = StartBusNumber;\r
188\r
ff62de37 189 //\r
190 // Reset all assigned PCI bus number\r
191 //\r
192 ResetAllPpbBusNumber (\r
8e8227d1 193 RootBridgeDev,\r
ff62de37 194 StartBusNumber\r
195 );\r
196\r
ead42efc 197 //\r
198 // Assign bus number\r
199 //\r
200 Status = PciScanBus (\r
201 RootBridgeDev,\r
5326528b 202 (UINT8) (Configuration->AddrRangeMin),\r
ead42efc 203 &SubBusNumber,\r
204 &PaddedBusRange\r
205 );\r
206\r
207 if (EFI_ERROR (Status)) {\r
208 return Status;\r
209 }\r
210\r
211\r
212 //\r
213 // Assign max bus number scanned\r
214 //\r
5326528b 215 Configuration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;\r
ead42efc 216\r
217 //\r
218 // Set bus number\r
219 //\r
220 Status = PciResAlloc->SetBusNumbers (\r
221 PciResAlloc,\r
222 RootBridgeHandle,\r
5326528b 223 Configuration\r
ead42efc 224 );\r
8e8227d1 225\r
48a9ea7b 226 FreePool (Configuration);\r
8e8227d1 227\r
ead42efc 228 if (EFI_ERROR (Status)) {\r
229 return Status;\r
230 }\r
231\r
232 return EFI_SUCCESS;\r
233}\r
234\r
a3b8e257 235/**\r
8e8227d1 236 This routine is used to process all PCI devices' Option Rom\r
237 on a certain root bridge.\r
238\r
239 @param Bridge Given parent's root bridge.\r
240 @param RomBase Base address of ROM driver loaded from.\r
241 @param MaxLength Maximum rom size.\r
242\r
a3b8e257 243**/\r
8e8227d1 244VOID\r
ead42efc 245ProcessOptionRom (\r
246 IN PCI_IO_DEVICE *Bridge,\r
247 IN UINT64 RomBase,\r
248 IN UINT64 MaxLength\r
249 )\r
ead42efc 250{\r
251 LIST_ENTRY *CurrentLink;\r
252 PCI_IO_DEVICE *Temp;\r
ead42efc 253\r
254 //\r
255 // Go through bridges to reach all devices\r
256 //\r
257 CurrentLink = Bridge->ChildList.ForwardLink;\r
97404058 258 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
ead42efc 259 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
260 if (!IsListEmpty (&Temp->ChildList)) {\r
261\r
262 //\r
263 // Go further to process the option rom under this bridge\r
264 //\r
eb9a9a5e 265 ProcessOptionRom (Temp, RomBase, MaxLength);\r
ead42efc 266 }\r
267\r
268 if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {\r
269\r
270 //\r
271 // Load and process the option rom\r
272 //\r
eb9a9a5e 273 LoadOpRomImage (Temp, RomBase);\r
ead42efc 274 }\r
275\r
276 CurrentLink = CurrentLink->ForwardLink;\r
277 }\r
ead42efc 278}\r
279\r
a3b8e257 280/**\r
281 This routine is used to assign bus number to the given PCI bus system\r
8e8227d1 282\r
283 @param Bridge Parent root bridge instance.\r
284 @param StartBusNumber Number of beginning.\r
285 @param SubBusNumber The number of sub bus.\r
286\r
287 @retval EFI_SUCCESS Successfully assigned bus number.\r
288 @retval EFI_DEVICE_ERROR Failed to assign bus number.\r
289\r
a3b8e257 290**/\r
ead42efc 291EFI_STATUS\r
292PciAssignBusNumber (\r
293 IN PCI_IO_DEVICE *Bridge,\r
294 IN UINT8 StartBusNumber,\r
295 OUT UINT8 *SubBusNumber\r
296 )\r
ead42efc 297{\r
298 EFI_STATUS Status;\r
299 PCI_TYPE00 Pci;\r
300 UINT8 Device;\r
301 UINT8 Func;\r
302 UINT64 Address;\r
303 UINTN SecondBus;\r
304 UINT16 Register;\r
305 UINT8 Register8;\r
306 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
307\r
308 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
309\r
310 SecondBus = 0;\r
311 Register = 0;\r
312\r
313 *SubBusNumber = StartBusNumber;\r
314\r
315 //\r
316 // First check to see whether the parent is ppb\r
317 //\r
318 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
319 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
320\r
321 //\r
322 // Check to see whether a pci device is present\r
323 //\r
ead42efc 324 Status = PciDevicePresent (\r
325 PciRootBridgeIo,\r
326 &Pci,\r
327 StartBusNumber,\r
328 Device,\r
329 Func\r
330 );\r
331\r
332 if (!EFI_ERROR (Status) &&\r
333 (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
334\r
335 //\r
336 // Reserved one bus for cardbus bridge\r
337 //\r
338 SecondBus = ++(*SubBusNumber);\r
339\r
340 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
341\r
342 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
343\r
344 Status = PciRootBridgeIoWrite (\r
345 PciRootBridgeIo,\r
346 &Pci,\r
347 EfiPciWidthUint16,\r
348 Address,\r
349 1,\r
350 &Register\r
351 );\r
352\r
353 //\r
354 // Initialize SubBusNumber to SecondBus\r
355 //\r
356 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
357 Status = PciRootBridgeIoWrite (\r
358 PciRootBridgeIo,\r
359 &Pci,\r
360 EfiPciWidthUint8,\r
361 Address,\r
362 1,\r
363 SubBusNumber\r
364 );\r
365 //\r
366 // If it is PPB, resursively search down this bridge\r
367 //\r
368 if (IS_PCI_BRIDGE (&Pci)) {\r
369\r
370 Register8 = 0xFF;\r
371 Status = PciRootBridgeIoWrite (\r
372 PciRootBridgeIo,\r
373 &Pci,\r
374 EfiPciWidthUint8,\r
375 Address,\r
376 1,\r
377 &Register8\r
378 );\r
379\r
380 Status = PciAssignBusNumber (\r
381 Bridge,\r
382 (UINT8) (SecondBus),\r
383 SubBusNumber\r
384 );\r
385\r
386 if (EFI_ERROR (Status)) {\r
387 return EFI_DEVICE_ERROR;\r
388 }\r
389 }\r
390\r
391 //\r
392 // Set the current maximum bus number under the PPB\r
393 //\r
ead42efc 394 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
395\r
396 Status = PciRootBridgeIoWrite (\r
397 PciRootBridgeIo,\r
398 &Pci,\r
399 EfiPciWidthUint8,\r
400 Address,\r
401 1,\r
402 SubBusNumber\r
403 );\r
404\r
405 }\r
406\r
407 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
408\r
409 //\r
410 // Skip sub functions, this is not a multi function device\r
411 //\r
ead42efc 412 Func = PCI_MAX_FUNC;\r
413 }\r
414 }\r
415 }\r
416\r
417 return EFI_SUCCESS;\r
418}\r
419\r
bcd70414 420/**\r
ead42efc 421 This routine is used to determine the root bridge attribute by interfacing\r
422 the host bridge resource allocation protocol.\r
423\r
a3b8e257 424 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
425 @param RootBridgeDev Root bridge instance\r
8e8227d1 426\r
427 @retval EFI_SUCCESS Successfully got root bridge's attribute.\r
428 @retval other Failed to get attribute.\r
429\r
bcd70414 430**/\r
a3b8e257 431EFI_STATUS\r
432DetermineRootBridgeAttributes (\r
433 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
434 IN PCI_IO_DEVICE *RootBridgeDev\r
435 )\r
ead42efc 436{\r
437 UINT64 Attributes;\r
438 EFI_STATUS Status;\r
439 EFI_HANDLE RootBridgeHandle;\r
440\r
441 Attributes = 0;\r
442 RootBridgeHandle = RootBridgeDev->Handle;\r
443\r
444 //\r
445 // Get root bridge attribute by calling into pci host bridge resource allocation protocol\r
446 //\r
447 Status = PciResAlloc->GetAllocAttributes (\r
448 PciResAlloc,\r
449 RootBridgeHandle,\r
450 &Attributes\r
451 );\r
452\r
453 if (EFI_ERROR (Status)) {\r
454 return Status;\r
455 }\r
456\r
457 //\r
458 // Here is the point where PCI bus driver calls HOST bridge allocation protocol\r
459 // Currently we hardcoded for ea815\r
460 //\r
97404058 461 if ((Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
ead42efc 462 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;\r
463 }\r
464\r
97404058 465 if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0) {\r
ead42efc 466 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
467 }\r
468\r
469 RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
470 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
471 RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
472\r
473 return EFI_SUCCESS;\r
474}\r
475\r
a3b8e257 476/**\r
8e8227d1 477 Get Max Option Rom size on specified bridge.\r
478\r
479 @param Bridge Given bridge device instance.\r
480\r
481 @return Max size of option rom needed.\r
482\r
a3b8e257 483**/\r
ead42efc 484UINT64\r
485GetMaxOptionRomSize (\r
486 IN PCI_IO_DEVICE *Bridge\r
487 )\r
ead42efc 488{\r
489 LIST_ENTRY *CurrentLink;\r
490 PCI_IO_DEVICE *Temp;\r
491 UINT64 MaxOptionRomSize;\r
492 UINT64 TempOptionRomSize;\r
493\r
494 MaxOptionRomSize = 0;\r
495\r
496 //\r
497 // Go through bridges to reach all devices\r
498 //\r
499 CurrentLink = Bridge->ChildList.ForwardLink;\r
97404058 500 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
ead42efc 501 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
502 if (!IsListEmpty (&Temp->ChildList)) {\r
503\r
504 //\r
505 // Get max option rom size under this bridge\r
506 //\r
507 TempOptionRomSize = GetMaxOptionRomSize (Temp);\r
508\r
509 //\r
510 // Compare with the option rom size of the bridge\r
511 // Get the larger one\r
512 //\r
513 if (Temp->RomSize > TempOptionRomSize) {\r
514 TempOptionRomSize = Temp->RomSize;\r
515 }\r
516\r
517 } else {\r
518\r
519 //\r
520 // For devices get the rom size directly\r
521 //\r
522 TempOptionRomSize = Temp->RomSize;\r
523 }\r
524\r
525 //\r
526 // Get the largest rom size on this bridge\r
527 //\r
528 if (TempOptionRomSize > MaxOptionRomSize) {\r
529 MaxOptionRomSize = TempOptionRomSize;\r
530 }\r
531\r
532 CurrentLink = CurrentLink->ForwardLink;\r
533 }\r
534\r
535 return MaxOptionRomSize;\r
536}\r
537\r
a3b8e257 538/**\r
539 Process attributes of devices on this host bridge\r
8e8227d1 540\r
97404058 541 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
8e8227d1 542\r
543 @retval EFI_SUCCESS Successfully process attribute.\r
97404058 544 @retval EFI_NOT_FOUND Can not find the specific root bridge device.\r
8e8227d1 545 @retval other Failed to determine the root bridge device's attribute.\r
546\r
a3b8e257 547**/\r
ead42efc 548EFI_STATUS\r
549PciHostBridgeDeviceAttribute (\r
550 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
551 )\r
ead42efc 552{\r
553 EFI_HANDLE RootBridgeHandle;\r
554 PCI_IO_DEVICE *RootBridgeDev;\r
555 EFI_STATUS Status;\r
556\r
557 RootBridgeHandle = NULL;\r
558\r
559 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
560\r
561 //\r
562 // Get RootBridg Device by handle\r
563 //\r
564 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
565\r
566 if (RootBridgeDev == NULL) {\r
567 return EFI_NOT_FOUND;\r
568 }\r
569\r
570 //\r
571 // Set the attributes for devcies behind the Root Bridge\r
572 //\r
573 Status = DetermineDeviceAttribute (RootBridgeDev);\r
574 if (EFI_ERROR (Status)) {\r
575 return Status;\r
576 }\r
577\r
578 }\r
579\r
580 return EFI_SUCCESS;\r
581}\r
582\r
a3b8e257 583/**\r
8e8227d1 584 Get resource allocation status from the ACPI resource descriptor.\r
585\r
586 @param AcpiConfig Point to Acpi configuration table.\r
587 @param IoResStatus Return the status of I/O resource.\r
588 @param Mem32ResStatus Return the status of 32-bit Memory resource.\r
589 @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.\r
590 @param Mem64ResStatus Return the status of 64-bit Memory resource.\r
591 @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.\r
592\r
a3b8e257 593**/\r
8e8227d1 594VOID\r
ead42efc 595GetResourceAllocationStatus (\r
596 VOID *AcpiConfig,\r
597 OUT UINT64 *IoResStatus,\r
598 OUT UINT64 *Mem32ResStatus,\r
599 OUT UINT64 *PMem32ResStatus,\r
600 OUT UINT64 *Mem64ResStatus,\r
601 OUT UINT64 *PMem64ResStatus\r
602 )\r
ead42efc 603{\r
ead42efc 604 UINT8 *Temp;\r
605 UINT64 ResStatus;\r
5326528b 606 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ACPIAddressDesc;\r
ead42efc 607\r
608 Temp = (UINT8 *) AcpiConfig;\r
609\r
610 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
611\r
5326528b 612 ACPIAddressDesc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
613 ResStatus = ACPIAddressDesc->AddrTranslationOffset;\r
ead42efc 614\r
5326528b 615 switch (ACPIAddressDesc->ResType) {\r
ead42efc 616 case 0:\r
5326528b 617 if (ACPIAddressDesc->AddrSpaceGranularity == 32) {\r
618 if (ACPIAddressDesc->SpecificFlag == 0x06) {\r
ead42efc 619 //\r
620 // Pmem32\r
621 //\r
622 *PMem32ResStatus = ResStatus;\r
623 } else {\r
624 //\r
625 // Mem32\r
626 //\r
627 *Mem32ResStatus = ResStatus;\r
628 }\r
629 }\r
630\r
5326528b 631 if (ACPIAddressDesc->AddrSpaceGranularity == 64) {\r
632 if (ACPIAddressDesc->SpecificFlag == 0x06) {\r
ead42efc 633 //\r
634 // PMem64\r
635 //\r
636 *PMem64ResStatus = ResStatus;\r
637 } else {\r
638 //\r
639 // Mem64\r
640 //\r
641 *Mem64ResStatus = ResStatus;\r
642 }\r
643 }\r
644\r
645 break;\r
646\r
647 case 1:\r
648 //\r
649 // Io\r
650 //\r
651 *IoResStatus = ResStatus;\r
652 break;\r
653\r
654 default:\r
655 break;\r
656 }\r
657\r
658 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
659 }\r
ead42efc 660}\r
661\r
a3b8e257 662/**\r
8e8227d1 663 Remove a PCI device from device pool and mark its bar.\r
664\r
97404058 665 @param PciDevice Instance of Pci device.\r
8e8227d1 666\r
667 @retval EFI_SUCCESS Successfully remove the PCI device.\r
668 @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.\r
669\r
a3b8e257 670**/\r
ead42efc 671EFI_STATUS\r
672RejectPciDevice (\r
673 IN PCI_IO_DEVICE *PciDevice\r
674 )\r
ead42efc 675{\r
676 PCI_IO_DEVICE *Bridge;\r
677 PCI_IO_DEVICE *Temp;\r
678 LIST_ENTRY *CurrentLink;\r
679\r
680 //\r
681 // Remove the padding resource from a bridge\r
682 //\r
8e8227d1 683 if ( IS_PCI_BRIDGE(&PciDevice->Pci) &&\r
97404058 684 PciDevice->ResourcePaddingDescriptors != NULL ) {\r
48a9ea7b 685 FreePool (PciDevice->ResourcePaddingDescriptors);\r
ead42efc 686 PciDevice->ResourcePaddingDescriptors = NULL;\r
687 return EFI_SUCCESS;\r
688 }\r
689\r
690 //\r
691 // Skip RB and PPB\r
692 //\r
97404058 693 if (IS_PCI_BRIDGE (&PciDevice->Pci) || (PciDevice->Parent == NULL)) {\r
ead42efc 694 return EFI_ABORTED;\r
695 }\r
696\r
697 if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {\r
698 //\r
699 // Get the root bridge device\r
700 //\r
701 Bridge = PciDevice;\r
97404058 702 while (Bridge->Parent != NULL) {\r
ead42efc 703 Bridge = Bridge->Parent;\r
704 }\r
705\r
706 RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);\r
707\r
708 //\r
709 // Mark its bar\r
710 //\r
711 InitializeP2C (PciDevice);\r
712 }\r
713\r
714 //\r
715 // Remove the device\r
716 //\r
717 Bridge = PciDevice->Parent;\r
718 CurrentLink = Bridge->ChildList.ForwardLink;\r
97404058 719 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
ead42efc 720 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
721 if (Temp == PciDevice) {\r
722 InitializePciDevice (Temp);\r
723 RemoveEntryList (CurrentLink);\r
724 FreePciDevice (Temp);\r
725 return EFI_SUCCESS;\r
726 }\r
727\r
728 CurrentLink = CurrentLink->ForwardLink;\r
729 }\r
730\r
731 return EFI_ABORTED;\r
732}\r
733\r
a3b8e257 734/**\r
97404058 735 Determine whethter a PCI device can be rejected.\r
8e8227d1 736\r
737 @param PciResNode Pointer to Pci resource node instance.\r
738\r
739 @retval TRUE The PCI device can be rejected.\r
740 @retval TRUE The PCI device cannot be rejected.\r
741\r
a3b8e257 742**/\r
ead42efc 743BOOLEAN\r
744IsRejectiveDevice (\r
745 IN PCI_RESOURCE_NODE *PciResNode\r
746 )\r
ead42efc 747{\r
748 PCI_IO_DEVICE *Temp;\r
749\r
750 Temp = PciResNode->PciDev;\r
751\r
752 //\r
753 // Ensure the device is present\r
754 //\r
97404058 755 if (Temp == NULL) {\r
ead42efc 756 return FALSE;\r
757 }\r
758\r
759 //\r
760 // PPB and RB should go ahead\r
761 //\r
97404058 762 if (IS_PCI_BRIDGE (&Temp->Pci) || (Temp->Parent == NULL)) {\r
ead42efc 763 return TRUE;\r
764 }\r
765\r
766 //\r
767 // Skip device on Bus0\r
768 //\r
97404058 769 if ((Temp->Parent != NULL) && (Temp->BusNumber == 0)) {\r
ead42efc 770 return FALSE;\r
771 }\r
772\r
773 //\r
774 // Skip VGA\r
775 //\r
776 if (IS_PCI_VGA (&Temp->Pci)) {\r
777 return FALSE;\r
778 }\r
779\r
780 return TRUE;\r
781}\r
782\r
a3b8e257 783/**\r
8e8227d1 784 Compare two resource nodes and get the larger resource consumer.\r
785\r
a3b8e257 786 @param PciResNode1 resource node 1 want to be compared\r
787 @param PciResNode2 resource node 2 want to be compared\r
8e8227d1 788\r
789 @return Larger resource node.\r
790\r
a3b8e257 791**/\r
ead42efc 792PCI_RESOURCE_NODE *\r
793GetLargerConsumerDevice (\r
794 IN PCI_RESOURCE_NODE *PciResNode1,\r
795 IN PCI_RESOURCE_NODE *PciResNode2\r
796 )\r
ead42efc 797{\r
97404058 798 if (PciResNode2 == NULL) {\r
ead42efc 799 return PciResNode1;\r
800 }\r
801\r
97404058 802 if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || (PciResNode2->PciDev->Parent == NULL)) \\r
ead42efc 803 && (PciResNode2->ResourceUsage != PciResUsagePadding) )\r
804 {\r
805 return PciResNode1;\r
806 }\r
807\r
97404058 808 if (PciResNode1 == NULL) {\r
ead42efc 809 return PciResNode2;\r
810 }\r
811\r
812 if ((PciResNode1->Length) > (PciResNode2->Length)) {\r
813 return PciResNode1;\r
814 }\r
815\r
816 return PciResNode2;\r
ead42efc 817}\r
818\r
a3b8e257 819\r
820/**\r
97404058 821 Get the max resource consumer in the host resource pool.\r
8e8227d1 822\r
97404058 823 @param ResPool Pointer to resource pool node.\r
8e8227d1 824\r
825 @return The max resource consumer in the host resource pool.\r
826\r
a3b8e257 827**/\r
ead42efc 828PCI_RESOURCE_NODE *\r
829GetMaxResourceConsumerDevice (\r
830 IN PCI_RESOURCE_NODE *ResPool\r
831 )\r
ead42efc 832{\r
833 PCI_RESOURCE_NODE *Temp;\r
834 LIST_ENTRY *CurrentLink;\r
835 PCI_RESOURCE_NODE *PciResNode;\r
836 PCI_RESOURCE_NODE *PPBResNode;\r
837\r
838 PciResNode = NULL;\r
839\r
840 CurrentLink = ResPool->ChildList.ForwardLink;\r
97404058 841 while (CurrentLink != NULL && CurrentLink != &ResPool->ChildList) {\r
ead42efc 842\r
843 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
844\r
845 if (!IsRejectiveDevice (Temp)) {\r
846 CurrentLink = CurrentLink->ForwardLink;\r
847 continue;\r
848 }\r
849\r
97404058 850 if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (Temp->PciDev->Parent == NULL)) \\r
ead42efc 851 && (Temp->ResourceUsage != PciResUsagePadding))\r
852 {\r
853 PPBResNode = GetMaxResourceConsumerDevice (Temp);\r
854 PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);\r
855 } else {\r
856 PciResNode = GetLargerConsumerDevice (PciResNode, Temp);\r
857 }\r
858\r
859 CurrentLink = CurrentLink->ForwardLink;\r
860 }\r
861\r
862 return PciResNode;\r
863}\r
864\r
a3b8e257 865/**\r
866 Adjust host bridge allocation so as to reduce resource requirement\r
8e8227d1 867\r
97404058 868 @param IoPool Pointer to instance of I/O resource Node.\r
869 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.\r
8e8227d1 870 @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.\r
97404058 871 @param Mem64Pool Pointer to instance of 64-bit memory resource node.\r
8e8227d1 872 @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.\r
97404058 873 @param IoResStatus Status of I/O resource Node.\r
874 @param Mem32ResStatus Status of 32-bit memory resource Node.\r
8e8227d1 875 @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.\r
97404058 876 @param Mem64ResStatus Status of 64-bit memory resource node.\r
8e8227d1 877 @param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.\r
878\r
879 @retval EFI_SUCCESS Successfully adjusted resoruce on host bridge.\r
880 @retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.\r
881\r
a3b8e257 882**/\r
ead42efc 883EFI_STATUS\r
884PciHostBridgeAdjustAllocation (\r
885 IN PCI_RESOURCE_NODE *IoPool,\r
886 IN PCI_RESOURCE_NODE *Mem32Pool,\r
887 IN PCI_RESOURCE_NODE *PMem32Pool,\r
888 IN PCI_RESOURCE_NODE *Mem64Pool,\r
889 IN PCI_RESOURCE_NODE *PMem64Pool,\r
890 IN UINT64 IoResStatus,\r
891 IN UINT64 Mem32ResStatus,\r
892 IN UINT64 PMem32ResStatus,\r
893 IN UINT64 Mem64ResStatus,\r
894 IN UINT64 PMem64ResStatus\r
895 )\r
ead42efc 896{\r
897 BOOLEAN AllocationAjusted;\r
898 PCI_RESOURCE_NODE *PciResNode;\r
899 PCI_RESOURCE_NODE *ResPool[5];\r
900 PCI_IO_DEVICE *RemovedPciDev[5];\r
901 UINT64 ResStatus[5];\r
902 UINTN RemovedPciDevNum;\r
903 UINTN DevIndex;\r
904 UINTN ResType;\r
905 EFI_STATUS Status;\r
1d6d9e7e 906 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
ead42efc 907\r
908 PciResNode = NULL;\r
909 ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));\r
910 RemovedPciDevNum = 0;\r
911\r
912 ResPool[0] = IoPool;\r
913 ResPool[1] = Mem32Pool;\r
914 ResPool[2] = PMem32Pool;\r
915 ResPool[3] = Mem64Pool;\r
916 ResPool[4] = PMem64Pool;\r
917\r
918 ResStatus[0] = IoResStatus;\r
919 ResStatus[1] = Mem32ResStatus;\r
920 ResStatus[2] = PMem32ResStatus;\r
921 ResStatus[3] = Mem64ResStatus;\r
922 ResStatus[4] = PMem64ResStatus;\r
923\r
924 AllocationAjusted = FALSE;\r
925\r
926 for (ResType = 0; ResType < 5; ResType++) {\r
927\r
928 if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {\r
929 continue;\r
930 }\r
931\r
7508355e 932 if (ResStatus[ResType] == EFI_RESOURCE_NOT_SATISFIED) {\r
ead42efc 933 //\r
8e8227d1 934 // Host bridge hasn't this resource type\r
ead42efc 935 //\r
936 return EFI_ABORTED;\r
937 }\r
938\r
939 //\r
940 // Hostbridge hasn't enough resource\r
941 //\r
942 PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);\r
97404058 943 if (PciResNode == NULL) {\r
ead42efc 944 continue;\r
945 }\r
946\r
947 //\r
948 // Check if the device has been removed before\r
949 //\r
950 for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {\r
951 if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {\r
a1d887b7 952 break;\r
ead42efc 953 }\r
954 }\r
a1d887b7 955\r
956 if (DevIndex != RemovedPciDevNum) {\r
957 continue;\r
958 }\r
ead42efc 959\r
960 //\r
961 // Remove the device if it isn't in the array\r
962 //\r
963 Status = RejectPciDevice (PciResNode->PciDev);\r
964 if (Status == EFI_SUCCESS) {\r
965\r
966 //\r
967 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
968 //\r
969 //\r
970 // Have no way to get ReqRes, AllocRes & Bar here\r
971 //\r
972 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
973 AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
974 AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;\r
975 AllocFailExtendedData.Bar = PciResNode->Bar;\r
976\r
977 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
978 EFI_PROGRESS_CODE,\r
979 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
980 (VOID *) &AllocFailExtendedData,\r
981 sizeof (AllocFailExtendedData)\r
982 );\r
983\r
984 //\r
985 // Add it to the array and indicate at least a device has been rejected\r
986 //\r
987 RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;\r
988 AllocationAjusted = TRUE;\r
989 }\r
990 }\r
991 //\r
992 // End for\r
993 //\r
994\r
995 if (AllocationAjusted) {\r
996 return EFI_SUCCESS;\r
997 } else {\r
998 return EFI_ABORTED;\r
999 }\r
1000}\r
1001\r
a3b8e257 1002/**\r
1003 Summary requests for all resource type, and contruct ACPI resource\r
1004 requestor instance.\r
8e8227d1 1005\r
a3b8e257 1006 @param Bridge detecting bridge\r
1007 @param IoNode Pointer to instance of I/O resource Node\r
1008 @param Mem32Node Pointer to instance of 32-bit memory resource Node\r
1009 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node\r
1010 @param Mem64Node Pointer to instance of 64-bit memory resource node\r
1011 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node\r
c72216a6 1012 @param Config Output buffer holding new constructed APCI resource requestor\r
8e8227d1 1013\r
1014 @retval EFI_SUCCESS Successfully constructed ACPI resource.\r
1015 @retval EFI_OUT_OF_RESOURCES No memory availabe.\r
1016\r
a3b8e257 1017**/\r
ead42efc 1018EFI_STATUS\r
1019ConstructAcpiResourceRequestor (\r
1020 IN PCI_IO_DEVICE *Bridge,\r
1021 IN PCI_RESOURCE_NODE *IoNode,\r
1022 IN PCI_RESOURCE_NODE *Mem32Node,\r
1023 IN PCI_RESOURCE_NODE *PMem32Node,\r
1024 IN PCI_RESOURCE_NODE *Mem64Node,\r
1025 IN PCI_RESOURCE_NODE *PMem64Node,\r
c72216a6 1026 OUT VOID **Config\r
ead42efc 1027 )\r
ead42efc 1028{\r
1029 UINT8 NumConfig;\r
1030 UINT8 Aperture;\r
1031 UINT8 *Configuration;\r
1032 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1033 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
1034\r
1035 NumConfig = 0;\r
1036 Aperture = 0;\r
1037\r
c72216a6 1038 *Config = NULL;\r
ead42efc 1039\r
1040 //\r
1041 // if there is io request, add to the io aperture\r
1042 //\r
1043 if (ResourceRequestExisted (IoNode)) {\r
1044 NumConfig++;\r
1045 Aperture |= 0x01;\r
1046 }\r
1047\r
1048 //\r
1049 // if there is mem32 request, add to the mem32 aperture\r
1050 //\r
1051 if (ResourceRequestExisted (Mem32Node)) {\r
1052 NumConfig++;\r
1053 Aperture |= 0x02;\r
1054 }\r
1055\r
1056 //\r
1057 // if there is pmem32 request, add to the pmem32 aperture\r
1058 //\r
1059 if (ResourceRequestExisted (PMem32Node)) {\r
1060 NumConfig++;\r
1061 Aperture |= 0x04;\r
1062 }\r
1063\r
1064 //\r
1065 // if there is mem64 request, add to the mem64 aperture\r
1066 //\r
1067 if (ResourceRequestExisted (Mem64Node)) {\r
1068 NumConfig++;\r
1069 Aperture |= 0x08;\r
1070 }\r
1071\r
1072 //\r
1073 // if there is pmem64 request, add to the pmem64 aperture\r
1074 //\r
1075 if (ResourceRequestExisted (PMem64Node)) {\r
1076 NumConfig++;\r
1077 Aperture |= 0x10;\r
1078 }\r
1079\r
1080 if (NumConfig != 0) {\r
1081\r
1082 //\r
1083 // If there is at least one type of resource request,\r
1084 // allocate a acpi resource node\r
1085 //\r
1086 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1087 if (Configuration == NULL) {\r
1088 return EFI_OUT_OF_RESOURCES;\r
1089 }\r
1090\r
1091 ZeroMem (\r
1092 Configuration,\r
1093 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
1094 );\r
1095\r
1096 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1097\r
1098 //\r
1099 // Deal with io aperture\r
1100 //\r
97404058 1101 if ((Aperture & 0x01) != 0) {\r
ead42efc 1102 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1103 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1104 //\r
1105 // Io\r
1106 //\r
1107 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1108 //\r
1109 // non ISA range\r
1110 //\r
1111 Ptr->SpecificFlag = 1;\r
1112 Ptr->AddrLen = IoNode->Length;\r
1113 Ptr->AddrRangeMax = IoNode->Alignment;\r
1114\r
f88b7fd4 1115 Ptr++;\r
ead42efc 1116 }\r
1117 //\r
1118 // Deal with mem32 aperture\r
1119 //\r
97404058 1120 if ((Aperture & 0x02) != 0) {\r
ead42efc 1121 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1122 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1123 //\r
1124 // Mem\r
1125 //\r
1126 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1127 //\r
1128 // Nonprefechable\r
1129 //\r
1130 Ptr->SpecificFlag = 0;\r
1131 //\r
1132 // 32 bit\r
1133 //\r
1134 Ptr->AddrSpaceGranularity = 32;\r
1135 Ptr->AddrLen = Mem32Node->Length;\r
1136 Ptr->AddrRangeMax = Mem32Node->Alignment;\r
1137\r
f88b7fd4 1138 Ptr++;\r
ead42efc 1139 }\r
1140\r
1141 //\r
1142 // Deal with Pmem32 aperture\r
1143 //\r
97404058 1144 if ((Aperture & 0x04) != 0) {\r
ead42efc 1145 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1146 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1147 //\r
1148 // Mem\r
1149 //\r
1150 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1151 //\r
1152 // prefechable\r
1153 //\r
1154 Ptr->SpecificFlag = 0x6;\r
1155 //\r
1156 // 32 bit\r
1157 //\r
1158 Ptr->AddrSpaceGranularity = 32;\r
1159 Ptr->AddrLen = PMem32Node->Length;\r
1160 Ptr->AddrRangeMax = PMem32Node->Alignment;\r
1161\r
f88b7fd4 1162 Ptr++;\r
ead42efc 1163 }\r
1164 //\r
1165 // Deal with mem64 aperture\r
1166 //\r
97404058 1167 if ((Aperture & 0x08) != 0) {\r
ead42efc 1168 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1169 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1170 //\r
1171 // Mem\r
1172 //\r
1173 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1174 //\r
1175 // nonprefechable\r
1176 //\r
1177 Ptr->SpecificFlag = 0;\r
1178 //\r
1179 // 64 bit\r
1180 //\r
1181 Ptr->AddrSpaceGranularity = 64;\r
1182 Ptr->AddrLen = Mem64Node->Length;\r
1183 Ptr->AddrRangeMax = Mem64Node->Alignment;\r
1184\r
f88b7fd4 1185 Ptr++;\r
ead42efc 1186 }\r
1187 //\r
1188 // Deal with Pmem64 aperture\r
1189 //\r
97404058 1190 if ((Aperture & 0x10) != 0) {\r
ead42efc 1191 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1192 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1193 //\r
1194 // Mem\r
1195 //\r
1196 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1197 //\r
1198 // prefechable\r
1199 //\r
1200 Ptr->SpecificFlag = 0x06;\r
1201 //\r
1202 // 64 bit\r
1203 //\r
1204 Ptr->AddrSpaceGranularity = 64;\r
1205 Ptr->AddrLen = PMem64Node->Length;\r
1206 Ptr->AddrRangeMax = PMem64Node->Alignment;\r
1207\r
f88b7fd4 1208 Ptr++;\r
ead42efc 1209 }\r
1210\r
1211 //\r
1212 // put the checksum\r
1213 //\r
f88b7fd4 1214 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr;\r
ead42efc 1215\r
1216 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1217 PtrEnd->Checksum = 0;\r
1218\r
1219 } else {\r
1220\r
1221 //\r
1222 // If there is no resource request\r
1223 //\r
1224 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1225 if (Configuration == NULL) {\r
1226 return EFI_OUT_OF_RESOURCES;\r
1227 }\r
1228\r
1229 ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1230\r
1231 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);\r
1232 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1233\r
f88b7fd4 1234 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Ptr + 1);\r
ead42efc 1235 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1236 PtrEnd->Checksum = 0;\r
1237 }\r
1238\r
c72216a6 1239 *Config = Configuration;\r
ead42efc 1240\r
1241 return EFI_SUCCESS;\r
1242}\r
1243\r
a3b8e257 1244/**\r
c72216a6 1245 Get resource base from an acpi configuration descriptor.\r
8e8227d1 1246\r
1247 @param Config An acpi configuration descriptor.\r
1248 @param IoBase Output of I/O resource base address.\r
1249 @param Mem32Base Output of 32-bit memory base address.\r
1250 @param PMem32Base Output of 32-bit prefetchable memory base address.\r
1251 @param Mem64Base Output of 64-bit memory base address.\r
1252 @param PMem64Base Output of 64-bit prefetchable memory base address.\r
c72216a6 1253\r
a3b8e257 1254**/\r
8e8227d1 1255VOID\r
ead42efc 1256GetResourceBase (\r
c72216a6 1257 IN VOID *Config,\r
ead42efc 1258 OUT UINT64 *IoBase,\r
1259 OUT UINT64 *Mem32Base,\r
1260 OUT UINT64 *PMem32Base,\r
1261 OUT UINT64 *Mem64Base,\r
1262 OUT UINT64 *PMem64Base\r
1263 )\r
ead42efc 1264{\r
1265 UINT8 *Temp;\r
1266 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1267 UINT64 ResStatus;\r
1268\r
c72216a6 1269 ASSERT (Config != NULL);\r
1270\r
ead42efc 1271 *IoBase = 0xFFFFFFFFFFFFFFFFULL;\r
1272 *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
1273 *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
1274 *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
1275 *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
1276\r
c72216a6 1277 Temp = (UINT8 *) Config;\r
ead42efc 1278\r
1279 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1280\r
1281 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
1282 ResStatus = Ptr->AddrTranslationOffset;\r
1283\r
1284 if (ResStatus == EFI_RESOURCE_SATISFIED) {\r
1285\r
1286 switch (Ptr->ResType) {\r
1287\r
1288 //\r
1289 // Memory type aperture\r
1290 //\r
1291 case 0:\r
1292\r
1293 //\r
1294 // Check to see the granularity\r
1295 //\r
1296 if (Ptr->AddrSpaceGranularity == 32) {\r
5326528b 1297 if ((Ptr->SpecificFlag & 0x06) != 0) {\r
ead42efc 1298 *PMem32Base = Ptr->AddrRangeMin;\r
1299 } else {\r
1300 *Mem32Base = Ptr->AddrRangeMin;\r
1301 }\r
1302 }\r
1303\r
1304 if (Ptr->AddrSpaceGranularity == 64) {\r
5326528b 1305 if ((Ptr->SpecificFlag & 0x06) != 0) {\r
ead42efc 1306 *PMem64Base = Ptr->AddrRangeMin;\r
1307 } else {\r
1308 *Mem64Base = Ptr->AddrRangeMin;\r
1309 }\r
1310 }\r
1311 break;\r
1312\r
1313 case 1:\r
1314\r
1315 //\r
1316 // Io type aperture\r
1317 //\r
1318 *IoBase = Ptr->AddrRangeMin;\r
1319 break;\r
1320\r
1321 default:\r
1322 break;\r
1323\r
1324 }\r
1325 //\r
1326 // End switch\r
1327 //\r
1328 }\r
1329 //\r
1330 // End for\r
1331 //\r
1332 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
1333 }\r
ead42efc 1334}\r
1335\r
a3b8e257 1336/**\r
1337 Enumerate pci bridge, allocate resource and determine attribute\r
8e8227d1 1338 for devices on this bridge.\r
1339\r
1340 @param BridgeDev Pointer to instance of bridge device.\r
1341\r
1342 @retval EFI_SUCCESS Successfully enumerated PCI bridge.\r
1343 @retval other Failed to enumerate.\r
1344\r
a3b8e257 1345**/\r
ead42efc 1346EFI_STATUS\r
1347PciBridgeEnumerator (\r
1348 IN PCI_IO_DEVICE *BridgeDev\r
1349 )\r
ead42efc 1350{\r
1351 UINT8 SubBusNumber;\r
1352 UINT8 StartBusNumber;\r
1353 EFI_PCI_IO_PROTOCOL *PciIo;\r
1354 EFI_STATUS Status;\r
1355\r
1356 SubBusNumber = 0;\r
1357 StartBusNumber = 0;\r
1358 PciIo = &(BridgeDev->PciIo);\r
1359 Status = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);\r
1360\r
1361 if (EFI_ERROR (Status)) {\r
1362 return Status;\r
1363 }\r
1364\r
1365 Status = PciAssignBusNumber (\r
1366 BridgeDev,\r
1367 StartBusNumber,\r
1368 &SubBusNumber\r
1369 );\r
1370\r
1371 if (EFI_ERROR (Status)) {\r
1372 return Status;\r
1373 }\r
1374\r
1375 Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);\r
1376\r
1377 if (EFI_ERROR (Status)) {\r
1378 return Status;\r
1379 }\r
1380\r
1381 Status = PciBridgeResourceAllocator (BridgeDev);\r
1382\r
1383 if (EFI_ERROR (Status)) {\r
1384 return Status;\r
1385 }\r
1386\r
1387 Status = DetermineDeviceAttribute (BridgeDev);\r
1388\r
1389 if (EFI_ERROR (Status)) {\r
1390 return Status;\r
1391 }\r
1392\r
1393 return EFI_SUCCESS;\r
1394\r
1395}\r
1396\r
a3b8e257 1397/**\r
8e8227d1 1398 Allocate all kinds of resource for PCI bridge.\r
1399\r
1400 @param Bridge Pointer to bridge instance.\r
1401\r
1402 @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.\r
1403 @retval other Failed to allocate resource for bridge.\r
1404\r
a3b8e257 1405**/\r
ead42efc 1406EFI_STATUS\r
1407PciBridgeResourceAllocator (\r
1408 IN PCI_IO_DEVICE *Bridge\r
1409 )\r
ead42efc 1410{\r
1411 PCI_RESOURCE_NODE *IoBridge;\r
1412 PCI_RESOURCE_NODE *Mem32Bridge;\r
1413 PCI_RESOURCE_NODE *PMem32Bridge;\r
1414 PCI_RESOURCE_NODE *Mem64Bridge;\r
1415 PCI_RESOURCE_NODE *PMem64Bridge;\r
1416 UINT64 IoBase;\r
1417 UINT64 Mem32Base;\r
1418 UINT64 PMem32Base;\r
1419 UINT64 Mem64Base;\r
1420 UINT64 PMem64Base;\r
1421 EFI_STATUS Status;\r
1422\r
1423 IoBridge = CreateResourceNode (\r
8e8227d1 1424 Bridge,\r
1425 0,\r
1426 0xFFF,\r
1427 0,\r
1428 PciBarTypeIo16,\r
1429 PciResUsageTypical\r
1430 );\r
ead42efc 1431\r
1432 Mem32Bridge = CreateResourceNode (\r
1433 Bridge,\r
1434 0,\r
1435 0xFFFFF,\r
1436 0,\r
1437 PciBarTypeMem32,\r
1438 PciResUsageTypical\r
1439 );\r
1440\r
1441 PMem32Bridge = CreateResourceNode (\r
8e8227d1 1442 Bridge,\r
1443 0,\r
1444 0xFFFFF,\r
1445 0,\r
1446 PciBarTypePMem32,\r
1447 PciResUsageTypical\r
1448 );\r
ead42efc 1449\r
1450 Mem64Bridge = CreateResourceNode (\r
1451 Bridge,\r
1452 0,\r
1453 0xFFFFF,\r
1454 0,\r
1455 PciBarTypeMem64,\r
1456 PciResUsageTypical\r
1457 );\r
1458\r
1459 PMem64Bridge = CreateResourceNode (\r
8e8227d1 1460 Bridge,\r
1461 0,\r
1462 0xFFFFF,\r
1463 0,\r
1464 PciBarTypePMem64,\r
1465 PciResUsageTypical\r
1466 );\r
ead42efc 1467\r
1468 //\r
1469 // Create resourcemap by going through all the devices subject to this root bridge\r
1470 //\r
8e8227d1 1471 CreateResourceMap (\r
1472 Bridge,\r
1473 IoBridge,\r
1474 Mem32Bridge,\r
1475 PMem32Bridge,\r
1476 Mem64Bridge,\r
1477 PMem64Bridge\r
1478 );\r
ead42efc 1479\r
1480 Status = GetResourceBaseFromBridge (\r
8e8227d1 1481 Bridge,\r
1482 &IoBase,\r
1483 &Mem32Base,\r
1484 &PMem32Base,\r
1485 &Mem64Base,\r
1486 &PMem64Base\r
1487 );\r
ead42efc 1488\r
1489 if (EFI_ERROR (Status)) {\r
1490 return Status;\r
1491 }\r
1492\r
1493 //\r
1494 // Program IO resources\r
1495 //\r
1496 ProgramResource (\r
1497 IoBase,\r
1498 IoBridge\r
1499 );\r
1500\r
1501 //\r
1502 // Program Mem32 resources\r
1503 //\r
1504 ProgramResource (\r
1505 Mem32Base,\r
1506 Mem32Bridge\r
1507 );\r
1508\r
1509 //\r
1510 // Program PMem32 resources\r
1511 //\r
1512 ProgramResource (\r
1513 PMem32Base,\r
1514 PMem32Bridge\r
1515 );\r
1516\r
1517 //\r
1518 // Program Mem64 resources\r
1519 //\r
1520 ProgramResource (\r
1521 Mem64Base,\r
1522 Mem64Bridge\r
1523 );\r
1524\r
1525 //\r
1526 // Program PMem64 resources\r
1527 //\r
1528 ProgramResource (\r
1529 PMem64Base,\r
1530 PMem64Bridge\r
1531 );\r
1532\r
1533 DestroyResourceTree (IoBridge);\r
1534 DestroyResourceTree (Mem32Bridge);\r
1535 DestroyResourceTree (PMem32Bridge);\r
1536 DestroyResourceTree (PMem64Bridge);\r
1537 DestroyResourceTree (Mem64Bridge);\r
1538\r
1539 gBS->FreePool (IoBridge);\r
1540 gBS->FreePool (Mem32Bridge);\r
1541 gBS->FreePool (PMem32Bridge);\r
1542 gBS->FreePool (PMem64Bridge);\r
1543 gBS->FreePool (Mem64Bridge);\r
1544\r
1545 return EFI_SUCCESS;\r
1546}\r
1547\r
a3b8e257 1548/**\r
8e8227d1 1549 Get resource base address for a pci bridge device.\r
1550\r
1551 @param Bridge Given Pci driver instance.\r
1552 @param IoBase Output for base address of I/O type resource.\r
1553 @param Mem32Base Output for base address of 32-bit memory type resource.\r
1554 @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.\r
1555 @param Mem64Base Output for base address of 64-bit memory type resource.\r
1556 @param PMem64Base Output for base address of 64-bit Pmemory type resource.\r
1557\r
1558 @retval EFI_SUCCESS Successfully got resource base address.\r
1559 @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.\r
1560\r
a3b8e257 1561**/\r
ead42efc 1562EFI_STATUS\r
1563GetResourceBaseFromBridge (\r
1564 IN PCI_IO_DEVICE *Bridge,\r
1565 OUT UINT64 *IoBase,\r
1566 OUT UINT64 *Mem32Base,\r
1567 OUT UINT64 *PMem32Base,\r
1568 OUT UINT64 *Mem64Base,\r
1569 OUT UINT64 *PMem64Base\r
1570 )\r
ead42efc 1571{\r
1572 if (!Bridge->Allocated) {\r
1573 return EFI_OUT_OF_RESOURCES;\r
1574 }\r
1575\r
1576 *IoBase = gAllOne;\r
1577 *Mem32Base = gAllOne;\r
1578 *PMem32Base = gAllOne;\r
1579 *Mem64Base = gAllOne;\r
1580 *PMem64Base = gAllOne;\r
1581\r
1582 if (IS_PCI_BRIDGE (&Bridge->Pci)) {\r
1583\r
97404058 1584 if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {\r
ead42efc 1585 *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;\r
1586 }\r
1587\r
97404058 1588 if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {\r
ead42efc 1589 *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;\r
1590 }\r
1591\r
97404058 1592 if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {\r
ead42efc 1593 *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;\r
1594 }\r
1595\r
97404058 1596 if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {\r
ead42efc 1597 *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;\r
1598 } else {\r
1599 *PMem64Base = gAllOne;\r
1600 }\r
1601\r
1602 }\r
1603\r
1604 if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {\r
97404058 1605 if (Bridge->PciBar[P2C_IO_1].Length > 0) {\r
ead42efc 1606 *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;\r
1607 } else {\r
97404058 1608 if (Bridge->PciBar[P2C_IO_2].Length > 0) {\r
ead42efc 1609 *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;\r
1610 }\r
1611 }\r
1612\r
97404058 1613 if (Bridge->PciBar[P2C_MEM_1].Length > 0) {\r
ead42efc 1614 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {\r
1615 *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
1616 }\r
1617\r
1618 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {\r
1619 *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
1620 }\r
1621 }\r
1622\r
97404058 1623 if (Bridge->PciBar[P2C_MEM_2].Length > 0) {\r
ead42efc 1624 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {\r
1625 *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
1626 }\r
1627\r
1628 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {\r
1629 *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
1630 }\r
1631 }\r
1632 }\r
1633\r
1634 return EFI_SUCCESS;\r
1635}\r
1636\r
a3b8e257 1637/**\r
8e8227d1 1638 These are the notifications from the PCI bus driver that it is about to enter a certain\r
a3b8e257 1639 phase of the PCI enumeration process.\r
1640\r
1641 This member function can be used to notify the host bridge driver to perform specific actions,\r
1642 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.\r
1643 Eight notification points are defined at this time. See belows:\r
8e8227d1 1644 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data\r
a3b8e257 1645 structures. The PCI enumerator should issue this notification\r
1646 before starting a fresh enumeration process. Enumeration cannot\r
1647 be restarted after sending any other notification such as\r
1648 EfiPciHostBridgeBeginBusAllocation.\r
8e8227d1 1649 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is\r
a3b8e257 1650 required here. This notification can be used to perform any\r
1651 chipset-specific programming.\r
8e8227d1 1652 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No\r
a3b8e257 1653 specific action is required here. This notification can be used to\r
1654 perform any chipset-specific programming.\r
8e8227d1 1655 EfiPciHostBridgeBeginResourceAllocation\r
1656 The resource allocation phase is about to begin. No specific\r
1657 action is required here. This notification can be used to perform\r
1658 any chipset-specific programming.\r
1659 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI\r
a3b8e257 1660 root bridges. These resource settings are returned on the next call to\r
1661 GetProposedResources(). Before calling NotifyPhase() with a Phase of\r
8e8227d1 1662 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible\r
1663 for gathering I/O and memory requests for\r
a3b8e257 1664 all the PCI root bridges and submitting these requests using\r
1665 SubmitResources(). This function pads the resource amount\r
1666 to suit the root bridge hardware, takes care of dependencies between\r
1667 the PCI root bridges, and calls the Global Coherency Domain (GCD)\r
1668 with the allocation request. In the case of padding, the allocated range\r
1669 could be bigger than what was requested.\r
8e8227d1 1670 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated\r
a3b8e257 1671 resources (proposed resources) for all the PCI root bridges. After the\r
1672 hardware is programmed, reassigning resources will not be supported.\r
1673 The bus settings are not affected.\r
8e8227d1 1674 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI\r
a3b8e257 1675 root bridges and resets the I/O and memory apertures to their initial\r
1676 state. The bus settings are not affected. If the request to allocate\r
1677 resources fails, the PCI enumerator can use this notification to\r
1678 deallocate previous resources, adjust the requests, and retry\r
1679 allocation.\r
8e8227d1 1680 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is\r
a3b8e257 1681 required here. This notification can be used to perform any chipsetspecific\r
1682 programming.\r
8e8227d1 1683\r
97404058 1684 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
a3b8e257 1685 @param[in] Phase The phase during enumeration\r
8e8227d1 1686\r
a3b8e257 1687 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error\r
1688 is valid for a Phase of EfiPciHostBridgeAllocateResources if\r
1689 SubmitResources() has not been called for one or more\r
1690 PCI root bridges before this call\r
1691 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid\r
1692 for a Phase of EfiPciHostBridgeSetResources.\r
1693 @retval EFI_INVALID_PARAMETER Invalid phase parameter\r
1694 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
1695 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the\r
1696 previously submitted resource requests cannot be fulfilled or\r
1697 were only partially fulfilled.\r
1698 @retval EFI_SUCCESS The notification was accepted without any errors.\r
1699\r
1700**/\r
ead42efc 1701EFI_STATUS\r
1702NotifyPhase (\r
1703 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
1704 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
1705 )\r
ead42efc 1706{\r
1707 EFI_HANDLE HostBridgeHandle;\r
1708 EFI_HANDLE RootBridgeHandle;\r
1709 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1710 EFI_STATUS Status;\r
1711\r
1712 HostBridgeHandle = NULL;\r
1713 RootBridgeHandle = NULL;\r
1714 if (gPciPlatformProtocol != NULL) {\r
1715 //\r
1716 // Get Host Bridge Handle.\r
1717 //\r
1718 PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);\r
1719\r
1720 //\r
1721 // Get the rootbridge Io protocol to find the host bridge handle\r
1722 //\r
1723 Status = gBS->HandleProtocol (\r
1724 RootBridgeHandle,\r
1725 &gEfiPciRootBridgeIoProtocolGuid,\r
1726 (VOID **) &PciRootBridgeIo\r
1727 );\r
1728\r
1729 if (EFI_ERROR (Status)) {\r
1730 return EFI_NOT_FOUND;\r
1731 }\r
1732\r
1733 HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
1734\r
1735 //\r
7698f336 1736 // Call PlatformPci::PlatformNotify() if the protocol is present.\r
ead42efc 1737 //\r
7698f336 1738 gPciPlatformProtocol->PlatformNotify (\r
ead42efc 1739 gPciPlatformProtocol,\r
1740 HostBridgeHandle,\r
1741 Phase,\r
1742 ChipsetEntry\r
1743 );\r
1744 }\r
1745\r
1746 Status = PciResAlloc->NotifyPhase (\r
1747 PciResAlloc,\r
1748 Phase\r
1749 );\r
1750\r
1751 if (gPciPlatformProtocol != NULL) {\r
1752 //\r
7698f336 1753 // Call PlatformPci::PlatformNotify() if the protocol is present.\r
ead42efc 1754 //\r
7698f336 1755 gPciPlatformProtocol->PlatformNotify (\r
ead42efc 1756 gPciPlatformProtocol,\r
1757 HostBridgeHandle,\r
1758 Phase,\r
1759 ChipsetExit\r
1760 );\r
1761\r
1762 }\r
1763\r
1764 return EFI_SUCCESS;\r
1765}\r
1766\r
a3b8e257 1767/**\r
8e8227d1 1768 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various\r
1769 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual\r
1770 PCI controllers before enumeration.\r
1771\r
1772 This function is called during the PCI enumeration process. No specific action is expected from this\r
1773 member function. It allows the host bridge driver to preinitialize individual PCI controllers before\r
1774 enumeration.\r
1775\r
1776 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
1777 @param Bus The bus number of the pci device.\r
1778 @param Device The device number of the pci device.\r
1779 @param Func The function number of the pci device.\r
1780 @param Phase The phase of the PCI device enumeration.\r
1781\r
1782 @retval EFI_SUCCESS The requested parameters were returned.\r
1783 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.\r
1784 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in\r
1785 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.\r
1786 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should\r
1787 not enumerate this device, including its child devices if it is a PCI-to-PCI\r
1788 bridge.\r
a3b8e257 1789\r
1790**/\r
ead42efc 1791EFI_STATUS\r
1792PreprocessController (\r
1793 IN PCI_IO_DEVICE *Bridge,\r
1794 IN UINT8 Bus,\r
1795 IN UINT8 Device,\r
1796 IN UINT8 Func,\r
1797 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
1798 )\r
ead42efc 1799{\r
1800 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;\r
1801 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;\r
1802 EFI_HANDLE RootBridgeHandle;\r
1803 EFI_HANDLE HostBridgeHandle;\r
1804 EFI_STATUS Status;\r
1805\r
1806 //\r
1807 // Get the host bridge handle\r
1808 //\r
1809 HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;\r
1810\r
1811 //\r
1812 // Get the pci host bridge resource allocation protocol\r
1813 //\r
1814 Status = gBS->OpenProtocol (\r
1815 HostBridgeHandle,\r
1816 &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
1817 (VOID **) &PciResAlloc,\r
1818 NULL,\r
1819 NULL,\r
1820 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1821 );\r
1822\r
1823 if (EFI_ERROR (Status)) {\r
1824 return EFI_UNSUPPORTED;\r
1825 }\r
1826\r
1827 //\r
1828 // Get Root Brige Handle\r
1829 //\r
97404058 1830 while (Bridge->Parent != NULL) {\r
ead42efc 1831 Bridge = Bridge->Parent;\r
1832 }\r
1833\r
1834 RootBridgeHandle = Bridge->Handle;\r
1835\r
1836 RootBridgePciAddress.Register = 0;\r
1837 RootBridgePciAddress.Function = Func;\r
1838 RootBridgePciAddress.Device = Device;\r
1839 RootBridgePciAddress.Bus = Bus;\r
1840 RootBridgePciAddress.ExtendedRegister = 0;\r
1841\r
1842 if (gPciPlatformProtocol != NULL) {\r
1843 //\r
1844 // Call PlatformPci::PrepController() if the protocol is present.\r
1845 //\r
1846 gPciPlatformProtocol->PlatformPrepController (\r
1847 gPciPlatformProtocol,\r
1848 HostBridgeHandle,\r
1849 RootBridgeHandle,\r
1850 RootBridgePciAddress,\r
1851 Phase,\r
1852 ChipsetEntry\r
1853 );\r
1854 }\r
1855\r
1856 Status = PciResAlloc->PreprocessController (\r
1857 PciResAlloc,\r
1858 RootBridgeHandle,\r
1859 RootBridgePciAddress,\r
1860 Phase\r
1861 );\r
1862\r
1863 if (gPciPlatformProtocol != NULL) {\r
1864 //\r
1865 // Call PlatformPci::PrepController() if the protocol is present.\r
1866 //\r
1867 gPciPlatformProtocol->PlatformPrepController (\r
1868 gPciPlatformProtocol,\r
1869 HostBridgeHandle,\r
1870 RootBridgeHandle,\r
1871 RootBridgePciAddress,\r
1872 Phase,\r
1873 ChipsetExit\r
1874 );\r
1875 }\r
1876\r
1877 return EFI_SUCCESS;\r
1878}\r
1879\r
a3b8e257 1880/**\r
8e8227d1 1881 This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has\r
1882 happened on the hot-plug controller. Currently, the operations include add operation and remove operation..\r
1883\r
1884 @param This A pointer to the hot plug request protocol.\r
1885 @param Operation The operation the PCI bus driver is requested to make.\r
1886 @param Controller The handle of the hot-plug controller.\r
1887 @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.\r
1888 @param NumberOfChildren The number of child handles.\r
1889 For a add operation, it is an output parameter.\r
1890