Hi Ard,
I have a question regarding DmaLib implementation. We took a deeper look at AHCI controller and it will be coherent on newer SoC version - as for now, we have non-coherent one and it's not working with NullDmaLib, whereas everything is ok when ArmDmaLib is used. In the same time, tests show that XHCI works fine both with NullDmaLib and ArmDmaLib. My question is, what are the contraindications for using ArmDmaLib for coherent devices if it is working good on them also? This solution seems to be covering for every case (contrary to NullDmaLib).
Best Regards, Jan
2016-10-31 12:59 GMT+01:00 Ard Biesheuvel ard.biesheuvel@linaro.org:
On 31 October 2016 at 11:42, Jan Dąbroś jsd@semihalf.com wrote:
Hi Ard,
Thanks a lot for your remarks. Please find my answers inline.
Do you have any more comments regarding this and next commits in patchset? Did you have a chance to take a look at them?
No, not yet.
+Next five PCDs are in unicode string, format containing settings for all devices +separated with semicolon.
- gMarvellTokenSpaceGuid.PcdPciEDevBaseAddress
I must say, I quite dislike this way of putting ; delimited strings into PCDs and then parsing them at runtime. But I don't have anything better to propose, so this is OK for now. We do intend to improve the situation somewhat around PCI I/O emulation (which is a terrible name as well, by the way) but for now this is fine.
We also cannot find anything better - other PCI I/O emulation drivers are limited to single type of device (which are hardcoded by the way). Although it's not perfect, this approach gives us some flexibility and scalability.
I see. As I said, I don't have anything better to propose, although I am working on a generic PCI emulation driver.
+#PciEmulation
- gMarvellTokenSpaceGuid.PcdPciEDevBaseAddress|{ 0x0 }|VOID*|0x30000058
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode1|{ 0x0 }|VOID*|0x30000059
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode2|{ 0x0 }|VOID*|0x30000060
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode3|{ 0x0 }|VOID*|0x30000061
- gMarvellTokenSpaceGuid.PcdPciEDevCount|0|UINT32|0x30000062
- gMarvellTokenSpaceGuid.PcdPciEDevRegSize|{ 0x0 }|VOID*|0x30000063
One potential issue with covering all PCI I/O emulated devices by a single driver is that they must all be coherent or non-coherent. There is no way for a single device to deviate in this respect. Did you take that into account for your platform?
All devices on our platform are coherent, so it isn't a problem in our case. I think that this driver may be improved in future in order to meet the requirements of another SoC, e.g support for coherent and non-coherent devices - however that's not the case with Armada70x0/80x0 family now. What do you think?
If they are all coherent, I think this is fine, but you are using the wrong DMA lib instance. See below
- if (Operation == EfiPciIoOperationBusMasterRead
) {
- DmaOperation = MapOperationBusMasterRead;
- } else if (Operation == EfiPciIoOperationBusMasterWrite) {
- DmaOperation = MapOperationBusMasterWrite;
- } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
- DmaOperation = MapOperationBusMasterCommonBuffer;
- } else {
- return EFI_INVALID_PARAMETER;
- }
- return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
Are all your peripherals 64-bit DMA capable? If not, you may have a problem here, given that NullDmaLib just returns the CPU address unmodified, so you may want to check the DeviceAddress if the EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute is not set. Another complication in the non-coherent case is that the buffer may be remapped by DmaLib, in which case you have no control over the final allocation, unless you perform the bounce buffering here.
Since our platform has less than 4GB memory visible for UEFI, returned address shouldn't be above this region. We use ArmDmaLib not NullDmaLib as DmaLib implementation. As I wrote above, we are using cache-coherent devices, so the problem with remapped buffer couldn't happen here.
You should be using NullDmaLib. ArmDmaLib is for non-coherent DMA only.
+EFI_STATUS +PciIoAllocateBuffer (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_ALLOCATE_TYPE Type,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- OUT VOID **HostAddress,
- IN UINT64 Attributes
- )
+{
- if (Attributes & (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {
- return EFI_UNSUPPORTED;
- }
- return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
Same question: are all your peripherals 64-bit DMA capable? If the EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute is not set, you must ensure that you allocate below 4 GB (if your platform also has UEFI visible memory above 4 GB)
Since we have less than 4GB memory visible, there shouldn't be problem with allocation above this region.
OK, good to know.
+[Packages]
- ArmPkg/ArmPkg.dec
- EmbeddedPkg/EmbeddedPkg.dec
- IntelFrameworkPkg/IntelFrameworkPkg.dec
- MdeModulePkg/MdeModulePkg.dec
- MdePkg/MdePkg.dec
- OpenPlatformPkg/Platforms/Marvell/Marvell.dec
- ShellPkg/ShellPkg.dec
Why on earth do you need the ShellPkg in a DXE_DRIVER module?
It's definitely placed here by mistake. Will be removed on v2.
2016-10-28 18:19 GMT+02:00 Ard Biesheuvel ard.biesheuvel@linaro.org:
Hello Marcin,
On 28 October 2016 at 16:42, Marcin Wojtas mw@semihalf.com wrote:
From: Jan Dąbroś jsd@semihalf.com
In order to use numerous UEFI drivers based on PCI bus, PciEmulation driver is implemented. This solution is based on Chips/TexasInstruments/Omap35xx/PciEmulation/ Configuring fake devices is performed via PCD.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jan Dabros jsd@semihalf.com Signed-off-by: Marcin Wojtas mw@semihalf.com
.../Marvell/PortingGuide/PciEmulation.txt | 53 ++ Platforms/Marvell/Marvell.dec | 8 + Platforms/Marvell/PciEmulation/PciEmulation.c | 678 +++++++++++++++++++++ Platforms/Marvell/PciEmulation/PciEmulation.h | 271 ++++++++ Platforms/Marvell/PciEmulation/PciEmulation.inf | 65 ++ Platforms/Marvell/PciEmulation/PciRootBridgeIo.c | 314 ++++++++++ 6 files changed, 1389 insertions(+) create mode 100644 Documentation/Marvell/PortingGuide/PciEmulation.txt create mode 100644 Platforms/Marvell/PciEmulation/PciEmulation.c create mode 100644 Platforms/Marvell/PciEmulation/PciEmulation.h create mode 100644 Platforms/Marvell/PciEmulation/PciEmulation.inf create mode 100644 Platforms/Marvell/PciEmulation/PciRootBridgeIo.c
diff --git a/Documentation/Marvell/PortingGuide/PciEmulation.txt b/Documentation/Marvell/PortingGuide/PciEmulation.txt new file mode 100644 index 0000000..5bb812a --- /dev/null +++ b/Documentation/Marvell/PortingGuide/PciEmulation.txt @@ -0,0 +1,53 @@ +PciEmulation configuration +-------------------------- +Instalation of various Pci devices via PciEmulation driver is performed via set +of PCDs. Following are available:
- gMarvellTokenSpaceGuid.PcdPciEDevCount
+Indicates how many fake Pci devices are placed on board.
+Next five PCDs are in unicode string, format containing settings for all devices +separated with semicolon.
- gMarvellTokenSpaceGuid.PcdPciEDevBaseAddress
I must say, I quite dislike this way of putting ; delimited strings into PCDs and then parsing them at runtime. But I don't have anything better to propose, so this is OK for now. We do intend to improve the situation somewhat around PCI I/O emulation (which is a terrible name as well, by the way) but for now this is fine.
+Indicates base address of Pci device register space.
- gMarvellTokenSpaceGuid.PcdPciEDevRegSize
+Indicates size of Pci device register space.
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode1
+Indicates device subclass code.
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode2
+Indicates device class code.
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode3
+Indicates Pci device class code.
+Examples +-------- +Assuming that there are two fake Pci xHCI controllers with register space +0xF2500000 - 0xF2510000 and 0xF2510000 - 0xF2520000 following PCD values should +be set:
- gMarvellTokenSpaceGuid.PcdPciEDevCount|2
- gMarvellTokenSpaceGuid.PcdPciEDevBaseAddress|L"0xF2500000;0xF2510000"
- gMarvellTokenSpaceGuid.PcdPciEDevRegSize|L"0x10000;0x10000"
- ## XHCI subclass
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode1|L"0x30;0x30"
- ## USB controller class
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode2|L"0x03;0x03"
- ## Serial bus controller Pci device class
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode3|L"0x0C;0x0C"
+Notes +----- +1.In order to find proper values for Pci class codes, please refer to
- PCI Local Bus Specification.
+2.PCDs are configured via UNICODE strings - remember to add L marker. diff --git a/Platforms/Marvell/Marvell.dec b/Platforms/Marvell/Marvell.dec index db99230..f56987d 100644 --- a/Platforms/Marvell/Marvell.dec +++ b/Platforms/Marvell/Marvell.dec @@ -209,6 +209,14 @@ gMarvellTokenSpaceGuid.PcdPp2XlgBaseAddress|0|UINT64|0x3000031 gMarvellTokenSpaceGuid.PcdPp2XlgDevSize|0|UINT32|0x3000032
+#PciEmulation
- gMarvellTokenSpaceGuid.PcdPciEDevBaseAddress|{ 0x0 }|VOID*|0x30000058
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode1|{ 0x0 }|VOID*|0x30000059
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode2|{ 0x0 }|VOID*|0x30000060
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode3|{ 0x0 }|VOID*|0x30000061
- gMarvellTokenSpaceGuid.PcdPciEDevCount|0|UINT32|0x30000062
- gMarvellTokenSpaceGuid.PcdPciEDevRegSize|{ 0x0 }|VOID*|0x30000063
One potential issue with covering all PCI I/O emulated devices by a single driver is that they must all be coherent or non-coherent. There is no way for a single device to deviate in this respect. Did you take that into account for your platform?
#ResetLib gMarvellTokenSpaceGuid.PcdResetRegAddress|0|UINT64|0x40000050 gMarvellTokenSpaceGuid.PcdResetRegMask|0|UINT32|0x4000051 diff --git a/Platforms/Marvell/PciEmulation/PciEmulation.c b/Platforms/Marvell/PciEmulation/PciEmulation.c new file mode 100644 index 0000000..a800bcb --- /dev/null +++ b/Platforms/Marvell/PciEmulation/PciEmulation.c @@ -0,0 +1,678 @@ +/** @file
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
- Copyright (c) 2016, Marvell. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD
- License which accompanies this distribution. The full text of the license
- may be found at http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include "PciEmulation.h"
+typedef struct {
- ACPI_HID_DEVICE_PATH AcpiDevicePath;
- PCI_DEVICE_PATH PciDevicePath;
- EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_IO_DEVICE_PATH;
+typedef struct {
- UINT32 Signature;
- EFI_PCI_IO_DEVICE_PATH DevicePath;
- EFI_PCI_IO_PROTOCOL PciIoProtocol;
- PCI_TYPE00 *ConfigSpace;
- PCI_ROOT_BRIDGE RootBridge;
- UINTN Segment;
+} EFI_PCI_IO_PRIVATE_DATA;
+#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o') +#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, \
PciIoProtocol, \
EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
+EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate = +{
- {
- {
ACPI_DEVICE_PATH,
ACPI_DP,
{
sizeof (ACPI_HID_DEVICE_PATH),
0
}
- },
- EISA_PNP_ID(0x0A03), // HID
- 0 // UID
- },
- {
- {
HARDWARE_DEVICE_PATH,
HW_PCI_DP,
{
sizeof (PCI_DEVICE_PATH),
0
}
- },
- 0,
- 0
- },
- {
- END_DEVICE_PATH_TYPE,
- END_ENTIRE_DEVICE_PATH_SUBTYPE,
- {
sizeof (EFI_DEVICE_PATH_PROTOCOL),
0
- }
- }
+};
+EFI_STATUS +PciIoPollMem (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- )
+{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
+}
+EFI_STATUS +PciIoPollIo (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- )
+{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
+}
+EFI_STATUS +PciIoMemRead (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
- return PciRootBridgeIoMemRead (
&Private->RootBridge.Io,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
Count,
Buffer
);
+}
+EFI_STATUS +PciIoMemWrite (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
- return PciRootBridgeIoMemWrite (
&Private->RootBridge.Io,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
Count,
Buffer
);
+}
+EFI_STATUS +PciIoIoRead (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
+}
+EFI_STATUS +PciIoIoWrite (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
+}
+/**
- Enable a PCI driver to read PCI controller registers in
- PCI configuration space.
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Offset The offset within the PCI configuration space for
the PCI controller.
- @param[in] Count The number of PCI configuration operations to
perform. Bytes moved is Width size * Count,
starting at Offset.
- @param[in out] Buffer The destination buffer to store the results.
- @retval EFI_SUCCESS The data was read from the PCI controller.
- @retval EFI_INVALID_PARAMETER "Width" is invalid.
- @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
+**/ +EFI_STATUS +PciIoPciRead (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT32 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
- if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- return PciRootBridgeIoMemRW (
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
Count,
TRUE,
(PTR)(UINTN)Buffer,
TRUE,
(PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset)
);
+}
+/**
- Enable a PCI driver to write PCI controller registers in
- PCI configuration space.
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Offset The offset within the PCI configuration space for
the PCI controller.
- @param[in] Count The number of PCI configuration operations to
perform. Bytes moved is Width size * Count,
starting at Offset.
- @param[in out] Buffer The source buffer to write data from.
- @retval EFI_SUCCESS The data was read from the PCI controller.
- @retval EFI_INVALID_PARAMETER "Width" is invalid.
- @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
+**/ +EFI_STATUS +PciIoPciWrite (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT32 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
- if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- return PciRootBridgeIoMemRW (
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
Count,
TRUE,
(PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset),
TRUE,
(PTR)(UINTN)Buffer
);
+}
+EFI_STATUS +PciIoCopyMem (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 DestBarIndex,
- IN UINT64 DestOffset,
- IN UINT8 SrcBarIndex,
- IN UINT64 SrcOffset,
- IN UINTN Count
- )
+{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
+}
+EFI_STATUS +PciIoMap (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
- IN VOID *HostAddress,
- IN OUT UINTN *NumberOfBytes,
- OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
- OUT VOID **Mapping
- )
+{
- DMA_MAP_OPERATION DmaOperation;
- if (Operation == EfiPciIoOperationBusMasterRead) {
- DmaOperation = MapOperationBusMasterRead;
- } else if (Operation == EfiPciIoOperationBusMasterWrite) {
- DmaOperation = MapOperationBusMasterWrite;
- } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
- DmaOperation = MapOperationBusMasterCommonBuffer;
- } else {
- return EFI_INVALID_PARAMETER;
- }
- return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
Are all your peripherals 64-bit DMA capable? If not, you may have a problem here, given that NullDmaLib just returns the CPU address unmodified, so you may want to check the DeviceAddress if the EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute is not set. Another complication in the non-coherent case is that the buffer may be remapped by DmaLib, in which case you have no control over the final allocation, unless you perform the bounce buffering here.
+}
+EFI_STATUS +PciIoUnmap (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN VOID *Mapping
- )
+{
- return DmaUnmap (Mapping);
+}
+/**
- Allocate pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
- mapping.
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Type This parameter is not used and must be ignored.
- @param[in] MemoryType The type of memory to allocate, EfiBootServicesData
or EfiRuntimeServicesData.
- @param[in] Pages The number of pages to allocate.
- @param[out] HostAddress A pointer to store the base system memory address of
the allocated range.
- @param[in] Attributes The requested bit mask of attributes for the
allocated range. Only the attributes,
EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE and
EFI_PCI_ATTRIBUTE_MEMORY_CACHED may be used with
this function. If any other bits are set, then
EFI_UNSUPPORTED is returned. This function ignores
this bit mask.
- @retval EFI_SUCCESS The requested memory pages were allocated.
- @retval EFI_INVALID_PARAMETER HostAddress is NULL.
- @retval EFI_INVALID_PARAMETER MemoryType is invalid.
- @retval EFI_UNSUPPORTED Attributes is unsupported.
- @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+**/ +EFI_STATUS +PciIoAllocateBuffer (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_ALLOCATE_TYPE Type,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- OUT VOID **HostAddress,
- IN UINT64 Attributes
- )
+{
- if (Attributes & (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {
- return EFI_UNSUPPORTED;
- }
- return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
Same question: are all your peripherals 64-bit DMA capable? If the EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute is not set, you must ensure that you allocate below 4 GB (if your platform also has UEFI visible memory above 4 GB)
+}
+EFI_STATUS +PciIoFreeBuffer (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINTN Pages,
- IN VOID *HostAddress
- )
+{
- return DmaFreeBuffer (Pages, HostAddress);
+}
+EFI_STATUS +PciIoFlush (
- IN EFI_PCI_IO_PROTOCOL *This
- )
+{
- return EFI_SUCCESS;
+}
+/**
- Retrieves this PCI controller's current PCI bus number, device number, and
- function number.
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[out] SegmentNumber The PCI controller's current PCI segment number.
- @param[out] BusNumber The PCI controller's current PCI bus number.
- @param[out] DeviceNumber The PCI controller's current PCI device number.
- @param[out] FunctionNumber The PCI controller’s current PCI function number.
- @retval EFI_SUCCESS The PCI controller location was returned.
- @retval EFI_INVALID_PARAMETER At least one out of the four output parameters
is a NULL pointer.
+**/ +EFI_STATUS +PciIoGetLocation (
- IN EFI_PCI_IO_PROTOCOL *This,
- OUT UINTN *SegmentNumber,
- OUT UINTN *BusNumber,
- OUT UINTN *DeviceNumber,
- OUT UINTN *FunctionNumber
- )
+{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
- if ((SegmentNumber == NULL) || (BusNumber == NULL) ||
(DeviceNumber == NULL) || (FunctionNumber == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- *SegmentNumber = Private->Segment;
- *BusNumber = 0xff;
- *DeviceNumber = 0;
- *FunctionNumber = 0;
- return EFI_SUCCESS;
+}
+/**
- Performs an operation on the attributes that this PCI controller supports.
- The operations include getting the set of supported attributes, retrieving
- the current attributes, setting the current attributes, enabling attributes,
- and disabling attributes.
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Operation The operation to perform on the attributes for this
PCI controller.
- @param[in] Attributes The mask of attributes that are used for Set,
Enable and Disable operations.
- @param[out] Result A pointer to the result mask of attributes that are
returned for the Get and Supported operations. This
is an optional parameter that may be NULL for the
Set, Enable, and Disable operations.
- @retval EFI_SUCCESS The operation on the PCI controller's
attributes was completed. If the operation
was Get or Supported, then the attribute mask
is returned in Result.
- @retval EFI_INVALID_PARAMETER Operation is greater than or equal to
EfiPciIoAttributeOperationMaximum.
- @retval EFI_INVALID_PARAMETER Operation is Get and Result is NULL.
- @retval EFI_INVALID_PARAMETER Operation is Supported and Result is NULL.
+**/ +EFI_STATUS +PciIoAttributes (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
- IN UINT64 Attributes,
- OUT UINT64 *Result OPTIONAL
- )
+{
- switch (Operation) {
- case EfiPciIoAttributeOperationGet:
- case EfiPciIoAttributeOperationSupported:
- if (Result == NULL) {
return EFI_INVALID_PARAMETER;
- }
- //
- // We are not a real PCI device so just say things we kind of do
- //
- *Result = EFI_PCI_DEVICE_ENABLE;
- break;
- case EfiPciIoAttributeOperationSet:
- case EfiPciIoAttributeOperationEnable:
- case EfiPciIoAttributeOperationDisable:
- if (Attributes & (~EFI_PCI_DEVICE_ENABLE)) {
return EFI_UNSUPPORTED;
- }
- //
- // Since we are not a real PCI device no enable/set or
- // disable operations exist.
- //
- return EFI_SUCCESS;
- default:
- return EFI_INVALID_PARAMETER;
- };
- return EFI_SUCCESS;
+}
+EFI_STATUS +PciIoGetBarAttributes (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINT8 BarIndex,
- OUT UINT64 *Supports, OPTIONAL
- OUT VOID **Resources OPTIONAL
- )
+{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
+}
+EFI_STATUS +PciIoSetBarAttributes (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINT64 Attributes,
- IN UINT8 BarIndex,
- IN OUT UINT64 *Offset,
- IN OUT UINT64 *Length
- )
+{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
+}
+EFI_PCI_IO_PROTOCOL PciIoTemplate = +{
- PciIoPollMem,
- PciIoPollIo,
- { PciIoMemRead, PciIoMemWrite },
- { PciIoIoRead, PciIoIoWrite },
- { PciIoPciRead, PciIoPciWrite },
- PciIoCopyMem,
- PciIoMap,
- PciIoUnmap,
- PciIoAllocateBuffer,
- PciIoFreeBuffer,
- PciIoFlush,
- PciIoGetLocation,
- PciIoAttributes,
- PciIoGetBarAttributes,
- PciIoSetBarAttributes,
- 0,
- 0
+};
+STATIC +EFI_STATUS +EFIAPI +InstallDevices (
- IN UINTN DeviceId,
- IN UINTN BaseAddr,
- IN UINTN AddressSpaceSize,
- IN UINTN ClassCode1,
- IN UINTN ClassCode2,
- IN UINTN ClassCode3
- )
+{
- EFI_PCI_IO_PRIVATE_DATA *Private;
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- // Create a private structure
- Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
- if (Private == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- return Status;
- }
- // Fill in signature
- Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE;
- // Fake Root Bridge structure needs a signature too
- Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE;
- // Get the register base
- Private->RootBridge.MemoryStart = BaseAddr;
- // Default to segment zero
- Private->Segment = 0;
- // Calculate the total size of device registers.
- Private->RootBridge.MemorySize = AddressSpaceSize;
- // Create fake PCI config space.
- Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
- if (Private->ConfigSpace == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- FreePool(Private);
- return Status;
- }
- //
- // Configure PCI config space
- //
- // Invalid vendor Id as it is not an actual device.
- Private->ConfigSpace->Hdr.VendorId = 0xFFFF;
- // Not relevant as the vendor id is not valid.
- Private->ConfigSpace->Hdr.DeviceId = 0x0000;
- Private->ConfigSpace->Hdr.ClassCode[0] = ClassCode1;
- Private->ConfigSpace->Hdr.ClassCode[1] = ClassCode2;
- Private->ConfigSpace->Hdr.ClassCode[2] = ClassCode3;
- Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart;
- Handle = NULL;
- // Unique device path.
- CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate));
- Private->DevicePath.AcpiDevicePath.UID = 0;
- Private->DevicePath.PciDevicePath.Device = DeviceId;
- // Copy protocol structure
- CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
- Status = gBS->InstallMultipleProtocolInterfaces(
&Handle,
&gEfiPciIoProtocolGuid,
&Private->PciIoProtocol,
&gEfiDevicePathProtocolGuid,
&Private->DevicePath,
NULL
);
- if (EFI_ERROR(Status)) {
- DEBUG((DEBUG_ERROR, "PciEmulation: InstallMultipleProtocolInterfaces failed\n"));
- }
- return Status;
+}
+// +// Below function is used to parse devices information from PCD strings. +// +EFI_STATUS +EFIAPI +PciEmulationEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
+{
- EFI_STATUS Status;
- UINT8 i, DevCount;
- UINTN BaseAddrTable[PcdGet32 (PcdPciEDevCount)];
- UINTN RegSizeTable[PcdGet32 (PcdPciEDevCount)];
- UINTN DevClass1Table[PcdGet32 (PcdPciEDevCount)];
- UINTN DevClass2Table[PcdGet32 (PcdPciEDevCount)];
- UINTN DevClass3Table[PcdGet32 (PcdPciEDevCount)];
- DevCount = PcdGet32 (PcdPciEDevCount);
- Status = ParsePcdString ((CHAR16 *) PcdGetPtr (PcdPciEDevBaseAddress), DevCount, BaseAddrTable, NULL);
- if (EFI_ERROR(Status)) {
- DEBUG((DEBUG_ERROR, "PciEmulation: Wrong PcdPciEDevBaseAddress format\n"));
- return EFI_INVALID_PARAMETER;
- }
- Status = ParsePcdString ((CHAR16 *) PcdGetPtr (PcdPciEDevRegSize), DevCount, RegSizeTable, NULL);
- if (EFI_ERROR(Status)) {
- DEBUG((DEBUG_ERROR, "PciEmulation: Wrong PcdPciEDevRegSize format\n"));
- return EFI_INVALID_PARAMETER;
- }
- Status = ParsePcdString ((CHAR16 *) PcdGetPtr (PcdPciEDevClassCode1), DevCount, DevClass1Table, NULL);
- if (EFI_ERROR(Status)) {
- DEBUG((DEBUG_ERROR, "PciEmulation: Wrong PcdPciEDevClassCode1 format\n"));
- return EFI_INVALID_PARAMETER;
- }
- Status = ParsePcdString ((CHAR16 *) PcdGetPtr (PcdPciEDevClassCode2), DevCount, DevClass2Table, NULL);
- if (EFI_ERROR(Status)) {
- DEBUG((DEBUG_ERROR, "PciEmulation: Wrong PcdPciEDevClassCode2 format\n"));
- return EFI_INVALID_PARAMETER;
- }
- Status = ParsePcdString ((CHAR16 *) PcdGetPtr (PcdPciEDevClassCode3), DevCount, DevClass3Table, NULL);
- if (EFI_ERROR(Status)) {
- DEBUG((DEBUG_ERROR, "PciEmulation: Wrong PcdPciEDevClassCode3 format\n"));
- return EFI_INVALID_PARAMETER;
- }
- for (i = 0; i < DevCount; i++) {
- Status = InstallDevices (i, BaseAddrTable[i], RegSizeTable[i],
DevClass1Table[i], DevClass2Table[i], DevClass3Table[i]);
- if (EFI_ERROR(Status)) {
DEBUG((DEBUG_ERROR, "PciEmulation: Cannot install device with ID=%d\n", i));
- }
- }
- return Status;
+} diff --git a/Platforms/Marvell/PciEmulation/PciEmulation.h b/Platforms/Marvell/PciEmulation/PciEmulation.h new file mode 100644 index 0000000..4f75539 --- /dev/null +++ b/Platforms/Marvell/PciEmulation/PciEmulation.h @@ -0,0 +1,271 @@ +/** @file
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
- Copyright (c) 2016, Marvell. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD
- License which accompanies this distribution. The full text of the license may
- be found at http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef _PCI_ROOT_BRIDGE_H_ +#define _PCI_ROOT_BRIDGE_H_
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h> +#include <IndustryStandard/Pci22.h> +#include <IndustryStandard/PciCodeId.h>
+#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/DmaLib.h> +#include <Library/DxeServicesTableLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/ParsePcdLib.h> +#include <Library/PcdLib.h> +#include <Library/PciLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h>
+#include <Protocol/DevicePath.h> +#include <Protocol/EmbeddedExternalDevice.h> +#include <Protocol/PciHostBridgeResourceAllocation.h> +#include <Protocol/PciIo.h> +#include <Protocol/PciRootBridgeIo.h>
+#define ACPI_CONFIG_IO 0 +#define ACPI_CONFIG_MMIO 1 +#define ACPI_CONFIG_BUS 2
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F')
+typedef struct {
- ACPI_HID_DEVICE_PATH AcpiDevicePath;
- EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+typedef struct {
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3];
- EFI_ACPI_END_TAG_DESCRIPTOR EndDesc;
+} ACPI_CONFIG_INFO;
+typedef struct {
- UINT32 Signature;
- EFI_HANDLE Handle;
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
- EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
- UINT8 StartBus;
- UINT8 EndBus;
- UINT16 Type;
- UINT32 MemoryStart;
- UINT32 MemorySize;
- UINTN IoOffset;
- UINT32 IoStart;
- UINT32 IoSize;
- UINT64 PciAttributes;
- ACPI_CONFIG_INFO *Config;
+} PCI_ROOT_BRIDGE;
+#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+typedef union {
- UINT8 volatile *buf;
- UINT8 volatile *ui8;
- UINT16 volatile *ui16;
- UINT32 volatile *ui32;
- UINT64 volatile *ui64;
- UINTN volatile ui;
+} PTR;
+EFI_STATUS +EFIAPI +PciRootBridgeIoPollMem (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoPollIo (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoMemRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoMemWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoIoRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 UserAddress,
- IN UINTN Count,
- IN OUT VOID *UserBuffer
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoIoWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 UserAddress,
- IN UINTN Count,
- IN OUT VOID *UserBuffer
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoCopyMem (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 DestAddress,
- IN UINT64 SrcAddress,
- IN UINTN Count
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoPciRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoPciWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoMap (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
- IN VOID *HostAddress,
- IN OUT UINTN *NumberOfBytes,
- OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
- OUT VOID **Mapping
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoUnmap (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN VOID *Mapping
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoAllocateBuffer (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_ALLOCATE_TYPE Type,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- OUT VOID **HostAddress,
- IN UINT64 Attributes
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoFreeBuffer (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN UINTN Pages,
- OUT VOID *HostAddress
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoFlush (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoGetAttributes (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- OUT UINT64 *Supported,
- OUT UINT64 *Attributes
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoSetAttributes (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN UINT64 Attributes,
- IN OUT UINT64 *ResourceBase,
- IN OUT UINT64 *ResourceLength
- );
+EFI_STATUS +EFIAPI +PciRootBridgeIoConfiguration (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- OUT VOID **Resources
- );
+// +// Private Function Prototypes +// +EFI_STATUS +EFIAPI +PciRootBridgeIoMemRW (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINTN Count,
- IN BOOLEAN InStrideFlag,
- IN PTR In,
- IN BOOLEAN OutStrideFlag,
- OUT PTR Out
- );
+BOOLEAN +PciIoMemAddressValid (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINT64 Address
- );
+#endif diff --git a/Platforms/Marvell/PciEmulation/PciEmulation.inf b/Platforms/Marvell/PciEmulation/PciEmulation.inf new file mode 100644 index 0000000..30ddfc2 --- /dev/null +++ b/Platforms/Marvell/PciEmulation/PciEmulation.inf @@ -0,0 +1,65 @@ +/** @file
- Copyright (c) 2009, Apple Inc. All rights reserved.<BR>
- Copyright (c) 2016, Marvell. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD
- License which accompanies this distribution. The full text of the license may
- be found at http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+[Defines]
- INF_VERSION = 0x00010019
- BASE_NAME = PciEmulation
- FILE_GUID = 3dfa08da-923b-4841-9435-c77a604d7493
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
- ENTRY_POINT = PciEmulationEntryPoint
+[Sources.common]
- PciEmulation.c
- PciRootBridgeIo.c
+[Packages]
- ArmPkg/ArmPkg.dec
- EmbeddedPkg/EmbeddedPkg.dec
- IntelFrameworkPkg/IntelFrameworkPkg.dec
- MdeModulePkg/MdeModulePkg.dec
- MdePkg/MdePkg.dec
- OpenPlatformPkg/Platforms/Marvell/Marvell.dec
- ShellPkg/ShellPkg.dec
Why on earth do you need the ShellPkg in a DXE_DRIVER module?
+[LibraryClasses]
- BaseLib
- DmaLib
- DxeServicesTableLib
- IoLib
- ParsePcdLib
- UefiBootServicesTableLib
- UefiDriverEntryPoint
- UefiLib
- UefiRuntimeServicesTableLib
+[Protocols]
- gEfiDevicePathProtocolGuid
- gEfiPciHostBridgeResourceAllocationProtocolGuid
- gEfiPciIoProtocolGuid
- gEfiPciRootBridgeIoProtocolGuid
- gEmbeddedExternalDeviceProtocolGuid
+[Pcd]
- gMarvellTokenSpaceGuid.PcdPciEDevBaseAddress
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode1
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode2
- gMarvellTokenSpaceGuid.PcdPciEDevClassCode3
- gMarvellTokenSpaceGuid.PcdPciEDevCount
- gMarvellTokenSpaceGuid.PcdPciEDevRegSize
+[Depex]
- TRUE
diff --git a/Platforms/Marvell/PciEmulation/PciRootBridgeIo.c b/Platforms/Marvell/PciEmulation/PciRootBridgeIo.c new file mode 100644 index 0000000..dab26b6 --- /dev/null +++ b/Platforms/Marvell/PciEmulation/PciRootBridgeIo.c @@ -0,0 +1,314 @@ +/** @file
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
- Copyright (c) 2016, Marvell. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD
- License which accompanies this distribution. The full text of the license may
- be found at http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include "PciEmulation.h"
+BOOLEAN +PciRootBridgeMemAddressValid (
- IN PCI_ROOT_BRIDGE *Private,
- IN UINT64 Address
- )
+{
- if ((Address >= Private->MemoryStart) &&
(Address < (Private->MemoryStart + Private->MemorySize))) {
- return TRUE;
- }
- return FALSE;
+}
+EFI_STATUS +PciRootBridgeIoMemRW (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINTN Count,
- IN BOOLEAN InStrideFlag,
- IN PTR In,
- IN BOOLEAN OutStrideFlag,
- OUT PTR Out
- )
+{
- UINTN Stride;
- UINTN InStride;
- UINTN OutStride;
- Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
- Stride = (UINTN)1 << Width;
- InStride = InStrideFlag ? Stride : 0;
- OutStride = OutStrideFlag ? Stride : 0;
- //
- // Loop for each iteration and move the data
- //
- switch (Width) {
- case EfiPciWidthUint8:
- for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
*In.ui8 = *Out.ui8;
- }
- break;
- case EfiPciWidthUint16:
- for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
*In.ui16 = *Out.ui16;
- }
- break;
- case EfiPciWidthUint32:
- for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
*In.ui32 = *Out.ui32;
- }
- break;
- default:
- return EFI_INVALID_PARAMETER;
- }
- return EFI_SUCCESS;
+}
+EFI_STATUS +PciRootBridgeIoPciRW (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN BOOLEAN Write,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 UserAddress,
- IN UINTN Count,
- IN OUT VOID *UserBuffer
- )
+{
- return EFI_SUCCESS;
+}
+/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge
- memory space.
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to
store the results. For write operations, the
source buffer to write data from.
- @retval EFI_SUCCESS The data was read from or written to the PCI
root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+**/ +EFI_STATUS +EFIAPI +PciRootBridgeIoMemRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- PCI_ROOT_BRIDGE *Private;
- UINTN AlignMask;
- PTR In;
- PTR Out;
- if ( Buffer == NULL ) {
- return EFI_INVALID_PARAMETER;
- }
- Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
- if (!PciRootBridgeMemAddressValid (Private, Address)) {
- return EFI_INVALID_PARAMETER;
- }
- AlignMask = (1 << (Width & 0x03)) - 1;
- if (Address & AlignMask) {
- return EFI_INVALID_PARAMETER;
- }
- In.buf = Buffer;
- Out.buf = (VOID *)(UINTN) Address;
- switch (Width) {
- case EfiPciWidthUint8:
- case EfiPciWidthUint16:
- case EfiPciWidthUint32:
- case EfiPciWidthUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
- case EfiPciWidthFifoUint8:
- case EfiPciWidthFifoUint16:
- case EfiPciWidthFifoUint32:
- case EfiPciWidthFifoUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
- case EfiPciWidthFillUint8:
- case EfiPciWidthFillUint16:
- case EfiPciWidthFillUint32:
- case EfiPciWidthFillUint64:
- return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
- default:
- break;
- }
- return EFI_INVALID_PARAMETER;
+}
+/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to
store the results. For write operations, the
source buffer to write data from.
- @retval EFI_SUCCESS The data was read from or written to the PCI
root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+**/ +EFI_STATUS +EFIAPI +PciRootBridgeIoMemWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- PCI_ROOT_BRIDGE *Private;
- UINTN AlignMask;
- PTR In;
- PTR Out;
- if (Buffer == NULL ) {
- return EFI_INVALID_PARAMETER;
- }
- Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
- if (!PciRootBridgeMemAddressValid (Private, Address)) {
- return EFI_INVALID_PARAMETER;
- }
- AlignMask = (1 << (Width & 0x03)) - 1;
- if (Address & AlignMask) {
- return EFI_INVALID_PARAMETER;
- }
- In.buf = (VOID *)(UINTN) Address;
- Out.buf = Buffer;
- switch (Width) {
- case EfiPciWidthUint8:
- case EfiPciWidthUint16:
- case EfiPciWidthUint32:
- case EfiPciWidthUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
- case EfiPciWidthFifoUint8:
- case EfiPciWidthFifoUint16:
- case EfiPciWidthFifoUint32:
- case EfiPciWidthFifoUint64:
- return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
- case EfiPciWidthFillUint8:
- case EfiPciWidthFillUint16:
- case EfiPciWidthFillUint32:
- case EfiPciWidthFillUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
- default:
- break;
- }
- return EFI_INVALID_PARAMETER;
+}
+/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge
- memory space.
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to
store the results. For write operations, the
source buffer to write data from.
- @retval EFI_SUCCESS The data was read from or written to the PCI
root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+**/ +EFI_STATUS +EFIAPI +PciRootBridgeIoPciRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to
store the results. For write operations, the
source buffer to write data from.
- @retval EFI_SUCCESS The data was read from or written to the PCI
root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+**/ +EFI_STATUS +EFIAPI +PciRootBridgeIoPciWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
+{
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
1.8.3.1