]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
Update some progress codes name per the PI Spec, 1.2 Errata B. This was one incompati...
[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
d4048391 4Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
9060e3ec 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "PciBus.h"\r
16\r
17\r
18/**\r
19 Retrieve the PCI Card device BAR information via PciIo interface.\r
20\r
21 @param PciIoDevice PCI Card device instance.\r
22\r
23**/\r
24VOID\r
25GetBackPcCardBar (\r
26 IN PCI_IO_DEVICE *PciIoDevice\r
27 )\r
28{\r
29 UINT32 Address;\r
30\r
31 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
32 return;\r
33 }\r
34\r
35 //\r
36 // Read PciBar information from the bar register\r
37 //\r
38 if (!gFullEnumeration) {\r
39 Address = 0;\r
40 PciIoDevice->PciIo.Pci.Read (\r
41 &(PciIoDevice->PciIo),\r
42 EfiPciIoWidthUint32,\r
43 PCI_CARD_MEMORY_BASE_0,\r
44 1,\r
45 &Address\r
46 );\r
47\r
48 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);\r
49 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;\r
50 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;\r
51\r
52 Address = 0;\r
53 PciIoDevice->PciIo.Pci.Read (\r
54 &(PciIoDevice->PciIo),\r
55 EfiPciIoWidthUint32,\r
56 PCI_CARD_MEMORY_BASE_1,\r
57 1,\r
58 &Address\r
59 );\r
60 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);\r
61 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;\r
62 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;\r
63\r
64 Address = 0;\r
65 PciIoDevice->PciIo.Pci.Read (\r
66 &(PciIoDevice->PciIo),\r
67 EfiPciIoWidthUint32,\r
68 PCI_CARD_IO_BASE_0_LOWER,\r
69 1,\r
70 &Address\r
71 );\r
72 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);\r
73 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;\r
74 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;\r
75\r
76 Address = 0;\r
77 PciIoDevice->PciIo.Pci.Read (\r
78 &(PciIoDevice->PciIo),\r
79 EfiPciIoWidthUint32,\r
80 PCI_CARD_IO_BASE_1_LOWER,\r
81 1,\r
82 &Address\r
83 );\r
84 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);\r
85 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;\r
86 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;\r
87\r
88 }\r
89\r
90 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
91 GetResourcePaddingForHpb (PciIoDevice);\r
92 }\r
93}\r
94\r
95/**\r
96 Remove rejected pci device from specific root bridge\r
97 handle.\r
98\r
99 @param RootBridgeHandle Specific parent root bridge handle.\r
100 @param Bridge Bridge device instance.\r
101\r
102**/\r
103VOID\r
104RemoveRejectedPciDevices (\r
105 IN EFI_HANDLE RootBridgeHandle,\r
106 IN PCI_IO_DEVICE *Bridge\r
107 )\r
108{\r
109 PCI_IO_DEVICE *Temp;\r
110 LIST_ENTRY *CurrentLink;\r
111 LIST_ENTRY *LastLink;\r
112\r
113 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
114 return;\r
115 }\r
116\r
117 CurrentLink = Bridge->ChildList.ForwardLink;\r
118\r
119 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
120\r
121 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
122\r
123 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
124 //\r
125 // Remove rejected devices recusively\r
126 //\r
127 RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
128 } else {\r
129 //\r
130 // Skip rejection for all PPBs, while detect rejection for others\r
131 //\r
132 if (IsPciDeviceRejected (Temp)) {\r
133\r
134 //\r
135 // For P2C, remove all devices on it\r
136 //\r
137 if (!IsListEmpty (&Temp->ChildList)) {\r
138 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
139 }\r
140\r
141 //\r
142 // Finally remove itself\r
143 //\r
144 LastLink = CurrentLink->BackLink;\r
145 RemoveEntryList (CurrentLink);\r
146 FreePciDevice (Temp);\r
147\r
148 CurrentLink = LastLink;\r
149 }\r
150 }\r
151\r
152 CurrentLink = CurrentLink->ForwardLink;\r
153 }\r
154}\r
155\r
156/**\r
157 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
158\r
159 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
160\r
161 @retval EFI_SUCCESS Successfully finished resource allocation.\r
162 @retval EFI_NOT_FOUND Cannot get root bridge instance.\r
163 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.\r
164 @retval other Some error occurred when allocating resources for the PCI Host Bridge.\r
165\r
166 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
167\r
168**/\r
169EFI_STATUS\r
170PciHostBridgeResourceAllocator (\r
171 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
172 )\r
173{\r
174 PCI_IO_DEVICE *RootBridgeDev;\r
175 EFI_HANDLE RootBridgeHandle;\r
176 VOID *AcpiConfig;\r
177 EFI_STATUS Status;\r
178 UINT64 IoBase;\r
179 UINT64 Mem32Base;\r
180 UINT64 PMem32Base;\r
181 UINT64 Mem64Base;\r
182 UINT64 PMem64Base;\r
183 UINT64 IoResStatus;\r
184 UINT64 Mem32ResStatus;\r
185 UINT64 PMem32ResStatus;\r
186 UINT64 Mem64ResStatus;\r
187 UINT64 PMem64ResStatus;\r
188 UINT64 MaxOptionRomSize;\r
189 PCI_RESOURCE_NODE *IoBridge;\r
190 PCI_RESOURCE_NODE *Mem32Bridge;\r
191 PCI_RESOURCE_NODE *PMem32Bridge;\r
192 PCI_RESOURCE_NODE *Mem64Bridge;\r
193 PCI_RESOURCE_NODE *PMem64Bridge;\r
194 PCI_RESOURCE_NODE IoPool;\r
195 PCI_RESOURCE_NODE Mem32Pool;\r
196 PCI_RESOURCE_NODE PMem32Pool;\r
197 PCI_RESOURCE_NODE Mem64Pool;\r
198 PCI_RESOURCE_NODE PMem64Pool;\r
199 BOOLEAN ReAllocate;\r
200 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;\r
201 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
202\r
203 //\r
204 // Reallocate flag\r
205 //\r
206 ReAllocate = FALSE;\r
207\r
208 //\r
209 // It may try several times if the resource allocation fails\r
210 //\r
211 while (TRUE) {\r
212 //\r
213 // Initialize resource pool\r
214 //\r
215 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
216 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
217 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
218 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
219 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
220\r
221 RootBridgeDev = NULL;\r
222 RootBridgeHandle = 0;\r
223\r
224 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
225 //\r
226 // Get Root Bridge Device by handle\r
227 //\r
228 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
229\r
230 if (RootBridgeDev == NULL) {\r
231 return EFI_NOT_FOUND;\r
232 }\r
233\r
234 //\r
235 // Create the entire system resource map from the information collected by\r
236 // enumerator. Several resource tree was created\r
237 //\r
238\r
1ef26783 239 //\r
240 // If non-stardard PCI Bridge I/O window alignment is supported,\r
241 // set I/O aligment to minimum possible alignment for root bridge.\r
242 //\r
9060e3ec 243 IoBridge = CreateResourceNode (\r
244 RootBridgeDev,\r
245 0,\r
1ef26783 246 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF,\r
9060e3ec 247 0,\r
248 PciBarTypeIo16,\r
249 PciResUsageTypical\r
250 );\r
251\r
252 Mem32Bridge = CreateResourceNode (\r
253 RootBridgeDev,\r
254 0,\r
255 0xFFFFF,\r
256 0,\r
257 PciBarTypeMem32,\r
258 PciResUsageTypical\r
259 );\r
260\r
261 PMem32Bridge = CreateResourceNode (\r
262 RootBridgeDev,\r
263 0,\r
264 0xFFFFF,\r
265 0,\r
266 PciBarTypePMem32,\r
267 PciResUsageTypical\r
268 );\r
269\r
270 Mem64Bridge = CreateResourceNode (\r
271 RootBridgeDev,\r
272 0,\r
273 0xFFFFF,\r
274 0,\r
275 PciBarTypeMem64,\r
276 PciResUsageTypical\r
277 );\r
278\r
279 PMem64Bridge = CreateResourceNode (\r
280 RootBridgeDev,\r
281 0,\r
282 0xFFFFF,\r
283 0,\r
284 PciBarTypePMem64,\r
285 PciResUsageTypical\r
286 );\r
287\r
288 //\r
289 // Create resourcemap by going through all the devices subject to this root bridge\r
290 //\r
291 CreateResourceMap (\r
292 RootBridgeDev,\r
293 IoBridge,\r
294 Mem32Bridge,\r
295 PMem32Bridge,\r
296 Mem64Bridge,\r
297 PMem64Bridge\r
298 );\r
299\r
300 //\r
301 // Get the max ROM size that the root bridge can process\r
302 //\r
303 RootBridgeDev->RomSize = Mem32Bridge->Length;\r
304\r
305 //\r
306 // Skip to enlarge the resource request during realloction\r
307 //\r
308 if (!ReAllocate) {\r
309 //\r
310 // Get Max Option Rom size for current root bridge\r
311 //\r
312 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
313\r
314 //\r
315 // Enlarger the mem32 resource to accomdate the option rom\r
316 // if the mem32 resource is not enough to hold the rom\r
317 //\r
318 if (MaxOptionRomSize > Mem32Bridge->Length) {\r
319\r
320 Mem32Bridge->Length = MaxOptionRomSize;\r
321 RootBridgeDev->RomSize = MaxOptionRomSize;\r
322\r
323 //\r
324 // Alignment should be adjusted as well\r
325 //\r
326 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
327 Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
328 }\r
329 }\r
330 }\r
331\r
332 //\r
333 // Based on the all the resource tree, contruct ACPI resource node to\r
334 // submit the resource aperture to pci host bridge protocol\r
335 //\r
336 Status = ConstructAcpiResourceRequestor (\r
337 RootBridgeDev,\r
338 IoBridge,\r
339 Mem32Bridge,\r
340 PMem32Bridge,\r
341 Mem64Bridge,\r
342 PMem64Bridge,\r
343 &AcpiConfig\r
344 );\r
345\r
346 //\r
347 // Insert these resource nodes into the database\r
348 //\r
349 InsertResourceNode (&IoPool, IoBridge);\r
350 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
351 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
352 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
353 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
354\r
355 if (Status == EFI_SUCCESS) {\r
356 //\r
357 // Submit the resource requirement\r
358 //\r
359 Status = PciResAlloc->SubmitResources (\r
360 PciResAlloc,\r
361 RootBridgeDev->Handle,\r
362 AcpiConfig\r
363 );\r
364 }\r
365\r
366 //\r
367 // Free acpi resource node\r
368 //\r
369 if (AcpiConfig != NULL) {\r
370 FreePool (AcpiConfig);\r
371 }\r
372\r
373 if (EFI_ERROR (Status)) {\r
374 //\r
375 // Destroy all the resource tree\r
376 //\r
377 DestroyResourceTree (&IoPool);\r
378 DestroyResourceTree (&Mem32Pool);\r
379 DestroyResourceTree (&PMem32Pool);\r
380 DestroyResourceTree (&Mem64Pool);\r
381 DestroyResourceTree (&PMem64Pool);\r
382 return Status;\r
383 }\r
384 }\r
385 //\r
386 // End while, at least one Root Bridge should be found.\r
387 //\r
388 ASSERT (RootBridgeDev != NULL);\r
389\r
390 //\r
391 // Notify platform to start to program the resource\r
392 //\r
393 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
394 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
395 //\r
396 // If Hot Plug is not supported\r
397 //\r
398 if (EFI_ERROR (Status)) {\r
399 //\r
400 // Allocation failed, then return\r
401 //\r
402 return EFI_OUT_OF_RESOURCES;\r
403 }\r
404 //\r
405 // Allocation succeed.\r
406 // Get host bridge handle for status report, and then skip the main while\r
407 //\r
408 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
409\r
410 break;\r
411\r
412 } else {\r
413 //\r
414 // If Hot Plug is supported\r
415 //\r
416 if (!EFI_ERROR (Status)) {\r
417 //\r
418 // Allocation succeed, then continue the following\r
419 //\r
420 break;\r
421 }\r
422\r
423 //\r
424 // If the resource allocation is unsuccessful, free resources on bridge\r
425 //\r
426\r
427 RootBridgeDev = NULL;\r
428 RootBridgeHandle = 0;\r
429\r
430 IoResStatus = EFI_RESOURCE_SATISFIED;\r
431 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
432 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
433 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
434 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
435\r
436 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
437 //\r
438 // Get RootBridg Device by handle\r
439 //\r
440 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
441 if (RootBridgeDev == NULL) {\r
442 return EFI_NOT_FOUND;\r
443 }\r
444\r
445 //\r
446 // Get host bridge handle for status report\r
447 //\r
448 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
449\r
450 //\r
451 // Get acpi resource node for all the resource types\r
452 //\r
453 AcpiConfig = NULL;\r
454\r
455 Status = PciResAlloc->GetProposedResources (\r
456 PciResAlloc,\r
457 RootBridgeDev->Handle,\r
458 &AcpiConfig\r
459 );\r
460\r
461 if (EFI_ERROR (Status)) {\r
462 return Status;\r
463 }\r
464\r
465 if (AcpiConfig != NULL) {\r
466 //\r
467 // Adjust resource allocation policy for each RB\r
468 //\r
469 GetResourceAllocationStatus (\r
470 AcpiConfig,\r
471 &IoResStatus,\r
472 &Mem32ResStatus,\r
473 &PMem32ResStatus,\r
474 &Mem64ResStatus,\r
475 &PMem64ResStatus\r
476 );\r
477 FreePool (AcpiConfig);\r
478 }\r
479 }\r
480 //\r
481 // End while\r
482 //\r
483\r
484 //\r
485 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
486 //\r
487 //\r
488 // It is very difficult to follow the spec here\r
489 // Device path , Bar index can not be get here\r
490 //\r
491 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
492\r
493 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
494 EFI_PROGRESS_CODE,\r
495 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
496 (VOID *) &AllocFailExtendedData,\r
497 sizeof (AllocFailExtendedData)\r
498 );\r
499\r
500 Status = PciHostBridgeAdjustAllocation (\r
501 &IoPool,\r
502 &Mem32Pool,\r
503 &PMem32Pool,\r
504 &Mem64Pool,\r
505 &PMem64Pool,\r
506 IoResStatus,\r
507 Mem32ResStatus,\r
508 PMem32ResStatus,\r
509 Mem64ResStatus,\r
510 PMem64ResStatus\r
511 );\r
512\r
513 //\r
514 // Destroy all the resource tree\r
515 //\r
516 DestroyResourceTree (&IoPool);\r
517 DestroyResourceTree (&Mem32Pool);\r
518 DestroyResourceTree (&PMem32Pool);\r
519 DestroyResourceTree (&Mem64Pool);\r
520 DestroyResourceTree (&PMem64Pool);\r
521\r
522 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
523\r
524 if (EFI_ERROR (Status)) {\r
525 return Status;\r
526 }\r
527\r
528 ReAllocate = TRUE;\r
529 }\r
530 }\r
531 //\r
532 // End main while\r
533 //\r
534\r
535 //\r
536 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
537 //\r
538 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
539 EFI_PROGRESS_CODE,\r
540 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,\r
541 (VOID *) &HandleExtendedData,\r
542 sizeof (HandleExtendedData)\r
543 );\r
544\r
545 //\r
546 // Notify pci bus driver starts to program the resource\r
547 //\r
548 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
549\r
550 RootBridgeDev = NULL;\r
551\r
552 RootBridgeHandle = 0;\r
553\r
554 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
555 //\r
556 // Get RootBridg Device by handle\r
557 //\r
558 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
559\r
560 if (RootBridgeDev == NULL) {\r
561 return EFI_NOT_FOUND;\r
562 }\r
563\r
564 //\r
565 // Get acpi resource node for all the resource types\r
566 //\r
567 AcpiConfig = NULL;\r
568 Status = PciResAlloc->GetProposedResources (\r
569 PciResAlloc,\r
570 RootBridgeDev->Handle,\r
571 &AcpiConfig\r
572 );\r
573\r
574 if (EFI_ERROR (Status)) {\r
575 return Status;\r
576 }\r
577\r
578 //\r
579 // Get the resource base by interpreting acpi resource node\r
580 //\r
581 //\r
582 GetResourceBase (\r
583 AcpiConfig,\r
584 &IoBase,\r
585 &Mem32Base,\r
586 &PMem32Base,\r
587 &Mem64Base,\r
588 &PMem64Base\r
589 );\r
590\r
591 //\r
592 // Process option rom for this root bridge\r
593 //\r
594 ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
595\r
596 //\r
597 // Create the entire system resource map from the information collected by\r
598 // enumerator. Several resource tree was created\r
599 //\r
600 GetResourceMap (\r
601 RootBridgeDev,\r
602 &IoBridge,\r
603 &Mem32Bridge,\r
604 &PMem32Bridge,\r
605 &Mem64Bridge,\r
606 &PMem64Bridge,\r
607 &IoPool,\r
608 &Mem32Pool,\r
609 &PMem32Pool,\r
610 &Mem64Pool,\r
611 &PMem64Pool\r
612 );\r
613\r
614 //\r
615 // Program IO resources\r
616 //\r
617 ProgramResource (\r
618 IoBase,\r
619 IoBridge\r
620 );\r
621\r
622 //\r
623 // Program Mem32 resources\r
624 //\r
625 ProgramResource (\r
626 Mem32Base,\r
627 Mem32Bridge\r
628 );\r
629\r
630 //\r
631 // Program PMem32 resources\r
632 //\r
633 ProgramResource (\r
634 PMem32Base,\r
635 PMem32Bridge\r
636 );\r
637\r
638 //\r
639 // Program Mem64 resources\r
640 //\r
641 ProgramResource (\r
642 Mem64Base,\r
643 Mem64Bridge\r
644 );\r
645\r
646 //\r
647 // Program PMem64 resources\r
648 //\r
649 ProgramResource (\r
650 PMem64Base,\r
651 PMem64Bridge\r
652 );\r
653\r
654 FreePool (AcpiConfig);\r
655 }\r
656\r
657 //\r
658 // Destroy all the resource tree\r
659 //\r
660 DestroyResourceTree (&IoPool);\r
661 DestroyResourceTree (&Mem32Pool);\r
662 DestroyResourceTree (&PMem32Pool);\r
663 DestroyResourceTree (&Mem64Pool);\r
664 DestroyResourceTree (&PMem64Pool);\r
665\r
666 //\r
667 // Notify the resource allocation phase is to end\r
668 //\r
669 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
670\r
671 return EFI_SUCCESS;\r
672}\r
673\r
674/**\r
675 Scan pci bus and assign bus number to the given PCI bus system.\r
676\r
677 @param Bridge Bridge device instance.\r
678 @param StartBusNumber start point.\r
679 @param SubBusNumber Point to sub bus number.\r
680 @param PaddedBusRange Customized bus number.\r
681\r
682 @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
683 @retval other Some error occurred when scanning pci bus.\r
684\r
685 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
686\r
687**/\r
688EFI_STATUS\r
689PciScanBus (\r
690 IN PCI_IO_DEVICE *Bridge,\r
691 IN UINT8 StartBusNumber,\r
692 OUT UINT8 *SubBusNumber,\r
693 OUT UINT8 *PaddedBusRange\r
694 )\r
695{\r
696 EFI_STATUS Status;\r
697 PCI_TYPE00 Pci;\r
698 UINT8 Device;\r
699 UINT8 Func;\r
700 UINT64 Address;\r
701 UINTN SecondBus;\r
702 UINT16 Register;\r
703 UINTN HpIndex;\r
704 PCI_IO_DEVICE *PciDevice;\r
705 EFI_EVENT Event;\r
706 EFI_HPC_STATE State;\r
707 UINT64 PciAddress;\r
708 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
709 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
710 UINT16 BusRange;\r
711 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
712 BOOLEAN BusPadding;\r
713 UINT32 TempReservedBusNum;\r
714\r
715 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
716 SecondBus = 0;\r
717 Register = 0;\r
718 State = 0;\r
719 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
720 BusRange = 0;\r
721 BusPadding = FALSE;\r
722 PciDevice = NULL;\r
723 PciAddress = 0;\r
724\r
725 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
726 TempReservedBusNum = 0;\r
727 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
728\r
729 //\r
730 // Check to see whether a pci device is present\r
731 //\r
732 Status = PciDevicePresent (\r
733 PciRootBridgeIo,\r
734 &Pci,\r
735 StartBusNumber,\r
736 Device,\r
737 Func\r
738 );\r
739\r
740 if (EFI_ERROR (Status)) {\r
9060e3ec 741 continue;\r
742 }\r
743\r
744 DEBUG((EFI_D_INFO, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));\r
745\r
d4048391 746 //\r
747 // Get the PCI device information\r
748 //\r
749 Status = PciSearchDevice (\r
750 Bridge,\r
751 &Pci,\r
752 StartBusNumber,\r
753 Device,\r
754 Func,\r
755 &PciDevice\r
756 );\r
9060e3ec 757\r
d4048391 758 ASSERT (!EFI_ERROR (Status));\r
9060e3ec 759\r
d4048391 760 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
9060e3ec 761\r
d4048391 762 if (!IS_PCI_BRIDGE (&Pci)) {\r
763 //\r
764 // PCI bridges will be called later\r
765 // Here just need for PCI device or PCI to cardbus controller\r
766 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
767 //\r
768 PreprocessController (\r
769 PciDevice,\r
770 PciDevice->BusNumber,\r
771 PciDevice->DeviceNumber,\r
772 PciDevice->FunctionNumber,\r
773 EfiPciBeforeChildBusEnumeration\r
774 );\r
775 }\r
9060e3ec 776\r
d4048391 777 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 778 //\r
779 // For Pci Hotplug controller devcie only\r
780 //\r
781 if (gPciHotPlugInit != NULL) {\r
782 //\r
783 // Check if it is a Hotplug PCI controller\r
784 //\r
785 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
55565b08 786 gPciRootHpcData[HpIndex].Found = TRUE;\r
9060e3ec 787\r
788 if (!gPciRootHpcData[HpIndex].Initialized) {\r
789\r
790 Status = CreateEventForHpc (HpIndex, &Event);\r
791\r
792 ASSERT (!EFI_ERROR (Status));\r
793\r
794 Status = gPciHotPlugInit->InitializeRootHpc (\r
795 gPciHotPlugInit,\r
796 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
797 PciAddress,\r
798 Event,\r
799 &State\r
800 );\r
801\r
802 PreprocessController (\r
803 PciDevice,\r
804 PciDevice->BusNumber,\r
805 PciDevice->DeviceNumber,\r
806 PciDevice->FunctionNumber,\r
807 EfiPciBeforeChildBusEnumeration\r
808 );\r
809 }\r
810 }\r
811 }\r
812 }\r
813\r
814 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
815 //\r
816 // For PPB\r
817 //\r
818 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
819 //\r
820 // If Hot Plug is not supported,\r
821 // get the bridge information\r
822 //\r
823 Status = PciSearchDevice (\r
824 Bridge,\r
825 &Pci,\r
826 StartBusNumber,\r
827 Device,\r
828 Func,\r
829 &PciDevice\r
830 );\r
831\r
832 if (EFI_ERROR (Status)) {\r
833 return Status;\r
834 }\r
835 } else {\r
836 //\r
837 // If Hot Plug is supported,\r
838 // Get the bridge information\r
839 //\r
840 BusPadding = FALSE;\r
841 if (gPciHotPlugInit != NULL) {\r
842\r
843 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
844\r
845 //\r
846 // If it is initialized, get the padded bus range\r
847 //\r
848 Status = gPciHotPlugInit->GetResourcePadding (\r
849 gPciHotPlugInit,\r
850 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
851 PciAddress,\r
852 &State,\r
853 (VOID **) &Descriptors,\r
854 &Attributes\r
855 );\r
856\r
857 if (EFI_ERROR (Status)) {\r
858 return Status;\r
859 }\r
860\r
861 BusRange = 0;\r
862 Status = PciGetBusRange (\r
863 &Descriptors,\r
864 NULL,\r
865 NULL,\r
866 &BusRange\r
867 );\r
868\r
869 FreePool (Descriptors);\r
870\r
871 if (EFI_ERROR (Status)) {\r
872 return Status;\r
873 }\r
874\r
875 BusPadding = TRUE;\r
876 }\r
877 }\r
878 }\r
879\r
880 //\r
881 // Add feature to support customized secondary bus number\r
882 //\r
883 if (*SubBusNumber == 0) {\r
884 *SubBusNumber = *PaddedBusRange;\r
885 *PaddedBusRange = 0;\r
886 }\r
887\r
888 (*SubBusNumber)++;\r
889 SecondBus = *SubBusNumber;\r
890\r
891 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
892 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
893\r
894 Status = PciRootBridgeIo->Pci.Write (\r
895 PciRootBridgeIo,\r
896 EfiPciWidthUint16,\r
897 Address,\r
898 1,\r
899 &Register\r
900 );\r
901\r
902\r
903 //\r
904 // If it is PPB, resursively search down this bridge\r
905 //\r
906 if (IS_PCI_BRIDGE (&Pci)) {\r
907\r
908 //\r
909 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
910 // PCI configuration transaction to go through any PPB\r
911 //\r
912 Register = 0xFF;\r
913 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
914 Status = PciRootBridgeIo->Pci.Write (\r
915 PciRootBridgeIo,\r
916 EfiPciWidthUint8,\r
917 Address,\r
918 1,\r
919 &Register\r
920 );\r
921\r
922 //\r
923 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
924 //\r
925 PreprocessController (\r
926 PciDevice,\r
927 PciDevice->BusNumber,\r
928 PciDevice->DeviceNumber,\r
929 PciDevice->FunctionNumber,\r
930 EfiPciBeforeChildBusEnumeration\r
931 );\r
932\r
933 DEBUG((EFI_D_INFO, "Scan PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber));\r
934 Status = PciScanBus (\r
935 PciDevice,\r
936 (UINT8) (SecondBus),\r
937 SubBusNumber,\r
938 PaddedBusRange\r
939 );\r
940 if (EFI_ERROR (Status)) {\r
941 return Status;\r
942 }\r
943 }\r
944\r
945 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
946 //\r
947 // Ensure the device is enabled and initialized\r
948 //\r
949 if ((Attributes == EfiPaddingPciRootBridge) &&\r
950 (State & EFI_HPC_STATE_ENABLED) != 0 &&\r
951 (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
952 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
953 } else {\r
954 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
955 }\r
956 }\r
957\r
958 //\r
959 // Set the current maximum bus number under the PPB\r
960 //\r
961 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
962\r
963 Status = PciRootBridgeIo->Pci.Write (\r
964 PciRootBridgeIo,\r
965 EfiPciWidthUint8,\r
966 Address,\r
967 1,\r
968 SubBusNumber\r
969 );\r
970 } else {\r
971 //\r
972 // It is device. Check PCI IOV for Bus reservation\r
9060e3ec 973 // Go through each function, just reserve the MAX ReservedBusNum for one device\r
974 //\r
d4048391 975 if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {\r
9060e3ec 976 if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
977\r
978 (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);\r
979 TempReservedBusNum = PciDevice->ReservedBusNum;\r
980\r
981 if (Func == 0) {\r
982 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
983 } else {\r
984 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
985 }\r
986 }\r
987 }\r
988 }\r
989\r
990 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
991\r
992 //\r
993 // Skip sub functions, this is not a multi function device\r
994 //\r
995\r
996 Func = PCI_MAX_FUNC;\r
997 }\r
998 }\r
999 }\r
1000\r
1001 return EFI_SUCCESS;\r
1002}\r
1003\r
1004/**\r
1005 Process Option Rom on the specified root bridge.\r
1006\r
1007 @param Bridge Pci root bridge device instance.\r
1008\r
1009 @retval EFI_SUCCESS Success process.\r
1010 @retval other Some error occurred when processing Option Rom on the root bridge.\r
1011\r
1012**/\r
1013EFI_STATUS\r
1014PciRootBridgeP2CProcess (\r
1015 IN PCI_IO_DEVICE *Bridge\r
1016 )\r
1017{\r
1018 LIST_ENTRY *CurrentLink;\r
1019 PCI_IO_DEVICE *Temp;\r
1020 EFI_HPC_STATE State;\r
1021 UINT64 PciAddress;\r
1022 EFI_STATUS Status;\r
1023\r
1024 CurrentLink = Bridge->ChildList.ForwardLink;\r
1025\r
1026 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
1027\r
1028 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1029\r
1030 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1031\r
1032 if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1033\r
1034 //\r
1035 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1036 //\r
1037 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1038 EFI_PROGRESS_CODE,\r
1039 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,\r
1040 Temp->DevicePath\r
1041 );\r
1042\r
1043 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1044 Status = gPciHotPlugInit->InitializeRootHpc (\r
1045 gPciHotPlugInit,\r
1046 Temp->DevicePath,\r
1047 PciAddress,\r
1048 NULL,\r
1049 &State\r
1050 );\r
1051\r
1052 if (!EFI_ERROR (Status)) {\r
1053 Status = PciBridgeEnumerator (Temp);\r
1054\r
1055 if (EFI_ERROR (Status)) {\r
1056 return Status;\r
1057 }\r
1058 }\r
1059\r
1060 CurrentLink = CurrentLink->ForwardLink;\r
1061 continue;\r
1062\r
1063 }\r
1064 }\r
1065\r
1066 if (!IsListEmpty (&Temp->ChildList)) {\r
1067 Status = PciRootBridgeP2CProcess (Temp);\r
1068 }\r
1069\r
1070 CurrentLink = CurrentLink->ForwardLink;\r
1071 }\r
1072\r
1073 return EFI_SUCCESS;\r
1074}\r
1075\r
1076/**\r
1077 Process Option Rom on the specified host bridge.\r
1078\r
1079 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
1080\r
1081 @retval EFI_SUCCESS Success process.\r
1082 @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
1083 @retval other Some error occurred when processing Option Rom on the host bridge.\r
1084\r
1085**/\r
1086EFI_STATUS\r
1087PciHostBridgeP2CProcess (\r
1088 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1089 )\r
1090{\r
1091 EFI_HANDLE RootBridgeHandle;\r
1092 PCI_IO_DEVICE *RootBridgeDev;\r
1093 EFI_STATUS Status;\r
1094\r
1095 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1096 return EFI_SUCCESS;\r
1097 }\r
1098\r
1099 RootBridgeHandle = NULL;\r
1100\r
1101 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1102\r
1103 //\r
1104 // Get RootBridg Device by handle\r
1105 //\r
1106 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1107\r
1108 if (RootBridgeDev == NULL) {\r
1109 return EFI_NOT_FOUND;\r
1110 }\r
1111\r
1112 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1113 if (EFI_ERROR (Status)) {\r
1114 return Status;\r
1115 }\r
1116\r
1117 }\r
1118\r
1119 return EFI_SUCCESS;\r
1120}\r
1121\r
1122/**\r
1123 This function is used to enumerate the entire host bridge\r
1124 in a given platform.\r
1125\r
1126 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
1127\r
1128 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1129 @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
1130 @retval other Some error occurred when enumerating the host bridge.\r
1131\r
1132**/\r
1133EFI_STATUS\r
1134PciHostBridgeEnumerator (\r
1135 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1136 )\r
1137{\r
1138 EFI_HANDLE RootBridgeHandle;\r
1139 PCI_IO_DEVICE *RootBridgeDev;\r
1140 EFI_STATUS Status;\r
1141 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1142 UINT16 MinBus;\r
1143 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1144 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
1145 UINT8 StartBusNumber;\r
1146 LIST_ENTRY RootBridgeList;\r
1147 LIST_ENTRY *Link;\r
1148\r
1149 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1150 InitializeHotPlugSupport ();\r
1151 }\r
1152\r
1153 InitializeListHead (&RootBridgeList);\r
1154\r
1155 //\r
1156 // Notify the bus allocation phase is about to start\r
1157 //\r
1158 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1159\r
1160 DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
1161 RootBridgeHandle = NULL;\r
1162 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1163\r
1164 //\r
1165 // if a root bridge instance is found, create root bridge device for it\r
1166 //\r
1167\r
1168 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1169\r
1170 if (RootBridgeDev == NULL) {\r
1171 return EFI_OUT_OF_RESOURCES;\r
1172 }\r
1173\r
1174 //\r
1175 // Enumerate all the buses under this root bridge\r
1176 //\r
1177 Status = PciRootBridgeEnumerator (\r
1178 PciResAlloc,\r
1179 RootBridgeDev\r
1180 );\r
1181\r
1182 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1183 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1184 } else {\r
1185 DestroyRootBridge (RootBridgeDev);\r
1186 }\r
1187 if (EFI_ERROR (Status)) {\r
1188 return Status;\r
1189 }\r
1190 }\r
1191\r
1192 //\r
1193 // Notify the bus allocation phase is finished for the first time\r
1194 //\r
1195 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1196\r
1197 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1198 //\r
1199 // Reset all assigned PCI bus number in all PPB\r
1200 //\r
1201 RootBridgeHandle = NULL;\r
1202 Link = GetFirstNode (&RootBridgeList);\r
1203 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1204 (!IsNull (&RootBridgeList, Link))) {\r
1205 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1206 //\r
1207 // Get the Bus information\r
1208 //\r
1209 Status = PciResAlloc->StartBusEnumeration (\r
1210 PciResAlloc,\r
1211 RootBridgeHandle,\r
1212 (VOID **) &Configuration\r
1213 );\r
1214 if (EFI_ERROR (Status)) {\r
1215 return Status;\r
1216 }\r
1217\r
1218 //\r
1219 // Get the bus number to start with\r
1220 //\r
1221 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
1222\r
1223 ResetAllPpbBusNumber (\r
1224 RootBridgeDev,\r
1225 StartBusNumber\r
1226 );\r
1227\r
1228 FreePool (Configuration);\r
8063b47b 1229 Link = RemoveEntryList (Link);\r
9060e3ec 1230 DestroyRootBridge (RootBridgeDev);\r
1231 }\r
1232\r
1233 //\r
1234 // Wait for all HPC initialized\r
1235 //\r
1236 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1237\r
1238 if (EFI_ERROR (Status)) {\r
55565b08 1239 DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));\r
9060e3ec 1240 return Status;\r
1241 }\r
1242\r
1243 //\r
1244 // Notify the bus allocation phase is about to start for the 2nd time\r
1245 //\r
1246 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1247\r
1248 DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
1249 RootBridgeHandle = NULL;\r
1250 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1251\r
1252 //\r
1253 // if a root bridge instance is found, create root bridge device for it\r
1254 //\r
1255 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1256\r
1257 if (RootBridgeDev == NULL) {\r
1258 return EFI_OUT_OF_RESOURCES;\r
1259 }\r
1260\r
1261 //\r
1262 // Enumerate all the buses under this root bridge\r
1263 //\r
1264 Status = PciRootBridgeEnumerator (\r
1265 PciResAlloc,\r
1266 RootBridgeDev\r
1267 );\r
1268\r
1269 DestroyRootBridge (RootBridgeDev);\r
1270 if (EFI_ERROR (Status)) {\r
1271 return Status;\r
1272 }\r
1273 }\r
1274\r
1275 //\r
1276 // Notify the bus allocation phase is to end for the 2nd time\r
1277 //\r
1278 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1279 }\r
1280\r
1281 //\r
1282 // Notify the resource allocation phase is to start\r
1283 //\r
1284 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1285\r
1286 RootBridgeHandle = NULL;\r
1287 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1288\r
1289 //\r
1290 // if a root bridge instance is found, create root bridge device for it\r
1291 //\r
1292 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1293\r
1294 if (RootBridgeDev == NULL) {\r
1295 return EFI_OUT_OF_RESOURCES;\r
1296 }\r
1297\r
1298 Status = StartManagingRootBridge (RootBridgeDev);\r
1299\r
1300 if (EFI_ERROR (Status)) {\r
1301 return Status;\r
1302 }\r
1303\r
1304 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1305 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1306\r
1307 if (EFI_ERROR (Status)) {\r
1308 return Status;\r
1309 }\r
1310\r
1311 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1312\r
1313 if (EFI_ERROR (Status)) {\r
1314 return Status;\r
1315 }\r
1316\r
1317 //\r
1318 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1319 // protocol\r
1320 //\r
1321 DetermineRootBridgeAttributes (\r
1322 PciResAlloc,\r
1323 RootBridgeDev\r
1324 );\r
1325\r
1326 //\r
1327 // Collect all the resource information under this root bridge\r
1328 // A database that records all the information about pci device subject to this\r
1329 // root bridge will then be created\r
1330 //\r
1331 Status = PciPciDeviceInfoCollector (\r
1332 RootBridgeDev,\r
1333 (UINT8) MinBus\r
1334 );\r
1335\r
1336 if (EFI_ERROR (Status)) {\r
1337 return Status;\r
1338 }\r
1339\r
1340 InsertRootBridge (RootBridgeDev);\r
1341\r
1342 //\r
1343 // Record the hostbridge handle\r
1344 //\r
1345 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1346 }\r
1347\r
1348 return EFI_SUCCESS;\r
1349}\r