]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
Merger tracker:Fixed a Pci bus driver logic error
[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 break;
1050 }
1051 }
1052
1053 if (DevIndex != RemovedPciDevNum) {
1054 continue;
1055 }
1056
1057 //
1058 // Remove the device if it isn't in the array
1059 //
1060 Status = RejectPciDevice (PciResNode->PciDev);
1061 if (Status == EFI_SUCCESS) {
1062
1063 //
1064 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1065 //
1066 //
1067 // Have no way to get ReqRes, AllocRes & Bar here
1068 //
1069 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
1070 AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);
1071 AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;
1072 AllocFailExtendedData.Bar = PciResNode->Bar;
1073
1074 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1075 EFI_PROGRESS_CODE,
1076 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
1077 (VOID *) &AllocFailExtendedData,
1078 sizeof (AllocFailExtendedData)
1079 );
1080
1081 //
1082 // Add it to the array and indicate at least a device has been rejected
1083 //
1084 RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
1085 AllocationAjusted = TRUE;
1086 }
1087 }
1088 //
1089 // End for
1090 //
1091
1092 if (AllocationAjusted) {
1093 return EFI_SUCCESS;
1094 } else {
1095 return EFI_ABORTED;
1096 }
1097 }
1098
1099 EFI_STATUS
1100 ConstructAcpiResourceRequestor (
1101 IN PCI_IO_DEVICE *Bridge,
1102 IN PCI_RESOURCE_NODE *IoNode,
1103 IN PCI_RESOURCE_NODE *Mem32Node,
1104 IN PCI_RESOURCE_NODE *PMem32Node,
1105 IN PCI_RESOURCE_NODE *Mem64Node,
1106 IN PCI_RESOURCE_NODE *PMem64Node,
1107 OUT VOID **pConfig
1108 )
1109 /*++
1110
1111 Routine Description:
1112
1113 Arguments:
1114
1115 Returns:
1116
1117 None
1118
1119 --*/
1120 // TODO: Bridge - add argument and description to function comment
1121 // TODO: IoNode - add argument and description to function comment
1122 // TODO: Mem32Node - add argument and description to function comment
1123 // TODO: PMem32Node - add argument and description to function comment
1124 // TODO: Mem64Node - add argument and description to function comment
1125 // TODO: PMem64Node - add argument and description to function comment
1126 // TODO: pConfig - add argument and description to function comment
1127 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1128 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1129 // TODO: EFI_SUCCESS - add return value to function comment
1130 {
1131 UINT8 NumConfig;
1132 UINT8 Aperture;
1133 UINT8 *Configuration;
1134 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1135 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
1136
1137 NumConfig = 0;
1138 Aperture = 0;
1139
1140 *pConfig = NULL;
1141
1142 //
1143 // if there is io request, add to the io aperture
1144 //
1145 if (ResourceRequestExisted (IoNode)) {
1146 NumConfig++;
1147 Aperture |= 0x01;
1148 }
1149
1150 //
1151 // if there is mem32 request, add to the mem32 aperture
1152 //
1153 if (ResourceRequestExisted (Mem32Node)) {
1154 NumConfig++;
1155 Aperture |= 0x02;
1156 }
1157
1158 //
1159 // if there is pmem32 request, add to the pmem32 aperture
1160 //
1161 if (ResourceRequestExisted (PMem32Node)) {
1162 NumConfig++;
1163 Aperture |= 0x04;
1164 }
1165
1166 //
1167 // if there is mem64 request, add to the mem64 aperture
1168 //
1169 if (ResourceRequestExisted (Mem64Node)) {
1170 NumConfig++;
1171 Aperture |= 0x08;
1172 }
1173
1174 //
1175 // if there is pmem64 request, add to the pmem64 aperture
1176 //
1177 if (ResourceRequestExisted (PMem64Node)) {
1178 NumConfig++;
1179 Aperture |= 0x10;
1180 }
1181
1182 if (NumConfig != 0) {
1183
1184 //
1185 // If there is at least one type of resource request,
1186 // allocate a acpi resource node
1187 //
1188 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1189 if (Configuration == NULL) {
1190 return EFI_OUT_OF_RESOURCES;
1191 }
1192
1193 ZeroMem (
1194 Configuration,
1195 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
1196 );
1197
1198 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1199
1200 //
1201 // Deal with io aperture
1202 //
1203 if (Aperture & 0x01) {
1204 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1205 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1206 //
1207 // Io
1208 //
1209 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1210 //
1211 // non ISA range
1212 //
1213 Ptr->SpecificFlag = 1;
1214 Ptr->AddrLen = IoNode->Length;
1215 Ptr->AddrRangeMax = IoNode->Alignment;
1216
1217 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1218 }
1219 //
1220 // Deal with mem32 aperture
1221 //
1222 if (Aperture & 0x02) {
1223 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1224 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1225 //
1226 // Mem
1227 //
1228 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1229 //
1230 // Nonprefechable
1231 //
1232 Ptr->SpecificFlag = 0;
1233 //
1234 // 32 bit
1235 //
1236 Ptr->AddrSpaceGranularity = 32;
1237 Ptr->AddrLen = Mem32Node->Length;
1238 Ptr->AddrRangeMax = Mem32Node->Alignment;
1239
1240 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1241 }
1242
1243 //
1244 // Deal with Pmem32 aperture
1245 //
1246 if (Aperture & 0x04) {
1247 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1248 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1249 //
1250 // Mem
1251 //
1252 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1253 //
1254 // prefechable
1255 //
1256 Ptr->SpecificFlag = 0x6;
1257 //
1258 // 32 bit
1259 //
1260 Ptr->AddrSpaceGranularity = 32;
1261 Ptr->AddrLen = PMem32Node->Length;
1262 Ptr->AddrRangeMax = PMem32Node->Alignment;
1263
1264 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1265 }
1266 //
1267 // Deal with mem64 aperture
1268 //
1269 if (Aperture & 0x08) {
1270 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1271 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1272 //
1273 // Mem
1274 //
1275 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1276 //
1277 // nonprefechable
1278 //
1279 Ptr->SpecificFlag = 0;
1280 //
1281 // 64 bit
1282 //
1283 Ptr->AddrSpaceGranularity = 64;
1284 Ptr->AddrLen = Mem64Node->Length;
1285 Ptr->AddrRangeMax = Mem64Node->Alignment;
1286
1287 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1288 }
1289 //
1290 // Deal with Pmem64 aperture
1291 //
1292 if (Aperture & 0x10) {
1293 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1294 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1295 //
1296 // Mem
1297 //
1298 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1299 //
1300 // prefechable
1301 //
1302 Ptr->SpecificFlag = 0x06;
1303 //
1304 // 64 bit
1305 //
1306 Ptr->AddrSpaceGranularity = 64;
1307 Ptr->AddrLen = PMem64Node->Length;
1308 Ptr->AddrRangeMax = PMem64Node->Alignment;
1309
1310 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1311 }
1312
1313 //
1314 // put the checksum
1315 //
1316 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
1317
1318 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1319 PtrEnd->Checksum = 0;
1320
1321 } else {
1322
1323 //
1324 // If there is no resource request
1325 //
1326 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1327 if (Configuration == NULL) {
1328 return EFI_OUT_OF_RESOURCES;
1329 }
1330
1331 ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1332
1333 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);
1334 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1335
1336 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1337 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1338 PtrEnd->Checksum = 0;
1339 }
1340
1341 *pConfig = Configuration;
1342
1343 return EFI_SUCCESS;
1344 }
1345
1346 EFI_STATUS
1347 GetResourceBase (
1348 IN VOID *pConfig,
1349 OUT UINT64 *IoBase,
1350 OUT UINT64 *Mem32Base,
1351 OUT UINT64 *PMem32Base,
1352 OUT UINT64 *Mem64Base,
1353 OUT UINT64 *PMem64Base
1354 )
1355 /*++
1356
1357 Routine Description:
1358
1359 Arguments:
1360
1361 Returns:
1362
1363 None
1364
1365 --*/
1366 // TODO: pConfig - add argument and description to function comment
1367 // TODO: IoBase - add argument and description to function comment
1368 // TODO: Mem32Base - add argument and description to function comment
1369 // TODO: PMem32Base - add argument and description to function comment
1370 // TODO: Mem64Base - add argument and description to function comment
1371 // TODO: PMem64Base - add argument and description to function comment
1372 // TODO: EFI_SUCCESS - add return value to function comment
1373 {
1374 UINT8 *Temp;
1375 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1376 UINT64 ResStatus;
1377
1378 *IoBase = 0xFFFFFFFFFFFFFFFFULL;
1379 *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;
1380 *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
1381 *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;
1382 *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
1383
1384 Temp = (UINT8 *) pConfig;
1385
1386 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1387
1388 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1389 ResStatus = Ptr->AddrTranslationOffset;
1390
1391 if (ResStatus == EFI_RESOURCE_SATISFIED) {
1392
1393 switch (Ptr->ResType) {
1394
1395 //
1396 // Memory type aperture
1397 //
1398 case 0:
1399
1400 //
1401 // Check to see the granularity
1402 //
1403 if (Ptr->AddrSpaceGranularity == 32) {
1404 if (Ptr->SpecificFlag & 0x06) {
1405 *PMem32Base = Ptr->AddrRangeMin;
1406 } else {
1407 *Mem32Base = Ptr->AddrRangeMin;
1408 }
1409 }
1410
1411 if (Ptr->AddrSpaceGranularity == 64) {
1412 if (Ptr->SpecificFlag & 0x06) {
1413 *PMem64Base = Ptr->AddrRangeMin;
1414 } else {
1415 *Mem64Base = Ptr->AddrRangeMin;
1416 }
1417 }
1418 break;
1419
1420 case 1:
1421
1422 //
1423 // Io type aperture
1424 //
1425 *IoBase = Ptr->AddrRangeMin;
1426 break;
1427
1428 default:
1429 break;
1430
1431 }
1432 //
1433 // End switch
1434 //
1435 }
1436 //
1437 // End for
1438 //
1439 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1440 }
1441
1442 return EFI_SUCCESS;
1443 }
1444
1445 EFI_STATUS
1446 PciBridgeEnumerator (
1447 IN PCI_IO_DEVICE *BridgeDev
1448 )
1449 /*++
1450
1451 Routine Description:
1452
1453 Arguments:
1454
1455 Returns:
1456
1457 None
1458
1459 --*/
1460 // TODO: BridgeDev - add argument and description to function comment
1461 // TODO: EFI_SUCCESS - add return value to function comment
1462 {
1463 UINT8 SubBusNumber;
1464 UINT8 StartBusNumber;
1465 EFI_PCI_IO_PROTOCOL *PciIo;
1466 EFI_STATUS Status;
1467
1468 SubBusNumber = 0;
1469 StartBusNumber = 0;
1470 PciIo = &(BridgeDev->PciIo);
1471 Status = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
1472
1473 if (EFI_ERROR (Status)) {
1474 return Status;
1475 }
1476
1477 Status = PciAssignBusNumber (
1478 BridgeDev,
1479 StartBusNumber,
1480 &SubBusNumber
1481 );
1482
1483 if (EFI_ERROR (Status)) {
1484 return Status;
1485 }
1486
1487 Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
1488
1489 if (EFI_ERROR (Status)) {
1490 return Status;
1491 }
1492
1493 Status = PciBridgeResourceAllocator (BridgeDev);
1494
1495 if (EFI_ERROR (Status)) {
1496 return Status;
1497 }
1498
1499 Status = DetermineDeviceAttribute (BridgeDev);
1500
1501 if (EFI_ERROR (Status)) {
1502 return Status;
1503 }
1504
1505 return EFI_SUCCESS;
1506
1507 }
1508
1509 EFI_STATUS
1510 PciBridgeResourceAllocator (
1511 IN PCI_IO_DEVICE *Bridge
1512 )
1513 /*++
1514
1515 Routine Description:
1516
1517 Arguments:
1518
1519 Returns:
1520
1521 None
1522
1523 --*/
1524 // TODO: Bridge - add argument and description to function comment
1525 // TODO: EFI_SUCCESS - add return value to function comment
1526 {
1527 PCI_RESOURCE_NODE *IoBridge;
1528 PCI_RESOURCE_NODE *Mem32Bridge;
1529 PCI_RESOURCE_NODE *PMem32Bridge;
1530 PCI_RESOURCE_NODE *Mem64Bridge;
1531 PCI_RESOURCE_NODE *PMem64Bridge;
1532 UINT64 IoBase;
1533 UINT64 Mem32Base;
1534 UINT64 PMem32Base;
1535 UINT64 Mem64Base;
1536 UINT64 PMem64Base;
1537 EFI_STATUS Status;
1538
1539 IoBridge = CreateResourceNode (
1540 Bridge,
1541 0,
1542 0xFFF,
1543 0,
1544 PciBarTypeIo16,
1545 PciResUsageTypical
1546 );
1547
1548 Mem32Bridge = CreateResourceNode (
1549 Bridge,
1550 0,
1551 0xFFFFF,
1552 0,
1553 PciBarTypeMem32,
1554 PciResUsageTypical
1555 );
1556
1557 PMem32Bridge = CreateResourceNode (
1558 Bridge,
1559 0,
1560 0xFFFFF,
1561 0,
1562 PciBarTypePMem32,
1563 PciResUsageTypical
1564 );
1565
1566 Mem64Bridge = CreateResourceNode (
1567 Bridge,
1568 0,
1569 0xFFFFF,
1570 0,
1571 PciBarTypeMem64,
1572 PciResUsageTypical
1573 );
1574
1575 PMem64Bridge = CreateResourceNode (
1576 Bridge,
1577 0,
1578 0xFFFFF,
1579 0,
1580 PciBarTypePMem64,
1581 PciResUsageTypical
1582 );
1583
1584 //
1585 // Create resourcemap by going through all the devices subject to this root bridge
1586 //
1587 Status = CreateResourceMap (
1588 Bridge,
1589 IoBridge,
1590 Mem32Bridge,
1591 PMem32Bridge,
1592 Mem64Bridge,
1593 PMem64Bridge
1594 );
1595
1596 if (EFI_ERROR (Status)) {
1597 return Status;
1598 }
1599
1600 Status = GetResourceBaseFromBridge (
1601 Bridge,
1602 &IoBase,
1603 &Mem32Base,
1604 &PMem32Base,
1605 &Mem64Base,
1606 &PMem64Base
1607 );
1608
1609 if (EFI_ERROR (Status)) {
1610 return Status;
1611 }
1612
1613 //
1614 // Program IO resources
1615 //
1616 ProgramResource (
1617 IoBase,
1618 IoBridge
1619 );
1620
1621 //
1622 // Program Mem32 resources
1623 //
1624 ProgramResource (
1625 Mem32Base,
1626 Mem32Bridge
1627 );
1628
1629 //
1630 // Program PMem32 resources
1631 //
1632 ProgramResource (
1633 PMem32Base,
1634 PMem32Bridge
1635 );
1636
1637 //
1638 // Program Mem64 resources
1639 //
1640 ProgramResource (
1641 Mem64Base,
1642 Mem64Bridge
1643 );
1644
1645 //
1646 // Program PMem64 resources
1647 //
1648 ProgramResource (
1649 PMem64Base,
1650 PMem64Bridge
1651 );
1652
1653 DestroyResourceTree (IoBridge);
1654 DestroyResourceTree (Mem32Bridge);
1655 DestroyResourceTree (PMem32Bridge);
1656 DestroyResourceTree (PMem64Bridge);
1657 DestroyResourceTree (Mem64Bridge);
1658
1659 gBS->FreePool (IoBridge);
1660 gBS->FreePool (Mem32Bridge);
1661 gBS->FreePool (PMem32Bridge);
1662 gBS->FreePool (PMem64Bridge);
1663 gBS->FreePool (Mem64Bridge);
1664
1665 return EFI_SUCCESS;
1666 }
1667
1668 EFI_STATUS
1669 GetResourceBaseFromBridge (
1670 IN PCI_IO_DEVICE *Bridge,
1671 OUT UINT64 *IoBase,
1672 OUT UINT64 *Mem32Base,
1673 OUT UINT64 *PMem32Base,
1674 OUT UINT64 *Mem64Base,
1675 OUT UINT64 *PMem64Base
1676 )
1677 /*++
1678
1679 Routine Description:
1680
1681 Arguments:
1682
1683 Returns:
1684
1685 None
1686
1687 --*/
1688 // TODO: Bridge - add argument and description to function comment
1689 // TODO: IoBase - add argument and description to function comment
1690 // TODO: Mem32Base - add argument and description to function comment
1691 // TODO: PMem32Base - add argument and description to function comment
1692 // TODO: Mem64Base - add argument and description to function comment
1693 // TODO: PMem64Base - add argument and description to function comment
1694 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1695 // TODO: EFI_SUCCESS - add return value to function comment
1696 {
1697 if (!Bridge->Allocated) {
1698 return EFI_OUT_OF_RESOURCES;
1699 }
1700
1701 *IoBase = gAllOne;
1702 *Mem32Base = gAllOne;
1703 *PMem32Base = gAllOne;
1704 *Mem64Base = gAllOne;
1705 *PMem64Base = gAllOne;
1706
1707 if (IS_PCI_BRIDGE (&Bridge->Pci)) {
1708
1709 if (Bridge->PciBar[PPB_IO_RANGE].Length) {
1710 *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
1711 }
1712
1713 if (Bridge->PciBar[PPB_MEM32_RANGE].Length) {
1714 *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
1715 }
1716
1717 if (Bridge->PciBar[PPB_PMEM32_RANGE].Length) {
1718 *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
1719 }
1720
1721 if (Bridge->PciBar[PPB_PMEM64_RANGE].Length) {
1722 *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
1723 } else {
1724 *PMem64Base = gAllOne;
1725 }
1726
1727 }
1728
1729 if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
1730 if (Bridge->PciBar[P2C_IO_1].Length) {
1731 *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
1732 } else {
1733 if (Bridge->PciBar[P2C_IO_2].Length) {
1734 *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
1735 }
1736 }
1737
1738 if (Bridge->PciBar[P2C_MEM_1].Length) {
1739 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
1740 *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1741 }
1742
1743 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
1744 *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1745 }
1746 }
1747
1748 if (Bridge->PciBar[P2C_MEM_2].Length) {
1749 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
1750 *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1751 }
1752
1753 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
1754 *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1755 }
1756 }
1757 }
1758
1759 return EFI_SUCCESS;
1760 }
1761
1762 EFI_STATUS
1763 NotifyPhase (
1764 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
1765 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1766 )
1767 /*++
1768
1769 Routine Description:
1770
1771 Arguments:
1772
1773 Returns:
1774
1775 None
1776
1777 --*/
1778 // TODO: PciResAlloc - add argument and description to function comment
1779 // TODO: Phase - add argument and description to function comment
1780 // TODO: EFI_NOT_FOUND - add return value to function comment
1781 // TODO: EFI_SUCCESS - add return value to function comment
1782 {
1783 EFI_HANDLE HostBridgeHandle;
1784 EFI_HANDLE RootBridgeHandle;
1785 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1786 EFI_STATUS Status;
1787
1788 HostBridgeHandle = NULL;
1789 RootBridgeHandle = NULL;
1790 if (gPciPlatformProtocol != NULL) {
1791 //
1792 // Get Host Bridge Handle.
1793 //
1794 PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
1795
1796 //
1797 // Get the rootbridge Io protocol to find the host bridge handle
1798 //
1799 Status = gBS->HandleProtocol (
1800 RootBridgeHandle,
1801 &gEfiPciRootBridgeIoProtocolGuid,
1802 (VOID **) &PciRootBridgeIo
1803 );
1804
1805 if (EFI_ERROR (Status)) {
1806 return EFI_NOT_FOUND;
1807 }
1808
1809 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
1810
1811 //
1812 // Call PlatformPci::PhaseNotify() if the protocol is present.
1813 //
1814 gPciPlatformProtocol->PhaseNotify (
1815 gPciPlatformProtocol,
1816 HostBridgeHandle,
1817 Phase,
1818 ChipsetEntry
1819 );
1820 }
1821
1822 Status = PciResAlloc->NotifyPhase (
1823 PciResAlloc,
1824 Phase
1825 );
1826
1827 if (gPciPlatformProtocol != NULL) {
1828 //
1829 // Call PlatformPci::PhaseNotify() if the protocol is present.
1830 //
1831 gPciPlatformProtocol->PhaseNotify (
1832 gPciPlatformProtocol,
1833 HostBridgeHandle,
1834 Phase,
1835 ChipsetExit
1836 );
1837
1838 }
1839
1840 return EFI_SUCCESS;
1841 }
1842
1843 EFI_STATUS
1844 PreprocessController (
1845 IN PCI_IO_DEVICE *Bridge,
1846 IN UINT8 Bus,
1847 IN UINT8 Device,
1848 IN UINT8 Func,
1849 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1850 )
1851 /*++
1852
1853 Routine Description:
1854
1855 Arguments:
1856
1857 Returns:
1858
1859 None
1860
1861 --*/
1862 // TODO: Bridge - add argument and description to function comment
1863 // TODO: Bus - add argument and description to function comment
1864 // TODO: Device - add argument and description to function comment
1865 // TODO: Func - add argument and description to function comment
1866 // TODO: Phase - add argument and description to function comment
1867 // TODO: EFI_UNSUPPORTED - add return value to function comment
1868 // TODO: EFI_SUCCESS - add return value to function comment
1869 {
1870 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;
1871 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
1872 EFI_HANDLE RootBridgeHandle;
1873 EFI_HANDLE HostBridgeHandle;
1874 EFI_STATUS Status;
1875
1876 //
1877 // Get the host bridge handle
1878 //
1879 HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
1880
1881 //
1882 // Get the pci host bridge resource allocation protocol
1883 //
1884 Status = gBS->OpenProtocol (
1885 HostBridgeHandle,
1886 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
1887 (VOID **) &PciResAlloc,
1888 NULL,
1889 NULL,
1890 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1891 );
1892
1893 if (EFI_ERROR (Status)) {
1894 return EFI_UNSUPPORTED;
1895 }
1896
1897 //
1898 // Get Root Brige Handle
1899 //
1900 while (Bridge->Parent) {
1901 Bridge = Bridge->Parent;
1902 }
1903
1904 RootBridgeHandle = Bridge->Handle;
1905
1906 RootBridgePciAddress.Register = 0;
1907 RootBridgePciAddress.Function = Func;
1908 RootBridgePciAddress.Device = Device;
1909 RootBridgePciAddress.Bus = Bus;
1910 RootBridgePciAddress.ExtendedRegister = 0;
1911
1912 if (gPciPlatformProtocol != NULL) {
1913 //
1914 // Call PlatformPci::PrepController() if the protocol is present.
1915 //
1916 gPciPlatformProtocol->PlatformPrepController (
1917 gPciPlatformProtocol,
1918 HostBridgeHandle,
1919 RootBridgeHandle,
1920 RootBridgePciAddress,
1921 Phase,
1922 ChipsetEntry
1923 );
1924 }
1925
1926 Status = PciResAlloc->PreprocessController (
1927 PciResAlloc,
1928 RootBridgeHandle,
1929 RootBridgePciAddress,
1930 Phase
1931 );
1932
1933 if (gPciPlatformProtocol != NULL) {
1934 //
1935 // Call PlatformPci::PrepController() if the protocol is present.
1936 //
1937 gPciPlatformProtocol->PlatformPrepController (
1938 gPciPlatformProtocol,
1939 HostBridgeHandle,
1940 RootBridgeHandle,
1941 RootBridgePciAddress,
1942 Phase,
1943 ChipsetExit
1944 );
1945 }
1946
1947 return EFI_SUCCESS;
1948 }
1949
1950 EFI_STATUS
1951 EFIAPI
1952 PciHotPlugRequestNotify (
1953 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
1954 IN EFI_PCI_HOTPLUG_OPERATION Operation,
1955 IN EFI_HANDLE Controller,
1956 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,
1957 IN OUT UINT8 *NumberOfChildren,
1958 IN OUT EFI_HANDLE * ChildHandleBuffer
1959 )
1960 /*++
1961
1962 Routine Description:
1963
1964 Hot plug request notify.
1965
1966 Arguments:
1967
1968 This - A pointer to the hot plug request protocol.
1969 Operation - The operation.
1970 Controller - A pointer to the controller.
1971 RemainningDevicePath - A pointer to the device path.
1972 NumberOfChildren - A the number of child handle in the ChildHandleBuffer.
1973 ChildHandleBuffer - A pointer to the array contain the child handle.
1974
1975 Returns:
1976
1977 Status code.
1978
1979 --*/
1980 // TODO: RemainingDevicePath - add argument and description to function comment
1981 // TODO: EFI_NOT_FOUND - add return value to function comment
1982 // TODO: EFI_SUCCESS - add return value to function comment
1983 // TODO: EFI_SUCCESS - add return value to function comment
1984 // TODO: EFI_SUCCESS - add return value to function comment
1985 {
1986 PCI_IO_DEVICE *Bridge;
1987 PCI_IO_DEVICE *Temp;
1988 EFI_PCI_IO_PROTOCOL *PciIo;
1989 UINTN Index;
1990 EFI_HANDLE RootBridgeHandle;
1991 EFI_STATUS Status;
1992
1993 Status = gBS->OpenProtocol (
1994 Controller,
1995 &gEfiPciIoProtocolGuid,
1996 (VOID **) &PciIo,
1997 gPciBusDriverBinding.DriverBindingHandle,
1998 Controller,
1999 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2000 );
2001
2002 if (EFI_ERROR (Status)) {
2003 return EFI_NOT_FOUND;
2004 }
2005
2006 Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
2007
2008 //
2009 // Get root bridge handle
2010 //
2011 Temp = Bridge;
2012 while (Temp->Parent) {
2013 Temp = Temp->Parent;
2014 }
2015
2016 RootBridgeHandle = Temp->Handle;
2017
2018 if (Operation == EfiPciHotPlugRequestAdd) {
2019
2020 if (NumberOfChildren != NULL) {
2021 *NumberOfChildren = 0;
2022 }
2023
2024 if (IsListEmpty (&Bridge->ChildList)) {
2025
2026 Status = PciBridgeEnumerator (Bridge);
2027
2028 if (EFI_ERROR (Status)) {
2029 return Status;
2030 }
2031 }
2032
2033 Status = StartPciDevicesOnBridge (
2034 RootBridgeHandle,
2035 Bridge,
2036 RemainingDevicePath,
2037 NumberOfChildren,
2038 ChildHandleBuffer
2039 );
2040
2041 return EFI_SUCCESS;
2042 }
2043
2044 if (Operation == EfiPciHotplugRequestRemove) {
2045
2046 if (*NumberOfChildren == 0) {
2047 //
2048 // Remove all devices on the bridge
2049 //
2050 Status = RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
2051 return Status;
2052
2053 }
2054
2055 for (Index = 0; Index < *NumberOfChildren; Index++) {
2056 //
2057 // De register all the pci device
2058 //
2059 Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
2060
2061 if (EFI_ERROR (Status)) {
2062 return Status;
2063 }
2064
2065 }
2066 //
2067 // End for
2068 //
2069 return EFI_SUCCESS;
2070 }
2071
2072 return EFI_SUCCESS;
2073 }
2074
2075 BOOLEAN
2076 SearchHostBridgeHandle (
2077 IN EFI_HANDLE RootBridgeHandle
2078 )
2079 /*++
2080
2081 Routine Description:
2082
2083 Arguments:
2084
2085 Returns:
2086
2087 None
2088
2089 --*/
2090 // TODO: RootBridgeHandle - add argument and description to function comment
2091 {
2092 EFI_HANDLE HostBridgeHandle;
2093 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2094 UINTN Index;
2095 EFI_STATUS Status;
2096
2097 //
2098 // Get the rootbridge Io protocol to find the host bridge handle
2099 //
2100 Status = gBS->OpenProtocol (
2101 RootBridgeHandle,
2102 &gEfiPciRootBridgeIoProtocolGuid,
2103 (VOID **) &PciRootBridgeIo,
2104 gPciBusDriverBinding.DriverBindingHandle,
2105 RootBridgeHandle,
2106 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2107 );
2108
2109 if (EFI_ERROR (Status)) {
2110 return FALSE;
2111 }
2112
2113 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
2114 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2115 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2116 return TRUE;
2117 }
2118 }
2119
2120 return FALSE;
2121 }
2122
2123 EFI_STATUS
2124 AddHostBridgeEnumerator (
2125 IN EFI_HANDLE HostBridgeHandle
2126 )
2127 /*++
2128
2129 Routine Description:
2130
2131 Arguments:
2132
2133 Returns:
2134
2135 None
2136
2137 --*/
2138 // TODO: HostBridgeHandle - add argument and description to function comment
2139 // TODO: EFI_ABORTED - add return value to function comment
2140 // TODO: EFI_ABORTED - add return value to function comment
2141 // TODO: EFI_SUCCESS - add return value to function comment
2142 {
2143 UINTN Index;
2144
2145 if (!HostBridgeHandle) {
2146 return EFI_ABORTED;
2147 }
2148
2149 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2150 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2151 return EFI_ABORTED;
2152 }
2153 }
2154
2155 if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
2156 gPciHostBrigeHandles[Index] = HostBridgeHandle;
2157 gPciHostBridgeNumber++;
2158 }
2159
2160 return EFI_SUCCESS;
2161 }