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