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