+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
- PcatPciRootBridgeIo.c\r
- \r
-Abstract:\r
-\r
- EFI PC AT PCI Root Bridge Io Protocol\r
-\r
-Revision History\r
-\r
---*/\r
-\r
-#include "PcatPciRootBridge.h"\r
-#include <IndustryStandard/Pci.h>\r
-#include "SalProc.h"\r
-\r
-#include EFI_GUID_DEFINITION (SalSystemTable)\r
-\r
-//\r
-// Might be good to put this in an include file, but people may start\r
-// using it! They should always access the EFI abstraction that is\r
-// contained in this file. Just a little information hiding.\r
-//\r
-#define PORT_TO_MEM(_Port) ( ((_Port) & 0xffffffffffff0000) | (((_Port) & 0xfffc) << 10) | ((_Port) & 0x0fff) )\r
- \r
-// \r
-// Macro's with casts make this much easier to use and read.\r
-//\r
-#define PORT_TO_MEM8(_Port) (*(UINT8 *)(PORT_TO_MEM(_Port)))\r
-#define PORT_TO_MEM16(_Port) (*(UINT16 *)(PORT_TO_MEM(_Port)))\r
-#define PORT_TO_MEM32(_Port) (*(UINT32 *)(PORT_TO_MEM(_Port)))\r
-\r
-#define EFI_PCI_ADDRESS_IA64(_seg, _bus,_dev,_func,_reg) \\r
- ( (UINT64) ( (((UINTN)_seg) << 24) + (((UINTN)_bus) << 16) + (((UINTN)_dev) << 11) + (((UINTN)_func) << 8) + ((UINTN)_reg)) )\r
-\r
-//\r
-// Local variables for performing SAL Proc calls\r
-//\r
-PLABEL mSalProcPlabel;\r
-CALL_SAL_PROC mGlobalSalProc;\r
-\r
-EFI_STATUS\r
-PcatRootBridgeIoIoRead (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 UserAddress,\r
- IN UINTN Count,\r
- IN OUT VOID *UserBuffer\r
- )\r
-{\r
- PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
- UINTN InStride;\r
- UINTN OutStride;\r
- UINTN AlignMask;\r
- UINTN Address;\r
- PTR Buffer;\r
- UINT16 Data16;\r
- UINT32 Data32;\r
- \r
- \r
- if ( UserBuffer == NULL ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
-\r
- Address = (UINTN) UserAddress;\r
- Buffer.buf = (UINT8 *)UserBuffer;\r
-\r
- if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- if ((UINT32)Width >= EfiPciWidthMaximum) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((Width & 0x03) == EfiPciWidthUint64) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- AlignMask = (1 << (Width & 0x03)) - 1;\r
- if ( Address & AlignMask ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- InStride = 1 << (Width & 0x03);\r
- OutStride = InStride;\r
- if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
- InStride = 0;\r
- }\r
- if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
- OutStride = 0;\r
- }\r
- Width = Width & 0x03;\r
-\r
- Address += PrivateData->PhysicalIoBase;\r
-\r
- //\r
- // Loop for each iteration and move the data\r
- //\r
-\r
- switch (Width) {\r
- case EfiPciWidthUint8:\r
- for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
- MEMORY_FENCE();\r
- *Buffer.ui8 = PORT_TO_MEM8(Address);\r
- MEMORY_FENCE();\r
- }\r
- break;\r
-\r
- case EfiPciWidthUint16:\r
- for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
- MEMORY_FENCE();\r
- if (Buffer.ui & 0x1) {\r
- Data16 = PORT_TO_MEM16(Address);\r
- *Buffer.ui8 = (UINT8)(Data16 & 0xff);\r
- *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);\r
- } else {\r
- *Buffer.ui16 = PORT_TO_MEM16(Address);\r
- }\r
- MEMORY_FENCE();\r
- }\r
- break;\r
-\r
- case EfiPciWidthUint32:\r
- for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
- MEMORY_FENCE();\r
- if (Buffer.ui & 0x3) {\r
- Data32 = PORT_TO_MEM32(Address);\r
- *Buffer.ui8 = (UINT8)(Data32 & 0xff);\r
- *(Buffer.ui8+1) = (UINT8)((Data32 >> 8) & 0xff);\r
- *(Buffer.ui8+2) = (UINT8)((Data32 >> 16) & 0xff);\r
- *(Buffer.ui8+3) = (UINT8)((Data32 >> 24) & 0xff);\r
- } else {\r
- *Buffer.ui32 = PORT_TO_MEM32(Address);\r
- }\r
- MEMORY_FENCE();\r
- }\r
- break;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-PcatRootBridgeIoIoWrite (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 UserAddress,\r
- IN UINTN Count,\r
- IN OUT VOID *UserBuffer\r
- )\r
-{\r
- PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
- UINTN InStride;\r
- UINTN OutStride;\r
- UINTN AlignMask;\r
- UINTN Address;\r
- PTR Buffer;\r
- UINT16 Data16;\r
- UINT32 Data32;\r
-\r
- if ( UserBuffer == NULL ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
-\r
- Address = (UINTN) UserAddress;\r
- Buffer.buf = (UINT8 *)UserBuffer;\r
-\r
- if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((Width & 0x03) == EfiPciWidthUint64) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- AlignMask = (1 << (Width & 0x03)) - 1;\r
- if ( Address & AlignMask ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- InStride = 1 << (Width & 0x03);\r
- OutStride = InStride;\r
- if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
- InStride = 0;\r
- }\r
- if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
- OutStride = 0;\r
- }\r
- Width = Width & 0x03;\r
-\r
- Address += PrivateData->PhysicalIoBase;\r
-\r
- //\r
- // Loop for each iteration and move the data\r
- //\r
-\r
- switch (Width) {\r
- case EfiPciWidthUint8:\r
- for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
- MEMORY_FENCE();\r
- PORT_TO_MEM8(Address) = *Buffer.ui8;\r
- MEMORY_FENCE();\r
- }\r
- break;\r
-\r
- case EfiPciWidthUint16:\r
- for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
- MEMORY_FENCE();\r
- if (Buffer.ui & 0x1) {\r
- Data16 = *Buffer.ui8;\r
- Data16 = Data16 | (*(Buffer.ui8+1) << 8);\r
- PORT_TO_MEM16(Address) = Data16;\r
- } else {\r
- PORT_TO_MEM16(Address) = *Buffer.ui16;\r
- }\r
- MEMORY_FENCE();\r
- }\r
- break;\r
- case EfiPciWidthUint32:\r
- for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
- MEMORY_FENCE();\r
- if (Buffer.ui & 0x3) {\r
- Data32 = *Buffer.ui8;\r
- Data32 = Data32 | (*(Buffer.ui8+1) << 8);\r
- Data32 = Data32 | (*(Buffer.ui8+2) << 16);\r
- Data32 = Data32 | (*(Buffer.ui8+3) << 24);\r
- PORT_TO_MEM32(Address) = Data32;\r
- } else {\r
- PORT_TO_MEM32(Address) = *Buffer.ui32;\r
- }\r
- MEMORY_FENCE();\r
- }\r
- break;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-PcatRootBridgeIoGetIoPortMapping (\r
- OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,\r
- OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping\r
- )\r
-/*++\r
-\r
- Get the IO Port Map from the SAL System Table.\r
- \r
---*/\r
-{\r
- SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable;\r
- SAL_ST_MEMORY_DESCRIPTOR_ENTRY *SalMemDesc;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // On all Itanium architectures, bit 63 is the I/O bit for performming Memory Mapped I/O operations\r
- //\r
- *MemoryPortMapping = 0x8000000000000000;\r
-\r
- Status = EfiLibGetSystemConfigurationTable(&gEfiSalSystemTableGuid, &SalSystemTable);\r
- if (EFI_ERROR(Status)) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // BugBug: Add code to test checksum on the Sal System Table\r
- //\r
- if (SalSystemTable->Entry0.Type != 0) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- mSalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry; \r
- mSalProcPlabel.GP = SalSystemTable->Entry0.GlobalDataPointer;\r
- mGlobalSalProc = (CALL_SAL_PROC)&mSalProcPlabel.ProcEntryPoint;\r
-\r
- //\r
- // The SalSystemTable pointer includes the Type 0 entry.\r
- // The SalMemDesc is Type 1 so it comes next.\r
- //\r
- SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);\r
- while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {\r
- if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {\r
- *IoPortMapping = SalMemDesc->PhysicalMemoryAddress;\r
- *IoPortMapping |= 0x8000000000000000;\r
- return EFI_SUCCESS;\r
- }\r
- SalMemDesc++;\r
- }\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-EFI_STATUS\r
-PcatRootBridgeIoPciRW (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN BOOLEAN Write,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 UserAddress,\r
- IN UINTN Count,\r
- IN OUT UINT8 *UserBuffer\r
- )\r
-{\r
- PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
- UINTN AlignMask;\r
- UINTN InStride;\r
- UINTN OutStride;\r
- UINT64 Address;\r
- DEFIO_PCI_ADDR *Defio;\r
- PTR Buffer;\r
- UINT32 Data32;\r
- UINT16 Data16;\r
- rArg Return;\r
-\r
- if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((Width & 0x03) == EfiPciWidthUint64) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- AlignMask = (1 << (Width & 0x03)) - 1;\r
- if ( UserAddress & AlignMask ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- InStride = 1 << (Width & 0x03);\r
- OutStride = InStride;\r
- if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
- InStride = 0;\r
- }\r
- if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
- OutStride = 0;\r
- }\r
- Width = Width & 0x03;\r
-\r
- Defio = (DEFIO_PCI_ADDR *)&UserAddress;\r
-\r
- if ((Defio->Function > PCI_MAX_FUNC) || (Defio->Device > PCI_MAX_DEVICE)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- \r
- Buffer.buf = (UINT8 *)UserBuffer;\r
- \r
- PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
-\r
- Address = EFI_PCI_ADDRESS_IA64(\r
- This->SegmentNumber, \r
- Defio->Bus, \r
- Defio->Device, \r
- Defio->Function, \r
- Defio->Register\r
- );\r
-\r
- //\r
- // PCI Config access are all 32-bit alligned, but by accessing the\r
- // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types\r
- // are possible on PCI.\r
- //\r
- // SalProc takes care of reading the proper register depending on stride\r
- //\r
-\r
- EfiAcquireLock(&PrivateData->PciLock);\r
-\r
- while (Count) {\r
-\r
- if(Write) {\r
-\r
- if (Buffer.ui & 0x3) {\r
- Data32 = (*(Buffer.ui8+0) << 0);\r
- Data32 |= (*(Buffer.ui8+1) << 8);\r
- Data32 |= (*(Buffer.ui8+2) << 16);\r
- Data32 |= (*(Buffer.ui8+3) << 24);\r
- } else {\r
- Data32 = *Buffer.ui32;\r
- }\r
-\r
- Return.p0 = -3;\r
- Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_WRITE,\r
- Address, 1 << Width, Data32, 0, 0, 0, 0);\r
- \r
- if(Return.p0) {\r
- EfiReleaseLock(&PrivateData->PciLock);\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- } else {\r
-\r
- Return.p0 = -3;\r
- Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_READ,\r
- Address, 1 << Width, 0, 0, 0, 0, 0);\r
-\r
- if(Return.p0) {\r
- EfiReleaseLock(&PrivateData->PciLock);\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- switch (Width) {\r
- case EfiPciWidthUint8:\r
- *Buffer.ui8 = (UINT8)Return.p1;\r
- break;\r
- case EfiPciWidthUint16:\r
- if (Buffer.ui & 0x1) {\r
- Data16 = (UINT16)Return.p1;\r
- *(Buffer.ui8 + 0) = Data16 & 0xff;\r
- *(Buffer.ui8 + 1) = (Data16 >> 8) & 0xff;\r
- } else {\r
- *Buffer.ui16 = (UINT16)Return.p1;\r
- }\r
- break;\r
- case EfiPciWidthUint32:\r
- if (Buffer.ui & 0x3) {\r
- Data32 = (UINT32)Return.p1;\r
- *(Buffer.ui8 + 0) = (UINT8)(Data32 & 0xff);\r
- *(Buffer.ui8 + 1) = (UINT8)((Data32 >> 8) & 0xff);\r
- *(Buffer.ui8 + 2) = (UINT8)((Data32 >> 16) & 0xff);\r
- *(Buffer.ui8 + 3) = (UINT8)((Data32 >> 24) & 0xff);\r
- } else {\r
- *Buffer.ui32 = (UINT32)Return.p1;\r
- }\r
- break;\r
- }\r
- }\r
-\r
- Address += InStride;\r
- Buffer.buf += OutStride;\r
- Count -= 1;\r
- }\r
- \r
- EfiReleaseLock(&PrivateData->PciLock);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-ScanPciRootBridgeForRoms(\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev\r
- )\r
- \r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r