]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciLib.c
Retired PciIncompatibleDeviceSupportLib from IntelFrameworkModulePkg.
[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
710 PciRootBridgeIo = Bridge->PciRootBridgeIo;
711 SecondBus = 0;
712 Register = 0;
713 State = 0;
714 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;
715 BusRange = 0;
716 BusPadding = FALSE;
717 PciDevice = NULL;
718 PciAddress = 0;
719
720 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
721 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
722
723 //
724 // Check to see whether a pci device is present
725 //
726 Status = PciDevicePresent (
727 PciRootBridgeIo,
728 &Pci,
729 StartBusNumber,
730 Device,
731 Func
732 );
733
734 if (EFI_ERROR (Status)) {
735 if (Func == 0) {
736 //
737 // Skip sub functions, this is not a multi function device
738 //
739 Func = PCI_MAX_FUNC;
740 }
741
742 continue;
743 }
744
745 DEBUG((EFI_D_ERROR, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));
746
747 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
748 //
749 // Get the PCI device information
750 //
751 Status = PciSearchDevice (
752 Bridge,
753 &Pci,
754 StartBusNumber,
755 Device,
756 Func,
757 &PciDevice
758 );
759
760 ASSERT (!EFI_ERROR (Status));
761
762 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
763
764 if (!IS_PCI_BRIDGE (&Pci)) {
765 //
766 // PCI bridges will be called later
767 // Here just need for PCI device or PCI to cardbus controller
768 // EfiPciBeforeChildBusEnumeration for PCI Device Node
769 //
770 PreprocessController (
771 PciDevice,
772 PciDevice->BusNumber,
773 PciDevice->DeviceNumber,
774 PciDevice->FunctionNumber,
775 EfiPciBeforeChildBusEnumeration
776 );
777 }
778
779 //
780 // For Pci Hotplug controller devcie only
781 //
782 if (gPciHotPlugInit != NULL) {
783 //
784 // Check if it is a Hotplug PCI controller
785 //
786 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
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_ERROR, "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 }
971
972 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
973
974 //
975 // Skip sub functions, this is not a multi function device
976 //
977
978 Func = PCI_MAX_FUNC;
979 }
980 }
981 }
982
983 return EFI_SUCCESS;
984 }
985
986 /**
987 Process Option Rom on the specified root bridge.
988
989 @param Bridge Pci root bridge device instance.
990
991 @retval EFI_SUCCESS Success process.
992 @retval other Some error occurred when processing Option Rom on the root bridge.
993
994 **/
995 EFI_STATUS
996 PciRootBridgeP2CProcess (
997 IN PCI_IO_DEVICE *Bridge
998 )
999 {
1000 LIST_ENTRY *CurrentLink;
1001 PCI_IO_DEVICE *Temp;
1002 EFI_HPC_STATE State;
1003 UINT64 PciAddress;
1004 EFI_STATUS Status;
1005
1006 CurrentLink = Bridge->ChildList.ForwardLink;
1007
1008 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
1009
1010 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1011
1012 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
1013
1014 if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1015
1016 //
1017 // Raise the EFI_IOB_PCI_HPC_INIT status code
1018 //
1019 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1020 EFI_PROGRESS_CODE,
1021 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,
1022 Temp->DevicePath
1023 );
1024
1025 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
1026 Status = gPciHotPlugInit->InitializeRootHpc (
1027 gPciHotPlugInit,
1028 Temp->DevicePath,
1029 PciAddress,
1030 NULL,
1031 &State
1032 );
1033
1034 if (!EFI_ERROR (Status)) {
1035 Status = PciBridgeEnumerator (Temp);
1036
1037 if (EFI_ERROR (Status)) {
1038 return Status;
1039 }
1040 }
1041
1042 CurrentLink = CurrentLink->ForwardLink;
1043 continue;
1044
1045 }
1046 }
1047
1048 if (!IsListEmpty (&Temp->ChildList)) {
1049 Status = PciRootBridgeP2CProcess (Temp);
1050 }
1051
1052 CurrentLink = CurrentLink->ForwardLink;
1053 }
1054
1055 return EFI_SUCCESS;
1056 }
1057
1058 /**
1059 Process Option Rom on the specified host bridge.
1060
1061 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1062
1063 @retval EFI_SUCCESS Success process.
1064 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1065 @retval other Some error occurred when processing Option Rom on the host bridge.
1066
1067 **/
1068 EFI_STATUS
1069 PciHostBridgeP2CProcess (
1070 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1071 )
1072 {
1073 EFI_HANDLE RootBridgeHandle;
1074 PCI_IO_DEVICE *RootBridgeDev;
1075 EFI_STATUS Status;
1076
1077 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1078 return EFI_SUCCESS;
1079 }
1080
1081 RootBridgeHandle = NULL;
1082
1083 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1084
1085 //
1086 // Get RootBridg Device by handle
1087 //
1088 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1089
1090 if (RootBridgeDev == NULL) {
1091 return EFI_NOT_FOUND;
1092 }
1093
1094 Status = PciRootBridgeP2CProcess (RootBridgeDev);
1095 if (EFI_ERROR (Status)) {
1096 return Status;
1097 }
1098
1099 }
1100
1101 return EFI_SUCCESS;
1102 }
1103
1104 /**
1105 This function is used to enumerate the entire host bridge
1106 in a given platform.
1107
1108 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1109
1110 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1111 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1112 @retval other Some error occurred when enumerating the host bridge.
1113
1114 **/
1115 EFI_STATUS
1116 PciHostBridgeEnumerator (
1117 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1118 )
1119 {
1120 EFI_HANDLE RootBridgeHandle;
1121 PCI_IO_DEVICE *RootBridgeDev;
1122 EFI_STATUS Status;
1123 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1124 UINT16 MinBus;
1125 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1126 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
1127 UINT8 StartBusNumber;
1128 LIST_ENTRY RootBridgeList;
1129 LIST_ENTRY *Link;
1130
1131 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1132 InitializeHotPlugSupport ();
1133 }
1134
1135 InitializeListHead (&RootBridgeList);
1136
1137 //
1138 // Notify the bus allocation phase is about to start
1139 //
1140 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1141
1142 DEBUG((EFI_D_ERROR, "PCI Bus First Scanning\n"));
1143 RootBridgeHandle = NULL;
1144 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1145
1146 //
1147 // if a root bridge instance is found, create root bridge device for it
1148 //
1149
1150 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1151
1152 if (RootBridgeDev == NULL) {
1153 return EFI_OUT_OF_RESOURCES;
1154 }
1155
1156 //
1157 // Enumerate all the buses under this root bridge
1158 //
1159 Status = PciRootBridgeEnumerator (
1160 PciResAlloc,
1161 RootBridgeDev
1162 );
1163
1164 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1165 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));
1166 } else {
1167 DestroyRootBridge (RootBridgeDev);
1168 }
1169 if (EFI_ERROR (Status)) {
1170 return Status;
1171 }
1172 }
1173
1174 //
1175 // Notify the bus allocation phase is finished for the first time
1176 //
1177 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1178
1179 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1180 //
1181 // Reset all assigned PCI bus number in all PPB
1182 //
1183 RootBridgeHandle = NULL;
1184 Link = GetFirstNode (&RootBridgeList);
1185 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&
1186 (!IsNull (&RootBridgeList, Link))) {
1187 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);
1188 //
1189 // Get the Bus information
1190 //
1191 Status = PciResAlloc->StartBusEnumeration (
1192 PciResAlloc,
1193 RootBridgeHandle,
1194 (VOID **) &Configuration
1195 );
1196 if (EFI_ERROR (Status)) {
1197 return Status;
1198 }
1199
1200 //
1201 // Get the bus number to start with
1202 //
1203 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);
1204
1205 ResetAllPpbBusNumber (
1206 RootBridgeDev,
1207 StartBusNumber
1208 );
1209
1210 FreePool (Configuration);
1211 Link = GetNextNode (&RootBridgeList, Link);
1212 DestroyRootBridge (RootBridgeDev);
1213 }
1214
1215 //
1216 // Wait for all HPC initialized
1217 //
1218 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
1219
1220 if (EFI_ERROR (Status)) {
1221 return Status;
1222 }
1223
1224 //
1225 // Notify the bus allocation phase is about to start for the 2nd time
1226 //
1227 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1228
1229 DEBUG((EFI_D_ERROR, "PCI Bus Second Scanning\n"));
1230 RootBridgeHandle = NULL;
1231 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1232
1233 //
1234 // if a root bridge instance is found, create root bridge device for it
1235 //
1236 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1237
1238 if (RootBridgeDev == NULL) {
1239 return EFI_OUT_OF_RESOURCES;
1240 }
1241
1242 //
1243 // Enumerate all the buses under this root bridge
1244 //
1245 Status = PciRootBridgeEnumerator (
1246 PciResAlloc,
1247 RootBridgeDev
1248 );
1249
1250 DestroyRootBridge (RootBridgeDev);
1251 if (EFI_ERROR (Status)) {
1252 return Status;
1253 }
1254 }
1255
1256 //
1257 // Notify the bus allocation phase is to end for the 2nd time
1258 //
1259 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1260 }
1261
1262 //
1263 // Notify the resource allocation phase is to start
1264 //
1265 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
1266
1267 RootBridgeHandle = NULL;
1268 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1269
1270 //
1271 // if a root bridge instance is found, create root bridge device for it
1272 //
1273 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1274
1275 if (RootBridgeDev == NULL) {
1276 return EFI_OUT_OF_RESOURCES;
1277 }
1278
1279 Status = StartManagingRootBridge (RootBridgeDev);
1280
1281 if (EFI_ERROR (Status)) {
1282 return Status;
1283 }
1284
1285 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
1286 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1287
1288 if (EFI_ERROR (Status)) {
1289 return Status;
1290 }
1291
1292 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
1293
1294 if (EFI_ERROR (Status)) {
1295 return Status;
1296 }
1297
1298 //
1299 // Determine root bridge attribute by calling interface of Pcihostbridge
1300 // protocol
1301 //
1302 DetermineRootBridgeAttributes (
1303 PciResAlloc,
1304 RootBridgeDev
1305 );
1306
1307 //
1308 // Collect all the resource information under this root bridge
1309 // A database that records all the information about pci device subject to this
1310 // root bridge will then be created
1311 //
1312 Status = PciPciDeviceInfoCollector (
1313 RootBridgeDev,
1314 (UINT8) MinBus
1315 );
1316
1317 if (EFI_ERROR (Status)) {
1318 return Status;
1319 }
1320
1321 InsertRootBridge (RootBridgeDev);
1322
1323 //
1324 // Record the hostbridge handle
1325 //
1326 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
1327 }
1328
1329 return EFI_SUCCESS;
1330 }