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