]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciLib.c
fixed ECC and Klocwork issues.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciLib.c
1 /** @file
2
3 PCI Bus Driver Lib file
4 It abstracts some functions that can be different
5 between light PCI bus driver and full PCI bus driver
6
7 Copyright (c) 2006 - 2008, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include "PciBus.h"
19
20 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest = {
21 PciHotPlugRequestNotify
22 };
23
24 /**
25 Install protocol gEfiPciHotPlugRequestProtocolGuid
26 @param Status return status of protocol installation.
27 **/
28 VOID
29 InstallHotPlugRequestProtocol (
30 IN EFI_STATUS *Status
31 )
32 {
33 EFI_HANDLE Handle;
34
35 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
36 return;
37 }
38
39 Handle = NULL;
40 *Status = gBS->InstallProtocolInterface (
41 &Handle,
42 &gEfiPciHotPlugRequestProtocolGuid,
43 EFI_NATIVE_INTERFACE,
44 &gPciHotPlugRequest
45 );
46 }
47
48 /**
49 Retrieve the BAR information via PciIo interface.
50
51 @param PciIoDevice Pci device instance.
52 **/
53 VOID
54 GetBackPcCardBar (
55 IN PCI_IO_DEVICE *PciIoDevice
56 )
57 {
58 UINT32 Address;
59
60 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
61 return;
62 }
63
64 //
65 // Read PciBar information from the bar register
66 //
67 if (!gFullEnumeration) {
68
69 Address = 0;
70 PciIoRead (
71 &(PciIoDevice->PciIo),
72 EfiPciIoWidthUint32,
73 0x1c,
74 1,
75 &Address
76 );
77
78 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);
79 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;
80 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;
81
82 Address = 0;
83 PciIoRead (
84 &(PciIoDevice->PciIo),
85 EfiPciIoWidthUint32,
86 0x20,
87 1,
88 &Address
89 );
90 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);
91 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;
92 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;
93
94 Address = 0;
95 PciIoRead (
96 &(PciIoDevice->PciIo),
97 EfiPciIoWidthUint32,
98 0x2c,
99 1,
100 &Address
101 );
102 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);
103 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;
104 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;
105
106 Address = 0;
107 PciIoRead (
108 &(PciIoDevice->PciIo),
109 EfiPciIoWidthUint32,
110 0x34,
111 1,
112 &Address
113 );
114 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);
115 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;
116 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;
117
118 }
119
120 if (gPciHotPlugInit != NULL) {
121 GetResourcePaddingForHpb (PciIoDevice);
122 }
123 }
124
125 /**
126 Remove rejected pci device from specific root bridge
127 handle.
128
129 @param RootBridgeHandle specific parent root bridge handle.
130 @param Bridge Bridge device instance.
131
132 @retval EFI_SUCCESS Success operation.
133 **/
134 EFI_STATUS
135 RemoveRejectedPciDevices (
136 EFI_HANDLE RootBridgeHandle,
137 IN PCI_IO_DEVICE *Bridge
138 )
139 {
140 PCI_IO_DEVICE *Temp;
141 LIST_ENTRY *CurrentLink;
142 LIST_ENTRY *LastLink;
143
144 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
145 return EFI_SUCCESS;
146 }
147
148 CurrentLink = Bridge->ChildList.ForwardLink;
149
150 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
151
152 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
153
154 if (IS_PCI_BRIDGE (&Temp->Pci)) {
155 //
156 // Remove rejected devices recusively
157 //
158 RemoveRejectedPciDevices (RootBridgeHandle, Temp);
159 } else {
160 //
161 // Skip rejection for all PPBs, while detect rejection for others
162 //
163 if (IsPciDeviceRejected (Temp)) {
164
165 //
166 // For P2C, remove all devices on it
167 //
168
169 if (!IsListEmpty (&Temp->ChildList)) {
170 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
171 }
172
173 //
174 // Finally remove itself
175 //
176
177 LastLink = CurrentLink->BackLink;
178 RemoveEntryList (CurrentLink);
179 FreePciDevice (Temp);
180
181 CurrentLink = LastLink;
182 }
183 }
184
185 CurrentLink = CurrentLink->ForwardLink;
186 }
187
188 return EFI_SUCCESS;
189 }
190
191 /**
192 Wrapper function for allocating resource for pci host bridge.
193
194 @param PciResAlloc Point to protocol instance EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
195
196 **/
197 EFI_STATUS
198 PciHostBridgeResourceAllocator (
199 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
200 )
201 {
202 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
203 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
204 PciResAlloc
205 );
206 } else {
207 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
208 PciResAlloc
209 );
210 }
211 }
212
213 /**
214 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
215
216 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
217
218 @retval EFI_SUCCESS Success.
219 **/
220 EFI_STATUS
221 PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
222 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
223 )
224 {
225 PCI_IO_DEVICE *RootBridgeDev;
226 EFI_HANDLE RootBridgeHandle;
227 VOID *AcpiConfig;
228 EFI_STATUS Status;
229 UINT64 IoBase;
230 UINT64 Mem32Base;
231 UINT64 PMem32Base;
232 UINT64 Mem64Base;
233 UINT64 PMem64Base;
234 UINT64 MaxOptionRomSize;
235 PCI_RESOURCE_NODE *IoBridge;
236 PCI_RESOURCE_NODE *Mem32Bridge;
237 PCI_RESOURCE_NODE *PMem32Bridge;
238 PCI_RESOURCE_NODE *Mem64Bridge;
239 PCI_RESOURCE_NODE *PMem64Bridge;
240 PCI_RESOURCE_NODE IoPool;
241 PCI_RESOURCE_NODE Mem32Pool;
242 PCI_RESOURCE_NODE PMem32Pool;
243 PCI_RESOURCE_NODE Mem64Pool;
244 PCI_RESOURCE_NODE PMem64Pool;
245 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD ExtendedData;
246
247 //
248 // Initialize resource pool
249 //
250
251 InitializeResourcePool (&IoPool, PciBarTypeIo16);
252 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
253 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
254 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
255 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
256
257 RootBridgeDev = NULL;
258 RootBridgeHandle = 0;
259
260 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
261 //
262 // Get RootBridg Device by handle
263 //
264 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
265
266 if (RootBridgeDev == NULL) {
267 return EFI_NOT_FOUND;
268 }
269
270 //
271 // Get host bridge handle for status report
272 //
273 ExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
274
275 //
276 // Create the entire system resource map from the information collected by
277 // enumerator. Several resource tree was created
278 //
279
280 IoBridge = CreateResourceNode (
281 RootBridgeDev,
282 0,
283 0xFFF,
284 0,
285 PciBarTypeIo16,
286 PciResUsageTypical
287 );
288
289 Mem32Bridge = CreateResourceNode (
290 RootBridgeDev,
291 0,
292 0xFFFFF,
293 0,
294 PciBarTypeMem32,
295 PciResUsageTypical
296 );
297
298 PMem32Bridge = CreateResourceNode (
299 RootBridgeDev,
300 0,
301 0xFFFFF,
302 0,
303 PciBarTypePMem32,
304 PciResUsageTypical
305 );
306
307 Mem64Bridge = CreateResourceNode (
308 RootBridgeDev,
309 0,
310 0xFFFFF,
311 0,
312 PciBarTypeMem64,
313 PciResUsageTypical
314 );
315
316 PMem64Bridge = CreateResourceNode (
317 RootBridgeDev,
318 0,
319 0xFFFFF,
320 0,
321 PciBarTypePMem64,
322 PciResUsageTypical
323 );
324
325 //
326 // Create resourcemap by going through all the devices subject to this root bridge
327 //
328 Status = CreateResourceMap (
329 RootBridgeDev,
330 IoBridge,
331 Mem32Bridge,
332 PMem32Bridge,
333 Mem64Bridge,
334 PMem64Bridge
335 );
336
337 //
338 // Get the max ROM size that the root bridge can process
339 //
340 RootBridgeDev->RomSize = Mem32Bridge->Length;
341
342 //
343 // Get Max Option Rom size for current root bridge
344 //
345 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
346
347 //
348 // Enlarger the mem32 resource to accomdate the option rom
349 // if the mem32 resource is not enough to hold the rom
350 //
351 if (MaxOptionRomSize > Mem32Bridge->Length) {
352
353 Mem32Bridge->Length = MaxOptionRomSize;
354 RootBridgeDev->RomSize = MaxOptionRomSize;
355
356 //
357 // Alignment should be adjusted as well
358 //
359 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
360 Mem32Bridge->Alignment = MaxOptionRomSize - 1;
361 }
362 }
363
364 //
365 // Based on the all the resource tree, contruct ACPI resource node to
366 // submit the resource aperture to pci host bridge protocol
367 //
368 Status = ConstructAcpiResourceRequestor (
369 RootBridgeDev,
370 IoBridge,
371 Mem32Bridge,
372 PMem32Bridge,
373 Mem64Bridge,
374 PMem64Bridge,
375 &AcpiConfig
376 );
377
378 //
379 // Insert these resource nodes into the database
380 //
381 InsertResourceNode (&IoPool, IoBridge);
382 InsertResourceNode (&Mem32Pool, Mem32Bridge);
383 InsertResourceNode (&PMem32Pool, PMem32Bridge);
384 InsertResourceNode (&Mem64Pool, Mem64Bridge);
385 InsertResourceNode (&PMem64Pool, PMem64Bridge);
386
387 if (Status == EFI_SUCCESS) {
388 //
389 // Submit the resource requirement
390 //
391 Status = PciResAlloc->SubmitResources (
392 PciResAlloc,
393 RootBridgeDev->Handle,
394 AcpiConfig
395 );
396 }
397 //
398 // Free acpi resource node
399 //
400 if (AcpiConfig != NULL) {
401 FreePool (AcpiConfig);
402 }
403
404 if (EFI_ERROR (Status)) {
405 //
406 // Destroy all the resource tree
407 //
408 DestroyResourceTree (&IoPool);
409 DestroyResourceTree (&Mem32Pool);
410 DestroyResourceTree (&PMem32Pool);
411 DestroyResourceTree (&Mem64Pool);
412 DestroyResourceTree (&PMem64Pool);
413 return Status;
414 }
415 }
416 //
417 // End while
418 //
419
420 //
421 // Notify pci bus driver starts to program the resource
422 //
423 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
424
425 if (EFI_ERROR (Status)) {
426 //
427 // Allocation failed, then return
428 //
429 return EFI_OUT_OF_RESOURCES;
430 }
431 //
432 // Raise the EFI_IOB_PCI_RES_ALLOC status code
433 //
434 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
435 EFI_PROGRESS_CODE,
436 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
437 (VOID *) &ExtendedData,
438 sizeof (ExtendedData)
439 );
440
441 //
442 // Notify pci bus driver starts to program the resource
443 //
444 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
445
446 RootBridgeDev = NULL;
447
448 RootBridgeHandle = 0;
449
450 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
451 //
452 // Get RootBridg Device by handle
453 //
454 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
455
456 if (RootBridgeDev == NULL) {
457 return EFI_NOT_FOUND;
458 }
459
460 //
461 // Get acpi resource node for all the resource types
462 //
463 AcpiConfig = NULL;
464 Status = PciResAlloc->GetProposedResources (
465 PciResAlloc,
466 RootBridgeDev->Handle,
467 &AcpiConfig
468 );
469 if (EFI_ERROR (Status)) {
470 return Status;
471 }
472
473 //
474 // Get the resource base by interpreting acpi resource node
475 //
476 //
477 GetResourceBase (
478 AcpiConfig,
479 &IoBase,
480 &Mem32Base,
481 &PMem32Base,
482 &Mem64Base,
483 &PMem64Base
484 );
485
486 //
487 // Process option rom for this root bridge
488 //
489 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
490
491 //
492 // Create the entire system resource map from the information collected by
493 // enumerator. Several resource tree was created
494 //
495 Status = GetResourceMap (
496 RootBridgeDev,
497 &IoBridge,
498 &Mem32Bridge,
499 &PMem32Bridge,
500 &Mem64Bridge,
501 &PMem64Bridge,
502 &IoPool,
503 &Mem32Pool,
504 &PMem32Pool,
505 &Mem64Pool,
506 &PMem64Pool
507 );
508
509 if (EFI_ERROR (Status)) {
510 return Status;
511 }
512
513 //
514 // Program IO resources
515 //
516 ProgramResource (
517 IoBase,
518 IoBridge
519 );
520
521 //
522 // Program Mem32 resources
523 //
524 ProgramResource (
525 Mem32Base,
526 Mem32Bridge
527 );
528
529 //
530 // Program PMem32 resources
531 //
532 ProgramResource (
533 PMem32Base,
534 PMem32Bridge
535 );
536
537 //
538 // Program Mem64 resources
539 //
540 ProgramResource (
541 Mem64Base,
542 Mem64Bridge
543 );
544
545 //
546 // Program PMem64 resources
547 //
548 ProgramResource (
549 PMem64Base,
550 PMem64Bridge
551 );
552
553 FreePool (AcpiConfig);
554 }
555
556 //
557 // Destroy all the resource tree
558 //
559 DestroyResourceTree (&IoPool);
560 DestroyResourceTree (&Mem32Pool);
561 DestroyResourceTree (&PMem32Pool);
562 DestroyResourceTree (&Mem64Pool);
563 DestroyResourceTree (&PMem64Pool);
564
565 //
566 // Notify the resource allocation phase is to end
567 //
568 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
569
570 return EFI_SUCCESS;
571 }
572
573 /**
574 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
575
576 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
577
578 @retval EFI_SUCCESS Success.
579 **/
580 EFI_STATUS
581 PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
582 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
583 )
584 {
585 PCI_IO_DEVICE *RootBridgeDev;
586 EFI_HANDLE RootBridgeHandle;
587 VOID *AcpiConfig;
588 EFI_STATUS Status;
589 UINT64 IoBase;
590 UINT64 Mem32Base;
591 UINT64 PMem32Base;
592 UINT64 Mem64Base;
593 UINT64 PMem64Base;
594 UINT64 IoResStatus;
595 UINT64 Mem32ResStatus;
596 UINT64 PMem32ResStatus;
597 UINT64 Mem64ResStatus;
598 UINT64 PMem64ResStatus;
599 UINT64 MaxOptionRomSize;
600 PCI_RESOURCE_NODE *IoBridge;
601 PCI_RESOURCE_NODE *Mem32Bridge;
602 PCI_RESOURCE_NODE *PMem32Bridge;
603 PCI_RESOURCE_NODE *Mem64Bridge;
604 PCI_RESOURCE_NODE *PMem64Bridge;
605 PCI_RESOURCE_NODE IoPool;
606 PCI_RESOURCE_NODE Mem32Pool;
607 PCI_RESOURCE_NODE PMem32Pool;
608 PCI_RESOURCE_NODE Mem64Pool;
609 PCI_RESOURCE_NODE PMem64Pool;
610 BOOLEAN ReAllocate;
611 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;
612 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;
613
614 //
615 // Reallocate flag
616 //
617 ReAllocate = FALSE;
618
619 //
620 // It will try several times if the resource allocation fails
621 //
622 while (TRUE) {
623
624 //
625 // Initialize resource pool
626 //
627 InitializeResourcePool (&IoPool, PciBarTypeIo16);
628 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
629 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
630 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
631 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
632
633 RootBridgeDev = NULL;
634 RootBridgeHandle = 0;
635
636 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
637
638 //
639 // Get RootBridg Device by handle
640 //
641 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
642
643 if (RootBridgeDev == NULL) {
644 return EFI_NOT_FOUND;
645 }
646
647 //
648 // Create the entire system resource map from the information collected by
649 // enumerator. Several resource tree was created
650 //
651
652 IoBridge = CreateResourceNode (
653 RootBridgeDev,
654 0,
655 0xFFF,
656 0,
657 PciBarTypeIo16,
658 PciResUsageTypical
659 );
660
661 Mem32Bridge = CreateResourceNode (
662 RootBridgeDev,
663 0,
664 0xFFFFF,
665 0,
666 PciBarTypeMem32,
667 PciResUsageTypical
668 );
669
670 PMem32Bridge = CreateResourceNode (
671 RootBridgeDev,
672 0,
673 0xFFFFF,
674 0,
675 PciBarTypePMem32,
676 PciResUsageTypical
677 );
678
679 Mem64Bridge = CreateResourceNode (
680 RootBridgeDev,
681 0,
682 0xFFFFF,
683 0,
684 PciBarTypeMem64,
685 PciResUsageTypical
686 );
687
688 PMem64Bridge = CreateResourceNode (
689 RootBridgeDev,
690 0,
691 0xFFFFF,
692 0,
693 PciBarTypePMem64,
694 PciResUsageTypical
695 );
696
697 //
698 // Create resourcemap by going through all the devices subject to this root bridge
699 //
700 Status = CreateResourceMap (
701 RootBridgeDev,
702 IoBridge,
703 Mem32Bridge,
704 PMem32Bridge,
705 Mem64Bridge,
706 PMem64Bridge
707 );
708
709 //
710 // Get the max ROM size that the root bridge can process
711 //
712 RootBridgeDev->RomSize = Mem32Bridge->Length;
713
714 //
715 // Skip to enlarge the resource request during realloction
716 //
717 if (!ReAllocate) {
718 //
719 // Get Max Option Rom size for current root bridge
720 //
721 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
722
723 //
724 // Enlarger the mem32 resource to accomdate the option rom
725 // if the mem32 resource is not enough to hold the rom
726 //
727 if (MaxOptionRomSize > Mem32Bridge->Length) {
728
729 Mem32Bridge->Length = MaxOptionRomSize;
730 RootBridgeDev->RomSize = MaxOptionRomSize;
731
732 //
733 // Alignment should be adjusted as well
734 //
735 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
736 Mem32Bridge->Alignment = MaxOptionRomSize - 1;
737 }
738 }
739 }
740
741 //
742 // Based on the all the resource tree, contruct ACPI resource node to
743 // submit the resource aperture to pci host bridge protocol
744 //
745 Status = ConstructAcpiResourceRequestor (
746 RootBridgeDev,
747 IoBridge,
748 Mem32Bridge,
749 PMem32Bridge,
750 Mem64Bridge,
751 PMem64Bridge,
752 &AcpiConfig
753 );
754
755 //
756 // Insert these resource nodes into the database
757 //
758 InsertResourceNode (&IoPool, IoBridge);
759 InsertResourceNode (&Mem32Pool, Mem32Bridge);
760 InsertResourceNode (&PMem32Pool, PMem32Bridge);
761 InsertResourceNode (&Mem64Pool, Mem64Bridge);
762 InsertResourceNode (&PMem64Pool, PMem64Bridge);
763
764 if (Status == EFI_SUCCESS) {
765 //
766 // Submit the resource requirement
767 //
768 Status = PciResAlloc->SubmitResources (
769 PciResAlloc,
770 RootBridgeDev->Handle,
771 AcpiConfig
772 );
773 }
774
775 //
776 // Free acpi resource node
777 //
778 if (AcpiConfig != NULL) {
779 FreePool (AcpiConfig);
780 }
781
782 if (EFI_ERROR (Status)) {
783 //
784 // Destroy all the resource tree
785 //
786 DestroyResourceTree (&IoPool);
787 DestroyResourceTree (&Mem32Pool);
788 DestroyResourceTree (&PMem32Pool);
789 DestroyResourceTree (&Mem64Pool);
790 DestroyResourceTree (&PMem64Pool);
791 return Status;
792 }
793 }
794
795 //
796 // Notify pci bus driver starts to program the resource
797 //
798
799 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
800
801 if (!EFI_ERROR (Status)) {
802 //
803 // Allocation succeed, then continue the following
804 //
805 break;
806 }
807
808 //
809 // If the resource allocation is unsuccessful, free resources on bridge
810 //
811
812 RootBridgeDev = NULL;
813 RootBridgeHandle = 0;
814
815 IoResStatus = EFI_RESOURCE_SATISFIED;
816 Mem32ResStatus = EFI_RESOURCE_SATISFIED;
817 PMem32ResStatus = EFI_RESOURCE_SATISFIED;
818 Mem64ResStatus = EFI_RESOURCE_SATISFIED;
819 PMem64ResStatus = EFI_RESOURCE_SATISFIED;
820
821 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
822 //
823 // Get RootBridg Device by handle
824 //
825 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
826 if (RootBridgeDev == NULL) {
827 return EFI_NOT_FOUND;
828 }
829
830 //
831 // Get host bridge handle for status report
832 //
833 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
834
835 //
836 // Get acpi resource node for all the resource types
837 //
838 AcpiConfig = NULL;
839
840 Status = PciResAlloc->GetProposedResources (
841 PciResAlloc,
842 RootBridgeDev->Handle,
843 &AcpiConfig
844 );
845
846 if (EFI_ERROR (Status)) {
847 return Status;
848 }
849
850 if (AcpiConfig != NULL) {
851 //
852 // Adjust resource allocation policy for each RB
853 //
854 GetResourceAllocationStatus (
855 AcpiConfig,
856 &IoResStatus,
857 &Mem32ResStatus,
858 &PMem32ResStatus,
859 &Mem64ResStatus,
860 &PMem64ResStatus
861 );
862 FreePool (AcpiConfig);
863 }
864 }
865 //
866 // End while
867 //
868
869 //
870 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
871 //
872 //
873 // It is very difficult to follow the spec here
874 // Device path , Bar index can not be get here
875 //
876 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
877
878 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
879 EFI_PROGRESS_CODE,
880 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
881 (VOID *) &AllocFailExtendedData,
882 sizeof (AllocFailExtendedData)
883 );
884
885 Status = PciHostBridgeAdjustAllocation (
886 &IoPool,
887 &Mem32Pool,
888 &PMem32Pool,
889 &Mem64Pool,
890 &PMem64Pool,
891 IoResStatus,
892 Mem32ResStatus,
893 PMem32ResStatus,
894 Mem64ResStatus,
895 PMem64ResStatus
896 );
897
898 //
899 // Destroy all the resource tree
900 //
901 DestroyResourceTree (&IoPool);
902 DestroyResourceTree (&Mem32Pool);
903 DestroyResourceTree (&PMem32Pool);
904 DestroyResourceTree (&Mem64Pool);
905 DestroyResourceTree (&PMem64Pool);
906
907 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
908
909 if (EFI_ERROR (Status)) {
910 return Status;
911 }
912
913 ReAllocate = TRUE;
914
915 }
916 //
917 // End main while
918 //
919
920 //
921 // Raise the EFI_IOB_PCI_RES_ALLOC status code
922 //
923 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
924 EFI_PROGRESS_CODE,
925 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
926 (VOID *) &HandleExtendedData,
927 sizeof (HandleExtendedData)
928 );
929
930 //
931 // Notify pci bus driver starts to program the resource
932 //
933 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
934
935 RootBridgeDev = NULL;
936
937 RootBridgeHandle = 0;
938
939 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
940
941 //
942 // Get RootBridg Device by handle
943 //
944 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
945
946 if (RootBridgeDev == NULL) {
947 return EFI_NOT_FOUND;
948 }
949
950 //
951 // Get acpi resource node for all the resource types
952 //
953 AcpiConfig = NULL;
954 Status = PciResAlloc->GetProposedResources (
955 PciResAlloc,
956 RootBridgeDev->Handle,
957 &AcpiConfig
958 );
959
960 if (EFI_ERROR (Status)) {
961 return Status;
962 }
963
964 //
965 // Get the resource base by interpreting acpi resource node
966 //
967 //
968 GetResourceBase (
969 AcpiConfig,
970 &IoBase,
971 &Mem32Base,
972 &PMem32Base,
973 &Mem64Base,
974 &PMem64Base
975 );
976
977 //
978 // Process option rom for this root bridge
979 //
980 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
981
982 //
983 // Create the entire system resource map from the information collected by
984 // enumerator. Several resource tree was created
985 //
986 Status = GetResourceMap (
987 RootBridgeDev,
988 &IoBridge,
989 &Mem32Bridge,
990 &PMem32Bridge,
991 &Mem64Bridge,
992 &PMem64Bridge,
993 &IoPool,
994 &Mem32Pool,
995 &PMem32Pool,
996 &Mem64Pool,
997 &PMem64Pool
998 );
999
1000 if (EFI_ERROR (Status)) {
1001 return Status;
1002 }
1003
1004 //
1005 // Program IO resources
1006 //
1007 ProgramResource (
1008 IoBase,
1009 IoBridge
1010 );
1011
1012 //
1013 // Program Mem32 resources
1014 //
1015 ProgramResource (
1016 Mem32Base,
1017 Mem32Bridge
1018 );
1019
1020 //
1021 // Program PMem32 resources
1022 //
1023 ProgramResource (
1024 PMem32Base,
1025 PMem32Bridge
1026 );
1027
1028 //
1029 // Program Mem64 resources
1030 //
1031 ProgramResource (
1032 Mem64Base,
1033 Mem64Bridge
1034 );
1035
1036 //
1037 // Program PMem64 resources
1038 //
1039 ProgramResource (
1040 PMem64Base,
1041 PMem64Bridge
1042 );
1043
1044 FreePool (AcpiConfig);
1045 }
1046
1047 //
1048 // Destroy all the resource tree
1049 //
1050 DestroyResourceTree (&IoPool);
1051 DestroyResourceTree (&Mem32Pool);
1052 DestroyResourceTree (&PMem32Pool);
1053 DestroyResourceTree (&Mem64Pool);
1054 DestroyResourceTree (&PMem64Pool);
1055
1056 //
1057 // Notify the resource allocation phase is to end
1058 //
1059 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
1060
1061 return EFI_SUCCESS;
1062 }
1063
1064 /**
1065 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1066 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1067
1068 @param Bridge Bridge device instance.
1069 @param StartBusNumber start point.
1070 @param SubBusNumber Point to sub bus number.
1071 @param PaddedBusRange Customized bus number.
1072
1073 @retval EFI_SUCCESS Success.
1074 @retval EFI_DEVICE_ERROR Fail to scan bus.
1075 **/
1076 EFI_STATUS
1077 PciScanBus (
1078 IN PCI_IO_DEVICE *Bridge,
1079 IN UINT8 StartBusNumber,
1080 OUT UINT8 *SubBusNumber,
1081 OUT UINT8 *PaddedBusRange
1082 )
1083 {
1084 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1085 return PciScanBus_WithHotPlugDeviceSupport (
1086 Bridge,
1087 StartBusNumber,
1088 SubBusNumber,
1089 PaddedBusRange
1090 );
1091 } else {
1092 return PciScanBus_WithoutHotPlugDeviceSupport (
1093 Bridge,
1094 StartBusNumber,
1095 SubBusNumber,
1096 PaddedBusRange
1097 );
1098 }
1099 }
1100
1101 /**
1102 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1103 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1104
1105 @param Bridge Bridge device instance.
1106 @param StartBusNumber start point.
1107 @param SubBusNumber Point to sub bus number.
1108 @param PaddedBusRange Customized bus number.
1109
1110 @retval EFI_SUCCESS Success.
1111 @retval EFI_DEVICE_ERROR Fail to scan bus.
1112 **/
1113 EFI_STATUS
1114 PciScanBus_WithoutHotPlugDeviceSupport (
1115 IN PCI_IO_DEVICE *Bridge,
1116 IN UINT8 StartBusNumber,
1117 OUT UINT8 *SubBusNumber,
1118 OUT UINT8 *PaddedBusRange
1119 )
1120 {
1121 EFI_STATUS Status;
1122 PCI_TYPE00 Pci;
1123 UINT8 Device;
1124 UINT8 Func;
1125 UINT64 Address;
1126 UINTN SecondBus;
1127 UINT16 Register;
1128 PCI_IO_DEVICE *PciDevice;
1129 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1130
1131 PciRootBridgeIo = Bridge->PciRootBridgeIo;
1132 SecondBus = 0;
1133 Register = 0;
1134
1135 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
1136 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
1137
1138 //
1139 // Check to see whether a pci device is present
1140 //
1141 Status = PciDevicePresent (
1142 PciRootBridgeIo,
1143 &Pci,
1144 StartBusNumber,
1145 Device,
1146 Func
1147 );
1148
1149 if (!EFI_ERROR (Status)) {
1150 DEBUG((EFI_D_ERROR, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func));
1151
1152 if (IS_PCI_BRIDGE (&Pci) ||
1153 IS_CARDBUS_BRIDGE (&Pci)) {
1154
1155 //
1156 // Get the bridge information
1157 //
1158 Status = PciSearchDevice (
1159 Bridge,
1160 &Pci,
1161 StartBusNumber,
1162 Device,
1163 Func,
1164 &PciDevice
1165 );
1166
1167 if (EFI_ERROR (Status)) {
1168 return Status;
1169 }
1170
1171 //
1172 // Add feature to support customized secondary bus number
1173 //
1174 if (*SubBusNumber == 0) {
1175 *SubBusNumber = *PaddedBusRange;
1176 *PaddedBusRange = 0;
1177 }
1178
1179 (*SubBusNumber)++;
1180
1181 SecondBus = (*SubBusNumber);
1182
1183 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
1184
1185 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
1186
1187 Status = PciRootBridgeIoWrite (
1188 PciRootBridgeIo,
1189 &Pci,
1190 EfiPciWidthUint16,
1191 Address,
1192 1,
1193 &Register
1194 );
1195
1196 //
1197 // Initialize SubBusNumber to SecondBus
1198 //
1199 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1200 Status = PciRootBridgeIoWrite (
1201 PciRootBridgeIo,
1202 &Pci,
1203 EfiPciWidthUint8,
1204 Address,
1205 1,
1206 SubBusNumber
1207 );
1208 //
1209 // If it is PPB, resursively search down this bridge
1210 //
1211 if (IS_PCI_BRIDGE (&Pci)) {
1212 //
1213 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1214 // PCI configuration transaction to go through any PPB
1215 //
1216 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1217 Register = 0xFF;
1218 Status = PciRootBridgeIoWrite (
1219 PciRootBridgeIo,
1220 &Pci,
1221 EfiPciWidthUint8,
1222 Address,
1223 1,
1224 &Register
1225 );
1226
1227 PreprocessController (
1228 PciDevice,
1229 PciDevice->BusNumber,
1230 PciDevice->DeviceNumber,
1231 PciDevice->FunctionNumber,
1232 EfiPciBeforeChildBusEnumeration
1233 );
1234
1235 DEBUG((EFI_D_ERROR, "Scan PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber ));
1236 Status = PciScanBus (
1237 PciDevice,
1238 (UINT8) (SecondBus),
1239 SubBusNumber,
1240 PaddedBusRange
1241 );
1242
1243 if (EFI_ERROR (Status)) {
1244 return EFI_DEVICE_ERROR;
1245 }
1246 }
1247
1248 //
1249 // Set the current maximum bus number under the PPB
1250 //
1251
1252 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1253
1254 Status = PciRootBridgeIoWrite (
1255 PciRootBridgeIo,
1256 &Pci,
1257 EfiPciWidthUint8,
1258 Address,
1259 1,
1260 SubBusNumber
1261 );
1262
1263 }
1264 }
1265 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1266
1267 //
1268 // Skip sub functions, this is not a multi function device
1269 //
1270
1271 Func = PCI_MAX_FUNC;
1272 }
1273 }
1274 }
1275
1276 return EFI_SUCCESS;
1277 }
1278
1279 /**
1280 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1281 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1282
1283 @param Bridge Bridge device instance.
1284 @param StartBusNumber start point.
1285 @param SubBusNumber Point to sub bus number.
1286 @param PaddedBusRange Customized bus number.
1287
1288 @retval EFI_SUCCESS Success.
1289 @retval EFI_DEVICE_ERROR Fail to scan bus.
1290 **/
1291 EFI_STATUS
1292 PciScanBus_WithHotPlugDeviceSupport (
1293 IN PCI_IO_DEVICE *Bridge,
1294 IN UINT8 StartBusNumber,
1295 OUT UINT8 *SubBusNumber,
1296 OUT UINT8 *PaddedBusRange
1297 )
1298 {
1299 EFI_STATUS Status;
1300 PCI_TYPE00 Pci;
1301 UINT8 Device;
1302 UINT8 Func;
1303 UINT64 Address;
1304 UINTN SecondBus;
1305 UINT16 Register;
1306 UINTN HpIndex;
1307 PCI_IO_DEVICE *PciDevice;
1308 EFI_EVENT Event;
1309 EFI_HPC_STATE State;
1310 UINT64 PciAddress;
1311 EFI_HPC_PADDING_ATTRIBUTES Attributes;
1312 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1313 UINT16 BusRange;
1314 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1315 BOOLEAN BusPadding;
1316
1317 PciRootBridgeIo = Bridge->PciRootBridgeIo;
1318 SecondBus = 0;
1319 Register = 0;
1320 State = 0;
1321 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;
1322 BusRange = 0;
1323
1324 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
1325 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
1326
1327 //
1328 // Check to see whether a pci device is present
1329 //
1330 Status = PciDevicePresent (
1331 PciRootBridgeIo,
1332 &Pci,
1333 StartBusNumber,
1334 Device,
1335 Func
1336 );
1337
1338 if (EFI_ERROR (Status)) {
1339 if (Func == 0) {
1340 //
1341 // Skip sub functions, this is not a multi function device
1342 //
1343 Func = PCI_MAX_FUNC;
1344 }
1345
1346 continue;
1347 }
1348
1349 DEBUG((EFI_D_ERROR, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));
1350
1351 //
1352 // Get the PCI device information
1353 //
1354 Status = PciSearchDevice (
1355 Bridge,
1356 &Pci,
1357 StartBusNumber,
1358 Device,
1359 Func,
1360 &PciDevice
1361 );
1362
1363 ASSERT (!EFI_ERROR (Status));
1364
1365 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
1366
1367 if (!IS_PCI_BRIDGE (&Pci)) {
1368 //
1369 // PCI bridges will be called later
1370 // Here just need for PCI device or PCI to cardbus controller
1371 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1372 //
1373 PreprocessController (
1374 PciDevice,
1375 PciDevice->BusNumber,
1376 PciDevice->DeviceNumber,
1377 PciDevice->FunctionNumber,
1378 EfiPciBeforeChildBusEnumeration
1379 );
1380 }
1381
1382 //
1383 // For Pci Hotplug controller devcie only
1384 //
1385 if (gPciHotPlugInit != NULL) {
1386 //
1387 // Check if it is a Hotplug PCI controller
1388 //
1389 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
1390
1391 if (!gPciRootHpcData[HpIndex].Initialized) {
1392
1393 Status = CreateEventForHpc (HpIndex, &Event);
1394
1395 ASSERT (!EFI_ERROR (Status));
1396
1397 Status = gPciHotPlugInit->InitializeRootHpc (
1398 gPciHotPlugInit,
1399 gPciRootHpcPool[HpIndex].HpcDevicePath,
1400 PciAddress,
1401 Event,
1402 &State
1403 );
1404
1405 PreprocessController (
1406 PciDevice,
1407 PciDevice->BusNumber,
1408 PciDevice->DeviceNumber,
1409 PciDevice->FunctionNumber,
1410 EfiPciBeforeChildBusEnumeration
1411 );
1412 }
1413 }
1414 }
1415
1416 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
1417 //
1418 // For PPB
1419 // Get the bridge information
1420 //
1421 BusPadding = FALSE;
1422 if (gPciHotPlugInit != NULL) {
1423
1424 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {
1425
1426 //
1427 // If it is initialized, get the padded bus range
1428 //
1429 Status = gPciHotPlugInit->GetResourcePadding (
1430 gPciHotPlugInit,
1431 gPciRootHpcPool[HpIndex].HpbDevicePath,
1432 PciAddress,
1433 &State,
1434 (VOID **) &Descriptors,
1435 &Attributes
1436 );
1437
1438 if (EFI_ERROR (Status)) {
1439 return Status;
1440 }
1441
1442 BusRange = 0;
1443 Status = PciGetBusRange (
1444 &Descriptors,
1445 NULL,
1446 NULL,
1447 &BusRange
1448 );
1449
1450 gBS->FreePool (Descriptors);
1451
1452 if (EFI_ERROR (Status)) {
1453 return Status;
1454 }
1455
1456 BusPadding = TRUE;
1457 }
1458 }
1459
1460 //
1461 // Add feature to support customized secondary bus number
1462 //
1463 if (*SubBusNumber == 0) {
1464 *SubBusNumber = *PaddedBusRange;
1465 *PaddedBusRange = 0;
1466 }
1467
1468 (*SubBusNumber)++;
1469 SecondBus = *SubBusNumber;
1470
1471 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
1472 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
1473
1474 Status = PciRootBridgeIoWrite (
1475 PciRootBridgeIo,
1476 &Pci,
1477 EfiPciWidthUint16,
1478 Address,
1479 1,
1480 &Register
1481 );
1482
1483
1484 //
1485 // If it is PPB, resursively search down this bridge
1486 //
1487 if (IS_PCI_BRIDGE (&Pci)) {
1488
1489 //
1490 // Initialize SubBusNumber to Maximum bus number
1491 //
1492 Register = 0xFF;
1493 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1494 Status = PciRootBridgeIoWrite (
1495 PciRootBridgeIo,
1496 &Pci,
1497 EfiPciWidthUint8,
1498 Address,
1499 1,
1500 &Register
1501 );
1502
1503 //
1504 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1505 //
1506 PreprocessController (
1507 PciDevice,
1508 PciDevice->BusNumber,
1509 PciDevice->DeviceNumber,
1510 PciDevice->FunctionNumber,
1511 EfiPciBeforeChildBusEnumeration
1512 );
1513
1514 DEBUG((EFI_D_ERROR, "Scan PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber ));
1515 Status = PciScanBus (
1516 PciDevice,
1517 (UINT8) (SecondBus),
1518 SubBusNumber,
1519 PaddedBusRange
1520 );
1521
1522 if (EFI_ERROR (Status)) {
1523 return EFI_DEVICE_ERROR;
1524 }
1525 }
1526
1527 if (BusPadding) {
1528 //
1529 // Ensure the device is enabled and initialized
1530 //
1531 if ((Attributes == EfiPaddingPciRootBridge) &&
1532 (State & EFI_HPC_STATE_ENABLED) != 0 &&
1533 (State & EFI_HPC_STATE_INITIALIZED) != 0) {
1534 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);
1535 } else {
1536 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);
1537 }
1538 }
1539
1540 //
1541 // Set the current maximum bus number under the PPB
1542 //
1543 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1544
1545 Status = PciRootBridgeIoWrite (
1546 PciRootBridgeIo,
1547 &Pci,
1548 EfiPciWidthUint8,
1549 Address,
1550 1,
1551 SubBusNumber
1552 );
1553 }
1554
1555 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1556
1557 //
1558 // Skip sub functions, this is not a multi function device
1559 //
1560 Func = PCI_MAX_FUNC;
1561 }
1562
1563 }
1564 }
1565
1566 return EFI_SUCCESS;
1567 }
1568
1569 /**
1570 Process Option Rom on this host bridge.
1571
1572 @param Bridge Pci bridge device instance.
1573
1574 @retval EFI_SUCCESS Success.
1575 **/
1576 EFI_STATUS
1577 PciRootBridgeP2CProcess (
1578 IN PCI_IO_DEVICE *Bridge
1579 )
1580 {
1581 LIST_ENTRY *CurrentLink;
1582 PCI_IO_DEVICE *Temp;
1583 EFI_HPC_STATE State;
1584 UINT64 PciAddress;
1585 EFI_STATUS Status;
1586
1587 CurrentLink = Bridge->ChildList.ForwardLink;
1588
1589 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
1590
1591 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1592
1593 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
1594
1595 if (gPciHotPlugInit != NULL && Temp->Allocated) {
1596
1597 //
1598 // Raise the EFI_IOB_PCI_HPC_INIT status code
1599 //
1600 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1601 EFI_PROGRESS_CODE,
1602 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,
1603 Temp->DevicePath
1604 );
1605
1606 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
1607 Status = gPciHotPlugInit->InitializeRootHpc (
1608 gPciHotPlugInit,
1609 Temp->DevicePath,
1610 PciAddress,
1611 NULL,
1612 &State
1613 );
1614
1615 if (!EFI_ERROR (Status)) {
1616 Status = PciBridgeEnumerator (Temp);
1617
1618 if (EFI_ERROR (Status)) {
1619 return Status;
1620 }
1621 }
1622
1623 CurrentLink = CurrentLink->ForwardLink;
1624 continue;
1625
1626 }
1627 }
1628
1629 if (!IsListEmpty (&Temp->ChildList)) {
1630 Status = PciRootBridgeP2CProcess (Temp);
1631 }
1632
1633 CurrentLink = CurrentLink->ForwardLink;
1634 }
1635
1636 return EFI_SUCCESS;
1637 }
1638
1639 /**
1640 Process Option Rom on this host bridge.
1641
1642 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1643
1644 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1645 @retval EFI_SUCCESS Success process.
1646 **/
1647 EFI_STATUS
1648 PciHostBridgeP2CProcess (
1649 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1650 )
1651 {
1652 EFI_HANDLE RootBridgeHandle;
1653 PCI_IO_DEVICE *RootBridgeDev;
1654 EFI_STATUS Status;
1655
1656 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1657 return EFI_SUCCESS;
1658 }
1659
1660 RootBridgeHandle = NULL;
1661
1662 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1663
1664 //
1665 // Get RootBridg Device by handle
1666 //
1667 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1668
1669 if (RootBridgeDev == NULL) {
1670 return EFI_NOT_FOUND;
1671 }
1672
1673 Status = PciRootBridgeP2CProcess (RootBridgeDev);
1674
1675 if (EFI_ERROR (Status)) {
1676 return Status;
1677 }
1678
1679 }
1680
1681 return EFI_SUCCESS;
1682 }
1683
1684 /**
1685 This function is used to enumerate the entire host bridge
1686 in a given platform.
1687
1688 @param PciResAlloc A pointer to the resource allocate protocol.
1689
1690 @retval EFI_OUT_OF_RESOURCES no enough resource.
1691 @retval EFI_SUCCESS Success.
1692
1693 **/
1694 EFI_STATUS
1695 PciHostBridgeEnumerator (
1696 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1697 )
1698 {
1699 EFI_HANDLE RootBridgeHandle;
1700 PCI_IO_DEVICE *RootBridgeDev;
1701 EFI_STATUS Status;
1702 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1703 UINT16 MinBus;
1704 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1705 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
1706 UINT8 StartBusNumber;
1707 LIST_ENTRY RootBridgeList;
1708 LIST_ENTRY *Link;
1709
1710 InitializeHotPlugSupport ();
1711
1712 InitializeListHead (&RootBridgeList);
1713
1714 //
1715 // Notify the bus allocation phase is about to start
1716 //
1717 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1718
1719 DEBUG((EFI_D_ERROR, "PCI Bus First Scanning\n"));
1720 RootBridgeHandle = NULL;
1721 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1722
1723 //
1724 // if a root bridge instance is found, create root bridge device for it
1725 //
1726
1727 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1728
1729 if (RootBridgeDev == NULL) {
1730 return EFI_OUT_OF_RESOURCES;
1731 }
1732
1733 //
1734 // Enumerate all the buses under this root bridge
1735 //
1736
1737 Status = PciRootBridgeEnumerator (
1738 PciResAlloc,
1739 RootBridgeDev
1740 );
1741
1742 if (gPciHotPlugInit != NULL) {
1743 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));
1744 } else {
1745 DestroyRootBridge (RootBridgeDev);
1746 }
1747 if (EFI_ERROR (Status)) {
1748 return Status;
1749 }
1750 }
1751
1752 //
1753 // Notify the bus allocation phase is finished for the first time
1754 //
1755 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1756
1757 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1758
1759 if (gPciHotPlugInit != NULL) {
1760 //
1761 // Reset all assigned PCI bus number in all PPB
1762 //
1763 RootBridgeHandle = NULL;
1764 Link = GetFirstNode (&RootBridgeList);
1765 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&
1766 (!IsNull (&RootBridgeList, Link))) {
1767 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);
1768 //
1769 // Get the Bus information
1770 //
1771 Status = PciResAlloc->StartBusEnumeration (
1772 PciResAlloc,
1773 RootBridgeHandle,
1774 (VOID **) &Configuration
1775 );
1776 if (EFI_ERROR (Status)) {
1777 return Status;
1778 }
1779
1780 //
1781 // Get the bus number to start with
1782 //
1783 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);
1784
1785 ResetAllPpbBusNumber (
1786 RootBridgeDev,
1787 StartBusNumber
1788 );
1789
1790 gBS->FreePool (Configuration);
1791 Link = GetNextNode (&RootBridgeList, Link);
1792 DestroyRootBridge (RootBridgeDev);
1793 }
1794
1795 //
1796 // Wait for all HPC initialized
1797 //
1798 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
1799
1800 if (EFI_ERROR (Status)) {
1801 return Status;
1802 }
1803
1804 //
1805 // Notify the bus allocation phase is about to start for the 2nd time
1806 //
1807 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1808
1809 DEBUG((EFI_D_ERROR, "PCI Bus Second Scanning\n"));
1810 RootBridgeHandle = NULL;
1811 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1812
1813 //
1814 // if a root bridge instance is found, create root bridge device for it
1815 //
1816
1817 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1818
1819 if (RootBridgeDev == NULL) {
1820 return EFI_OUT_OF_RESOURCES;
1821 }
1822
1823 //
1824 // Enumerate all the buses under this root bridge
1825 //
1826
1827 Status = PciRootBridgeEnumerator (
1828 PciResAlloc,
1829 RootBridgeDev
1830 );
1831
1832 DestroyRootBridge (RootBridgeDev);
1833 if (EFI_ERROR (Status)) {
1834 return Status;
1835 }
1836 }
1837
1838 //
1839 // Notify the bus allocation phase is to end for the 2nd time
1840 //
1841 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1842 }
1843 }
1844
1845 //
1846 // Notify the resource allocation phase is to start
1847 //
1848 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
1849
1850 RootBridgeHandle = NULL;
1851 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1852
1853 //
1854 // if a root bridge instance is found, create root bridge device for it
1855 //
1856
1857 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1858
1859 if (RootBridgeDev == NULL) {
1860 return EFI_OUT_OF_RESOURCES;
1861 }
1862
1863 Status = StartManagingRootBridge (RootBridgeDev);
1864
1865 if (EFI_ERROR (Status)) {
1866 return Status;
1867 }
1868
1869 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
1870 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1871
1872 if (EFI_ERROR (Status)) {
1873 return Status;
1874 }
1875
1876 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
1877
1878 if (EFI_ERROR (Status)) {
1879 return Status;
1880 }
1881
1882 //
1883 // Determine root bridge attribute by calling interface of Pcihostbridge
1884 // protocol
1885 //
1886 DetermineRootBridgeAttributes (
1887 PciResAlloc,
1888 RootBridgeDev
1889 );
1890
1891 //
1892 // Collect all the resource information under this root bridge
1893 // A database that records all the information about pci device subject to this
1894 // root bridge will then be created
1895 //
1896 Status = PciPciDeviceInfoCollector (
1897 RootBridgeDev,
1898 (UINT8) MinBus
1899 );
1900
1901 if (EFI_ERROR (Status)) {
1902 return Status;
1903 }
1904
1905 InsertRootBridge (RootBridgeDev);
1906
1907 //
1908 // Record the hostbridge handle
1909 //
1910 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
1911 }
1912
1913 return EFI_SUCCESS;
1914 }
1915
1916 /**
1917 Read PCI device configuration register by specified address.
1918
1919 This function check the incompatiblilites on PCI device. Return the register
1920 value.
1921
1922 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1923 @param PciIo A pointer to EFI_PCI_PROTOCOL.
1924 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
1925 @param Width Signifies the width of the memory operations.
1926 @param Address The address within the PCI configuration space for the PCI controller.
1927 @param Buffer For read operations, the destination buffer to store the results. For
1928 write operations, the source buffer to write data from.
1929
1930 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1931 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
1932 @retval EFI_INVALID_PARAMETER Buffer is NULL.
1933 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1934
1935 **/
1936 EFI_STATUS
1937 ReadConfigData (
1938 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
1939 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
1940 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
1941 IN UINT64 Width,
1942 IN UINT64 Address,
1943 IN OUT VOID *Buffer
1944 )
1945 {
1946 EFI_STATUS Status;
1947 UINT64 AccessWidth;
1948 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;
1949 UINT64 AccessAddress;
1950 UINTN Stride;
1951 UINT64 TempBuffer;
1952 UINT8 *Pointer;
1953
1954 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
1955
1956 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {
1957 //
1958 // check access compatibility at first time
1959 //
1960 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, Address & 0xff, Width, &PciRegisterAccessData);
1961
1962 if (Status == EFI_SUCCESS) {
1963 //
1964 // there exist incompatibility on this operation
1965 //
1966 AccessWidth = Width;
1967
1968 if (PciRegisterAccessData->Width != VALUE_NOCARE) {
1969 AccessWidth = PciRegisterAccessData->Width;
1970 }
1971
1972 AccessAddress = Address & ~((1 << AccessWidth) - 1);
1973
1974 TempBuffer = 0;
1975 Stride = 0;
1976 Pointer = (UINT8 *) &TempBuffer;
1977
1978 while (1) {
1979
1980 if (PciRootBridgeIo != NULL) {
1981 Status = PciRootBridgeIo->Pci.Read (
1982 PciRootBridgeIo,
1983 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,
1984 AccessAddress,
1985 1,
1986 Pointer
1987 );
1988 } else if (PciIo != NULL) {
1989 Status = PciIo->Pci.Read (
1990 PciIo,
1991 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,
1992 (UINT32) AccessAddress,
1993 1,
1994 Pointer
1995 );
1996 }
1997
1998 if (Status != EFI_SUCCESS) {
1999 return Status;
2000 }
2001
2002 Stride = (UINTN)1 << AccessWidth;
2003 AccessAddress += Stride;
2004 if (AccessAddress >= (Address + LShiftU64 (1ULL, (UINTN)Width))) {
2005 //
2006 // if all datas have been read, exist
2007 //
2008 break;
2009 }
2010
2011 Pointer += Stride;
2012
2013 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {
2014 //
2015 // if current offset doesn't reach the end
2016 //
2017 continue;
2018 }
2019
2020 FreePool (PciRegisterAccessData);
2021
2022 //
2023 // continue checking access incompatibility
2024 //
2025 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);
2026 if (Status == EFI_SUCCESS) {
2027 if (PciRegisterAccessData->Width != VALUE_NOCARE) {
2028 AccessWidth = PciRegisterAccessData->Width;
2029 }
2030 }
2031 }
2032
2033 FreePool (PciRegisterAccessData);
2034
2035 switch (Width) {
2036 case EfiPciWidthUint8:
2037 * (UINT8 *) Buffer = (UINT8) TempBuffer;
2038 break;
2039 case EfiPciWidthUint16:
2040 * (UINT16 *) Buffer = (UINT16) TempBuffer;
2041 break;
2042 case EfiPciWidthUint32:
2043 * (UINT32 *) Buffer = (UINT32) TempBuffer;
2044 break;
2045 default:
2046 return EFI_UNSUPPORTED;
2047 }
2048
2049 return Status;
2050 }
2051 }
2052 //
2053 // AccessWidth incompatible check not supportted
2054 // or, there doesn't exist incompatibility on this operation
2055 //
2056 if (PciRootBridgeIo != NULL) {
2057 Status = PciRootBridgeIo->Pci.Read (
2058 PciRootBridgeIo,
2059 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
2060 Address,
2061 1,
2062 Buffer
2063 );
2064
2065 } else {
2066 Status = PciIo->Pci.Read (
2067 PciIo,
2068 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
2069 (UINT32) Address,
2070 1,
2071 Buffer
2072 );
2073 }
2074
2075 return Status;
2076 }
2077
2078 /**
2079 Update register value by checking PCI device incompatibility.
2080
2081 This function check register value incompatibilites on PCI device. Return the register
2082 value.
2083
2084 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2085 @param AccessType Access type, READ or WRITE.
2086 @param Width Signifies the width of the memory operations.
2087 @param Address The address within the PCI configuration space.
2088 @param Buffer Store the register data.
2089
2090 @retval EFI_SUCCESS The data has been updated.
2091
2092 **/
2093 EFI_STATUS
2094 UpdateConfigData (
2095 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
2096 IN UINT64 AccessType,
2097 IN UINT64 Width,
2098 IN UINT64 Address,
2099 IN OUT VOID *Buffer
2100 )
2101 {
2102 EFI_STATUS Status;
2103 EFI_PCI_REGISTER_VALUE_DATA *PciRegisterData;
2104 UINT32 AndValue;
2105 UINT32 OrValue;
2106 UINT32 TempValue;
2107
2108 //
2109 // check register value incompatibility
2110 //
2111 Status = PciRegisterUpdateCheck (PciDeviceInfo, AccessType, Address & 0xff, &PciRegisterData);
2112
2113 if (Status == EFI_SUCCESS) {
2114
2115 AndValue = ((UINT32) PciRegisterData->AndValue) >> (((UINT8) Address & 0x3) * 8);
2116 OrValue = ((UINT32) PciRegisterData->OrValue) >> (((UINT8) Address & 0x3) * 8);
2117
2118 TempValue = * (UINT32 *) Buffer;
2119 if (PciRegisterData->AndValue != VALUE_NOCARE) {
2120 TempValue &= AndValue;
2121 }
2122 if (PciRegisterData->OrValue != VALUE_NOCARE) {
2123 TempValue |= OrValue;
2124 }
2125
2126 switch (Width) {
2127 case EfiPciWidthUint8:
2128 *(UINT8 *)Buffer = (UINT8) TempValue;
2129 break;
2130
2131 case EfiPciWidthUint16:
2132 *(UINT16 *)Buffer = (UINT16) TempValue;
2133 break;
2134 case EfiPciWidthUint32:
2135 *(UINT32 *)Buffer = TempValue;
2136 break;
2137
2138 default:
2139 return EFI_UNSUPPORTED;
2140 }
2141
2142 FreePool (PciRegisterData);
2143 }
2144
2145 return Status;
2146 }
2147
2148 /**
2149 Write PCI device configuration register by specified address.
2150
2151 This function check the incompatiblilites on PCI device, and write date
2152 into register.
2153
2154 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2155 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2156 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2157 @param Width Signifies the width of the memory operations.
2158 @param Address The address within the PCI configuration space for the PCI controller.
2159 @param Buffer For read operations, the destination buffer to store the results. For
2160 write operations, the source buffer to write data from.
2161
2162 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2163 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2164 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2165 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2166
2167 **/
2168 EFI_STATUS
2169 WriteConfigData (
2170 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
2171 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
2172 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
2173 IN UINT64 Width,
2174 IN UINT64 Address,
2175 IN VOID *Buffer
2176 )
2177 {
2178 EFI_STATUS Status;
2179 UINT64 AccessWidth;
2180 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;
2181 UINT64 AccessAddress;
2182 UINTN Stride;
2183 UINT8 *Pointer;
2184 UINT64 Data;
2185 UINTN Shift;
2186
2187 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
2188
2189 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {
2190 //
2191 // check access compatibility at first time
2192 //
2193 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, Address & 0xff, Width, &PciRegisterAccessData);
2194
2195 if (Status == EFI_SUCCESS) {
2196 //
2197 // there exist incompatibility on this operation
2198 //
2199 AccessWidth = Width;
2200
2201 if (PciRegisterAccessData->Width != VALUE_NOCARE) {
2202 AccessWidth = PciRegisterAccessData->Width;
2203 }
2204
2205 AccessAddress = Address & ~((1 << AccessWidth) - 1);
2206
2207 Stride = 0;
2208 Pointer = (UINT8 *) &Buffer;
2209 Data = * (UINT64 *) Buffer;
2210
2211 while (1) {
2212
2213 if (AccessWidth > Width) {
2214 //
2215 // if actual access width is larger than orignal one, additional data need to be read back firstly
2216 //
2217 Status = ReadConfigData (PciRootBridgeIo, PciIo, PciDeviceInfo, AccessWidth, AccessAddress, &Data);
2218 if (Status != EFI_SUCCESS) {
2219 return Status;
2220 }
2221
2222 //
2223 // check data read incompatibility
2224 //
2225 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_READ, AccessWidth, AccessAddress & 0xff, &Data);
2226
2227 Shift = (UINTN)(Address - AccessAddress) * 8;
2228 switch (Width) {
2229 case EfiPciWidthUint8:
2230 Data = (* (UINT8 *) Buffer) << Shift | (Data & ~(0xff << Shift));
2231 break;
2232
2233 case EfiPciWidthUint16:
2234 Data = (* (UINT16 *) Buffer) << Shift | (Data & ~(0xffff << Shift));
2235 break;
2236 }
2237
2238 //
2239 // check data write incompatibility
2240 //
2241 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_WRITE, AccessWidth, MultU64x32 (AccessAddress, 0xff), &Data);
2242 }
2243
2244 if (PciRootBridgeIo != NULL) {
2245 Status = PciRootBridgeIo->Pci.Write (
2246 PciRootBridgeIo,
2247 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,
2248 AccessAddress,
2249 1,
2250 &Data
2251 );
2252 } else {
2253 Status = PciIo->Pci.Write (
2254 PciIo,
2255 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,
2256 (UINT32) AccessAddress,
2257 1,
2258 &Data
2259 );
2260 }
2261
2262 if (Status != EFI_SUCCESS) {
2263 return Status;
2264 }
2265
2266 Data = RShiftU64 (Data, ((1 << AccessWidth) * 8));
2267
2268 Stride = (UINTN)1 << AccessWidth;
2269 AccessAddress += Stride;
2270 if (AccessAddress >= (Address + LShiftU64 (1ULL, (UINTN)Width))) {
2271 //
2272 // if all datas have been written, exist
2273 //
2274 break;
2275 }
2276
2277 Pointer += Stride;
2278
2279 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {
2280 //
2281 // if current offset doesn't reach the end
2282 //
2283 continue;
2284 }
2285
2286 FreePool (PciRegisterAccessData);
2287
2288 //
2289 // continue checking access incompatibility
2290 //
2291 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);
2292 if (Status == EFI_SUCCESS) {
2293 if (PciRegisterAccessData->Width != VALUE_NOCARE) {
2294 AccessWidth = PciRegisterAccessData->Width;
2295 }
2296 }
2297 };
2298
2299 FreePool (PciRegisterAccessData);
2300
2301 return Status;
2302 }
2303
2304 }
2305 //
2306 // AccessWidth incompatible check not supportted
2307 // or, there doesn't exist incompatibility on this operation
2308 //
2309 if (PciRootBridgeIo != NULL) {
2310 Status = PciRootBridgeIo->Pci.Write (
2311 PciRootBridgeIo,
2312 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
2313 Address,
2314 1,
2315 Buffer
2316 );
2317 } else {
2318 Status = PciIo->Pci.Write (
2319 PciIo,
2320 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
2321 (UINT32) Address,
2322 1,
2323 Buffer
2324 );
2325 }
2326
2327 return Status;
2328 }
2329
2330 /**
2331 Abstract PCI device device information.
2332
2333 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2334 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2335 @param Pci A pointer to PCI_TYPE00.
2336 @param Address The address within the PCI configuration space for the PCI controller.
2337 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2338
2339 @retval EFI_SUCCESS Pci device device information has been abstracted.
2340
2341 **/
2342 EFI_STATUS
2343 GetPciDeviceDeviceInfo (
2344 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
2345 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
2346 IN PCI_TYPE00 *Pci, OPTIONAL
2347 IN UINT64 Address, OPTIONAL
2348 OUT EFI_PCI_DEVICE_INFO *PciDeviceInfo
2349 )
2350 {
2351 EFI_STATUS Status;
2352 UINT64 PciAddress;
2353 UINT32 PciConfigData;
2354 PCI_IO_DEVICE *PciIoDevice;
2355
2356 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
2357
2358 if (PciIo != NULL) {
2359 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
2360
2361 //
2362 // get pointer to PCI_TYPE00 from PciIoDevice
2363 //
2364 Pci = &PciIoDevice->Pci;
2365 }
2366
2367 if (Pci == NULL) {
2368 //
2369 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly
2370 //
2371 PciAddress = Address & 0xffffffffffffff00ULL;
2372 Status = PciRootBridgeIo->Pci.Read (
2373 PciRootBridgeIo,
2374 EfiPciWidthUint32,
2375 PciAddress,
2376 1,
2377 &PciConfigData
2378 );
2379
2380 if (EFI_ERROR (Status)) {
2381 return Status;
2382 }
2383
2384 if ((PciConfigData & 0xffff) == 0xffff) {
2385 return EFI_NOT_FOUND;
2386 }
2387
2388 PciDeviceInfo->VendorID = PciConfigData & 0xffff;
2389 PciDeviceInfo->DeviceID = PciConfigData >> 16;
2390
2391 Status = PciRootBridgeIo->Pci.Read (
2392 PciRootBridgeIo,
2393 EfiPciWidthUint32,
2394 PciAddress + 8,
2395 1,
2396 &PciConfigData
2397 );
2398 if (EFI_ERROR (Status)) {
2399 return Status;
2400 }
2401
2402 PciDeviceInfo->RevisionID = PciConfigData & 0xf;
2403
2404 Status = PciRootBridgeIo->Pci.Read (
2405 PciRootBridgeIo,
2406 EfiPciWidthUint32,
2407 PciAddress + 0x2c,
2408 1,
2409 &PciConfigData
2410 );
2411
2412 if (EFI_ERROR (Status)) {
2413 return Status;
2414 }
2415
2416 PciDeviceInfo->SubsystemVendorID = PciConfigData & 0xffff;
2417 PciDeviceInfo->SubsystemID = PciConfigData >> 16;
2418
2419 } else {
2420 PciDeviceInfo->VendorID = Pci->Hdr.VendorId;
2421 PciDeviceInfo->DeviceID = Pci->Hdr.DeviceId;
2422 PciDeviceInfo->RevisionID = Pci->Hdr.RevisionID;
2423 PciDeviceInfo->SubsystemVendorID = Pci->Device.SubsystemVendorID;
2424 PciDeviceInfo->SubsystemID = Pci->Device.SubsystemID;
2425 }
2426
2427 return EFI_SUCCESS;
2428 }
2429
2430 /**
2431 Read PCI configuration space with incompatibility check.
2432
2433 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2434 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2435 @param Pci A pointer to PCI_TYPE00.
2436 @param Width Signifies the width of the memory operations.
2437 @param Address The address within the PCI configuration space for the PCI controller.
2438 @param Count The number of unit to be read.
2439 @param Buffer For read operations, the destination buffer to store the results. For
2440 write operations, the source buffer to write data from.
2441
2442 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2443 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2444 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2445 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2446
2447 **/
2448 EFI_STATUS
2449 PciIncompatibilityCheckRead (
2450 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
2451 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
2452 IN PCI_TYPE00 *Pci, OPTIONAL
2453 IN UINTN Width,
2454 IN UINT64 Address,
2455 IN UINTN Count,
2456 IN OUT VOID *Buffer
2457 )
2458 {
2459 EFI_STATUS Status;
2460 EFI_PCI_DEVICE_INFO PciDeviceInfo;
2461 UINT32 Stride;
2462
2463 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
2464
2465 //
2466 // get PCI device device information
2467 //
2468 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);
2469 if (Status != EFI_SUCCESS) {
2470 return Status;
2471 }
2472
2473 Stride = 1 << Width;
2474
2475 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *)Buffer + Stride) {
2476
2477 //
2478 // read configuration register
2479 //
2480 Status = ReadConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, (UINT64) Width, Address, Buffer);
2481
2482 if (Status != EFI_SUCCESS) {
2483 return Status;
2484 }
2485
2486 //
2487 // update the data read from configuration register
2488 //
2489 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {
2490 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_READ, Width, Address & 0xff, Buffer);
2491 }
2492 }
2493
2494 return EFI_SUCCESS;
2495 }
2496
2497 /**
2498 Write PCI configuration space with incompatibility check.
2499
2500 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2501 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2502 @param Pci A pointer to PCI_TYPE00.
2503 @param Width Signifies the width of the memory operations.
2504 @param Address The address within the PCI configuration space for the PCI controller.
2505 @param Count The number of unit to be write.
2506 @param Buffer For read operations, the destination buffer to store the results. For
2507 write operations, the source buffer to write data from.
2508
2509 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2510 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2511 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2512 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2513
2514 **/
2515 EFI_STATUS
2516 PciIncompatibilityCheckWrite (
2517 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
2518 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
2519 IN PCI_TYPE00 *Pci, OPTIONAL
2520 IN UINTN Width,
2521 IN UINT64 Address,
2522 IN UINTN Count,
2523 IN OUT VOID *Buffer
2524 )
2525 {
2526 EFI_STATUS Status;
2527 EFI_PCI_DEVICE_INFO PciDeviceInfo;
2528 UINT32 Stride;
2529 UINT64 Data;
2530
2531 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
2532
2533 //
2534 // get PCI device device information
2535 //
2536 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);
2537 if (Status != EFI_SUCCESS) {
2538 return Status;
2539 }
2540
2541 Stride = 1 << Width;
2542
2543 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *) Buffer + Stride) {
2544
2545 Data = 0;
2546
2547 switch (Width) {
2548 case EfiPciWidthUint8:
2549 Data = * (UINT8 *) Buffer;
2550 break;
2551 case EfiPciWidthUint16:
2552 Data = * (UINT16 *) Buffer;
2553 break;
2554
2555 case EfiPciWidthUint32:
2556 Data = * (UINT32 *) Buffer;
2557 break;
2558
2559 default:
2560 return EFI_UNSUPPORTED;
2561 }
2562
2563 //
2564 // update the data writen into configuration register
2565 //
2566 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {
2567 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_WRITE, Width, Address & 0xff, &Data);
2568 }
2569
2570 //
2571 // write configuration register
2572 //
2573 Status = WriteConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, Width, Address, &Data);
2574
2575 if (Status != EFI_SUCCESS) {
2576 return Status;
2577 }
2578 }
2579
2580 return EFI_SUCCESS;
2581 }
2582
2583 /**
2584 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2585
2586 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2587 @param Pci A pointer to PCI_TYPE00.
2588 @param Width Signifies the width of the memory operations.
2589 @param Address The address within the PCI configuration space for the PCI controller.
2590 @param Count The number of unit to be read.
2591 @param Buffer For read operations, the destination buffer to store the results. For
2592 write operations, the source buffer to write data from.
2593
2594 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2595 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2596 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2597 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2598
2599 **/
2600 EFI_STATUS
2601 PciRootBridgeIoRead (
2602 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
2603 IN PCI_TYPE00 *Pci, OPTIONAL
2604 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
2605 IN UINT64 Address,
2606 IN UINTN Count,
2607 IN OUT VOID *Buffer
2608 )
2609 {
2610 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {
2611 //
2612 // if PCI incompatibility check enabled
2613 //
2614 return PciIncompatibilityCheckRead (
2615 PciRootBridgeIo,
2616 NULL,
2617 Pci,
2618 (UINTN) Width,
2619 Address,
2620 Count,
2621 Buffer
2622 );
2623 } else {
2624 return PciRootBridgeIo->Pci.Read (
2625 PciRootBridgeIo,
2626 Width,
2627 Address,
2628 Count,
2629 Buffer
2630 );
2631 }
2632 }
2633
2634 /**
2635 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2636
2637 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2638 @param Pci A pointer to PCI_TYPE00.
2639 @param Width Signifies the width of the memory operations.
2640 @param Address The address within the PCI configuration space for the PCI controller.
2641 @param Count The number of unit to be read.
2642 @param Buffer For read operations, the destination buffer to store the results. For
2643 write operations, the source buffer to write data from.
2644
2645 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2646 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2647 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2648 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2649
2650 **/
2651 EFI_STATUS
2652 PciRootBridgeIoWrite (
2653 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
2654 IN PCI_TYPE00 *Pci,
2655 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
2656 IN UINT64 Address,
2657 IN UINTN Count,
2658 IN OUT VOID *Buffer
2659 )
2660 {
2661 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {
2662 //
2663 // if PCI incompatibility check enabled
2664 //
2665 return PciIncompatibilityCheckWrite (
2666 PciRootBridgeIo,
2667 NULL,
2668 Pci,
2669 Width,
2670 Address,
2671 Count,
2672 Buffer
2673 );
2674
2675 } else {
2676 return PciRootBridgeIo->Pci.Write (
2677 PciRootBridgeIo,
2678 Width,
2679 Address,
2680 Count,
2681 Buffer
2682 );
2683 }
2684 }
2685
2686 /**
2687 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
2688
2689 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2690 @param Width Signifies the width of the memory operations.
2691 @param Address The address within the PCI configuration space for the PCI controller.
2692 @param Count The number of unit to be read.
2693 @param Buffer For read operations, the destination buffer to store the results. For
2694 write operations, the source buffer to write data from.
2695
2696 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2697 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2698 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2699 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2700
2701 **/
2702 EFI_STATUS
2703 PciIoRead (
2704 IN EFI_PCI_IO_PROTOCOL *PciIo,
2705 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
2706 IN UINT32 Address,
2707 IN UINTN Count,
2708 IN OUT VOID *Buffer
2709 )
2710 {
2711 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {
2712 //
2713 // if PCI incompatibility check enabled
2714 //
2715 return PciIncompatibilityCheckRead (
2716 NULL,
2717 PciIo,
2718 NULL,
2719 (UINTN) Width,
2720 Address,
2721 Count,
2722 Buffer
2723 );
2724 } else {
2725 return PciIo->Pci.Read (
2726 PciIo,
2727 Width,
2728 Address,
2729 Count,
2730 Buffer
2731 );
2732 }
2733 }
2734
2735 /**
2736 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
2737
2738 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2739 @param Width Signifies the width of the memory operations.
2740 @param Address The address within the PCI configuration space for the PCI controller.
2741 @param Count The number of unit to be read.
2742 @param Buffer For read operations, the destination buffer to store the results. For
2743 write operations, the source buffer to write data from.
2744
2745 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2746 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2747 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2748 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2749
2750 **/
2751 EFI_STATUS
2752 PciIoWrite (
2753 IN EFI_PCI_IO_PROTOCOL *PciIo,
2754 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
2755 IN UINT32 Address,
2756 IN UINTN Count,
2757 IN OUT VOID *Buffer
2758 )
2759 {
2760 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {
2761
2762 //
2763 // if PCI incompatibility check enabled
2764 //
2765 return PciIncompatibilityCheckWrite (
2766 NULL,
2767 PciIo,
2768 NULL,
2769 Width,
2770 Address,
2771 Count,
2772 Buffer
2773 );
2774
2775 } else {
2776 return PciIo->Pci.Write (
2777 PciIo,
2778 Width,
2779 Address,
2780 Count,
2781 Buffer
2782 );
2783 }
2784 }
2785