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