]> git.proxmox.com Git - mirror_edk2.git/blob - 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
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 if (PciDevice == NULL) {
977 //
978 // No PciDevice found, conitue Scan
979 //
980 continue;
981 }
982 //
983 // Go through each function, just reserve the MAX ReservedBusNum for one device
984 //
985 if ((PciDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {
986
987 if (TempReservedBusNum < PciDevice->ReservedBusNum) {
988
989 (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);
990 TempReservedBusNum = PciDevice->ReservedBusNum;
991
992 if (Func == 0) {
993 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));
994 } else {
995 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));
996 }
997 }
998 }
999 }
1000
1001 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1002
1003 //
1004 // Skip sub functions, this is not a multi function device
1005 //
1006
1007 Func = PCI_MAX_FUNC;
1008 }
1009 }
1010 }
1011
1012 return EFI_SUCCESS;
1013 }
1014
1015 /**
1016 Process Option Rom on the specified root bridge.
1017
1018 @param Bridge Pci root bridge device instance.
1019
1020 @retval EFI_SUCCESS Success process.
1021 @retval other Some error occurred when processing Option Rom on the root bridge.
1022
1023 **/
1024 EFI_STATUS
1025 PciRootBridgeP2CProcess (
1026 IN PCI_IO_DEVICE *Bridge
1027 )
1028 {
1029 LIST_ENTRY *CurrentLink;
1030 PCI_IO_DEVICE *Temp;
1031 EFI_HPC_STATE State;
1032 UINT64 PciAddress;
1033 EFI_STATUS Status;
1034
1035 CurrentLink = Bridge->ChildList.ForwardLink;
1036
1037 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
1038
1039 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1040
1041 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
1042
1043 if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1044
1045 //
1046 // Raise the EFI_IOB_PCI_HPC_INIT status code
1047 //
1048 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1049 EFI_PROGRESS_CODE,
1050 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,
1051 Temp->DevicePath
1052 );
1053
1054 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
1055 Status = gPciHotPlugInit->InitializeRootHpc (
1056 gPciHotPlugInit,
1057 Temp->DevicePath,
1058 PciAddress,
1059 NULL,
1060 &State
1061 );
1062
1063 if (!EFI_ERROR (Status)) {
1064 Status = PciBridgeEnumerator (Temp);
1065
1066 if (EFI_ERROR (Status)) {
1067 return Status;
1068 }
1069 }
1070
1071 CurrentLink = CurrentLink->ForwardLink;
1072 continue;
1073
1074 }
1075 }
1076
1077 if (!IsListEmpty (&Temp->ChildList)) {
1078 Status = PciRootBridgeP2CProcess (Temp);
1079 }
1080
1081 CurrentLink = CurrentLink->ForwardLink;
1082 }
1083
1084 return EFI_SUCCESS;
1085 }
1086
1087 /**
1088 Process Option Rom on the specified host bridge.
1089
1090 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1091
1092 @retval EFI_SUCCESS Success process.
1093 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1094 @retval other Some error occurred when processing Option Rom on the host bridge.
1095
1096 **/
1097 EFI_STATUS
1098 PciHostBridgeP2CProcess (
1099 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1100 )
1101 {
1102 EFI_HANDLE RootBridgeHandle;
1103 PCI_IO_DEVICE *RootBridgeDev;
1104 EFI_STATUS Status;
1105
1106 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1107 return EFI_SUCCESS;
1108 }
1109
1110 RootBridgeHandle = NULL;
1111
1112 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1113
1114 //
1115 // Get RootBridg Device by handle
1116 //
1117 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1118
1119 if (RootBridgeDev == NULL) {
1120 return EFI_NOT_FOUND;
1121 }
1122
1123 Status = PciRootBridgeP2CProcess (RootBridgeDev);
1124 if (EFI_ERROR (Status)) {
1125 return Status;
1126 }
1127
1128 }
1129
1130 return EFI_SUCCESS;
1131 }
1132
1133 /**
1134 This function is used to enumerate the entire host bridge
1135 in a given platform.
1136
1137 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1138
1139 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1140 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1141 @retval other Some error occurred when enumerating the host bridge.
1142
1143 **/
1144 EFI_STATUS
1145 PciHostBridgeEnumerator (
1146 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1147 )
1148 {
1149 EFI_HANDLE RootBridgeHandle;
1150 PCI_IO_DEVICE *RootBridgeDev;
1151 EFI_STATUS Status;
1152 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1153 UINT16 MinBus;
1154 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1155 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
1156 UINT8 StartBusNumber;
1157 LIST_ENTRY RootBridgeList;
1158 LIST_ENTRY *Link;
1159
1160 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1161 InitializeHotPlugSupport ();
1162 }
1163
1164 InitializeListHead (&RootBridgeList);
1165
1166 //
1167 // Notify the bus allocation phase is about to start
1168 //
1169 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1170
1171 DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));
1172 RootBridgeHandle = NULL;
1173 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1174
1175 //
1176 // if a root bridge instance is found, create root bridge device for it
1177 //
1178
1179 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1180
1181 if (RootBridgeDev == NULL) {
1182 return EFI_OUT_OF_RESOURCES;
1183 }
1184
1185 //
1186 // Enumerate all the buses under this root bridge
1187 //
1188 Status = PciRootBridgeEnumerator (
1189 PciResAlloc,
1190 RootBridgeDev
1191 );
1192
1193 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1194 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));
1195 } else {
1196 DestroyRootBridge (RootBridgeDev);
1197 }
1198 if (EFI_ERROR (Status)) {
1199 return Status;
1200 }
1201 }
1202
1203 //
1204 // Notify the bus allocation phase is finished for the first time
1205 //
1206 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1207
1208 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1209 //
1210 // Reset all assigned PCI bus number in all PPB
1211 //
1212 RootBridgeHandle = NULL;
1213 Link = GetFirstNode (&RootBridgeList);
1214 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&
1215 (!IsNull (&RootBridgeList, Link))) {
1216 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);
1217 //
1218 // Get the Bus information
1219 //
1220 Status = PciResAlloc->StartBusEnumeration (
1221 PciResAlloc,
1222 RootBridgeHandle,
1223 (VOID **) &Configuration
1224 );
1225 if (EFI_ERROR (Status)) {
1226 return Status;
1227 }
1228
1229 //
1230 // Get the bus number to start with
1231 //
1232 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);
1233
1234 ResetAllPpbBusNumber (
1235 RootBridgeDev,
1236 StartBusNumber
1237 );
1238
1239 FreePool (Configuration);
1240 Link = GetNextNode (&RootBridgeList, Link);
1241 DestroyRootBridge (RootBridgeDev);
1242 }
1243
1244 //
1245 // Wait for all HPC initialized
1246 //
1247 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
1248
1249 if (EFI_ERROR (Status)) {
1250 return Status;
1251 }
1252
1253 //
1254 // Notify the bus allocation phase is about to start for the 2nd time
1255 //
1256 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1257
1258 DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));
1259 RootBridgeHandle = NULL;
1260 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1261
1262 //
1263 // if a root bridge instance is found, create root bridge device for it
1264 //
1265 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1266
1267 if (RootBridgeDev == NULL) {
1268 return EFI_OUT_OF_RESOURCES;
1269 }
1270
1271 //
1272 // Enumerate all the buses under this root bridge
1273 //
1274 Status = PciRootBridgeEnumerator (
1275 PciResAlloc,
1276 RootBridgeDev
1277 );
1278
1279 DestroyRootBridge (RootBridgeDev);
1280 if (EFI_ERROR (Status)) {
1281 return Status;
1282 }
1283 }
1284
1285 //
1286 // Notify the bus allocation phase is to end for the 2nd time
1287 //
1288 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1289 }
1290
1291 //
1292 // Notify the resource allocation phase is to start
1293 //
1294 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
1295
1296 RootBridgeHandle = NULL;
1297 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1298
1299 //
1300 // if a root bridge instance is found, create root bridge device for it
1301 //
1302 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1303
1304 if (RootBridgeDev == NULL) {
1305 return EFI_OUT_OF_RESOURCES;
1306 }
1307
1308 Status = StartManagingRootBridge (RootBridgeDev);
1309
1310 if (EFI_ERROR (Status)) {
1311 return Status;
1312 }
1313
1314 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
1315 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1316
1317 if (EFI_ERROR (Status)) {
1318 return Status;
1319 }
1320
1321 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
1322
1323 if (EFI_ERROR (Status)) {
1324 return Status;
1325 }
1326
1327 //
1328 // Determine root bridge attribute by calling interface of Pcihostbridge
1329 // protocol
1330 //
1331 DetermineRootBridgeAttributes (
1332 PciResAlloc,
1333 RootBridgeDev
1334 );
1335
1336 //
1337 // Collect all the resource information under this root bridge
1338 // A database that records all the information about pci device subject to this
1339 // root bridge will then be created
1340 //
1341 Status = PciPciDeviceInfoCollector (
1342 RootBridgeDev,
1343 (UINT8) MinBus
1344 );
1345
1346 if (EFI_ERROR (Status)) {
1347 return Status;
1348 }
1349
1350 InsertRootBridge (RootBridgeDev);
1351
1352 //
1353 // Record the hostbridge handle
1354 //
1355 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
1356 }
1357
1358 return EFI_SUCCESS;
1359 }