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