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