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 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "PciRootBridge.h"
21 // Define PCI express offse
23 #define PCIE_OFF(Bus, Device, Function, Register) \
24 ((UINT64) ((UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) (Function << 12) + (UINTN) (Register)))
27 // Pci Root Bridge Io Module Variables
29 EFI_METRONOME_ARCH_PROTOCOL
*mMetronome
;
30 EFI_CPU_IO2_PROTOCOL
*mCpuIo
;
33 SimpleIioRootBridgeConstructor (
34 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*Protocol
,
35 IN EFI_HANDLE HostBridgeHandle
,
36 IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE
*ResAperture
,
37 UINT64 AllocAttributes
43 Construct the Pci Root Bridge Io protocol.
47 Protocol - Protocol to initialize.
48 HostBridgeHandle - Handle to the HostBridge.
49 ResAperture - Resource apperture of the root bridge.
50 AllocAttributes - Attribute of resouce allocated.
54 EFI_SUCCESS - Success.
60 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
61 PCI_RESOURCE_TYPE Index
;
65 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol
);
68 // Initialize the apertures with default values
71 &PrivateData
->Aperture
,
73 sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE
)
76 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
77 PrivateData
->ResAllocNode
[Index
].Type
= Index
;
78 PrivateData
->ResAllocNode
[Index
].Base
= 0;
79 PrivateData
->ResAllocNode
[Index
].Length
= 0;
80 PrivateData
->ResAllocNode
[Index
].Status
= ResNone
;
83 EfiInitializeLock (&PrivateData
->PciLock
, TPL_HIGH_LEVEL
);
84 PrivateData
->PciAddress
= 0xCF8;
85 PrivateData
->PciData
= 0xCFC;
87 PrivateData
->RootBridgeAllocAttrib
= AllocAttributes
;
88 PrivateData
->Attributes
= 0;
89 PrivateData
->Supports
= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
|
90 EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
|
91 EFI_PCI_ATTRIBUTE_ISA_IO_16
|
92 EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
|
93 EFI_PCI_ATTRIBUTE_VGA_MEMORY
|
94 EFI_PCI_ATTRIBUTE_VGA_IO_16
;
97 // Don't support BASE above 4GB currently
98 // Position to bit 39:28
100 HecBase
= (UINT32
) PcdGet64 (PcdPciExpressBaseAddress
);
101 HecSize
= (UINT32
) PcdGet64 (PcdPciExpressSize
);
103 ASSERT ((HecBase
& (HecSize
- 1)) == 0);
104 ASSERT (HecBase
!= 0);
106 PrivateData
->HecBase
= HecBase
;
107 PrivateData
->HecLen
= HecSize
;
109 PrivateData
->BusNumberAssigned
= FALSE
;
110 PrivateData
->BusScanCount
= 0;
112 Protocol
->ParentHandle
= HostBridgeHandle
;
114 Protocol
->PollMem
= RootBridgeIoPollMem
;
115 Protocol
->PollIo
= RootBridgeIoPollIo
;
117 Protocol
->Mem
.Read
= RootBridgeIoMemRead
;
118 Protocol
->Mem
.Write
= RootBridgeIoMemWrite
;
120 Protocol
->Io
.Read
= RootBridgeIoIoRead
;
121 Protocol
->Io
.Write
= RootBridgeIoIoWrite
;
123 Protocol
->CopyMem
= RootBridgeIoCopyMem
;
125 Protocol
->Pci
.Read
= RootBridgeIoPciRead
;
126 Protocol
->Pci
.Write
= RootBridgeIoPciWrite
;
128 Protocol
->Map
= RootBridgeIoMap
;
129 Protocol
->Unmap
= RootBridgeIoUnmap
;
131 Protocol
->AllocateBuffer
= RootBridgeIoAllocateBuffer
;
132 Protocol
->FreeBuffer
= RootBridgeIoFreeBuffer
;
134 Protocol
->Flush
= RootBridgeIoFlush
;
136 Protocol
->GetAttributes
= RootBridgeIoGetAttributes
;
137 Protocol
->SetAttributes
= RootBridgeIoSetAttributes
;
139 Protocol
->Configuration
= RootBridgeIoConfiguration
;
141 Protocol
->SegmentNumber
= 0;
143 Status
= gBS
->LocateProtocol (&gEfiMetronomeArchProtocolGuid
, NULL
, (VOID
**) &mMetronome
);
144 ASSERT_EFI_ERROR (Status
);
146 Status
= gBS
->LocateProtocol (
147 &gEfiCpuIo2ProtocolGuid
,
151 ASSERT_EFI_ERROR (Status
);
158 RootBridgeIoPollMem (
159 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
160 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
171 Poll an address in memory mapped space until an exit condition is met
176 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
177 Width - Width of the memory operation.
178 Address - The base address of the memory operation.
179 Mask - Mask used for polling criteria.
180 Value - Comparison value used for polling exit criteria.
181 Delay - Number of 100ns units to poll.
182 Result - Pointer to the last value read from memory location.
186 EFI_SUCCESS - Success.
187 EFI_INVALID_PARAMETER - Invalid parameter found.
188 EFI_TIMEOUT - Delay expired before a match occurred.
189 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
194 UINT64 NumberOfTicks
;
197 if (Result
== NULL
) {
198 return EFI_INVALID_PARAMETER
;
201 if (Width
< 0 || Width
> EfiPciWidthUint64
) {
202 return EFI_INVALID_PARAMETER
;
205 // No matter what, always do a single poll.
207 Status
= This
->Mem
.Read (
214 if (EFI_ERROR (Status
)) {
218 if ((*Result
& Mask
) == Value
) {
224 // Determine the proper # of metronome ticks to wait for polling the
225 // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
226 // The "+1" to account for the possibility of the first tick being short
227 // because we started in the middle of a tick.
229 // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
230 // protocol definition is updated.
232 NumberOfTicks
= DivU64x32Remainder (
234 (UINT32
) mMetronome
->TickPeriod
,
237 if (Remainder
!= 0) {
243 while (NumberOfTicks
) {
245 mMetronome
->WaitForTick (mMetronome
, 1);
247 Status
= This
->Mem
.Read (
254 if (EFI_ERROR (Status
)) {
258 if ((*Result
& Mask
) == Value
) {
272 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
273 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
284 Poll an address in I/O space until an exit condition is met
289 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
290 Width - Width of I/O operation.
291 Address - The base address of the I/O operation.
292 Mask - Mask used for polling criteria.
293 Value - Comparison value used for polling exit criteria.
294 Delay - Number of 100ns units to poll.
295 Result - Pointer to the last value read from memory location.
299 EFI_SUCCESS - Success.
300 EFI_INVALID_PARAMETER - Invalid parameter found.
301 EFI_TIMEOUT - Delay expired before a match occurred.
302 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
307 UINT64 NumberOfTicks
;
311 // No matter what, always do a single poll.
313 if (Result
== NULL
) {
314 return EFI_INVALID_PARAMETER
;
317 if (Width
< 0 || Width
> EfiPciWidthUint64
) {
318 return EFI_INVALID_PARAMETER
;
321 Status
= This
->Io
.Read (
328 if (EFI_ERROR (Status
)) {
332 if ((*Result
& Mask
) == Value
) {
338 // Determine the proper # of metronome ticks to wait for polling the
339 // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
340 // The "+1" to account for the possibility of the first tick being short
341 // because we started in the middle of a tick.
343 NumberOfTicks
= DivU64x32Remainder (
345 (UINT32
) mMetronome
->TickPeriod
,
348 if (Remainder
!= 0) {
354 while (NumberOfTicks
) {
356 mMetronome
->WaitForTick (mMetronome
, 1);
358 Status
= This
->Io
.Read (
365 if (EFI_ERROR (Status
)) {
369 if ((*Result
& Mask
) == Value
) {
382 RootBridgeIoMemRead (
383 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
384 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
393 Allow read from memory mapped I/O space.
397 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
398 Width - The width of memory operation.
399 Address - Base address of the memory operation.
400 Count - Number of memory opeartion to perform.
401 Buffer - The destination buffer to store data.
405 EFI_SUCCESS - Success.
406 EFI_INVALID_PARAMETER - Invalid parameter found.
407 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
411 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
412 if (Buffer
== NULL
) {
413 return EFI_INVALID_PARAMETER
;
417 Width
== EfiPciWidthUint64
||
418 Width
== EfiPciWidthFifoUint64
||
419 Width
== EfiPciWidthFillUint64
||
420 Width
>= EfiPciWidthMaximum
422 return EFI_INVALID_PARAMETER
;
425 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
427 // Check memory access limit
429 if (PrivateData
->Aperture
.Mem64Limit
> PrivateData
->Aperture
.Mem64Base
) {
430 if (Address
> PrivateData
->Aperture
.Mem64Limit
) {
431 return EFI_INVALID_PARAMETER
;
434 if (Address
> PrivateData
->Aperture
.Mem32Limit
) {
435 return EFI_INVALID_PARAMETER
;
439 return mCpuIo
->Mem
.Read (
441 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
450 RootBridgeIoMemWrite (
451 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
452 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
461 Allow write to memory mapped I/O space.
465 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
466 Width - The width of memory operation.
467 Address - Base address of the memory operation.
468 Count - Number of memory opeartion to perform.
469 Buffer - The source buffer to write data from.
473 EFI_SUCCESS - Success.
474 EFI_INVALID_PARAMETER - Invalid parameter found.
475 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
479 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
481 if (Buffer
== NULL
) {
482 return EFI_INVALID_PARAMETER
;
486 Width
== EfiPciWidthUint64
||
487 Width
== EfiPciWidthFifoUint64
||
488 Width
== EfiPciWidthFillUint64
||
489 Width
>= EfiPciWidthMaximum
491 return EFI_INVALID_PARAMETER
;
494 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
497 // Check memory access limit
499 if (PrivateData
->Aperture
.Mem64Limit
> PrivateData
->Aperture
.Mem64Base
) {
500 if (Address
> PrivateData
->Aperture
.Mem64Limit
) {
501 return EFI_INVALID_PARAMETER
;
504 if (Address
> PrivateData
->Aperture
.Mem32Limit
) {
505 return EFI_INVALID_PARAMETER
;
509 return mCpuIo
->Mem
.Write (
511 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
521 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
522 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
531 Enable a PCI driver to read PCI controller registers in the
532 PCI root bridge I/O space.
536 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
537 Width - Signifies the width of the memory operation.
538 Address - The base address of the I/O operation.
539 Count - The number of I/O operations to perform.
540 Buffer - The destination buffer to store the results.
544 EFI_SUCCESS - The data was read from the PCI root bridge.
545 EFI_INVALID_PARAMETER - Invalid parameters found.
546 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
552 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
554 if (Buffer
== NULL
) {
555 return EFI_INVALID_PARAMETER
;
559 Width
== EfiPciWidthUint64
||
560 Width
== EfiPciWidthFifoUint64
||
561 Width
== EfiPciWidthFillUint64
||
562 Width
>= EfiPciWidthMaximum
564 return EFI_INVALID_PARAMETER
;
567 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
570 // AlignMask = (1 << Width) - 1;
572 AlignMask
= (1 << (Width
& 0x03)) - 1;
575 // check Io access limit
577 if (Address
> PrivateData
->Aperture
.IoLimit
) {
578 return EFI_INVALID_PARAMETER
;
581 if (Address
& AlignMask
) {
582 return EFI_INVALID_PARAMETER
;
585 return mCpuIo
->Io
.Read (
587 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
597 RootBridgeIoIoWrite (
598 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
599 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
608 Enable a PCI driver to write to PCI controller registers in the
609 PCI root bridge I/O space.
613 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
614 Width - Signifies the width of the memory operation.
615 Address - The base address of the I/O operation.
616 Count - The number of I/O operations to perform.
617 Buffer - The source buffer to write data from.
621 EFI_SUCCESS - The data was written to the PCI root bridge.
622 EFI_INVALID_PARAMETER - Invalid parameters found.
623 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
628 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
630 if (Buffer
== NULL
) {
631 return EFI_INVALID_PARAMETER
;
635 Width
== EfiPciWidthUint64
||
636 Width
== EfiPciWidthFifoUint64
||
637 Width
== EfiPciWidthFillUint64
||
638 Width
>= EfiPciWidthMaximum
640 return EFI_INVALID_PARAMETER
;
643 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
646 // AlignMask = (1 << Width) - 1;
648 AlignMask
= (1 << (Width
& 0x03)) - 1;
651 // Check Io access limit
653 if (Address
> PrivateData
->Aperture
.IoLimit
) {
654 return EFI_INVALID_PARAMETER
;
657 if (Address
& AlignMask
) {
658 return EFI_INVALID_PARAMETER
;
661 return mCpuIo
->Io
.Write (
663 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
673 RootBridgeIoCopyMem (
674 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
675 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
676 IN UINT64 DestAddress
,
677 IN UINT64 SrcAddress
,
684 Copy one region of PCI root bridge memory space to be copied to
685 another region of PCI root bridge memory space.
689 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
690 Width - Signifies the width of the memory operation.
691 DestAddress - Destination address of the memory operation.
692 SrcAddress - Source address of the memory operation.
693 Count - Number of memory operations to perform.
697 EFI_SUCCESS - The data was copied successfully.
698 EFI_INVALID_PARAMETER - Invalid parameters found.
699 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
709 if (Width
< 0 || Width
> EfiPciWidthUint64
) {
710 return EFI_INVALID_PARAMETER
;
713 if (DestAddress
== SrcAddress
) {
717 Stride
= (UINTN
)1 << Width
;
720 if ((DestAddress
> SrcAddress
) && (DestAddress
< (SrcAddress
+ Count
* Stride
))) {
722 SrcAddress
= SrcAddress
+ (Count
- 1) * Stride
;
723 DestAddress
= DestAddress
+ (Count
- 1) * Stride
;
726 for (Index
= 0; Index
< Count
; Index
++) {
727 Status
= RootBridgeIoMemRead (
734 if (EFI_ERROR (Status
)) {
738 Status
= RootBridgeIoMemWrite (
745 if (EFI_ERROR (Status
)) {
750 SrcAddress
+= Stride
;
751 DestAddress
+= Stride
;
753 SrcAddress
-= Stride
;
754 DestAddress
-= Stride
;
763 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
765 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
766 IN UINT64 UserAddress
,
768 IN OUT VOID
*UserBuffer
780 PCI_CONFIG_ACCESS_CF8 Pci
;
781 PCI_CONFIG_ACCESS_CF8 PciAligned
;
785 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
787 if (Width
>= EfiPciWidthMaximum
) {
788 return EFI_INVALID_PARAMETER
;
791 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This
);
793 ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*)&UserAddress
)->ExtendedRegister
== 0x00);
797 Pci
.Bits
.Reg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Register
;
798 Pci
.Bits
.Func
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Function
;
799 Pci
.Bits
.Dev
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Device
;
800 Pci
.Bits
.Bus
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Bus
;
801 Pci
.Bits
.Reserved
= 0;
805 // PCI Configure access are all 32-bit aligned, but by accessing the
806 // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
807 // are possible on PCI.
809 // To read a byte of PCI configuration space you load 0xcf8 and
810 // read 0xcfc, 0xcfd, 0xcfe, 0xcff
812 PciDataStride
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &UserAddress
)->Register
& 0x03;
816 PciAligned
.Bits
.Reg
&= 0xfc;
817 PciData
= PrivateData
->PciData
+ PciDataStride
;
818 EfiAcquireLock(&PrivateData
->PciLock
);
819 This
->Io
.Write (This
, EfiPciWidthUint32
, \
820 PrivateData
->PciAddress
, 1, &PciAligned
);
822 This
->Io
.Write (This
, Width
, PciData
, 1, UserBuffer
);
824 This
->Io
.Read (This
, Width
, PciData
, 1, UserBuffer
);
826 EfiReleaseLock(&PrivateData
->PciLock
);
827 UserBuffer
= ((UINT8
*)UserBuffer
) + Stride
;
828 PciDataStride
= (PciDataStride
+ Stride
) % 4;
832 // Only increment the PCI address if Width is not a FIFO.
834 if (Width
>= EfiPciWidthUint8
&& Width
<= EfiPciWidthUint64
) {
835 Pci
.Bits
.Reg
+= Stride
;
843 RootBridgeIoPciRead (
844 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
845 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
854 Allows read from PCI configuration space.
858 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
859 Width - Signifies the width of the memory operation.
860 Address - The address within the PCI configuration space
861 for the PCI controller.
862 Count - The number of PCI configuration operations
864 Buffer - The destination buffer to store the results.
868 EFI_SUCCESS - The data was read from the PCI root bridge.
869 EFI_INVALID_PARAMETER - Invalid parameters found.
870 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
874 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
881 if (Buffer
== NULL
) {
882 return EFI_INVALID_PARAMETER
;
886 Width
== EfiPciWidthUint64
||
887 Width
== EfiPciWidthFifoUint64
||
888 Width
== EfiPciWidthFillUint64
||
889 Width
>= EfiPciWidthMaximum
891 return EFI_INVALID_PARAMETER
;
895 // Read Pci configuration space
897 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
899 if (PrivateData
->HecBase
== 0) {
900 return RootBridgeIoPciRW (This
, FALSE
, Width
, Address
, Count
, Buffer
);
903 if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->ExtendedRegister
) {
904 PciExtReg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Register
;
906 PciExtReg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->ExtendedRegister
& 0x0FFF;
909 PciBus
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Bus
;
910 PciDev
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Device
;
911 PciFn
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Function
;
913 ExtConfigAdd
= (UINT64
) PrivateData
->HecBase
+ PCIE_OFF (PciBus
, PciDev
, PciFn
, PciExtReg
);
915 return mCpuIo
->Mem
.Read (
917 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
926 RootBridgeIoPciWrite (
927 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
928 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
937 Allows write to PCI configuration space.
941 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
942 Width - Signifies the width of the memory operation.
943 Address - The address within the PCI configuration space
944 for the PCI controller.
945 Count - The number of PCI configuration operations
947 Buffer - The source buffer to get the results.
951 EFI_SUCCESS - The data was written to the PCI root bridge.
952 EFI_INVALID_PARAMETER - Invalid parameters found.
953 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
957 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
964 if (Buffer
== NULL
) {
965 return EFI_INVALID_PARAMETER
;
968 if (Width
< 0 || Width
>= EfiPciWidthMaximum
) {
969 return EFI_INVALID_PARAMETER
;
973 // Write Pci configuration space
975 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
977 if (PrivateData
->HecBase
== 0) {
978 return RootBridgeIoPciRW (This
, TRUE
, Width
, Address
, Count
, Buffer
);
981 if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->ExtendedRegister
) {
982 PciExtReg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Register
;
984 PciExtReg
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->ExtendedRegister
& 0x0FFF;
987 PciBus
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Bus
;
988 PciDev
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Device
;
989 PciFn
= ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
)->Function
;
991 ExtConfigAdd
= (UINT64
) PrivateData
->HecBase
+ PCIE_OFF (PciBus
, PciDev
, PciFn
, PciExtReg
);
993 return mCpuIo
->Mem
.Write (
995 (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
1005 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1006 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation
,
1007 IN VOID
*HostAddress
,
1008 IN OUT UINTN
*NumberOfBytes
,
1009 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1014 Routine Description:
1016 Provides the PCI controller-specific address needed to access
1017 system memory for DMA.
1021 This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1022 Operation - Indicate if the bus master is going to read or write
1024 HostAddress - The system memory address to map on the PCI controller.
1025 NumberOfBytes - On input the number of bytes to map.
1026 On output the number of bytes that were mapped.
1027 DeviceAddress - The resulting map address for the bus master PCI
1028 controller to use to access the system memory's HostAddress.
1029 Mapping - The value to pass to Unmap() when the bus master DMA
1030 operation is complete.
1034 EFI_SUCCESS - Success.
1035 EFI_INVALID_PARAMETER - Invalid parameters found.
1036 EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common
1038 EFI_DEVICE_ERROR - The System hardware could not map the requested
1040 EFI_OUT_OF_RESOURCES - The request could not be completed due to
1046 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1049 if (NumberOfBytes
== NULL
|| Mapping
== NULL
|| DeviceAddress
== NULL
|| HostAddress
== NULL
) {
1050 return EFI_INVALID_PARAMETER
;
1053 // Initialize the return values to their defaults
1058 // Make sure that Operation is valid
1060 if ((Operation
< 0) || (Operation
> EfiPciOperationBusMasterCommonBuffer64
)) {
1061 return EFI_INVALID_PARAMETER
;
1064 // Most PCAT like chipsets can not handle performing DMA above 4GB.
1065 // If any part of the DMA transfer being mapped is above 4GB, then
1066 // map the DMA transfer to a buffer below 4GB.
1068 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1069 if ((PhysicalAddress
+*NumberOfBytes
) > 0x100000000ULL
) {
1071 // Common Buffer operations can not be remapped. If the common buffer
1072 // if above 4GB, then it is not possible to generate a mapping, so return
1075 if (Operation
== EfiPciOperationBusMasterCommonBuffer
|| Operation
== EfiPciOperationBusMasterCommonBuffer64
) {
1076 return EFI_INVALID_PARAMETER
;
1080 if ((PhysicalAddress
+ *NumberOfBytes
) > (DMA_MEMORY_TOP
+1)) {
1083 // Common Buffer operations can not be remapped.
1085 if (Operation
== EfiPciOperationBusMasterCommonBuffer
|| Operation
== EfiPciOperationBusMasterCommonBuffer64
) {
1086 *DeviceAddress
= PhysicalAddress
;
1090 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
1093 Status
= gBS
->AllocatePool (
1094 EfiBootServicesData
,
1098 if (EFI_ERROR (Status
)) {
1103 // Return a pointer to the MAP_INFO structure in Mapping
1108 // Initialize the MAP_INFO structure
1110 MapInfo
->Operation
= Operation
;
1111 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
1112 MapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (*NumberOfBytes
);
1113 MapInfo
->HostAddress
= PhysicalAddress
;
1114 MapInfo
->MappedHostAddress
= DMA_MEMORY_TOP
;
1117 // Allocate a buffer below DMA_MEMORY_TOP to map the transfer to.
1119 Status
= gBS
->AllocatePages (
1121 EfiBootServicesData
,
1122 MapInfo
->NumberOfPages
,
1123 &MapInfo
->MappedHostAddress
1125 if (EFI_ERROR (Status
)) {
1126 gBS
->FreePool (MapInfo
);
1131 // If this is a read operation from the Bus Master's point of view,
1132 // then copy the contents of the real buffer into the mapped buffer
1133 // so the Bus Master can read the contents of the real buffer.
1135 if (Operation
== EfiPciOperationBusMasterRead
|| Operation
== EfiPciOperationBusMasterRead64
) {
1137 (VOID
*) (UINTN
) MapInfo
->MappedHostAddress
,
1138 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
1139 MapInfo
->NumberOfBytes
1143 // The DeviceAddress is the address of the maped buffer below DMA_MEMORY_TOP
1145 *DeviceAddress
= MapInfo
->MappedHostAddress
;
1148 // The transfer is below DMA_MEMORY_TOP, so the DeviceAddress is simply the HostAddress
1150 *DeviceAddress
= PhysicalAddress
;
1159 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1164 Routine Description:
1166 Completes the Map() operation and releases any corresponding resources.
1170 This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1171 Mapping - The value returned from Map() operation.
1175 EFI_SUCCESS - The range was unmapped successfully.
1176 EFI_INVALID_PARAMETER - Mapping is not a value that was returned
1178 EFI_DEVICE_ERROR - The data was not committed to the target
1186 // See if the Map() operation associated with this Unmap() required a mapping buffer.
1187 // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
1189 if (Mapping
!= NULL
) {
1191 // Get the MAP_INFO structure from Mapping
1193 MapInfo
= (MAP_INFO
*) Mapping
;
1196 // If this is a write operation from the Bus Master's point of view,
1197 // then copy the contents of the mapped buffer into the real buffer
1198 // so the processor can read the contents of the real buffer.
1200 if ((MapInfo
->Operation
== EfiPciOperationBusMasterWrite
) ||
1201 (MapInfo
->Operation
== EfiPciOperationBusMasterWrite64
)
1204 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
1205 (VOID
*) (UINTN
) MapInfo
->MappedHostAddress
,
1206 MapInfo
->NumberOfBytes
1210 // Free the mapped buffer and the MAP_INFO structure.
1212 gBS
->FreePages (MapInfo
->MappedHostAddress
, MapInfo
->NumberOfPages
);
1213 gBS
->FreePool (Mapping
);
1221 RootBridgeIoAllocateBuffer (
1222 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1223 IN EFI_ALLOCATE_TYPE Type
,
1224 IN EFI_MEMORY_TYPE MemoryType
,
1226 OUT VOID
**HostAddress
,
1227 IN UINT64 Attributes
1231 Routine Description:
1233 Allocates pages that are suitable for a common buffer mapping.
1237 This - Pointer to EFI_ROOT_BRIDGE_IO_PROTOCOL instance.
1238 Type - Not used and can be ignored.
1239 MemoryType - Type of memory to allocate.
1240 Pages - Number of pages to allocate.
1241 HostAddress - Pointer to store the base system memory address
1242 of the allocated range.
1243 Attributes - Requested bit mask of attributes of the allocated
1248 EFI_SUCCESS - The requested memory range were allocated.
1249 EFI_INVALID_PARAMETER - Invalid parameter found.
1250 EFI_UNSUPPORTED - Attributes is unsupported.
1255 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1258 // Validate Attributes
1260 if ((Attributes
& EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER
) != 0) {
1261 return EFI_UNSUPPORTED
;
1264 // Check for invalid inputs
1266 if (HostAddress
== NULL
) {
1267 return EFI_INVALID_PARAMETER
;
1270 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1272 if ((MemoryType
!= EfiBootServicesData
) && (MemoryType
!= EfiRuntimeServicesData
)) {
1273 return EFI_INVALID_PARAMETER
;
1276 // Limit allocations to memory below DMA_MEMORY_TOP
1278 PhysicalAddress
= DMA_MEMORY_TOP
;
1280 Status
= gBS
->AllocatePages (
1286 if (EFI_ERROR (Status
)) {
1290 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1297 RootBridgeIoFreeBuffer (
1298 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1300 OUT VOID
*HostAddress
1304 Routine Description:
1306 Free memory allocated in AllocateBuffer.
1310 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1312 Pages - Number of pages to free.
1313 HostAddress - The base system memory address of the
1318 EFI_SUCCESS - Requested memory pages were freed.
1319 EFI_INVALID_PARAMETER - Invalid parameter found.
1323 return gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
, Pages
);
1329 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
1333 Routine Description:
1335 Flushes all PCI posted write transactions from a PCI host
1336 bridge to system memory.
1340 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1344 EFI_SUCCESS - PCI posted write transactions were flushed
1345 from PCI host bridge to system memory.
1346 EFI_DEVICE_ERROR - Fail due to hardware error.
1351 // not supported yet
1358 RootBridgeIoGetAttributes (
1359 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1360 OUT UINT64
*Supported
,
1361 OUT UINT64
*Attributes
1365 Routine Description:
1367 Get the attributes that a PCI root bridge supports and
1368 the attributes the PCI root bridge is currently using.
1372 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1374 Supports - A pointer to the mask of attributes that
1375 this PCI root bridge supports.
1376 Attributes - A pointer to the mask of attributes that
1377 this PCI root bridge is currently using.
1380 EFI_SUCCESS - Success.
1381 EFI_INVALID_PARAMETER - Invalid parameter found.
1385 // GC_TODO: Supported - add argument and description to function comment
1387 // GC_TODO: Supported - add argument and description to function comment
1389 // GC_TODO: Supported - add argument and description to function comment
1392 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
1394 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
1396 if (Attributes
== NULL
&& Supported
== NULL
) {
1397 return EFI_INVALID_PARAMETER
;
1400 // Set the return value for Supported and Attributes
1403 *Supported
= PrivateData
->Supports
;
1407 *Attributes
= PrivateData
->Attributes
;
1415 RootBridgeIoSetAttributes (
1416 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1417 IN UINT64 Attributes
,
1418 IN OUT UINT64
*ResourceBase
,
1419 IN OUT UINT64
*ResourceLength
1423 Routine Description:
1425 Sets the attributes for a resource range on a PCI root bridge.
1429 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1430 Attributes - The mask of attributes to set.
1431 ResourceBase - Pointer to the base address of the resource range
1432 to be modified by the attributes specified by Attributes.
1433 ResourceLength - Pointer to the length of the resource range to be modified.
1436 EFI_SUCCESS - Success.
1437 EFI_INVALID_PARAMETER - Invalid parameter found.
1438 EFI_OUT_OF_RESOURCES - Not enough resources to set the attributes upon.
1443 // GC_TODO: EFI_UNSUPPORTED - add return value to function comment
1446 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
1448 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
1450 if (Attributes
!= 0) {
1451 Attributes
&= (PrivateData
->Supports
);
1452 if (Attributes
== 0) {
1453 return EFI_UNSUPPORTED
;
1457 if (Attributes
== PrivateData
->Attributes
) {
1461 // It is just a trick for some attribute can only be enabled or disabled
1462 // otherwise it can impact on other devices
1464 PrivateData
->Attributes
= Attributes
;
1471 RootBridgeIoConfiguration (
1472 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1473 OUT VOID
**Resources
1477 Routine Description:
1479 Retrieves the current resource settings of this PCI root bridge
1480 in the form of a set of ACPI 2.0 resource descriptor.
1484 This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1485 Resources - Pointer to the ACPI 2.0 resource descriptor that
1486 describe the current configuration of this PCI root
1491 EFI_SUCCESS - Success.
1492 EFI_UNSUPPORTED - Current configuration of the PCI root bridge
1493 could not be retrieved.
1498 // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1504 PCI_ROOT_BRIDGE_INSTANCE
*RbPrivateData
;
1505 PCI_RES_NODE
*ResAllocNode
;
1506 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Config
;
1509 // Get this instance of the Root Bridge.
1511 RbPrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
1514 // If the pointer is not NULL, it points to a buffer already allocated.
1516 if (RbPrivateData
->ConfigBuffer
== NULL
) {
1517 Status
= gBS
->AllocatePool (
1518 EfiBootServicesData
,
1519 TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
),
1520 &RbPrivateData
->ConfigBuffer
1522 if (EFI_ERROR (Status
)) {
1523 return EFI_OUT_OF_RESOURCES
;
1527 Config
= RbPrivateData
->ConfigBuffer
;
1529 ZeroMem (Config
, TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1531 for (Idx
= 0; Idx
< TypeMax
; Idx
++) {
1533 ResAllocNode
= &RbPrivateData
->ResAllocNode
[Idx
];
1535 if (ResAllocNode
->Status
!= ResAllocated
) {
1539 switch (ResAllocNode
->Type
) {
1542 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1543 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1544 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1545 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1546 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1547 Config
->AddrLen
= ResAllocNode
->Length
;
1551 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1552 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1553 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1554 Config
->AddrSpaceGranularity
= 32;
1555 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1556 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1557 Config
->AddrLen
= ResAllocNode
->Length
;
1561 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1562 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1563 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1564 Config
->SpecificFlag
= 6;
1565 Config
->AddrSpaceGranularity
= 32;
1566 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1567 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1568 Config
->AddrLen
= ResAllocNode
->Length
;
1572 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1573 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1574 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1575 Config
->SpecificFlag
= 6;
1576 Config
->AddrSpaceGranularity
= 64;
1577 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1578 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1579 Config
->AddrLen
= ResAllocNode
->Length
;
1583 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1584 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1585 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1586 Config
->SpecificFlag
= 6;
1587 Config
->AddrSpaceGranularity
= 64;
1588 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1589 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1590 Config
->AddrLen
= ResAllocNode
->Length
;
1594 Config
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1595 Config
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1596 Config
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
1597 Config
->AddrRangeMin
= ResAllocNode
->Base
;
1598 Config
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1599 Config
->AddrLen
= ResAllocNode
->Length
;
1609 // Terminate the entries.
1611 ((EFI_ACPI_END_TAG_DESCRIPTOR
*) Config
)->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1612 ((EFI_ACPI_END_TAG_DESCRIPTOR
*) Config
)->Checksum
= 0x0;
1614 *Resources
= RbPrivateData
->ConfigBuffer
;