2 IIO PCI Root Bridge Io Protocol code. Generic enough to work for all IIOs.
3 Does not support configuration accesses to the extended PCI Express registers yet.
5 Copyright (c) 2013-2015 Intel Corporation.
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "PciRootBridge.h"
15 // Define PCI express offse
17 #define PCIE_OFF(Bus, Device, Function, Register) \
18 ((UINT64) ((UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) (Function << 12) + (UINTN) (Register)))
21 // Pci Root Bridge Io Module Variables
23 EFI_METRONOME_ARCH_PROTOCOL
*mMetronome
;
24 EFI_CPU_IO2_PROTOCOL
*mCpuIo
;
27 SimpleIioRootBridgeConstructor (
28 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*Protocol
,
29 IN EFI_HANDLE HostBridgeHandle
,
30 IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE
*ResAperture
,
31 UINT64 AllocAttributes
37 Construct the Pci Root Bridge Io protocol.
41 Protocol - Protocol to initialize.
42 HostBridgeHandle - Handle to the HostBridge.
43 ResAperture - Resource apperture of the root bridge.
44 AllocAttributes - Attribute of resouce allocated.
48 EFI_SUCCESS - Success.
54 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
55 PCI_RESOURCE_TYPE Index
;
59 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol
);
62 // Initialize the apertures with default values
65 &PrivateData
->Aperture
,
67 sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE
)
70 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
71 PrivateData
->ResAllocNode
[Index
].Type
= Index
;
72 PrivateData
->ResAllocNode
[Index
].Base
= 0;
73 PrivateData
->ResAllocNode
[Index
].Length
= 0;
74 PrivateData
->ResAllocNode
[Index
].Status
= ResNone
;
77 EfiInitializeLock (&PrivateData
->PciLock
, TPL_HIGH_LEVEL
);
78 PrivateData
->PciAddress
= 0xCF8;
79 PrivateData
->PciData
= 0xCFC;
81 PrivateData
->RootBridgeAllocAttrib
= AllocAttributes
;
82 PrivateData
->Attributes
= 0;
83 PrivateData
->Supports
= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
|
84 EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
|
85 EFI_PCI_ATTRIBUTE_ISA_IO_16
|
86 EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
|
87 EFI_PCI_ATTRIBUTE_VGA_MEMORY
|
88 EFI_PCI_ATTRIBUTE_VGA_IO_16
;
91 // Don't support BASE above 4GB currently
92 // Position to bit 39:28
94 HecBase
= (UINT32
) PcdGet64 (PcdPciExpressBaseAddress
);
95 HecSize
= (UINT32
) PcdGet64 (PcdPciExpressSize
);
97 ASSERT ((HecBase
& (HecSize
- 1)) == 0);
98 ASSERT (HecBase
!= 0);
100 PrivateData
->HecBase
= HecBase
;
101 PrivateData
->HecLen
= HecSize
;
103 PrivateData
->BusNumberAssigned
= FALSE
;
104 PrivateData
->BusScanCount
= 0;
106 Protocol
->ParentHandle
= HostBridgeHandle
;
108 Protocol
->PollMem
= RootBridgeIoPollMem
;
109 Protocol
->PollIo
= RootBridgeIoPollIo
;
111 Protocol
->Mem
.Read
= RootBridgeIoMemRead
;
112 Protocol
->Mem
.Write
= RootBridgeIoMemWrite
;
114 Protocol
->Io
.Read
= RootBridgeIoIoRead
;
115 Protocol
->Io
.Write
= RootBridgeIoIoWrite
;
117 Protocol
->CopyMem
= RootBridgeIoCopyMem
;
119 Protocol
->Pci
.Read
= RootBridgeIoPciRead
;
120 Protocol
->Pci
.Write
= RootBridgeIoPciWrite
;
122 Protocol
->Map
= RootBridgeIoMap
;
123 Protocol
->Unmap
= RootBridgeIoUnmap
;
125 Protocol
->AllocateBuffer
= RootBridgeIoAllocateBuffer
;
126 Protocol
->FreeBuffer
= RootBridgeIoFreeBuffer
;
128 Protocol
->Flush
= RootBridgeIoFlush
;
130 Protocol
->GetAttributes
= RootBridgeIoGetAttributes
;
131 Protocol
->SetAttributes
= RootBridgeIoSetAttributes
;
133 Protocol
->Configuration
= RootBridgeIoConfiguration
;
135 Protocol
->SegmentNumber
= 0;
137 Status
= gBS
->LocateProtocol (&gEfiMetronomeArchProtocolGuid
, NULL
, (VOID
**) &mMetronome
);
138 ASSERT_EFI_ERROR (Status
);
140 Status
= gBS
->LocateProtocol (
141 &gEfiCpuIo2ProtocolGuid
,
145 ASSERT_EFI_ERROR (Status
);
152 RootBridgeIoPollMem (
153 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
154 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
165 Poll an address in memory mapped space until an exit condition is met
170 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
171 Width - Width of the memory operation.
172 Address - The base address of the memory operation.
173 Mask - Mask used for polling criteria.
174 Value - Comparison value used for polling exit criteria.
175 Delay - Number of 100ns units to poll.
176 Result - Pointer to the last value read from memory location.
180 EFI_SUCCESS - Success.
181 EFI_INVALID_PARAMETER - Invalid parameter found.
182 EFI_TIMEOUT - Delay expired before a match occurred.
183 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
188 UINT64 NumberOfTicks
;
191 if (Result
== NULL
) {
192 return EFI_INVALID_PARAMETER
;
195 if (Width
< 0 || Width
> EfiPciWidthUint64
) {
196 return EFI_INVALID_PARAMETER
;
199 // No matter what, always do a single poll.
201 Status
= This
->Mem
.Read (
208 if (EFI_ERROR (Status
)) {
212 if ((*Result
& Mask
) == Value
) {
218 // Determine the proper # of metronome ticks to wait for polling the
219 // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
220 // The "+1" to account for the possibility of the first tick being short
221 // because we started in the middle of a tick.
223 // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
224 // protocol definition is updated.
226 NumberOfTicks
= DivU64x32Remainder (
228 (UINT32
) mMetronome
->TickPeriod
,
231 if (Remainder
!= 0) {
237 while (NumberOfTicks
) {
239 mMetronome
->WaitForTick (mMetronome
, 1);
241 Status
= This
->Mem
.Read (
248 if (EFI_ERROR (Status
)) {
252 if ((*Result
& Mask
) == Value
) {
266 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
267 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
278 Poll an address in I/O space until an exit condition is met
283 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
284 Width - Width of I/O operation.
285 Address - The base address of the I/O operation.
286 Mask - Mask used for polling criteria.
287 Value - Comparison value used for polling exit criteria.
288 Delay - Number of 100ns units to poll.
289 Result - Pointer to the last value read from memory location.
293 EFI_SUCCESS - Success.
294 EFI_INVALID_PARAMETER - Invalid parameter found.
295 EFI_TIMEOUT - Delay expired before a match occurred.
296 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
301 UINT64 NumberOfTicks
;
305 // No matter what, always do a single poll.
307 if (Result
== NULL
) {
308 return EFI_INVALID_PARAMETER
;
311 if (Width
< 0 || Width
> EfiPciWidthUint64
) {
312 return EFI_INVALID_PARAMETER
;
315 Status
= This
->Io
.Read (
322 if (EFI_ERROR (Status
)) {
326 if ((*Result
& Mask
) == Value
) {
332 // Determine the proper # of metronome ticks to wait for polling the
333 // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
334 // The "+1" to account for the possibility of the first tick being short
335 // because we started in the middle of a tick.
337 NumberOfTicks
= DivU64x32Remainder (
339 (UINT32
) mMetronome
->TickPeriod
,
342 if (Remainder
!= 0) {
348 while (NumberOfTicks
) {
350 mMetronome
->WaitForTick (mMetronome
, 1);
352 Status
= This
->Io
.Read (
359 if (EFI_ERROR (Status
)) {
363 if ((*Result
& Mask
) == Value
) {
376 RootBridgeIoMemRead (
377 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
378 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
387 Allow read from memory mapped I/O space.
391 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
392 Width - The width of memory operation.
393 Address - Base address of the memory operation.
394 Count - Number of memory opeartion to perform.
395 Buffer - The destination buffer to store data.
399 EFI_SUCCESS - Success.
400 EFI_INVALID_PARAMETER - Invalid parameter found.
401 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
405 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
406 if (Buffer
== NULL
) {
407 return EFI_INVALID_PARAMETER
;
411 Width
== EfiPciWidthUint64
||
412 Width
== EfiPciWidthFifoUint64
||
413 Width
== EfiPciWidthFillUint64
||
414 Width
>= EfiPciWidthMaximum
416 return EFI_INVALID_PARAMETER
;
419 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
421 // Check memory access limit
423 if (PrivateData
->Aperture
.Mem64Limit
> PrivateData
->Aperture
.Mem64Base
) {
424 if (Address
> PrivateData
->Aperture
.Mem64Limit
) {
425 return EFI_INVALID_PARAMETER
;
428 if (Address
> PrivateData
->Aperture
.Mem32Limit
) {
429 return EFI_INVALID_PARAMETER
;
433 return mCpuIo
->Mem
.Read (
435 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
444 RootBridgeIoMemWrite (
445 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
446 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
455 Allow write to memory mapped I/O space.
459 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
460 Width - The width of memory operation.
461 Address - Base address of the memory operation.
462 Count - Number of memory opeartion to perform.
463 Buffer - The source buffer to write data from.
467 EFI_SUCCESS - Success.
468 EFI_INVALID_PARAMETER - Invalid parameter found.
469 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
473 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
475 if (Buffer
== NULL
) {
476 return EFI_INVALID_PARAMETER
;
480 Width
== EfiPciWidthUint64
||
481 Width
== EfiPciWidthFifoUint64
||
482 Width
== EfiPciWidthFillUint64
||
483 Width
>= EfiPciWidthMaximum
485 return EFI_INVALID_PARAMETER
;
488 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
491 // Check memory access limit
493 if (PrivateData
->Aperture
.Mem64Limit
> PrivateData
->Aperture
.Mem64Base
) {
494 if (Address
> PrivateData
->Aperture
.Mem64Limit
) {
495 return EFI_INVALID_PARAMETER
;
498 if (Address
> PrivateData
->Aperture
.Mem32Limit
) {
499 return EFI_INVALID_PARAMETER
;
503 return mCpuIo
->Mem
.Write (
505 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
515 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
516 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
525 Enable a PCI driver to read PCI controller registers in the
526 PCI root bridge I/O space.
530 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
531 Width - Signifies the width of the memory operation.
532 Address - The base address of the I/O operation.
533 Count - The number of I/O operations to perform.
534 Buffer - The destination buffer to store the results.
538 EFI_SUCCESS - The data was read from the PCI root bridge.
539 EFI_INVALID_PARAMETER - Invalid parameters found.
540 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
546 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
548 if (Buffer
== NULL
) {
549 return EFI_INVALID_PARAMETER
;
553 Width
== EfiPciWidthUint64
||
554 Width
== EfiPciWidthFifoUint64
||
555 Width
== EfiPciWidthFillUint64
||
556 Width
>= EfiPciWidthMaximum
558 return EFI_INVALID_PARAMETER
;
561 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
564 // AlignMask = (1 << Width) - 1;
566 AlignMask
= (1 << (Width
& 0x03)) - 1;
569 // check Io access limit
571 if (Address
> PrivateData
->Aperture
.IoLimit
) {
572 return EFI_INVALID_PARAMETER
;
575 if (Address
& AlignMask
) {
576 return EFI_INVALID_PARAMETER
;
579 return mCpuIo
->Io
.Read (
581 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
591 RootBridgeIoIoWrite (
592 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
593 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
602 Enable a PCI driver to write to PCI controller registers in the
603 PCI root bridge I/O space.
607 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
608 Width - Signifies the width of the memory operation.
609 Address - The base address of the I/O operation.
610 Count - The number of I/O operations to perform.
611 Buffer - The source buffer to write data from.
615 EFI_SUCCESS - The data was written to the PCI root bridge.
616 EFI_INVALID_PARAMETER - Invalid parameters found.
617 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
622 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
624 if (Buffer
== NULL
) {
625 return EFI_INVALID_PARAMETER
;
629 Width
== EfiPciWidthUint64
||
630 Width
== EfiPciWidthFifoUint64
||
631 Width
== EfiPciWidthFillUint64
||
632 Width
>= EfiPciWidthMaximum
634 return EFI_INVALID_PARAMETER
;
637 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
640 // AlignMask = (1 << Width) - 1;
642 AlignMask
= (1 << (Width
& 0x03)) - 1;
645 // Check Io access limit
647 if (Address
> PrivateData
->Aperture
.IoLimit
) {
648 return EFI_INVALID_PARAMETER
;
651 if (Address
& AlignMask
) {
652 return EFI_INVALID_PARAMETER
;
655 return mCpuIo
->Io
.Write (
657 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
667 RootBridgeIoCopyMem (
668 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
669 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
670 IN UINT64 DestAddress
,
671 IN UINT64 SrcAddress
,
678 Copy one region of PCI root bridge memory space to be copied to
679 another region of PCI root bridge memory space.
683 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
684 Width - Signifies the width of the memory operation.
685 DestAddress - Destination address of the memory operation.
686 SrcAddress - Source address of the memory operation.
687 Count - Number of memory operations to perform.
691 EFI_SUCCESS - The data was copied successfully.
692 EFI_INVALID_PARAMETER - Invalid parameters found.
693 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
703 if (Width
< 0 || Width
> EfiPciWidthUint64
) {
704 return EFI_INVALID_PARAMETER
;
707 if (DestAddress
== SrcAddress
) {
711 Stride
= (UINTN
)1 << Width
;
714 if ((DestAddress
> SrcAddress
) && (DestAddress
< (SrcAddress
+ Count
* Stride
))) {
716 SrcAddress
= SrcAddress
+ (Count
- 1) * Stride
;
717 DestAddress
= DestAddress
+ (Count
- 1) * Stride
;
720 for (Index
= 0; Index
< Count
; Index
++) {
721 Status
= RootBridgeIoMemRead (
728 if (EFI_ERROR (Status
)) {
732 Status
= RootBridgeIoMemWrite (
739 if (EFI_ERROR (Status
)) {
744 SrcAddress
+= Stride
;
745 DestAddress
+= Stride
;
747 SrcAddress
-= Stride
;
748 DestAddress
-= Stride
;
757 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
759 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
760 IN UINT64 UserAddress
,
762 IN OUT VOID
*UserBuffer
774 PCI_CONFIG_ACCESS_CF8 Pci
;
775 PCI_CONFIG_ACCESS_CF8 PciAligned
;
779 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
781 if (Width
>= EfiPciWidthMaximum
) {
782 return EFI_INVALID_PARAMETER
;
785 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This
);
787 ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*)&UserAddress
)->ExtendedRegister
== 0x00);
791 Pci
.Bits
.Reg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Register
;
792 Pci
.Bits
.Func
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Function
;
793 Pci
.Bits
.Dev
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Device
;
794 Pci
.Bits
.Bus
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Bus
;
795 Pci
.Bits
.Reserved
= 0;
799 // PCI Configure access are all 32-bit aligned, but by accessing the
800 // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
801 // are possible on PCI.
803 // To read a byte of PCI configuration space you load 0xcf8 and
804 // read 0xcfc, 0xcfd, 0xcfe, 0xcff
806 PciDataStride
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Register
& 0x03;
810 PciAligned
.Bits
.Reg
&= 0xfc;
811 PciData
= PrivateData
->PciData
+ PciDataStride
;
812 EfiAcquireLock(&PrivateData
->PciLock
);
813 This
->Io
.Write (This
, EfiPciWidthUint32
, \
814 PrivateData
->PciAddress
, 1, &PciAligned
);
816 This
->Io
.Write (This
, Width
, PciData
, 1, UserBuffer
);
818 This
->Io
.Read (This
, Width
, PciData
, 1, UserBuffer
);
820 EfiReleaseLock(&PrivateData
->PciLock
);
821 UserBuffer
= ((UINT8
*)UserBuffer
) + Stride
;
822 PciDataStride
= (PciDataStride
+ Stride
) % 4;
826 // Only increment the PCI address if Width is not a FIFO.
828 if (Width
>= EfiPciWidthUint8
&& Width
<= EfiPciWidthUint64
) {
829 Pci
.Bits
.Reg
+= Stride
;
837 RootBridgeIoPciRead (
838 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
839 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
848 Allows read from PCI configuration space.
852 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
853 Width - Signifies the width of the memory operation.
854 Address - The address within the PCI configuration space
855 for the PCI controller.
856 Count - The number of PCI configuration operations
858 Buffer - The destination buffer to store the results.
862 EFI_SUCCESS - The data was read from the PCI root bridge.
863 EFI_INVALID_PARAMETER - Invalid parameters found.
864 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
868 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
875 if (Buffer
== NULL
) {
876 return EFI_INVALID_PARAMETER
;
880 Width
== EfiPciWidthUint64
||
881 Width
== EfiPciWidthFifoUint64
||
882 Width
== EfiPciWidthFillUint64
||
883 Width
>= EfiPciWidthMaximum
885 return EFI_INVALID_PARAMETER
;
889 // Read Pci configuration space
891 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
893 if (PrivateData
->HecBase
== 0) {
894 return RootBridgeIoPciRW (This
, FALSE
, Width
, Address
, Count
, Buffer
);
897 if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->ExtendedRegister
) {
898 PciExtReg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Register
;
900 PciExtReg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->ExtendedRegister
& 0x0FFF;
903 PciBus
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Bus
;
904 PciDev
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Device
;
905 PciFn
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Function
;
907 ExtConfigAdd
= (UINT64
) PrivateData
->HecBase
+ PCIE_OFF (PciBus
, PciDev
, PciFn
, PciExtReg
);
909 return mCpuIo
->Mem
.Read (
911 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
920 RootBridgeIoPciWrite (
921 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
922 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
931 Allows write to PCI configuration space.
935 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
936 Width - Signifies the width of the memory operation.
937 Address - The address within the PCI configuration space
938 for the PCI controller.
939 Count - The number of PCI configuration operations
941 Buffer - The source buffer to get the results.
945 EFI_SUCCESS - The data was written to the PCI root bridge.
946 EFI_INVALID_PARAMETER - Invalid parameters found.
947 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
951 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
958 if (Buffer
== NULL
) {
959 return EFI_INVALID_PARAMETER
;
962 if (Width
< 0 || Width
>= EfiPciWidthMaximum
) {
963 return EFI_INVALID_PARAMETER
;
967 // Write Pci configuration space
969 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
971 if (PrivateData
->HecBase
== 0) {
972 return RootBridgeIoPciRW (This
, TRUE
, Width
, Address
, Count
, Buffer
);
975 if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->ExtendedRegister
) {
976 PciExtReg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Register
;
978 PciExtReg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->ExtendedRegister
& 0x0FFF;
981 PciBus
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Bus
;
982 PciDev
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Device
;
983 PciFn
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Function
;
985 ExtConfigAdd
= (UINT64
) PrivateData
->HecBase
+ PCIE_OFF (PciBus
, PciDev
, PciFn
, PciExtReg
);
987 return mCpuIo
->Mem
.Write (
989 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
999 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1000 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation
,
1001 IN VOID
*HostAddress
,
1002 IN OUT UINTN
*NumberOfBytes
,
1003 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1008 Routine Description:
1010 Provides the PCI controller-specific address needed to access
1011 system memory for DMA.
1015 This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1016 Operation - Indicate if the bus master is going to read or write
1018 HostAddress - The system memory address to map on the PCI controller.
1019 NumberOfBytes - On input the number of bytes to map.
1020 On output the number of bytes that were mapped.
1021 DeviceAddress - The resulting map address for the bus master PCI
1022 controller to use to access the system memory's HostAddress.
1023 Mapping - The value to pass to Unmap() when the bus master DMA
1024 operation is complete.
1028 EFI_SUCCESS - Success.
1029 EFI_INVALID_PARAMETER - Invalid parameters found.
1030 EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common
1032 EFI_DEVICE_ERROR - The System hardware could not map the requested
1034 EFI_OUT_OF_RESOURCES - The request could not be completed due to
1040 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1043 if (NumberOfBytes
== NULL
|| Mapping
== NULL
|| DeviceAddress
== NULL
|| HostAddress
== NULL
) {
1044 return EFI_INVALID_PARAMETER
;
1047 // Initialize the return values to their defaults
1052 // Make sure that Operation is valid
1054 if ((Operation
< 0) || (Operation
> EfiPciOperationBusMasterCommonBuffer64
)) {
1055 return EFI_INVALID_PARAMETER
;
1058 // Most PCAT like chipsets can not handle performing DMA above 4GB.
1059 // If any part of the DMA transfer being mapped is above 4GB, then
1060 // map the DMA transfer to a buffer below 4GB.
1062 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1063 if ((PhysicalAddress
+*NumberOfBytes
) > 0x100000000ULL
) {
1065 // Common Buffer operations can not be remapped. If the common buffer
1066 // if above 4GB, then it is not possible to generate a mapping, so return
1069 if (Operation
== EfiPciOperationBusMasterCommonBuffer
|| Operation
== EfiPciOperationBusMasterCommonBuffer64
) {
1070 return EFI_INVALID_PARAMETER
;
1074 if ((PhysicalAddress
+ *NumberOfBytes
) > (DMA_MEMORY_TOP
+1)) {
1077 // Common Buffer operations can not be remapped.
1079 if (Operation
== EfiPciOperationBusMasterCommonBuffer
|| Operation
== EfiPciOperationBusMasterCommonBuffer64
) {
1080 *DeviceAddress
= PhysicalAddress
;
1084 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
1087 Status
= gBS
->AllocatePool (
1088 EfiBootServicesData
,
1092 if (EFI_ERROR (Status
)) {
1097 // Return a pointer to the MAP_INFO structure in Mapping
1102 // Initialize the MAP_INFO structure
1104 MapInfo
->Operation
= Operation
;
1105 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
1106 MapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1107 MapInfo
->HostAddress
= PhysicalAddress
;
1108 MapInfo
->MappedHostAddress
= DMA_MEMORY_TOP
;
1111 // Allocate a buffer below DMA_MEMORY_TOP to map the transfer to.
1113 Status
= gBS
->AllocatePages (
1115 EfiBootServicesData
,
1116 MapInfo
->NumberOfPages
,
1117 &MapInfo
->MappedHostAddress
1119 if (EFI_ERROR (Status
)) {
1120 gBS
->FreePool (MapInfo
);
1125 // If this is a read operation from the Bus Master's point of view,
1126 // then copy the contents of the real buffer into the mapped buffer
1127 // so the Bus Master can read the contents of the real buffer.
1129 if (Operation
== EfiPciOperationBusMasterRead
|| Operation
== EfiPciOperationBusMasterRead64
) {
1131 (VOID
*) (UINTN
) MapInfo
->MappedHostAddress
,
1132 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
1133 MapInfo
->NumberOfBytes
1137 // The DeviceAddress is the address of the maped buffer below DMA_MEMORY_TOP
1139 *DeviceAddress
= MapInfo
->MappedHostAddress
;
1142 // The transfer is below DMA_MEMORY_TOP, so the DeviceAddress is simply the HostAddress
1144 *DeviceAddress
= PhysicalAddress
;
1153 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1158 Routine Description:
1160 Completes the Map() operation and releases any corresponding resources.
1164 This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1165 Mapping - The value returned from Map() operation.
1169 EFI_SUCCESS - The range was unmapped successfully.
1170 EFI_INVALID_PARAMETER - Mapping is not a value that was returned
1172 EFI_DEVICE_ERROR - The data was not committed to the target
1180 // See if the Map() operation associated with this Unmap() required a mapping buffer.
1181 // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
1183 if (Mapping
!= NULL
) {
1185 // Get the MAP_INFO structure from Mapping
1187 MapInfo
= (MAP_INFO
*) Mapping
;
1190 // If this is a write operation from the Bus Master's point of view,
1191 // then copy the contents of the mapped buffer into the real buffer
1192 // so the processor can read the contents of the real buffer.
1194 if ((MapInfo
->Operation
== EfiPciOperationBusMasterWrite
) ||
1195 (MapInfo
->Operation
== EfiPciOperationBusMasterWrite64
)
1198 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
1199 (VOID
*) (UINTN
) MapInfo
->MappedHostAddress
,
1200 MapInfo
->NumberOfBytes
1204 // Free the mapped buffer and the MAP_INFO structure.
1206 gBS
->FreePages (MapInfo
->MappedHostAddress
, MapInfo
->NumberOfPages
);
1207 gBS
->FreePool (Mapping
);
1215 RootBridgeIoAllocateBuffer (
1216 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1217 IN EFI_ALLOCATE_TYPE Type
,
1218 IN EFI_MEMORY_TYPE MemoryType
,
1220 OUT VOID
**HostAddress
,
1221 IN UINT64 Attributes
1225 Routine Description:
1227 Allocates pages that are suitable for a common buffer mapping.
1231 This - Pointer to EFI_ROOT_BRIDGE_IO_PROTOCOL instance.
1232 Type - Not used and can be ignored.
1233 MemoryType - Type of memory to allocate.
1234 Pages - Number of pages to allocate.
1235 HostAddress - Pointer to store the base system memory address
1236 of the allocated range.
1237 Attributes - Requested bit mask of attributes of the allocated
1242 EFI_SUCCESS - The requested memory range were allocated.
1243 EFI_INVALID_PARAMETER - Invalid parameter found.
1244 EFI_UNSUPPORTED - Attributes is unsupported.
1249 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1252 // Validate Attributes
1254 if ((Attributes
& EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER
) != 0) {
1255 return EFI_UNSUPPORTED
;
1258 // Check for invalid inputs
1260 if (HostAddress
== NULL
) {
1261 return EFI_INVALID_PARAMETER
;
1264 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1266 if ((MemoryType
!= EfiBootServicesData
) && (MemoryType
!= EfiRuntimeServicesData
)) {
1267 return EFI_INVALID_PARAMETER
;
1270 // Limit allocations to memory below DMA_MEMORY_TOP
1272 PhysicalAddress
= DMA_MEMORY_TOP
;
1274 Status
= gBS
->AllocatePages (
1280 if (EFI_ERROR (Status
)) {
1284 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1291 RootBridgeIoFreeBuffer (
1292 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1294 OUT VOID
*HostAddress
1298 Routine Description:
1300 Free memory allocated in AllocateBuffer.
1304 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1306 Pages - Number of pages to free.
1307 HostAddress - The base system memory address of the
1312 EFI_SUCCESS - Requested memory pages were freed.
1313 EFI_INVALID_PARAMETER - Invalid parameter found.
1317 return gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
, Pages
);
1323 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
1327 Routine Description:
1329 Flushes all PCI posted write transactions from a PCI host
1330 bridge to system memory.
1334 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1338 EFI_SUCCESS - PCI posted write transactions were flushed
1339 from PCI host bridge to system memory.
1340 EFI_DEVICE_ERROR - Fail due to hardware error.
1345 // not supported yet
1352 RootBridgeIoGetAttributes (
1353 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1354 OUT UINT64
*Supported
,
1355 OUT UINT64
*Attributes
1359 Routine Description:
1361 Get the attributes that a PCI root bridge supports and
1362 the attributes the PCI root bridge is currently using.
1366 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1368 Supports - A pointer to the mask of attributes that
1369 this PCI root bridge supports.
1370 Attributes - A pointer to the mask of attributes that
1371 this PCI root bridge is currently using.
1374 EFI_SUCCESS - Success.
1375 EFI_INVALID_PARAMETER - Invalid parameter found.
1379 // GC_TODO: Supported - add argument and description to function comment
1381 // GC_TODO: Supported - add argument and description to function comment
1383 // GC_TODO: Supported - add argument and description to function comment
1386 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
1388 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
1390 if (Attributes
== NULL
&& Supported
== NULL
) {
1391 return EFI_INVALID_PARAMETER
;
1394 // Set the return value for Supported and Attributes
1397 *Supported
= PrivateData
->Supports
;
1401 *Attributes
= PrivateData
->Attributes
;
1409 RootBridgeIoSetAttributes (
1410 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1411 IN UINT64 Attributes
,
1412 IN OUT UINT64
*ResourceBase
,
1413 IN OUT UINT64
*ResourceLength
1417 Routine Description:
1419 Sets the attributes for a resource range on a PCI root bridge.
1423 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1424 Attributes - The mask of attributes to set.
1425 ResourceBase - Pointer to the base address of the resource range
1426 to be modified by the attributes specified by Attributes.
1427 ResourceLength - Pointer to the length of the resource range to be modified.
1430 EFI_SUCCESS - Success.
1431 EFI_INVALID_PARAMETER - Invalid parameter found.
1432 EFI_OUT_OF_RESOURCES - Not enough resources to set the attributes upon.
1437 // GC_TODO: EFI_UNSUPPORTED - add return value to function comment
1440 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
1442 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
1444 if (Attributes
!= 0) {
1445 Attributes
&= (PrivateData
->Supports
);
1446 if (Attributes
== 0) {
1447 return EFI_UNSUPPORTED
;
1451 if (Attributes
== PrivateData
->Attributes
) {
1455 // It is just a trick for some attribute can only be enabled or disabled
1456 // otherwise it can impact on other devices
1458 PrivateData
->Attributes
= Attributes
;
1465 RootBridgeIoConfiguration (
1466 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1467 OUT VOID
**Resources
1471 Routine Description:
1473 Retrieves the current resource settings of this PCI root bridge
1474 in the form of a set of ACPI 2.0 resource descriptor.
1478 This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1479 Resources - Pointer to the ACPI 2.0 resource descriptor that
1480 describe the current configuration of this PCI root
1485 EFI_SUCCESS - Success.
1486 EFI_UNSUPPORTED - Current configuration of the PCI root bridge
1487 could not be retrieved.
1492 // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1498 PCI_ROOT_BRIDGE_INSTANCE
*RbPrivateData
;
1499 PCI_RES_NODE
*ResAllocNode
;
1500 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Config
;
1503 // Get this instance of the Root Bridge.
1505 RbPrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
1508 // If the pointer is not NULL, it points to a buffer already allocated.
1510 if (RbPrivateData
->ConfigBuffer
== NULL
) {
1511 Status
= gBS
->AllocatePool (
1512 EfiBootServicesData
,
1513 TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
),
1514 &RbPrivateData
->ConfigBuffer
1516 if (EFI_ERROR (Status
)) {
1517 return EFI_OUT_OF_RESOURCES
;
1521 Config
= RbPrivateData
->ConfigBuffer
;
1523 ZeroMem (Config
, TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1525 for (Idx
= 0; Idx
< TypeMax
; Idx
++) {
1527 ResAllocNode
= &RbPrivateData
->ResAllocNode
[Idx
];
1529 if (ResAllocNode
->Status
!= ResAllocated
) {
1533 switch (ResAllocNode
->Type
) {
1536 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1537 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1538 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1539 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1540 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1541 Config
->AddrLen
= ResAllocNode
->Length
;
1545 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1546 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1547 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1548 Config
->AddrSpaceGranularity
= 32;
1549 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1550 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1551 Config
->AddrLen
= ResAllocNode
->Length
;
1555 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1556 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1557 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1558 Config
->SpecificFlag
= 6;
1559 Config
->AddrSpaceGranularity
= 32;
1560 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1561 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1562 Config
->AddrLen
= ResAllocNode
->Length
;
1566 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1567 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1568 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1569 Config
->SpecificFlag
= 6;
1570 Config
->AddrSpaceGranularity
= 64;
1571 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1572 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1573 Config
->AddrLen
= ResAllocNode
->Length
;
1577 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1578 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1579 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1580 Config
->SpecificFlag
= 6;
1581 Config
->AddrSpaceGranularity
= 64;
1582 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1583 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1584 Config
->AddrLen
= ResAllocNode
->Length
;
1588 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1589 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1590 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
1591 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1592 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1593 Config
->AddrLen
= ResAllocNode
->Length
;
1603 // Terminate the entries.
1605 ((EFI_ACPI_END_TAG_DESCRIPTOR
*) Config
)->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1606 ((EFI_ACPI_END_TAG_DESCRIPTOR
*) Config
)->Checksum
= 0x0;
1608 *Resources
= RbPrivateData
->ConfigBuffer
;