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