]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c
Add PciBus & IdeBus
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBus / Dxe / PciEnumerator.c
1 /*++
2
3 Copyright (c) 2006 - 2007, 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 PciEnumerator.c
15
16 Abstract:
17
18 PCI Bus Driver
19
20 Revision History
21
22 --*/
23
24 #include "pcibus.h"
25 #include "PciEnumerator.h"
26 #include "PciResourceSupport.h"
27 #include "PciOptionRomSupport.h"
28
29 EFI_STATUS
30 PciEnumerator (
31 IN EFI_HANDLE Controller
32 )
33 /*++
34
35 Routine Description:
36
37 This routine is used to enumerate entire pci bus system
38 in a given platform
39
40 Arguments:
41
42 Returns:
43
44 None
45
46 --*/
47 // TODO: Controller - add argument and description to function comment
48 // TODO: EFI_SUCCESS - add return value to function comment
49 // TODO: EFI_SUCCESS - add return value to function comment
50 {
51
52 EFI_HANDLE HostBridgeHandle;
53 EFI_STATUS Status;
54 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
55 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
56
57 //
58 // If PCI bus has already done the full enumeration, never do it again
59 //
60 if (!gFullEnumeration) {
61 return PciEnumeratorLight (Controller);
62 }
63
64 //
65 // If this host bridge has been already enumerated, then return successfully
66 //
67 if (RootBridgeExisted (Controller)) {
68 return EFI_SUCCESS;
69 }
70
71 //
72 // Get the rootbridge Io protocol to find the host bridge handle
73 //
74 Status = gBS->OpenProtocol (
75 Controller,
76 &gEfiPciRootBridgeIoProtocolGuid,
77 (VOID **) &PciRootBridgeIo,
78 gPciBusDriverBinding.DriverBindingHandle,
79 Controller,
80 EFI_OPEN_PROTOCOL_GET_PROTOCOL
81 );
82
83 if (EFI_ERROR (Status)) {
84 return Status;
85 }
86
87 //
88 // Get the host bridge handle
89 //
90 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
91
92 //
93 // Get the pci host bridge resource allocation protocol
94 //
95 Status = gBS->OpenProtocol (
96 HostBridgeHandle,
97 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
98 (VOID **) &PciResAlloc,
99 gPciBusDriverBinding.DriverBindingHandle,
100 Controller,
101 EFI_OPEN_PROTOCOL_GET_PROTOCOL
102 );
103
104 if (EFI_ERROR (Status)) {
105 return Status;
106 }
107
108 //
109 // Notify the pci bus enumeration is about to begin
110 //
111 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
112
113 //
114 // Start the bus allocation phase
115 //
116 Status = PciHostBridgeEnumerator (PciResAlloc);
117
118 if (EFI_ERROR (Status)) {
119 return Status;
120 }
121
122 //
123 // Submit the resource request
124 //
125 Status = PciHostBridgeResourceAllocator (PciResAlloc);
126
127 if (EFI_ERROR (Status)) {
128 return Status;
129 }
130
131 //
132 // Process P2C
133 //
134 Status = PciHostBridgeP2CProcess (PciResAlloc);
135
136 if (EFI_ERROR (Status)) {
137 return Status;
138 }
139
140 //
141 // Process attributes for devices on this host bridge
142 //
143 Status = PciHostBridgeDeviceAttribute (PciResAlloc);
144 if (EFI_ERROR (Status)) {
145 return Status;
146 }
147
148 gFullEnumeration = FALSE;
149
150 return EFI_SUCCESS;
151 }
152
153 EFI_STATUS
154 PciRootBridgeEnumerator (
155 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
156 IN PCI_IO_DEVICE *RootBridgeDev
157 )
158 /*++
159
160 Routine Description:
161
162 Arguments:
163
164 Returns:
165
166 None
167
168 --*/
169 // TODO: PciResAlloc - add argument and description to function comment
170 // TODO: RootBridgeDev - add argument and description to function comment
171 // TODO: EFI_SUCCESS - add return value to function comment
172 {
173 EFI_STATUS Status;
174 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *pConfiguration;
175 UINT8 SubBusNumber;
176 UINT8 StartBusNumber;
177 UINT8 PaddedBusRange;
178 EFI_HANDLE RootBridgeHandle;
179
180 SubBusNumber = 0;
181 StartBusNumber = 0;
182 PaddedBusRange = 0;
183
184 //
185 // Get the root bridge handle
186 //
187 RootBridgeHandle = RootBridgeDev->Handle;
188
189 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
190 EFI_PROGRESS_CODE,
191 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,
192 RootBridgeDev->DevicePath
193 );
194
195 //
196 // Get the Bus information
197 //
198 Status = PciResAlloc->StartBusEnumeration (
199 PciResAlloc,
200 RootBridgeHandle,
201 (VOID **) &pConfiguration
202 );
203
204 if (EFI_ERROR (Status)) {
205 return Status;
206 }
207
208 //
209 // Get the bus number to start with
210 //
211 StartBusNumber = (UINT8) (pConfiguration->AddrRangeMin);
212
213 //
214 // Initialize the subordinate bus number
215 //
216 SubBusNumber = StartBusNumber;
217
218 //
219 // Assign bus number
220 //
221 Status = PciScanBus (
222 RootBridgeDev,
223 (UINT8) (pConfiguration->AddrRangeMin),
224 &SubBusNumber,
225 &PaddedBusRange
226 );
227
228 if (EFI_ERROR (Status)) {
229 return Status;
230 }
231
232
233 //
234 // Assign max bus number scanned
235 //
236 pConfiguration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;
237
238 //
239 // Set bus number
240 //
241 Status = PciResAlloc->SetBusNumbers (
242 PciResAlloc,
243 RootBridgeHandle,
244 pConfiguration
245 );
246
247 if (EFI_ERROR (Status)) {
248 return Status;
249 }
250
251 return EFI_SUCCESS;
252 }
253
254 EFI_STATUS
255 ProcessOptionRom (
256 IN PCI_IO_DEVICE *Bridge,
257 IN UINT64 RomBase,
258 IN UINT64 MaxLength
259 )
260 /*++
261
262 Routine Description:
263
264 This routine is used to process option rom on a certain root bridge
265
266 Arguments:
267
268 Returns:
269
270 None
271
272 --*/
273 // TODO: Bridge - add argument and description to function comment
274 // TODO: RomBase - add argument and description to function comment
275 // TODO: MaxLength - add argument and description to function comment
276 // TODO: EFI_SUCCESS - add return value to function comment
277 {
278 LIST_ENTRY *CurrentLink;
279 PCI_IO_DEVICE *Temp;
280 EFI_STATUS Status;
281
282 //
283 // Go through bridges to reach all devices
284 //
285 CurrentLink = Bridge->ChildList.ForwardLink;
286 while (CurrentLink && CurrentLink != &Bridge->ChildList) {
287 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
288 if (!IsListEmpty (&Temp->ChildList)) {
289
290 //
291 // Go further to process the option rom under this bridge
292 //
293 Status = ProcessOptionRom (Temp, RomBase, MaxLength);
294 }
295
296 if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {
297
298 //
299 // Load and process the option rom
300 //
301 Status = LoadOpRomImage (Temp, RomBase);
302 if (Status == EFI_SUCCESS) {
303 Status = ProcessOpRomImage (Temp);
304 }
305 }
306
307 CurrentLink = CurrentLink->ForwardLink;
308 }
309
310 return EFI_SUCCESS;
311 }
312
313 EFI_STATUS
314 PciAssignBusNumber (
315 IN PCI_IO_DEVICE *Bridge,
316 IN UINT8 StartBusNumber,
317 OUT UINT8 *SubBusNumber
318 )
319 /*++
320
321 Routine Description:
322
323 This routine is used to assign bus number to the given PCI bus system
324
325 Arguments:
326
327 Returns:
328
329 None
330
331 --*/
332 // TODO: Bridge - add argument and description to function comment
333 // TODO: StartBusNumber - add argument and description to function comment
334 // TODO: SubBusNumber - add argument and description to function comment
335 // TODO: EFI_DEVICE_ERROR - add return value to function comment
336 // TODO: EFI_SUCCESS - add return value to function comment
337 {
338 EFI_STATUS Status;
339 PCI_TYPE00 Pci;
340 UINT8 Device;
341 UINT8 Func;
342 UINT64 Address;
343 UINTN SecondBus;
344 UINT16 Register;
345 UINT8 Register8;
346 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
347
348 PciRootBridgeIo = Bridge->PciRootBridgeIo;
349
350 SecondBus = 0;
351 Register = 0;
352
353 *SubBusNumber = StartBusNumber;
354
355 //
356 // First check to see whether the parent is ppb
357 //
358 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
359 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
360
361 //
362 // Check to see whether a pci device is present
363 //
364
365 Status = PciDevicePresent (
366 PciRootBridgeIo,
367 &Pci,
368 StartBusNumber,
369 Device,
370 Func
371 );
372
373 if (!EFI_ERROR (Status) &&
374 (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
375
376 //
377 // Reserved one bus for cardbus bridge
378 //
379 SecondBus = ++(*SubBusNumber);
380
381 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
382
383 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
384
385 Status = PciRootBridgeIoWrite (
386 PciRootBridgeIo,
387 &Pci,
388 EfiPciWidthUint16,
389 Address,
390 1,
391 &Register
392 );
393
394 //
395 // Initialize SubBusNumber to SecondBus
396 //
397 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
398 Status = PciRootBridgeIoWrite (
399 PciRootBridgeIo,
400 &Pci,
401 EfiPciWidthUint8,
402 Address,
403 1,
404 SubBusNumber
405 );
406 //
407 // If it is PPB, resursively search down this bridge
408 //
409 if (IS_PCI_BRIDGE (&Pci)) {
410
411 Register8 = 0xFF;
412 Status = PciRootBridgeIoWrite (
413 PciRootBridgeIo,
414 &Pci,
415 EfiPciWidthUint8,
416 Address,
417 1,
418 &Register8
419 );
420
421 Status = PciAssignBusNumber (
422 Bridge,
423 (UINT8) (SecondBus),
424 SubBusNumber
425 );
426
427 if (EFI_ERROR (Status)) {
428 return EFI_DEVICE_ERROR;
429 }
430 }
431
432 //
433 // Set the current maximum bus number under the PPB
434 //
435
436 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
437
438 Status = PciRootBridgeIoWrite (
439 PciRootBridgeIo,
440 &Pci,
441 EfiPciWidthUint8,
442 Address,
443 1,
444 SubBusNumber
445 );
446
447 }
448
449 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
450
451 //
452 // Skip sub functions, this is not a multi function device
453 //
454
455 Func = PCI_MAX_FUNC;
456 }
457 }
458 }
459
460 return EFI_SUCCESS;
461 }
462
463 EFI_STATUS
464 DetermineRootBridgeAttributes (
465 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
466 IN PCI_IO_DEVICE *RootBridgeDev
467 )
468 /*++
469
470 Routine Description:
471
472 This routine is used to determine the root bridge attribute by interfacing
473 the host bridge resource allocation protocol.
474
475 Arguments:
476
477 Returns:
478
479 None
480
481 --*/
482 // TODO: PciResAlloc - add argument and description to function comment
483 // TODO: RootBridgeDev - add argument and description to function comment
484 // TODO: EFI_SUCCESS - add return value to function comment
485 {
486 UINT64 Attributes;
487 EFI_STATUS Status;
488 EFI_HANDLE RootBridgeHandle;
489
490 Attributes = 0;
491 RootBridgeHandle = RootBridgeDev->Handle;
492
493 //
494 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
495 //
496 Status = PciResAlloc->GetAllocAttributes (
497 PciResAlloc,
498 RootBridgeHandle,
499 &Attributes
500 );
501
502 if (EFI_ERROR (Status)) {
503 return Status;
504 }
505
506 //
507 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
508 // Currently we hardcoded for ea815
509 //
510
511 if (Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) {
512 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;
513 }
514
515 if (Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) {
516 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
517 }
518
519 RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
520 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
521 RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
522
523 return EFI_SUCCESS;
524 }
525
526 UINT64
527 GetMaxOptionRomSize (
528 IN PCI_IO_DEVICE *Bridge
529 )
530 /*++
531
532 Routine Description:
533
534 Get Max Option Rom size on this bridge
535
536 Arguments:
537
538 Returns:
539
540 None
541
542 --*/
543 // TODO: Bridge - add argument and description to function comment
544 {
545 LIST_ENTRY *CurrentLink;
546 PCI_IO_DEVICE *Temp;
547 UINT64 MaxOptionRomSize;
548 UINT64 TempOptionRomSize;
549
550 MaxOptionRomSize = 0;
551
552 //
553 // Go through bridges to reach all devices
554 //
555 CurrentLink = Bridge->ChildList.ForwardLink;
556 while (CurrentLink && CurrentLink != &Bridge->ChildList) {
557 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
558 if (!IsListEmpty (&Temp->ChildList)) {
559
560 //
561 // Get max option rom size under this bridge
562 //
563 TempOptionRomSize = GetMaxOptionRomSize (Temp);
564
565 //
566 // Compare with the option rom size of the bridge
567 // Get the larger one
568 //
569 if (Temp->RomSize > TempOptionRomSize) {
570 TempOptionRomSize = Temp->RomSize;
571 }
572
573 } else {
574
575 //
576 // For devices get the rom size directly
577 //
578 TempOptionRomSize = Temp->RomSize;
579 }
580
581 //
582 // Get the largest rom size on this bridge
583 //
584 if (TempOptionRomSize > MaxOptionRomSize) {
585 MaxOptionRomSize = TempOptionRomSize;
586 }
587
588 CurrentLink = CurrentLink->ForwardLink;
589 }
590
591 return MaxOptionRomSize;
592 }
593
594 EFI_STATUS
595 PciHostBridgeDeviceAttribute (
596 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
597 )
598 /*++
599
600 Routine Description:
601
602 Process attributes of devices on this host bridge
603
604 Arguments:
605
606 Returns:
607
608 None
609
610 --*/
611 // TODO: PciResAlloc - add argument and description to function comment
612 // TODO: EFI_NOT_FOUND - add return value to function comment
613 // TODO: EFI_SUCCESS - add return value to function comment
614 {
615 EFI_HANDLE RootBridgeHandle;
616 PCI_IO_DEVICE *RootBridgeDev;
617 EFI_STATUS Status;
618
619 RootBridgeHandle = NULL;
620
621 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
622
623 //
624 // Get RootBridg Device by handle
625 //
626 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
627
628 if (RootBridgeDev == NULL) {
629 return EFI_NOT_FOUND;
630 }
631
632 //
633 // Set the attributes for devcies behind the Root Bridge
634 //
635 Status = DetermineDeviceAttribute (RootBridgeDev);
636 if (EFI_ERROR (Status)) {
637 return Status;
638 }
639
640 }
641
642 return EFI_SUCCESS;
643 }
644
645 EFI_STATUS
646 GetResourceAllocationStatus (
647 VOID *AcpiConfig,
648 OUT UINT64 *IoResStatus,
649 OUT UINT64 *Mem32ResStatus,
650 OUT UINT64 *PMem32ResStatus,
651 OUT UINT64 *Mem64ResStatus,
652 OUT UINT64 *PMem64ResStatus
653 )
654 /*++
655
656 Routine Description:
657
658 Get resource allocation status from the ACPI pointer
659
660 Arguments:
661
662 Returns:
663
664 None
665
666 --*/
667 // TODO: AcpiConfig - add argument and description to function comment
668 // TODO: IoResStatus - add argument and description to function comment
669 // TODO: Mem32ResStatus - add argument and description to function comment
670 // TODO: PMem32ResStatus - add argument and description to function comment
671 // TODO: Mem64ResStatus - add argument and description to function comment
672 // TODO: PMem64ResStatus - add argument and description to function comment
673 // TODO: EFI_SUCCESS - add return value to function comment
674 {
675
676 UINT8 *Temp;
677 UINT64 ResStatus;
678 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
679
680 Temp = (UINT8 *) AcpiConfig;
681
682 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
683
684 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
685 ResStatus = ptr->AddrTranslationOffset;
686
687 switch (ptr->ResType) {
688 case 0:
689 if (ptr->AddrSpaceGranularity == 32) {
690 if (ptr->SpecificFlag == 0x06) {
691 //
692 // Pmem32
693 //
694 *PMem32ResStatus = ResStatus;
695 } else {
696 //
697 // Mem32
698 //
699 *Mem32ResStatus = ResStatus;
700 }
701 }
702
703 if (ptr->AddrSpaceGranularity == 64) {
704 if (ptr->SpecificFlag == 0x06) {
705 //
706 // PMem64
707 //
708 *PMem64ResStatus = ResStatus;
709 } else {
710 //
711 // Mem64
712 //
713 *Mem64ResStatus = ResStatus;
714 }
715 }
716
717 break;
718
719 case 1:
720 //
721 // Io
722 //
723 *IoResStatus = ResStatus;
724 break;
725
726 default:
727 break;
728 }
729
730 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
731 }
732
733 return EFI_SUCCESS;
734 }
735
736 EFI_STATUS
737 RejectPciDevice (
738 IN PCI_IO_DEVICE *PciDevice
739 )
740 /*++
741
742 Routine Description:
743
744 Remove a PCI device from device pool and mark its bar
745
746 Arguments:
747
748 Returns:
749
750 None
751
752 --*/
753 // TODO: PciDevice - add argument and description to function comment
754 // TODO: EFI_SUCCESS - add return value to function comment
755 // TODO: EFI_ABORTED - add return value to function comment
756 // TODO: EFI_SUCCESS - add return value to function comment
757 // TODO: EFI_ABORTED - add return value to function comment
758 {
759 PCI_IO_DEVICE *Bridge;
760 PCI_IO_DEVICE *Temp;
761 LIST_ENTRY *CurrentLink;
762
763 //
764 // Remove the padding resource from a bridge
765 //
766 if ( IS_PCI_BRIDGE(&PciDevice->Pci) && \
767 PciDevice->ResourcePaddingDescriptors ) {
768 gBS->FreePool (PciDevice->ResourcePaddingDescriptors);
769 PciDevice->ResourcePaddingDescriptors = NULL;
770 return EFI_SUCCESS;
771 }
772
773 //
774 // Skip RB and PPB
775 //
776 if (IS_PCI_BRIDGE (&PciDevice->Pci) || (!PciDevice->Parent)) {
777 return EFI_ABORTED;
778 }
779
780 if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
781 //
782 // Get the root bridge device
783 //
784 Bridge = PciDevice;
785 while (Bridge->Parent) {
786 Bridge = Bridge->Parent;
787 }
788
789 RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
790
791 //
792 // Mark its bar
793 //
794 InitializeP2C (PciDevice);
795 }
796
797 //
798 // Remove the device
799 //
800 Bridge = PciDevice->Parent;
801 CurrentLink = Bridge->ChildList.ForwardLink;
802 while (CurrentLink && CurrentLink != &Bridge->ChildList) {
803 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
804 if (Temp == PciDevice) {
805 InitializePciDevice (Temp);
806 RemoveEntryList (CurrentLink);
807 FreePciDevice (Temp);
808 return EFI_SUCCESS;
809 }
810
811 CurrentLink = CurrentLink->ForwardLink;
812 }
813
814 return EFI_ABORTED;
815 }
816
817 BOOLEAN
818 IsRejectiveDevice (
819 IN PCI_RESOURCE_NODE *PciResNode
820 )
821 /*++
822
823 Routine Description:
824
825 Determine whethter a PCI device can be rejected
826
827 Arguments:
828
829 Returns:
830
831 None
832
833 --*/
834 // TODO: PciResNode - add argument and description to function comment
835 {
836 PCI_IO_DEVICE *Temp;
837
838 Temp = PciResNode->PciDev;
839
840 //
841 // Ensure the device is present
842 //
843 if (!Temp) {
844 return FALSE;
845 }
846
847 //
848 // PPB and RB should go ahead
849 //
850 if (IS_PCI_BRIDGE (&Temp->Pci) || (!Temp->Parent)) {
851 return TRUE;
852 }
853
854 //
855 // Skip device on Bus0
856 //
857 if ((Temp->Parent) && (Temp->BusNumber == 0)) {
858 return FALSE;
859 }
860
861 //
862 // Skip VGA
863 //
864 if (IS_PCI_VGA (&Temp->Pci)) {
865 return FALSE;
866 }
867
868 return TRUE;
869 }
870
871 PCI_RESOURCE_NODE *
872 GetLargerConsumerDevice (
873 IN PCI_RESOURCE_NODE *PciResNode1,
874 IN PCI_RESOURCE_NODE *PciResNode2
875 )
876 /*++
877
878 Routine Description:
879
880 Get the larger resource consumer
881
882 Arguments:
883
884 Returns:
885
886 None
887
888 --*/
889 // TODO: PciResNode1 - add argument and description to function comment
890 // TODO: PciResNode2 - add argument and description to function comment
891 {
892 if (!PciResNode2) {
893 return PciResNode1;
894 }
895
896 if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || !(PciResNode2->PciDev->Parent)) \
897 && (PciResNode2->ResourceUsage != PciResUsagePadding) )
898 {
899 return PciResNode1;
900 }
901
902 if (!PciResNode1) {
903 return PciResNode2;
904 }
905
906 if ((PciResNode1->Length) > (PciResNode2->Length)) {
907 return PciResNode1;
908 }
909
910 return PciResNode2;
911
912 }
913
914 PCI_RESOURCE_NODE *
915 GetMaxResourceConsumerDevice (
916 IN PCI_RESOURCE_NODE *ResPool
917 )
918 /*++
919
920 Routine Description:
921
922 Get the max resource consumer in the host resource pool
923
924 Arguments:
925
926 Returns:
927
928 None
929
930 --*/
931 // TODO: ResPool - add argument and description to function comment
932 {
933 PCI_RESOURCE_NODE *Temp;
934 LIST_ENTRY *CurrentLink;
935 PCI_RESOURCE_NODE *PciResNode;
936 PCI_RESOURCE_NODE *PPBResNode;
937
938 PciResNode = NULL;
939
940 CurrentLink = ResPool->ChildList.ForwardLink;
941 while (CurrentLink && CurrentLink != &ResPool->ChildList) {
942
943 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
944
945 if (!IsRejectiveDevice (Temp)) {
946 CurrentLink = CurrentLink->ForwardLink;
947 continue;
948 }
949
950 if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (!Temp->PciDev->Parent)) \
951 && (Temp->ResourceUsage != PciResUsagePadding))
952 {
953 PPBResNode = GetMaxResourceConsumerDevice (Temp);
954 PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);
955 } else {
956 PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
957 }
958
959 CurrentLink = CurrentLink->ForwardLink;
960 }
961
962 return PciResNode;
963 }
964
965 EFI_STATUS
966 PciHostBridgeAdjustAllocation (
967 IN PCI_RESOURCE_NODE *IoPool,
968 IN PCI_RESOURCE_NODE *Mem32Pool,
969 IN PCI_RESOURCE_NODE *PMem32Pool,
970 IN PCI_RESOURCE_NODE *Mem64Pool,
971 IN PCI_RESOURCE_NODE *PMem64Pool,
972 IN UINT64 IoResStatus,
973 IN UINT64 Mem32ResStatus,
974 IN UINT64 PMem32ResStatus,
975 IN UINT64 Mem64ResStatus,
976 IN UINT64 PMem64ResStatus
977 )
978 /*++
979
980 Routine Description:
981
982 Adjust host bridge allocation so as to reduce resource requirement
983
984 Arguments:
985
986 Returns:
987
988 None
989
990 --*/
991 // TODO: IoPool - add argument and description to function comment
992 // TODO: Mem32Pool - add argument and description to function comment
993 // TODO: PMem32Pool - add argument and description to function comment
994 // TODO: Mem64Pool - add argument and description to function comment
995 // TODO: PMem64Pool - add argument and description to function comment
996 // TODO: IoResStatus - add argument and description to function comment
997 // TODO: Mem32ResStatus - add argument and description to function comment
998 // TODO: PMem32ResStatus - add argument and description to function comment
999 // TODO: Mem64ResStatus - add argument and description to function comment
1000 // TODO: PMem64ResStatus - add argument and description to function comment
1001 // TODO: EFI_ABORTED - add return value to function comment
1002 // TODO: EFI_SUCCESS - add return value to function comment
1003 // TODO: EFI_ABORTED - add return value to function comment
1004 {
1005 BOOLEAN AllocationAjusted;
1006 PCI_RESOURCE_NODE *PciResNode;
1007 PCI_RESOURCE_NODE *ResPool[5];
1008 PCI_IO_DEVICE *RemovedPciDev[5];
1009 UINT64 ResStatus[5];
1010 UINTN RemovedPciDevNum;
1011 UINTN DevIndex;
1012 UINTN ResType;
1013 EFI_STATUS Status;
1014 REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;
1015
1016 PciResNode = NULL;
1017 ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
1018 RemovedPciDevNum = 0;
1019
1020 ResPool[0] = IoPool;
1021 ResPool[1] = Mem32Pool;
1022 ResPool[2] = PMem32Pool;
1023 ResPool[3] = Mem64Pool;
1024 ResPool[4] = PMem64Pool;
1025
1026 ResStatus[0] = IoResStatus;
1027 ResStatus[1] = Mem32ResStatus;
1028 ResStatus[2] = PMem32ResStatus;
1029 ResStatus[3] = Mem64ResStatus;
1030 ResStatus[4] = PMem64ResStatus;
1031
1032 AllocationAjusted = FALSE;
1033
1034 for (ResType = 0; ResType < 5; ResType++) {
1035
1036 if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
1037 continue;
1038 }
1039
1040 if (ResStatus[ResType] == EFI_RESOURCE_NONEXISTENT) {
1041 //
1042 // Hostbridge hasn't this resource type
1043 //
1044 return EFI_ABORTED;
1045 }
1046
1047 //
1048 // Hostbridge hasn't enough resource
1049 //
1050 PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
1051 if (!PciResNode) {
1052 continue;
1053 }
1054
1055 //
1056 // Check if the device has been removed before
1057 //
1058 for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
1059 if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
1060 continue;
1061 }
1062 }
1063
1064 //
1065 // Remove the device if it isn't in the array
1066 //
1067 Status = RejectPciDevice (PciResNode->PciDev);
1068 if (Status == EFI_SUCCESS) {
1069
1070 //
1071 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1072 //
1073 //
1074 // Have no way to get ReqRes, AllocRes & Bar here
1075 //
1076 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
1077 AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);
1078 AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;
1079 AllocFailExtendedData.Bar = PciResNode->Bar;
1080
1081 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1082 EFI_PROGRESS_CODE,
1083 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
1084 (VOID *) &AllocFailExtendedData,
1085 sizeof (AllocFailExtendedData)
1086 );
1087
1088 //
1089 // Add it to the array and indicate at least a device has been rejected
1090 //
1091 RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
1092 AllocationAjusted = TRUE;
1093 }
1094 }
1095 //
1096 // End for
1097 //
1098
1099 if (AllocationAjusted) {
1100 return EFI_SUCCESS;
1101 } else {
1102 return EFI_ABORTED;
1103 }
1104 }
1105
1106 EFI_STATUS
1107 ConstructAcpiResourceRequestor (
1108 IN PCI_IO_DEVICE *Bridge,
1109 IN PCI_RESOURCE_NODE *IoNode,
1110 IN PCI_RESOURCE_NODE *Mem32Node,
1111 IN PCI_RESOURCE_NODE *PMem32Node,
1112 IN PCI_RESOURCE_NODE *Mem64Node,
1113 IN PCI_RESOURCE_NODE *PMem64Node,
1114 OUT VOID **pConfig
1115 )
1116 /*++
1117
1118 Routine Description:
1119
1120 Arguments:
1121
1122 Returns:
1123
1124 None
1125
1126 --*/
1127 // TODO: Bridge - add argument and description to function comment
1128 // TODO: IoNode - add argument and description to function comment
1129 // TODO: Mem32Node - add argument and description to function comment
1130 // TODO: PMem32Node - add argument and description to function comment
1131 // TODO: Mem64Node - add argument and description to function comment
1132 // TODO: PMem64Node - add argument and description to function comment
1133 // TODO: pConfig - add argument and description to function comment
1134 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1135 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1136 // TODO: EFI_SUCCESS - add return value to function comment
1137 {
1138 UINT8 NumConfig;
1139 UINT8 Aperture;
1140 UINT8 *Configuration;
1141 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1142 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
1143
1144 NumConfig = 0;
1145 Aperture = 0;
1146
1147 *pConfig = NULL;
1148
1149 //
1150 // if there is io request, add to the io aperture
1151 //
1152 if (ResourceRequestExisted (IoNode)) {
1153 NumConfig++;
1154 Aperture |= 0x01;
1155 }
1156
1157 //
1158 // if there is mem32 request, add to the mem32 aperture
1159 //
1160 if (ResourceRequestExisted (Mem32Node)) {
1161 NumConfig++;
1162 Aperture |= 0x02;
1163 }
1164
1165 //
1166 // if there is pmem32 request, add to the pmem32 aperture
1167 //
1168 if (ResourceRequestExisted (PMem32Node)) {
1169 NumConfig++;
1170 Aperture |= 0x04;
1171 }
1172
1173 //
1174 // if there is mem64 request, add to the mem64 aperture
1175 //
1176 if (ResourceRequestExisted (Mem64Node)) {
1177 NumConfig++;
1178 Aperture |= 0x08;
1179 }
1180
1181 //
1182 // if there is pmem64 request, add to the pmem64 aperture
1183 //
1184 if (ResourceRequestExisted (PMem64Node)) {
1185 NumConfig++;
1186 Aperture |= 0x10;
1187 }
1188
1189 if (NumConfig != 0) {
1190
1191 //
1192 // If there is at least one type of resource request,
1193 // allocate a acpi resource node
1194 //
1195 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1196 if (Configuration == NULL) {
1197 return EFI_OUT_OF_RESOURCES;
1198 }
1199
1200 ZeroMem (
1201 Configuration,
1202 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
1203 );
1204
1205 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1206
1207 //
1208 // Deal with io aperture
1209 //
1210 if (Aperture & 0x01) {
1211 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1212 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1213 //
1214 // Io
1215 //
1216 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1217 //
1218 // non ISA range
1219 //
1220 Ptr->SpecificFlag = 1;
1221 Ptr->AddrLen = IoNode->Length;
1222 Ptr->AddrRangeMax = IoNode->Alignment;
1223
1224 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1225 }
1226 //
1227 // Deal with mem32 aperture
1228 //
1229 if (Aperture & 0x02) {
1230 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1231 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1232 //
1233 // Mem
1234 //
1235 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1236 //
1237 // Nonprefechable
1238 //
1239 Ptr->SpecificFlag = 0;
1240 //
1241 // 32 bit
1242 //
1243 Ptr->AddrSpaceGranularity = 32;
1244 Ptr->AddrLen = Mem32Node->Length;
1245 Ptr->AddrRangeMax = Mem32Node->Alignment;
1246
1247 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1248 }
1249
1250 //
1251 // Deal with Pmem32 aperture
1252 //
1253 if (Aperture & 0x04) {
1254 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1255 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1256 //
1257 // Mem
1258 //
1259 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1260 //
1261 // prefechable
1262 //
1263 Ptr->SpecificFlag = 0x6;
1264 //
1265 // 32 bit
1266 //
1267 Ptr->AddrSpaceGranularity = 32;
1268 Ptr->AddrLen = PMem32Node->Length;
1269 Ptr->AddrRangeMax = PMem32Node->Alignment;
1270
1271 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1272 }
1273 //
1274 // Deal with mem64 aperture
1275 //
1276 if (Aperture & 0x08) {
1277 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1278 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1279 //
1280 // Mem
1281 //
1282 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1283 //
1284 // nonprefechable
1285 //
1286 Ptr->SpecificFlag = 0;
1287 //
1288 // 64 bit
1289 //
1290 Ptr->AddrSpaceGranularity = 64;
1291 Ptr->AddrLen = Mem64Node->Length;
1292 Ptr->AddrRangeMax = Mem64Node->Alignment;
1293
1294 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1295 }
1296 //
1297 // Deal with Pmem64 aperture
1298 //
1299 if (Aperture & 0x10) {
1300 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1301 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1302 //
1303 // Mem
1304 //
1305 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1306 //
1307 // prefechable
1308 //
1309 Ptr->SpecificFlag = 0x06;
1310 //
1311 // 64 bit
1312 //
1313 Ptr->AddrSpaceGranularity = 64;
1314 Ptr->AddrLen = PMem64Node->Length;
1315 Ptr->AddrRangeMax = PMem64Node->Alignment;
1316
1317 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1318 }
1319
1320 //
1321 // put the checksum
1322 //
1323 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
1324
1325 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1326 PtrEnd->Checksum = 0;
1327
1328 } else {
1329
1330 //
1331 // If there is no resource request
1332 //
1333 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1334 if (Configuration == NULL) {
1335 return EFI_OUT_OF_RESOURCES;
1336 }
1337
1338 ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1339
1340 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);
1341 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1342
1343 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
1344 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1345 PtrEnd->Checksum = 0;
1346 }
1347
1348 *pConfig = Configuration;
1349
1350 return EFI_SUCCESS;
1351 }
1352
1353 EFI_STATUS
1354 GetResourceBase (
1355 IN VOID *pConfig,
1356 OUT UINT64 *IoBase,
1357 OUT UINT64 *Mem32Base,
1358 OUT UINT64 *PMem32Base,
1359 OUT UINT64 *Mem64Base,
1360 OUT UINT64 *PMem64Base
1361 )
1362 /*++
1363
1364 Routine Description:
1365
1366 Arguments:
1367
1368 Returns:
1369
1370 None
1371
1372 --*/
1373 // TODO: pConfig - add argument and description to function comment
1374 // TODO: IoBase - add argument and description to function comment
1375 // TODO: Mem32Base - add argument and description to function comment
1376 // TODO: PMem32Base - add argument and description to function comment
1377 // TODO: Mem64Base - add argument and description to function comment
1378 // TODO: PMem64Base - add argument and description to function comment
1379 // TODO: EFI_SUCCESS - add return value to function comment
1380 {
1381 UINT8 *Temp;
1382 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1383 UINT64 ResStatus;
1384
1385 *IoBase = 0xFFFFFFFFFFFFFFFFULL;
1386 *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;
1387 *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
1388 *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;
1389 *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
1390
1391 Temp = (UINT8 *) pConfig;
1392
1393 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1394
1395 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1396 ResStatus = Ptr->AddrTranslationOffset;
1397
1398 if (ResStatus == EFI_RESOURCE_SATISFIED) {
1399
1400 switch (Ptr->ResType) {
1401
1402 //
1403 // Memory type aperture
1404 //
1405 case 0:
1406
1407 //
1408 // Check to see the granularity
1409 //
1410 if (Ptr->AddrSpaceGranularity == 32) {
1411 if (Ptr->SpecificFlag & 0x06) {
1412 *PMem32Base = Ptr->AddrRangeMin;
1413 } else {
1414 *Mem32Base = Ptr->AddrRangeMin;
1415 }
1416 }
1417
1418 if (Ptr->AddrSpaceGranularity == 64) {
1419 if (Ptr->SpecificFlag & 0x06) {
1420 *PMem64Base = Ptr->AddrRangeMin;
1421 } else {
1422 *Mem64Base = Ptr->AddrRangeMin;
1423 }
1424 }
1425 break;
1426
1427 case 1:
1428
1429 //
1430 // Io type aperture
1431 //
1432 *IoBase = Ptr->AddrRangeMin;
1433 break;
1434
1435 default:
1436 break;
1437
1438 }
1439 //
1440 // End switch
1441 //
1442 }
1443 //
1444 // End for
1445 //
1446 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1447 }
1448
1449 return EFI_SUCCESS;
1450 }
1451
1452 EFI_STATUS
1453 PciBridgeEnumerator (
1454 IN PCI_IO_DEVICE *BridgeDev
1455 )
1456 /*++
1457
1458 Routine Description:
1459
1460 Arguments:
1461
1462 Returns:
1463
1464 None
1465
1466 --*/
1467 // TODO: BridgeDev - add argument and description to function comment
1468 // TODO: EFI_SUCCESS - add return value to function comment
1469 {
1470 UINT8 SubBusNumber;
1471 UINT8 StartBusNumber;
1472 EFI_PCI_IO_PROTOCOL *PciIo;
1473 EFI_STATUS Status;
1474
1475 SubBusNumber = 0;
1476 StartBusNumber = 0;
1477 PciIo = &(BridgeDev->PciIo);
1478 Status = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
1479
1480 if (EFI_ERROR (Status)) {
1481 return Status;
1482 }
1483
1484 Status = PciAssignBusNumber (
1485 BridgeDev,
1486 StartBusNumber,
1487 &SubBusNumber
1488 );
1489
1490 if (EFI_ERROR (Status)) {
1491 return Status;
1492 }
1493
1494 Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
1495
1496 if (EFI_ERROR (Status)) {
1497 return Status;
1498 }
1499
1500 Status = PciBridgeResourceAllocator (BridgeDev);
1501
1502 if (EFI_ERROR (Status)) {
1503 return Status;
1504 }
1505
1506 Status = DetermineDeviceAttribute (BridgeDev);
1507
1508 if (EFI_ERROR (Status)) {
1509 return Status;
1510 }
1511
1512 return EFI_SUCCESS;
1513
1514 }
1515
1516 EFI_STATUS
1517 PciBridgeResourceAllocator (
1518 IN PCI_IO_DEVICE *Bridge
1519 )
1520 /*++
1521
1522 Routine Description:
1523
1524 Arguments:
1525
1526 Returns:
1527
1528 None
1529
1530 --*/
1531 // TODO: Bridge - add argument and description to function comment
1532 // TODO: EFI_SUCCESS - add return value to function comment
1533 {
1534 PCI_RESOURCE_NODE *IoBridge;
1535 PCI_RESOURCE_NODE *Mem32Bridge;
1536 PCI_RESOURCE_NODE *PMem32Bridge;
1537 PCI_RESOURCE_NODE *Mem64Bridge;
1538 PCI_RESOURCE_NODE *PMem64Bridge;
1539 UINT64 IoBase;
1540 UINT64 Mem32Base;
1541 UINT64 PMem32Base;
1542 UINT64 Mem64Base;
1543 UINT64 PMem64Base;
1544 EFI_STATUS Status;
1545
1546 IoBridge = CreateResourceNode (
1547 Bridge,
1548 0,
1549 0xFFF,
1550 0,
1551 PciBarTypeIo16,
1552 PciResUsageTypical
1553 );
1554
1555 Mem32Bridge = CreateResourceNode (
1556 Bridge,
1557 0,
1558 0xFFFFF,
1559 0,
1560 PciBarTypeMem32,
1561 PciResUsageTypical
1562 );
1563
1564 PMem32Bridge = CreateResourceNode (
1565 Bridge,
1566 0,
1567 0xFFFFF,
1568 0,
1569 PciBarTypePMem32,
1570 PciResUsageTypical
1571 );
1572
1573 Mem64Bridge = CreateResourceNode (
1574 Bridge,
1575 0,
1576 0xFFFFF,
1577 0,
1578 PciBarTypeMem64,
1579 PciResUsageTypical
1580 );
1581
1582 PMem64Bridge = CreateResourceNode (
1583 Bridge,
1584 0,
1585 0xFFFFF,
1586 0,
1587 PciBarTypePMem64,
1588 PciResUsageTypical
1589 );
1590
1591 //
1592 // Create resourcemap by going through all the devices subject to this root bridge
1593 //
1594 Status = CreateResourceMap (
1595 Bridge,
1596 IoBridge,
1597 Mem32Bridge,
1598 PMem32Bridge,
1599 Mem64Bridge,
1600 PMem64Bridge
1601 );
1602
1603 if (EFI_ERROR (Status)) {
1604 return Status;
1605 }
1606
1607 Status = GetResourceBaseFromBridge (
1608 Bridge,
1609 &IoBase,
1610 &Mem32Base,
1611 &PMem32Base,
1612 &Mem64Base,
1613 &PMem64Base
1614 );
1615
1616 if (EFI_ERROR (Status)) {
1617 return Status;
1618 }
1619
1620 //
1621 // Program IO resources
1622 //
1623 ProgramResource (
1624 IoBase,
1625 IoBridge
1626 );
1627
1628 //
1629 // Program Mem32 resources
1630 //
1631 ProgramResource (
1632 Mem32Base,
1633 Mem32Bridge
1634 );
1635
1636 //
1637 // Program PMem32 resources
1638 //
1639 ProgramResource (
1640 PMem32Base,
1641 PMem32Bridge
1642 );
1643
1644 //
1645 // Program Mem64 resources
1646 //
1647 ProgramResource (
1648 Mem64Base,
1649 Mem64Bridge
1650 );
1651
1652 //
1653 // Program PMem64 resources
1654 //
1655 ProgramResource (
1656 PMem64Base,
1657 PMem64Bridge
1658 );
1659
1660 DestroyResourceTree (IoBridge);
1661 DestroyResourceTree (Mem32Bridge);
1662 DestroyResourceTree (PMem32Bridge);
1663 DestroyResourceTree (PMem64Bridge);
1664 DestroyResourceTree (Mem64Bridge);
1665
1666 gBS->FreePool (IoBridge);
1667 gBS->FreePool (Mem32Bridge);
1668 gBS->FreePool (PMem32Bridge);
1669 gBS->FreePool (PMem64Bridge);
1670 gBS->FreePool (Mem64Bridge);
1671
1672 return EFI_SUCCESS;
1673 }
1674
1675 EFI_STATUS
1676 GetResourceBaseFromBridge (
1677 IN PCI_IO_DEVICE *Bridge,
1678 OUT UINT64 *IoBase,
1679 OUT UINT64 *Mem32Base,
1680 OUT UINT64 *PMem32Base,
1681 OUT UINT64 *Mem64Base,
1682 OUT UINT64 *PMem64Base
1683 )
1684 /*++
1685
1686 Routine Description:
1687
1688 Arguments:
1689
1690 Returns:
1691
1692 None
1693
1694 --*/
1695 // TODO: Bridge - add argument and description to function comment
1696 // TODO: IoBase - add argument and description to function comment
1697 // TODO: Mem32Base - add argument and description to function comment
1698 // TODO: PMem32Base - add argument and description to function comment
1699 // TODO: Mem64Base - add argument and description to function comment
1700 // TODO: PMem64Base - add argument and description to function comment
1701 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1702 // TODO: EFI_SUCCESS - add return value to function comment
1703 {
1704 if (!Bridge->Allocated) {
1705 return EFI_OUT_OF_RESOURCES;
1706 }
1707
1708 *IoBase = gAllOne;
1709 *Mem32Base = gAllOne;
1710 *PMem32Base = gAllOne;
1711 *Mem64Base = gAllOne;
1712 *PMem64Base = gAllOne;
1713
1714 if (IS_PCI_BRIDGE (&Bridge->Pci)) {
1715
1716 if (Bridge->PciBar[PPB_IO_RANGE].Length) {
1717 *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
1718 }
1719
1720 if (Bridge->PciBar[PPB_MEM32_RANGE].Length) {
1721 *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
1722 }
1723
1724 if (Bridge->PciBar[PPB_PMEM32_RANGE].Length) {
1725 *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
1726 }
1727
1728 if (Bridge->PciBar[PPB_PMEM64_RANGE].Length) {
1729 *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
1730 } else {
1731 *PMem64Base = gAllOne;
1732 }
1733
1734 }
1735
1736 if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
1737 if (Bridge->PciBar[P2C_IO_1].Length) {
1738 *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
1739 } else {
1740 if (Bridge->PciBar[P2C_IO_2].Length) {
1741 *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
1742 }
1743 }
1744
1745 if (Bridge->PciBar[P2C_MEM_1].Length) {
1746 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
1747 *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1748 }
1749
1750 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
1751 *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1752 }
1753 }
1754
1755 if (Bridge->PciBar[P2C_MEM_2].Length) {
1756 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
1757 *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1758 }
1759
1760 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
1761 *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1762 }
1763 }
1764 }
1765
1766 return EFI_SUCCESS;
1767 }
1768
1769 EFI_STATUS
1770 NotifyPhase (
1771 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
1772 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1773 )
1774 /*++
1775
1776 Routine Description:
1777
1778 Arguments:
1779
1780 Returns:
1781
1782 None
1783
1784 --*/
1785 // TODO: PciResAlloc - add argument and description to function comment
1786 // TODO: Phase - add argument and description to function comment
1787 // TODO: EFI_NOT_FOUND - add return value to function comment
1788 // TODO: EFI_SUCCESS - add return value to function comment
1789 {
1790 EFI_HANDLE HostBridgeHandle;
1791 EFI_HANDLE RootBridgeHandle;
1792 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1793 EFI_STATUS Status;
1794
1795 HostBridgeHandle = NULL;
1796 RootBridgeHandle = NULL;
1797 if (gPciPlatformProtocol != NULL) {
1798 //
1799 // Get Host Bridge Handle.
1800 //
1801 PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
1802
1803 //
1804 // Get the rootbridge Io protocol to find the host bridge handle
1805 //
1806 Status = gBS->HandleProtocol (
1807 RootBridgeHandle,
1808 &gEfiPciRootBridgeIoProtocolGuid,
1809 (VOID **) &PciRootBridgeIo
1810 );
1811
1812 if (EFI_ERROR (Status)) {
1813 return EFI_NOT_FOUND;
1814 }
1815
1816 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
1817
1818 //
1819 // Call PlatformPci::PhaseNotify() if the protocol is present.
1820 //
1821 gPciPlatformProtocol->PhaseNotify (
1822 gPciPlatformProtocol,
1823 HostBridgeHandle,
1824 Phase,
1825 ChipsetEntry
1826 );
1827 }
1828
1829 Status = PciResAlloc->NotifyPhase (
1830 PciResAlloc,
1831 Phase
1832 );
1833
1834 if (gPciPlatformProtocol != NULL) {
1835 //
1836 // Call PlatformPci::PhaseNotify() if the protocol is present.
1837 //
1838 gPciPlatformProtocol->PhaseNotify (
1839 gPciPlatformProtocol,
1840 HostBridgeHandle,
1841 Phase,
1842 ChipsetExit
1843 );
1844
1845 }
1846
1847 return EFI_SUCCESS;
1848 }
1849
1850 EFI_STATUS
1851 PreprocessController (
1852 IN PCI_IO_DEVICE *Bridge,
1853 IN UINT8 Bus,
1854 IN UINT8 Device,
1855 IN UINT8 Func,
1856 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1857 )
1858 /*++
1859
1860 Routine Description:
1861
1862 Arguments:
1863
1864 Returns:
1865
1866 None
1867
1868 --*/
1869 // TODO: Bridge - add argument and description to function comment
1870 // TODO: Bus - add argument and description to function comment
1871 // TODO: Device - add argument and description to function comment
1872 // TODO: Func - add argument and description to function comment
1873 // TODO: Phase - add argument and description to function comment
1874 // TODO: EFI_UNSUPPORTED - add return value to function comment
1875 // TODO: EFI_SUCCESS - add return value to function comment
1876 {
1877 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;
1878 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
1879 EFI_HANDLE RootBridgeHandle;
1880 EFI_HANDLE HostBridgeHandle;
1881 EFI_STATUS Status;
1882
1883 //
1884 // Get the host bridge handle
1885 //
1886 HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
1887
1888 //
1889 // Get the pci host bridge resource allocation protocol
1890 //
1891 Status = gBS->OpenProtocol (
1892 HostBridgeHandle,
1893 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
1894 (VOID **) &PciResAlloc,
1895 NULL,
1896 NULL,
1897 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1898 );
1899
1900 if (EFI_ERROR (Status)) {
1901 return EFI_UNSUPPORTED;
1902 }
1903
1904 //
1905 // Get Root Brige Handle
1906 //
1907 while (Bridge->Parent) {
1908 Bridge = Bridge->Parent;
1909 }
1910
1911 RootBridgeHandle = Bridge->Handle;
1912
1913 RootBridgePciAddress.Register = 0;
1914 RootBridgePciAddress.Function = Func;
1915 RootBridgePciAddress.Device = Device;
1916 RootBridgePciAddress.Bus = Bus;
1917 RootBridgePciAddress.ExtendedRegister = 0;
1918
1919 if (gPciPlatformProtocol != NULL) {
1920 //
1921 // Call PlatformPci::PrepController() if the protocol is present.
1922 //
1923 gPciPlatformProtocol->PlatformPrepController (
1924 gPciPlatformProtocol,
1925 HostBridgeHandle,
1926 RootBridgeHandle,
1927 RootBridgePciAddress,
1928 Phase,
1929 ChipsetEntry
1930 );
1931 }
1932
1933 Status = PciResAlloc->PreprocessController (
1934 PciResAlloc,
1935 RootBridgeHandle,
1936 RootBridgePciAddress,
1937 Phase
1938 );
1939
1940 if (gPciPlatformProtocol != NULL) {
1941 //
1942 // Call PlatformPci::PrepController() if the protocol is present.
1943 //
1944 gPciPlatformProtocol->PlatformPrepController (
1945 gPciPlatformProtocol,
1946 HostBridgeHandle,
1947 RootBridgeHandle,
1948 RootBridgePciAddress,
1949 Phase,
1950 ChipsetExit
1951 );
1952 }
1953
1954 return EFI_SUCCESS;
1955 }
1956
1957 EFI_STATUS
1958 EFIAPI
1959 PciHotPlugRequestNotify (
1960 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
1961 IN EFI_PCI_HOTPLUG_OPERATION Operation,
1962 IN EFI_HANDLE Controller,
1963 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,
1964 IN OUT UINT8 *NumberOfChildren,
1965 IN OUT EFI_HANDLE * ChildHandleBuffer
1966 )
1967 /*++
1968
1969 Routine Description:
1970
1971 Hot plug request notify.
1972
1973 Arguments:
1974
1975 This - A pointer to the hot plug request protocol.
1976 Operation - The operation.
1977 Controller - A pointer to the controller.
1978 RemainningDevicePath - A pointer to the device path.
1979 NumberOfChildren - A the number of child handle in the ChildHandleBuffer.
1980 ChildHandleBuffer - A pointer to the array contain the child handle.
1981
1982 Returns:
1983
1984 Status code.
1985
1986 --*/
1987 // TODO: RemainingDevicePath - add argument and description to function comment
1988 // TODO: EFI_NOT_FOUND - add return value to function comment
1989 // TODO: EFI_SUCCESS - add return value to function comment
1990 // TODO: EFI_SUCCESS - add return value to function comment
1991 // TODO: EFI_SUCCESS - add return value to function comment
1992 {
1993 PCI_IO_DEVICE *Bridge;
1994 PCI_IO_DEVICE *Temp;
1995 EFI_PCI_IO_PROTOCOL *PciIo;
1996 UINTN Index;
1997 EFI_HANDLE RootBridgeHandle;
1998 EFI_STATUS Status;
1999
2000 Status = gBS->OpenProtocol (
2001 Controller,
2002 &gEfiPciIoProtocolGuid,
2003 (VOID **) &PciIo,
2004 gPciBusDriverBinding.DriverBindingHandle,
2005 Controller,
2006 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2007 );
2008
2009 if (EFI_ERROR (Status)) {
2010 return EFI_NOT_FOUND;
2011 }
2012
2013 Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
2014
2015 //
2016 // Get root bridge handle
2017 //
2018 Temp = Bridge;
2019 while (Temp->Parent) {
2020 Temp = Temp->Parent;
2021 }
2022
2023 RootBridgeHandle = Temp->Handle;
2024
2025 if (Operation == EfiPciHotPlugRequestAdd) {
2026
2027 if (NumberOfChildren != NULL) {
2028 *NumberOfChildren = 0;
2029 }
2030
2031 if (IsListEmpty (&Bridge->ChildList)) {
2032
2033 Status = PciBridgeEnumerator (Bridge);
2034
2035 if (EFI_ERROR (Status)) {
2036 return Status;
2037 }
2038 }
2039
2040 Status = StartPciDevicesOnBridge (
2041 RootBridgeHandle,
2042 Bridge,
2043 RemainingDevicePath,
2044 NumberOfChildren,
2045 ChildHandleBuffer
2046 );
2047
2048 return EFI_SUCCESS;
2049 }
2050
2051 if (Operation == EfiPciHotplugRequestRemove) {
2052
2053 if (*NumberOfChildren == 0) {
2054 //
2055 // Remove all devices on the bridge
2056 //
2057 Status = RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
2058 return Status;
2059
2060 }
2061
2062 for (Index = 0; Index < *NumberOfChildren; Index++) {
2063 //
2064 // De register all the pci device
2065 //
2066 Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
2067
2068 if (EFI_ERROR (Status)) {
2069 return Status;
2070 }
2071
2072 }
2073 //
2074 // End for
2075 //
2076 return EFI_SUCCESS;
2077 }
2078
2079 return EFI_SUCCESS;
2080 }
2081
2082 BOOLEAN
2083 SearchHostBridgeHandle (
2084 IN EFI_HANDLE RootBridgeHandle
2085 )
2086 /*++
2087
2088 Routine Description:
2089
2090 Arguments:
2091
2092 Returns:
2093
2094 None
2095
2096 --*/
2097 // TODO: RootBridgeHandle - add argument and description to function comment
2098 {
2099 EFI_HANDLE HostBridgeHandle;
2100 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2101 UINTN Index;
2102 EFI_STATUS Status;
2103
2104 //
2105 // Get the rootbridge Io protocol to find the host bridge handle
2106 //
2107 Status = gBS->OpenProtocol (
2108 RootBridgeHandle,
2109 &gEfiPciRootBridgeIoProtocolGuid,
2110 (VOID **) &PciRootBridgeIo,
2111 gPciBusDriverBinding.DriverBindingHandle,
2112 RootBridgeHandle,
2113 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2114 );
2115
2116 if (EFI_ERROR (Status)) {
2117 return FALSE;
2118 }
2119
2120 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
2121 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2122 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2123 return TRUE;
2124 }
2125 }
2126
2127 return FALSE;
2128 }
2129
2130 EFI_STATUS
2131 AddHostBridgeEnumerator (
2132 IN EFI_HANDLE HostBridgeHandle
2133 )
2134 /*++
2135
2136 Routine Description:
2137
2138 Arguments:
2139
2140 Returns:
2141
2142 None
2143
2144 --*/
2145 // TODO: HostBridgeHandle - add argument and description to function comment
2146 // TODO: EFI_ABORTED - add return value to function comment
2147 // TODO: EFI_ABORTED - add return value to function comment
2148 // TODO: EFI_SUCCESS - add return value to function comment
2149 {
2150 UINTN Index;
2151
2152 if (!HostBridgeHandle) {
2153 return EFI_ABORTED;
2154 }
2155
2156 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2157 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2158 return EFI_ABORTED;
2159 }
2160 }
2161
2162 if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
2163 gPciHostBrigeHandles[Index] = HostBridgeHandle;
2164 gPciHostBridgeNumber++;
2165 }
2166
2167 return EFI_SUCCESS;
2168 }