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