11a0c2921070aa30cdee9692806246fef2124516
[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 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 Handle = NULL;
53 *Status = gBS->InstallProtocolInterface (
54 &Handle,
55 &gEfiPciHotPlugRequestProtocolGuid,
56 EFI_NATIVE_INTERFACE,
57 &gPciHotPlugRequest
58 );
59 }
60
61 VOID
62 InstallPciHotplugGuid (
63 IN PCI_IO_DEVICE *PciIoDevice
64 )
65 /*++
66
67 Routine Description:
68
69 Arguments:
70
71 PciIoDevice - A pointer to the PCI_IO_DEVICE.
72
73 Returns:
74
75 None
76
77 --*/
78 {
79 EFI_STATUS Status;
80
81 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Parent->Pci)) {
82
83 Status = gBS->InstallProtocolInterface (
84 &PciIoDevice->Handle,
85 &gEfiPciHotplugDeviceGuid,
86 EFI_NATIVE_INTERFACE,
87 NULL
88 );
89 }
90 }
91
92 VOID
93 UninstallPciHotplugGuid (
94 IN PCI_IO_DEVICE *PciIoDevice
95 )
96 /*++
97
98 Routine Description:
99
100 Arguments:
101
102 PciIoDevice - A pointer to the PCI_IO_DEVICE.
103
104 Returns:
105
106 None
107
108 --*/
109 {
110 EFI_STATUS Status;
111
112 Status = gBS->OpenProtocol (
113 PciIoDevice->Handle,
114 &gEfiPciHotplugDeviceGuid,
115 NULL,
116 NULL,
117 NULL,
118 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
119 );
120
121 if (Status == EFI_SUCCESS) {
122 //
123 // This may triger CardBus driver to stop for
124 // Pccard devices opened the GUID via BY_DRIVER
125 //
126 Status = gBS->UninstallProtocolInterface (
127 PciIoDevice->Handle,
128 &gEfiPciHotplugDeviceGuid,
129 NULL
130 );
131 }
132 }
133
134 VOID
135 GetBackPcCardBar (
136 IN PCI_IO_DEVICE *PciIoDevice
137 )
138 /*++
139
140 Routine Description:
141
142
143 Arguments:
144
145 PciIoDevice - A pointer to the PCI_IO_DEVICE.
146
147 Returns:
148
149 None
150
151 --*/
152 {
153 UINT32 Address;
154
155 //
156 // Read PciBar information from the bar register
157 //
158 if (!gFullEnumeration) {
159
160 Address = 0;
161 PciIoDevice->PciIo.Pci.Read (
162 &(PciIoDevice->PciIo),
163 EfiPciIoWidthUint32,
164 0x1c,
165 1,
166 &Address
167 );
168
169 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);
170 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;
171 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;
172
173 Address = 0;
174 PciIoDevice->PciIo.Pci.Read (
175 &(PciIoDevice->PciIo),
176 EfiPciIoWidthUint32,
177 0x20,
178 1,
179 &Address
180 );
181 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);
182 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;
183 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;
184
185 Address = 0;
186 PciIoDevice->PciIo.Pci.Read (
187 &(PciIoDevice->PciIo),
188 EfiPciIoWidthUint32,
189 0x2c,
190 1,
191 &Address
192 );
193 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);
194 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;
195 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;
196
197 Address = 0;
198 PciIoDevice->PciIo.Pci.Read (
199 &(PciIoDevice->PciIo),
200 EfiPciIoWidthUint32,
201 0x34,
202 1,
203 &Address
204 );
205 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);
206 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;
207 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;
208
209 }
210
211 if (gPciHotPlugInit != NULL) {
212 GetResourcePaddingForHpb (PciIoDevice);
213 }
214 }
215
216 EFI_STATUS
217 RemoveRejectedPciDevices (
218 EFI_HANDLE RootBridgeHandle,
219 IN PCI_IO_DEVICE *Bridge
220 )
221 /*++
222
223 Routine Description:
224
225
226 Arguments:
227
228 RootBridgeHandle - An efi handle.
229 Bridge - An pointer to the PCI_IO_DEVICE.
230
231 Returns:
232
233 None
234
235 --*/
236 // TODO: EFI_SUCCESS - add return value to function comment
237 {
238 PCI_IO_DEVICE *Temp;
239 LIST_ENTRY *CurrentLink;
240 LIST_ENTRY *LastLink;
241
242 CurrentLink = Bridge->ChildList.ForwardLink;
243
244 while (CurrentLink && CurrentLink != &Bridge->ChildList) {
245
246 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
247
248 if (IS_PCI_BRIDGE (&Temp->Pci)) {
249 //
250 // Remove rejected devices recusively
251 //
252 RemoveRejectedPciDevices (RootBridgeHandle, Temp);
253 } else {
254 //
255 // Skip rejection for all PPBs, while detect rejection for others
256 //
257 if (IsPciDeviceRejected (Temp)) {
258
259 //
260 // For P2C, remove all devices on it
261 //
262
263 if (!IsListEmpty (&Temp->ChildList)) {
264 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
265 }
266
267 //
268 // Finally remove itself
269 //
270
271 LastLink = CurrentLink->BackLink;
272 RemoveEntryList (CurrentLink);
273 FreePciDevice (Temp);
274
275 CurrentLink = LastLink;
276 }
277 }
278
279 CurrentLink = CurrentLink->ForwardLink;
280 }
281
282 return EFI_SUCCESS;
283 }
284
285 EFI_STATUS
286 PciHostBridgeResourceAllocator (
287 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
288 )
289 /*++
290
291 Routine Description:
292
293 Host brige resource allocator.
294
295 Arguments:
296
297 PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
298
299 Returns:
300
301 EFI Status.
302
303 --*/
304 // TODO: EFI_NOT_FOUND - add return value to function comment
305 // TODO: EFI_NOT_FOUND - add return value to function comment
306 // TODO: EFI_NOT_FOUND - add return value to function comment
307 // TODO: EFI_SUCCESS - add return value to function comment
308 {
309 PCI_IO_DEVICE *RootBridgeDev;
310 EFI_HANDLE RootBridgeHandle;
311 VOID *AcpiConfig;
312 EFI_STATUS Status;
313 UINT64 IoBase;
314 UINT64 Mem32Base;
315 UINT64 PMem32Base;
316 UINT64 Mem64Base;
317 UINT64 PMem64Base;
318 UINT64 IoResStatus;
319 UINT64 Mem32ResStatus;
320 UINT64 PMem32ResStatus;
321 UINT64 Mem64ResStatus;
322 UINT64 PMem64ResStatus;
323 UINT64 MaxOptionRomSize;
324 PCI_RESOURCE_NODE *IoBridge;
325 PCI_RESOURCE_NODE *Mem32Bridge;
326 PCI_RESOURCE_NODE *PMem32Bridge;
327 PCI_RESOURCE_NODE *Mem64Bridge;
328 PCI_RESOURCE_NODE *PMem64Bridge;
329 PCI_RESOURCE_NODE IoPool;
330 PCI_RESOURCE_NODE Mem32Pool;
331 PCI_RESOURCE_NODE PMem32Pool;
332 PCI_RESOURCE_NODE Mem64Pool;
333 PCI_RESOURCE_NODE PMem64Pool;
334 BOOLEAN ReAllocate;
335 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA HandleExtendedData;
336 REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;
337
338 //
339 // Reallocate flag
340 //
341 ReAllocate = FALSE;
342
343 //
344 // It will try several times if the resource allocation fails
345 //
346 while (TRUE) {
347
348 //
349 // Initialize resource pool
350 //
351 InitializeResourcePool (&IoPool, PciBarTypeIo16);
352 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
353 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
354 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
355 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
356
357 RootBridgeDev = NULL;
358 RootBridgeHandle = 0;
359
360 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
361
362 //
363 // Get RootBridg Device by handle
364 //
365 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
366
367 if (RootBridgeDev == NULL) {
368 return EFI_NOT_FOUND;
369 }
370
371 //
372 // Create the entire system resource map from the information collected by
373 // enumerator. Several resource tree was created
374 //
375
376 IoBridge = CreateResourceNode (
377 RootBridgeDev,
378 0,
379 0xFFF,
380 0,
381 PciBarTypeIo16,
382 PciResUsageTypical
383 );
384
385 Mem32Bridge = CreateResourceNode (
386 RootBridgeDev,
387 0,
388 0xFFFFF,
389 0,
390 PciBarTypeMem32,
391 PciResUsageTypical
392 );
393
394 PMem32Bridge = CreateResourceNode (
395 RootBridgeDev,
396 0,
397 0xFFFFF,
398 0,
399 PciBarTypePMem32,
400 PciResUsageTypical
401 );
402
403 Mem64Bridge = CreateResourceNode (
404 RootBridgeDev,
405 0,
406 0xFFFFF,
407 0,
408 PciBarTypeMem64,
409 PciResUsageTypical
410 );
411
412 PMem64Bridge = CreateResourceNode (
413 RootBridgeDev,
414 0,
415 0xFFFFF,
416 0,
417 PciBarTypePMem64,
418 PciResUsageTypical
419 );
420
421 //
422 // Create resourcemap by going through all the devices subject to this root bridge
423 //
424 Status = CreateResourceMap (
425 RootBridgeDev,
426 IoBridge,
427 Mem32Bridge,
428 PMem32Bridge,
429 Mem64Bridge,
430 PMem64Bridge
431 );
432
433 //
434 // Get the max ROM size that the root bridge can process
435 //
436 RootBridgeDev->RomSize = Mem32Bridge->Length;
437
438 //
439 // Skip to enlarge the resource request during realloction
440 //
441 if (!ReAllocate) {
442 //
443 // Get Max Option Rom size for current root bridge
444 //
445 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
446
447 //
448 // Enlarger the mem32 resource to accomdate the option rom
449 // if the mem32 resource is not enough to hold the rom
450 //
451 if (MaxOptionRomSize > Mem32Bridge->Length) {
452
453 Mem32Bridge->Length = MaxOptionRomSize;
454 RootBridgeDev->RomSize = MaxOptionRomSize;
455
456 //
457 // Alignment should be adjusted as well
458 //
459 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
460 Mem32Bridge->Alignment = MaxOptionRomSize - 1;
461 }
462 }
463 }
464
465 //
466 // Based on the all the resource tree, contruct ACPI resource node to
467 // submit the resource aperture to pci host bridge protocol
468 //
469 Status = ConstructAcpiResourceRequestor (
470 RootBridgeDev,
471 IoBridge,
472 Mem32Bridge,
473 PMem32Bridge,
474 Mem64Bridge,
475 PMem64Bridge,
476 &AcpiConfig
477 );
478
479 //
480 // Insert these resource nodes into the database
481 //
482 InsertResourceNode (&IoPool, IoBridge);
483 InsertResourceNode (&Mem32Pool, Mem32Bridge);
484 InsertResourceNode (&PMem32Pool, PMem32Bridge);
485 InsertResourceNode (&Mem64Pool, Mem64Bridge);
486 InsertResourceNode (&PMem64Pool, PMem64Bridge);
487
488 if (Status == EFI_SUCCESS) {
489 //
490 // Submit the resource requirement
491 //
492 Status = PciResAlloc->SubmitResources (
493 PciResAlloc,
494 RootBridgeDev->Handle,
495 AcpiConfig
496 );
497 }
498
499 //
500 // Free acpi resource node
501 //
502 if (AcpiConfig != NULL) {
503 gBS->FreePool (AcpiConfig);
504 }
505
506 if (EFI_ERROR (Status)) {
507 //
508 // Destroy all the resource tree
509 //
510 DestroyResourceTree (&IoPool);
511 DestroyResourceTree (&Mem32Pool);
512 DestroyResourceTree (&PMem32Pool);
513 DestroyResourceTree (&Mem64Pool);
514 DestroyResourceTree (&PMem64Pool);
515 return Status;
516 }
517 }
518
519 //
520 // Notify pci bus driver starts to program the resource
521 //
522
523 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
524
525 if (!EFI_ERROR (Status)) {
526 //
527 // Allocation succeed, then continue the following
528 //
529 break;
530 }
531
532 //
533 // If the resource allocation is unsuccessful, free resources on bridge
534 //
535
536 RootBridgeDev = NULL;
537 RootBridgeHandle = 0;
538
539 IoResStatus = EFI_RESOURCE_SATISFIED;
540 Mem32ResStatus = EFI_RESOURCE_SATISFIED;
541 PMem32ResStatus = EFI_RESOURCE_SATISFIED;
542 Mem64ResStatus = EFI_RESOURCE_SATISFIED;
543 PMem64ResStatus = EFI_RESOURCE_SATISFIED;
544
545 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
546 //
547 // Get RootBridg Device by handle
548 //
549 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
550 if (RootBridgeDev == NULL) {
551 return EFI_NOT_FOUND;
552 }
553
554 //
555 // Get host bridge handle for status report
556 //
557 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
558
559 //
560 // Get acpi resource node for all the resource types
561 //
562 AcpiConfig = NULL;
563
564 Status = PciResAlloc->GetProposedResources (
565 PciResAlloc,
566 RootBridgeDev->Handle,
567 &AcpiConfig
568 );
569
570 if (EFI_ERROR (Status)) {
571 return Status;
572 }
573
574 if (AcpiConfig != NULL) {
575 //
576 // Adjust resource allocation policy for each RB
577 //
578 GetResourceAllocationStatus (
579 AcpiConfig,
580 &IoResStatus,
581 &Mem32ResStatus,
582 &PMem32ResStatus,
583 &Mem64ResStatus,
584 &PMem64ResStatus
585 );
586 gBS->FreePool (AcpiConfig);
587 }
588 }
589 //
590 // End while
591 //
592
593 //
594 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
595 //
596 //
597 // It is very difficult to follow the spec here
598 // Device path , Bar index can not be get here
599 //
600 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
601
602 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
603 EFI_PROGRESS_CODE,
604 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
605 (VOID *) &AllocFailExtendedData,
606 sizeof (AllocFailExtendedData)
607 );
608
609 Status = PciHostBridgeAdjustAllocation (
610 &IoPool,
611 &Mem32Pool,
612 &PMem32Pool,
613 &Mem64Pool,
614 &PMem64Pool,
615 IoResStatus,
616 Mem32ResStatus,
617 PMem32ResStatus,
618 Mem64ResStatus,
619 PMem64ResStatus
620 );
621
622 //
623 // Destroy all the resource tree
624 //
625 DestroyResourceTree (&IoPool);
626 DestroyResourceTree (&Mem32Pool);
627 DestroyResourceTree (&PMem32Pool);
628 DestroyResourceTree (&Mem64Pool);
629 DestroyResourceTree (&PMem64Pool);
630
631 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
632
633 if (EFI_ERROR (Status)) {
634 return Status;
635 }
636
637 ReAllocate = TRUE;
638
639 }
640 //
641 // End main while
642 //
643
644 //
645 // Raise the EFI_IOB_PCI_RES_ALLOC status code
646 //
647 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
648 EFI_PROGRESS_CODE,
649 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
650 (VOID *) &HandleExtendedData,
651 sizeof (HandleExtendedData)
652 );
653
654 //
655 // Notify pci bus driver starts to program the resource
656 //
657 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
658
659 RootBridgeDev = NULL;
660
661 RootBridgeHandle = 0;
662
663 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
664
665 //
666 // Get RootBridg Device by handle
667 //
668 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
669
670 if (RootBridgeDev == NULL) {
671 return EFI_NOT_FOUND;
672 }
673
674 //
675 // Get acpi resource node for all the resource types
676 //
677 AcpiConfig = NULL;
678 Status = PciResAlloc->GetProposedResources (
679 PciResAlloc,
680 RootBridgeDev->Handle,
681 &AcpiConfig
682 );
683
684 if (EFI_ERROR (Status)) {
685 return Status;
686 }
687
688 //
689 // Get the resource base by interpreting acpi resource node
690 //
691 //
692 GetResourceBase (
693 AcpiConfig,
694 &IoBase,
695 &Mem32Base,
696 &PMem32Base,
697 &Mem64Base,
698 &PMem64Base
699 );
700
701 //
702 // Process option rom for this root bridge
703 //
704 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
705
706 //
707 // Create the entire system resource map from the information collected by
708 // enumerator. Several resource tree was created
709 //
710 Status = GetResourceMap (
711 RootBridgeDev,
712 &IoBridge,
713 &Mem32Bridge,
714 &PMem32Bridge,
715 &Mem64Bridge,
716 &PMem64Bridge,
717 &IoPool,
718 &Mem32Pool,
719 &PMem32Pool,
720 &Mem64Pool,
721 &PMem64Pool
722 );
723
724 if (EFI_ERROR (Status)) {
725 return Status;
726 }
727
728 //
729 // Program IO resources
730 //
731 ProgramResource (
732 IoBase,
733 IoBridge
734 );
735
736 //
737 // Program Mem32 resources
738 //
739 ProgramResource (
740 Mem32Base,
741 Mem32Bridge
742 );
743
744 //
745 // Program PMem32 resources
746 //
747 ProgramResource (
748 PMem32Base,
749 PMem32Bridge
750 );
751
752 //
753 // Program Mem64 resources
754 //
755 ProgramResource (
756 Mem64Base,
757 Mem64Bridge
758 );
759
760 //
761 // Program PMem64 resources
762 //
763 ProgramResource (
764 PMem64Base,
765 PMem64Bridge
766 );
767
768 if (AcpiConfig != NULL) {
769 gBS->FreePool (AcpiConfig);
770 }
771 }
772
773 //
774 // Destroy all the resource tree
775 //
776 DestroyResourceTree (&IoPool);
777 DestroyResourceTree (&Mem32Pool);
778 DestroyResourceTree (&PMem32Pool);
779 DestroyResourceTree (&Mem64Pool);
780 DestroyResourceTree (&PMem64Pool);
781
782 //
783 // Notify the resource allocation phase is to end
784 //
785 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
786
787 return EFI_SUCCESS;
788 }
789
790 EFI_STATUS
791 PciScanBus (
792 IN PCI_IO_DEVICE *Bridge,
793 IN UINT8 StartBusNumber,
794 OUT UINT8 *SubBusNumber,
795 OUT UINT8 *PaddedBusRange
796 )
797 /*++
798
799 Routine Description:
800
801 This routine is used to assign bus number to the given PCI bus system
802
803 Arguments:
804
805 Bridge - A pointer to the PCI_IO_DEVICE structure.
806 StartBusNumber - The start bus number.
807 SubBusNumber - A pointer to the sub bus number.
808 PaddedBusRange - A pointer to the padded bus range.
809
810 Returns:
811
812 None
813
814 --*/
815 // TODO: EFI_DEVICE_ERROR - add return value to function comment
816 // TODO: EFI_SUCCESS - add return value to function comment
817 {
818 EFI_STATUS Status;
819 PCI_TYPE00 Pci;
820 UINT8 Device;
821 UINT8 Func;
822 UINT64 Address;
823 UINTN SecondBus;
824 UINT16 Register;
825 UINTN HpIndex;
826 PCI_IO_DEVICE *PciDevice;
827 EFI_EVENT Event;
828 EFI_HPC_STATE State;
829 UINT64 PciAddress;
830 EFI_HPC_PADDING_ATTRIBUTES Attributes;
831 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
832 UINT16 BusRange;
833 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
834 BOOLEAN BusPadding;
835
836 PciRootBridgeIo = Bridge->PciRootBridgeIo;
837 SecondBus = 0;
838 Register = 0;
839 State = 0;
840 Attributes = 0;
841 BusRange = 0;
842
843 ResetAllPpbBusReg (Bridge, StartBusNumber);
844
845 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
846 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
847
848 //
849 // Check to see whether a pci device is present
850 //
851 Status = PciDevicePresent (
852 PciRootBridgeIo,
853 &Pci,
854 StartBusNumber,
855 Device,
856 Func
857 );
858
859 if (EFI_ERROR (Status)) {
860 if (Func == 0) {
861 //
862 // Skip sub functions, this is not a multi function device
863 //
864 Func = PCI_MAX_FUNC;
865 }
866
867 continue;
868 }
869
870 //
871 // Get the PCI device information
872 //
873 Status = PciSearchDevice (
874 Bridge,
875 &Pci,
876 StartBusNumber,
877 Device,
878 Func,
879 &PciDevice
880 );
881
882 ASSERT (!EFI_ERROR (Status));
883
884 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
885
886 if (!IS_PCI_BRIDGE (&Pci)) {
887 //
888 // PCI bridges will be called later
889 // Here just need for PCI device or PCI to cardbus controller
890 // EfiPciBeforeChildBusEnumeration for PCI Device Node
891 //
892 PreprocessController (
893 PciDevice,
894 PciDevice->BusNumber,
895 PciDevice->DeviceNumber,
896 PciDevice->FunctionNumber,
897 EfiPciBeforeChildBusEnumeration
898 );
899 }
900
901 //
902 // For Pci Hotplug controller devcie only
903 //
904 if (gPciHotPlugInit != NULL) {
905 //
906 // Check if it is a Hotplug PCI controller
907 //
908 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
909
910 if (!gPciRootHpcData[HpIndex].Initialized) {
911
912 Status = CreateEventForHpc (HpIndex, &Event);
913
914 ASSERT (!EFI_ERROR (Status));
915
916 Status = gPciHotPlugInit->InitializeRootHpc (
917 gPciHotPlugInit,
918 gPciRootHpcPool[HpIndex].HpcDevicePath,
919 PciAddress,
920 Event,
921 &State
922 );
923
924 PreprocessController (
925 PciDevice,
926 PciDevice->BusNumber,
927 PciDevice->DeviceNumber,
928 PciDevice->FunctionNumber,
929 EfiPciBeforeChildBusEnumeration
930 );
931 continue;
932 }
933 }
934 }
935
936 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
937 //
938 // For PPB
939 // Get the bridge information
940 //
941 BusPadding = FALSE;
942 if (gPciHotPlugInit != NULL) {
943
944 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {
945
946 //
947 // If it is initialized, get the padded bus range
948 //
949 Status = gPciHotPlugInit->GetResourcePadding (
950 gPciHotPlugInit,
951 gPciRootHpcPool[HpIndex].HpbDevicePath,
952 PciAddress,
953 &State,
954 (VOID **) &Descriptors,
955 &Attributes
956 );
957
958 if (EFI_ERROR (Status)) {
959 return Status;
960 }
961
962 BusRange = 0;
963 Status = PciGetBusRange (
964 &Descriptors,
965 NULL,
966 NULL,
967 &BusRange
968 );
969
970 gBS->FreePool (Descriptors);
971
972 if (EFI_ERROR (Status)) {
973 return Status;
974 }
975
976 BusPadding = TRUE;
977 }
978 }
979
980 (*SubBusNumber)++;
981 SecondBus = *SubBusNumber;
982
983 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
984 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
985
986 Status = PciRootBridgeIo->Pci.Write (
987 PciRootBridgeIo,
988 EfiPciWidthUint16,
989 Address,
990 1,
991 &Register
992 );
993
994
995 //
996 // If it is PPB, resursively search down this bridge
997 //
998 if (IS_PCI_BRIDGE (&Pci)) {
999
1000 //
1001 // Initialize SubBusNumber to Maximum bus number
1002 //
1003 Register = 0xFF;
1004 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1005 Status = PciRootBridgeIo->Pci.Write (
1006 PciRootBridgeIo,
1007 EfiPciWidthUint8,
1008 Address,
1009 1,
1010 &Register
1011 );
1012
1013 //
1014 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1015 //
1016 PreprocessController (
1017 PciDevice,
1018 PciDevice->BusNumber,
1019 PciDevice->DeviceNumber,
1020 PciDevice->FunctionNumber,
1021 EfiPciBeforeChildBusEnumeration
1022 );
1023
1024 Status = PciScanBus (
1025 PciDevice,
1026 (UINT8) (SecondBus),
1027 SubBusNumber,
1028 PaddedBusRange
1029 );
1030
1031 if (EFI_ERROR (Status)) {
1032 return EFI_DEVICE_ERROR;
1033 }
1034 }
1035
1036 if (BusPadding) {
1037 //
1038 // Ensure the device is enabled and initialized
1039 //
1040 if ((Attributes == EfiPaddingPciRootBridge) &&
1041 (State & EFI_HPC_STATE_ENABLED) &&
1042 (State & EFI_HPC_STATE_INITIALIZED) ) {
1043 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);
1044 } else {
1045 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);
1046 }
1047 }
1048
1049 //
1050 // Set the current maximum bus number under the PPB
1051 //
1052 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1053
1054 Status = PciRootBridgeIo->Pci.Write (
1055 PciRootBridgeIo,
1056 EfiPciWidthUint8,
1057 Address,
1058 1,
1059 SubBusNumber
1060 );
1061 }
1062
1063 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1064
1065 //
1066 // Skip sub functions, this is not a multi function device
1067 //
1068 Func = PCI_MAX_FUNC;
1069 }
1070
1071 }
1072 }
1073
1074 return EFI_SUCCESS;
1075 }
1076
1077 EFI_STATUS
1078 PciRootBridgeP2CProcess (
1079 IN PCI_IO_DEVICE *Bridge
1080 )
1081 /*++
1082
1083 Routine Description:
1084
1085 Process Option Rom on this host bridge
1086
1087 Arguments:
1088
1089 Returns:
1090
1091 None
1092
1093 --*/
1094 // TODO: Bridge - add argument and description to function comment
1095 // TODO: EFI_SUCCESS - add return value to function comment
1096 {
1097 LIST_ENTRY *CurrentLink;
1098 PCI_IO_DEVICE *Temp;
1099 EFI_HPC_STATE State;
1100 UINT64 PciAddress;
1101 EFI_STATUS Status;
1102
1103 CurrentLink = Bridge->ChildList.ForwardLink;
1104
1105 while (CurrentLink && CurrentLink != &Bridge->ChildList) {
1106
1107 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1108
1109 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
1110
1111 if (gPciHotPlugInit && Temp->Allocated) {
1112
1113 //
1114 // Raise the EFI_IOB_PCI_HPC_INIT status code
1115 //
1116 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1117 EFI_PROGRESS_CODE,
1118 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,
1119 Temp->DevicePath
1120 );
1121
1122 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
1123 Status = gPciHotPlugInit->InitializeRootHpc (
1124 gPciHotPlugInit,
1125 Temp->DevicePath,
1126 PciAddress,
1127 NULL,
1128 &State
1129 );
1130
1131 if (!EFI_ERROR (Status)) {
1132 Status = PciBridgeEnumerator (Temp);
1133
1134 if (EFI_ERROR (Status)) {
1135 return Status;
1136 }
1137 }
1138
1139 CurrentLink = CurrentLink->ForwardLink;
1140 continue;
1141
1142 }
1143 }
1144
1145 if (!IsListEmpty (&Temp->ChildList)) {
1146 Status = PciRootBridgeP2CProcess (Temp);
1147 }
1148
1149 CurrentLink = CurrentLink->ForwardLink;
1150 }
1151
1152 return EFI_SUCCESS;
1153 }
1154
1155 EFI_STATUS
1156 PciHostBridgeP2CProcess (
1157 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1158 )
1159 /*++
1160
1161 Routine Description:
1162
1163 Arguments:
1164
1165 Returns:
1166
1167 None
1168
1169 --*/
1170 // TODO: PciResAlloc - add argument and description to function comment
1171 // TODO: EFI_NOT_FOUND - add return value to function comment
1172 // TODO: EFI_SUCCESS - add return value to function comment
1173 {
1174 EFI_HANDLE RootBridgeHandle;
1175 PCI_IO_DEVICE *RootBridgeDev;
1176 EFI_STATUS Status;
1177
1178 RootBridgeHandle = NULL;
1179
1180 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1181
1182 //
1183 // Get RootBridg Device by handle
1184 //
1185 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1186
1187 if (RootBridgeDev == NULL) {
1188 return EFI_NOT_FOUND;
1189 }
1190
1191 Status = PciRootBridgeP2CProcess (RootBridgeDev);
1192
1193 if (EFI_ERROR (Status)) {
1194 return Status;
1195 }
1196
1197 }
1198
1199 return EFI_SUCCESS;
1200 }
1201
1202 EFI_STATUS
1203 PciHostBridgeEnumerator (
1204 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1205 )
1206 /*++
1207
1208 Routine Description:
1209
1210 This function is used to enumerate the entire host bridge
1211 in a given platform
1212
1213 Arguments:
1214
1215 PciResAlloc - A pointer to the resource allocate protocol.
1216
1217 Returns:
1218
1219 None
1220
1221 --*/
1222 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1223 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1224 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1225 // TODO: EFI_SUCCESS - add return value to function comment
1226 {
1227 EFI_HANDLE RootBridgeHandle;
1228 PCI_IO_DEVICE *RootBridgeDev;
1229 EFI_STATUS Status;
1230 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1231 UINT16 MinBus;
1232 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1233
1234 InitializeHotPlugSupport ();
1235
1236 //
1237 // Notify the bus allocation phase is about to start
1238 //
1239 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1240
1241 RootBridgeHandle = NULL;
1242 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1243
1244 //
1245 // if a root bridge instance is found, create root bridge device for it
1246 //
1247
1248 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1249
1250 if (RootBridgeDev == NULL) {
1251 return EFI_OUT_OF_RESOURCES;
1252 }
1253
1254 //
1255 // Enumerate all the buses under this root bridge
1256 //
1257
1258 Status = PciRootBridgeEnumerator (
1259 PciResAlloc,
1260 RootBridgeDev
1261 );
1262
1263 if (EFI_ERROR (Status)) {
1264 return Status;
1265 }
1266
1267 DestroyRootBridge (RootBridgeDev);
1268
1269 //
1270 // Error proccess here
1271 //
1272 }
1273
1274 //
1275 // Notify the bus allocation phase is finished for the first time
1276 //
1277 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1278
1279
1280 if (gPciHotPlugInit != NULL) {
1281 //
1282 // Wait for all HPC initialized
1283 //
1284 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
1285
1286 if (EFI_ERROR (Status)) {
1287 return Status;
1288 }
1289
1290 //
1291 // Notify the bus allocation phase is about to start for the 2nd time
1292 //
1293 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1294
1295 RootBridgeHandle = NULL;
1296 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1297
1298 //
1299 // if a root bridge instance is found, create root bridge device for it
1300 //
1301
1302 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1303
1304 if (RootBridgeDev == NULL) {
1305 return EFI_OUT_OF_RESOURCES;
1306 }
1307
1308 //
1309 // Enumerate all the buses under this root bridge
1310 //
1311
1312 Status = PciRootBridgeEnumerator (
1313 PciResAlloc,
1314 RootBridgeDev
1315 );
1316
1317 DestroyRootBridge (RootBridgeDev);
1318 if (EFI_ERROR (Status)) {
1319 return Status;
1320 }
1321 }
1322
1323 //
1324 // Notify the bus allocation phase is to end
1325 //
1326 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1327 }
1328
1329 //
1330 // Notify the resource allocation phase is to start
1331 //
1332 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
1333
1334 RootBridgeHandle = NULL;
1335 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1336
1337 //
1338 // if a root bridge instance is found, create root bridge device for it
1339 //
1340
1341 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1342
1343 if (RootBridgeDev == NULL) {
1344 return EFI_OUT_OF_RESOURCES;
1345 }
1346
1347 Status = StartManagingRootBridge (RootBridgeDev);
1348
1349 if (EFI_ERROR (Status)) {
1350 return Status;
1351 }
1352
1353 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
1354 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1355
1356 if (EFI_ERROR (Status)) {
1357 return Status;
1358 }
1359
1360 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
1361
1362 if (EFI_ERROR (Status)) {
1363 return Status;
1364 }
1365
1366 //
1367 // Determine root bridge attribute by calling interface of Pcihostbridge
1368 // protocol
1369 //
1370 DetermineRootBridgeAttributes (
1371 PciResAlloc,
1372 RootBridgeDev
1373 );
1374
1375 //
1376 // Collect all the resource information under this root bridge
1377 // A database that records all the information about pci device subject to this
1378 // root bridge will then be created
1379 //
1380 Status = PciPciDeviceInfoCollector (
1381 RootBridgeDev,
1382 (UINT8) MinBus
1383 );
1384
1385 if (EFI_ERROR (Status)) {
1386 return Status;
1387 }
1388
1389 InsertRootBridge (RootBridgeDev);
1390
1391 //
1392 // Record the hostbridge handle
1393 //
1394 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
1395 }
1396
1397 return EFI_SUCCESS;
1398 }