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