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