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