]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
Coding style modification.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciResourceSupport.c
1 /**@file
2
3 Copyright (c) 2006 - 2007, 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 #include "pcibus.h"
15 #include "PciResourceSupport.h"
16 #include "PciCommand.h"
17
18 EFI_STATUS
19 SkipVGAAperture (
20 OUT UINT64 *Start,
21 IN UINT64 Length
22 )
23 /**
24
25 Routine Description:
26
27 The function is used to skip VGA range
28
29 Arguments:
30
31 Returns:
32
33 None
34
35 **/
36 // TODO: Start - add argument and description to function comment
37 // TODO: Length - add argument and description to function comment
38 // TODO: EFI_SUCCESS - add return value to function comment
39 {
40 UINT64 Original;
41 UINT64 Mask;
42 UINT64 StartOffset;
43 UINT64 LimitOffset;
44
45 //
46 // For legacy VGA, bit 10 to bit 15 is not decoded
47 //
48 Mask = 0x3FF;
49
50 Original = *Start;
51 StartOffset = Original & Mask;
52 LimitOffset = ((*Start) + Length - 1) & Mask;
53 if (LimitOffset >= VGABASE1) {
54 *Start = *Start - StartOffset + VGALIMIT2 + 1;
55 }
56
57 return EFI_SUCCESS;
58 }
59
60 EFI_STATUS
61 SkipIsaAliasAperture (
62 OUT UINT64 *Start,
63 IN UINT64 Length
64 )
65 /**
66
67 Routine Description:
68
69 This function is used to skip ISA aliasing aperture
70
71 Arguments:
72
73 Returns:
74
75 None
76
77 **/
78 // TODO: Start - add argument and description to function comment
79 // TODO: Length - add argument and description to function comment
80 // TODO: EFI_SUCCESS - add return value to function comment
81 {
82
83 UINT64 Original;
84 UINT64 Mask;
85 UINT64 StartOffset;
86 UINT64 LimitOffset;
87
88 //
89 // For legacy ISA, bit 10 to bit 15 is not decoded
90 //
91 Mask = 0x3FF;
92
93 Original = *Start;
94 StartOffset = Original & Mask;
95 LimitOffset = ((*Start) + Length - 1) & Mask;
96
97 if (LimitOffset >= ISABASE) {
98 *Start = *Start - StartOffset + ISALIMIT + 1;
99 }
100
101 return EFI_SUCCESS;
102 }
103
104 EFI_STATUS
105 InsertResourceNode (
106 PCI_RESOURCE_NODE *Bridge,
107 PCI_RESOURCE_NODE *ResNode
108 )
109 /**
110
111 Routine Description:
112
113 This function inserts a resource node into the resource list.
114 The resource list is sorted in descend order.
115
116 Arguments:
117
118 Returns:
119
120 None
121
122 **/
123 // TODO: Bridge - add argument and description to function comment
124 // TODO: ResNode - add argument and description to function comment
125 // TODO: EFI_SUCCESS - add return value to function comment
126 {
127 LIST_ENTRY *CurrentLink;
128 PCI_RESOURCE_NODE *Temp;
129 UINT64 ResNodeAlignRest;
130 UINT64 TempAlignRest;
131
132 InsertHeadList (&Bridge->ChildList, &ResNode->Link);
133
134 CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;
135 while (CurrentLink != &Bridge->ChildList) {
136 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
137
138 if (ResNode->Alignment > Temp->Alignment) {
139 break;
140 } else if (ResNode->Alignment == Temp->Alignment) {
141 ResNodeAlignRest = ResNode->Length & ResNode->Alignment;
142 TempAlignRest = Temp->Length & Temp->Alignment;
143 if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {
144 break;
145 }
146 }
147
148 SwapListEntries (&ResNode->Link, CurrentLink);
149
150 CurrentLink = ResNode->Link.ForwardLink;
151 }
152
153 return EFI_SUCCESS;
154 }
155
156 EFI_STATUS
157 MergeResourceTree (
158 PCI_RESOURCE_NODE *Dst,
159 PCI_RESOURCE_NODE *Res,
160 BOOLEAN TypeMerge
161 )
162 /**
163
164 Routine Description:
165
166 This routine is used to merge two different resource tree in need of
167 resoure degradation. For example, if a upstream PPB doesn't support,
168 prefetchable memory decoding, the PCI bus driver will choose to call this function
169 to merge prefectchable memory resource list into normal memory list.
170
171 If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
172 type.
173
174 Arguments:
175
176 Returns:
177
178 None
179
180 **/
181 // TODO: Dst - add argument and description to function comment
182 // TODO: Res - add argument and description to function comment
183 // TODO: TypeMerge - add argument and description to function comment
184 // TODO: EFI_SUCCESS - add return value to function comment
185 {
186
187 LIST_ENTRY *CurrentLink;
188 PCI_RESOURCE_NODE *Temp;
189
190 while (!IsListEmpty (&Res->ChildList)) {
191 CurrentLink = Res->ChildList.ForwardLink;
192
193 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
194
195 if (TypeMerge) {
196 Temp->ResType = Dst->ResType;
197 }
198
199 RemoveEntryList (CurrentLink);
200 InsertResourceNode (Dst, Temp);
201
202 }
203
204 return EFI_SUCCESS;
205 }
206
207 EFI_STATUS
208 CalculateApertureIo16 (
209 IN PCI_RESOURCE_NODE *Bridge
210 )
211 /**
212
213 Routine Description:
214
215 This function is used to calculate the IO16 aperture
216 for a bridge.
217
218 Arguments:
219
220 Returns:
221
222 None
223
224 **/
225 // TODO: Bridge - add argument and description to function comment
226 // TODO: EFI_SUCCESS - add return value to function comment
227 // TODO: EFI_SUCCESS - add return value to function comment
228 {
229
230 UINT64 Aperture;
231 LIST_ENTRY *CurrentLink;
232 PCI_RESOURCE_NODE *Node;
233 UINT64 offset;
234 BOOLEAN IsaEnable;
235 BOOLEAN VGAEnable;
236
237 //
238 // Always assume there is ISA device and VGA device on the platform
239 // will be customized later
240 //
241 IsaEnable = FALSE;
242 VGAEnable = FALSE;
243
244 if (FeaturePcdGet (PcdPciIsaEnable)){
245 IsaEnable = TRUE;
246 }
247
248 if (FeaturePcdGet (PcdPciVgaEnable)){
249 VGAEnable = TRUE;
250 }
251
252 Aperture = 0;
253
254 if (!Bridge) {
255 return EFI_SUCCESS;
256 }
257
258 CurrentLink = Bridge->ChildList.ForwardLink;
259
260 //
261 // Assume the bridge is aligned
262 //
263 while (CurrentLink != &Bridge->ChildList) {
264
265 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
266
267 //
268 // Consider the aperture alignment
269 //
270 offset = Aperture & (Node->Alignment);
271
272 if (offset) {
273
274 Aperture = Aperture + (Node->Alignment + 1) - offset;
275
276 }
277
278 //
279 // IsaEnable and VGAEnable can not be implemented now.
280 // If both of them are enabled, then the IO resource would
281 // become too limited to meet the requirement of most of devices.
282 //
283
284 if (IsaEnable || VGAEnable) {
285 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
286 //
287 // Check if there is need to support ISA/VGA decoding
288 // If so, we need to avoid isa/vga aliasing range
289 //
290 if (IsaEnable) {
291 SkipIsaAliasAperture (
292 &Aperture,
293 Node->Length
294 );
295 offset = Aperture & (Node->Alignment);
296 if (offset) {
297 Aperture = Aperture + (Node->Alignment + 1) - offset;
298 }
299 } else if (VGAEnable) {
300 SkipVGAAperture (
301 &Aperture,
302 Node->Length
303 );
304 offset = Aperture & (Node->Alignment);
305 if (offset) {
306 Aperture = Aperture + (Node->Alignment + 1) - offset;
307 }
308 }
309 }
310 }
311
312 Node->Offset = Aperture;
313
314 //
315 // Increment aperture by the length of node
316 //
317 Aperture += Node->Length;
318
319 CurrentLink = CurrentLink->ForwardLink;
320 }
321
322 //
323 // At last, adjust the aperture with the bridge's
324 // alignment
325 //
326 offset = Aperture & (Bridge->Alignment);
327
328 if (offset) {
329 Aperture = Aperture + (Bridge->Alignment + 1) - offset;
330 }
331
332 Bridge->Length = Aperture;
333 //
334 // At last, adjust the bridge's alignment to the first child's alignment
335 // if the bridge has at least one child
336 //
337 CurrentLink = Bridge->ChildList.ForwardLink;
338 if (CurrentLink != &Bridge->ChildList) {
339 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
340 if (Node->Alignment > Bridge->Alignment) {
341 Bridge->Alignment = Node->Alignment;
342 }
343 }
344
345 return EFI_SUCCESS;
346 }
347
348 EFI_STATUS
349 CalculateResourceAperture (
350 IN PCI_RESOURCE_NODE *Bridge
351 )
352 /**
353
354 Routine Description:
355
356 This function is used to calculate the resource aperture
357 for a given bridge device
358
359 Arguments:
360
361 Returns:
362
363 None
364
365 **/
366 // TODO: Bridge - add argument and description to function comment
367 // TODO: EFI_SUCCESS - add return value to function comment
368 // TODO: EFI_SUCCESS - add return value to function comment
369 {
370 UINT64 Aperture;
371 LIST_ENTRY *CurrentLink;
372 PCI_RESOURCE_NODE *Node;
373
374 UINT64 offset;
375
376 Aperture = 0;
377
378 if (!Bridge) {
379 return EFI_SUCCESS;
380 }
381
382 if (Bridge->ResType == PciBarTypeIo16) {
383 return CalculateApertureIo16 (Bridge);
384 }
385
386 CurrentLink = Bridge->ChildList.ForwardLink;
387
388 //
389 // Assume the bridge is aligned
390 //
391 while (CurrentLink != &Bridge->ChildList) {
392
393 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
394
395 //
396 // Apply padding resource if available
397 //
398
399 offset = Aperture & (Node->Alignment);
400
401 if (offset) {
402
403 Aperture = Aperture + (Node->Alignment + 1) - offset;
404
405 }
406
407 //
408 // Recode current aperture as a offset
409 // this offset will be used in future real allocation
410 //
411 Node->Offset = Aperture;
412
413 //
414 // Increment aperture by the length of node
415 //
416 Aperture += Node->Length;
417
418 //
419 // Consider the aperture alignment
420 //
421
422 CurrentLink = CurrentLink->ForwardLink;
423 }
424
425 //
426 // At last, adjust the aperture with the bridge's
427 // alignment
428 //
429 offset = Aperture & (Bridge->Alignment);
430 if (offset) {
431 Aperture = Aperture + (Bridge->Alignment + 1) - offset;
432 }
433
434 //
435 // If the bridge has already padded the resource and the
436 // amount of padded resource is larger, then keep the
437 // padded resource
438 //
439 if (Bridge->Length < Aperture) {
440 Bridge->Length = Aperture;
441 }
442
443 //
444 // At last, adjust the bridge's alignment to the first child's alignment
445 // if the bridge has at least one child
446 //
447 CurrentLink = Bridge->ChildList.ForwardLink;
448 if (CurrentLink != &Bridge->ChildList) {
449 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
450 if (Node->Alignment > Bridge->Alignment) {
451 Bridge->Alignment = Node->Alignment;
452 }
453 }
454
455 return EFI_SUCCESS;
456 }
457
458 EFI_STATUS
459 GetResourceFromDevice (
460 PCI_IO_DEVICE *PciDev,
461 PCI_RESOURCE_NODE *IoNode,
462 PCI_RESOURCE_NODE *Mem32Node,
463 PCI_RESOURCE_NODE *PMem32Node,
464 PCI_RESOURCE_NODE *Mem64Node,
465 PCI_RESOURCE_NODE *PMem64Node
466 )
467 /**
468
469 Routine Description:
470
471 Arguments:
472
473 Returns:
474
475 None
476
477 **/
478 // TODO: PciDev - add argument and description to function comment
479 // TODO: IoNode - add argument and description to function comment
480 // TODO: Mem32Node - add argument and description to function comment
481 // TODO: PMem32Node - add argument and description to function comment
482 // TODO: Mem64Node - add argument and description to function comment
483 // TODO: PMem64Node - add argument and description to function comment
484 // TODO: EFI_SUCCESS - add return value to function comment
485 {
486
487 UINT8 Index;
488 PCI_RESOURCE_NODE *Node;
489 BOOLEAN ResourceRequested;
490
491 Node = NULL;
492 ResourceRequested = FALSE;
493
494 for (Index = 0; Index < PCI_MAX_BAR; Index++) {
495
496 switch ((PciDev->PciBar)[Index].BarType) {
497
498 case PciBarTypeMem32:
499
500 Node = CreateResourceNode (
501 PciDev,
502 (PciDev->PciBar)[Index].Length,
503 (PciDev->PciBar)[Index].Alignment,
504 Index,
505 PciBarTypeMem32,
506 PciResUsageTypical
507 );
508
509 InsertResourceNode (
510 Mem32Node,
511 Node
512 );
513
514 ResourceRequested = TRUE;
515 break;
516
517 case PciBarTypeMem64:
518
519 Node = CreateResourceNode (
520 PciDev,
521 (PciDev->PciBar)[Index].Length,
522 (PciDev->PciBar)[Index].Alignment,
523 Index,
524 PciBarTypeMem64,
525 PciResUsageTypical
526 );
527
528 InsertResourceNode (
529 Mem64Node,
530 Node
531 );
532
533 ResourceRequested = TRUE;
534 break;
535
536 case PciBarTypePMem64:
537
538 Node = CreateResourceNode (
539 PciDev,
540 (PciDev->PciBar)[Index].Length,
541 (PciDev->PciBar)[Index].Alignment,
542 Index,
543 PciBarTypePMem64,
544 PciResUsageTypical
545 );
546
547 InsertResourceNode (
548 PMem64Node,
549 Node
550 );
551
552 ResourceRequested = TRUE;
553 break;
554
555 case PciBarTypePMem32:
556
557 Node = CreateResourceNode (
558 PciDev,
559 (PciDev->PciBar)[Index].Length,
560 (PciDev->PciBar)[Index].Alignment,
561 Index,
562 PciBarTypePMem32,
563 PciResUsageTypical
564 );
565
566 InsertResourceNode (
567 PMem32Node,
568 Node
569 );
570 ResourceRequested = TRUE;
571 break;
572
573 case PciBarTypeIo16:
574 case PciBarTypeIo32:
575
576 Node = CreateResourceNode (
577 PciDev,
578 (PciDev->PciBar)[Index].Length,
579 (PciDev->PciBar)[Index].Alignment,
580 Index,
581 PciBarTypeIo16,
582 PciResUsageTypical
583 );
584
585 InsertResourceNode (
586 IoNode,
587 Node
588 );
589 ResourceRequested = TRUE;
590 break;
591
592 case PciBarTypeUnknown:
593 break;
594
595 default:
596 break;
597 }
598 }
599
600 //
601 // If there is no resource requested from this device,
602 // then we indicate this device has been allocated naturally.
603 //
604 if (!ResourceRequested) {
605 PciDev->Allocated = TRUE;
606 }
607
608 return EFI_SUCCESS;
609 }
610
611 PCI_RESOURCE_NODE *
612 CreateResourceNode (
613 IN PCI_IO_DEVICE *PciDev,
614 IN UINT64 Length,
615 IN UINT64 Alignment,
616 IN UINT8 Bar,
617 IN PCI_BAR_TYPE ResType,
618 IN PCI_RESOURCE_USAGE ResUsage
619 )
620 /**
621
622 Routine Description:
623
624 This function is used to create a resource node
625
626 Arguments:
627
628 Returns:
629
630 None
631
632 **/
633 // TODO: PciDev - add argument and description to function comment
634 // TODO: Length - add argument and description to function comment
635 // TODO: Alignment - add argument and description to function comment
636 // TODO: Bar - add argument and description to function comment
637 // TODO: ResType - add argument and description to function comment
638 // TODO: ResUsage - add argument and description to function comment
639 {
640 PCI_RESOURCE_NODE *Node;
641
642 Node = NULL;
643
644 Node = AllocatePool (sizeof (PCI_RESOURCE_NODE));
645 ASSERT (Node != NULL);
646 if (Node == NULL) {
647 return NULL;
648 }
649
650 ZeroMem (Node, sizeof (PCI_RESOURCE_NODE));
651
652 Node->Signature = PCI_RESOURCE_SIGNATURE;
653 Node->PciDev = PciDev;
654 Node->Length = Length;
655 Node->Alignment = Alignment;
656 if(((ResType == PciBarTypeIo16) || (ResType == PciBarTypeIo32)) && ( Alignment == 0x0FFF))
657 {
658 if((PciDev->Decodes & EFI_BRIDGE_IOEN1K_DECODE_SUPPORTED) == EFI_BRIDGE_IOEN1K_DECODE_SUPPORTED)
659 Node->Alignment = 0x3FF;
660 else
661 Node->Alignment = 0xFFF;
662 }
663 Node->Bar = Bar;
664 Node->ResType = ResType;
665 Node->Reserved = FALSE;
666 Node->ResourceUsage = ResUsage;
667 InitializeListHead (&Node->ChildList);
668 return Node;
669 }
670
671 EFI_STATUS
672 CreateResourceMap (
673 IN PCI_IO_DEVICE *Bridge,
674 IN PCI_RESOURCE_NODE *IoNode,
675 IN PCI_RESOURCE_NODE *Mem32Node,
676 IN PCI_RESOURCE_NODE *PMem32Node,
677 IN PCI_RESOURCE_NODE *Mem64Node,
678 IN PCI_RESOURCE_NODE *PMem64Node
679 )
680 /**
681
682 Routine Description:
683
684 This routine is used to extract resource request from
685 device node list.
686
687 Arguments:
688
689 Returns:
690
691 None
692
693 **/
694 // TODO: Bridge - add argument and description to function comment
695 // TODO: IoNode - add argument and description to function comment
696 // TODO: Mem32Node - add argument and description to function comment
697 // TODO: PMem32Node - add argument and description to function comment
698 // TODO: Mem64Node - add argument and description to function comment
699 // TODO: PMem64Node - add argument and description to function comment
700 // TODO: EFI_SUCCESS - add return value to function comment
701 {
702 PCI_IO_DEVICE *Temp;
703 PCI_RESOURCE_NODE *IoBridge;
704 PCI_RESOURCE_NODE *Mem32Bridge;
705 PCI_RESOURCE_NODE *PMem32Bridge;
706 PCI_RESOURCE_NODE *Mem64Bridge;
707 PCI_RESOURCE_NODE *PMem64Bridge;
708 LIST_ENTRY *CurrentLink;
709
710 CurrentLink = Bridge->ChildList.ForwardLink;
711
712 while (CurrentLink && CurrentLink != &Bridge->ChildList) {
713
714 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
715
716 //
717 // Create resource nodes for this device by scanning the
718 // Bar array in the device private data
719 // If the upstream bridge doesn't support this device,
720 // no any resource node will be created for this device
721 //
722 GetResourceFromDevice (
723 Temp,
724 IoNode,
725 Mem32Node,
726 PMem32Node,
727 Mem64Node,
728 PMem64Node
729 );
730
731 if (IS_PCI_BRIDGE (&Temp->Pci)) {
732
733 //
734 // If the device has children, create a bridge resource node for this PPB
735 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
736 // is aligned with 4KB
737 // This device is typically a bridge device like PPB and P2C
738 //
739 IoBridge = CreateResourceNode (
740 Temp,
741 0,
742 0xFFF,
743 PPB_IO_RANGE,
744 PciBarTypeIo16,
745 PciResUsageTypical
746 ); //0x1000 aligned
747
748 Mem32Bridge = CreateResourceNode (
749 Temp,
750 0,
751 0xFFFFF,
752 PPB_MEM32_RANGE,
753 PciBarTypeMem32,
754 PciResUsageTypical
755 );
756
757 PMem32Bridge = CreateResourceNode (
758 Temp,
759 0,
760 0xFFFFF,
761 PPB_PMEM32_RANGE,
762 PciBarTypePMem32,
763 PciResUsageTypical
764 );
765
766 Mem64Bridge = CreateResourceNode (
767 Temp,
768 0,
769 0xFFFFF,
770 PPB_MEM64_RANGE,
771 PciBarTypeMem64,
772 PciResUsageTypical
773 );
774
775 PMem64Bridge = CreateResourceNode (
776 Temp,
777 0,
778 0xFFFFF,
779 PPB_PMEM64_RANGE,
780 PciBarTypePMem64,
781 PciResUsageTypical
782 );
783
784 //
785 // Recursively create resouce map on this bridge
786 //
787 CreateResourceMap (
788 Temp,
789 IoBridge,
790 Mem32Bridge,
791 PMem32Bridge,
792 Mem64Bridge,
793 PMem64Bridge
794 );
795
796 if (ResourceRequestExisted (IoBridge)) {
797 InsertResourceNode (
798 IoNode,
799 IoBridge
800 );
801 } else {
802 gBS->FreePool (IoBridge);
803 IoBridge = NULL;
804 }
805
806 //
807 // If there is node under this resource bridge,
808 // then calculate bridge's aperture of this type
809 // and insert it into the respective resource tree.
810 // If no, delete this resource bridge
811 //
812 if (ResourceRequestExisted (Mem32Bridge)) {
813 InsertResourceNode (
814 Mem32Node,
815 Mem32Bridge
816 );
817 } else {
818 gBS->FreePool (Mem32Bridge);
819 Mem32Bridge = NULL;
820 }
821
822 //
823 // If there is node under this resource bridge,
824 // then calculate bridge's aperture of this type
825 // and insert it into the respective resource tree.
826 // If no, delete this resource bridge
827 //
828 if (ResourceRequestExisted (PMem32Bridge)) {
829 InsertResourceNode (
830 PMem32Node,
831 PMem32Bridge
832 );
833 } else {
834 gBS->FreePool (PMem32Bridge);
835 PMem32Bridge = NULL;
836 }
837
838 //
839 // If there is node under this resource bridge,
840 // then calculate bridge's aperture of this type
841 // and insert it into the respective resource tree.
842 // If no, delete this resource bridge
843 //
844 if (ResourceRequestExisted (Mem64Bridge)) {
845 InsertResourceNode (
846 Mem64Node,
847 Mem64Bridge
848 );
849 } else {
850 gBS->FreePool (Mem64Bridge);
851 Mem64Bridge = NULL;
852 }
853
854 //
855 // If there is node under this resource bridge,
856 // then calculate bridge's aperture of this type
857 // and insert it into the respective resource tree.
858 // If no, delete this resource bridge
859 //
860 if (ResourceRequestExisted (PMem64Bridge)) {
861 InsertResourceNode (
862 PMem64Node,
863 PMem64Bridge
864 );
865 } else {
866 gBS->FreePool (PMem64Bridge);
867 PMem64Bridge = NULL;
868 }
869
870 }
871
872 //
873 // If it is P2C, apply hard coded resource padding
874 //
875 //
876 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
877 ResourcePaddingForCardBusBridge (
878 Temp,
879 IoNode,
880 Mem32Node,
881 PMem32Node,
882 Mem64Node,
883 PMem64Node
884 );
885 }
886
887 CurrentLink = CurrentLink->ForwardLink;
888 }
889 //
890 //
891 // To do some platform specific resource padding ...
892 //
893 ResourcePaddingPolicy (
894 Bridge,
895 IoNode,
896 Mem32Node,
897 PMem32Node,
898 Mem64Node,
899 PMem64Node
900 );
901
902 //
903 // Degrade resource if necessary
904 //
905 DegradeResource (
906 Bridge,
907 Mem32Node,
908 PMem32Node,
909 Mem64Node,
910 PMem64Node
911 );
912
913 //
914 // Calculate resource aperture for this bridge device
915 //
916 CalculateResourceAperture (Mem32Node);
917 CalculateResourceAperture (PMem32Node);
918 CalculateResourceAperture (Mem64Node);
919 CalculateResourceAperture (PMem64Node);
920 CalculateResourceAperture (IoNode);
921
922 return EFI_SUCCESS;
923
924 }
925
926 EFI_STATUS
927 ResourcePaddingPolicy (
928 PCI_IO_DEVICE *PciDev,
929 PCI_RESOURCE_NODE *IoNode,
930 PCI_RESOURCE_NODE *Mem32Node,
931 PCI_RESOURCE_NODE *PMem32Node,
932 PCI_RESOURCE_NODE *Mem64Node,
933 PCI_RESOURCE_NODE *PMem64Node
934 )
935 /**
936
937 Routine Description:
938
939 This function is used to do the resource padding for a specific platform
940
941 Arguments:
942
943 PciDev - A pointer to the PCI_IO_DEVICE structrue.
944 IoNode - A pointer to the PCI_RESOURCE_NODE structrue.
945 Mem32Node - A pointer to the PCI_RESOURCE_NODE structrue.
946 PMem32Node - A pointer to the PCI_RESOURCE_NODE structrue.
947 Mem64Node - A pointer to the PCI_RESOURCE_NODE structrue.
948 PMem64Node - A pointer to the PCI_RESOURCE_NODE structrue.
949
950 Returns:
951 Status code
952
953 None
954
955 **/
956 // TODO: EFI_SUCCESS - add return value to function comment
957 {
958 //
959 // Create padding resource node
960 //
961 if (PciDev->ResourcePaddingDescriptors != NULL) {
962 ApplyResourcePadding (
963 PciDev,
964 IoNode,
965 Mem32Node,
966 PMem32Node,
967 Mem64Node,
968 PMem64Node
969 );
970 }
971
972 return EFI_SUCCESS;
973
974 }
975
976 EFI_STATUS
977 DegradeResource (
978 IN PCI_IO_DEVICE *Bridge,
979 IN PCI_RESOURCE_NODE *Mem32Node,
980 IN PCI_RESOURCE_NODE *PMem32Node,
981 IN PCI_RESOURCE_NODE *Mem64Node,
982 IN PCI_RESOURCE_NODE *PMem64Node
983 )
984 /**
985
986 Routine Description:
987
988 This function is used to degrade resource if the upstream bridge
989 doesn't support certain resource. Degradation path is
990 PMEM64 -> MEM64 -> MEM32
991 PMEM64 -> PMEM32 -> MEM32
992 IO32 -> IO16
993
994 Arguments:
995
996 Returns:
997
998 None
999
1000 **/
1001 // TODO: Bridge - add argument and description to function comment
1002 // TODO: Mem32Node - add argument and description to function comment
1003 // TODO: PMem32Node - add argument and description to function comment
1004 // TODO: Mem64Node - add argument and description to function comment
1005 // TODO: PMem64Node - add argument and description to function comment
1006 // TODO: EFI_SUCCESS - add return value to function comment
1007 {
1008
1009 //
1010 // If bridge doesn't support Prefetchable
1011 // memory64, degrade it to Prefetchable memory32
1012 //
1013 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
1014 MergeResourceTree (
1015 PMem32Node,
1016 PMem64Node,
1017 TRUE
1018 );
1019 } else {
1020 //
1021 // if no PMem32 request, still keep PMem64. Otherwise degrade to PMem32
1022 //
1023 if (PMem32Node != NULL && PMem32Node->Length != 0 && Bridge->Parent != NULL ) {
1024 //
1025 // Fixed the issue that there is no resource for 64-bit (above 4G)
1026 //
1027 MergeResourceTree (
1028 PMem32Node,
1029 PMem64Node,
1030 TRUE
1031 );
1032 }
1033 }
1034
1035
1036 //
1037 // If bridge doesn't support Mem64
1038 // degrade it to mem32
1039 //
1040 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
1041 MergeResourceTree (
1042 Mem32Node,
1043 Mem64Node,
1044 TRUE
1045 );
1046 }
1047
1048 //
1049 // If bridge doesn't support Pmem32
1050 // degrade it to mem32
1051 //
1052 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
1053 MergeResourceTree (
1054 Mem32Node,
1055 PMem32Node,
1056 TRUE
1057 );
1058 }
1059
1060 //
1061 // if bridge supports combined Pmem Mem decoding
1062 // merge these two type of resource
1063 //
1064 if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
1065 MergeResourceTree (
1066 Mem32Node,
1067 PMem32Node,
1068 FALSE
1069 );
1070
1071 MergeResourceTree (
1072 Mem64Node,
1073 PMem64Node,
1074 FALSE
1075 );
1076 }
1077
1078 return EFI_SUCCESS;
1079 }
1080
1081 BOOLEAN
1082 BridgeSupportResourceDecode (
1083 IN PCI_IO_DEVICE *Bridge,
1084 IN UINT32 Decode
1085 )
1086 /**
1087
1088 Routine Description:
1089
1090 TODO: Add function description
1091
1092 Arguments:
1093
1094 Bridge - TODO: add argument description
1095 Decode - TODO: add argument description
1096
1097 Returns:
1098
1099 TODO: add return values
1100
1101 **/
1102 {
1103 /**
1104
1105 Routine Description:
1106
1107 Arguments:
1108
1109 Returns:
1110
1111 None
1112
1113 **/
1114 if ((Bridge->Decodes) & Decode) {
1115 return TRUE;
1116 }
1117
1118 return FALSE;
1119 }
1120
1121 EFI_STATUS
1122 ProgramResource (
1123 IN UINT64 Base,
1124 IN PCI_RESOURCE_NODE *Bridge
1125 )
1126 /**
1127
1128 Routine Description:
1129
1130 This function is used to program the resource allocated
1131 for each resource node
1132
1133 Arguments:
1134
1135 Returns:
1136
1137 None
1138
1139 **/
1140 // TODO: Base - add argument and description to function comment
1141 // TODO: Bridge - add argument and description to function comment
1142 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1143 // TODO: EFI_SUCCESS - add return value to function comment
1144 {
1145 LIST_ENTRY *CurrentLink;
1146 PCI_RESOURCE_NODE *Node;
1147 EFI_STATUS Status;
1148
1149 if (Base == gAllOne) {
1150 return EFI_OUT_OF_RESOURCES;
1151 }
1152
1153 CurrentLink = Bridge->ChildList.ForwardLink;
1154
1155 while (CurrentLink != &Bridge->ChildList) {
1156
1157 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
1158
1159 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
1160
1161 if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
1162 ProgramP2C (Base, Node);
1163 } else {
1164 ProgramBar (Base, Node);
1165 }
1166 } else {
1167 Status = ProgramResource (Base + Node->Offset, Node);
1168
1169 if (EFI_ERROR (Status)) {
1170 return Status;
1171 }
1172
1173 ProgramPpbApperture (Base, Node);
1174 }
1175
1176 CurrentLink = CurrentLink->ForwardLink;
1177 }
1178
1179 return EFI_SUCCESS;
1180 }
1181
1182 EFI_STATUS
1183 ProgramBar (
1184 IN UINT64 Base,
1185 IN PCI_RESOURCE_NODE *Node
1186 )
1187 /**
1188
1189 Routine Description:
1190
1191 Arguments:
1192
1193 Returns:
1194
1195 None
1196
1197 **/
1198 // TODO: Base - add argument and description to function comment
1199 // TODO: Node - add argument and description to function comment
1200 // TODO: EFI_SUCCESS - add return value to function comment
1201 {
1202 EFI_PCI_IO_PROTOCOL *PciIo;
1203 UINT64 Address;
1204 UINT32 Address32;
1205
1206 Address = 0;
1207 PciIo = &(Node->PciDev->PciIo);
1208
1209 Address = Base + Node->Offset;
1210
1211 //
1212 // Indicate pci bus driver has allocated
1213 // resource for this device
1214 // It might be a temporary solution here since
1215 // pci device could have multiple bar
1216 //
1217 Node->PciDev->Allocated = TRUE;
1218
1219 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1220
1221 case PciBarTypeIo16:
1222 case PciBarTypeIo32:
1223 case PciBarTypeMem32:
1224 case PciBarTypePMem32:
1225
1226 PciIoWrite (
1227 PciIo,
1228 EfiPciIoWidthUint32,
1229 (Node->PciDev->PciBar[Node->Bar]).Offset,
1230 1,
1231 &Address
1232 );
1233
1234 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1235
1236 break;
1237
1238 case PciBarTypeMem64:
1239 case PciBarTypePMem64:
1240
1241 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1242
1243 PciIoWrite (
1244 PciIo,
1245 EfiPciIoWidthUint32,
1246 (Node->PciDev->PciBar[Node->Bar]).Offset,
1247 1,
1248 &Address32
1249 );
1250
1251 Address32 = (UINT32) RShiftU64 (Address, 32);
1252
1253 PciIoWrite (
1254 PciIo,
1255 EfiPciIoWidthUint32,
1256 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1257 1,
1258 &Address32
1259 );
1260
1261 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1262
1263 break;
1264
1265 default:
1266 break;
1267 }
1268
1269 return EFI_SUCCESS;
1270 }
1271
1272 EFI_STATUS
1273 ProgramPpbApperture (
1274 IN UINT64 Base,
1275 IN PCI_RESOURCE_NODE *Node
1276 )
1277 /**
1278
1279 Routine Description:
1280
1281 Arguments:
1282
1283 Returns:
1284
1285 None
1286
1287 **/
1288 // TODO: Base - add argument and description to function comment
1289 // TODO: Node - add argument and description to function comment
1290 // TODO: EFI_SUCCESS - add return value to function comment
1291 // TODO: EFI_SUCCESS - add return value to function comment
1292 {
1293 EFI_PCI_IO_PROTOCOL *PciIo;
1294 UINT64 Address;
1295 UINT32 Address32;
1296
1297 Address = 0;
1298 //
1299 // if no device south of this PPB, return anyway
1300 // Apperture is set default in the initialization code
1301 //
1302 if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
1303 //
1304 // For padding resource node, just ignore when programming
1305 //
1306 return EFI_SUCCESS;
1307 }
1308
1309 PciIo = &(Node->PciDev->PciIo);
1310 Address = Base + Node->Offset;
1311
1312 //
1313 // Indicate the PPB resource has been allocated
1314 //
1315 Node->PciDev->Allocated = TRUE;
1316
1317 switch (Node->Bar) {
1318
1319 case PPB_BAR_0:
1320 case PPB_BAR_1:
1321 PciIoWrite (
1322 PciIo,
1323 EfiPciIoWidthUint32,
1324 (Node->PciDev->PciBar[Node->Bar]).Offset,
1325 1,
1326 &Address
1327 );
1328
1329 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1330 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1331
1332 break;
1333
1334 case PPB_IO_RANGE:
1335
1336 Address32 = ((UINT32) (Address)) >> 8;
1337 PciIoWrite (
1338 PciIo,
1339 EfiPciIoWidthUint8,
1340 0x1C,
1341 1,
1342 &Address32
1343 );
1344
1345 Address32 >>= 8;
1346 PciIoWrite (
1347 PciIo,
1348 EfiPciIoWidthUint16,
1349 0x30,
1350 1,
1351 &Address32
1352 );
1353
1354 Address32 = (UINT32) (Address + Node->Length - 1);
1355 Address32 = ((UINT32) (Address32)) >> 8;
1356 PciIoWrite (
1357 PciIo,
1358 EfiPciIoWidthUint8,
1359 0x1D,
1360 1,
1361 &Address32
1362 );
1363
1364 Address32 >>= 8;
1365 PciIoWrite (
1366 PciIo,
1367 EfiPciIoWidthUint16,
1368 0x32,
1369 1,
1370 &Address32
1371 );
1372
1373 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1374 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1375 break;
1376
1377 case PPB_MEM32_RANGE:
1378
1379 Address32 = ((UINT32) (Address)) >> 16;
1380 PciIoWrite (
1381 PciIo,
1382 EfiPciIoWidthUint16,
1383 0x20,
1384 1,
1385 &Address32
1386 );
1387
1388 Address32 = (UINT32) (Address + Node->Length - 1);
1389 Address32 = ((UINT32) (Address32)) >> 16;
1390 PciIoWrite (
1391 PciIo,
1392 EfiPciIoWidthUint16,
1393 0x22,
1394 1,
1395 &Address32
1396 );
1397
1398 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1399 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1400 break;
1401
1402 case PPB_PMEM32_RANGE:
1403 case PPB_PMEM64_RANGE:
1404
1405 Address32 = ((UINT32) (Address)) >> 16;
1406 PciIoWrite (
1407 PciIo,
1408 EfiPciIoWidthUint16,
1409 0x24,
1410 1,
1411 &Address32
1412 );
1413
1414 Address32 = (UINT32) (Address + Node->Length - 1);
1415 Address32 = ((UINT32) (Address32)) >> 16;
1416 PciIoWrite (
1417 PciIo,
1418 EfiPciIoWidthUint16,
1419 0x26,
1420 1,
1421 &Address32
1422 );
1423
1424 Address32 = (UINT32) RShiftU64 (Address, 32);
1425 PciIoWrite (
1426 PciIo,
1427 EfiPciIoWidthUint32,
1428 0x28,
1429 1,
1430 &Address32
1431 );
1432
1433 Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
1434 PciIoWrite (
1435 PciIo,
1436 EfiPciIoWidthUint32,
1437 0x2C,
1438 1,
1439 &Address32
1440 );
1441
1442 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1443 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1444 break;
1445
1446 default:
1447 break;
1448 }
1449
1450 return EFI_SUCCESS;
1451 }
1452
1453 EFI_STATUS
1454 ProgrameUpstreamBridgeForRom (
1455 IN PCI_IO_DEVICE *PciDevice,
1456 IN UINT32 OptionRomBase,
1457 IN BOOLEAN Enable
1458 )
1459 /**
1460
1461 Routine Description:
1462
1463 Arguments:
1464
1465 Returns:
1466
1467 **/
1468 // TODO: PciDevice - add argument and description to function comment
1469 // TODO: OptionRomBase - add argument and description to function comment
1470 // TODO: Enable - add argument and description to function comment
1471 // TODO: EFI_SUCCESS - add return value to function comment
1472 {
1473 PCI_IO_DEVICE *Parent;
1474 PCI_RESOURCE_NODE Node;
1475 //
1476 // For root bridge, just return.
1477 //
1478 Parent = PciDevice->Parent;
1479 ZeroMem (&Node, sizeof (Node));
1480 while (Parent) {
1481 if (!IS_PCI_BRIDGE (&Parent->Pci)) {
1482 break;
1483 }
1484
1485 Node.PciDev = Parent;
1486 Node.Length = PciDevice->RomSize;
1487 Node.Alignment = 0;
1488 Node.Bar = PPB_MEM32_RANGE;
1489 Node.ResType = PciBarTypeMem32;
1490 Node.Offset = 0;
1491
1492 //
1493 // Program PPB to only open a single <= 16<MB apperture
1494 //
1495 if (Enable) {
1496 ProgramPpbApperture (OptionRomBase, &Node);
1497 PciEnableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1498 } else {
1499 InitializePpb (Parent);
1500 PciDisableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1501 }
1502
1503 Parent = Parent->Parent;
1504 }
1505
1506 return EFI_SUCCESS;
1507 }
1508
1509 BOOLEAN
1510 ResourceRequestExisted (
1511 IN PCI_RESOURCE_NODE *Bridge
1512 )
1513 /**
1514
1515 Routine Description:
1516
1517 Arguments:
1518
1519 Bridge - A pointer to the PCI_RESOURCE_NODE.
1520
1521 Returns:
1522
1523 None
1524
1525 **/
1526 {
1527 if (Bridge != NULL) {
1528 if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
1529 return TRUE;
1530 }
1531 }
1532
1533 return FALSE;
1534 }
1535
1536 EFI_STATUS
1537 InitializeResourcePool (
1538 PCI_RESOURCE_NODE *ResourcePool,
1539 PCI_BAR_TYPE ResourceType
1540 )
1541 /**
1542
1543 Routine Description:
1544
1545 Arguments:
1546
1547 Returns:
1548
1549 None
1550
1551 **/
1552 // TODO: ResourcePool - add argument and description to function comment
1553 // TODO: ResourceType - add argument and description to function comment
1554 // TODO: EFI_SUCCESS - add return value to function comment
1555 {
1556
1557 ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
1558 ResourcePool->ResType = ResourceType;
1559 ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
1560 InitializeListHead (&ResourcePool->ChildList);
1561
1562 return EFI_SUCCESS;
1563 }
1564
1565 EFI_STATUS
1566 GetResourceMap (
1567 PCI_IO_DEVICE *PciDev,
1568 PCI_RESOURCE_NODE **IoBridge,
1569 PCI_RESOURCE_NODE **Mem32Bridge,
1570 PCI_RESOURCE_NODE **PMem32Bridge,
1571 PCI_RESOURCE_NODE **Mem64Bridge,
1572 PCI_RESOURCE_NODE **PMem64Bridge,
1573 PCI_RESOURCE_NODE *IoPool,
1574 PCI_RESOURCE_NODE *Mem32Pool,
1575 PCI_RESOURCE_NODE *PMem32Pool,
1576 PCI_RESOURCE_NODE *Mem64Pool,
1577 PCI_RESOURCE_NODE *PMem64Pool
1578 )
1579 /**
1580
1581 Routine Description:
1582
1583 Arguments:
1584
1585 Returns:
1586
1587 None
1588
1589 **/
1590 // TODO: PciDev - add argument and description to function comment
1591 // TODO: IoBridge - add argument and description to function comment
1592 // TODO: Mem32Bridge - add argument and description to function comment
1593 // TODO: PMem32Bridge - add argument and description to function comment
1594 // TODO: Mem64Bridge - add argument and description to function comment
1595 // TODO: PMem64Bridge - add argument and description to function comment
1596 // TODO: IoPool - add argument and description to function comment
1597 // TODO: Mem32Pool - add argument and description to function comment
1598 // TODO: PMem32Pool - add argument and description to function comment
1599 // TODO: Mem64Pool - add argument and description to function comment
1600 // TODO: PMem64Pool - add argument and description to function comment
1601 // TODO: EFI_SUCCESS - add return value to function comment
1602 {
1603
1604 PCI_RESOURCE_NODE *Temp;
1605 LIST_ENTRY *CurrentLink;
1606
1607 CurrentLink = IoPool->ChildList.ForwardLink;
1608
1609 //
1610 // Get Io resource map
1611 //
1612 while (CurrentLink != &IoPool->ChildList) {
1613
1614 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1615
1616 if (Temp->PciDev == PciDev) {
1617 *IoBridge = Temp;
1618 }
1619
1620 CurrentLink = CurrentLink->ForwardLink;
1621 }
1622
1623 //
1624 // Get Mem32 resource map
1625 //
1626 CurrentLink = Mem32Pool->ChildList.ForwardLink;
1627
1628 while (CurrentLink != &Mem32Pool->ChildList) {
1629
1630 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1631
1632 if (Temp->PciDev == PciDev) {
1633 *Mem32Bridge = Temp;
1634 }
1635
1636 CurrentLink = CurrentLink->ForwardLink;
1637 }
1638
1639 //
1640 // Get Pmem32 resource map
1641 //
1642 CurrentLink = PMem32Pool->ChildList.ForwardLink;
1643
1644 while (CurrentLink != &PMem32Pool->ChildList) {
1645
1646 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1647
1648 if (Temp->PciDev == PciDev) {
1649 *PMem32Bridge = Temp;
1650 }
1651
1652 CurrentLink = CurrentLink->ForwardLink;
1653 }
1654
1655 //
1656 // Get Mem64 resource map
1657 //
1658 CurrentLink = Mem64Pool->ChildList.ForwardLink;
1659
1660 while (CurrentLink != &Mem64Pool->ChildList) {
1661
1662 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1663
1664 if (Temp->PciDev == PciDev) {
1665 *Mem64Bridge = Temp;
1666 }
1667
1668 CurrentLink = CurrentLink->ForwardLink;
1669 }
1670
1671 //
1672 // Get Pmem64 resource map
1673 //
1674 CurrentLink = PMem64Pool->ChildList.ForwardLink;
1675
1676 while (CurrentLink != &PMem64Pool->ChildList) {
1677
1678 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1679
1680 if (Temp->PciDev == PciDev) {
1681 *PMem64Bridge = Temp;
1682 }
1683
1684 CurrentLink = CurrentLink->ForwardLink;
1685 }
1686
1687 return EFI_SUCCESS;
1688 }
1689
1690 EFI_STATUS
1691 DestroyResourceTree (
1692 IN PCI_RESOURCE_NODE *Bridge
1693 )
1694 /**
1695
1696 Routine Description:
1697
1698 Arguments:
1699
1700 Returns:
1701
1702 None
1703
1704 **/
1705 // TODO: Bridge - add argument and description to function comment
1706 // TODO: EFI_SUCCESS - add return value to function comment
1707 {
1708 PCI_RESOURCE_NODE *Temp;
1709 LIST_ENTRY *CurrentLink;
1710
1711 while (!IsListEmpty (&Bridge->ChildList)) {
1712
1713 CurrentLink = Bridge->ChildList.ForwardLink;
1714
1715 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1716
1717 RemoveEntryList (CurrentLink);
1718
1719 if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
1720 DestroyResourceTree (Temp);
1721 }
1722
1723 gBS->FreePool (Temp);
1724 }
1725
1726 return EFI_SUCCESS;
1727 }
1728
1729 EFI_STATUS
1730 RecordReservedResource (
1731 IN UINT64 Base,
1732 IN UINT64 Length,
1733 IN PCI_BAR_TYPE ResType,
1734 IN PCI_IO_DEVICE *Bridge
1735 )
1736 /**
1737
1738 Routine Description:
1739
1740 Arguments:
1741
1742 Returns:
1743
1744 None
1745
1746 **/
1747 // TODO: Base - add argument and description to function comment
1748 // TODO: Length - add argument and description to function comment
1749 // TODO: ResType - add argument and description to function comment
1750 // TODO: Bridge - add argument and description to function comment
1751 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1752 // TODO: EFI_SUCCESS - add return value to function comment
1753 {
1754 PCI_RESERVED_RESOURCE_LIST *ReservedNode;
1755
1756 ReservedNode = AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST));
1757 if (ReservedNode == NULL) {
1758 return EFI_OUT_OF_RESOURCES;
1759 }
1760
1761 ReservedNode->Signature = RESERVED_RESOURCE_SIGNATURE;
1762 ReservedNode->Node.Base = Base;
1763 ReservedNode->Node.Length = Length;
1764 ReservedNode->Node.ResType = ResType;
1765
1766 InsertTailList (&Bridge->ReservedResourceList, &(ReservedNode->Link));
1767
1768 return EFI_SUCCESS;
1769 }
1770
1771 EFI_STATUS
1772 ResourcePaddingForCardBusBridge (
1773 PCI_IO_DEVICE *PciDev,
1774 PCI_RESOURCE_NODE *IoNode,
1775 PCI_RESOURCE_NODE *Mem32Node,
1776 PCI_RESOURCE_NODE *PMem32Node,
1777 PCI_RESOURCE_NODE *Mem64Node,
1778 PCI_RESOURCE_NODE *PMem64Node
1779 )
1780 /**
1781
1782 Routine Description:
1783
1784 Arguments:
1785
1786 Returns:
1787
1788 None
1789
1790 **/
1791 // TODO: PciDev - add argument and description to function comment
1792 // TODO: IoNode - add argument and description to function comment
1793 // TODO: Mem32Node - add argument and description to function comment
1794 // TODO: PMem32Node - add argument and description to function comment
1795 // TODO: Mem64Node - add argument and description to function comment
1796 // TODO: PMem64Node - add argument and description to function comment
1797 // TODO: EFI_SUCCESS - add return value to function comment
1798 {
1799 PCI_RESOURCE_NODE *Node;
1800
1801 Node = NULL;
1802
1803 //
1804 // Memory Base/Limit Register 0
1805 // Bar 1 denodes memory range 0
1806 //
1807 Node = CreateResourceNode (
1808 PciDev,
1809 0x2000000,
1810 0x1ffffff,
1811 1,
1812 PciBarTypeMem32,
1813 PciResUsagePadding
1814 );
1815
1816 InsertResourceNode (
1817 Mem32Node,
1818 Node
1819 );
1820
1821 //
1822 // Memory Base/Limit Register 1
1823 // Bar 2 denodes memory range1
1824 //
1825 Node = CreateResourceNode (
1826 PciDev,
1827 0x2000000,
1828 0x1ffffff,
1829 2,
1830 PciBarTypePMem32,
1831 PciResUsagePadding
1832 );
1833
1834 InsertResourceNode (
1835 PMem32Node,
1836 Node
1837 );
1838
1839 //
1840 // Io Base/Limit
1841 // Bar 3 denodes io range 0
1842 //
1843 Node = CreateResourceNode (
1844 PciDev,
1845 0x100,
1846 0xff,
1847 3,
1848 PciBarTypeIo16,
1849 PciResUsagePadding
1850 );
1851
1852 InsertResourceNode (
1853 IoNode,
1854 Node
1855 );
1856
1857 //
1858 // Io Base/Limit
1859 // Bar 4 denodes io range 0
1860 //
1861 Node = CreateResourceNode (
1862 PciDev,
1863 0x100,
1864 0xff,
1865 4,
1866 PciBarTypeIo16,
1867 PciResUsagePadding
1868 );
1869
1870 InsertResourceNode (
1871 IoNode,
1872 Node
1873 );
1874
1875 return EFI_SUCCESS;
1876 }
1877
1878 EFI_STATUS
1879 ProgramP2C (
1880 IN UINT64 Base,
1881 IN PCI_RESOURCE_NODE *Node
1882 )
1883 /**
1884
1885 Routine Description:
1886
1887 Arguments:
1888
1889 Returns:
1890
1891 None
1892
1893 **/
1894 // TODO: Base - add argument and description to function comment
1895 // TODO: Node - add argument and description to function comment
1896 // TODO: EFI_SUCCESS - add return value to function comment
1897 {
1898 EFI_PCI_IO_PROTOCOL *PciIo;
1899 UINT64 Address;
1900 UINT64 TempAddress;
1901 UINT16 BridgeControl;
1902
1903 Address = 0;
1904 PciIo = &(Node->PciDev->PciIo);
1905
1906 Address = Base + Node->Offset;
1907
1908 //
1909 // Indicate pci bus driver has allocated
1910 // resource for this device
1911 // It might be a temporary solution here since
1912 // pci device could have multiple bar
1913 //
1914 Node->PciDev->Allocated = TRUE;
1915
1916 switch (Node->Bar) {
1917
1918 case P2C_BAR_0:
1919 PciIoWrite (
1920 PciIo,
1921 EfiPciIoWidthUint32,
1922 (Node->PciDev->PciBar[Node->Bar]).Offset,
1923 1,
1924 &Address
1925 );
1926
1927 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1928 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1929 break;
1930
1931 case P2C_MEM_1:
1932 PciIoWrite (
1933 PciIo,
1934 EfiPciIoWidthUint32,
1935 0x1c,
1936 1,
1937 &Address
1938 );
1939
1940 TempAddress = Address + Node->Length - 1;
1941 PciIoWrite (
1942 PciIo,
1943 EfiPciIoWidthUint32,
1944 0x20,
1945 1,
1946 &TempAddress
1947 );
1948
1949 if (Node->ResType == PciBarTypeMem32) {
1950
1951 //
1952 // Set non-prefetchable bit
1953 //
1954 PciIoRead (
1955 PciIo,
1956 EfiPciIoWidthUint16,
1957 0x3e,
1958 1,
1959 &BridgeControl
1960 );
1961
1962 BridgeControl &= 0xfeff;
1963 PciIoWrite (
1964 PciIo,
1965 EfiPciIoWidthUint16,
1966 0x3e,
1967 1,
1968 &BridgeControl
1969 );
1970
1971 } else {
1972
1973 //
1974 // Set pre-fetchable bit
1975 //
1976 PciIoRead (
1977 PciIo,
1978 EfiPciIoWidthUint16,
1979 0x3e,
1980 1,
1981 &BridgeControl
1982 );
1983
1984 BridgeControl |= 0x0100;
1985 PciIoWrite (
1986 PciIo,
1987 EfiPciIoWidthUint16,
1988 0x3e,
1989 1,
1990 &BridgeControl
1991 );
1992 }
1993
1994 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1995 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1996 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
1997
1998 break;
1999
2000 case P2C_MEM_2:
2001 PciIoWrite (
2002 PciIo,
2003 EfiPciIoWidthUint32,
2004 0x24,
2005 1,
2006 &Address
2007 );
2008
2009 TempAddress = Address + Node->Length - 1;
2010
2011 PciIoWrite (
2012 PciIo,
2013 EfiPciIoWidthUint32,
2014 0x28,
2015 1,
2016 &TempAddress
2017 );
2018
2019 if (Node->ResType == PciBarTypeMem32) {
2020
2021 //
2022 // Set non-prefetchable bit
2023 //
2024 PciIoRead (
2025 PciIo,
2026 EfiPciIoWidthUint16,
2027 0x3e,
2028 1,
2029 &BridgeControl
2030 );
2031
2032 BridgeControl &= 0xfdff;
2033 PciIoWrite (
2034 PciIo,
2035 EfiPciIoWidthUint16,
2036 0x3e,
2037 1,
2038 &BridgeControl
2039 );
2040 } else {
2041
2042 //
2043 // Set pre-fetchable bit
2044 //
2045 PciIoRead (
2046 PciIo,
2047 EfiPciIoWidthUint16,
2048 0x3e,
2049 1,
2050 &BridgeControl
2051 );
2052
2053 BridgeControl |= 0x0200;
2054 PciIoWrite (
2055 PciIo,
2056 EfiPciIoWidthUint16,
2057 0x3e,
2058 1,
2059 &BridgeControl
2060 );
2061 }
2062
2063 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2064 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2065 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2066 break;
2067
2068 case P2C_IO_1:
2069 PciIoWrite (
2070 PciIo,
2071 EfiPciIoWidthUint32,
2072 0x2c,
2073 1,
2074 &Address
2075 );
2076 TempAddress = Address + Node->Length - 1;
2077 PciIoWrite (
2078 PciIo,
2079 EfiPciIoWidthUint32,
2080 0x30,
2081 1,
2082 &TempAddress
2083 );
2084
2085 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2086 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2087 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2088
2089 break;
2090
2091 case P2C_IO_2:
2092 PciIoWrite (
2093 PciIo,
2094 EfiPciIoWidthUint32,
2095 0x34,
2096 1,
2097 &Address
2098 );
2099
2100 TempAddress = Address + Node->Length - 1;
2101 PciIoWrite (
2102 PciIo,
2103 EfiPciIoWidthUint32,
2104 0x38,
2105 1,
2106 &TempAddress
2107 );
2108
2109 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2110 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2111 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2112 break;
2113
2114 default:
2115 break;
2116 }
2117
2118 return EFI_SUCCESS;
2119 }
2120
2121 EFI_STATUS
2122 ApplyResourcePadding (
2123 PCI_IO_DEVICE *PciDev,
2124 PCI_RESOURCE_NODE *IoNode,
2125 PCI_RESOURCE_NODE *Mem32Node,
2126 PCI_RESOURCE_NODE *PMem32Node,
2127 PCI_RESOURCE_NODE *Mem64Node,
2128 PCI_RESOURCE_NODE *PMem64Node
2129 )
2130 /**
2131
2132 Routine Description:
2133
2134 Arguments:
2135
2136 Returns:
2137
2138 None
2139
2140 **/
2141 // TODO: PciDev - add argument and description to function comment
2142 // TODO: IoNode - add argument and description to function comment
2143 // TODO: Mem32Node - add argument and description to function comment
2144 // TODO: PMem32Node - add argument and description to function comment
2145 // TODO: Mem64Node - add argument and description to function comment
2146 // TODO: PMem64Node - add argument and description to function comment
2147 // TODO: EFI_SUCCESS - add return value to function comment
2148 {
2149 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
2150 PCI_RESOURCE_NODE *Node;
2151 UINT8 DummyBarIndex;
2152
2153 DummyBarIndex = 0;
2154 Ptr = PciDev->ResourcePaddingDescriptors;
2155
2156 while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2157
2158 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
2159 if (Ptr->AddrLen != 0) {
2160
2161 Node = CreateResourceNode (
2162 PciDev,
2163 Ptr->AddrLen,
2164 Ptr->AddrRangeMax,
2165 DummyBarIndex,
2166 PciBarTypeIo16,
2167 PciResUsagePadding
2168 );
2169 InsertResourceNode (
2170 IoNode,
2171 Node
2172 );
2173 }
2174
2175 Ptr++;
2176 continue;
2177 }
2178
2179 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
2180
2181 if (Ptr->AddrSpaceGranularity == 32) {
2182
2183 //
2184 // prefechable
2185 //
2186 if (Ptr->SpecificFlag == 0x6) {
2187 if (Ptr->AddrLen) {
2188 Node = CreateResourceNode (
2189 PciDev,
2190 Ptr->AddrLen,
2191 Ptr->AddrRangeMax,
2192 DummyBarIndex,
2193 PciBarTypePMem32,
2194 PciResUsagePadding
2195 );
2196 InsertResourceNode (
2197 PMem32Node,
2198 Node
2199 );
2200 }
2201
2202 Ptr++;
2203 continue;
2204 }
2205
2206 //
2207 // Non-prefechable
2208 //
2209 if (Ptr->SpecificFlag == 0) {
2210 if (Ptr->AddrLen) {
2211 Node = CreateResourceNode (
2212 PciDev,
2213 Ptr->AddrLen,
2214 Ptr->AddrRangeMax,
2215 DummyBarIndex,
2216 PciBarTypeMem32,
2217 PciResUsagePadding
2218 );
2219 InsertResourceNode (
2220 Mem32Node,
2221 Node
2222 );
2223 }
2224
2225 Ptr++;
2226 continue;
2227 }
2228 }
2229
2230 if (Ptr->AddrSpaceGranularity == 64) {
2231
2232 //
2233 // prefechable
2234 //
2235 if (Ptr->SpecificFlag == 0x6) {
2236 if (Ptr->AddrLen) {
2237 Node = CreateResourceNode (
2238 PciDev,
2239 Ptr->AddrLen,
2240 Ptr->AddrRangeMax,
2241 DummyBarIndex,
2242 PciBarTypePMem64,
2243 PciResUsagePadding
2244 );
2245 InsertResourceNode (
2246 PMem64Node,
2247 Node
2248 );
2249 }
2250
2251 Ptr++;
2252 continue;
2253 }
2254
2255 //
2256 // Non-prefechable
2257 //
2258 if (Ptr->SpecificFlag == 0) {
2259 if (Ptr->AddrLen) {
2260 Node = CreateResourceNode (
2261 PciDev,
2262 Ptr->AddrLen,
2263 Ptr->AddrRangeMax,
2264 DummyBarIndex,
2265 PciBarTypeMem64,
2266 PciResUsagePadding
2267 );
2268 InsertResourceNode (
2269 Mem64Node,
2270 Node
2271 );
2272 }
2273
2274 Ptr++;
2275 continue;
2276 }
2277 }
2278 }
2279
2280 Ptr++;
2281 }
2282
2283 return EFI_SUCCESS;
2284 }
2285
2286 //
2287 // Light PCI bus driver woundn't support hotplug root device
2288 // So no need to pad resource for them
2289 //
2290 VOID
2291 GetResourcePaddingPpb (
2292 IN PCI_IO_DEVICE *PciIoDevice
2293 )
2294 /**
2295
2296 Routine Description:
2297
2298 Get resource.
2299
2300 Arguments:
2301
2302 PciIoDevice A pointer to a pci device.
2303
2304 Returns:
2305
2306 None
2307
2308 **/
2309 {
2310 if (gPciHotPlugInit) {
2311 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
2312 GetResourcePaddingForHpb (PciIoDevice);
2313 }
2314 }
2315 }