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