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