--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 - 2007, Intel Corporation \r
+All rights reserved. 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
+\r
+ PciIo.c\r
+ \r
+Abstract:\r
+\r
+ PCI I/O Abstraction Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Pcibus.h"\r
+\r
+//\r
+// PCI I/O Support Function Prototypes\r
+//\r
+//\r
+\r
+BOOLEAN \r
+PciDevicesOnTheSamePath (\r
+ IN PCI_IO_DEVICE *PciDevice1,\r
+ IN PCI_IO_DEVICE *PciDevice2\r
+);\r
+\r
+\r
+EFI_STATUS \r
+UpStreamBridgesAttributes (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
+ IN UINT64 Attributes\r
+);\r
+\r
+\r
+BOOLEAN \r
+CheckBarType ( \r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ UINT8 BarIndex,\r
+ PCI_BAR_TYPE BarType\r
+);\r
+\r
+\r
+EFI_STATUS \r
+SetBootVGA ( \r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+);\r
+\r
+EFI_STATUS \r
+DisableBootVGA ( \r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+);\r
+\r
+\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+ PCI_IO_DEVICE *PciIoDevice,\r
+ UINT8 BarIndex,\r
+ PCI_BAR_TYPE Type,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ UINT64 *Offset\r
+);\r
+\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+ PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN UINT64 *Offset\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+);\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+); \r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 DestBarIndex,\r
+ IN UINT64 DestOffset,\r
+ IN UINT8 SrcBarIndex,\r
+ IN UINT64 SrcOffset,\r
+ IN UINTN Count\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ IN VOID *HostAddress\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+ IN EFI_PCI_IO_PROTOCOL *This\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ OUT UINTN *Segment,\r
+ OUT UINTN *Bus,\r
+ OUT UINTN *Device,\r
+ OUT UINTN *Function\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
+ IN UINT64 Attributes,\r
+ OUT UINT64 *Result OPTIONAL\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes(\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN UINT8 BarIndex,\r
+ OUT UINT64 *Supports, OPTIONAL\r
+ OUT VOID **Resources OPTIONAL\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes(\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN UINT8 BarIndex,\r
+ IN OUT UINT64 *Offset,\r
+ IN OUT UINT64 *Length\r
+ );\r
+\r
+\r
+//\r
+// Pci Io Protocol Interface\r
+//\r
+static EFI_PCI_IO_PROTOCOL PciIoInterface = {\r
+ PciIoPollMem,\r
+ PciIoPollIo,\r
+ {\r
+ PciIoMemRead,\r
+ PciIoMemWrite\r
+ },\r
+ {\r
+ PciIoIoRead,\r
+ PciIoIoWrite\r
+ },\r
+ {\r
+ PciIoConfigRead,\r
+ PciIoConfigWrite\r
+ },\r
+ PciIoCopyMem,\r
+ PciIoMap,\r
+ PciIoUnmap,\r
+ PciIoAllocateBuffer,\r
+ PciIoFreeBuffer,\r
+ PciIoFlush,\r
+ PciIoGetLocation,\r
+ PciIoAttributes,\r
+ PciIoGetBarAttributes,\r
+ PciIoSetBarAttributes,\r
+ 0,\r
+ NULL\r
+};\r
+\r
+\r
+EFI_STATUS\r
+InitializePciIoInstance (\r
+ PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initializes a PCI I/O Instance\r
+\r
+Arguments:\r
+ \r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+\r
+{\r
+ CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+ PCI_IO_DEVICE *PciIoDevice,\r
+ UINT8 BarIndex,\r
+ PCI_BAR_TYPE Type,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ UINT64 *Offset\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Verifies access to a PCI Base Address Register (BAR)\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // BarIndex 0-5 is legal\r
+ //\r
+ if (BarIndex >= PCI_MAX_BAR) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!CheckBarType (PciIoDevice, BarIndex, Type)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+ //\r
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ Count = 1;\r
+ }\r
+\r
+ Width &= 0x03;\r
+\r
+ if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+ PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN UINT64 *Offset\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Verifies access to a PCI Config Header\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ UINT64 ExtendOffset;\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+ //\r
+ Width &= 0x03;\r
+\r
+ if (PciIoDevice->IsPciExp) {\r
+ if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ ExtendOffset = LShiftU64 (*Offset, 32);\r
+ *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
+ *Offset = (*Offset) | ExtendOffset;\r
+\r
+ } else {\r
+ if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Poll PCI Memmory\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (Width > EfiPciIoWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->PollMem (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Mask,\r
+ Value,\r
+ Delay,\r
+ Result\r
+ );\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Poll PCI IO\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width > EfiPciIoWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->PollIo (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Mask,\r
+ Value,\r
+ Delay,\r
+ Result\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Performs a PCI Memory Read Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ if (Buffer == NULL){\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Mem.Read (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Performs a PCI Memory Write Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ if (Buffer == NULL){\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Mem.Write (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Performs a PCI I/O Read Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ if (Buffer == NULL){\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Io.Read (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Performs a PCI I/O Write Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ if (Buffer == NULL){\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Io.Write (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Performs a PCI Configuration Read Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ UINT64 Address;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ Address = Offset;\r
+ Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Pci.Read (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Performs a PCI Configuration Write Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ UINT64 Address;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ Address = Offset;\r
+ Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Pci.Write (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 DestBarIndex,\r
+ IN UINT64 DestOffset,\r
+ IN UINT8 SrcBarIndex,\r
+ IN UINT64 SrcOffset,\r
+ IN UINTN Count\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Copy PCI Memory\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Width == EfiPciIoWidthFifoUint8 ||\r
+ Width == EfiPciIoWidthFifoUint16 ||\r
+ Width == EfiPciIoWidthFifoUint32 ||\r
+ Width == EfiPciIoWidthFifoUint64 ||\r
+ Width == EfiPciIoWidthFillUint8 ||\r
+ Width == EfiPciIoWidthFillUint16 ||\r
+ Width == EfiPciIoWidthFillUint32 ||\r
+ Width == EfiPciIoWidthFillUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->CopyMem (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ DestOffset,\r
+ SrcOffset,\r
+ Count\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Maps a memory region for DMA\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {\r
+ Operation = Operation + EfiPciOperationBusMasterRead64;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Map (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
+ HostAddress,\r
+ NumberOfBytes,\r
+ DeviceAddress,\r
+ Mapping\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Unmaps a memory region for DMA\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ Mapping\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Allocates a common buffer for DMA\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ if (Attributes &\r
+ (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {\r
+ Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ Type,\r
+ MemoryType,\r
+ Pages,\r
+ HostAddress,\r
+ Attributes\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ IN VOID *HostAddress\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Frees a common buffer \r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ \r
+ if( HostAddress == NULL ){\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ Pages,\r
+ HostAddress\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+ IN EFI_PCI_IO_PROTOCOL *This\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Flushes a DMA buffer\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 Register;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ //\r
+ // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to \r
+ // flush the posted write cycles through the PCI-PCI bridges\r
+ //\r
+ if (PciIoDevice->Parent != NULL) {\r
+ Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register);\r
+ }\r
+\r
+ //\r
+ // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset\r
+ //\r
+ Status = PciIoDevice->PciRootBridgeIo->Flush (\r
+ PciIoDevice->PciRootBridgeIo\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ OUT UINTN *Segment,\r
+ OUT UINTN *Bus,\r
+ OUT UINTN *Device,\r
+ OUT UINTN *Function\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Gets a PCI device's current bus number, device number, and function number.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;\r
+ *Bus = PciIoDevice->BusNumber;\r
+ *Device = PciIoDevice->DeviceNumber;\r
+ *Function = PciIoDevice->FunctionNumber;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+CheckBarType (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ UINT8 BarIndex,\r
+ PCI_BAR_TYPE BarType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Sets a PCI controllers attributes on a resource range\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ switch (BarType) {\r
+\r
+ case PciBarTypeMem:\r
+\r
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 &&\r
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&\r
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&\r
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+\r
+ case PciBarTypeIo:\r
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&\r
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL * This,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
+ IN UINT64 Attributes,\r
+ OUT UINT64 *Result OPTIONAL\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ PCI_IO_DEVICE *Temp;\r
+ UINT64 NewAttributes;\r
+ UINT64 PciRootBridgeSupports;\r
+ UINT64 PciRootBridgeAttributes;\r
+ UINT64 NewPciRootBridgeAttributes;\r
+ UINT64 NewUpStreamBridgeAttributes;\r
+ UINT64 ModifiedPciRootBridgeAttributes;\r
+ UINT16 EnableCommand;\r
+ UINT16 DisableCommand;\r
+ UINT16 EnableBridge;\r
+ UINT16 DisableBridge;\r
+ UINT16 Command;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+ NewUpStreamBridgeAttributes = 0;\r
+\r
+ EnableCommand = 0;\r
+ DisableCommand = 0;\r
+ EnableBridge = 0;\r
+ DisableBridge = 0;\r
+\r
+ switch (Operation) {\r
+ case EfiPciIoAttributeOperationGet:\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Result = PciIoDevice->Attributes;\r
+ return EFI_SUCCESS;\r
+\r
+ case EfiPciIoAttributeOperationSupported:\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Result = PciIoDevice->Supports;\r
+ return EFI_SUCCESS;\r
+\r
+ case EfiPciIoAttributeOperationEnable:\r
+ if(Attributes & ~(PciIoDevice->Supports)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ NewAttributes = PciIoDevice->Attributes | Attributes;\r
+ break;\r
+ case EfiPciIoAttributeOperationDisable:\r
+ if(Attributes & ~(PciIoDevice->Supports)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ NewAttributes = PciIoDevice->Attributes & (~Attributes);\r
+ break;\r
+ case EfiPciIoAttributeOperationSet:\r
+ if(Attributes & ~(PciIoDevice->Supports)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ NewAttributes = Attributes;\r
+ break;\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // If VGA_IO is set, then set VGA_MEMORY too. This driver can not enable them seperately.\r
+ //\r
+ if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {\r
+ NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+ }\r
+\r
+ //\r
+ // If VGA_MEMORY is set, then set VGA_IO too. This driver can not enable them seperately.\r
+ //\r
+ if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) {\r
+ NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+ }\r
+\r
+ //\r
+ // If the attributes are already set correctly, then just return EFI_SUCCESS;\r
+ //\r
+ if ((NewAttributes ^ PciIoDevice->Attributes) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and\r
+ // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER. Strip these 3 bits off the new attribute mask so\r
+ // a call to the PCI Root Bridge I/O Protocol can be made\r
+ //\r
+\r
+ if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) {\r
+ NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));\r
+\r
+ // \r
+ // Get the current attributes of this PCI device's PCI Root Bridge\r
+ //\r
+ Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ &PciRootBridgeSupports,\r
+ &PciRootBridgeAttributes\r
+ );\r
+\r
+ //\r
+ // Check to see if any of the PCI Root Bridge attributes are being modified\r
+ //\r
+ ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes;\r
+ if (ModifiedPciRootBridgeAttributes) {\r
+\r
+ //\r
+ // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing\r
+ //\r
+ if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) {\r
+ // return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Call the PCI Root Bridge to attempt to modify the attributes\r
+ //\r
+ Status = PciIoDevice->PciRootBridgeIo->SetAttributes (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ NewPciRootBridgeAttributes,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The PCI Root Bridge could not modify the attributes, so return the error.\r
+ //\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) {\r
+\r
+\r
+ //\r
+ // Check to see if an VGA related attributes are being set.\r
+ //\r
+ if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {\r
+\r
+ if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {\r
+ EnableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
+ } else {\r
+ DisableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check to see if an VGA related attributes are being set.\r
+ // If ISA Enable on the PPB is set, the PPB will block the\r
+ // 0x100-0x3FF for each 1KB block in the first 64K I/O block\r
+ //\r
+ if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) {\r
+\r
+ if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {\r
+ DisableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
+ } else {\r
+ EnableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check to see if an VGA related attributes are being set.\r
+ //\r
+ if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {\r
+\r
+ if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {\r
+ EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ } else {\r
+ DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ }\r
+ }\r
+\r
+ } else {\r
+\r
+ if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {\r
+\r
+ if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {\r
+\r
+ //\r
+ //Check if there have been an active VGA device on the same segment\r
+ //\r
+ Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+\r
+ if (Temp && Temp != PciIoDevice) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ }\r
+\r
+ if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {\r
+ if (IS_PCI_GFX(&PciIoDevice->Pci)) {\r
+\r
+ //\r
+ //Get the boot VGA on the same segement\r
+ //\r
+ Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+\r
+ if (!Temp) {\r
+\r
+ //\r
+ // If there is no VGA device on the segement, set\r
+ // this graphics card to decode the palette range\r
+ //\r
+ DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ } else {\r
+\r
+ //\r
+ // Check these two agents are on the same path\r
+ //\r
+ if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) {\r
+\r
+ //\r
+ // Check if they are on the same bus\r
+ //\r
+ if (Temp->Parent == PciIoDevice->Parent) {\r
+\r
+ PciReadCommandRegister (Temp, &Command);\r
+\r
+ //\r
+ // If they are on the same bus, either one can\r
+ // be set to snoop, the other set to decode\r
+ //\r
+ if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {\r
+ DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ } else {\r
+ EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ }\r
+ } else {\r
+\r
+ //\r
+ // If they are on the same path but on the different bus\r
+ // The first agent is set to snoop, the second one set to\r
+ // decode\r
+ //\r
+ if (Temp->BusNumber > PciIoDevice->BusNumber) {\r
+ PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+ DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ } else {\r
+ PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+ EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ }\r
+ }\r
+ } else {\r
+\r
+ EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check to see of the I/O enable is being modified\r
+ //\r
+ if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) {\r
+ if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) {\r
+ EnableCommand |= EFI_PCI_COMMAND_IO_SPACE;\r
+ } else {\r
+ DisableCommand |= EFI_PCI_COMMAND_IO_SPACE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check to see of the Memory enable is being modified\r
+ //\r
+ if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) {\r
+ if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {\r
+ EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
+ } else {\r
+ DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check to see of the Bus Master enable is being modified\r
+ //\r
+ if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) {\r
+ if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {\r
+ EnableCommand |= EFI_PCI_COMMAND_BUS_MASTER;\r
+ } else {\r
+ DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER;\r
+ }\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ if (EnableCommand) {\r
+ Status = PciEnableCommandRegister(PciIoDevice, EnableCommand);\r
+ } \r
+\r
+ if (DisableCommand) {\r
+ Status = PciDisableCommandRegister(PciIoDevice, DisableCommand);\r
+ }\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (EnableBridge) {\r
+ Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge);\r
+ }\r
+\r
+ if (DisableBridge) {\r
+ Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge);\r
+ }\r
+ \r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Set the upstream bridge attributes\r
+ //\r
+ if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) {\r
+\r
+ //\r
+ // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER\r
+ // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED\r
+ // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge\r
+ // \r
+ NewUpStreamBridgeAttributes = Attributes & \\r
+ (~(EFI_PCI_IO_ATTRIBUTE_IO | \\r
+ EFI_PCI_IO_ATTRIBUTE_MEMORY | \\r
+ EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \\r
+ EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \\r
+ EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \\r
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));\r
+\r
+ if (NewUpStreamBridgeAttributes){\r
+ UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes);\r
+ }\r
+ }\r
+ \r
+ PciIoDevice->Attributes = NewAttributes;\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL * This,\r
+ IN UINT8 BarIndex,\r
+ OUT UINT64 *Supports, OPTIONAL\r
+ OUT VOID **Resources OPTIONAL\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+\r
+ UINT8 *Configuration;\r
+ UINT8 NumConfig;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
+\r
+ NumConfig = 0;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Supports == NULL && Resources == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BarIndex >= PCI_MAX_BAR) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // This driver does not support modifications to the WRITE_COMBINE or\r
+ // CACHED attributes for BAR ranges.\r
+ //\r
+ if (Supports != NULL) {\r
+ *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+ }\r
+\r
+ if (Resources != NULL) {\r
+\r
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {\r
+ NumConfig = 1;\r
+ }\r
+\r
+ Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+ if (Configuration == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ ZeroMem (\r
+ Configuration,\r
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+ );\r
+\r
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+\r
+ if (NumConfig == 1) {\r
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+\r
+ Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+ Ptr->AddrLen = PciIoDevice->PciBar[BarIndex].Length;\r
+ Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;\r
+\r
+ switch (PciIoDevice->PciBar[BarIndex].BarType) {\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+ //\r
+ // Io\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ break;\r
+\r
+ case PciBarTypeMem32:\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // 32 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case PciBarTypePMem32:\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // prefechable\r
+ //\r
+ Ptr->SpecificFlag = 0x6;\r
+ //\r
+ // 32 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case PciBarTypeMem64:\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // 64 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 64;\r
+ break;\r
+\r
+ case PciBarTypePMem64:\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // prefechable\r
+ //\r
+ Ptr->SpecificFlag = 0x6;\r
+ //\r
+ // 64 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 64;\r
+ break;\r
+ }\r
+\r
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
+ }\r
+ \r
+ //\r
+ // put the checksum\r
+ //\r
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ PtrEnd->Checksum = 0;\r
+\r
+ *Resources = Configuration;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN UINT8 BarIndex,\r
+ IN OUT UINT64 *Offset,\r
+ IN OUT UINT64 *Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ UINT64 NonRelativeOffset;\r
+ UINT64 Supports;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ //\r
+ // Make sure Offset and Length are not NULL\r
+ //\r
+ if (Offset == NULL || Length == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.\r
+ // If Attributes is not 0, then return EFI_UNSUPPORTED.\r
+ //\r
+ Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+\r
+ if (Attributes != (Attributes & Supports)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and\r
+ // Length are valid for this PCI device.\r
+ //\r
+ NonRelativeOffset = *Offset;\r
+ Status = PciIoVerifyBarAccess (\r
+ PciIoDevice,\r
+ BarIndex,\r
+ PciBarTypeMem,\r
+ EfiPciIoWidthUint8,\r
+ (UINT32) *Length,\r
+ &NonRelativeOffset\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpStreamBridgesAttributes (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
+ IN UINT64 Attributes\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PCI_IO_DEVICE *Parent;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ Parent = PciIoDevice->Parent;\r
+\r
+ while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {\r
+\r
+ //\r
+ // Get the PciIo Protocol\r
+ //\r
+ PciIo = &Parent->PciIo;\r
+\r
+ PciIo->Attributes (PciIo, Operation, Attributes, NULL);\r
+\r
+ Parent = Parent->Parent;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+PciDevicesOnTheSamePath (\r
+ IN PCI_IO_DEVICE *PciDevice1,\r
+ IN PCI_IO_DEVICE *PciDevice2\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ PciDevice1 - The pointer to the first PCI_IO_DEVICE.\r
+ PciDevice2 - The pointer to the second PCI_IO_DEVICE.\r
+\r
+Returns:\r
+\r
+ TRUE - The two Pci devices are on the same path.\r
+ FALSE - The two Pci devices are not on the same path.\r
+\r
+--*/\r
+{\r
+\r
+ if (PciDevice1->Parent == PciDevice2->Parent) {\r
+ return TRUE;\r
+ }\r
+\r
+ return (PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1));\r
+}\r