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