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