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