]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciLib.c
... / ...
CommitLineData
1/** @file\r
2 Internal library implementation for PCI Bus module.\r
3\r
4Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>\r
5(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "PciBus.h"\r
11\r
12GLOBAL_REMOVE_IF_UNREFERENCED\r
13CHAR16 *mBarTypeStr[] = {\r
14 L"Unknow",\r
15 L" Io16",\r
16 L" Io32",\r
17 L" Mem32",\r
18 L"PMem32",\r
19 L" Mem64",\r
20 L"PMem64",\r
21 L" OpRom",\r
22 L" Io",\r
23 L" Mem",\r
24 L"Unknow"\r
25};\r
26\r
27/**\r
28 Retrieve the max bus number that is assigned to the Root Bridge hierarchy.\r
29 It can support the case that there are multiple bus ranges.\r
30\r
31 @param Bridge Bridge device instance.\r
32\r
33 @retval The max bus number that is assigned to this Root Bridge hierarchy.\r
34\r
35**/\r
36UINT16\r
37PciGetMaxBusNumber (\r
38 IN PCI_IO_DEVICE *Bridge\r
39 )\r
40{\r
41 PCI_IO_DEVICE *RootBridge;\r
42 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges;\r
43 UINT64 MaxNumberInRange;\r
44\r
45 //\r
46 // Get PCI Root Bridge device\r
47 //\r
48 RootBridge = Bridge;\r
49 while (RootBridge->Parent != NULL) {\r
50 RootBridge = RootBridge->Parent;\r
51 }\r
52\r
53 MaxNumberInRange = 0;\r
54 //\r
55 // Iterate the bus number ranges to get max PCI bus number\r
56 //\r
57 BusNumberRanges = RootBridge->BusNumberRanges;\r
58 while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
59 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
60 BusNumberRanges++;\r
61 }\r
62\r
63 return (UINT16)MaxNumberInRange;\r
64}\r
65\r
66/**\r
67 Retrieve the PCI Card device BAR information via PciIo interface.\r
68\r
69 @param PciIoDevice PCI Card device instance.\r
70\r
71**/\r
72VOID\r
73GetBackPcCardBar (\r
74 IN PCI_IO_DEVICE *PciIoDevice\r
75 )\r
76{\r
77 UINT32 Address;\r
78\r
79 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
80 return;\r
81 }\r
82\r
83 //\r
84 // Read PciBar information from the bar register\r
85 //\r
86 if (!gFullEnumeration) {\r
87 Address = 0;\r
88 PciIoDevice->PciIo.Pci.Read (\r
89 &(PciIoDevice->PciIo),\r
90 EfiPciIoWidthUint32,\r
91 PCI_CARD_MEMORY_BASE_0,\r
92 1,\r
93 &Address\r
94 );\r
95\r
96 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64)(Address);\r
97 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;\r
98 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;\r
99\r
100 Address = 0;\r
101 PciIoDevice->PciIo.Pci.Read (\r
102 &(PciIoDevice->PciIo),\r
103 EfiPciIoWidthUint32,\r
104 PCI_CARD_MEMORY_BASE_1,\r
105 1,\r
106 &Address\r
107 );\r
108 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64)(Address);\r
109 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;\r
110 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;\r
111\r
112 Address = 0;\r
113 PciIoDevice->PciIo.Pci.Read (\r
114 &(PciIoDevice->PciIo),\r
115 EfiPciIoWidthUint32,\r
116 PCI_CARD_IO_BASE_0_LOWER,\r
117 1,\r
118 &Address\r
119 );\r
120 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64)(Address);\r
121 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;\r
122 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;\r
123\r
124 Address = 0;\r
125 PciIoDevice->PciIo.Pci.Read (\r
126 &(PciIoDevice->PciIo),\r
127 EfiPciIoWidthUint32,\r
128 PCI_CARD_IO_BASE_1_LOWER,\r
129 1,\r
130 &Address\r
131 );\r
132 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64)(Address);\r
133 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;\r
134 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;\r
135 }\r
136\r
137 if ((gPciHotPlugInit != NULL) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
138 GetResourcePaddingForHpb (PciIoDevice);\r
139 }\r
140}\r
141\r
142/**\r
143 Remove rejected pci device from specific root bridge\r
144 handle.\r
145\r
146 @param RootBridgeHandle Specific parent root bridge handle.\r
147 @param Bridge Bridge device instance.\r
148\r
149**/\r
150VOID\r
151RemoveRejectedPciDevices (\r
152 IN EFI_HANDLE RootBridgeHandle,\r
153 IN PCI_IO_DEVICE *Bridge\r
154 )\r
155{\r
156 PCI_IO_DEVICE *Temp;\r
157 LIST_ENTRY *CurrentLink;\r
158 LIST_ENTRY *LastLink;\r
159\r
160 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
161 return;\r
162 }\r
163\r
164 CurrentLink = Bridge->ChildList.ForwardLink;\r
165\r
166 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
167 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
168\r
169 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
170 //\r
171 // Remove rejected devices recusively\r
172 //\r
173 RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
174 } else {\r
175 //\r
176 // Skip rejection for all PPBs, while detect rejection for others\r
177 //\r
178 if (IsPciDeviceRejected (Temp)) {\r
179 //\r
180 // For P2C, remove all devices on it\r
181 //\r
182 if (!IsListEmpty (&Temp->ChildList)) {\r
183 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
184 }\r
185\r
186 //\r
187 // Finally remove itself\r
188 //\r
189 LastLink = CurrentLink->BackLink;\r
190 RemoveEntryList (CurrentLink);\r
191 FreePciDevice (Temp);\r
192\r
193 CurrentLink = LastLink;\r
194 }\r
195 }\r
196\r
197 CurrentLink = CurrentLink->ForwardLink;\r
198 }\r
199}\r
200\r
201/**\r
202 Dump the resourc map of the bridge device.\r
203\r
204 @param[in] BridgeResource Resource descriptor of the bridge device.\r
205**/\r
206VOID\r
207DumpBridgeResource (\r
208 IN PCI_RESOURCE_NODE *BridgeResource\r
209 )\r
210{\r
211 LIST_ENTRY *Link;\r
212 PCI_RESOURCE_NODE *Resource;\r
213 PCI_BAR *Bar;\r
214\r
215 if ((BridgeResource != NULL) && (BridgeResource->Length != 0)) {\r
216 DEBUG ((\r
217 DEBUG_INFO,\r
218 "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",\r
219 mBarTypeStr[MIN (BridgeResource->ResType, PciBarTypeMaxType)],\r
220 BridgeResource->PciDev->PciBar[BridgeResource->Bar].BaseAddress,\r
221 BridgeResource->Length,\r
222 BridgeResource->Alignment\r
223 ));\r
224 for ( Link = GetFirstNode (&BridgeResource->ChildList)\r
225 ; !IsNull (&BridgeResource->ChildList, Link)\r
226 ; Link = GetNextNode (&BridgeResource->ChildList, Link)\r
227 )\r
228 {\r
229 Resource = RESOURCE_NODE_FROM_LINK (Link);\r
230 if (Resource->ResourceUsage == PciResUsageTypical) {\r
231 Bar = Resource->Virtual ? Resource->PciDev->VfPciBar : Resource->PciDev->PciBar;\r
232 DEBUG ((\r
233 DEBUG_INFO,\r
234 " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",\r
235 Bar[Resource->Bar].BaseAddress,\r
236 Resource->Length,\r
237 Resource->Alignment,\r
238 IS_PCI_BRIDGE (&Resource->PciDev->Pci) ? L"PPB" :\r
239 IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) ? L"P2C" :\r
240 L"PCI",\r
241 Resource->PciDev->BusNumber,\r
242 Resource->PciDev->DeviceNumber,\r
243 Resource->PciDev->FunctionNumber\r
244 ));\r
245\r
246 if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) ||\r
247 (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < PPB_IO_RANGE)) ||\r
248 (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < P2C_MEM_1))\r
249 )\r
250 {\r
251 //\r
252 // The resource requirement comes from the device itself.\r
253 //\r
254 DEBUG ((DEBUG_INFO, "%02x]", Bar[Resource->Bar].Offset));\r
255 } else {\r
256 //\r
257 // The resource requirement comes from the subordinate devices.\r
258 //\r
259 DEBUG ((DEBUG_INFO, "**]"));\r
260 }\r
261 } else {\r
262 DEBUG ((DEBUG_INFO, " Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource->Length, Resource->Alignment));\r
263 }\r
264\r
265 if (BridgeResource->ResType != Resource->ResType) {\r
266 DEBUG ((DEBUG_INFO, "; Type = %s", mBarTypeStr[MIN (Resource->ResType, PciBarTypeMaxType)]));\r
267 }\r
268\r
269 DEBUG ((DEBUG_INFO, "\n"));\r
270 }\r
271 }\r
272}\r
273\r
274/**\r
275 Find the corresponding resource node for the Device in child list of BridgeResource.\r
276\r
277 @param[in] Device Pointer to PCI_IO_DEVICE.\r
278 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.\r
279 @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.\r
280\r
281 @return Count of the resource descriptors returned.\r
282**/\r
283UINTN\r
284FindResourceNode (\r
285 IN PCI_IO_DEVICE *Device,\r
286 IN PCI_RESOURCE_NODE *BridgeResource,\r
287 OUT PCI_RESOURCE_NODE **DeviceResources OPTIONAL\r
288 )\r
289{\r
290 LIST_ENTRY *Link;\r
291 PCI_RESOURCE_NODE *Resource;\r
292 UINTN Count;\r
293\r
294 Count = 0;\r
295 for ( Link = BridgeResource->ChildList.ForwardLink\r
296 ; Link != &BridgeResource->ChildList\r
297 ; Link = Link->ForwardLink\r
298 )\r
299 {\r
300 Resource = RESOURCE_NODE_FROM_LINK (Link);\r
301 if (Resource->PciDev == Device) {\r
302 if (DeviceResources != NULL) {\r
303 DeviceResources[Count] = Resource;\r
304 }\r
305\r
306 Count++;\r
307 }\r
308 }\r
309\r
310 return Count;\r
311}\r
312\r
313/**\r
314 Dump the resource map of all the devices under Bridge.\r
315\r
316 @param[in] Bridge Bridge device instance.\r
317 @param[in] Resources Resource descriptors for the bridge device.\r
318 @param[in] ResourceCount Count of resource descriptors.\r
319**/\r
320VOID\r
321DumpResourceMap (\r
322 IN PCI_IO_DEVICE *Bridge,\r
323 IN PCI_RESOURCE_NODE **Resources,\r
324 IN UINTN ResourceCount\r
325 )\r
326{\r
327 EFI_STATUS Status;\r
328 LIST_ENTRY *Link;\r
329 PCI_IO_DEVICE *Device;\r
330 UINTN Index;\r
331 CHAR16 *Str;\r
332 PCI_RESOURCE_NODE **ChildResources;\r
333 UINTN ChildResourceCount;\r
334\r
335 DEBUG ((DEBUG_INFO, "PciBus: Resource Map for "));\r
336\r
337 Status = gBS->OpenProtocol (\r
338 Bridge->Handle,\r
339 &gEfiPciRootBridgeIoProtocolGuid,\r
340 NULL,\r
341 NULL,\r
342 NULL,\r
343 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
344 );\r
345 if (EFI_ERROR (Status)) {\r
346 DEBUG ((\r
347 DEBUG_INFO,\r
348 "Bridge [%02x|%02x|%02x]\n",\r
349 Bridge->BusNumber,\r
350 Bridge->DeviceNumber,\r
351 Bridge->FunctionNumber\r
352 ));\r
353 } else {\r
354 Str = ConvertDevicePathToText (\r
355 DevicePathFromHandle (Bridge->Handle),\r
356 FALSE,\r
357 FALSE\r
358 );\r
359 DEBUG ((DEBUG_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));\r
360 if (Str != NULL) {\r
361 FreePool (Str);\r
362 }\r
363 }\r
364\r
365 for (Index = 0; Index < ResourceCount; Index++) {\r
366 DumpBridgeResource (Resources[Index]);\r
367 }\r
368\r
369 DEBUG ((DEBUG_INFO, "\n"));\r
370\r
371 for ( Link = Bridge->ChildList.ForwardLink\r
372 ; Link != &Bridge->ChildList\r
373 ; Link = Link->ForwardLink\r
374 )\r
375 {\r
376 Device = PCI_IO_DEVICE_FROM_LINK (Link);\r
377 if (IS_PCI_BRIDGE (&Device->Pci)) {\r
378 ChildResourceCount = 0;\r
379 for (Index = 0; Index < ResourceCount; Index++) {\r
380 ChildResourceCount += FindResourceNode (Device, Resources[Index], NULL);\r
381 }\r
382\r
383 ChildResources = AllocatePool (sizeof (PCI_RESOURCE_NODE *) * ChildResourceCount);\r
384 ASSERT (ChildResources != NULL);\r
385 ChildResourceCount = 0;\r
386 for (Index = 0; Index < ResourceCount; Index++) {\r
387 ChildResourceCount += FindResourceNode (Device, Resources[Index], &ChildResources[ChildResourceCount]);\r
388 }\r
389\r
390 DumpResourceMap (Device, ChildResources, ChildResourceCount);\r
391 FreePool (ChildResources);\r
392 }\r
393 }\r
394}\r
395\r
396/**\r
397 Adjust the Devices' BAR size to minimum value if it support Resizeable BAR capability.\r
398\r
399 @param RootBridgeDev Pointer to instance of PCI_IO_DEVICE..\r
400\r
401 @return TRUE if BAR size is adjusted.\r
402\r
403**/\r
404BOOLEAN\r
405AdjustPciDeviceBarSize (\r
406 IN PCI_IO_DEVICE *RootBridgeDev\r
407 )\r
408{\r
409 PCI_IO_DEVICE *PciIoDevice;\r
410 LIST_ENTRY *CurrentLink;\r
411 BOOLEAN Adjusted;\r
412 UINTN Offset;\r
413 UINTN BarIndex;\r
414\r
415 Adjusted = FALSE;\r
416 CurrentLink = RootBridgeDev->ChildList.ForwardLink;\r
417\r
418 while (CurrentLink != NULL && CurrentLink != &RootBridgeDev->ChildList) {\r
419 PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
420\r
421 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
422 if (AdjustPciDeviceBarSize (PciIoDevice)) {\r
423 Adjusted = TRUE;\r
424 }\r
425 } else {\r
426 if (PciIoDevice->ResizableBarOffset != 0) {\r
427 DEBUG ((\r
428 DEBUG_ERROR,\r
429 "PciBus: [%02x|%02x|%02x] Adjust Pci Device Bar Size\n",\r
430 PciIoDevice->BusNumber,\r
431 PciIoDevice->DeviceNumber,\r
432 PciIoDevice->FunctionNumber\r
433 ));\r
434 PciProgramResizableBar (PciIoDevice, PciResizableBarMin);\r
435 //\r
436 // Start to parse the bars\r
437 //\r
438 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {\r
439 Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
440 }\r
441\r
442 Adjusted = TRUE;\r
443 DEBUG_CODE (\r
444 DumpPciBars (PciIoDevice);\r
445 );\r
446 }\r
447 }\r
448\r
449 CurrentLink = CurrentLink->ForwardLink;\r
450 }\r
451\r
452 return Adjusted;\r
453}\r
454\r
455/**\r
456 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
457\r
458 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
459\r
460 @retval EFI_SUCCESS Successfully finished resource allocation.\r
461 @retval EFI_NOT_FOUND Cannot get root bridge instance.\r
462 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.\r
463 @retval other Some error occurred when allocating resources for the PCI Host Bridge.\r
464\r
465 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
466\r
467**/\r
468EFI_STATUS\r
469PciHostBridgeResourceAllocator (\r
470 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
471 )\r
472{\r
473 PCI_IO_DEVICE *RootBridgeDev;\r
474 EFI_HANDLE RootBridgeHandle;\r
475 VOID *AcpiConfig;\r
476 EFI_STATUS Status;\r
477 UINT64 IoBase;\r
478 UINT64 Mem32Base;\r
479 UINT64 PMem32Base;\r
480 UINT64 Mem64Base;\r
481 UINT64 PMem64Base;\r
482 UINT64 IoResStatus;\r
483 UINT64 Mem32ResStatus;\r
484 UINT64 PMem32ResStatus;\r
485 UINT64 Mem64ResStatus;\r
486 UINT64 PMem64ResStatus;\r
487 UINT32 MaxOptionRomSize;\r
488 PCI_RESOURCE_NODE *IoBridge;\r
489 PCI_RESOURCE_NODE *Mem32Bridge;\r
490 PCI_RESOURCE_NODE *PMem32Bridge;\r
491 PCI_RESOURCE_NODE *Mem64Bridge;\r
492 PCI_RESOURCE_NODE *PMem64Bridge;\r
493 PCI_RESOURCE_NODE IoPool;\r
494 PCI_RESOURCE_NODE Mem32Pool;\r
495 PCI_RESOURCE_NODE PMem32Pool;\r
496 PCI_RESOURCE_NODE Mem64Pool;\r
497 PCI_RESOURCE_NODE PMem64Pool;\r
498 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;\r
499 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
500 BOOLEAN ResizableBarNeedAdjust;\r
501 BOOLEAN ResizableBarAdjusted;\r
502\r
503 ResizableBarNeedAdjust = PcdGetBool (PcdPcieResizableBarSupport);\r
504\r
505 //\r
506 // It may try several times if the resource allocation fails\r
507 //\r
508 while (TRUE) {\r
509 //\r
510 // Initialize resource pool\r
511 //\r
512 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
513 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
514 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
515 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
516 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
517\r
518 RootBridgeDev = NULL;\r
519 RootBridgeHandle = 0;\r
520\r
521 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
522 //\r
523 // Get Root Bridge Device by handle\r
524 //\r
525 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
526\r
527 if (RootBridgeDev == NULL) {\r
528 return EFI_NOT_FOUND;\r
529 }\r
530\r
531 //\r
532 // Create the entire system resource map from the information collected by\r
533 // enumerator. Several resource tree was created\r
534 //\r
535\r
536 //\r
537 // If non-standard PCI Bridge I/O window alignment is supported,\r
538 // set I/O aligment to minimum possible alignment for root bridge.\r
539 //\r
540 IoBridge = CreateResourceNode (\r
541 RootBridgeDev,\r
542 0,\r
543 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF : 0xFFF,\r
544 RB_IO_RANGE,\r
545 PciBarTypeIo16,\r
546 PciResUsageTypical\r
547 );\r
548\r
549 Mem32Bridge = CreateResourceNode (\r
550 RootBridgeDev,\r
551 0,\r
552 0xFFFFF,\r
553 RB_MEM32_RANGE,\r
554 PciBarTypeMem32,\r
555 PciResUsageTypical\r
556 );\r
557\r
558 PMem32Bridge = CreateResourceNode (\r
559 RootBridgeDev,\r
560 0,\r
561 0xFFFFF,\r
562 RB_PMEM32_RANGE,\r
563 PciBarTypePMem32,\r
564 PciResUsageTypical\r
565 );\r
566\r
567 Mem64Bridge = CreateResourceNode (\r
568 RootBridgeDev,\r
569 0,\r
570 0xFFFFF,\r
571 RB_MEM64_RANGE,\r
572 PciBarTypeMem64,\r
573 PciResUsageTypical\r
574 );\r
575\r
576 PMem64Bridge = CreateResourceNode (\r
577 RootBridgeDev,\r
578 0,\r
579 0xFFFFF,\r
580 RB_PMEM64_RANGE,\r
581 PciBarTypePMem64,\r
582 PciResUsageTypical\r
583 );\r
584\r
585 //\r
586 // Get the max ROM size that the root bridge can process\r
587 // Insert to resource map so that there will be dedicate MEM32 resource range for Option ROM.\r
588 // All devices' Option ROM share the same MEM32 resource.\r
589 //\r
590 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
591 if (MaxOptionRomSize != 0) {\r
592 RootBridgeDev->PciBar[0].BarType = PciBarTypeOpRom;\r
593 RootBridgeDev->PciBar[0].Length = MaxOptionRomSize;\r
594 RootBridgeDev->PciBar[0].Alignment = MaxOptionRomSize - 1;\r
595 GetResourceFromDevice (RootBridgeDev, IoBridge, Mem32Bridge, PMem32Bridge, Mem64Bridge, PMem64Bridge);\r
596 }\r
597\r
598 //\r
599 // Create resourcemap by going through all the devices subject to this root bridge\r
600 //\r
601 CreateResourceMap (\r
602 RootBridgeDev,\r
603 IoBridge,\r
604 Mem32Bridge,\r
605 PMem32Bridge,\r
606 Mem64Bridge,\r
607 PMem64Bridge\r
608 );\r
609\r
610 //\r
611 // Based on the all the resource tree, construct ACPI resource node to\r
612 // submit the resource aperture to pci host bridge protocol\r
613 //\r
614 Status = ConstructAcpiResourceRequestor (\r
615 RootBridgeDev,\r
616 IoBridge,\r
617 Mem32Bridge,\r
618 PMem32Bridge,\r
619 Mem64Bridge,\r
620 PMem64Bridge,\r
621 &AcpiConfig\r
622 );\r
623\r
624 //\r
625 // Insert these resource nodes into the database\r
626 //\r
627 InsertResourceNode (&IoPool, IoBridge);\r
628 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
629 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
630 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
631 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
632\r
633 if (Status == EFI_SUCCESS) {\r
634 //\r
635 // Submit the resource requirement\r
636 //\r
637 Status = PciResAlloc->SubmitResources (\r
638 PciResAlloc,\r
639 RootBridgeDev->Handle,\r
640 AcpiConfig\r
641 );\r
642 //\r
643 // If SubmitResources returns error, PciBus isn't able to start.\r
644 // It's a fatal error so assertion is added.\r
645 //\r
646 DEBUG ((DEBUG_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status));\r
647 ASSERT_EFI_ERROR (Status);\r
648 }\r
649\r
650 //\r
651 // Free acpi resource node\r
652 //\r
653 if (AcpiConfig != NULL) {\r
654 FreePool (AcpiConfig);\r
655 }\r
656\r
657 if (EFI_ERROR (Status)) {\r
658 //\r
659 // Destroy all the resource tree\r
660 //\r
661 DestroyResourceTree (&IoPool);\r
662 DestroyResourceTree (&Mem32Pool);\r
663 DestroyResourceTree (&PMem32Pool);\r
664 DestroyResourceTree (&Mem64Pool);\r
665 DestroyResourceTree (&PMem64Pool);\r
666 return Status;\r
667 }\r
668 }\r
669\r
670 //\r
671 // End while, at least one Root Bridge should be found.\r
672 //\r
673 ASSERT (RootBridgeDev != NULL);\r
674\r
675 //\r
676 // Notify platform to start to program the resource\r
677 //\r
678 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
679 DEBUG ((DEBUG_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status));\r
680 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
681 //\r
682 // If Hot Plug is not supported\r
683 //\r
684 if (EFI_ERROR (Status)) {\r
685 //\r
686 // Allocation failed, then return\r
687 //\r
688 return EFI_OUT_OF_RESOURCES;\r
689 }\r
690\r
691 //\r
692 // Allocation succeed.\r
693 // Get host bridge handle for status report, and then skip the main while\r
694 //\r
695 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
696\r
697 break;\r
698 } else {\r
699 //\r
700 // If Hot Plug is supported\r
701 //\r
702 if (!EFI_ERROR (Status)) {\r
703 //\r
704 // Allocation succeed, then continue the following\r
705 //\r
706 break;\r
707 }\r
708\r
709 //\r
710 // If the resource allocation is unsuccessful, free resources on bridge\r
711 //\r
712\r
713 RootBridgeDev = NULL;\r
714 RootBridgeHandle = 0;\r
715\r
716 IoResStatus = EFI_RESOURCE_SATISFIED;\r
717 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
718 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
719 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
720 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
721\r
722 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
723 //\r
724 // Get RootBridg Device by handle\r
725 //\r
726 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
727 if (RootBridgeDev == NULL) {\r
728 return EFI_NOT_FOUND;\r
729 }\r
730\r
731 //\r
732 // Get host bridge handle for status report\r
733 //\r
734 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
735\r
736 //\r
737 // Get acpi resource node for all the resource types\r
738 //\r
739 AcpiConfig = NULL;\r
740\r
741 Status = PciResAlloc->GetProposedResources (\r
742 PciResAlloc,\r
743 RootBridgeDev->Handle,\r
744 &AcpiConfig\r
745 );\r
746\r
747 if (EFI_ERROR (Status)) {\r
748 return Status;\r
749 }\r
750\r
751 if (AcpiConfig != NULL) {\r
752 //\r
753 // Adjust resource allocation policy for each RB\r
754 //\r
755 GetResourceAllocationStatus (\r
756 AcpiConfig,\r
757 &IoResStatus,\r
758 &Mem32ResStatus,\r
759 &PMem32ResStatus,\r
760 &Mem64ResStatus,\r
761 &PMem64ResStatus\r
762 );\r
763 FreePool (AcpiConfig);\r
764 }\r
765 }\r
766\r
767 //\r
768 // End while\r
769 //\r
770\r
771 //\r
772 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
773 //\r
774 //\r
775 // It is very difficult to follow the spec here\r
776 // Device path , Bar index can not be get here\r
777 //\r
778 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
779\r
780 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
781 EFI_PROGRESS_CODE,\r
782 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
783 (VOID *)&AllocFailExtendedData,\r
784 sizeof (AllocFailExtendedData)\r
785 );\r
786\r
787 //\r
788 // When resource conflict happens, adjust the BAR size first.\r
789 // Only when adjusting BAR size doesn't help or BAR size cannot be adjusted,\r
790 // reject the device who requests largest resource that causes conflict.\r
791 //\r
792 ResizableBarAdjusted = FALSE;\r
793 if (ResizableBarNeedAdjust) {\r
794 ResizableBarAdjusted = AdjustPciDeviceBarSize (RootBridgeDev);\r
795 ResizableBarNeedAdjust = FALSE;\r
796 }\r
797\r
798 if (!ResizableBarAdjusted) {\r
799 Status = PciHostBridgeAdjustAllocation (\r
800 &IoPool,\r
801 &Mem32Pool,\r
802 &PMem32Pool,\r
803 &Mem64Pool,\r
804 &PMem64Pool,\r
805 IoResStatus,\r
806 Mem32ResStatus,\r
807 PMem32ResStatus,\r
808 Mem64ResStatus,\r
809 PMem64ResStatus\r
810 );\r
811 }\r
812\r
813 //\r
814 // Destroy all the resource tree\r
815 //\r
816 DestroyResourceTree (&IoPool);\r
817 DestroyResourceTree (&Mem32Pool);\r
818 DestroyResourceTree (&PMem32Pool);\r
819 DestroyResourceTree (&Mem64Pool);\r
820 DestroyResourceTree (&PMem64Pool);\r
821\r
822 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
823\r
824 if (EFI_ERROR (Status)) {\r
825 return Status;\r
826 }\r
827 }\r
828 }\r
829\r
830 //\r
831 // End main while\r
832 //\r
833\r
834 //\r
835 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
836 //\r
837 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
838 EFI_PROGRESS_CODE,\r
839 EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,\r
840 (VOID *)&HandleExtendedData,\r
841 sizeof (HandleExtendedData)\r
842 );\r
843\r
844 //\r
845 // Notify pci bus driver starts to program the resource\r
846 //\r
847 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
848\r
849 if (EFI_ERROR (Status)) {\r
850 return Status;\r
851 }\r
852\r
853 RootBridgeDev = NULL;\r
854\r
855 RootBridgeHandle = 0;\r
856\r
857 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
858 //\r
859 // Get RootBridg Device by handle\r
860 //\r
861 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
862\r
863 if (RootBridgeDev == NULL) {\r
864 return EFI_NOT_FOUND;\r
865 }\r
866\r
867 //\r
868 // Get acpi resource node for all the resource types\r
869 //\r
870 AcpiConfig = NULL;\r
871 Status = PciResAlloc->GetProposedResources (\r
872 PciResAlloc,\r
873 RootBridgeDev->Handle,\r
874 &AcpiConfig\r
875 );\r
876\r
877 if (EFI_ERROR (Status)) {\r
878 return Status;\r
879 }\r
880\r
881 //\r
882 // Get the resource base by interpreting acpi resource node\r
883 //\r
884 //\r
885 GetResourceBase (\r
886 AcpiConfig,\r
887 &IoBase,\r
888 &Mem32Base,\r
889 &PMem32Base,\r
890 &Mem64Base,\r
891 &PMem64Base\r
892 );\r
893\r
894 //\r
895 // Create the entire system resource map from the information collected by\r
896 // enumerator. Several resource tree was created\r
897 //\r
898 FindResourceNode (RootBridgeDev, &IoPool, &IoBridge);\r
899 FindResourceNode (RootBridgeDev, &Mem32Pool, &Mem32Bridge);\r
900 FindResourceNode (RootBridgeDev, &PMem32Pool, &PMem32Bridge);\r
901 FindResourceNode (RootBridgeDev, &Mem64Pool, &Mem64Bridge);\r
902 FindResourceNode (RootBridgeDev, &PMem64Pool, &PMem64Bridge);\r
903\r
904 ASSERT (IoBridge != NULL);\r
905 ASSERT (Mem32Bridge != NULL);\r
906 ASSERT (PMem32Bridge != NULL);\r
907 ASSERT (Mem64Bridge != NULL);\r
908 ASSERT (PMem64Bridge != NULL);\r
909\r
910 //\r
911 // Program IO resources\r
912 //\r
913 ProgramResource (\r
914 IoBase,\r
915 IoBridge\r
916 );\r
917\r
918 //\r
919 // Program Mem32 resources\r
920 //\r
921 ProgramResource (\r
922 Mem32Base,\r
923 Mem32Bridge\r
924 );\r
925\r
926 //\r
927 // Program PMem32 resources\r
928 //\r
929 ProgramResource (\r
930 PMem32Base,\r
931 PMem32Bridge\r
932 );\r
933\r
934 //\r
935 // Program Mem64 resources\r
936 //\r
937 ProgramResource (\r
938 Mem64Base,\r
939 Mem64Bridge\r
940 );\r
941\r
942 //\r
943 // Program PMem64 resources\r
944 //\r
945 ProgramResource (\r
946 PMem64Base,\r
947 PMem64Bridge\r
948 );\r
949\r
950 //\r
951 // Process Option ROM for this root bridge after all BARs are programmed.\r
952 // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Base in order to\r
953 // shadow the Option ROM of the devices under the PPB.\r
954 // After the shadow, Option ROM BAR decoding is turned off and the PPB's MEM32 RANGE\r
955 // BAR is restored back to the original value.\r
956 // The original value is programmed by ProgramResource() above.\r
957 //\r
958 DEBUG ((\r
959 DEBUG_INFO,\r
960 "Process Option ROM: BAR Base/Length = %lx/%lx\n",\r
961 RootBridgeDev->PciBar[0].BaseAddress,\r
962 RootBridgeDev->PciBar[0].Length\r
963 ));\r
964 ProcessOptionRom (RootBridgeDev, RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length);\r
965\r
966 IoBridge->PciDev->PciBar[IoBridge->Bar].BaseAddress = IoBase;\r
967 Mem32Bridge->PciDev->PciBar[Mem32Bridge->Bar].BaseAddress = Mem32Base;\r
968 PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;\r
969 Mem64Bridge->PciDev->PciBar[Mem64Bridge->Bar].BaseAddress = Mem64Base;\r
970 PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;\r
971\r
972 //\r
973 // Dump the resource map for current root bridge\r
974 //\r
975 DEBUG_CODE (\r
976 PCI_RESOURCE_NODE *Resources[5];\r
977 Resources[0] = IoBridge;\r
978 Resources[1] = Mem32Bridge;\r
979 Resources[2] = PMem32Bridge;\r
980 Resources[3] = Mem64Bridge;\r
981 Resources[4] = PMem64Bridge;\r
982 DumpResourceMap (RootBridgeDev, Resources, ARRAY_SIZE (Resources));\r
983 );\r
984\r
985 FreePool (AcpiConfig);\r
986 }\r
987\r
988 //\r
989 // Destroy all the resource tree\r
990 //\r
991 DestroyResourceTree (&IoPool);\r
992 DestroyResourceTree (&Mem32Pool);\r
993 DestroyResourceTree (&PMem32Pool);\r
994 DestroyResourceTree (&Mem64Pool);\r
995 DestroyResourceTree (&PMem64Pool);\r
996\r
997 //\r
998 // Notify the resource allocation phase is to end\r
999 //\r
1000 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
1001\r
1002 return Status;\r
1003}\r
1004\r
1005/**\r
1006 Allocate NumberOfBuses buses and return the next available PCI bus number.\r
1007\r
1008 @param Bridge Bridge device instance.\r
1009 @param StartBusNumber Current available PCI bus number.\r
1010 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.\r
1011 @param NextBusNumber Next available PCI bus number.\r
1012\r
1013 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number\r
1014 is returned in NextBusNumber.\r
1015 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.\r
1016\r
1017**/\r
1018EFI_STATUS\r
1019PciAllocateBusNumber (\r
1020 IN PCI_IO_DEVICE *Bridge,\r
1021 IN UINT8 StartBusNumber,\r
1022 IN UINT8 NumberOfBuses,\r
1023 OUT UINT8 *NextBusNumber\r
1024 )\r
1025{\r
1026 PCI_IO_DEVICE *RootBridge;\r
1027 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges;\r
1028 UINT8 NextNumber;\r
1029 UINT64 MaxNumberInRange;\r
1030\r
1031 //\r
1032 // Get PCI Root Bridge device\r
1033 //\r
1034 RootBridge = Bridge;\r
1035 while (RootBridge->Parent != NULL) {\r
1036 RootBridge = RootBridge->Parent;\r
1037 }\r
1038\r
1039 //\r
1040 // Get next available PCI bus number\r
1041 //\r
1042 BusNumberRanges = RootBridge->BusNumberRanges;\r
1043 while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1044 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
1045 if ((StartBusNumber >= BusNumberRanges->AddrRangeMin) && (StartBusNumber <= MaxNumberInRange)) {\r
1046 NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);\r
1047 while (NextNumber > MaxNumberInRange) {\r
1048 ++BusNumberRanges;\r
1049 if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {\r
1050 return EFI_OUT_OF_RESOURCES;\r
1051 }\r
1052\r
1053 NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));\r
1054 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
1055 }\r
1056\r
1057 *NextBusNumber = NextNumber;\r
1058 return EFI_SUCCESS;\r
1059 }\r
1060\r
1061 BusNumberRanges++;\r
1062 }\r
1063\r
1064 return EFI_OUT_OF_RESOURCES;\r
1065}\r
1066\r
1067/**\r
1068 Scan pci bus and assign bus number to the given PCI bus system.\r
1069\r
1070 @param Bridge Bridge device instance.\r
1071 @param StartBusNumber start point.\r
1072 @param SubBusNumber Point to sub bus number.\r
1073 @param PaddedBusRange Customized bus number.\r
1074\r
1075 @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
1076 @retval other Some error occurred when scanning pci bus.\r
1077\r
1078 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
1079\r
1080**/\r
1081EFI_STATUS\r
1082PciScanBus (\r
1083 IN PCI_IO_DEVICE *Bridge,\r
1084 IN UINT8 StartBusNumber,\r
1085 OUT UINT8 *SubBusNumber,\r
1086 OUT UINT8 *PaddedBusRange\r
1087 )\r
1088{\r
1089 EFI_STATUS Status;\r
1090 PCI_TYPE00 Pci;\r
1091 UINT8 Device;\r
1092 UINT8 Func;\r
1093 UINT64 Address;\r
1094 UINT8 SecondBus;\r
1095 UINT8 PaddedSubBus;\r
1096 UINT16 Register;\r
1097 UINTN HpIndex;\r
1098 PCI_IO_DEVICE *PciDevice;\r
1099 EFI_EVENT Event;\r
1100 EFI_HPC_STATE State;\r
1101 UINT64 PciAddress;\r
1102 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
1103 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1104 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *NextDescriptors;\r
1105 UINT16 BusRange;\r
1106 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1107 BOOLEAN BusPadding;\r
1108 UINT32 TempReservedBusNum;\r
1109\r
1110 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1111 SecondBus = 0;\r
1112 Register = 0;\r
1113 State = 0;\r
1114 Attributes = (EFI_HPC_PADDING_ATTRIBUTES)0;\r
1115 BusRange = 0;\r
1116 BusPadding = FALSE;\r
1117 PciDevice = NULL;\r
1118 PciAddress = 0;\r
1119\r
1120 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1121 TempReservedBusNum = 0;\r
1122 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1123 //\r
1124 // Check to see whether a pci device is present\r
1125 //\r
1126 Status = PciDevicePresent (\r
1127 PciRootBridgeIo,\r
1128 &Pci,\r
1129 StartBusNumber,\r
1130 Device,\r
1131 Func\r
1132 );\r
1133\r
1134 if (EFI_ERROR (Status) && (Func == 0)) {\r
1135 //\r
1136 // go to next device if there is no Function 0\r
1137 //\r
1138 break;\r
1139 }\r
1140\r
1141 if (EFI_ERROR (Status)) {\r
1142 continue;\r
1143 }\r
1144\r
1145 //\r
1146 // Get the PCI device information\r
1147 //\r
1148 Status = PciSearchDevice (\r
1149 Bridge,\r
1150 &Pci,\r
1151 StartBusNumber,\r
1152 Device,\r
1153 Func,\r
1154 &PciDevice\r
1155 );\r
1156\r
1157 if (EFI_ERROR (Status)) {\r
1158 continue;\r
1159 }\r
1160\r
1161 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
1162\r
1163 if (!IS_PCI_BRIDGE (&Pci)) {\r
1164 //\r
1165 // PCI bridges will be called later\r
1166 // Here just need for PCI device or PCI to cardbus controller\r
1167 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
1168 //\r
1169 PreprocessController (\r
1170 PciDevice,\r
1171 PciDevice->BusNumber,\r
1172 PciDevice->DeviceNumber,\r
1173 PciDevice->FunctionNumber,\r
1174 EfiPciBeforeChildBusEnumeration\r
1175 );\r
1176 }\r
1177\r
1178 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1179 //\r
1180 // For Pci Hotplug controller devcie only\r
1181 //\r
1182 if (gPciHotPlugInit != NULL) {\r
1183 //\r
1184 // Check if it is a Hotplug PCI controller\r
1185 //\r
1186 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
1187 gPciRootHpcData[HpIndex].Found = TRUE;\r
1188\r
1189 if (!gPciRootHpcData[HpIndex].Initialized) {\r
1190 Status = CreateEventForHpc (HpIndex, &Event);\r
1191\r
1192 ASSERT (!EFI_ERROR (Status));\r
1193\r
1194 Status = gPciHotPlugInit->InitializeRootHpc (\r
1195 gPciHotPlugInit,\r
1196 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1197 PciAddress,\r
1198 Event,\r
1199 &State\r
1200 );\r
1201\r
1202 PreprocessController (\r
1203 PciDevice,\r
1204 PciDevice->BusNumber,\r
1205 PciDevice->DeviceNumber,\r
1206 PciDevice->FunctionNumber,\r
1207 EfiPciBeforeChildBusEnumeration\r
1208 );\r
1209 }\r
1210 }\r
1211 }\r
1212 }\r
1213\r
1214 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1215 //\r
1216 // For PPB\r
1217 //\r
1218 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1219 //\r
1220 // If Hot Plug is supported,\r
1221 // Get the bridge information\r
1222 //\r
1223 BusPadding = FALSE;\r
1224 if (gPciHotPlugInit != NULL) {\r
1225 if (IsPciHotPlugBus (PciDevice)) {\r
1226 //\r
1227 // If it is initialized, get the padded bus range\r
1228 //\r
1229 Status = gPciHotPlugInit->GetResourcePadding (\r
1230 gPciHotPlugInit,\r
1231 PciDevice->DevicePath,\r
1232 PciAddress,\r
1233 &State,\r
1234 (VOID **)&Descriptors,\r
1235 &Attributes\r
1236 );\r
1237\r
1238 if (EFI_ERROR (Status)) {\r
1239 return Status;\r
1240 }\r
1241\r
1242 BusRange = 0;\r
1243 NextDescriptors = Descriptors;\r
1244 Status = PciGetBusRange (\r
1245 &NextDescriptors,\r
1246 NULL,\r
1247 NULL,\r
1248 &BusRange\r
1249 );\r
1250\r
1251 FreePool (Descriptors);\r
1252\r
1253 if (!EFI_ERROR (Status)) {\r
1254 BusPadding = TRUE;\r
1255 } else if (Status != EFI_NOT_FOUND) {\r
1256 //\r
1257 // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.\r
1258 //\r
1259 return Status;\r
1260 }\r
1261 }\r
1262 }\r
1263 }\r
1264\r
1265 Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
1266 if (EFI_ERROR (Status)) {\r
1267 return Status;\r
1268 }\r
1269\r
1270 SecondBus = *SubBusNumber;\r
1271\r
1272 Register = (UINT16)((SecondBus << 8) | (UINT16)StartBusNumber);\r
1273 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
1274\r
1275 Status = PciRootBridgeIo->Pci.Write (\r
1276 PciRootBridgeIo,\r
1277 EfiPciWidthUint16,\r
1278 Address,\r
1279 1,\r
1280 &Register\r
1281 );\r
1282\r
1283 //\r
1284 // If it is PPB, resursively search down this bridge\r
1285 //\r
1286 if (IS_PCI_BRIDGE (&Pci)) {\r
1287 //\r
1288 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1289 // PCI configuration transaction to go through any PPB\r
1290 //\r
1291 Register = PciGetMaxBusNumber (Bridge);\r
1292 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1293 Status = PciRootBridgeIo->Pci.Write (\r
1294 PciRootBridgeIo,\r
1295 EfiPciWidthUint8,\r
1296 Address,\r
1297 1,\r
1298 &Register\r
1299 );\r
1300\r
1301 //\r
1302 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1303 //\r
1304 PreprocessController (\r
1305 PciDevice,\r
1306 PciDevice->BusNumber,\r
1307 PciDevice->DeviceNumber,\r
1308 PciDevice->FunctionNumber,\r
1309 EfiPciBeforeChildBusEnumeration\r
1310 );\r
1311\r
1312 Status = PciScanBus (\r
1313 PciDevice,\r
1314 SecondBus,\r
1315 SubBusNumber,\r
1316 PaddedBusRange\r
1317 );\r
1318 if (EFI_ERROR (Status)) {\r
1319 return Status;\r
1320 }\r
1321 }\r
1322\r
1323 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
1324 //\r
1325 // Ensure the device is enabled and initialized\r
1326 //\r
1327 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1328 ((State & EFI_HPC_STATE_ENABLED) != 0) &&\r
1329 ((State & EFI_HPC_STATE_INITIALIZED) != 0))\r
1330 {\r
1331 *PaddedBusRange = (UINT8)((UINT8)(BusRange) + *PaddedBusRange);\r
1332 } else {\r
1333 //\r
1334 // Reserve the larger one between the actual occupied bus number and padded bus number\r
1335 //\r
1336 Status = PciAllocateBusNumber (PciDevice, SecondBus, (UINT8)(BusRange), &PaddedSubBus);\r
1337 if (EFI_ERROR (Status)) {\r
1338 return Status;\r
1339 }\r
1340\r
1341 *SubBusNumber = MAX (PaddedSubBus, *SubBusNumber);\r
1342 }\r
1343 }\r
1344\r
1345 //\r
1346 // Set the current maximum bus number under the PPB\r
1347 //\r
1348 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1349\r
1350 Status = PciRootBridgeIo->Pci.Write (\r
1351 PciRootBridgeIo,\r
1352 EfiPciWidthUint8,\r
1353 Address,\r
1354 1,\r
1355 SubBusNumber\r
1356 );\r
1357 } else {\r
1358 //\r
1359 // It is device. Check PCI IOV for Bus reservation\r
1360 // Go through each function, just reserve the MAX ReservedBusNum for one device\r
1361 //\r
1362 if (PcdGetBool (PcdSrIovSupport) && (PciDevice->SrIovCapabilityOffset != 0)) {\r
1363 if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
1364 Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8)(PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);\r
1365 if (EFI_ERROR (Status)) {\r
1366 return Status;\r
1367 }\r
1368\r
1369 TempReservedBusNum = PciDevice->ReservedBusNum;\r
1370\r
1371 if (Func == 0) {\r
1372 DEBUG ((DEBUG_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
1373 } else {\r
1374 DEBUG ((DEBUG_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
1375 }\r
1376 }\r
1377 }\r
1378 }\r
1379\r
1380 if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1381 //\r
1382 // Skip sub functions, this is not a multi function device\r
1383 //\r
1384\r
1385 Func = PCI_MAX_FUNC;\r
1386 }\r
1387 }\r
1388 }\r
1389\r
1390 return EFI_SUCCESS;\r
1391}\r
1392\r
1393/**\r
1394 Process Option Rom on the specified root bridge.\r
1395\r
1396 @param Bridge Pci root bridge device instance.\r
1397\r
1398 @retval EFI_SUCCESS Success process.\r
1399 @retval other Some error occurred when processing Option Rom on the root bridge.\r
1400\r
1401**/\r
1402EFI_STATUS\r
1403PciRootBridgeP2CProcess (\r
1404 IN PCI_IO_DEVICE *Bridge\r
1405 )\r
1406{\r
1407 LIST_ENTRY *CurrentLink;\r
1408 PCI_IO_DEVICE *Temp;\r
1409 EFI_HPC_STATE State;\r
1410 UINT64 PciAddress;\r
1411 EFI_STATUS Status;\r
1412\r
1413 CurrentLink = Bridge->ChildList.ForwardLink;\r
1414\r
1415 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
1416 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1417\r
1418 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1419 if ((gPciHotPlugInit != NULL) && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1420 //\r
1421 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1422 //\r
1423 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1424 EFI_PROGRESS_CODE,\r
1425 EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,\r
1426 Temp->DevicePath\r
1427 );\r
1428\r
1429 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1430 Status = gPciHotPlugInit->InitializeRootHpc (\r
1431 gPciHotPlugInit,\r
1432 Temp->DevicePath,\r
1433 PciAddress,\r
1434 NULL,\r
1435 &State\r
1436 );\r
1437\r
1438 if (!EFI_ERROR (Status)) {\r
1439 Status = PciBridgeEnumerator (Temp);\r
1440\r
1441 if (EFI_ERROR (Status)) {\r
1442 return Status;\r
1443 }\r
1444 }\r
1445\r
1446 CurrentLink = CurrentLink->ForwardLink;\r
1447 continue;\r
1448 }\r
1449 }\r
1450\r
1451 if (!IsListEmpty (&Temp->ChildList)) {\r
1452 Status = PciRootBridgeP2CProcess (Temp);\r
1453 }\r
1454\r
1455 CurrentLink = CurrentLink->ForwardLink;\r
1456 }\r
1457\r
1458 return EFI_SUCCESS;\r
1459}\r
1460\r
1461/**\r
1462 Process Option Rom on the specified host bridge.\r
1463\r
1464 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
1465\r
1466 @retval EFI_SUCCESS Success process.\r
1467 @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
1468 @retval other Some error occurred when processing Option Rom on the host bridge.\r
1469\r
1470**/\r
1471EFI_STATUS\r
1472PciHostBridgeP2CProcess (\r
1473 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1474 )\r
1475{\r
1476 EFI_HANDLE RootBridgeHandle;\r
1477 PCI_IO_DEVICE *RootBridgeDev;\r
1478 EFI_STATUS Status;\r
1479\r
1480 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1481 return EFI_SUCCESS;\r
1482 }\r
1483\r
1484 RootBridgeHandle = NULL;\r
1485\r
1486 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1487 //\r
1488 // Get RootBridg Device by handle\r
1489 //\r
1490 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1491\r
1492 if (RootBridgeDev == NULL) {\r
1493 return EFI_NOT_FOUND;\r
1494 }\r
1495\r
1496 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1497 if (EFI_ERROR (Status)) {\r
1498 return Status;\r
1499 }\r
1500 }\r
1501\r
1502 return EFI_SUCCESS;\r
1503}\r
1504\r
1505/**\r
1506 This function is used to enumerate the entire host bridge\r
1507 in a given platform.\r
1508\r
1509 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
1510\r
1511 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1512 @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
1513 @retval other Some error occurred when enumerating the host bridge.\r
1514\r
1515**/\r
1516EFI_STATUS\r
1517PciHostBridgeEnumerator (\r
1518 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1519 )\r
1520{\r
1521 EFI_HANDLE RootBridgeHandle;\r
1522 PCI_IO_DEVICE *RootBridgeDev;\r
1523 EFI_STATUS Status;\r
1524 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1525 UINT16 MinBus;\r
1526 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1527 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
1528 UINT8 StartBusNumber;\r
1529 LIST_ENTRY RootBridgeList;\r
1530 LIST_ENTRY *Link;\r
1531\r
1532 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1533 InitializeHotPlugSupport ();\r
1534 }\r
1535\r
1536 InitializeListHead (&RootBridgeList);\r
1537\r
1538 //\r
1539 // Notify the bus allocation phase is about to start\r
1540 //\r
1541 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1542\r
1543 if (EFI_ERROR (Status)) {\r
1544 return Status;\r
1545 }\r
1546\r
1547 DEBUG ((DEBUG_INFO, "PCI Bus First Scanning\n"));\r
1548 RootBridgeHandle = NULL;\r
1549 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1550 //\r
1551 // if a root bridge instance is found, create root bridge device for it\r
1552 //\r
1553\r
1554 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1555\r
1556 if (RootBridgeDev == NULL) {\r
1557 return EFI_OUT_OF_RESOURCES;\r
1558 }\r
1559\r
1560 //\r
1561 // Enumerate all the buses under this root bridge\r
1562 //\r
1563 Status = PciRootBridgeEnumerator (\r
1564 PciResAlloc,\r
1565 RootBridgeDev\r
1566 );\r
1567\r
1568 if ((gPciHotPlugInit != NULL) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1569 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1570 } else {\r
1571 DestroyRootBridge (RootBridgeDev);\r
1572 }\r
1573\r
1574 if (EFI_ERROR (Status)) {\r
1575 return Status;\r
1576 }\r
1577 }\r
1578\r
1579 //\r
1580 // Notify the bus allocation phase is finished for the first time\r
1581 //\r
1582 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1583\r
1584 if ((gPciHotPlugInit != NULL) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1585 //\r
1586 // Reset all assigned PCI bus number in all PPB\r
1587 //\r
1588 RootBridgeHandle = NULL;\r
1589 Link = GetFirstNode (&RootBridgeList);\r
1590 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1591 (!IsNull (&RootBridgeList, Link)))\r
1592 {\r
1593 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1594 //\r
1595 // Get the Bus information\r
1596 //\r
1597 Status = PciResAlloc->StartBusEnumeration (\r
1598 PciResAlloc,\r
1599 RootBridgeHandle,\r
1600 (VOID **)&Configuration\r
1601 );\r
1602 if (EFI_ERROR (Status)) {\r
1603 return Status;\r
1604 }\r
1605\r
1606 //\r
1607 // Get the bus number to start with\r
1608 //\r
1609 StartBusNumber = (UINT8)(Configuration->AddrRangeMin);\r
1610\r
1611 ResetAllPpbBusNumber (\r
1612 RootBridgeDev,\r
1613 StartBusNumber\r
1614 );\r
1615\r
1616 FreePool (Configuration);\r
1617 Link = RemoveEntryList (Link);\r
1618 DestroyRootBridge (RootBridgeDev);\r
1619 }\r
1620\r
1621 //\r
1622 // Wait for all HPC initialized\r
1623 //\r
1624 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1625\r
1626 if (EFI_ERROR (Status)) {\r
1627 DEBUG ((DEBUG_ERROR, "Some root HPC failed to initialize\n"));\r
1628 return Status;\r
1629 }\r
1630\r
1631 //\r
1632 // Notify the bus allocation phase is about to start for the 2nd time\r
1633 //\r
1634 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1635\r
1636 if (EFI_ERROR (Status)) {\r
1637 return Status;\r
1638 }\r
1639\r
1640 DEBUG ((DEBUG_INFO, "PCI Bus Second Scanning\n"));\r
1641 RootBridgeHandle = NULL;\r
1642 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1643 //\r
1644 // if a root bridge instance is found, create root bridge device for it\r
1645 //\r
1646 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1647\r
1648 if (RootBridgeDev == NULL) {\r
1649 return EFI_OUT_OF_RESOURCES;\r
1650 }\r
1651\r
1652 //\r
1653 // Enumerate all the buses under this root bridge\r
1654 //\r
1655 Status = PciRootBridgeEnumerator (\r
1656 PciResAlloc,\r
1657 RootBridgeDev\r
1658 );\r
1659\r
1660 DestroyRootBridge (RootBridgeDev);\r
1661 if (EFI_ERROR (Status)) {\r
1662 return Status;\r
1663 }\r
1664 }\r
1665\r
1666 //\r
1667 // Notify the bus allocation phase is to end for the 2nd time\r
1668 //\r
1669 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1670 }\r
1671\r
1672 //\r
1673 // Notify the resource allocation phase is to start\r
1674 //\r
1675 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1676\r
1677 if (EFI_ERROR (Status)) {\r
1678 return Status;\r
1679 }\r
1680\r
1681 RootBridgeHandle = NULL;\r
1682 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1683 //\r
1684 // if a root bridge instance is found, create root bridge device for it\r
1685 //\r
1686 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1687\r
1688 if (RootBridgeDev == NULL) {\r
1689 return EFI_OUT_OF_RESOURCES;\r
1690 }\r
1691\r
1692 Status = StartManagingRootBridge (RootBridgeDev);\r
1693\r
1694 if (EFI_ERROR (Status)) {\r
1695 return Status;\r
1696 }\r
1697\r
1698 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1699 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **)&Descriptors);\r
1700\r
1701 if (EFI_ERROR (Status)) {\r
1702 return Status;\r
1703 }\r
1704\r
1705 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1706\r
1707 if (EFI_ERROR (Status)) {\r
1708 return Status;\r
1709 }\r
1710\r
1711 //\r
1712 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1713 // protocol\r
1714 //\r
1715 DetermineRootBridgeAttributes (\r
1716 PciResAlloc,\r
1717 RootBridgeDev\r
1718 );\r
1719\r
1720 //\r
1721 // Collect all the resource information under this root bridge\r
1722 // A database that records all the information about pci device subject to this\r
1723 // root bridge will then be created\r
1724 //\r
1725 Status = PciPciDeviceInfoCollector (\r
1726 RootBridgeDev,\r
1727 (UINT8)MinBus\r
1728 );\r
1729\r
1730 if (EFI_ERROR (Status)) {\r
1731 return Status;\r
1732 }\r
1733\r
1734 InsertRootBridge (RootBridgeDev);\r
1735\r
1736 //\r
1737 // Record the hostbridge handle\r
1738 //\r
1739 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1740 }\r
1741\r
1742 return EFI_SUCCESS;\r
1743}\r
1744\r
1745/**\r
1746 This function is used to program the Resizable BAR Register.\r
1747\r
1748 @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
1749 @param ResizableBarOp PciResizableBarMax: Set BAR to max size\r
1750 PciResizableBarMin: set BAR to min size.\r
1751\r
1752 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1753 @retval other Some error occurred when enumerating the host bridge.\r
1754\r
1755**/\r
1756EFI_STATUS\r
1757PciProgramResizableBar (\r
1758 IN PCI_IO_DEVICE *PciIoDevice,\r
1759 IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp\r
1760 )\r
1761{\r
1762 EFI_PCI_IO_PROTOCOL *PciIo;\r
1763 UINT64 Capabilities;\r
1764 UINT32 Index;\r
1765 UINT32 Offset;\r
1766 INTN Bit;\r
1767 UINTN ResizableBarNumber;\r
1768 EFI_STATUS Status;\r
1769 PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Entries[PCI_MAX_BAR];\r
1770\r
1771 ASSERT (PciIoDevice->ResizableBarOffset != 0);\r
1772\r
1773 DEBUG ((\r
1774 DEBUG_INFO,\r
1775 " Programs Resizable BAR register, offset: 0x%08x, number: %d\n",\r
1776 PciIoDevice->ResizableBarOffset,\r
1777 PciIoDevice->ResizableBarNumber\r
1778 ));\r
1779\r
1780 ResizableBarNumber = MIN (PciIoDevice->ResizableBarNumber, PCI_MAX_BAR);\r
1781 PciIo = &PciIoDevice->PciIo;\r
1782 Status = PciIo->Pci.Read (\r
1783 PciIo,\r
1784 EfiPciIoWidthUint8,\r
1785 PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER),\r
1786 sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,\r
1787 (VOID *)(&Entries)\r
1788 );\r
1789 ASSERT_EFI_ERROR (Status);\r
1790\r
1791 for (Index = 0; Index < ResizableBarNumber; Index++) {\r
1792 //\r
1793 // When the bit of Capabilities Set, indicates that the Function supports\r
1794 // operating with the BAR sized to (2^Bit) MB.\r
1795 // Example:\r
1796 // Bit 0 is set: supports operating with the BAR sized to 1 MB\r
1797 // Bit 1 is set: supports operating with the BAR sized to 2 MB\r
1798 // Bit n is set: supports operating with the BAR sized to (2^n) MB\r
1799 //\r
1800 Capabilities = LShiftU64 (Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28)\r
1801 | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability;\r
1802\r
1803 if (ResizableBarOp == PciResizableBarMax) {\r
1804 Bit = HighBitSet64 (Capabilities);\r
1805 } else {\r
1806 ASSERT (ResizableBarOp == PciResizableBarMin);\r
1807 Bit = LowBitSet64 (Capabilities);\r
1808 }\r
1809\r
1810 ASSERT (Bit >= 0);\r
1811\r
1812 Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)\r
1813 + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY)\r
1814 + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, ResizableBarControl);\r
1815\r
1816 Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32)Bit;\r
1817 DEBUG ((\r
1818 DEBUG_INFO,\r
1819 " Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n",\r
1820 OFFSET_OF (PCI_TYPE00, Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]),\r
1821 Capabilities,\r
1822 LShiftU64 (SIZE_1MB, Bit)\r
1823 ));\r
1824 PciIo->Pci.Write (\r
1825 PciIo,\r
1826 EfiPciIoWidthUint32,\r
1827 Offset,\r
1828 1,\r
1829 &Entries[Index].ResizableBarControl.Uint32\r
1830 );\r
1831 }\r
1832\r
1833 return EFI_SUCCESS;\r
1834}\r