]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
4717140255c1bce3970c4e71a9ca160d601d2b88
[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_PC_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
787 if (!gPciRootHpcData[HpIndex].Initialized) {
788
789 Status = CreateEventForHpc (HpIndex, &Event);
790
791 ASSERT (!EFI_ERROR (Status));
792
793 Status = gPciHotPlugInit->InitializeRootHpc (
794 gPciHotPlugInit,
795 gPciRootHpcPool[HpIndex].HpcDevicePath,
796 PciAddress,
797 Event,
798 &State
799 );
800
801 PreprocessController (
802 PciDevice,
803 PciDevice->BusNumber,
804 PciDevice->DeviceNumber,
805 PciDevice->FunctionNumber,
806 EfiPciBeforeChildBusEnumeration
807 );
808 }
809 }
810 }
811 }
812
813 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
814 //
815 // For PPB
816 //
817 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
818 //
819 // If Hot Plug is not supported,
820 // get the bridge information
821 //
822 Status = PciSearchDevice (
823 Bridge,
824 &Pci,
825 StartBusNumber,
826 Device,
827 Func,
828 &PciDevice
829 );
830
831 if (EFI_ERROR (Status)) {
832 return Status;
833 }
834 } else {
835 //
836 // If Hot Plug is supported,
837 // Get the bridge information
838 //
839 BusPadding = FALSE;
840 if (gPciHotPlugInit != NULL) {
841
842 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {
843
844 //
845 // If it is initialized, get the padded bus range
846 //
847 Status = gPciHotPlugInit->GetResourcePadding (
848 gPciHotPlugInit,
849 gPciRootHpcPool[HpIndex].HpbDevicePath,
850 PciAddress,
851 &State,
852 (VOID **) &Descriptors,
853 &Attributes
854 );
855
856 if (EFI_ERROR (Status)) {
857 return Status;
858 }
859
860 BusRange = 0;
861 Status = PciGetBusRange (
862 &Descriptors,
863 NULL,
864 NULL,
865 &BusRange
866 );
867
868 FreePool (Descriptors);
869
870 if (EFI_ERROR (Status)) {
871 return Status;
872 }
873
874 BusPadding = TRUE;
875 }
876 }
877 }
878
879 //
880 // Add feature to support customized secondary bus number
881 //
882 if (*SubBusNumber == 0) {
883 *SubBusNumber = *PaddedBusRange;
884 *PaddedBusRange = 0;
885 }
886
887 (*SubBusNumber)++;
888 SecondBus = *SubBusNumber;
889
890 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
891 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);
892
893 Status = PciRootBridgeIo->Pci.Write (
894 PciRootBridgeIo,
895 EfiPciWidthUint16,
896 Address,
897 1,
898 &Register
899 );
900
901
902 //
903 // If it is PPB, resursively search down this bridge
904 //
905 if (IS_PCI_BRIDGE (&Pci)) {
906
907 //
908 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
909 // PCI configuration transaction to go through any PPB
910 //
911 Register = 0xFF;
912 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
913 Status = PciRootBridgeIo->Pci.Write (
914 PciRootBridgeIo,
915 EfiPciWidthUint8,
916 Address,
917 1,
918 &Register
919 );
920
921 //
922 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
923 //
924 PreprocessController (
925 PciDevice,
926 PciDevice->BusNumber,
927 PciDevice->DeviceNumber,
928 PciDevice->FunctionNumber,
929 EfiPciBeforeChildBusEnumeration
930 );
931
932 DEBUG((EFI_D_INFO, "Scan PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber));
933 Status = PciScanBus (
934 PciDevice,
935 (UINT8) (SecondBus),
936 SubBusNumber,
937 PaddedBusRange
938 );
939 if (EFI_ERROR (Status)) {
940 return Status;
941 }
942 }
943
944 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {
945 //
946 // Ensure the device is enabled and initialized
947 //
948 if ((Attributes == EfiPaddingPciRootBridge) &&
949 (State & EFI_HPC_STATE_ENABLED) != 0 &&
950 (State & EFI_HPC_STATE_INITIALIZED) != 0) {
951 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);
952 } else {
953 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);
954 }
955 }
956
957 //
958 // Set the current maximum bus number under the PPB
959 //
960 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
961
962 Status = PciRootBridgeIo->Pci.Write (
963 PciRootBridgeIo,
964 EfiPciWidthUint8,
965 Address,
966 1,
967 SubBusNumber
968 );
969 } else {
970 //
971 // It is device. Check PCI IOV for Bus reservation
972 // Go through each function, just reserve the MAX ReservedBusNum for one device
973 //
974 if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {
975 if (TempReservedBusNum < PciDevice->ReservedBusNum) {
976
977 (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);
978 TempReservedBusNum = PciDevice->ReservedBusNum;
979
980 if (Func == 0) {
981 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));
982 } else {
983 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));
984 }
985 }
986 }
987 }
988
989 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
990
991 //
992 // Skip sub functions, this is not a multi function device
993 //
994
995 Func = PCI_MAX_FUNC;
996 }
997 }
998 }
999
1000 return EFI_SUCCESS;
1001 }
1002
1003 /**
1004 Process Option Rom on the specified root bridge.
1005
1006 @param Bridge Pci root bridge device instance.
1007
1008 @retval EFI_SUCCESS Success process.
1009 @retval other Some error occurred when processing Option Rom on the root bridge.
1010
1011 **/
1012 EFI_STATUS
1013 PciRootBridgeP2CProcess (
1014 IN PCI_IO_DEVICE *Bridge
1015 )
1016 {
1017 LIST_ENTRY *CurrentLink;
1018 PCI_IO_DEVICE *Temp;
1019 EFI_HPC_STATE State;
1020 UINT64 PciAddress;
1021 EFI_STATUS Status;
1022
1023 CurrentLink = Bridge->ChildList.ForwardLink;
1024
1025 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
1026
1027 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1028
1029 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
1030
1031 if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1032
1033 //
1034 // Raise the EFI_IOB_PCI_HPC_INIT status code
1035 //
1036 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1037 EFI_PROGRESS_CODE,
1038 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,
1039 Temp->DevicePath
1040 );
1041
1042 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
1043 Status = gPciHotPlugInit->InitializeRootHpc (
1044 gPciHotPlugInit,
1045 Temp->DevicePath,
1046 PciAddress,
1047 NULL,
1048 &State
1049 );
1050
1051 if (!EFI_ERROR (Status)) {
1052 Status = PciBridgeEnumerator (Temp);
1053
1054 if (EFI_ERROR (Status)) {
1055 return Status;
1056 }
1057 }
1058
1059 CurrentLink = CurrentLink->ForwardLink;
1060 continue;
1061
1062 }
1063 }
1064
1065 if (!IsListEmpty (&Temp->ChildList)) {
1066 Status = PciRootBridgeP2CProcess (Temp);
1067 }
1068
1069 CurrentLink = CurrentLink->ForwardLink;
1070 }
1071
1072 return EFI_SUCCESS;
1073 }
1074
1075 /**
1076 Process Option Rom on the specified host bridge.
1077
1078 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1079
1080 @retval EFI_SUCCESS Success process.
1081 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1082 @retval other Some error occurred when processing Option Rom on the host bridge.
1083
1084 **/
1085 EFI_STATUS
1086 PciHostBridgeP2CProcess (
1087 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1088 )
1089 {
1090 EFI_HANDLE RootBridgeHandle;
1091 PCI_IO_DEVICE *RootBridgeDev;
1092 EFI_STATUS Status;
1093
1094 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1095 return EFI_SUCCESS;
1096 }
1097
1098 RootBridgeHandle = NULL;
1099
1100 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1101
1102 //
1103 // Get RootBridg Device by handle
1104 //
1105 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1106
1107 if (RootBridgeDev == NULL) {
1108 return EFI_NOT_FOUND;
1109 }
1110
1111 Status = PciRootBridgeP2CProcess (RootBridgeDev);
1112 if (EFI_ERROR (Status)) {
1113 return Status;
1114 }
1115
1116 }
1117
1118 return EFI_SUCCESS;
1119 }
1120
1121 /**
1122 This function is used to enumerate the entire host bridge
1123 in a given platform.
1124
1125 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1126
1127 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1128 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1129 @retval other Some error occurred when enumerating the host bridge.
1130
1131 **/
1132 EFI_STATUS
1133 PciHostBridgeEnumerator (
1134 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1135 )
1136 {
1137 EFI_HANDLE RootBridgeHandle;
1138 PCI_IO_DEVICE *RootBridgeDev;
1139 EFI_STATUS Status;
1140 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1141 UINT16 MinBus;
1142 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1143 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
1144 UINT8 StartBusNumber;
1145 LIST_ENTRY RootBridgeList;
1146 LIST_ENTRY *Link;
1147
1148 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1149 InitializeHotPlugSupport ();
1150 }
1151
1152 InitializeListHead (&RootBridgeList);
1153
1154 //
1155 // Notify the bus allocation phase is about to start
1156 //
1157 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1158
1159 DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));
1160 RootBridgeHandle = NULL;
1161 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1162
1163 //
1164 // if a root bridge instance is found, create root bridge device for it
1165 //
1166
1167 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1168
1169 if (RootBridgeDev == NULL) {
1170 return EFI_OUT_OF_RESOURCES;
1171 }
1172
1173 //
1174 // Enumerate all the buses under this root bridge
1175 //
1176 Status = PciRootBridgeEnumerator (
1177 PciResAlloc,
1178 RootBridgeDev
1179 );
1180
1181 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1182 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));
1183 } else {
1184 DestroyRootBridge (RootBridgeDev);
1185 }
1186 if (EFI_ERROR (Status)) {
1187 return Status;
1188 }
1189 }
1190
1191 //
1192 // Notify the bus allocation phase is finished for the first time
1193 //
1194 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1195
1196 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1197 //
1198 // Reset all assigned PCI bus number in all PPB
1199 //
1200 RootBridgeHandle = NULL;
1201 Link = GetFirstNode (&RootBridgeList);
1202 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&
1203 (!IsNull (&RootBridgeList, Link))) {
1204 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);
1205 //
1206 // Get the Bus information
1207 //
1208 Status = PciResAlloc->StartBusEnumeration (
1209 PciResAlloc,
1210 RootBridgeHandle,
1211 (VOID **) &Configuration
1212 );
1213 if (EFI_ERROR (Status)) {
1214 return Status;
1215 }
1216
1217 //
1218 // Get the bus number to start with
1219 //
1220 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);
1221
1222 ResetAllPpbBusNumber (
1223 RootBridgeDev,
1224 StartBusNumber
1225 );
1226
1227 FreePool (Configuration);
1228 Link = RemoveEntryList (Link);
1229 DestroyRootBridge (RootBridgeDev);
1230 }
1231
1232 //
1233 // Wait for all HPC initialized
1234 //
1235 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
1236
1237 if (EFI_ERROR (Status)) {
1238 return Status;
1239 }
1240
1241 //
1242 // Notify the bus allocation phase is about to start for the 2nd time
1243 //
1244 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1245
1246 DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));
1247 RootBridgeHandle = NULL;
1248 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1249
1250 //
1251 // if a root bridge instance is found, create root bridge device for it
1252 //
1253 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1254
1255 if (RootBridgeDev == NULL) {
1256 return EFI_OUT_OF_RESOURCES;
1257 }
1258
1259 //
1260 // Enumerate all the buses under this root bridge
1261 //
1262 Status = PciRootBridgeEnumerator (
1263 PciResAlloc,
1264 RootBridgeDev
1265 );
1266
1267 DestroyRootBridge (RootBridgeDev);
1268 if (EFI_ERROR (Status)) {
1269 return Status;
1270 }
1271 }
1272
1273 //
1274 // Notify the bus allocation phase is to end for the 2nd time
1275 //
1276 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1277 }
1278
1279 //
1280 // Notify the resource allocation phase is to start
1281 //
1282 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
1283
1284 RootBridgeHandle = NULL;
1285 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1286
1287 //
1288 // if a root bridge instance is found, create root bridge device for it
1289 //
1290 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1291
1292 if (RootBridgeDev == NULL) {
1293 return EFI_OUT_OF_RESOURCES;
1294 }
1295
1296 Status = StartManagingRootBridge (RootBridgeDev);
1297
1298 if (EFI_ERROR (Status)) {
1299 return Status;
1300 }
1301
1302 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
1303 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1304
1305 if (EFI_ERROR (Status)) {
1306 return Status;
1307 }
1308
1309 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
1310
1311 if (EFI_ERROR (Status)) {
1312 return Status;
1313 }
1314
1315 //
1316 // Determine root bridge attribute by calling interface of Pcihostbridge
1317 // protocol
1318 //
1319 DetermineRootBridgeAttributes (
1320 PciResAlloc,
1321 RootBridgeDev
1322 );
1323
1324 //
1325 // Collect all the resource information under this root bridge
1326 // A database that records all the information about pci device subject to this
1327 // root bridge will then be created
1328 //
1329 Status = PciPciDeviceInfoCollector (
1330 RootBridgeDev,
1331 (UINT8) MinBus
1332 );
1333
1334 if (EFI_ERROR (Status)) {
1335 return Status;
1336 }
1337
1338 InsertRootBridge (RootBridgeDev);
1339
1340 //
1341 // Record the hostbridge handle
1342 //
1343 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
1344 }
1345
1346 return EFI_SUCCESS;
1347 }