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