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