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