]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
Merge tracker. Add check whether CreateResourceNode successful or not.
[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 Node->Bar = Bar;
657 Node->ResType = ResType;
658 Node->Reserved = FALSE;
659 Node->ResourceUsage = ResUsage;
660 InitializeListHead (&Node->ChildList);
661 return Node;
662 }
663
664 EFI_STATUS
665 CreateResourceMap (
666 IN PCI_IO_DEVICE *Bridge,
667 IN PCI_RESOURCE_NODE *IoNode,
668 IN PCI_RESOURCE_NODE *Mem32Node,
669 IN PCI_RESOURCE_NODE *PMem32Node,
670 IN PCI_RESOURCE_NODE *Mem64Node,
671 IN PCI_RESOURCE_NODE *PMem64Node
672 )
673 /*++
674
675 Routine Description:
676
677 This routine is used to extract resource request from
678 device node list.
679
680 Arguments:
681
682 Returns:
683
684 None
685
686 --*/
687 // TODO: Bridge - add argument and description to function comment
688 // TODO: IoNode - add argument and description to function comment
689 // TODO: Mem32Node - add argument and description to function comment
690 // TODO: PMem32Node - add argument and description to function comment
691 // TODO: Mem64Node - add argument and description to function comment
692 // TODO: PMem64Node - add argument and description to function comment
693 // TODO: EFI_SUCCESS - add return value to function comment
694 {
695 PCI_IO_DEVICE *Temp;
696 PCI_RESOURCE_NODE *IoBridge;
697 PCI_RESOURCE_NODE *Mem32Bridge;
698 PCI_RESOURCE_NODE *PMem32Bridge;
699 PCI_RESOURCE_NODE *Mem64Bridge;
700 PCI_RESOURCE_NODE *PMem64Bridge;
701 LIST_ENTRY *CurrentLink;
702
703 CurrentLink = Bridge->ChildList.ForwardLink;
704
705 while (CurrentLink && CurrentLink != &Bridge->ChildList) {
706
707 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
708
709 //
710 // Create resource nodes for this device by scanning the
711 // Bar array in the device private data
712 // If the upstream bridge doesn't support this device,
713 // no any resource node will be created for this device
714 //
715 GetResourceFromDevice (
716 Temp,
717 IoNode,
718 Mem32Node,
719 PMem32Node,
720 Mem64Node,
721 PMem64Node
722 );
723
724 if (IS_PCI_BRIDGE (&Temp->Pci)) {
725
726 //
727 // If the device has children, create a bridge resource node for this PPB
728 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
729 // is aligned with 4KB
730 // This device is typically a bridge device like PPB and P2C
731 //
732 IoBridge = CreateResourceNode (
733 Temp,
734 0,
735 0xFFF,
736 PPB_IO_RANGE,
737 PciBarTypeIo16,
738 PciResUsageTypical
739 ); //0x1000 aligned
740
741 Mem32Bridge = CreateResourceNode (
742 Temp,
743 0,
744 0xFFFFF,
745 PPB_MEM32_RANGE,
746 PciBarTypeMem32,
747 PciResUsageTypical
748 );
749
750 PMem32Bridge = CreateResourceNode (
751 Temp,
752 0,
753 0xFFFFF,
754 PPB_PMEM32_RANGE,
755 PciBarTypePMem32,
756 PciResUsageTypical
757 );
758
759 Mem64Bridge = CreateResourceNode (
760 Temp,
761 0,
762 0xFFFFF,
763 PPB_MEM64_RANGE,
764 PciBarTypeMem64,
765 PciResUsageTypical
766 );
767
768 PMem64Bridge = CreateResourceNode (
769 Temp,
770 0,
771 0xFFFFF,
772 PPB_PMEM64_RANGE,
773 PciBarTypePMem64,
774 PciResUsageTypical
775 );
776
777 //
778 // Recursively create resouce map on this bridge
779 //
780 CreateResourceMap (
781 Temp,
782 IoBridge,
783 Mem32Bridge,
784 PMem32Bridge,
785 Mem64Bridge,
786 PMem64Bridge
787 );
788
789 if (ResourceRequestExisted (IoBridge)) {
790 InsertResourceNode (
791 IoNode,
792 IoBridge
793 );
794 } else {
795 gBS->FreePool (IoBridge);
796 IoBridge = NULL;
797 }
798
799 //
800 // If there is node under this resource bridge,
801 // then calculate bridge's aperture of this type
802 // and insert it into the respective resource tree.
803 // If no, delete this resource bridge
804 //
805 if (ResourceRequestExisted (Mem32Bridge)) {
806 InsertResourceNode (
807 Mem32Node,
808 Mem32Bridge
809 );
810 } else {
811 gBS->FreePool (Mem32Bridge);
812 Mem32Bridge = NULL;
813 }
814
815 //
816 // If there is node under this resource bridge,
817 // then calculate bridge's aperture of this type
818 // and insert it into the respective resource tree.
819 // If no, delete this resource bridge
820 //
821 if (ResourceRequestExisted (PMem32Bridge)) {
822 InsertResourceNode (
823 PMem32Node,
824 PMem32Bridge
825 );
826 } else {
827 gBS->FreePool (PMem32Bridge);
828 PMem32Bridge = NULL;
829 }
830
831 //
832 // If there is node under this resource bridge,
833 // then calculate bridge's aperture of this type
834 // and insert it into the respective resource tree.
835 // If no, delete this resource bridge
836 //
837 if (ResourceRequestExisted (Mem64Bridge)) {
838 InsertResourceNode (
839 Mem64Node,
840 Mem64Bridge
841 );
842 } else {
843 gBS->FreePool (Mem64Bridge);
844 Mem64Bridge = NULL;
845 }
846
847 //
848 // If there is node under this resource bridge,
849 // then calculate bridge's aperture of this type
850 // and insert it into the respective resource tree.
851 // If no, delete this resource bridge
852 //
853 if (ResourceRequestExisted (PMem64Bridge)) {
854 InsertResourceNode (
855 PMem64Node,
856 PMem64Bridge
857 );
858 } else {
859 gBS->FreePool (PMem64Bridge);
860 PMem64Bridge = NULL;
861 }
862
863 }
864
865 //
866 // If it is P2C, apply hard coded resource padding
867 //
868 //
869 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
870 ResourcePaddingForCardBusBridge (
871 Temp,
872 IoNode,
873 Mem32Node,
874 PMem32Node,
875 Mem64Node,
876 PMem64Node
877 );
878 }
879
880 CurrentLink = CurrentLink->ForwardLink;
881 }
882 //
883 //
884 // To do some platform specific resource padding ...
885 //
886 ResourcePaddingPolicy (
887 Bridge,
888 IoNode,
889 Mem32Node,
890 PMem32Node,
891 Mem64Node,
892 PMem64Node
893 );
894
895 //
896 // Degrade resource if necessary
897 //
898 DegradeResource (
899 Bridge,
900 Mem32Node,
901 PMem32Node,
902 Mem64Node,
903 PMem64Node
904 );
905
906 //
907 // Calculate resource aperture for this bridge device
908 //
909 CalculateResourceAperture (Mem32Node);
910 CalculateResourceAperture (PMem32Node);
911 CalculateResourceAperture (Mem64Node);
912 CalculateResourceAperture (PMem64Node);
913 CalculateResourceAperture (IoNode);
914
915 return EFI_SUCCESS;
916
917 }
918
919 EFI_STATUS
920 ResourcePaddingPolicy (
921 PCI_IO_DEVICE *PciDev,
922 PCI_RESOURCE_NODE *IoNode,
923 PCI_RESOURCE_NODE *Mem32Node,
924 PCI_RESOURCE_NODE *PMem32Node,
925 PCI_RESOURCE_NODE *Mem64Node,
926 PCI_RESOURCE_NODE *PMem64Node
927 )
928 /*++
929
930 Routine Description:
931
932 This function is used to do the resource padding for a specific platform
933
934 Arguments:
935
936 PciDev - A pointer to the PCI_IO_DEVICE structrue.
937 IoNode - A pointer to the PCI_RESOURCE_NODE structrue.
938 Mem32Node - A pointer to the PCI_RESOURCE_NODE structrue.
939 PMem32Node - A pointer to the PCI_RESOURCE_NODE structrue.
940 Mem64Node - A pointer to the PCI_RESOURCE_NODE structrue.
941 PMem64Node - A pointer to the PCI_RESOURCE_NODE structrue.
942
943 Returns:
944 Status code
945
946 None
947
948 --*/
949 // TODO: EFI_SUCCESS - add return value to function comment
950 {
951 //
952 // Create padding resource node
953 //
954 if (PciDev->ResourcePaddingDescriptors != NULL) {
955 ApplyResourcePadding (
956 PciDev,
957 IoNode,
958 Mem32Node,
959 PMem32Node,
960 Mem64Node,
961 PMem64Node
962 );
963 }
964
965 return EFI_SUCCESS;
966
967 }
968
969 EFI_STATUS
970 DegradeResource (
971 IN PCI_IO_DEVICE *Bridge,
972 IN PCI_RESOURCE_NODE *Mem32Node,
973 IN PCI_RESOURCE_NODE *PMem32Node,
974 IN PCI_RESOURCE_NODE *Mem64Node,
975 IN PCI_RESOURCE_NODE *PMem64Node
976 )
977 /*++
978
979 Routine Description:
980
981 This function is used to degrade resource if the upstream bridge
982 doesn't support certain resource. Degradation path is
983 PMEM64 -> MEM64 -> MEM32
984 PMEM64 -> PMEM32 -> MEM32
985 IO32 -> IO16
986
987 Arguments:
988
989 Returns:
990
991 None
992
993 --*/
994 // TODO: Bridge - add argument and description to function comment
995 // TODO: Mem32Node - add argument and description to function comment
996 // TODO: PMem32Node - add argument and description to function comment
997 // TODO: Mem64Node - add argument and description to function comment
998 // TODO: PMem64Node - add argument and description to function comment
999 // TODO: EFI_SUCCESS - add return value to function comment
1000 {
1001
1002 //
1003 // If bridge doesn't support Prefetchable
1004 // memory64, degrade it to Prefetchable memory32
1005 //
1006 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
1007 MergeResourceTree (
1008 PMem32Node,
1009 PMem64Node,
1010 TRUE
1011 );
1012 } else {
1013 //
1014 // if no PMem32 request, still keep PMem64. Otherwise degrade to PMem32
1015 //
1016 if (PMem32Node != NULL) {
1017 MergeResourceTree (
1018 PMem32Node,
1019 PMem64Node,
1020 TRUE
1021 );
1022 }
1023 }
1024
1025
1026 //
1027 // If bridge doesn't support Mem64
1028 // degrade it to mem32
1029 //
1030 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
1031 MergeResourceTree (
1032 Mem32Node,
1033 Mem64Node,
1034 TRUE
1035 );
1036 }
1037
1038 //
1039 // If bridge doesn't support Pmem32
1040 // degrade it to mem32
1041 //
1042 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
1043 MergeResourceTree (
1044 Mem32Node,
1045 PMem32Node,
1046 TRUE
1047 );
1048 }
1049
1050 //
1051 // if bridge supports combined Pmem Mem decoding
1052 // merge these two type of resource
1053 //
1054 if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
1055 MergeResourceTree (
1056 Mem32Node,
1057 PMem32Node,
1058 FALSE
1059 );
1060
1061 MergeResourceTree (
1062 Mem64Node,
1063 PMem64Node,
1064 FALSE
1065 );
1066 }
1067
1068 return EFI_SUCCESS;
1069 }
1070
1071 BOOLEAN
1072 BridgeSupportResourceDecode (
1073 IN PCI_IO_DEVICE *Bridge,
1074 IN UINT32 Decode
1075 )
1076 /*++
1077
1078 Routine Description:
1079
1080 TODO: Add function description
1081
1082 Arguments:
1083
1084 Bridge - TODO: add argument description
1085 Decode - TODO: add argument description
1086
1087 Returns:
1088
1089 TODO: add return values
1090
1091 --*/
1092 {
1093 /*++
1094
1095 Routine Description:
1096
1097 Arguments:
1098
1099 Returns:
1100
1101 None
1102
1103 --*/
1104 if ((Bridge->Decodes) & Decode) {
1105 return TRUE;
1106 }
1107
1108 return FALSE;
1109 }
1110
1111 EFI_STATUS
1112 ProgramResource (
1113 IN UINT64 Base,
1114 IN PCI_RESOURCE_NODE *Bridge
1115 )
1116 /*++
1117
1118 Routine Description:
1119
1120 This function is used to program the resource allocated
1121 for each resource node
1122
1123 Arguments:
1124
1125 Returns:
1126
1127 None
1128
1129 --*/
1130 // TODO: Base - add argument and description to function comment
1131 // TODO: Bridge - add argument and description to function comment
1132 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1133 // TODO: EFI_SUCCESS - add return value to function comment
1134 {
1135 LIST_ENTRY *CurrentLink;
1136 PCI_RESOURCE_NODE *Node;
1137 EFI_STATUS Status;
1138
1139 if (Base == gAllOne) {
1140 return EFI_OUT_OF_RESOURCES;
1141 }
1142
1143 CurrentLink = Bridge->ChildList.ForwardLink;
1144
1145 while (CurrentLink != &Bridge->ChildList) {
1146
1147 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
1148
1149 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
1150
1151 if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
1152 ProgramP2C (Base, Node);
1153 } else {
1154 ProgramBar (Base, Node);
1155 }
1156 } else {
1157 Status = ProgramResource (Base + Node->Offset, Node);
1158
1159 if (EFI_ERROR (Status)) {
1160 return Status;
1161 }
1162
1163 ProgramPpbApperture (Base, Node);
1164 }
1165
1166 CurrentLink = CurrentLink->ForwardLink;
1167 }
1168
1169 return EFI_SUCCESS;
1170 }
1171
1172 EFI_STATUS
1173 ProgramBar (
1174 IN UINT64 Base,
1175 IN PCI_RESOURCE_NODE *Node
1176 )
1177 /*++
1178
1179 Routine Description:
1180
1181 Arguments:
1182
1183 Returns:
1184
1185 None
1186
1187 --*/
1188 // TODO: Base - add argument and description to function comment
1189 // TODO: Node - add argument and description to function comment
1190 // TODO: EFI_SUCCESS - add return value to function comment
1191 {
1192 EFI_PCI_IO_PROTOCOL *PciIo;
1193 UINT64 Address;
1194 UINT32 Address32;
1195
1196 Address = 0;
1197 PciIo = &(Node->PciDev->PciIo);
1198
1199 Address = Base + Node->Offset;
1200
1201 //
1202 // Indicate pci bus driver has allocated
1203 // resource for this device
1204 // It might be a temporary solution here since
1205 // pci device could have multiple bar
1206 //
1207 Node->PciDev->Allocated = TRUE;
1208
1209 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1210
1211 case PciBarTypeIo16:
1212 case PciBarTypeIo32:
1213 case PciBarTypeMem32:
1214 case PciBarTypePMem32:
1215
1216 PciIoWrite (
1217 PciIo,
1218 EfiPciIoWidthUint32,
1219 (Node->PciDev->PciBar[Node->Bar]).Offset,
1220 1,
1221 &Address
1222 );
1223
1224 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1225
1226 break;
1227
1228 case PciBarTypeMem64:
1229 case PciBarTypePMem64:
1230
1231 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1232
1233 PciIoWrite (
1234 PciIo,
1235 EfiPciIoWidthUint32,
1236 (Node->PciDev->PciBar[Node->Bar]).Offset,
1237 1,
1238 &Address32
1239 );
1240
1241 Address32 = (UINT32) RShiftU64 (Address, 32);
1242
1243 PciIoWrite (
1244 PciIo,
1245 EfiPciIoWidthUint32,
1246 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1247 1,
1248 &Address32
1249 );
1250
1251 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1252
1253 break;
1254
1255 default:
1256 break;
1257 }
1258
1259 return EFI_SUCCESS;
1260 }
1261
1262 EFI_STATUS
1263 ProgramPpbApperture (
1264 IN UINT64 Base,
1265 IN PCI_RESOURCE_NODE *Node
1266 )
1267 /*++
1268
1269 Routine Description:
1270
1271 Arguments:
1272
1273 Returns:
1274
1275 None
1276
1277 --*/
1278 // TODO: Base - add argument and description to function comment
1279 // TODO: Node - add argument and description to function comment
1280 // TODO: EFI_SUCCESS - add return value to function comment
1281 // TODO: EFI_SUCCESS - add return value to function comment
1282 {
1283 EFI_PCI_IO_PROTOCOL *PciIo;
1284 UINT64 Address;
1285 UINT32 Address32;
1286
1287 Address = 0;
1288 //
1289 // if no device south of this PPB, return anyway
1290 // Apperture is set default in the initialization code
1291 //
1292 if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
1293 //
1294 // For padding resource node, just ignore when programming
1295 //
1296 return EFI_SUCCESS;
1297 }
1298
1299 PciIo = &(Node->PciDev->PciIo);
1300 Address = Base + Node->Offset;
1301
1302 //
1303 // Indicate the PPB resource has been allocated
1304 //
1305 Node->PciDev->Allocated = TRUE;
1306
1307 switch (Node->Bar) {
1308
1309 case PPB_BAR_0:
1310 case PPB_BAR_1:
1311 PciIoWrite (
1312 PciIo,
1313 EfiPciIoWidthUint32,
1314 (Node->PciDev->PciBar[Node->Bar]).Offset,
1315 1,
1316 &Address
1317 );
1318
1319 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1320 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1321
1322 break;
1323
1324 case PPB_IO_RANGE:
1325
1326 Address32 = ((UINT32) (Address)) >> 8;
1327 PciIoWrite (
1328 PciIo,
1329 EfiPciIoWidthUint8,
1330 0x1C,
1331 1,
1332 &Address32
1333 );
1334
1335 Address32 >>= 8;
1336 PciIoWrite (
1337 PciIo,
1338 EfiPciIoWidthUint16,
1339 0x30,
1340 1,
1341 &Address32
1342 );
1343
1344 Address32 = (UINT32) (Address + Node->Length - 1);
1345 Address32 = ((UINT32) (Address32)) >> 8;
1346 PciIoWrite (
1347 PciIo,
1348 EfiPciIoWidthUint8,
1349 0x1D,
1350 1,
1351 &Address32
1352 );
1353
1354 Address32 >>= 8;
1355 PciIoWrite (
1356 PciIo,
1357 EfiPciIoWidthUint16,
1358 0x32,
1359 1,
1360 &Address32
1361 );
1362
1363 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1364 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1365 break;
1366
1367 case PPB_MEM32_RANGE:
1368
1369 Address32 = ((UINT32) (Address)) >> 16;
1370 PciIoWrite (
1371 PciIo,
1372 EfiPciIoWidthUint16,
1373 0x20,
1374 1,
1375 &Address32
1376 );
1377
1378 Address32 = (UINT32) (Address + Node->Length - 1);
1379 Address32 = ((UINT32) (Address32)) >> 16;
1380 PciIoWrite (
1381 PciIo,
1382 EfiPciIoWidthUint16,
1383 0x22,
1384 1,
1385 &Address32
1386 );
1387
1388 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1389 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1390 break;
1391
1392 case PPB_PMEM32_RANGE:
1393 case PPB_PMEM64_RANGE:
1394
1395 Address32 = ((UINT32) (Address)) >> 16;
1396 PciIoWrite (
1397 PciIo,
1398 EfiPciIoWidthUint16,
1399 0x24,
1400 1,
1401 &Address32
1402 );
1403
1404 Address32 = (UINT32) (Address + Node->Length - 1);
1405 Address32 = ((UINT32) (Address32)) >> 16;
1406 PciIoWrite (
1407 PciIo,
1408 EfiPciIoWidthUint16,
1409 0x26,
1410 1,
1411 &Address32
1412 );
1413
1414 Address32 = (UINT32) RShiftU64 (Address, 32);
1415 PciIoWrite (
1416 PciIo,
1417 EfiPciIoWidthUint32,
1418 0x28,
1419 1,
1420 &Address32
1421 );
1422
1423 Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
1424 PciIoWrite (
1425 PciIo,
1426 EfiPciIoWidthUint32,
1427 0x2C,
1428 1,
1429 &Address32
1430 );
1431
1432 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1433 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1434 break;
1435
1436 default:
1437 break;
1438 }
1439
1440 return EFI_SUCCESS;
1441 }
1442
1443 EFI_STATUS
1444 ProgrameUpstreamBridgeForRom (
1445 IN PCI_IO_DEVICE *PciDevice,
1446 IN UINT32 OptionRomBase,
1447 IN BOOLEAN Enable
1448 )
1449 /*++
1450
1451 Routine Description:
1452
1453 Arguments:
1454
1455 Returns:
1456
1457 --*/
1458 // TODO: PciDevice - add argument and description to function comment
1459 // TODO: OptionRomBase - add argument and description to function comment
1460 // TODO: Enable - add argument and description to function comment
1461 // TODO: EFI_SUCCESS - add return value to function comment
1462 {
1463 PCI_IO_DEVICE *Parent;
1464 PCI_RESOURCE_NODE Node;
1465 //
1466 // For root bridge, just return.
1467 //
1468 Parent = PciDevice->Parent;
1469 ZeroMem (&Node, sizeof (Node));
1470 while (Parent) {
1471 if (!IS_PCI_BRIDGE (&Parent->Pci)) {
1472 break;
1473 }
1474
1475 Node.PciDev = Parent;
1476 Node.Length = PciDevice->RomSize;
1477 Node.Alignment = 0;
1478 Node.Bar = PPB_MEM32_RANGE;
1479 Node.ResType = PciBarTypeMem32;
1480 Node.Offset = 0;
1481
1482 //
1483 // Program PPB to only open a single <= 16<MB apperture
1484 //
1485 if (Enable) {
1486 ProgramPpbApperture (OptionRomBase, &Node);
1487 PciEnableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1488 } else {
1489 InitializePpb (Parent);
1490 PciDisableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1491 }
1492
1493 Parent = Parent->Parent;
1494 }
1495
1496 return EFI_SUCCESS;
1497 }
1498
1499 BOOLEAN
1500 ResourceRequestExisted (
1501 IN PCI_RESOURCE_NODE *Bridge
1502 )
1503 /*++
1504
1505 Routine Description:
1506
1507 Arguments:
1508
1509 Bridge - A pointer to the PCI_RESOURCE_NODE.
1510
1511 Returns:
1512
1513 None
1514
1515 --*/
1516 {
1517 if (Bridge != NULL) {
1518 if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
1519 return TRUE;
1520 }
1521 }
1522
1523 return FALSE;
1524 }
1525
1526 EFI_STATUS
1527 InitializeResourcePool (
1528 PCI_RESOURCE_NODE *ResourcePool,
1529 PCI_BAR_TYPE ResourceType
1530 )
1531 /*++
1532
1533 Routine Description:
1534
1535 Arguments:
1536
1537 Returns:
1538
1539 None
1540
1541 --*/
1542 // TODO: ResourcePool - add argument and description to function comment
1543 // TODO: ResourceType - add argument and description to function comment
1544 // TODO: EFI_SUCCESS - add return value to function comment
1545 {
1546
1547 ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
1548 ResourcePool->ResType = ResourceType;
1549 ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
1550 InitializeListHead (&ResourcePool->ChildList);
1551
1552 return EFI_SUCCESS;
1553 }
1554
1555 EFI_STATUS
1556 GetResourceMap (
1557 PCI_IO_DEVICE *PciDev,
1558 PCI_RESOURCE_NODE **IoBridge,
1559 PCI_RESOURCE_NODE **Mem32Bridge,
1560 PCI_RESOURCE_NODE **PMem32Bridge,
1561 PCI_RESOURCE_NODE **Mem64Bridge,
1562 PCI_RESOURCE_NODE **PMem64Bridge,
1563 PCI_RESOURCE_NODE *IoPool,
1564 PCI_RESOURCE_NODE *Mem32Pool,
1565 PCI_RESOURCE_NODE *PMem32Pool,
1566 PCI_RESOURCE_NODE *Mem64Pool,
1567 PCI_RESOURCE_NODE *PMem64Pool
1568 )
1569 /*++
1570
1571 Routine Description:
1572
1573 Arguments:
1574
1575 Returns:
1576
1577 None
1578
1579 --*/
1580 // TODO: PciDev - add argument and description to function comment
1581 // TODO: IoBridge - add argument and description to function comment
1582 // TODO: Mem32Bridge - add argument and description to function comment
1583 // TODO: PMem32Bridge - add argument and description to function comment
1584 // TODO: Mem64Bridge - add argument and description to function comment
1585 // TODO: PMem64Bridge - add argument and description to function comment
1586 // TODO: IoPool - add argument and description to function comment
1587 // TODO: Mem32Pool - add argument and description to function comment
1588 // TODO: PMem32Pool - add argument and description to function comment
1589 // TODO: Mem64Pool - add argument and description to function comment
1590 // TODO: PMem64Pool - add argument and description to function comment
1591 // TODO: EFI_SUCCESS - add return value to function comment
1592 {
1593
1594 PCI_RESOURCE_NODE *Temp;
1595 LIST_ENTRY *CurrentLink;
1596
1597 CurrentLink = IoPool->ChildList.ForwardLink;
1598
1599 //
1600 // Get Io resource map
1601 //
1602 while (CurrentLink != &IoPool->ChildList) {
1603
1604 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1605
1606 if (Temp->PciDev == PciDev) {
1607 *IoBridge = Temp;
1608 }
1609
1610 CurrentLink = CurrentLink->ForwardLink;
1611 }
1612
1613 //
1614 // Get Mem32 resource map
1615 //
1616 CurrentLink = Mem32Pool->ChildList.ForwardLink;
1617
1618 while (CurrentLink != &Mem32Pool->ChildList) {
1619
1620 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1621
1622 if (Temp->PciDev == PciDev) {
1623 *Mem32Bridge = Temp;
1624 }
1625
1626 CurrentLink = CurrentLink->ForwardLink;
1627 }
1628
1629 //
1630 // Get Pmem32 resource map
1631 //
1632 CurrentLink = PMem32Pool->ChildList.ForwardLink;
1633
1634 while (CurrentLink != &PMem32Pool->ChildList) {
1635
1636 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1637
1638 if (Temp->PciDev == PciDev) {
1639 *PMem32Bridge = Temp;
1640 }
1641
1642 CurrentLink = CurrentLink->ForwardLink;
1643 }
1644
1645 //
1646 // Get Mem64 resource map
1647 //
1648 CurrentLink = Mem64Pool->ChildList.ForwardLink;
1649
1650 while (CurrentLink != &Mem64Pool->ChildList) {
1651
1652 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1653
1654 if (Temp->PciDev == PciDev) {
1655 *Mem64Bridge = Temp;
1656 }
1657
1658 CurrentLink = CurrentLink->ForwardLink;
1659 }
1660
1661 //
1662 // Get Pmem64 resource map
1663 //
1664 CurrentLink = PMem64Pool->ChildList.ForwardLink;
1665
1666 while (CurrentLink != &PMem64Pool->ChildList) {
1667
1668 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1669
1670 if (Temp->PciDev == PciDev) {
1671 *PMem64Bridge = Temp;
1672 }
1673
1674 CurrentLink = CurrentLink->ForwardLink;
1675 }
1676
1677 return EFI_SUCCESS;
1678 }
1679
1680 EFI_STATUS
1681 DestroyResourceTree (
1682 IN PCI_RESOURCE_NODE *Bridge
1683 )
1684 /*++
1685
1686 Routine Description:
1687
1688 Arguments:
1689
1690 Returns:
1691
1692 None
1693
1694 --*/
1695 // TODO: Bridge - add argument and description to function comment
1696 // TODO: EFI_SUCCESS - add return value to function comment
1697 {
1698 PCI_RESOURCE_NODE *Temp;
1699 LIST_ENTRY *CurrentLink;
1700
1701 while (!IsListEmpty (&Bridge->ChildList)) {
1702
1703 CurrentLink = Bridge->ChildList.ForwardLink;
1704
1705 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1706
1707 RemoveEntryList (CurrentLink);
1708
1709 if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
1710 DestroyResourceTree (Temp);
1711 }
1712
1713 gBS->FreePool (Temp);
1714 }
1715
1716 return EFI_SUCCESS;
1717 }
1718
1719 EFI_STATUS
1720 RecordReservedResource (
1721 IN UINT64 Base,
1722 IN UINT64 Length,
1723 IN PCI_BAR_TYPE ResType,
1724 IN PCI_IO_DEVICE *Bridge
1725 )
1726 /*++
1727
1728 Routine Description:
1729
1730 Arguments:
1731
1732 Returns:
1733
1734 None
1735
1736 --*/
1737 // TODO: Base - add argument and description to function comment
1738 // TODO: Length - add argument and description to function comment
1739 // TODO: ResType - add argument and description to function comment
1740 // TODO: Bridge - add argument and description to function comment
1741 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1742 // TODO: EFI_SUCCESS - add return value to function comment
1743 {
1744 PCI_RESERVED_RESOURCE_LIST *ReservedNode;
1745
1746 ReservedNode = AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST));
1747 if (ReservedNode == NULL) {
1748 return EFI_OUT_OF_RESOURCES;
1749 }
1750
1751 ReservedNode->Signature = RESERVED_RESOURCE_SIGNATURE;
1752 ReservedNode->Node.Base = Base;
1753 ReservedNode->Node.Length = Length;
1754 ReservedNode->Node.ResType = ResType;
1755
1756 InsertTailList (&Bridge->ReservedResourceList, &(ReservedNode->Link));
1757
1758 return EFI_SUCCESS;
1759 }
1760
1761 EFI_STATUS
1762 ResourcePaddingForCardBusBridge (
1763 PCI_IO_DEVICE *PciDev,
1764 PCI_RESOURCE_NODE *IoNode,
1765 PCI_RESOURCE_NODE *Mem32Node,
1766 PCI_RESOURCE_NODE *PMem32Node,
1767 PCI_RESOURCE_NODE *Mem64Node,
1768 PCI_RESOURCE_NODE *PMem64Node
1769 )
1770 /*++
1771
1772 Routine Description:
1773
1774 Arguments:
1775
1776 Returns:
1777
1778 None
1779
1780 --*/
1781 // TODO: PciDev - add argument and description to function comment
1782 // TODO: IoNode - add argument and description to function comment
1783 // TODO: Mem32Node - add argument and description to function comment
1784 // TODO: PMem32Node - add argument and description to function comment
1785 // TODO: Mem64Node - add argument and description to function comment
1786 // TODO: PMem64Node - add argument and description to function comment
1787 // TODO: EFI_SUCCESS - add return value to function comment
1788 {
1789 PCI_RESOURCE_NODE *Node;
1790
1791 Node = NULL;
1792
1793 //
1794 // Memory Base/Limit Register 0
1795 // Bar 1 denodes memory range 0
1796 //
1797 Node = CreateResourceNode (
1798 PciDev,
1799 0x2000000,
1800 0x1ffffff,
1801 1,
1802 PciBarTypeMem32,
1803 PciResUsagePadding
1804 );
1805
1806 InsertResourceNode (
1807 Mem32Node,
1808 Node
1809 );
1810
1811 //
1812 // Memory Base/Limit Register 1
1813 // Bar 2 denodes memory range1
1814 //
1815 Node = CreateResourceNode (
1816 PciDev,
1817 0x2000000,
1818 0x1ffffff,
1819 2,
1820 PciBarTypePMem32,
1821 PciResUsagePadding
1822 );
1823
1824 InsertResourceNode (
1825 PMem32Node,
1826 Node
1827 );
1828
1829 //
1830 // Io Base/Limit
1831 // Bar 3 denodes io range 0
1832 //
1833 Node = CreateResourceNode (
1834 PciDev,
1835 0x100,
1836 0xff,
1837 3,
1838 PciBarTypeIo16,
1839 PciResUsagePadding
1840 );
1841
1842 InsertResourceNode (
1843 IoNode,
1844 Node
1845 );
1846
1847 //
1848 // Io Base/Limit
1849 // Bar 4 denodes io range 0
1850 //
1851 Node = CreateResourceNode (
1852 PciDev,
1853 0x100,
1854 0xff,
1855 4,
1856 PciBarTypeIo16,
1857 PciResUsagePadding
1858 );
1859
1860 InsertResourceNode (
1861 IoNode,
1862 Node
1863 );
1864
1865 return EFI_SUCCESS;
1866 }
1867
1868 EFI_STATUS
1869 ProgramP2C (
1870 IN UINT64 Base,
1871 IN PCI_RESOURCE_NODE *Node
1872 )
1873 /*++
1874
1875 Routine Description:
1876
1877 Arguments:
1878
1879 Returns:
1880
1881 None
1882
1883 --*/
1884 // TODO: Base - add argument and description to function comment
1885 // TODO: Node - add argument and description to function comment
1886 // TODO: EFI_SUCCESS - add return value to function comment
1887 {
1888 EFI_PCI_IO_PROTOCOL *PciIo;
1889 UINT64 Address;
1890 UINT64 TempAddress;
1891 UINT16 BridgeControl;
1892
1893 Address = 0;
1894 PciIo = &(Node->PciDev->PciIo);
1895
1896 Address = Base + Node->Offset;
1897
1898 //
1899 // Indicate pci bus driver has allocated
1900 // resource for this device
1901 // It might be a temporary solution here since
1902 // pci device could have multiple bar
1903 //
1904 Node->PciDev->Allocated = TRUE;
1905
1906 switch (Node->Bar) {
1907
1908 case P2C_BAR_0:
1909 PciIoWrite (
1910 PciIo,
1911 EfiPciIoWidthUint32,
1912 (Node->PciDev->PciBar[Node->Bar]).Offset,
1913 1,
1914 &Address
1915 );
1916
1917 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1918 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1919 break;
1920
1921 case P2C_MEM_1:
1922 PciIoWrite (
1923 PciIo,
1924 EfiPciIoWidthUint32,
1925 0x1c,
1926 1,
1927 &Address
1928 );
1929
1930 TempAddress = Address + Node->Length - 1;
1931 PciIoWrite (
1932 PciIo,
1933 EfiPciIoWidthUint32,
1934 0x20,
1935 1,
1936 &TempAddress
1937 );
1938
1939 if (Node->ResType == PciBarTypeMem32) {
1940
1941 //
1942 // Set non-prefetchable bit
1943 //
1944 PciIoRead (
1945 PciIo,
1946 EfiPciIoWidthUint16,
1947 0x3e,
1948 1,
1949 &BridgeControl
1950 );
1951
1952 BridgeControl &= 0xfeff;
1953 PciIoWrite (
1954 PciIo,
1955 EfiPciIoWidthUint16,
1956 0x3e,
1957 1,
1958 &BridgeControl
1959 );
1960
1961 } else {
1962
1963 //
1964 // Set pre-fetchable bit
1965 //
1966 PciIoRead (
1967 PciIo,
1968 EfiPciIoWidthUint16,
1969 0x3e,
1970 1,
1971 &BridgeControl
1972 );
1973
1974 BridgeControl |= 0x0100;
1975 PciIoWrite (
1976 PciIo,
1977 EfiPciIoWidthUint16,
1978 0x3e,
1979 1,
1980 &BridgeControl
1981 );
1982 }
1983
1984 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1985 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1986 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
1987
1988 break;
1989
1990 case P2C_MEM_2:
1991 PciIoWrite (
1992 PciIo,
1993 EfiPciIoWidthUint32,
1994 0x24,
1995 1,
1996 &Address
1997 );
1998
1999 TempAddress = Address + Node->Length - 1;
2000
2001 PciIoWrite (
2002 PciIo,
2003 EfiPciIoWidthUint32,
2004 0x28,
2005 1,
2006 &TempAddress
2007 );
2008
2009 if (Node->ResType == PciBarTypeMem32) {
2010
2011 //
2012 // Set non-prefetchable bit
2013 //
2014 PciIoRead (
2015 PciIo,
2016 EfiPciIoWidthUint16,
2017 0x3e,
2018 1,
2019 &BridgeControl
2020 );
2021
2022 BridgeControl &= 0xfdff;
2023 PciIoWrite (
2024 PciIo,
2025 EfiPciIoWidthUint16,
2026 0x3e,
2027 1,
2028 &BridgeControl
2029 );
2030 } else {
2031
2032 //
2033 // Set pre-fetchable bit
2034 //
2035 PciIoRead (
2036 PciIo,
2037 EfiPciIoWidthUint16,
2038 0x3e,
2039 1,
2040 &BridgeControl
2041 );
2042
2043 BridgeControl |= 0x0200;
2044 PciIoWrite (
2045 PciIo,
2046 EfiPciIoWidthUint16,
2047 0x3e,
2048 1,
2049 &BridgeControl
2050 );
2051 }
2052
2053 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2054 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2055 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2056 break;
2057
2058 case P2C_IO_1:
2059 PciIoWrite (
2060 PciIo,
2061 EfiPciIoWidthUint32,
2062 0x2c,
2063 1,
2064 &Address
2065 );
2066 TempAddress = Address + Node->Length - 1;
2067 PciIoWrite (
2068 PciIo,
2069 EfiPciIoWidthUint32,
2070 0x30,
2071 1,
2072 &TempAddress
2073 );
2074
2075 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2076 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2077 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2078
2079 break;
2080
2081 case P2C_IO_2:
2082 PciIoWrite (
2083 PciIo,
2084 EfiPciIoWidthUint32,
2085 0x34,
2086 1,
2087 &Address
2088 );
2089
2090 TempAddress = Address + Node->Length - 1;
2091 PciIoWrite (
2092 PciIo,
2093 EfiPciIoWidthUint32,
2094 0x38,
2095 1,
2096 &TempAddress
2097 );
2098
2099 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2100 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2101 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2102 break;
2103
2104 default:
2105 break;
2106 }
2107
2108 return EFI_SUCCESS;
2109 }
2110
2111 EFI_STATUS
2112 ApplyResourcePadding (
2113 PCI_IO_DEVICE *PciDev,
2114 PCI_RESOURCE_NODE *IoNode,
2115 PCI_RESOURCE_NODE *Mem32Node,
2116 PCI_RESOURCE_NODE *PMem32Node,
2117 PCI_RESOURCE_NODE *Mem64Node,
2118 PCI_RESOURCE_NODE *PMem64Node
2119 )
2120 /*++
2121
2122 Routine Description:
2123
2124 Arguments:
2125
2126 Returns:
2127
2128 None
2129
2130 --*/
2131 // TODO: PciDev - add argument and description to function comment
2132 // TODO: IoNode - add argument and description to function comment
2133 // TODO: Mem32Node - add argument and description to function comment
2134 // TODO: PMem32Node - add argument and description to function comment
2135 // TODO: Mem64Node - add argument and description to function comment
2136 // TODO: PMem64Node - add argument and description to function comment
2137 // TODO: EFI_SUCCESS - add return value to function comment
2138 {
2139 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
2140 PCI_RESOURCE_NODE *Node;
2141 UINT8 DummyBarIndex;
2142
2143 DummyBarIndex = 0;
2144 Ptr = PciDev->ResourcePaddingDescriptors;
2145
2146 while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2147
2148 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
2149 if (Ptr->AddrLen != 0) {
2150
2151 Node = CreateResourceNode (
2152 PciDev,
2153 Ptr->AddrLen,
2154 Ptr->AddrRangeMax,
2155 DummyBarIndex,
2156 PciBarTypeIo16,
2157 PciResUsagePadding
2158 );
2159 InsertResourceNode (
2160 IoNode,
2161 Node
2162 );
2163 }
2164
2165 Ptr++;
2166 continue;
2167 }
2168
2169 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
2170
2171 if (Ptr->AddrSpaceGranularity == 32) {
2172
2173 //
2174 // prefechable
2175 //
2176 if (Ptr->SpecificFlag == 0x6) {
2177 if (Ptr->AddrLen) {
2178 Node = CreateResourceNode (
2179 PciDev,
2180 Ptr->AddrLen,
2181 Ptr->AddrRangeMax,
2182 DummyBarIndex,
2183 PciBarTypePMem32,
2184 PciResUsagePadding
2185 );
2186 InsertResourceNode (
2187 PMem32Node,
2188 Node
2189 );
2190 }
2191
2192 Ptr++;
2193 continue;
2194 }
2195
2196 //
2197 // Non-prefechable
2198 //
2199 if (Ptr->SpecificFlag == 0) {
2200 if (Ptr->AddrLen) {
2201 Node = CreateResourceNode (
2202 PciDev,
2203 Ptr->AddrLen,
2204 Ptr->AddrRangeMax,
2205 DummyBarIndex,
2206 PciBarTypeMem32,
2207 PciResUsagePadding
2208 );
2209 InsertResourceNode (
2210 Mem32Node,
2211 Node
2212 );
2213 }
2214
2215 Ptr++;
2216 continue;
2217 }
2218 }
2219
2220 if (Ptr->AddrSpaceGranularity == 64) {
2221
2222 //
2223 // prefechable
2224 //
2225 if (Ptr->SpecificFlag == 0x6) {
2226 if (Ptr->AddrLen) {
2227 Node = CreateResourceNode (
2228 PciDev,
2229 Ptr->AddrLen,
2230 Ptr->AddrRangeMax,
2231 DummyBarIndex,
2232 PciBarTypePMem64,
2233 PciResUsagePadding
2234 );
2235 InsertResourceNode (
2236 PMem64Node,
2237 Node
2238 );
2239 }
2240
2241 Ptr++;
2242 continue;
2243 }
2244
2245 //
2246 // Non-prefechable
2247 //
2248 if (Ptr->SpecificFlag == 0) {
2249 if (Ptr->AddrLen) {
2250 Node = CreateResourceNode (
2251 PciDev,
2252 Ptr->AddrLen,
2253 Ptr->AddrRangeMax,
2254 DummyBarIndex,
2255 PciBarTypeMem64,
2256 PciResUsagePadding
2257 );
2258 InsertResourceNode (
2259 Mem64Node,
2260 Node
2261 );
2262 }
2263
2264 Ptr++;
2265 continue;
2266 }
2267 }
2268 }
2269
2270 Ptr++;
2271 }
2272
2273 return EFI_SUCCESS;
2274 }
2275
2276 //
2277 // Light PCI bus driver woundn't support hotplug root device
2278 // So no need to pad resource for them
2279 //
2280 VOID
2281 GetResourcePaddingPpb (
2282 IN PCI_IO_DEVICE *PciIoDevice
2283 )
2284 /*++
2285
2286 Routine Description:
2287
2288 Get resource.
2289
2290 Arguments:
2291
2292 PciIoDevice A pointer to a pci device.
2293
2294 Returns:
2295
2296 None
2297
2298 --*/
2299 {
2300 if (gPciHotPlugInit) {
2301 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
2302 GetResourcePaddingForHpb (PciIoDevice);
2303 }
2304 }
2305 }