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