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