diff options
Diffstat (limited to 'DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf')
-rw-r--r-- | DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c new file mode 100644 index 0000000000..9979d47c4e --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c @@ -0,0 +1,459 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+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.
+
+Module Name:
+ PcatPciRootBridgeIo.c
+
+Abstract:
+
+ EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+#include "pci22.h"
+#include "SalProc.h"
+
+#include EFI_GUID_DEFINITION (SalSystemTable)
+
+//
+// Might be good to put this in an include file, but people may start
+// using it! They should always access the EFI abstraction that is
+// contained in this file. Just a little information hiding.
+//
+#define PORT_TO_MEM(_Port) ( ((_Port) & 0xffffffffffff0000) | (((_Port) & 0xfffc) << 10) | ((_Port) & 0x0fff) )
+
+//
+// Macro's with casts make this much easier to use and read.
+//
+#define PORT_TO_MEM8(_Port) (*(UINT8 *)(PORT_TO_MEM(_Port)))
+#define PORT_TO_MEM16(_Port) (*(UINT16 *)(PORT_TO_MEM(_Port)))
+#define PORT_TO_MEM32(_Port) (*(UINT32 *)(PORT_TO_MEM(_Port)))
+
+#define EFI_PCI_ADDRESS_IA64(_seg, _bus,_dev,_func,_reg) \
+ ( (UINT64) ( (((UINTN)_seg) << 24) + (((UINTN)_bus) << 16) + (((UINTN)_dev) << 11) + (((UINTN)_func) << 8) + ((UINTN)_reg)) )
+
+//
+// Local variables for performing SAL Proc calls
+//
+static PLABEL mSalProcPlabel;
+static CALL_SAL_PROC mGlobalSalProc;
+
+EFI_STATUS
+PcatRootBridgeIoIoRead (
+ 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
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN InStride;
+ UINTN OutStride;
+ UINTN AlignMask;
+ UINTN Address;
+ PTR Buffer;
+ UINT16 Data16;
+ UINT32 Data32;
+
+
+ if ( UserBuffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ Address = (UINTN) UserAddress;
+ Buffer.buf = (UINT8 *)UserBuffer;
+
+ if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) == EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ( Address & AlignMask ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ InStride = 0;
+ }
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ OutStride = 0;
+ }
+ Width = Width & 0x03;
+
+ Address += PrivateData->PhysicalIoBase;
+
+ //
+ // Loop for each iteration and move the data
+ //
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ *Buffer.ui8 = PORT_TO_MEM8(Address);
+ MEMORY_FENCE();
+ }
+ break;
+
+ case EfiPciWidthUint16:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x1) {
+ Data16 = PORT_TO_MEM16(Address);
+ *Buffer.ui8 = (UINT8)(Data16 & 0xff);
+ *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);
+ } else {
+ *Buffer.ui16 = PORT_TO_MEM16(Address);
+ }
+ MEMORY_FENCE();
+ }
+ break;
+
+ case EfiPciWidthUint32:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x3) {
+ Data32 = PORT_TO_MEM32(Address);
+ *Buffer.ui8 = (UINT8)(Data32 & 0xff);
+ *(Buffer.ui8+1) = (UINT8)((Data32 >> 8) & 0xff);
+ *(Buffer.ui8+2) = (UINT8)((Data32 >> 16) & 0xff);
+ *(Buffer.ui8+3) = (UINT8)((Data32 >> 24) & 0xff);
+ } else {
+ *Buffer.ui32 = PORT_TO_MEM32(Address);
+ }
+ MEMORY_FENCE();
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoIoWrite (
+ 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
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN InStride;
+ UINTN OutStride;
+ UINTN AlignMask;
+ UINTN Address;
+ PTR Buffer;
+ UINT16 Data16;
+ UINT32 Data32;
+
+ if ( UserBuffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ Address = (UINTN) UserAddress;
+ Buffer.buf = (UINT8 *)UserBuffer;
+
+ if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) == EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ( Address & AlignMask ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ InStride = 0;
+ }
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ OutStride = 0;
+ }
+ Width = Width & 0x03;
+
+ Address += PrivateData->PhysicalIoBase;
+
+ //
+ // Loop for each iteration and move the data
+ //
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ PORT_TO_MEM8(Address) = *Buffer.ui8;
+ MEMORY_FENCE();
+ }
+ break;
+
+ case EfiPciWidthUint16:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x1) {
+ Data16 = *Buffer.ui8;
+ Data16 = Data16 | (*(Buffer.ui8+1) << 8);
+ PORT_TO_MEM16(Address) = Data16;
+ } else {
+ PORT_TO_MEM16(Address) = *Buffer.ui16;
+ }
+ MEMORY_FENCE();
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x3) {
+ Data32 = *Buffer.ui8;
+ Data32 = Data32 | (*(Buffer.ui8+1) << 8);
+ Data32 = Data32 | (*(Buffer.ui8+2) << 16);
+ Data32 = Data32 | (*(Buffer.ui8+3) << 24);
+ PORT_TO_MEM32(Address) = Data32;
+ } else {
+ PORT_TO_MEM32(Address) = *Buffer.ui32;
+ }
+ MEMORY_FENCE();
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
+ )
+/*++
+
+ Get the IO Port Map from the SAL System Table.
+
+--*/
+{
+ SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable;
+ SAL_ST_MEMORY_DESCRIPTOR_ENTRY *SalMemDesc;
+ EFI_STATUS Status;
+
+ //
+ // On all Itanium architectures, bit 63 is the I/O bit for performming Memory Mapped I/O operations
+ //
+ *MemoryPortMapping = 0x8000000000000000;
+
+ Status = EfiLibGetSystemConfigurationTable(&gEfiSalSystemTableGuid, &SalSystemTable);
+ if (EFI_ERROR(Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // BugBug: Add code to test checksum on the Sal System Table
+ //
+ if (SalSystemTable->Entry0.Type != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ mSalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry;
+ mSalProcPlabel.GP = SalSystemTable->Entry0.GlobalDataPointer;
+ mGlobalSalProc = (CALL_SAL_PROC)&mSalProcPlabel.ProcEntryPoint;
+
+ //
+ // The SalSystemTable pointer includes the Type 0 entry.
+ // The SalMemDesc is Type 1 so it comes next.
+ //
+ SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);
+ while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {
+ if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {
+ *IoPortMapping = SalMemDesc->PhysicalMemoryAddress;
+ *IoPortMapping |= 0x8000000000000000;
+ return EFI_SUCCESS;
+ }
+ SalMemDesc++;
+ }
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+ 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 UINT8 *UserBuffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN AlignMask;
+ UINTN InStride;
+ UINTN OutStride;
+ UINT64 Address;
+ DEFIO_PCI_ADDR *Defio;
+ PTR Buffer;
+ UINT32 Data32;
+ UINT16 Data16;
+ rArg Return;
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) == EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ( UserAddress & AlignMask ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ InStride = 0;
+ }
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ OutStride = 0;
+ }
+ Width = Width & 0x03;
+
+ Defio = (DEFIO_PCI_ADDR *)&UserAddress;
+
+ if ((Defio->Function > PCI_MAX_FUNC) || (Defio->Device > PCI_MAX_DEVICE)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Buffer.buf = (UINT8 *)UserBuffer;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ Address = EFI_PCI_ADDRESS_IA64(
+ This->SegmentNumber,
+ Defio->Bus,
+ Defio->Device,
+ Defio->Function,
+ Defio->Register
+ );
+
+ //
+ // PCI Config access are all 32-bit alligned, but by accessing the
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+ // are possible on PCI.
+ //
+ // SalProc takes care of reading the proper register depending on stride
+ //
+
+ EfiAcquireLock(&PrivateData->PciLock);
+
+ while (Count) {
+
+ if(Write) {
+
+ if (Buffer.ui & 0x3) {
+ Data32 = (*(Buffer.ui8+0) << 0);
+ Data32 |= (*(Buffer.ui8+1) << 8);
+ Data32 |= (*(Buffer.ui8+2) << 16);
+ Data32 |= (*(Buffer.ui8+3) << 24);
+ } else {
+ Data32 = *Buffer.ui32;
+ }
+
+ Return.p0 = -3;
+ Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_WRITE,
+ Address, 1 << Width, Data32, 0, 0, 0, 0);
+
+ if(Return.p0) {
+ EfiReleaseLock(&PrivateData->PciLock);
+ return EFI_UNSUPPORTED;
+ }
+
+ } else {
+
+ Return.p0 = -3;
+ Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_READ,
+ Address, 1 << Width, 0, 0, 0, 0, 0);
+
+ if(Return.p0) {
+ EfiReleaseLock(&PrivateData->PciLock);
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ *Buffer.ui8 = (UINT8)Return.p1;
+ break;
+ case EfiPciWidthUint16:
+ if (Buffer.ui & 0x1) {
+ Data16 = (UINT16)Return.p1;
+ *(Buffer.ui8 + 0) = Data16 & 0xff;
+ *(Buffer.ui8 + 1) = (Data16 >> 8) & 0xff;
+ } else {
+ *Buffer.ui16 = (UINT16)Return.p1;
+ }
+ break;
+ case EfiPciWidthUint32:
+ if (Buffer.ui & 0x3) {
+ Data32 = (UINT32)Return.p1;
+ *(Buffer.ui8 + 0) = (UINT8)(Data32 & 0xff);
+ *(Buffer.ui8 + 1) = (UINT8)((Data32 >> 8) & 0xff);
+ *(Buffer.ui8 + 2) = (UINT8)((Data32 >> 16) & 0xff);
+ *(Buffer.ui8 + 3) = (UINT8)((Data32 >> 24) & 0xff);
+ } else {
+ *Buffer.ui32 = (UINT32)Return.p1;
+ }
+ break;
+ }
+ }
+
+ Address += InStride;
+ Buffer.buf += OutStride;
+ Count -= 1;
+ }
+
+ EfiReleaseLock(&PrivateData->PciLock);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+
+{
+ return EFI_UNSUPPORTED;
+}
|