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