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