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