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