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