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