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