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