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