]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c
Fix component name bugs when input Controller Name is invalid
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / PciBus / Dxe / PciLib.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 PciLib.c
15
16 Abstract:
17
18 PCI Bus Driver Lib file
19 It abstracts some functions that can be different
20 between light PCI bus driver and full PCI bus driver
21
22 Revision History
23
24 --*/
25
26 #include "pcibus.h"
27
28 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest = {
29 PciHotPlugRequestNotify
30 };
31
32
33 VOID
34 InstallHotPlugRequestProtocol (
35 IN EFI_STATUS *Status
36 )
37 /*++
38
39 Routine Description:
40
41 Arguments:
42 Status - A pointer to the status.
43
44 Returns:
45
46 None
47
48 --*/
49 {
50 EFI_HANDLE Handle;
51
52 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
53 return;
54 }
55
56 Handle = NULL;
57 *Status = gBS->InstallProtocolInterface (
58 &Handle,
59 &gEfiPciHotPlugRequestProtocolGuid,
60 EFI_NATIVE_INTERFACE,
61 &gPciHotPlugRequest
62 );
63 }
64
65 VOID
66 InstallPciHotplugGuid (
67 IN PCI_IO_DEVICE *PciIoDevice
68 )
69 /*++
70
71 Routine Description:
72
73 Arguments:
74
75 PciIoDevice - A pointer to the PCI_IO_DEVICE.
76
77 Returns:
78
79 None
80
81 --*/
82 {
83 EFI_STATUS Status;
84
85 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
86 return;
87 }
88
89 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Parent->Pci)) {
90
91 Status = gBS->InstallProtocolInterface (
92 &PciIoDevice->Handle,
93 &gEfiPciHotplugDeviceGuid,
94 EFI_NATIVE_INTERFACE,
95 NULL
96 );
97 }
98 }
99
100 VOID
101 UninstallPciHotplugGuid (
102 IN PCI_IO_DEVICE *PciIoDevice
103 )
104 /*++
105
106 Routine Description:
107
108 Arguments:
109
110 PciIoDevice - A pointer to the PCI_IO_DEVICE.
111
112 Returns:
113
114 None
115
116 --*/
117 {
118 EFI_STATUS Status;
119
120 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
121 return;
122 }
123
124 Status = gBS->OpenProtocol (
125 PciIoDevice->Handle,
126 &gEfiPciHotplugDeviceGuid,
127 NULL,
128 NULL,
129 NULL,
130 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
131 );
132
133 if (Status == EFI_SUCCESS) {
134 //
135 // This may triger CardBus driver to stop for
136 // Pccard devices opened the GUID via BY_DRIVER
137 //
138 Status = gBS->UninstallProtocolInterface (
139 PciIoDevice->Handle,
140 &gEfiPciHotplugDeviceGuid,
141 NULL
142 );
143 }
144 }
145
146 VOID
147 GetBackPcCardBar (
148 IN PCI_IO_DEVICE *PciIoDevice
149 )
150 /*++
151
152 Routine Description:
153
154
155 Arguments:
156
157 PciIoDevice - A pointer to the PCI_IO_DEVICE.
158
159 Returns:
160
161 None
162
163 --*/
164 {
165 UINT32 Address;
166
167 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
168 return;
169 }
170
171 //
172 // Read PciBar information from the bar register
173 //
174 if (!gFullEnumeration) {
175
176 Address = 0;
177 PciIoDevice->PciIo.Pci.Read (
178 &(PciIoDevice->PciIo),
179 EfiPciIoWidthUint32,
180 0x1c,
181 1,
182 &Address
183 );
184
185 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);
186 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;
187 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;
188
189 Address = 0;
190 PciIoDevice->PciIo.Pci.Read (
191 &(PciIoDevice->PciIo),
192 EfiPciIoWidthUint32,
193 0x20,
194 1,
195 &Address
196 );
197 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);
198 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;
199 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;
200
201 Address = 0;
202 PciIoDevice->PciIo.Pci.Read (
203 &(PciIoDevice->PciIo),
204 EfiPciIoWidthUint32,
205 0x2c,
206 1,
207 &Address
208 );
209 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);
210 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;
211 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;
212
213 Address = 0;
214 PciIoDevice->PciIo.Pci.Read (
215 &(PciIoDevice->PciIo),
216 EfiPciIoWidthUint32,
217 0x34,
218 1,
219 &Address
220 );
221 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);
222 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;
223 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;
224
225 }
226
227 if (gPciHotPlugInit != NULL) {
228 GetResourcePaddingForHpb (PciIoDevice);
229 }
230 }
231
232 EFI_STATUS
233 RemoveRejectedPciDevices (
234 EFI_HANDLE RootBridgeHandle,
235 IN PCI_IO_DEVICE *Bridge
236 )
237 /*++
238
239 Routine Description:
240
241
242 Arguments:
243
244 RootBridgeHandle - An efi handle.
245 Bridge - An pointer to the PCI_IO_DEVICE.
246
247 Returns:
248
249 None
250
251 --*/
252 // TODO: EFI_SUCCESS - add return value to function comment
253 {
254 PCI_IO_DEVICE *Temp;
255 LIST_ENTRY *CurrentLink;
256 LIST_ENTRY *LastLink;
257
258 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
259 return EFI_SUCCESS;
260 }
261
262 CurrentLink = Bridge->ChildList.ForwardLink;
263
264 while (CurrentLink && CurrentLink != &Bridge->ChildList) {
265
266 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
267
268 if (IS_PCI_BRIDGE (&Temp->Pci)) {
269 //
270 // Remove rejected devices recusively
271 //
272 RemoveRejectedPciDevices (RootBridgeHandle, Temp);
273 } else {
274 //
275 // Skip rejection for all PPBs, while detect rejection for others
276 //
277 if (IsPciDeviceRejected (Temp)) {
278
279 //
280 // For P2C, remove all devices on it
281 //
282
283 if (!IsListEmpty (&Temp->ChildList)) {
284 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
285 }
286
287 //
288 // Finally remove itself
289 //
290
291 LastLink = CurrentLink->BackLink;
292 RemoveEntryList (CurrentLink);
293 FreePciDevice (Temp);
294
295 CurrentLink = LastLink;
296 }
297 }
298
299 CurrentLink = CurrentLink->ForwardLink;
300 }
301
302 return EFI_SUCCESS;
303 }
304
305 EFI_STATUS
306 PciHostBridgeResourceAllocator (
307 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
308 )
309 {
310 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
311 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
312 PciResAlloc
313 );
314 } else {
315 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
316 PciResAlloc
317 );
318 }
319 }
320
321
322 EFI_STATUS
323 PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
324 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
325 )
326 /*++
327
328 Routine Description:
329
330 Arguments:
331
332 Returns:
333
334 None
335
336 --*/
337 // TODO: PciResAlloc - add argument and description to function comment
338 // TODO: EFI_NOT_FOUND - add return value to function comment
339 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
340 // TODO: EFI_NOT_FOUND - add return value to function comment
341 // TODO: EFI_SUCCESS - add return value to function comment
342 {
343 PCI_IO_DEVICE *RootBridgeDev;
344 EFI_HANDLE RootBridgeHandle;
345 VOID *AcpiConfig;
346 EFI_STATUS Status;
347 UINT64 IoBase;
348 UINT64 Mem32Base;
349 UINT64 PMem32Base;
350 UINT64 Mem64Base;
351 UINT64 PMem64Base;
352 UINT64 MaxOptionRomSize;
353 PCI_RESOURCE_NODE *IoBridge;
354 PCI_RESOURCE_NODE *Mem32Bridge;
355 PCI_RESOURCE_NODE *PMem32Bridge;
356 PCI_RESOURCE_NODE *Mem64Bridge;
357 PCI_RESOURCE_NODE *PMem64Bridge;
358 PCI_RESOURCE_NODE IoPool;
359 PCI_RESOURCE_NODE Mem32Pool;
360 PCI_RESOURCE_NODE PMem32Pool;
361 PCI_RESOURCE_NODE Mem64Pool;
362 PCI_RESOURCE_NODE PMem64Pool;
363 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
364
365 //
366 // Initialize resource pool
367 //
368
369 InitializeResourcePool (&IoPool, PciBarTypeIo16);
370 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
371 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
372 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
373 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
374
375 RootBridgeDev = NULL;
376 RootBridgeHandle = 0;
377
378 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
379 //
380 // Get RootBridg Device by handle
381 //
382 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
383
384 if (RootBridgeDev == NULL) {
385 return EFI_NOT_FOUND;
386 }
387
388 //
389 // Get host bridge handle for status report
390 //
391 ExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
392
393 //
394 // Create the entire system resource map from the information collected by
395 // enumerator. Several resource tree was created
396 //
397
398 IoBridge = CreateResourceNode (
399 RootBridgeDev,
400 0,
401 0xFFF,
402 0,
403 PciBarTypeIo16,
404 PciResUsageTypical
405 );
406
407 Mem32Bridge = CreateResourceNode (
408 RootBridgeDev,
409 0,
410 0xFFFFF,
411 0,
412 PciBarTypeMem32,
413 PciResUsageTypical
414 );
415
416 PMem32Bridge = CreateResourceNode (
417 RootBridgeDev,
418 0,
419 0xFFFFF,
420 0,
421 PciBarTypePMem32,
422 PciResUsageTypical
423 );
424
425 Mem64Bridge = CreateResourceNode (
426 RootBridgeDev,
427 0,
428 0xFFFFF,
429 0,
430 PciBarTypeMem64,
431 PciResUsageTypical
432 );
433
434 PMem64Bridge = CreateResourceNode (
435 RootBridgeDev,
436 0,
437 0xFFFFF,
438 0,
439 PciBarTypePMem64,
440 PciResUsageTypical
441 );
442
443 //
444 // Create resourcemap by going through all the devices subject to this root bridge
445 //
446 Status = CreateResourceMap (
447 RootBridgeDev,
448 IoBridge,
449 Mem32Bridge,
450 PMem32Bridge,
451 Mem64Bridge,
452 PMem64Bridge
453 );
454
455 //
456 // Get the max ROM size that the root bridge can process
457 //
458 RootBridgeDev->RomSize = Mem32Bridge->Length;
459
460 //
461 // Get Max Option Rom size for current root bridge
462 //
463 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
464
465 //
466 // Enlarger the mem32 resource to accomdate the option rom
467 // if the mem32 resource is not enough to hold the rom
468 //
469 if (MaxOptionRomSize > Mem32Bridge->Length) {
470
471 Mem32Bridge->Length = MaxOptionRomSize;
472 RootBridgeDev->RomSize = MaxOptionRomSize;
473
474 //
475 // Alignment should be adjusted as well
476 //
477 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
478 Mem32Bridge->Alignment = MaxOptionRomSize - 1;
479 }
480 }
481
482 //
483 // Based on the all the resource tree, contruct ACPI resource node to
484 // submit the resource aperture to pci host bridge protocol
485 //
486 Status = ConstructAcpiResourceRequestor (
487 RootBridgeDev,
488 IoBridge,
489 Mem32Bridge,
490 PMem32Bridge,
491 Mem64Bridge,
492 PMem64Bridge,
493 &AcpiConfig
494 );
495
496 //
497 // Insert these resource nodes into the database
498 //
499 InsertResourceNode (&IoPool, IoBridge);
500 InsertResourceNode (&Mem32Pool, Mem32Bridge);
501 InsertResourceNode (&PMem32Pool, PMem32Bridge);
502 InsertResourceNode (&Mem64Pool, Mem64Bridge);
503 InsertResourceNode (&PMem64Pool, PMem64Bridge);
504
505 if (Status == EFI_SUCCESS) {
506 //
507 // Submit the resource requirement
508 //
509 Status = PciResAlloc->SubmitResources (
510 PciResAlloc,
511 RootBridgeDev->Handle,
512 AcpiConfig
513 );
514 }
515 //
516 // Free acpi resource node
517 //
518 if (AcpiConfig) {
519 gBS->FreePool (AcpiConfig);
520 }
521
522 if (EFI_ERROR (Status)) {
523 //
524 // Destroy all the resource tree
525 //
526 DestroyResourceTree (&IoPool);
527 DestroyResourceTree (&Mem32Pool);
528 DestroyResourceTree (&PMem32Pool);
529 DestroyResourceTree (&Mem64Pool);
530 DestroyResourceTree (&PMem64Pool);
531 return Status;
532 }
533 }
534 //
535 // End while
536 //
537
538 //
539 // Notify pci bus driver starts to program the resource
540 //
541 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
542
543 if (EFI_ERROR (Status)) {
544 //
545 // Allocation failed, then return
546 //
547 return EFI_OUT_OF_RESOURCES;
548 }
549 //
550 // Raise the EFI_IOB_PCI_RES_ALLOC status code
551 //
552 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
553 EFI_PROGRESS_CODE,
554 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
555 (VOID *) &ExtendedData,
556 sizeof (ExtendedData)
557 );
558
559 //
560 // Notify pci bus driver starts to program the resource
561 //
562 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
563
564 RootBridgeDev = NULL;
565
566 RootBridgeHandle = 0;
567
568 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
569 //
570 // Get RootBridg Device by handle
571 //
572 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
573
574 if (RootBridgeDev == NULL) {
575 return EFI_NOT_FOUND;
576 }
577
578 //
579 // Get acpi resource node for all the resource types
580 //
581 AcpiConfig = NULL;
582 Status = PciResAlloc->GetProposedResources (
583 PciResAlloc,
584 RootBridgeDev->Handle,
585 &AcpiConfig
586 );
587
588 if (EFI_ERROR (Status)) {
589 return Status;
590 }
591
592 //
593 // Get the resource base by interpreting acpi resource node
594 //
595 //
596 GetResourceBase (
597 AcpiConfig,
598 &IoBase,
599 &Mem32Base,
600 &PMem32Base,
601 &Mem64Base,
602 &PMem64Base
603 );
604
605 //
606 // Process option rom for this root bridge
607 //
608 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
609
610 //
611 // Create the entire system resource map from the information collected by
612 // enumerator. Several resource tree was created
613 //
614 Status = GetResourceMap (
615 RootBridgeDev,
616 &IoBridge,
617 &Mem32Bridge,
618 &PMem32Bridge,
619 &Mem64Bridge,
620 &PMem64Bridge,
621 &IoPool,
622 &Mem32Pool,
623 &PMem32Pool,
624 &Mem64Pool,
625 &PMem64Pool
626 );
627
628 if (EFI_ERROR (Status)) {
629 return Status;
630 }
631
632 //
633 // Program IO resources
634 //
635 ProgramResource (
636 IoBase,
637 IoBridge
638 );
639
640 //
641 // Program Mem32 resources
642 //
643 ProgramResource (
644 Mem32Base,
645 Mem32Bridge
646 );
647
648 //
649 // Program PMem32 resources
650 //
651 ProgramResource (
652 PMem32Base,
653 PMem32Bridge
654 );
655
656 //
657 // Program Mem64 resources
658 //
659 ProgramResource (
660 Mem64Base,
661 Mem64Bridge
662 );
663
664 //
665 // Program PMem64 resources
666 //
667 ProgramResource (
668 PMem64Base,
669 PMem64Bridge
670 );
671
672 if (AcpiConfig != NULL) {
673 gBS->FreePool (AcpiConfig);
674 }
675 }
676
677 //
678 // Destroy all the resource tree
679 //
680 DestroyResourceTree (&IoPool);
681 DestroyResourceTree (&Mem32Pool);
682 DestroyResourceTree (&PMem32Pool);
683 DestroyResourceTree (&Mem64Pool);
684 DestroyResourceTree (&PMem64Pool);
685
686 //
687 // Notify the resource allocation phase is to end
688 //
689 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
690
691 return EFI_SUCCESS;
692 }
693
694
695 EFI_STATUS
696 PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
697 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
698 )
699 /*++
700
701 Routine Description:
702
703 Host brige resource allocator.
704
705 Arguments:
706
707 PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
708
709 Returns:
710
711 EFI Status.
712
713 --*/
714 // TODO: EFI_NOT_FOUND - add return value to function comment
715 // TODO: EFI_NOT_FOUND - add return value to function comment
716 // TODO: EFI_NOT_FOUND - add return value to function comment
717 // TODO: EFI_SUCCESS - add return value to function comment
718 {
719 PCI_IO_DEVICE *RootBridgeDev;
720 EFI_HANDLE RootBridgeHandle;
721 VOID *AcpiConfig;
722 EFI_STATUS Status;
723 UINT64 IoBase;
724 UINT64 Mem32Base;
725 UINT64 PMem32Base;
726 UINT64 Mem64Base;
727 UINT64 PMem64Base;
728 UINT64 IoResStatus;
729 UINT64 Mem32ResStatus;
730 UINT64 PMem32ResStatus;
731 UINT64 Mem64ResStatus;
732 UINT64 PMem64ResStatus;
733 UINT64 MaxOptionRomSize;
734 PCI_RESOURCE_NODE *IoBridge;
735 PCI_RESOURCE_NODE *Mem32Bridge;
736 PCI_RESOURCE_NODE *PMem32Bridge;
737 PCI_RESOURCE_NODE *Mem64Bridge;
738 PCI_RESOURCE_NODE *PMem64Bridge;
739 PCI_RESOURCE_NODE IoPool;
740 PCI_RESOURCE_NODE Mem32Pool;
741 PCI_RESOURCE_NODE PMem32Pool;
742 PCI_RESOURCE_NODE Mem64Pool;
743 PCI_RESOURCE_NODE PMem64Pool;
744 BOOLEAN ReAllocate;
745 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA HandleExtendedData;
746 REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;
747
748 //
749 // Reallocate flag
750 //
751 ReAllocate = FALSE;
752
753 //
754 // It will try several times if the resource allocation fails
755 //
756 while (TRUE) {
757
758 //
759 // Initialize resource pool
760 //
761 InitializeResourcePool (&IoPool, PciBarTypeIo16);
762 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
763 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
764 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
765 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
766
767 RootBridgeDev = NULL;
768 RootBridgeHandle = 0;
769
770 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
771
772 //
773 // Get RootBridg Device by handle
774 //
775 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
776
777 if (RootBridgeDev == NULL) {
778 return EFI_NOT_FOUND;
779 }
780
781 //
782 // Create the entire system resource map from the information collected by
783 // enumerator. Several resource tree was created
784 //
785
786 IoBridge = CreateResourceNode (
787 RootBridgeDev,
788 0,
789 0xFFF,
790 0,
791 PciBarTypeIo16,
792 PciResUsageTypical
793 );
794
795 Mem32Bridge = CreateResourceNode (
796 RootBridgeDev,
797 0,
798 0xFFFFF,
799 0,
800 PciBarTypeMem32,
801 PciResUsageTypical
802 );
803
804 PMem32Bridge = CreateResourceNode (
805 RootBridgeDev,
806 0,
807 0xFFFFF,
808 0,
809 PciBarTypePMem32,
810 PciResUsageTypical
811 );
812
813 Mem64Bridge = CreateResourceNode (
814 RootBridgeDev,
815 0,
816 0xFFFFF,
817 0,
818 PciBarTypeMem64,
819 PciResUsageTypical
820 );
821
822 PMem64Bridge = CreateResourceNode (
823 RootBridgeDev,
824 0,
825 0xFFFFF,
826 0,
827 PciBarTypePMem64,
828 PciResUsageTypical
829 );
830
831 //
832 // Create resourcemap by going through all the devices subject to this root bridge
833 //
834 Status = CreateResourceMap (
835 RootBridgeDev,
836 IoBridge,
837 Mem32Bridge,
838 PMem32Bridge,
839 Mem64Bridge,
840 PMem64Bridge
841 );
842
843 //
844 // Get the max ROM size that the root bridge can process
845 //
846 RootBridgeDev->RomSize = Mem32Bridge->Length;
847
848 //
849 // Skip to enlarge the resource request during realloction
850 //
851 if (!ReAllocate) {
852 //
853 // Get Max Option Rom size for current root bridge
854 //
855 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
856
857 //
858 // Enlarger the mem32 resource to accomdate the option rom
859 // if the mem32 resource is not enough to hold the rom
860 //
861 if (MaxOptionRomSize > Mem32Bridge->Length) {
862
863 Mem32Bridge->Length = MaxOptionRomSize;
864 RootBridgeDev->RomSize = MaxOptionRomSize;
865
866 //
867 // Alignment should be adjusted as well
868 //
869 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
870 Mem32Bridge->Alignment = MaxOptionRomSize - 1;
871 }
872 }
873 }
874
875 //
876 // Based on the all the resource tree, contruct ACPI resource node to
877 // submit the resource aperture to pci host bridge protocol
878 //
879 Status = ConstructAcpiResourceRequestor (
880 RootBridgeDev,
881 IoBridge,
882 Mem32Bridge,
883 PMem32Bridge,
884 Mem64Bridge,
885 PMem64Bridge,
886 &AcpiConfig
887 );
888
889 //
890 // Insert these resource nodes into the database
891 //
892 InsertResourceNode (&IoPool, IoBridge);
893 InsertResourceNode (&Mem32Pool, Mem32Bridge);
894 InsertResourceNode (&PMem32Pool, PMem32Bridge);
895 InsertResourceNode (&Mem64Pool, Mem64Bridge);
896 InsertResourceNode (&PMem64Pool, PMem64Bridge);
897
898 if (Status == EFI_SUCCESS) {
899 //
900 // Submit the resource requirement
901 //
902 Status = PciResAlloc->SubmitResources (
903 PciResAlloc,
904 RootBridgeDev->Handle,
905 AcpiConfig
906 );
907 }
908
909 //
910 // Free acpi resource node
911 //
912 if (AcpiConfig != NULL) {
913 gBS->FreePool (AcpiConfig);
914 }
915
916 if (EFI_ERROR (Status)) {
917 //
918 // Destroy all the resource tree
919 //
920 DestroyResourceTree (&IoPool);
921 DestroyResourceTree (&Mem32Pool);
922 DestroyResourceTree (&PMem32Pool);
923 DestroyResourceTree (&Mem64Pool);
924 DestroyResourceTree (&PMem64Pool);
925 return Status;
926 }
927 }
928
929 //
930 // Notify pci bus driver starts to program the resource
931 //
932
933 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
934
935 if (!EFI_ERROR (Status)) {
936 //
937 // Allocation succeed, then continue the following
938 //
939 break;
940 }
941
942 //
943 // If the resource allocation is unsuccessful, free resources on bridge
944 //
945
946 RootBridgeDev = NULL;
947 RootBridgeHandle = 0;
948
949 IoResStatus = EFI_RESOURCE_SATISFIED;
950 Mem32ResStatus = EFI_RESOURCE_SATISFIED;
951 PMem32ResStatus = EFI_RESOURCE_SATISFIED;
952 Mem64ResStatus = EFI_RESOURCE_SATISFIED;
953 PMem64ResStatus = EFI_RESOURCE_SATISFIED;
954
955 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
956 //
957 // Get RootBridg Device by handle
958 //
959 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
960 if (RootBridgeDev == NULL) {
961 return EFI_NOT_FOUND;
962 }
963
964 //
965 // Get host bridge handle for status report
966 //
967 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
968
969 //
970 // Get acpi resource node for all the resource types
971 //
972 AcpiConfig = NULL;
973
974 Status = PciResAlloc->GetProposedResources (
975 PciResAlloc,
976 RootBridgeDev->Handle,
977 &AcpiConfig
978 );
979
980 if (EFI_ERROR (Status)) {
981 return Status;
982 }
983
984 if (AcpiConfig != NULL) {
985 //
986 // Adjust resource allocation policy for each RB
987 //
988 GetResourceAllocationStatus (
989 AcpiConfig,
990 &IoResStatus,
991 &Mem32ResStatus,
992 &PMem32ResStatus,
993 &Mem64ResStatus,
994 &PMem64ResStatus
995 );
996 gBS->FreePool (AcpiConfig);
997 }
998 }
999 //
1000 // End while
1001 //
1002
1003 //
1004 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1005 //
1006 //
1007 // It is very difficult to follow the spec here
1008 // Device path , Bar index can not be get here
1009 //
1010 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
1011
1012 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1013 EFI_PROGRESS_CODE,
1014 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
1015 (VOID *) &AllocFailExtendedData,
1016 sizeof (AllocFailExtendedData)
1017 );
1018
1019 Status = PciHostBridgeAdjustAllocation (
1020 &IoPool,
1021 &Mem32Pool,
1022 &PMem32Pool,
1023 &Mem64Pool,
1024 &PMem64Pool,
1025 IoResStatus,
1026 Mem32ResStatus,
1027 PMem32ResStatus,
1028 Mem64ResStatus,
1029 PMem64ResStatus
1030 );
1031
1032 //
1033 // Destroy all the resource tree
1034 //
1035 DestroyResourceTree (&IoPool);
1036 DestroyResourceTree (&Mem32Pool);
1037 DestroyResourceTree (&PMem32Pool);
1038 DestroyResourceTree (&Mem64Pool);
1039 DestroyResourceTree (&PMem64Pool);
1040
1041 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
1042
1043 if (EFI_ERROR (Status)) {
1044 return Status;
1045 }
1046
1047 ReAllocate = TRUE;
1048
1049 }
1050 //
1051 // End main while
1052 //
1053
1054 //
1055 // Raise the EFI_IOB_PCI_RES_ALLOC status code
1056 //
1057 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1058 EFI_PROGRESS_CODE,
1059 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
1060 (VOID *) &HandleExtendedData,
1061 sizeof (HandleExtendedData)
1062 );
1063
1064 //
1065 // Notify pci bus driver starts to program the resource
1066 //
1067 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
1068
1069 RootBridgeDev = NULL;
1070
1071 RootBridgeHandle = 0;
1072
1073 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1074
1075 //
1076 // Get RootBridg Device by handle
1077 //
1078 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1079
1080 if (RootBridgeDev == NULL) {
1081 return EFI_NOT_FOUND;
1082 }
1083
1084 //
1085 // Get acpi resource node for all the resource types
1086 //
1087 AcpiConfig = NULL;
1088 Status = PciResAlloc->GetProposedResources (
1089 PciResAlloc,
1090 RootBridgeDev->Handle,
1091 &AcpiConfig
1092 );
1093
1094 if (EFI_ERROR (Status)) {
1095 return Status;
1096 }
1097
1098 //
1099 // Get the resource base by interpreting acpi resource node
1100 //
1101 //
1102 GetResourceBase (
1103 AcpiConfig,
1104 &IoBase,
1105 &Mem32Base,
1106 &PMem32Base,
1107 &Mem64Base,
1108 &PMem64Base
1109 );
1110
1111 //
1112 // Process option rom for this root bridge
1113 //
1114 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
1115
1116 //
1117 // Create the entire system resource map from the information collected by
1118 // enumerator. Several resource tree was created
1119 //
1120 Status = GetResourceMap (
1121 RootBridgeDev,
1122 &IoBridge,
1123 &Mem32Bridge,
1124 &PMem32Bridge,
1125 &Mem64Bridge,
1126 &PMem64Bridge,
1127 &IoPool,
1128 &Mem32Pool,
1129 &PMem32Pool,
1130 &Mem64Pool,
1131 &PMem64Pool
1132 );
1133
1134 if (EFI_ERROR (Status)) {
1135 return Status;
1136 }
1137
1138 //
1139 // Program IO resources
1140 //
1141 ProgramResource (
1142 IoBase,
1143 IoBridge
1144 );
1145
1146 //
1147 // Program Mem32 resources
1148 //
1149 ProgramResource (
1150 Mem32Base,
1151 Mem32Bridge
1152 );
1153
1154 //
1155 // Program PMem32 resources
1156 //
1157 ProgramResource (
1158 PMem32Base,
1159 PMem32Bridge
1160 );
1161
1162 //
1163 // Program Mem64 resources
1164 //
1165 ProgramResource (
1166 Mem64Base,
1167 Mem64Bridge
1168 );
1169
1170 //
1171 // Program PMem64 resources
1172 //
1173 ProgramResource (
1174 PMem64Base,
1175 PMem64Bridge
1176 );
1177
1178 if (AcpiConfig != NULL) {
1179 gBS->FreePool (AcpiConfig);
1180 }
1181 }
1182
1183 //
1184 // Destroy all the resource tree
1185 //
1186 DestroyResourceTree (&IoPool);
1187 DestroyResourceTree (&Mem32Pool);
1188 DestroyResourceTree (&PMem32Pool);
1189 DestroyResourceTree (&Mem64Pool);
1190 DestroyResourceTree (&PMem64Pool);
1191
1192 //
1193 // Notify the resource allocation phase is to end
1194 //
1195 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
1196
1197 return EFI_SUCCESS;
1198 }
1199
1200
1201 EFI_STATUS
1202 PciScanBus (
1203 IN PCI_IO_DEVICE *Bridge,
1204 IN UINT8 StartBusNumber,
1205 OUT UINT8 *SubBusNumber,
1206 OUT UINT8 *PaddedBusRange
1207 )
1208 {
1209 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1210 return PciScanBus_WithHotPlugDeviceSupport (
1211 Bridge,
1212 StartBusNumber,
1213 SubBusNumber,
1214 PaddedBusRange
1215 );
1216 } else {
1217 return PciScanBus_WithoutHotPlugDeviceSupport (
1218 Bridge,
1219 StartBusNumber,
1220 SubBusNumber,
1221 PaddedBusRange
1222 );
1223 }
1224 }
1225
1226
1227 EFI_STATUS
1228 PciScanBus_WithoutHotPlugDeviceSupport (
1229 IN PCI_IO_DEVICE *Bridge,
1230 IN UINT8 StartBusNumber,
1231 OUT UINT8 *SubBusNumber,
1232 OUT UINT8 *PaddedBusRange
1233 )
1234 /*++
1235
1236 Routine Description:
1237
1238 This routine is used to assign bus number to the given PCI bus system
1239
1240 Arguments:
1241
1242 Returns:
1243
1244 None
1245
1246 --*/
1247 // TODO: Bridge - add argument and description to function comment
1248 // TODO: StartBusNumber - add argument and description to function comment
1249 // TODO: SubBusNumber - add argument and description to function comment
1250 // TODO: PaddedBusRange - add argument and description to function comment
1251 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1252 // TODO: EFI_SUCCESS - add return value to function comment
1253 {
1254 EFI_STATUS Status;
1255 PCI_TYPE00 Pci;
1256 UINT8 Device;
1257 UINT8 Func;
1258 UINT64 Address;
1259 UINTN SecondBus;
1260 UINT16 Register;
1261 PCI_IO_DEVICE *PciDevice;
1262 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1263
1264 PciRootBridgeIo = Bridge->PciRootBridgeIo;
1265 SecondBus = 0;
1266 Register = 0;
1267
1268 ResetAllPpbBusReg (Bridge, StartBusNumber);
1269
1270 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
1271 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
1272
1273 //
1274 // Check to see whether a pci device is present
1275 //
1276 Status = PciDevicePresent (
1277 PciRootBridgeIo,
1278 &Pci,
1279 StartBusNumber,
1280 Device,
1281 Func
1282 );
1283
1284 if (!EFI_ERROR (Status) &&
1285 (IS_PCI_BRIDGE (&Pci) ||
1286 IS_CARDBUS_BRIDGE (&Pci))) {
1287
1288 //
1289 // Get the bridge information
1290 //
1291 Status = PciSearchDevice (
1292 Bridge,
1293 &Pci,
1294 StartBusNumber,
1295 Device,
1296 Func,
1297 &PciDevice
1298 );
1299
1300 if (EFI_ERROR (Status)) {
1301 return Status;
1302 }
1303
1304 (*SubBusNumber)++;
1305
1306 SecondBus = (*SubBusNumber);
1307
1308 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
1309
1310 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
1311
1312 Status = PciRootBridgeIo->Pci.Write (
1313 PciRootBridgeIo,
1314 EfiPciWidthUint16,
1315 Address,
1316 1,
1317 &Register
1318 );
1319
1320 //
1321 // Initialize SubBusNumber to SecondBus
1322 //
1323 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1324 Status = PciRootBridgeIo->Pci.Write (
1325 PciRootBridgeIo,
1326 EfiPciWidthUint8,
1327 Address,
1328 1,
1329 SubBusNumber
1330 );
1331 //
1332 // If it is PPB, resursively search down this bridge
1333 //
1334 if (IS_PCI_BRIDGE (&Pci)) {
1335 //
1336 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1337 // PCI configuration transaction to go through any PPB
1338 //
1339 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1340 Register = 0xFF;
1341 Status = PciRootBridgeIo->Pci.Write (
1342 PciRootBridgeIo,
1343 EfiPciWidthUint8,
1344 Address,
1345 1,
1346 &Register
1347 );
1348
1349 PreprocessController (
1350 PciDevice,
1351 PciDevice->BusNumber,
1352 PciDevice->DeviceNumber,
1353 PciDevice->FunctionNumber,
1354 EfiPciBeforeChildBusEnumeration
1355 );
1356
1357 Status = PciScanBus (
1358 PciDevice,
1359 (UINT8) (SecondBus),
1360 SubBusNumber,
1361 PaddedBusRange
1362 );
1363
1364 if (EFI_ERROR (Status)) {
1365 return EFI_DEVICE_ERROR;
1366 }
1367 }
1368
1369 //
1370 // Set the current maximum bus number under the PPB
1371 //
1372
1373 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1374
1375 Status = PciRootBridgeIo->Pci.Write (
1376 PciRootBridgeIo,
1377 EfiPciWidthUint8,
1378 Address,
1379 1,
1380 SubBusNumber
1381 );
1382
1383 }
1384
1385 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1386
1387 //
1388 // Skip sub functions, this is not a multi function device
1389 //
1390
1391 Func = PCI_MAX_FUNC;
1392 }
1393 }
1394 }
1395
1396 return EFI_SUCCESS;
1397 }
1398
1399 EFI_STATUS
1400 PciScanBus_WithHotPlugDeviceSupport (
1401 IN PCI_IO_DEVICE *Bridge,
1402 IN UINT8 StartBusNumber,
1403 OUT UINT8 *SubBusNumber,
1404 OUT UINT8 *PaddedBusRange
1405 )
1406 /*++
1407
1408 Routine Description:
1409
1410 This routine is used to assign bus number to the given PCI bus system
1411
1412 Arguments:
1413
1414 Bridge - A pointer to the PCI_IO_DEVICE structure.
1415 StartBusNumber - The start bus number.
1416 SubBusNumber - A pointer to the sub bus number.
1417 PaddedBusRange - A pointer to the padded bus range.
1418
1419 Returns:
1420
1421 None
1422
1423 --*/
1424 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1425 // TODO: EFI_SUCCESS - add return value to function comment
1426 {
1427 EFI_STATUS Status;
1428 PCI_TYPE00 Pci;
1429 UINT8 Device;
1430 UINT8 Func;
1431 UINT64 Address;
1432 UINTN SecondBus;
1433 UINT16 Register;
1434 UINTN HpIndex;
1435 PCI_IO_DEVICE *PciDevice;
1436 EFI_EVENT Event;
1437 EFI_HPC_STATE State;
1438 UINT64 PciAddress;
1439 EFI_HPC_PADDING_ATTRIBUTES Attributes;
1440 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1441 UINT16 BusRange;
1442 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1443 BOOLEAN BusPadding;
1444
1445 PciRootBridgeIo = Bridge->PciRootBridgeIo;
1446 SecondBus = 0;
1447 Register = 0;
1448 State = 0;
1449 Attributes = 0;
1450 BusRange = 0;
1451
1452 ResetAllPpbBusReg (Bridge, StartBusNumber);
1453
1454 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
1455 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
1456
1457 //
1458 // Check to see whether a pci device is present
1459 //
1460 Status = PciDevicePresent (
1461 PciRootBridgeIo,
1462 &Pci,
1463 StartBusNumber,
1464 Device,
1465 Func
1466 );
1467
1468 if (EFI_ERROR (Status)) {
1469 if (Func == 0) {
1470 //
1471 // Skip sub functions, this is not a multi function device
1472 //
1473 Func = PCI_MAX_FUNC;
1474 }
1475
1476 continue;
1477 }
1478
1479 //
1480 // Get the PCI device information
1481 //
1482 Status = PciSearchDevice (
1483 Bridge,
1484 &Pci,
1485 StartBusNumber,
1486 Device,
1487 Func,
1488 &PciDevice
1489 );
1490
1491 ASSERT (!EFI_ERROR (Status));
1492
1493 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
1494
1495 if (!IS_PCI_BRIDGE (&Pci)) {
1496 //
1497 // PCI bridges will be called later
1498 // Here just need for PCI device or PCI to cardbus controller
1499 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1500 //
1501 PreprocessController (
1502 PciDevice,
1503 PciDevice->BusNumber,
1504 PciDevice->DeviceNumber,
1505 PciDevice->FunctionNumber,
1506 EfiPciBeforeChildBusEnumeration
1507 );
1508 }
1509
1510 //
1511 // For Pci Hotplug controller devcie only
1512 //
1513 if (gPciHotPlugInit != NULL) {
1514 //
1515 // Check if it is a Hotplug PCI controller
1516 //
1517 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
1518
1519 if (!gPciRootHpcData[HpIndex].Initialized) {
1520
1521 Status = CreateEventForHpc (HpIndex, &Event);
1522
1523 ASSERT (!EFI_ERROR (Status));
1524
1525 Status = gPciHotPlugInit->InitializeRootHpc (
1526 gPciHotPlugInit,
1527 gPciRootHpcPool[HpIndex].HpcDevicePath,
1528 PciAddress,
1529 Event,
1530 &State
1531 );
1532
1533 PreprocessController (
1534 PciDevice,
1535 PciDevice->BusNumber,
1536 PciDevice->DeviceNumber,
1537 PciDevice->FunctionNumber,
1538 EfiPciBeforeChildBusEnumeration
1539 );
1540 continue;
1541 }
1542 }
1543 }
1544
1545 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
1546 //
1547 // For PPB
1548 // Get the bridge information
1549 //
1550 BusPadding = FALSE;
1551 if (gPciHotPlugInit != NULL) {
1552
1553 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {
1554
1555 //
1556 // If it is initialized, get the padded bus range
1557 //
1558 Status = gPciHotPlugInit->GetResourcePadding (
1559 gPciHotPlugInit,
1560 gPciRootHpcPool[HpIndex].HpbDevicePath,
1561 PciAddress,
1562 &State,
1563 (VOID **) &Descriptors,
1564 &Attributes
1565 );
1566
1567 if (EFI_ERROR (Status)) {
1568 return Status;
1569 }
1570
1571 BusRange = 0;
1572 Status = PciGetBusRange (
1573 &Descriptors,
1574 NULL,
1575 NULL,
1576 &BusRange
1577 );
1578
1579 gBS->FreePool (Descriptors);
1580
1581 if (EFI_ERROR (Status)) {
1582 return Status;
1583 }
1584
1585 BusPadding = TRUE;
1586 }
1587 }
1588
1589 (*SubBusNumber)++;
1590 SecondBus = *SubBusNumber;
1591
1592 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
1593 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
1594
1595 Status = PciRootBridgeIo->Pci.Write (
1596 PciRootBridgeIo,
1597 EfiPciWidthUint16,
1598 Address,
1599 1,
1600 &Register
1601 );
1602
1603
1604 //
1605 // If it is PPB, resursively search down this bridge
1606 //
1607 if (IS_PCI_BRIDGE (&Pci)) {
1608
1609 //
1610 // Initialize SubBusNumber to Maximum bus number
1611 //
1612 Register = 0xFF;
1613 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1614 Status = PciRootBridgeIo->Pci.Write (
1615 PciRootBridgeIo,
1616 EfiPciWidthUint8,
1617 Address,
1618 1,
1619 &Register
1620 );
1621
1622 //
1623 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1624 //
1625 PreprocessController (
1626 PciDevice,
1627 PciDevice->BusNumber,
1628 PciDevice->DeviceNumber,
1629 PciDevice->FunctionNumber,
1630 EfiPciBeforeChildBusEnumeration
1631 );
1632
1633 Status = PciScanBus (
1634 PciDevice,
1635 (UINT8) (SecondBus),
1636 SubBusNumber,
1637 PaddedBusRange
1638 );
1639
1640 if (EFI_ERROR (Status)) {
1641 return EFI_DEVICE_ERROR;
1642 }
1643 }
1644
1645 if (BusPadding) {
1646 //
1647 // Ensure the device is enabled and initialized
1648 //
1649 if ((Attributes == EfiPaddingPciRootBridge) &&
1650 (State & EFI_HPC_STATE_ENABLED) &&
1651 (State & EFI_HPC_STATE_INITIALIZED) ) {
1652 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);
1653 } else {
1654 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);
1655 }
1656 }
1657
1658 //
1659 // Set the current maximum bus number under the PPB
1660 //
1661 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1662
1663 Status = PciRootBridgeIo->Pci.Write (
1664 PciRootBridgeIo,
1665 EfiPciWidthUint8,
1666 Address,
1667 1,
1668 SubBusNumber
1669 );
1670 }
1671
1672 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1673
1674 //
1675 // Skip sub functions, this is not a multi function device
1676 //
1677 Func = PCI_MAX_FUNC;
1678 }
1679
1680 }
1681 }
1682
1683 return EFI_SUCCESS;
1684 }
1685
1686 EFI_STATUS
1687 PciRootBridgeP2CProcess (
1688 IN PCI_IO_DEVICE *Bridge
1689 )
1690 /*++
1691
1692 Routine Description:
1693
1694 Process Option Rom on this host bridge
1695
1696 Arguments:
1697
1698 Returns:
1699
1700 None
1701
1702 --*/
1703 // TODO: Bridge - add argument and description to function comment
1704 // TODO: EFI_SUCCESS - add return value to function comment
1705 {
1706 LIST_ENTRY *CurrentLink;
1707 PCI_IO_DEVICE *Temp;
1708 EFI_HPC_STATE State;
1709 UINT64 PciAddress;
1710 EFI_STATUS Status;
1711
1712 CurrentLink = Bridge->ChildList.ForwardLink;
1713
1714 while (CurrentLink && CurrentLink != &Bridge->ChildList) {
1715
1716 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1717
1718 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
1719
1720 if (gPciHotPlugInit && Temp->Allocated) {
1721
1722 //
1723 // Raise the EFI_IOB_PCI_HPC_INIT status code
1724 //
1725 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1726 EFI_PROGRESS_CODE,
1727 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,
1728 Temp->DevicePath
1729 );
1730
1731 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
1732 Status = gPciHotPlugInit->InitializeRootHpc (
1733 gPciHotPlugInit,
1734 Temp->DevicePath,
1735 PciAddress,
1736 NULL,
1737 &State
1738 );
1739
1740 if (!EFI_ERROR (Status)) {
1741 Status = PciBridgeEnumerator (Temp);
1742
1743 if (EFI_ERROR (Status)) {
1744 return Status;
1745 }
1746 }
1747
1748 CurrentLink = CurrentLink->ForwardLink;
1749 continue;
1750
1751 }
1752 }
1753
1754 if (!IsListEmpty (&Temp->ChildList)) {
1755 Status = PciRootBridgeP2CProcess (Temp);
1756 }
1757
1758 CurrentLink = CurrentLink->ForwardLink;
1759 }
1760
1761 return EFI_SUCCESS;
1762 }
1763
1764 EFI_STATUS
1765 PciHostBridgeP2CProcess (
1766 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1767 )
1768 /*++
1769
1770 Routine Description:
1771
1772 Arguments:
1773
1774 Returns:
1775
1776 None
1777
1778 --*/
1779 // TODO: PciResAlloc - add argument and description to function comment
1780 // TODO: EFI_NOT_FOUND - add return value to function comment
1781 // TODO: EFI_SUCCESS - add return value to function comment
1782 {
1783 EFI_HANDLE RootBridgeHandle;
1784 PCI_IO_DEVICE *RootBridgeDev;
1785 EFI_STATUS Status;
1786
1787 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1788 return EFI_SUCCESS;
1789 }
1790
1791 RootBridgeHandle = NULL;
1792
1793 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1794
1795 //
1796 // Get RootBridg Device by handle
1797 //
1798 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1799
1800 if (RootBridgeDev == NULL) {
1801 return EFI_NOT_FOUND;
1802 }
1803
1804 Status = PciRootBridgeP2CProcess (RootBridgeDev);
1805
1806 if (EFI_ERROR (Status)) {
1807 return Status;
1808 }
1809
1810 }
1811
1812 return EFI_SUCCESS;
1813 }
1814
1815 EFI_STATUS
1816 PciHostBridgeEnumerator (
1817 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1818 )
1819 /*++
1820
1821 Routine Description:
1822
1823 This function is used to enumerate the entire host bridge
1824 in a given platform
1825
1826 Arguments:
1827
1828 PciResAlloc - A pointer to the resource allocate protocol.
1829
1830 Returns:
1831
1832 None
1833
1834 --*/
1835 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1836 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1837 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1838 // TODO: EFI_SUCCESS - add return value to function comment
1839 {
1840 EFI_HANDLE RootBridgeHandle;
1841 PCI_IO_DEVICE *RootBridgeDev;
1842 EFI_STATUS Status;
1843 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1844 UINT16 MinBus;
1845 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1846
1847 InitializeHotPlugSupport ();
1848
1849 //
1850 // Notify the bus allocation phase is about to start
1851 //
1852 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1853
1854 RootBridgeHandle = NULL;
1855 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1856
1857 //
1858 // if a root bridge instance is found, create root bridge device for it
1859 //
1860
1861 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1862
1863 if (RootBridgeDev == NULL) {
1864 return EFI_OUT_OF_RESOURCES;
1865 }
1866
1867 //
1868 // Enumerate all the buses under this root bridge
1869 //
1870
1871 Status = PciRootBridgeEnumerator (
1872 PciResAlloc,
1873 RootBridgeDev
1874 );
1875
1876 if (EFI_ERROR (Status)) {
1877 return Status;
1878 }
1879
1880 DestroyRootBridge (RootBridgeDev);
1881
1882 //
1883 // Error proccess here
1884 //
1885 }
1886
1887 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1888
1889 //
1890 // Notify the bus allocation phase is finished for the first time
1891 //
1892 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1893
1894
1895 if (gPciHotPlugInit != NULL) {
1896 //
1897 // Wait for all HPC initialized
1898 //
1899 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
1900
1901 if (EFI_ERROR (Status)) {
1902 return Status;
1903 }
1904
1905 //
1906 // Notify the bus allocation phase is about to start for the 2nd time
1907 //
1908 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1909
1910 RootBridgeHandle = NULL;
1911 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1912
1913 //
1914 // if a root bridge instance is found, create root bridge device for it
1915 //
1916
1917 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1918
1919 if (RootBridgeDev == NULL) {
1920 return EFI_OUT_OF_RESOURCES;
1921 }
1922
1923 //
1924 // Enumerate all the buses under this root bridge
1925 //
1926
1927 Status = PciRootBridgeEnumerator (
1928 PciResAlloc,
1929 RootBridgeDev
1930 );
1931
1932 DestroyRootBridge (RootBridgeDev);
1933 if (EFI_ERROR (Status)) {
1934 return Status;
1935 }
1936 }
1937
1938 //
1939 // Notify the bus allocation phase is to end
1940 //
1941 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1942 }
1943 } else {
1944 //
1945 // Notify the bus allocation phase is to end
1946 //
1947 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1948 }
1949
1950 //
1951 // Notify the resource allocation phase is to start
1952 //
1953 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
1954
1955 RootBridgeHandle = NULL;
1956 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1957
1958 //
1959 // if a root bridge instance is found, create root bridge device for it
1960 //
1961
1962 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1963
1964 if (RootBridgeDev == NULL) {
1965 return EFI_OUT_OF_RESOURCES;
1966 }
1967
1968 Status = StartManagingRootBridge (RootBridgeDev);
1969
1970 if (EFI_ERROR (Status)) {
1971 return Status;
1972 }
1973
1974 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
1975 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1976
1977 if (EFI_ERROR (Status)) {
1978 return Status;
1979 }
1980
1981 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
1982
1983 if (EFI_ERROR (Status)) {
1984 return Status;
1985 }
1986
1987 //
1988 // Determine root bridge attribute by calling interface of Pcihostbridge
1989 // protocol
1990 //
1991 DetermineRootBridgeAttributes (
1992 PciResAlloc,
1993 RootBridgeDev
1994 );
1995
1996 //
1997 // Collect all the resource information under this root bridge
1998 // A database that records all the information about pci device subject to this
1999 // root bridge will then be created
2000 //
2001 Status = PciPciDeviceInfoCollector (
2002 RootBridgeDev,
2003 (UINT8) MinBus
2004 );
2005
2006 if (EFI_ERROR (Status)) {
2007 return Status;
2008 }
2009
2010 InsertRootBridge (RootBridgeDev);
2011
2012 //
2013 // Record the hostbridge handle
2014 //
2015 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
2016 }
2017
2018 return EFI_SUCCESS;
2019 }