summaryrefslogtreecommitdiff
path: root/Core/EM/PCI
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/PCI
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/PCI')
-rw-r--r--Core/EM/PCI/DeviceIo.c696
-rw-r--r--Core/EM/PCI/PciBus.c13734
-rw-r--r--Core/EM/PCI/PciBus.chmbin0 -> 89243 bytes
-rw-r--r--Core/EM/PCI/PciBus.cif19
-rw-r--r--Core/EM/PCI/PciBus.mak152
-rw-r--r--Core/EM/PCI/PciBus.sd1067
-rw-r--r--Core/EM/PCI/PciBus.sdl351
-rw-r--r--Core/EM/PCI/PciBus.unibin0 -> 34772 bytes
-rw-r--r--Core/EM/PCI/PciBusSetup.c97
-rw-r--r--Core/EM/PCI/PciBusSrc.chmbin0 -> 179322 bytes
-rw-r--r--Core/EM/PCI/PciBusSrc.cif13
-rw-r--r--Core/EM/PCI/PciBusSrc.mak82
-rw-r--r--Core/EM/PCI/PciBusSrc.sdl37
-rw-r--r--Core/EM/PCI/PciHostBridge.c3814
-rw-r--r--Core/EM/PCI/PciPort.c926
-rw-r--r--Core/EM/PCI/PciPort.h136
-rw-r--r--Core/EM/PCI/PciRootBridge.dxs67
-rw-r--r--Core/EM/PCI/PciSetup.h155
18 files changed, 21346 insertions, 0 deletions
diff --git a/Core/EM/PCI/DeviceIo.c b/Core/EM/PCI/DeviceIo.c
new file mode 100644
index 0000000..c9c9605
--- /dev/null
+++ b/Core/EM/PCI/DeviceIo.c
@@ -0,0 +1,696 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/PciBus/DeviceIo.c 1 3/12/07 12:02p Yakovlevs $
+//
+// $Revision: 1 $
+//
+// $Date: 3/12/07 12:02p $
+//*****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/PciBus/DeviceIo.c $
+//
+// 1 3/12/07 12:02p Yakovlevs
+//
+// 3 4/03/06 5:17p Felixp
+// Updated to support new PCI infrastructure
+//
+// 1 4/01/05 12:45p Robert
+// Initial Checkin
+//
+// 1 1/21/05 6:27p Sivagarn
+// NB Chipset Template Initial Checkin - Based on template version 0001
+//
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//
+// Name: DeviceIo_c
+//
+// Description: This file contains the DeviceIo Protocol and its construction.
+//
+//<AMI_FHDR_END>
+//*****************************************************************************
+
+#include <Token.h>
+#if AMI_ROOT_BRIDGE_SUPPORT == 1
+/****** DO NOT WRITE ABOVE THIS LINE *******/
+
+#include "PciHostBridge.h"
+#include <Protocol\PciIo.h>
+#include <Protocol\DevicePath.h>
+
+typedef struct {
+ EFI_DEVICE_IO_INTERFACE DeviceIo;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} PRIVATE_DEVICE_IO;
+
+EFI_GUID gPciIoProtocolGuid = EFI_PCI_IO_PROTOCOL_GUID;
+EFI_GUID gEfiDevicePathProtocolGuid=EFI_DEVICE_PATH_PROTOCOL_GUID;
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoMemRead
+//
+// Description: Read memory into a buffer.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN EFI_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: PciMemRead
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Validate width parameter. The parameter is a subset of the one used by RootBridgeIo.
+// 2. Call PciRootBridgeIo PciMemRead and return its Status.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoMemRead (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ if (Width >= IO_UINT64) return EFI_INVALID_PARAMETER;
+ return PciMemRead (((PRIVATE_DEVICE_IO*)This)->RootBridgeIo,Width,Address,Count,Buffer);
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoMemWrite
+//
+// Description: Write memory from a buffer.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN EFI_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: PciMemWrite
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Validate width parameter. The parameter is a subset of the one used by RootBridgeIo.
+// 2. Call PciRootBridgeIo PciMemWrite and return its Status.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoMemWrite (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ if (Width >= IO_UINT64) return EFI_INVALID_PARAMETER;
+ return PciMemWrite (((PRIVATE_DEVICE_IO*)This)->RootBridgeIo,Width,Address,Count,Buffer);
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoIoRead
+//
+// Description: Read Io into a buffer.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN EFI_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: PciIoRead
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Validate width parameter. The parameter is a subset of the one used by RootBridgeIo.
+// 2. Call PciRootBridgeIo PciIoRead and return its Status.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoIoRead (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ if (Width >= IO_UINT64) return EFI_INVALID_PARAMETER;
+ return PciIoRead (((PRIVATE_DEVICE_IO*)This)->RootBridgeIo,Width,Address,Count,Buffer);
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoIoWrite
+//
+// Description: Write Io from a buffer.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+/// IN EFI_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: PciIoWrite
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Validate width parameter. The parameter is a subset of the one used by RootBridgeIo.
+// 2. Call PciRootBridgeIo PciIoWrite and return its Status.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoIoWrite (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ if (Width >= IO_UINT64) return EFI_INVALID_PARAMETER;
+ return PciIoWrite (((PRIVATE_DEVICE_IO*)This)->RootBridgeIo,Width,Address,Count,Buffer);
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoPciRead
+//
+// Description: Read Pci registers into a buffer.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN EFI_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: PciRead
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Validate width parameter. The parameter is a subset of the one used by RootBridgeIo.
+// 2. Call PciRootBridgeIo PciRead and return its Status.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoPciRead (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ if (Width >= IO_UINT64) return EFI_INVALID_PARAMETER;
+ return PciRead (((PRIVATE_DEVICE_IO*)This)->RootBridgeIo,Width,Address,Count,Buffer);
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoPciWrite
+//
+// Description: Write Pci registers from a buffer.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN EFI_IO_WIDTH Width
+// IN UINT64 Address
+// IN UINTN Count
+// IN OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: PciWrite
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Validate width parameter. The parameter is a subset of the one used by RootBridgeIo.
+// 2. Call PciRootBridgeIo PciWrite and return its Status.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoPciWrite (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ if (Width >= IO_UINT64) return EFI_INVALID_PARAMETER;
+ return PciWrite (((PRIVATE_DEVICE_IO*)This)->RootBridgeIo,Width,Address,Count,Buffer);
+}
+
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoPciDevicePath
+//
+// Description: Get a device path for a Pci Bus/Device/Function.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN UINT64 PciAddress
+// IN OUT EFI_DEVICE_PATH **PciDevicePath
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: LocateHandleBuffer HandleProtocol GetLocation DPCopy FreePool
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Locate handes of the PciIo Protocol.
+// 2. Call the PciIo function GetLocation to find the matching PciDevicePath.
+// 3. If match found, copy the the DevicePath on the same handle as the PciIo
+// Protocol. Otherwise, return EFI_UNSUPPORTED.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoPciDevicePath (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN UINT64 PciAddress,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
+)
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *Path;
+
+ UINTN Segment, Bus, Device, Function;
+ EFI_STATUS Status;
+ UINTN NoHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN i;
+
+ EFI_PCI_CONFIGURATION_ADDRESS PciAddr;
+ *(UINT64*)&PciAddr = PciAddress;
+
+ Status = pBS->LocateHandleBuffer (
+ ByProtocol,
+ &gPciIoProtocolGuid,
+ NULL,
+ &NoHandles,
+ &HandleBuffer);
+ if (EFI_ERROR(Status)) return Status;
+
+ for(i = 0; i < NoHandles; ++i)
+ {
+ Status = pBS->HandleProtocol(
+ HandleBuffer[i],
+ &gPciIoProtocolGuid,
+ &PciIo
+ );
+ if (EFI_ERROR(Status)) goto Exit; //Should never get an error here.
+
+ Status = PciIo->GetLocation(PciIo,
+ &Segment,
+ &Bus,
+ &Device,
+ &Function
+ );
+ if (EFI_ERROR(Status)) goto Exit; //Should never get an error here.
+
+
+ //Note: Difference in DeviceIo and PciRootBridgeIo defintion of PciAddress for bits [64:32].
+ //DeviceIo [39:32] = Segment and PciRootBridgeIo [64:32] = Extended register
+ if (Segment != (PciAddr.ExtendedRegister&0xff)) continue;
+ if (Bus != PciAddr.Bus || Device != PciAddr.Device || Function != PciAddr.Function) continue;
+
+ Status = pBS->HandleProtocol(
+ HandleBuffer[i],
+ &gEfiDevicePathProtocolGuid,
+ &Path
+ );
+ if (EFI_ERROR(Status))
+ {
+ Status = EFI_UNSUPPORTED; //Should never get an error here. Should always have a device path.
+ goto Exit;
+ }
+
+ *PciDevicePath = DPCopy(Path); //Copy device path.
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ Status = EFI_UNSUPPORTED;
+Exit:
+ pBS->FreePool(HandleBuffer);
+ return Status;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoMap
+//
+// Description: Map a device address to a host address.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN EFI_IO_OPERATION_TYPE Operation
+// IN EFI_PHYSICAL_ADDRESS *HostAddress
+// IN OUT UINTN *NumberOfBytes
+// OUT EFI_PHYSICAL_ADDRESS *DeviceAddress
+// OUT VOID **Mapping
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: Map
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Verify Operation. It is a subset of the PciRootBridgeIo Map Operation.
+// 2. Verify valid map address range. Can not map any addresses over 4G.
+// 3. Call PciRootBridgeIo Map.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoMap (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN EFI_IO_OPERATION_TYPE Operation,
+ IN EFI_PHYSICAL_ADDRESS *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+)
+{
+ if ((unsigned)Operation > EfiBusMasterCommonBuffer) return EFI_INVALID_PARAMETER;
+ if ((*HostAddress + *NumberOfBytes) > 0xffffffff) return EFI_UNSUPPORTED;
+
+ return Map(
+ ((PRIVATE_DEVICE_IO*)This)->RootBridgeIo,
+ Operation,
+ (VOID*)(*HostAddress),
+ NumberOfBytes,
+ DeviceAddress,
+ Mapping);
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoUnmap
+//
+// Description: Unmap a device.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN VOID *Mapping
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: Unmap
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Call PciRootBridgeIo UnMap.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoUnmap (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN VOID *Mapping
+)
+{
+ return Unmap(((PRIVATE_DEVICE_IO*)This)->RootBridgeIo, Mapping);
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoAllocateBuffer
+//
+// Description: Allocate a buffer.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN EFI_ALLOCATE_TYPE Type
+// IN EFI_MEMORY_TYPE MemoryType
+// IN UINTN Pages
+// IN OUT EFI_PHYSICAL_ADDRESS *HostAddress
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AllocatePages
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Verify inputs to function.
+// 2. If allocate type is AllocateAnyPages, change max address of 4G-1.
+// 3. If allocate type is AllocateMaxAddress of 4G, change max address to 4G-1.
+// 4. If allocate type is AllocateAddress, verify address is les than 4G.
+// 3. Call BootServices Alloate.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoAllocateBuffer (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *HostAddress
+)
+{
+ EFI_STATUS Status;
+ EFI_ALLOCATE_TYPE AllocateType = Type; //May be changed in the code below.
+
+
+ if (HostAddress == NULL) return EFI_INVALID_PARAMETER;
+ if (AllocateType >= MaxAllocateType) return EFI_INVALID_PARAMETER;
+
+ // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
+ if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData)
+ return EFI_INVALID_PARAMETER;
+
+ if (AllocateType == AllocateAnyPages)
+ {
+ AllocateType = AllocateMaxAddress;
+ *HostAddress = 0xffffffff;
+ } else if (AllocateType == AllocateMaxAddress && *HostAddress > 0xffffffff)
+ {
+ *HostAddress = 0xffffffff;
+ } else //AllocateAddress
+ {
+ if (*HostAddress + 4096 * Pages > 0xffffffff) return EFI_UNSUPPORTED;
+ }
+
+
+ Status = pBS->AllocatePages (AllocateType, MemoryType, Pages, HostAddress);
+ if (EFI_ERROR(Status)) return Status;
+
+ return EFI_SUCCESS;
+}
+
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoFlush
+//
+// Description: Flush cache lines.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: Flush
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Call PciRootBridgeIo Flush.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoFlush (
+ IN EFI_DEVICE_IO_INTERFACE *This
+)
+{
+ return Flush(((PRIVATE_DEVICE_IO*)This)->RootBridgeIo);
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DeviceIoFreeBuffer
+//
+// Description: Free a buffer.
+//
+// Input:
+// IN EFI_DEVICE_IO_INTERFACE *This
+// IN UINTN Pages
+// IN EFI_PHYSICAL_ADDRESS HostAddress
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: FreeBuffer
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Call PciRootBridgeIo FreeBuffer.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS DeviceIoFreeBuffer (
+ IN EFI_DEVICE_IO_INTERFACE *This,
+ IN UINTN Pages,
+ IN EFI_PHYSICAL_ADDRESS HostAddress
+)
+{
+ return FreeBuffer(((PRIVATE_DEVICE_IO*)This)->RootBridgeIo,Pages,(VOID*)HostAddress);
+}
+
+
+EFI_DEVICE_IO_INTERFACE gDeviceIo = {
+ {DeviceIoMemRead,DeviceIoMemWrite},
+ {DeviceIoIoRead,DeviceIoIoWrite},
+ {DeviceIoPciRead,DeviceIoPciWrite},
+ DeviceIoMap,
+ DeviceIoPciDevicePath,
+ DeviceIoUnmap,
+ DeviceIoAllocateBuffer,
+ DeviceIoFlush,
+ DeviceIoFreeBuffer
+};
+
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: ConstructDeviceIoProtocol
+//
+// Description: Construct a DeviceIo protocol.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo
+// IN EFI_DEVICE_PATH *Path
+//
+// Output:
+// EFI_DEVICE_IO_INTERFACE *
+//
+// Modified:
+//
+// Referrals: AllocatePool
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Allocate moemory for Private DeviceIo.
+// 2. Copy DeviceIo functions to private structure.
+// 3. Copy pointer RootBridgeIo to private structure.
+// 4. Copy pointer to RootBridgeIo path to private structure.
+// 5. Return pointer to private structure.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_DEVICE_IO_INTERFACE * ConstructDeviceIoProtocol(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * RootBridgeIo, EFI_DEVICE_PATH_PROTOCOL *Path)
+{
+ EFI_STATUS Status;
+ PRIVATE_DEVICE_IO *PrivateDeviceIo;
+
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(PRIVATE_DEVICE_IO),&PrivateDeviceIo);
+ if (EFI_ERROR(Status)) return 0;
+
+ PrivateDeviceIo->DeviceIo = gDeviceIo;
+ PrivateDeviceIo->RootBridgeIo = RootBridgeIo;
+ PrivateDeviceIo->DevicePath = Path;
+
+ return (EFI_DEVICE_IO_INTERFACE*)PrivateDeviceIo;
+}
+
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#endif //#if AMI_ROOT_BRIDGE_SUPPORT == 1
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/PCI/PciBus.c b/Core/EM/PCI/PciBus.c
new file mode 100644
index 0000000..bbd51a8
--- /dev/null
+++ b/Core/EM/PCI/PciBus.c
@@ -0,0 +1,13734 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/PCI/PciBus.c 3 12/19/12 7:07a Wesleychen $
+//
+// $Revision: 3 $
+//
+// $Date: 12/19/12 7:07a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/PCI/PciBus.c $
+//
+// 3 12/19/12 7:07a Wesleychen
+// Update to rev#152 for EIP107491.
+//
+// 152 11/26/12 4:23p Yakovlevs
+// [TAG] EIP107491
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] PciBus can not detect some pcie card (LSI).
+// [RootCause] A config write is required in order for the device to
+// re-capture the Bus number
+// [Solution] Add a dummy config write to VID/DID register offset 0
+// [Files] PciBus.c
+//
+// 150 9/20/12 12:15p Yakovlevs
+// [TAG] EIP100249
+// [Category] New Feature
+// [Description] Token to set PCIE capabilities Clock PM default value.
+// Clock PM Settings was excluded for GEN1 devices.
+//
+// [Files] PciBus.c
+//
+// 149 9/12/12 11:55a Yakovlevs
+// Restoring overrided Artem's changes.
+//
+// 148 9/12/12 11:51a Yakovlevs
+// [TAG] EIP99393
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] I350 Powerville LOM UEFI driver is not loading
+// [RootCause] Issue in invocation following function.
+// DoubleCheckOpRom((VOID*)&PciRomHdr, &Pcir);
+// variable PciRomHd was defined as buffer in stack but function requeres
+// actual pointer at the ROM
+// [Solution] Replace Parameters passing from PciRomHd to (base + trs)
+// [Files] PciBus,c
+//
+// 146 9/10/12 12:51p Yakovlevs
+// [TAG] EIP93341
+// [Category] Improvement
+// [Description] Preserve PCI DEV/LNK/SLT control register in S3 resume
+// path.
+// [Files] PciBus.c PciBus.sd PciBus.uni PciSetup.h PciPort.c
+//
+// 145 7/20/12 12:50p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Call GetOptRom before installing PciIO protocol, so ROM
+// pointer has valid vaule
+// [Files] Pcibus.c
+//
+// 144 7/13/12 5:14p Yakovlevs
+// [TAG] EIP94699
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Coding error in PciBus.c
+// [RootCause] Typo
+// [Solution] fixing typo replace tBarMmio64 with tBarMmio64pf
+// [Files] PciBus.c
+//
+// 143 6/26/12 5:53p Yakovlevs
+// [TAG] EIP93341
+// [Category] Improvement
+// [Description] Preserve PCI DEV/LNK/SLT control register in S3 resume
+// path.
+// [Files] PciBus.c
+//
+// 142 6/20/12 12:25p Olegi
+// [TAG] EIP93141
+// [Description] PCI_IO_PROTOCOL.Attributes may fail
+//
+// 141 5/22/12 4:49p Yakovlevs
+// Removing wrong comment
+//
+// 140 5/21/12 3:39p Artems
+// [TAG] EIP86097
+// [Category] Improvement
+// [Description] Separate control for loading UEFI Oprom Driver
+// Added porting hook to CsmOptOut to enable/disable UEFI
+// OpROM execution for particular PCI device, identified by PCI handle
+// [Files] PciBus.c CsmOptOut.c
+//
+// 139 5/01/12 5:07p Yakovlevs
+// [TAG] EIP84986
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Yellow mark issue in windows device manager on
+// PCIe slots if only 2 CPU for potter city platform.
+// [RootCause] For multy root system where root socets partialy
+// populated SDL data interfered with
+// Actual Hardware configuration.
+// [Solution] Allow control flow keep going when certain
+// ERROR_STATUS received.
+// [Files] PciBus.c; PciHostBridge.c
+//
+// 138 5/01/12 4:25p Yakovlevs
+// [TAG] EIP88259
+// [Category] Improvement
+// [Description] Have valid PCI handle before processing OpROM
+// [Files] PciBus.c
+//
+// 137 4/10/12 10:16a Yakovlevs
+// [TAG] EIP87005
+// [Category] Bug Fix
+// [Symptom] Aptio4.6.5.3...SCT Execution test failed.(PCI Bus Support
+// Test\PCI IO Protocol Test)
+// [RootCause] In DevAttributes() function we have masking
+// Platform specific attributes since they don't affect
+// functionality but may hung the system when somebody ties
+// to set or reset it.
+// [Solution] Remove code masking attributes 0x2000 0x4000
+// [Files] PciBus.c
+//
+// 136 12/19/11 2:08p Yakovlevs
+// [TAG] EIP73172
+// [Category] Bug Fix
+// [RootCause] It tires to read the PCI ROM header in DWORD unit.
+// However the size of PCI_STD_OPT_ROM_HEADER is 26 which can not be
+// divided by 4 without reminders.
+// After this change it will only read 24 bytes, the last 2 bytes
+// (PCI_STD_OPT_ROM_HEADER.PcirOffset) will not be read.
+// The code then read memory from the PcirOffset pointer which is
+// undefined....
+//
+// [Solution] Roll back changes keeping 1 Byte access to the opt ROM
+// header
+// [Files] PCiBus.c
+//
+// 135 12/19/11 11:06a Yakovlevs
+//
+// 134 12/19/11 11:05a Yakovlevs
+// [TAG] EIP73172
+// [Description] (JPJP000D) It stops POST Code 94h, when connected PCIE
+// media read/write device.
+// [Files] Added 4 byte alligned structure definition to handle 4 byte
+// header read.
+//
+// 133 12/14/11 6:44p Yakovlevs
+// [TAG] EIP73172
+// [Description] (JPJP000D) It stops POST Code 94h, when connected PCIE
+// media read/write device.
+// Also: fixed Init pci_address var in SetSlotProprties();
+// Fixed reconnect -r issue in PciBusStart()
+// Changed size of access to the ROM BAR register in GetOpRom() from 1
+// byte to 4 - some cards could hang the system if 1 byte is used
+//
+// [Files] PciBus.c
+//
+// 132 12/07/11 11:00a Yakovlevs
+// Fixed potential bug in PcieSetSlotProperties() routine. It was using
+// uninitialized ADDRESS var.
+//
+// 131 12/02/11 2:30p Yakovlevs
+// According to AMD GOP Driver GetBarAttributes() must return _GRA field
+// set as a bar type NOT A RESOURCE TYPE.
+//
+// 130 11/09/11 2:03p Yakovlevs
+// [TAG] EIP71380
+// [Category] New Feature
+// [Description] Core support for CSM opt-out feature
+// [Files] PciBus.c; PciPort.c; PciBus.sd; PciBus.uni; PciSetup.h;
+// PciBusSetup.c;
+//
+// 129 11/08/11 11:03a Yakovlevs
+// [TAG] EIP72803
+// [Category] Improvement
+// [Description] Small fixes of previous checkin
+// [Files] PciBus.c
+//
+// 128 11/03/11 5:59p Yakovlevs
+// Added some debug messages.
+//
+// 127 11/03/11 5:39p Yakovlevs
+// [TAG] EIP72803
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Incorrect Max Payload setting
+// [RootCause] The issue was that recorded MPL value was updated before
+// PcieProgramPayloadUp() function was invoked.
+// In that function we check condition again since it was needed to
+// maintain loop exit.
+// But control newer enter the loop since conditions were not met at that
+// point for reason stated above.
+//
+// [Solution] Move code that updates recorded MPL with a new value
+// after call to PcieProgramPayloadUp().
+// [Files] PciBus.c
+//
+// 126 10/17/11 2:39p Yakovlevs
+// [TAG] EIP71694
+// [Category] Bug Fix
+// [Symptom] Option ROM is corrupted when copied from device on Rosecity
+// Core 4.6.5.1.
+// [RootCause] MemCopy routine was updated to use 64 bit access but PCI
+// BAR
+// Copy cannot handle this
+//
+// [Solution] Introduced MemCpy32 routine to handle fast copy 4 byte at
+// a time
+// [Files] PciBus.c; MemCpy32.asm; AmiLib.h
+//
+// 124 8/03/11 2:19p Artems
+// Added changes discarded by previous check-in
+//
+// 123 8/03/11 1:14p Artems
+// EIP 64107: Added changes for module to be compliant with UEFI
+// specification v 2.3.1
+// 122 8/02/11 3:51p Yakovlevs
+// [TAG] EIP66216
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Hotplug resource padding not working for ROOT bridges other
+// than 0
+// [RootCause] Hot plug slots was incorrectly associated alvays withthe
+// RootBridge #0
+// [Solution] Changed algorithm to beter distinguish between Root
+// Bridges.
+// Added debug messagers to monitor HPC_LOCATION_DATA.
+// [Files] PciBus.c; PciHostBridge.c.
+//
+// 121 7/20/11 11:59a Yakovlevs
+// Added IO 3C0-3DF reservation when VGA attributes set.
+//
+// 120 7/06/11 11:52a Yakovlevs
+// Fixed build issue when PCI_EXPRESS_GEN2_SUPPORT token set to OFF.
+//
+// 119 6/28/11 5:33p Yakovlevs
+// [TAG] EIP63430; 61101
+// [Category] Improvement
+// [Description] 1. Replace use of PciIo->MemRead with MemCpy() for
+// Option ROMs.
+// 2.The secondary bus reset in the link retraining code causes downstream
+// PLX bridges to disappear.
+// [Files] PciBus.c
+//
+// 118 6/11/11 1:24p Yakovlevs
+// [TAG] EIP 61311
+// [Category] Improvement
+// [Description] PCI Express controllers may not be correctly
+// initialized, because of missing delays, while resetting the link.
+//
+// [Files] Added delay code and tokens PCI_T_RST and PCI_T_RST_RECOVERY
+// to fine tune delay.
+//
+// 117 6/11/11 1:05p Yakovlevs
+// [TAG] EIP 61310
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Unable to enter OpROM on Adaptec 1430 card. OpROM executes,
+// attached drives will boot but pressing Ctrl A to enter utility hangs
+// system
+// [RootCause] Card option ROM has 2 images The second one was a BOOT
+// AGENT which does not have MATCHING DID in PCIR Header.
+// [Solution] Considered DID==0 as a valid option meaning all devices.
+//
+//
+// [Files] PciBus.c
+//
+// 116 5/12/11 11:30a Yakovlevs
+// Fixed bug in PcieRetrainLink function it was not doing other attempts
+// to retrain link because of missing else statement.
+//
+// 115 5/05/11 12:27p Yakovlevs
+// Added LinkSpeed trace when link reset or retrain called.
+//
+// 114 5/04/11 6:18p Yakovlevs
+// [TAG] EIP53475; 54911
+// [Category] New Feature
+// [Description] PCI Express support issue fixed.
+// Reconnect -r issue fixed.
+// [Files] PCIBus.c
+//
+// 113 4/25/11 4:26p Yakovlevs
+// Revert back changes in DeviceAttributes() function it was done by
+// mistake.
+//
+// 112 4/21/11 6:04p Yakovlevs
+// [TAG] EIP54911
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Calling Stop function was causing ASSERT
+// [RootCause] Incorrect setting of the attributes and handling Stop
+// function for Device of Type tRootBridge.
+// [Solution] Change functions DeviceAttribute StopPciDevice.
+// [Files] PciBus.c
+//
+// 111 4/20/11 11:54a Yakovlevs
+//
+// 110 4/19/11 5:39p Yakovlevs
+// [TAG] EIP58702
+// [Category] New Feature
+// [Description] Aptio PI 1.2; UEFI 2.3.1 Support
+// Changes in Bus Drivers protocols (PCI bus driver)
+//
+// [Files] PciBus.c
+//
+// 109 4/19/11 11:02a Yakovlevs
+// [TAG] EIP 57664
+// [Category] New Feature
+// [Description] Aptio PI 1.2; UEFI 2.3.1 Support Extended PCI bus
+// driver functionality
+// Genericaly supported PCI_DEV_REVERSE_SCAN_ORDER.
+// [Files] DevicePath.h; LoadFile2.h; PciBus.h; PciBus.c.
+//
+// 108 4/05/11 11:36a Yakovlevs
+// [TAG] EIP 38174 EIP 53475;
+// [Category] New Feature
+// [Description] 38174 Generic support to handle PCI OUT OF RESOURDCES
+// added.
+// 53475 PCI Express 3.0 support added.
+//
+// [Files] PciBus.c; PciHostBridge.c;
+//
+// 107 2/02/11 3:42p Yakovlevs
+//
+// 106 1/28/11 4:26p Yakovlevs
+// [TAG] EIP48290
+// [Category] New Feature
+// [Description] Added PCI_AMI_COMBINE_MEM_PMEM32 token that tells to
+// map 32 bit sized PF MMIO BARs trough NON PF MMIO Bridge registers.
+//
+// [Files] PciBus.c; PciBus.sdl;
+//
+// 105 1/28/11 2:55p Yakovlevs
+// [TAG] EIP43879
+// [Category] New Feature
+// [Description] Added PciPortOemGetOptRom() OEM Hook to override
+// content of the PCI Device Option ROM.
+// [Files] PciBus.c; PciPort.c; PciPort.h; PciBus.mak; PciBus.sdl
+//
+// 104 1/20/11 3:07p Yakovlevs
+// [TAG] EIP45278
+// [Category] Improvement
+// [Description] Added PCI_MMIO_RES_TOP_ALLIGN token to control Resource
+// allocation algorithm selection.
+// [Files] PciBus.c; PciHostBridge.c; PciBus.sdl.
+//
+// 103 1/14/11 10:50a Yakovlevs
+// [TAG] EIPEIP49743
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Incorrect initialization complicated PCI infrastructure
+// [RootCause] wrong condition to breake {do while loop}.
+// [Solution] Change conditions
+// [Files] PciBus.c
+//
+// 102 1/13/11 2:59p Yakovlevs
+// [TAG] EIP49743
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] In the PcieCalcLatency(), the do-while loop condition have
+// issue in this.
+// [RootCause] It may be a condition when while loop in function
+// PcieCalcLatency(), will never break.
+// [Solution] Cahnge conditiondn iinstead of logical OR use AND.
+// [Files] PciBus.c
+//
+// 101 1/13/11 1:31p Yakovlevs
+// [TAG] EIP45278
+// [Category] Improvement
+// [Description] Changed default resource allocation algorithm to work
+// more efficiently.
+// [Files] PciBus.c; PciHostBridge.c.
+//
+// 100 1/13/11 1:21p Yakovlevs
+// [TAG] EIP49743
+// [Category] Improvement
+// [Description] Workaround for devices which having Link Retrain bit
+// "sticky"
+// [Files] PciBus.c
+//
+// 99 1/13/11 1:14p Yakovlevs
+// [TAG] EIP50097
+// [Category] Improvement
+// [Description] Fixed issue when with PCI_FIXED_BUS_ASSIGNMENT==1
+// system was ASSERTING.
+// Reason was that with complicated PCI structure next bridge XLAT entry
+// that used to determine Subordinate bus #, selected incorrectly.
+//
+// [Files] PciBus.c
+//
+// 98 12/09/10 2:53p Yakovlevs
+// Fixed bug in PcieCalcLatency() function. It was not calculating L1
+// latency correctly.
+//
+// 97 12/08/10 3:17p Yakovlevs
+// Removed Setup Option "Selectable DeEmphasis" since it is HwInit Bit.
+//
+// 96 11/18/10 3:50p Yakovlevs
+// 1.Changed Install Option ROM debug messages to make it more precise.
+// 2. Added call to DoubleCheckOpRom() to verify ROM size before
+// processing UEFI OpROM.
+//
+// 95 11/12/10 6:37p Yakovlevs
+// PcieDoubleCheckCard() routine added to support cards that slowly
+// respond on CFG transactions.
+//
+// 94 11/08/10 6:16p Felixp
+//
+// 93 11/08/10 6:13p Felixp
+// The Core source files are updated to remove upper ASCII characters
+// (above 128)
+// from the comment blocks. The characters caused build errors
+// with Japanese version of Microsoft compiler.
+//
+// 92 11/05/10 5:06p Yakovlevs
+// Changed if Default (AUTO) MaxReadRequest selected don't change value
+// sitting there.
+// Removed assert in PcieConvertLatency function.
+//
+// 90 10/07/10 12:13p Felixp
+// PEI_TRACE on TPL_HIGH is removed.
+// Headers updated.
+//
+// 89 10/05/10 4:46p Yakovlevs
+// Changed Default (AUTO) MaxReadRequest Size value from == MPL to spec.
+// default == 512.
+//
+// 88 10/01/10 6:05p Yakovlevs
+// Fixed issue with low level PciCfgXX() access functions. When
+// ExtendedRgister used.
+//
+// 87 9/01/10 11:52a Yakovlevs
+// Improved Override ASPM Porting hook, now it called for UPSTREAM as well
+// as DOWNSTREAM port.
+//
+// 86 8/16/10 1:05p Yakovlevs
+// New Incompatibility Type Sypport: icBad64BitBar - Device has a bar that
+// is 64bit capable, but the card does not function properly when it is
+// allocated.
+//
+// 85 7/08/10 6:00p Yakovlevs
+// Removed EFI_EADLOOP() left in InstallEfiRom() function
+//
+// 84 7/08/10 3:12p Yakovlevs
+// Fixed UEFI Option ROM Size miscalculation.
+//
+// 83 6/30/10 11:11a Yakovlevs
+// Fixed WDK Build Issue EIP 40554
+//
+// 82 6/08/10 3:31p Yakovlevs
+// Minor fix for EIP 38289 Klocwork Issues II.
+//
+// 81 6/07/10 3:36p Yakovlevs
+// Improved logic to select matching PCI Bus Xlat table entry.
+//
+// 80 5/25/10 3:16p Yakovlevs
+// Fixed condition to disable device using 64 bit resource threshold
+//
+// 79 5/19/10 12:43p Yakovlevs
+//
+// 78 5/07/10 12:24p Yakovlevs
+// Bug fix in PcieProgramPayloadUp() function. canged order when recording
+// calculated PayLoad.
+// It use to recursive call was made after reduced value of MPL was
+// recorded. It was preventing function to program MPL correctly.
+//
+// 77 4/28/10 11:33a Yakovlevs
+// Fixed bug in DoubleCheckOpRom() when OpROM is a Single Image ROM.
+//
+// 76 4/20/10 5:46p Yakovlevs
+// Fixed build error with SRIOV token ON; Fixed InitDevCahain() function
+// Logic.
+//
+// 75 4/15/10 4:28p Yakovlevs
+// Fixed issue with PCIe Switches and MPL programming UP
+//
+// 74 4/14/10 4:43p Yakovlevs
+// Fixed Possible issue with incorrect MPL Programming.
+//
+// 73 3/03/10 12:46p Yakovlevs
+// Fixed bug in IsFunc0() function.
+//
+// 72 3/01/10 6:18p Yakovlevs
+// PCI Express V2.1 support added.
+//
+// 68 12/24/09 10:45a Yakovlevs
+// Fixed issue when removing unused entries from IRQ routing tables, PIC
+// and APIC.
+//
+// 67 9/24/09 1:51p Yakovlevs
+// Fixed EIP 26787. If P2P Bridge has ExpROM BAR, value that has to go
+// there was programmed as Secondary Interface Forward Range.
+//
+// 66 9/22/09 6:09p Yakovlevs
+// 6. Fixed conditions in ApplyAcpiResources() where function assumes
+// validity of Resource Range. In case of Fixed Resource Allocation
+// Resource window allocated by custom unction might be bigger than actual
+// hardware resource request
+//
+// 65 9/08/09 12:57p Yakovlevs
+// Fixed ~0LU statement to 0ULL. This is correct statement for 64 bit
+// Value
+// Made QueryPciDevice() routine set Interrupt Line register(0x3C) to 0xFF
+//
+// 64 8/28/09 10:27a Felixp
+// Component Name protocol implementation is upadted to support both
+// ComponentName and ComponentName2 protocols
+// (based on value of the EFI_SPECIFICATION_VERSION SDL token).
+//
+// 63 8/21/09 3:53p Yakovlevs
+// Fixed: EIP 19106 If 1 Bus set to be paded in Setup, PCI Bus driver
+// still creates 1 BUS for this bridge instead of 2.
+//
+//
+// 62 7/07/09 12:39p Yakovlevs
+// Moved DisableBridgeDecoding() call before Disable device decoding since
+// it could decode 0-4K of IO and 0-1M of Mem.
+//
+// 61 5/22/09 2:16p Yakovlevs
+//
+// 60 5/05/09 5:46p Yakovlevs
+// Fixed build issue in IA32 mode with SRIOV_SUPPORT == ON.
+//
+// 59 4/24/09 11:49a Yakovlevs
+//
+// 58 4/23/09 8:28p Yakovlevs
+// Fixed some minor issues related to PCI IRQ entries usage and updating.
+//
+// 57 4/23/09 2:02p Yakovlevs
+// Fixed potentiial Memory Coruption issue when assigning Ext->XlatEntry
+// ->BusRun
+// for bridges who doesnot have it's XlatTbl Entry.
+//
+// 56 4/19/09 2:14p Yakovlevs
+// Fixed issue with Multiple Root Bridges, when PCI Bus Driver was
+// incorrectly calculating ranges buses to scan.
+//
+// 55 4/17/09 6:38p Yakovlevs
+// Fixed issue EIP 21366 with OptimizeBrgResource() function see EIP for
+// more details.
+//
+// 54 4/16/09 1:49p Yakovlevs
+// Fixed issue where for Second Root Bridge Bus numbers were assifned
+// started fron LAST ROOT_0_BUS + 1
+//
+// 53 4/01/09 9:57a Yakovlevs
+// Minor fixes
+//
+// 52 3/30/09 5:23p Yakovlevs
+// Fixed issue in AssignBridgeResources function when there are no bars to
+// program function was returning ERROR Status.
+//
+// 51 3/27/09 7:02p Yakovlevs
+// Fixed Uninitialized PCI DB issue.
+//
+// 50 3/27/09 11:47a Yakovlevs
+// Fixed some issues with re starting driver.
+//
+// 49 3/25/09 11:02a Yakovlevs
+// ADDED Generic implementation of #PERR, #SERR; and VGA Palette Snoop.
+//
+// 48 3/23/09 2:27p Yakovlevs
+// ADDED support for VGA_16_BIT_DECODE. VGA aliasing support pending.
+//
+// 47 2/04/09 4:03p Yakovlevs
+// Fixed PciPortSkipThisDevice() function was not preserving PCI.CMD
+// register.
+//
+// 46 2/04/09 4:01p Yakovlevs
+//
+// 45 2/03/09 3:27p Yakovlevs
+// Added fixes for EIP 19144. Break the PCI Express Extended Capability
+// header access routine if read of offset 0x100 returns 0xFFFF
+//
+// 44 1/30/09 1:03p Yakovlevs
+// Minor bug fixes and improuvements EIP 8874; EIP 17947
+//
+// 43 11/26/08 3:55p Yakovlevs
+//
+// 42 11/26/08 3:54p Yakovlevs
+// Start function NOW returns EFI_ALREADY_STARTED, when all PCI devices
+// installed PciIo interface.
+//
+// 41 11/26/08 11:37a Yakovlevs
+// Fixed connect -r issue when shell was hunging in infinite loop.
+//
+// 40 11/14/08 3:34p Yakovlevs
+// Removed EFI_DEADLOOP() used for debug
+//
+// 39 11/14/08 1:21p Yakovlevs
+// Introduced AMI Board Info Protocol which has *.inc OUTPUTS generated
+// by AMISDL tool. To keep it in one place and Make PciBus Driver use it.
+//
+// 38 10/31/08 6:10p Yakovlevs
+//
+// 36 10/15/08 10:45a Yakovlevs
+// Fixed EIP 16990 CsmVideo can't work
+//
+// 35 10/14/08 1:15p Yakovlevs
+// Rearrange Function order to support ROM BARs as PCI incompatible BARs
+//
+// 33 10/10/08 5:40p Yakovlevs
+// Added Pci Compliance tests workarounds
+//
+// 32 10/01/08 7:12p Yakovlevs
+// Updated AMI FUNC HEADER information
+//
+// 31 9/24/08 6:41p Yakovlevs
+// New features and bug fixes:
+// New features.
+// 1. Make PCI Bus Driver use VeB generated structures.
+// 2. Added SRIOV support
+// 3. Added Fixed Bus Allocation (Buses for the bridges will be allocated
+// same way as in Build time)
+// 4. Scan full bus ranges.
+// 5. Added support for UEFI 2.1 PCI requirements.
+// 6. Added Token to disable PCI Bus Driver Debug Messages.
+// 7. Removed dependency from SETUP_DATA fields layout.
+// 8. Progress/Error codes.
+// 9. Support for S3 Video Repost.
+//
+// Bug fixes:
+// 1. Attribute function.
+// 2. If device decodes only PFMMIO Bridge MMIO Base and Limit register
+// was initialized with 0 making it decode space from 0x10000.
+// 3. OptimizeBridgeResources() function was not working correctly in some
+// rare cases.
+//
+// 29 5/13/08 11:59a Felixp
+// ComponentName protocol converted to ComponentName2
+//
+// 28 4/29/08 6:55p Yakovlevs
+// Generic S3 Video Repost support added.
+// Added mechanism to suppress PCI BUs driver debug messages(Latest
+// PciBus.sdl and PciBus.h required).
+//
+// 27 4/24/08 12:19p Yakovlevs
+// Added generic support for S3 VIDEO Repost feature.
+//
+// 26 4/18/08 3:53p Yakovlevs
+// Added missing function headers
+//
+// 25 4/17/08 6:23p Yakovlevs
+// fixed potencial issue in OptimizeBridgeResources.
+//
+// 24 3/12/08 12:45p Felixp
+// Progress/Error codes reporting added
+//
+// 23 2/21/08 4:37p Felixp
+// 1. Bug fix in StartPciChildDevice. Handling of remaining device path
+// has changed.
+// 2. Handling of setup data structure in PciBusStart updated to work fine
+// without PCI sources
+//
+// 22 1/31/08 8:31p Yakovlevs
+// Fixed issue with hotplug resource padding.
+//
+// 21 1/31/08 2:51p Yakovlevs
+// 1. Fixed resource allocation issue on bridges only branches.
+// 2. Cahnged Default Padding routine for Card bus bridges.
+//
+// 20 12/10/07 4:15p Yakovlevs
+// 1.Fixed bug in OprimizeBrgResources() function, (it might hung in
+// infinite loop).
+// 2.Corrected ApplyCrdPadding () implementation to take care of
+// EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM allocation attribute.
+//
+// 19 11/08/07 4:51p Felixp
+// Code updated to compile and work without CSM.
+//
+// 18 10/23/07 5:28p Felixp
+// VC8 warnings fixed
+//
+// 17 10/18/07 11:22a Felixp
+// ASPN SDL tokens replaced with external constants defined in PciPort.c
+//
+// 16 10/15/07 4:11p Yakovlevs
+// Fixed bug in OptimizeResources function.
+//
+// 15 10/08/07 5:26p Yakovlevs
+// Fix to handle not compliant PCI Option Roms.
+//
+// 4 9/21/07 6:38p Yakovlevs
+// Sinchronize with recent PCI Bus updates
+//
+// 14 9/21/07 6:24p Yakovlevs
+// Fixed ASPM related bugs.
+//
+// 13 9/18/07 5:23p Yakovlevs
+// Inplemented Intel's recomendation of calculating EP Acceptable ASPM
+// Latency.
+//
+// 12 8/31/07 11:18a Yakovlevs
+// Improuvements in PCI Resource Allocation Algorithm.
+//
+// 10 7/25/07 12:54p Felixp
+// AMI Debugger-related code is updated to enable Debugger in non-debug
+// mode.
+// The code is enabled when USB_DEBUG_TRANSPORT or EFI_DEBUG is on.
+//
+// 9 7/17/07 6:29p Felixp
+// Minor bug fix in GetOptRom: GetEmbeddedRom was called with UINT32 image
+// size pointer instead of UINTN
+//
+// 8 7/04/07 5:51a Yakovlevs
+// Version of this file will work with 4.5.3_CSM.6.37_51 label of CSM,
+// which requires USB module upgrade to Label 4.05.03_USB_08.07.11.
+// 1. Fixed Disabling VGA attributes for Devices behind multiple bridges.
+// 2. Added some debug messages for Installing Devices PciIo interface.
+// 3. Changed GetOptRom() function to search for Embeded ROMs(onboard) as
+// well and populate PciIo.OptionRom*.
+//
+// 7 5/23/07 5:32p Yakovlevs
+// Previouse fix had some side effects on protocol installation side -
+// this one fixes these.
+// Also some debug messages at protocol installation phase was added.
+//
+// 6 5/18/07 6:30p Yakovlevs
+// Fixed Issue with incorrect Status returning from StartPciChildDevice().
+//
+// 5 5/14/07 7:49p Yakovlevs
+// Somehow changes to impruve PCI Config Acces were lost. Resored them.
+//
+// 4 5/04/07 3:50p Yakovlevs
+//
+// 3 5/04/07 11:51a Yakovlevs
+//
+// 2 5/02/07 4:41p Yakovlevs
+//
+// 1 3/12/07 12:02p Yakovlevs
+//
+// 48 12/28/06 7:16p Yakovlevs
+// In ActivateOptRom function removed upate of OptROM size where
+// PciIo->OptionRom points
+// It is not needed.
+//
+// 47 12/22/06 9:42p Yakovlevs
+// Code Cleanup and CHM headers added
+//
+// 46 12/21/06 5:13p Yakovlevs
+// Code cleanup. Added CHM headers.
+//
+// 44 12/19/06 11:54a Yakovlevs
+// Fixed Padding for the bridge if CombineMemPmem Allocation Attribute is
+// set
+//
+// 43 12/05/06 3:27p Yakovlevs
+// Fixed SCT 2.0 PciIo Disable Attributes ISSUE.
+//
+// 42 12/05/06 11:54a Felixp
+//
+// 41 11/22/06 10:27a Olegi
+//
+// 40 11/22/06 10:26a Olegi
+// InstallPciDevice is modified so that the device with DebugPort
+// enumeration will not be skipped.
+//
+// 39 10/20/06 5:50p Yakovlevs
+//
+// 38 10/13/06 4:42p Yakovlevs
+//
+// 37 10/13/06 4:10p Yakovlevs
+// Function Headers Added!!!!! IDE Attributes support added, Hotplug
+// support fix (NULL pointer).
+//
+// 36 9/11/06 11:51a Yakovlevs
+// Fixed CacheLineSize rergister programming issue
+//
+// 35 8/24/06 10:11a Felixp
+// x64 support: warning/error fixes
+//
+// 34 8/09/06 5:08p Yakovlevs
+// VC initialization and boot sript support for PCI Express.
+// This fixes NVIDIA 7800 GT issue
+//
+// 31 6/04/06 9:06p Yakovlevs
+// Fixed issue when PciBus driver was writting in IRQ Line Reg some junk.
+//
+// 30 6/04/06 8:22p Yakovlevs
+// Fixed PCI_EXPRESS_SUPPORT and HOTPLUG_SUPPORT featueses.
+// Added some debug messages during PCI bus enumeration process.
+//
+// 29 6/01/06 12:21p Yakovlevs
+// Changes to accomodate HbCspAdjustMemoryMmioOverlap function in PciRB.
+//
+// 28 5/19/06 10:45p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 27 4/25/06 4:49p Stacyh
+//
+// 26 4/03/06 3:52p Felixp
+// Major changes in PCI and Super I/O:
+// PCI - Root Bridge Resource Allocation Sepcification support
+// Super I/O - multiple Super I/O support; SIO Setup page added;
+//
+// 25 3/20/06 9:26a Felixp
+// Bug fix in attribute clearing logic.
+//
+// 24 3/13/06 10:07a Felixp
+//
+// 21 11/08/05 4:08a Felixp
+// AMI Debugger ifdefs changed from AMI_DEBUGGER_SUPPORT to EFI_DEBUG
+//
+// 20 10/27/05 5:39p Felixp
+//
+// 19 10/12/05 7:19p Felixp
+// AMI Debugger support added
+//
+// 18 7/18/05 3:25p Felixp
+//
+// 17 6/26/05 6:50p Olegi
+// Incompatible PCI device list updated.
+//
+// 16 6/26/05 6:43p Yakovlevs
+// Card Bus Support Added
+// Some other bug fixes
+// Incompatibility list extended with icBarFixedSize.
+//
+// 15 5/25/05 6:26p Yakovlevs
+//
+// 14 5/11/05 3:09p Yakovlevs
+// Fixed: CacheLine Size register Latency timer Reg, gets programmed,
+// IO resource lesser than 16 bytes padded to 16 bytes.
+//
+// 13 4/21/05 2:03p Sivagarn
+// - Option ROM signature is validated before copying into the memory
+// - Option ROM size is obtained from the header instead of using size
+// calculated from PCI base register
+//
+// 12 4/06/05 10:33a Felixp
+// Bug fix in StartPciDevices
+//
+// 11 3/29/05 5:16p Olegi
+// Problem with ATI Video fixed.
+//
+// 10 3/23/05 6:17p Yakovlevs
+//
+// 9 3/23/05 5:48p Yakovlevs
+// Changes to avoid clearing HostBridge Command register.
+//
+// 8 3/15/05 5:23p Yakovlevs
+// Option ROM issue for on bord device with implemented ROM BAR and ROM
+// image at ROM BIOS fixed.
+// Now if ActivateOptionRom routine fails to validate option rom it frees
+// OptROM buffer.
+//
+// 7 3/04/05 9:26a Mandal
+//
+// 6 2/14/05 7:36p Yakovlevs
+// Handled situation when Start Function calls multiple times for every
+// next DP node.
+// Fixed Option Rom Size issue
+//
+// 5 2/14/05 6:12p Yakovlevs
+//
+// 4 2/13/05 4:54p Yakovlevs
+// Fixed issue with 64 bit width BARs; PCI incompatible device support
+// added.
+//
+// 3 2/11/05 7:48p Yakovlevs
+// Incompatible Pci Device Support added.
+//
+// 2 2/01/05 1:16a Felixp
+//
+// 1 1/28/05 12:45p Felixp
+//
+// 8 1/21/05 7:00p Yakovlevs
+//
+// 7 1/21/05 5:19p Yakovlevs
+// Fixed some stuff from TODO list:
+// 1.Made ajustments to exchange information with RB Driver.
+// 2.Support of 64 bit resources on P2P Brg (EnableBrgPfmmDecoding)
+// routine,
+//
+// 4 1/13/05 8:26p Yakovlevs
+//
+// 3 1/11/05 5:25p Yakovlevs
+//
+// 1 12/22/04 6:19p Admin
+//
+// 1 12/22/04 6:18p Admin
+//
+// 55 12/21/04 4:20p Markw
+// Renamed hardware device path definition for consistency.
+//
+// 54 12/06/04 5:14p Yakovlevs
+//
+// 53 12/06/04 4:51p Robert
+// PciIoCheckConfig - the comparison for the buffer length should not
+// exceed 256 bytes. Therefore it should be > not >=
+//
+// 52 10/22/04 7:26p Yakovlevs
+//
+// 51 10/20/04 3:02p Yakovlevs
+//
+// 50 10/20/04 11:43a Yakovlevs
+// InstallMultipleProtocol and Close Protocol opened by Child Controller
+// added
+//
+// 49 10/20/04 9:28a Yakovlevs
+//
+// 48 10/04/04 1:44p Yakovlevs
+// Make use of AcpuRes.h resource Tamplete Definitions
+//
+// 47 9/24/04 9:31p Yakovlevs
+// Uncachable Attributes set for PCI Bus MMIO regions
+//
+// 46 9/22/04 6:51p Yakovlevs
+//
+// 45 9/16/04 10:24a Yakovlevs
+//
+// 44 9/15/04 6:01p Yakovlevs
+//
+// 43 9/15/04 9:42a Yakovlevs
+//
+// 42 9/09/04 3:06p Yakovlevs
+// Bug fixes:
+// 1. Handling of RemainingDevicePath in Start routine
+// 2. Option ROM handling
+// Path:
+// Temporary patch to make Cirrus Logic and some other Add-On cards work
+//
+// 41 9/03/04 11:58a Yakovlevs
+//
+// 40 8/27/04 6:36p Yakovlevs
+//
+// 39 8/26/04 7:47p Yakovlevs
+// SCT PCI Bus Support -> OK!
+//
+// 38 8/24/04 1:01p Yakovlevs
+//
+// 37 8/15/04 7:32p Yakovlevs
+//
+// 36 8/13/04 9:21a Yakovlevs
+//
+// 35 7/13/04 10:42a Felixp
+//
+// 34 5/27/04 10:30a Yakovlevs
+//
+// 33 5/06/04 8:20p Felixp
+//
+// 32 5/06/04 6:31p Felixp
+//
+// 31 5/06/04 10:25a Yakovlevs
+//
+// 30 5/05/04 8:14p Yakovlevs
+//
+// 28 5/03/04 8:13p Felixp
+//
+// 27 5/03/04 6:15p Yakovlevs
+//
+// 26 5/03/04 6:04p Yakovlevs
+//
+// 25 5/03/04 12:24p Yakovlevs
+//
+// 24 5/03/04 11:52a Yakovlevs
+// Changes to avoid hardcoded Array size and accomodate all resource types
+//
+// 23 4/23/04 5:43p Felixp
+//
+// 22 4/23/04 3:20p Felixp
+//
+// 21 4/23/04 2:36p Felixp
+//
+// 20 4/23/04 12:08p Felixp
+//
+// 19 4/22/04 12:27p Yakovlevs
+//
+// 18 4/21/04 8:33p Yakovlevs
+//
+// 17 4/21/04 12:49p Yakovlevs
+//
+// 16 4/20/04 9:19p Yakovlevs
+//
+// 15 4/20/04 11:51a Yakovlevs
+//
+// 14 4/19/04 11:56a Yakovlevs
+//
+// 13 4/18/04 4:05p Felixp
+//
+// 12 4/16/04 7:12p Felixp
+//
+// 11 4/12/04 4:59p Yakovlevs
+//
+// 10 4/12/04 4:12p Yakovlevs
+//
+// 9 4/09/04 6:40p Yakovlevs
+//
+// 8 4/02/04 6:28p Yakovlevs
+//
+// 7 4/02/04 6:23p Yakovlevs
+//
+// 6 4/02/04 6:05p Yakovlevs
+//
+// 5 3/28/04 2:11p Felixp
+// 1. PE Loader and some other commonly used code moved to the Library
+// 2. Warnings fixed (from now on warning will be treated as error)
+//
+// 4 3/26/04 1:50p Yakovlevs
+//
+// 3 3/26/04 1:19p Felixp
+//
+// 2 3/22/04 10:29a Yakovlevs
+//
+// 1 3/15/04 11:20a Felixp
+//
+// 1 3/12/04 6:47p Yakovlevs
+//
+// 3 2/04/04 6:50p Yakovlevs
+//
+// 2 2/04/04 4:22p Yakovlevs
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: <PciBus.c>
+//
+// Description: EFI PCI Bus Generic Driver.
+//
+// Tabsize: 4
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//---------------------------------------------------------------------------
+// Include Files
+//---------------------------------------------------------------------------
+#include <Efi.h>
+#include <Token.h>
+#include <Protocol\PciRootBridgeIo.h>
+#include <Protocol\DevicePath.h>
+#include <Protocol\DriverBinding.h>
+#include <Protocol\BusSpecificDriverOverride.h>
+#include <Protocol\Decompress.h>
+#include <Protocol\ComponentName2.h>
+#include <Protocol\PciHostBridgeResourceAllocation.h>
+#include <Protocol\PciHotplugInit.h>
+#include <Protocol\PciPlatform.h>
+#include <Protocol\IncompatiblePciDeviceSupport.h>
+#include <Protocol\BootScriptSave.h>
+#include <Dxe.h>
+#include <AmiDxeLib.h>
+#include <AMIHobs.h>
+#include <PciBus.h>
+#include <PciBusEx.h>
+#include <AcpiRes.h>
+#include <AmiLoadCsmPolicy.h>
+
+#if PCI_OUT_OF_RESOURCE_SETUP_SUPPORT
+#include <Setup.h>
+#endif
+#include "PciPort.h"
+
+#if CSM_SUPPORT
+#include <Protocol\LegacyBiosExt.h>
+#endif
+
+#if EFI_DEBUG || USB_DEBUG_TRANSPORT
+#include <AmiDebugPort.h>
+#endif
+
+#include "PciSetup.h"
+
+//==================================================================================
+//Function Prototypes for Driver Binding Protocol Interface
+//==================================================================================
+EFI_STATUS PciBusSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath);
+
+EFI_STATUS PciBusStart(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath );
+
+EFI_STATUS PciBusStop(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer);
+
+EFI_STATUS EnumerateAll(EFI_HANDLE Controller);
+
+EFI_STATUS StartPciDevices(IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath);
+
+//-------------------------------------------------------
+//Forward declarations for Extended PCI Bus Protocol
+EFI_STATUS PciExtIsPciExpresss(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCIE_DATA **PciExpData OPTIONAL
+);
+
+EFI_STATUS PciExtIsPciX(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCIX_DATA **PciXData OPTIONAL
+);
+
+EFI_STATUS PciExtIsPciBrg(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_BRG_EXT **BrgData OPTIONAL
+);
+
+
+EFI_STATUS PciExtIsCrdBrg(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_BRG_EXT **BrgData OPTIONAL
+);
+
+
+EFI_STATUS PciExtIsDevice(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL
+);
+
+
+EFI_STATUS PciExtClassCodes(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_DEV_CLASS *CassCodes
+);
+
+
+EFI_STATUS PciExtPicIrqRout (
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_IRQ_PIC_ROUTE **PicIrqTblEntry,
+ OUT EFI_PCI_CONFIGURATION_ADDRESS **ParentDevices,
+ OUT UINTN *EntryCount
+);
+
+EFI_STATUS PciExtApicIrqRout (
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_IRQ_APIC_ROUTE **ApicIrqTblEntry,
+ OUT EFI_PCI_CONFIGURATION_ADDRESS **ParentDevices,
+ OUT UINTN *EntryCount
+);
+
+EFI_STATUS ReadEfiRom(PCI_DEV_INFO *Dev, PCI_ROM_IMAGE_DATA *RomData, VOID **ImgBase, UINT32 *ImgSize);
+
+//==================================================================================
+//Some Protocole GUIDs needed here
+//==================================================================================
+static EFI_GUID gDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+static EFI_GUID gPciRootBridgeIoProtocolGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID;
+static EFI_GUID gDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+static EFI_GUID gPciIoProtocolGuid = EFI_PCI_IO_PROTOCOL_GUID;
+static EFI_GUID gBusSpecificDriverOverrideProtocolGuid = EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID;
+static EFI_GUID gEfiDecompressProtocolGuid = EFI_DECOMPRESS_PROTOCOL_GUID;
+static EFI_GUID gEfiPciHostBrgResAllocProtocolGuid = EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GUID;
+static EFI_GUID gEfiPciHotPlugInitProtocolGuid = EFI_PCI_HOT_PLUG_INIT_PROTOCOL_GUID;
+static EFI_GUID gEfiPciPlatformProtocolGuid = EFI_PCI_PLATFORM_PROTOCOL_GUID;
+static EFI_GUID gEfiIncompatiblePciDeviceProtocolGuid = EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL_GUID;
+static EFI_GUID gEfiBootScriptSaveGuid = EFI_BOOT_SCRIPT_SAVE_GUID;
+static EFI_GUID gAmiExtPciBusProtocolGuid = AMI_PCI_BUS_EXT_PROTOCOL_GUID;
+static EFI_GUID gAmiBoardInfoProtocolGuid = AMI_BOARD_INFO_PROTOCOL_GUID;
+
+#if CSM_SUPPORT
+static EFI_GUID gEfiLegacyBiosExtProtocolGuid = EFI_LEGACY_BIOS_EXT_PROTOCOL_GUID;
+#endif
+
+
+#if PCI_EXPRESS_SUPPORT
+static T_ITEM_LIST gPcieEpList = {0,0,NULL};
+#endif
+
+
+//=============================================================================
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gBadPciDevList
+//
+// Description: Incompatible PCI Devices List known so far.
+//
+// Notes:
+// See PCI_BAD_BAR for field names and usage details.
+// If BarType field == tBarMaxType then BarOffset field should be used.
+// For "BarType" field only tBarIo, tBarMem and tBarMaxType allowed!
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+PCI_BAD_BAR gBadPciDevList[]={
+//-----------------------------------------------------------------------------------------------------------------------
+//enum UINT16 UINT16 UINT16 UINT16 PCI_BAR_TYPE UINTN UINT64 UINT64
+//IncompType; VendorId; DeviceId; DevIdMask; Reserved; BarType; BarOffset; BarBase; BarLength;
+//-----------------------------------------------------------------------------------------------------------------------
+//Device Adaptec 9004
+{ icBarBad, 0x9004, 0xFFFF, 0x0000, 0x0000, tBarIo, 0x0000, 0, 0 },
+//Device Adaptec 9005
+{ icBarBad, 0x9005, 0xFFFF, 0x0000, 0x0000, tBarIo, 0x0000, 0, 0 },
+//Device QLogic 1007
+{ icBarBad, 0x1007, 0xFFFF, 0x0000, 0x0000, tBarIo, 0x0000, 0, 0 },
+//Device Agilent 103C
+{ icBarBad, 0x103C, 0xFFFF, 0x0000, 0x0000, tBarIo, 0x0000, 0, 0 },
+//Device Agilent 15BC
+{ icBarBad, 0x15BC, 0xFFFF, 0x0000, 0x0000, tBarIo, 0x0000, 0, 0 },
+//Device AMI Mega RAID 493
+{icBarFixedSize,0x1077, 0x1216, 0xFFFF, 0x0000, tBarMaxType,0x0014, 0, 0x400000 },
+//ICH8 smbus controller
+{icNotBar, 0x8086, 0x283E, 0xFFFF, 0x0000, tBarMaxType,0x0014, 0, 0 },
+//RTL8111E
+{ icNotBar, 0x10EC, 0x8168, 0xFFFF, 0x0000, tBarMaxType,0x0030, 0, 0 },
+//NVIDIA 7200 GS
+{icBad64BitBar, 0x10de, 0x01d3, 0xFFFF, 0x0000, tBarMaxType,0x0014, 0, 0 }
+};
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gBadPciDevCount
+//
+// Description: Number or records in gBadPciDevList table.
+// Notes: UINTN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+UINTN gBadPciDevCount=sizeof(gBadPciDevList)/sizeof(PCI_BAD_BAR);
+
+
+//==================================================================================
+// PCI Bus Driver Global Variables
+//==================================================================================
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gAllocationAttributes
+//
+// Description: Root Bridge Allocation Attributes
+// Notes: UINT64
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+UINT64 gAllocationAttributes=0;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gPciOutOfRes
+//
+// Description: Indicates Out Of Resources Condition.
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN gPciOutOfRes=FALSE;
+
+BOOLEAN gPciOutOfResHit=FALSE;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gLowResType
+//
+// Description: Indicates what type of resource has Out Of Resources Condition.
+// Notes: MRES_TYPE
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+MRES_TYPE gLowResType=rtMaxRes;
+
+AMI_OUT_OF_RES_VAR gPciOutOfResData={0};
+
+
+//----------------------------------------------------------------------------------
+//EfiDBE Key field definition used to sort resources by size
+//Function prototypes used for Compare keys we will use a custom way.
+//We will be using combination UINT64 Length (LS64) + UINT64 Granularity (MS64).
+INTN Cmp128IntRR(IN VOID *pContext, VOID *pRecord1, VOID *pRecord2);
+INTN Cmp128IntKR(IN DBE_OFFSET_KEY_CONTEXT *pContext, VOID *pKey, VOID *pRecord);
+//Initialize BAR DataBase KeyField Structure
+DBE_OFFSET_KEY_CONTEXT BarKeyInfo = { EFI_FIELD_OFFSET(PCI_BAR,Length),
+ EFI_FIELD_SIZE(PCI_BAR,Length)+EFI_FIELD_SIZE(PCI_BAR,Gran)};
+DBE_KEY_FIELD gBarKey = {&Cmp128IntRR, &Cmp128IntKR, &BarKeyInfo};
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gPciBusDb
+//
+// Description: Bus order Data Base if fixed bus allocation selected we need
+// to know how many buses does this bridge suppose to decode
+// Notes: T_ITEM_LIST
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+T_ITEM_LIST gPciBusDb={0,0,NULL};
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: *gPciSetupData
+//
+// Description: Global Setup Variable to get the setup settings pointer.
+//
+// Notes: PCI_SETUP_DATA
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+PCI_SETUP_DATA *gPciSetupData=NULL;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: mMaxBusFound; mMaxBusScan; mMaxBusReport.
+//
+// Description: Global counter of buses found.
+//
+// Notes: UINT8
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+UINT8 mMaxBusFound;
+UINTN mMaxBusScan;
+UINT8 mMaxBusReport=0;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gHostCnt
+//
+// Description: Initial Global Variable to store Host Bridge Count.
+//
+// Notes: UINTN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+UINTN gHostCnt;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gPciHost
+//
+// Description: Initial Global Variable to store pointer on PCI Subsystem
+// Host (This is very ROOT of the PCI Bus Driver Data).
+//
+// Notes: PCI_HOST_INFO
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+PCI_HOST_INFO *gPciHost=NULL;
+
+//----------------------------------------------------------------------------------
+//Bot script save protocol interface
+EFI_BOOT_SCRIPT_SAVE_PROTOCOL *gBootScriptSave=NULL;
+
+//----------------------------------------------------------------------------------
+#if CSM_SUPPORT
+EFI_LEGACY_BIOS_EXT_PROTOCOL *gLegacyBiosExt=NULL;
+#endif
+
+//----------------------------------------------------------------------------------
+#if S3_VIDEO_REPOST_SUPPORT == 1
+EFI_EVENT gVgaS3Event=NULL;
+#endif
+
+//----------------------------------------------------------------------------------
+//Initial Global Variable to store RootBridge info
+UINT16 gCpuCaheLineSize=0x10;
+UINT8 gPciCaheLineSize=0;
+
+//----------------------------------------------------------------------------------
+//To Avoid Enumerating AmiDebug Port Usb Device
+#if EFI_DEBUG || USB_DEBUG_TRANSPORT
+AMI_DEBUGPORT_INFORMATION_HOB *gDbgPortHob=NULL;
+DEBUG_PORT_INFO gDbgPortInfo={0,0,0,0,0,0,0,0};
+#endif
+
+//==================================================================================
+//Externals produced by VeB used by Pci Bus Driver
+//==================================================================================
+//Legacy IRQ routing table delivered from oempir.inc and PCIBoard.ASM
+//IOAPIC IRQ routing table delivered from mppciirq.inc and PCIBoard.ASM
+//PCI Buses Xlate Table
+//Instead we have now AMI_BOARD_INFO_PROTOCOL
+AMI_BOARD_INFO_PROTOCOL *gAmiBoardInfo=NULL;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gPciBusDriverBinding
+//
+// Description: Extended PCI Bus Protocol instance for PciBus Driver
+//
+// Notes: AMI_PCI_EXT_PROTOCOL
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+AMI_PCI_EXT_PROTOCOL gAmiExtPciBusProtocol = {
+ PciExtIsPciExpresss,
+ PciExtIsPciX,
+ PciExtIsPciBrg,
+ PciExtIsCrdBrg,
+ PciExtIsDevice,
+ PciExtClassCodes,
+ PciExtPicIrqRout,
+ PciExtApicIrqRout,
+ NULL
+};
+
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gPciBusDriverBinding
+//
+// Description: Driver binding protocol instance for PciBus Driver
+//
+// Notes: EFI_DRIVER_BINDING_PROTOCOL
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding = {
+ PciBusSupported, //Supported
+ PciBusStart, //PciBusDrvStart,
+ PciBusStop, //PciBusDrvStop,
+ ((PCI_BUS_MAJOR_VER<<16)|(PCI_BUS_MINOR_VER<<8)|(PCI_BUS_REVISION)), //Version
+ NULL, //Image Handle
+ NULL //DriverBindingHandle
+};
+
+#ifdef EFI_DEBUG
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+#ifndef LANGUAGE_CODE_ENGLISH
+#define LANGUAGE_CODE_ENGLISH "eng"
+#endif
+static BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2
+){
+ return LangCode1[0]==LangCode2[0]
+ && LangCode1[1]==LangCode2[1]
+ && LangCode1[2]==LangCode2[2];
+}
+static EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+#endif
+//---------------------------------------------------------------------------
+//Driver Name Interface of the PCI Bus Driver
+//---------------------------------------------------------------------------
+static UINT16 *gDriverName=L"AMI PCI Bus Driver";
+
+
+//---------------------------------------------------------------------------
+// Function Definitions
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ComponentNameGetControllerName()
+//
+// Description: This function is the one of interface functions of the
+// OPTIONAL, EFI_COMPONENT_NAME_PROTOCOL. Suppose to retun Controller
+// Name String. Currently returning EFI_UNSUPPORTED.
+//
+// Input:
+// EFI_COMPONENT_NAME_PROTOCOL
+// *This Pointer to EFI_COMPONENT_NAME_PROTOCOL.
+// EFI_HANDLE ControllerHandle EFI_HANDLE of the device which to return.
+// EFI_HANDLE ChildHandle OPTIONAL, an EFI_HANDLE of child device.
+// CHAR8 *Language Pointer to 3 char Language name.
+// CHAR16 **ControllerName Pointer to the data buffer for Name Sring.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_UNSUPPORTED When feature not supported by the Driver.
+//
+// Reference: EFI_COMPONENT_NAME2_PROTOCOL
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName )
+{
+ return EFI_UNSUPPORTED;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ComponentNameGetDriverName()
+//
+// Description: This function is the one of interface functions of the OPTIONAL
+// EFI_COMPONENT_NAME_PROTOCOL. Retuning Driver Name String of the PCI BUS Driver.
+//
+// Input:
+// EFI_COMPONENT_NAME_PROTOCOL
+// *This Pointer to EFI_COMPONENT_NAME_PROTOCOL.
+// CHAR8 *Language Pointer to 3 char Language name.
+// CHAR16 **ControllerName Pointer to the data buffer for Name Sring.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_UNSUPPORTED When feature not supported by the Driver.
+//
+// Reference: EFI_COMPONENT_NAME_PROTOCOL
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS ComponentNameGetDriverName(IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName)
+{
+ //Supports only English
+ if(!Language || !DriverName) return EFI_INVALID_PARAMETER;
+
+ if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH))
+ return EFI_UNSUPPORTED;
+ else
+ *DriverName=gDriverName;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gComponentName
+//
+// Description: Declaration of the EFI_COMPONENT_NAME_PROTOCOL
+//
+// Fields: Name Type Description
+// ------------------------------------------------------------------
+// ComponentNameGetDriverName, F_PTR DriverName function pointer.
+// ComponentNameGetControllerName, F_PTR ControllerName function pointer.
+// "eng" CHAR8 Language list Buffer.
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+static EFI_COMPONENT_NAME2_PROTOCOL gComponentName = {
+ ComponentNameGetDriverName,
+ ComponentNameGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+
+#endif
+
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//PCI BUS Driver Entry Point
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciBusEntryPoint()
+//
+// Description: This function is the entry point for PCI BUS Driver.
+// Since PCI BUS Driver follows EFI 1.1 driver model in it's entry point
+// it will initialize some global data and install
+// EFI_DRIVER_BINDING_PROTOCOL.
+//
+// Input:
+// EFI_HANDLE ImageHandle Image handle.
+// EFI_SYSTEM_TABLE *SystemTable Pointer to the EFI system table.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When something required is not found!
+// EFI_DEVICE_ERROR When the device is not responding!
+//
+// Notes:
+// Entry Points are used to locate or install protocol interfaces and
+// notification events.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciBusEntryPoint(IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable )
+{
+ static EFI_GUID CpuInfoHobGuid = AMI_CPUINFO_HOB_GUID;
+#if EFI_DEBUG || USB_DEBUG_TRANSPORT
+ static EFI_GUID DbgPortHobGuid = AMI_DEBUGPORT_HOB_GUID;
+#endif
+ static EFI_GUID HobListGuid = HOB_LIST_GUID;
+ CPUINFO_HOB *CpuInfoHob;
+ EFI_STATUS Status;
+//--------------------------------------------------------------------
+
+ //Init some Global Data
+ InitAmiLib(ImageHandle,SystemTable);
+ gPciBusDriverBinding.DriverBindingHandle=NULL;
+ gPciBusDriverBinding.ImageHandle=ImageHandle;
+
+ //Get CPU Cache Line Size
+ CpuInfoHob=(CPUINFO_HOB*)GetEfiConfigurationTable(pST,&HobListGuid);
+ if(CpuInfoHob==NULL) Status=EFI_UNSUPPORTED;
+ else Status=FindNextHobByGuid(&CpuInfoHobGuid,(VOID**)&CpuInfoHob);
+
+ if(!EFI_ERROR(Status)){
+ gCpuCaheLineSize=CpuInfoHob->CacheLineSize; //in bytes
+ gPciCaheLineSize=(UINT8)gCpuCaheLineSize/4; //in DWORDs
+ PCI_TRACE((TRACE_PCI,"PciBus: Find CpuInfo HOB! gCpuCaheLineSize=%X; gPciCaheLineSize=%X;\n", gCpuCaheLineSize, gPciCaheLineSize));
+ } else {
+ PCI_TRACE((TRACE_PCI,"PciBus: Unable to find CpuInfo HOB! Setting default CacheLineSize -> %X\n", gCpuCaheLineSize));
+ }
+
+#if EFI_DEBUG || USB_DEBUG_TRANSPORT
+//Get Ami Debug Port Settings
+ gDbgPortHob=(AMI_DEBUGPORT_INFORMATION_HOB*)GetEfiConfigurationTable(pST,&HobListGuid);
+ if(gDbgPortHob) Status=FindNextHobByGuid(&DbgPortHobGuid,(VOID**)&gDbgPortHob);
+ if(EFI_ERROR(Status)) gDbgPortHob=NULL;
+ else {
+ Status=gDbgPortHob->GetDebugPortProperties(gDbgPortHob, &gDbgPortInfo);
+ ASSERT_EFI_ERROR(Status);
+ }
+#endif
+
+ //Install Multiple Prot Drv. Binding and Comp. Name
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &gPciBusDriverBinding.DriverBindingHandle,
+ &gDriverBindingProtocolGuid,&gPciBusDriverBinding,
+#ifdef EFI_DEBUG
+ &gEfiComponentName2ProtocolGuid,&gComponentName,
+#endif
+ NULL);
+ //Here we can set up notification events if needed
+
+
+ //------------------------------------
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsFunc0OfMfDev()
+//
+// Description: Checks if PCI_DEV_INFO data passed belongs to Function 0 of
+// Multy-Functional device.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: BOOLEAN
+// TRUE Device is Function 0 of Mulifunctional device.
+// FALSE Device is not Function 0 of Mulifunctional device.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsFunc0OfMfDev(PCI_DEV_INFO *Device ){
+ //If (Func0==NULL && FuncCount==0) function is a single function device, following fields are not used and reserved;
+ //If (Func0!=NULL && FuncCount==0) function is one of the Func1..Func7 of multyfunc device Func0 points on DevFunc0;
+ //If (Func0!=NULL && (FuncCount!=0 || FuncInitCnt!=0)) function is Func0 of multyfunc device DevFunc holds pointers at all other Func1..7 found
+ //If (Func0==NULL && FuncCount!=0) Illehgal combination - reserved!
+ if((Device->Func0!=NULL) && ((Device->FuncInitCnt!=0)||(Device->FuncCount!=0))) return TRUE;
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsFunc0()
+//
+// Description: Checks if PCI_DEV_INFO is Function 0 of PCI device.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: BOOLEAN
+// TRUE Device is Function 0 of Mulifunctional device.
+// FALSE Device is not Function 0 of Mulifunctional device.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsFunc0(PCI_DEV_INFO *Device ){
+ //If (Func0==NULL && FuncCount==0) function is a single function device, following fields are not used and reserved;
+ //If (Func0!=NULL && FuncCount==0) function is one of the Func1..Func7 of multyfunc device Func0 points on DevFunc0;
+ //If (Func0!=NULL && (FuncCount!=0 || FuncInitCnt!=0)) function is Func0 of multyfunc device DevFunc holds pointers at all other Func1..7 found
+ //If (Func0==NULL && FuncCount!=0) Illehgal combination - reserved!
+ if(IsFunc0OfMfDev(Device)) return TRUE;
+ if((Device->Func0==NULL) && (Device->FuncInitCnt==0) && (Device->FuncCount==0)) return TRUE;
+ return FALSE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CpyItemLst()
+//
+// Description: Creates a copy of T_ITEM_LST structure.
+//
+// Input:
+// T_ITEM_LIST *Lst Pointer to the structure to copy.
+// T_ITEM_LIST **NewLstPtr Double Pointer to the copied data (Memory allocation is done by this function).
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CpyItemLst(T_ITEM_LIST *Lst, T_ITEM_LIST **NewLstPtr)
+{
+ T_ITEM_LIST *NewLst;
+//--------------------------
+ if(*NewLstPtr == NULL) *NewLstPtr = MallocZ(sizeof(T_ITEM_LIST));
+
+ if (*NewLstPtr==NULL) return EFI_OUT_OF_RESOURCES;
+
+ NewLst = *NewLstPtr;
+ NewLst->InitialCount = Lst->InitialCount;
+ if (Lst->InitialCount == 0) return EFI_SUCCESS;
+
+ NewLst->Items = MallocZ( Lst->InitialCount * sizeof(VOID*) );
+ if (!NewLst->Items) return EFI_OUT_OF_RESOURCES;
+
+ pBS->CopyMem((VOID*)NewLst->Items,(VOID*)Lst->Items,sizeof(VOID*)*Lst->ItemCount);
+
+ NewLst->ItemCount = Lst->ItemCount;
+
+ return EFI_SUCCESS;
+}
+
+
+#if HOTPLUG_SUPPORT
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//Following function to initialize PCI Root Hotplug Controller
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckRootHotplug()
+//
+// Description: This function will update pointer to PCI_RHPC_INFO of
+// Bridge Type device which creates a hot plug bus. Also if "Device"
+// creates the 'home bus' for Root HPC it will initialize Root HPC and
+// record the HPC state;
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CheckRootHotplug(PCI_DEV_INFO *Device){
+ EFI_STATUS Status=EFI_SUCCESS;
+ EFI_DEVICE_PATH_PROTOCOL *dp=NULL;
+ PCI_HPC_INFO *rhpc;
+ UINTN i;
+//---------------
+ if(Device->Type==tPci2PciBrg || Device->Type==tPci2CrdBrg || Device->Type==tPciRootBrg){
+ //we have identify and Init all the Root Hpc and HPB
+ if(Device->HostData->InitRhpcCount==Device->HostData->RhpcCount) return EFI_SUCCESS;
+ PROGRESS_CODE(DXE_PCI_BUS_HPC_INIT);
+ //here we must check if 2 things:
+ // 1.If "Device" Device Path mutches with one of Root Hpc Device pathes
+ // 2.If "Device" Device Path mutches with one of Root Hpb Device pathes
+ for(i=0; i<Device->HostData->RhpcCount; i++){
+ rhpc=Device->HostData->RhpcList[i];
+ //if this controller already has been initialized - keep going
+ if(rhpc->Initialized && rhpc->BusFound) continue;
+
+
+ //check if it is a secondary interface of the bridge where RHPC is sitting
+ if(!rhpc->BusFound){
+ if(!DPCmp(Device->DevicePath, rhpc->HpcLocation->HpbDevicePath)){
+ rhpc->HpbBridge=Device;
+ rhpc->BusFound=TRUE;
+ Device->HotPlug=rhpc;
+ PCI_TRACE((TRACE_PCI,"PciBus: Found HP Bus Bridge @ B%X|D%X|F%X \n\n", Device->Address.Addr.Bus,Device->Address.Addr.Device, Device->Address.Addr.Function));
+ }
+ }
+
+ if(!rhpc->Initialized){
+ //We will cut the last node of the HPC device path
+ //resulting Device Path will correspond to the ParentBridge.DevicePath of the HPC
+ dp=DPCut(rhpc->HpcLocation->HpcDevicePath);
+ //if the HPC sits behind this bridge get the secondary I/F bus number
+ if(!DPCmp(Device->DevicePath,dp)){
+ EFI_DEVICE_PATH_PROTOCOL *tdp;
+ //-----------------------------------
+ rhpc->HpcPciAddr.Addr.Bus=mMaxBusFound;
+ tdp=DPGetLastNode(rhpc->HpcLocation->HpcDevicePath);
+
+ rhpc->HpcPciAddr.Addr.Device=((PCI_DEVICE_PATH*)tdp)->Device;
+ rhpc->HpcPciAddr.Addr.Function=((PCI_DEVICE_PATH*)tdp)->Function;
+
+ //we will not set up an event to signal when HPC initialization is ready
+ //that will give us a possibility to enumerate PCI BUS in one pass
+ Status=Device->HostData->HpInitProt->InitializeRootHpc(
+ Device->HostData->HpInitProt, rhpc->HpcLocation->HpcDevicePath,
+ rhpc->HpcPciAddr.ADDR, NULL, &rhpc->HpcState);
+
+ ASSERT_EFI_ERROR(Status);
+ rhpc->Owner=Device;
+ rhpc->Initialized=TRUE;
+ PCI_TRACE((TRACE_PCI,"PciBus: Found RHPC @ B%X|D%X|F%X \n", Device->Address.Addr.Bus,Device->Address.Addr.Device, Device->Address.Addr.Function));
+ }
+ }
+
+ //if we come here we did some step of the initialization process
+ //let's check if this controller has been completly initialized.
+ //if so we did our job. there are no reasons to stay in this loop any longer
+ if(rhpc->Initialized && rhpc->BusFound) {
+ Device->HostData->InitRhpcCount++;
+ break;
+ }
+
+ }//for
+ }
+ if(dp)pBS->FreePool(dp);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsHpb()
+//
+// Description: This function will check if "Device" passed is the Bridge
+// Type Device with hotplug support.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: BOOLEAN
+// TRUE If "Device" is a Bridge with HPC on it.
+// FALSE Otherwice.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsHpb(PCI_DEV_INFO *Device){
+
+ //check if it is the right type of device to have Hotplug capabilities
+ if(!((Device->Type==tPci2PciBrg)||(Device->Type==tPci2CrdBrg)||(Device->Type==tPciRootBrg))) return FALSE;
+
+ //Check if it has Root Hpc or PciExpress capabilities
+ if(!Device->HotPlug && !Device->PciExpress) return FALSE;
+
+ //If Device is PciExpress, check if SLOT CAPABILITIES Register supports Hotplug
+ if(Device->PciExpress && (!Device->PciExpress->SlotCap.HpCapable))return FALSE;
+
+ return TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetHpbResPadding()
+//
+// Description: This function will get and apply resource padding
+// requirements for the PCI to PCI Bridge or Card Bus Bridge, if this
+// Bridge is supports hot plug.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetHpbResPadding(PCI_DEV_INFO *Device){
+ EFI_STATUS Status=0;
+//-----------------------------
+ if(IsHpb(Device)){
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(Device+1);
+ ASLR_QWORD_ASD *cnf, *res;
+ PCI_BAR *bar;
+ //----------------------------
+ Status=Device->HostData->HpInitProt->GetResourcePadding(Device->HostData->HpInitProt,
+ Device->HotPlug->HpcLocation->HpcDevicePath, Device->HotPlug->HpcPciAddr.ADDR,
+ &Device->HotPlug->HpcState,&cnf,&ext->PaddAttr);
+
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ if(ext->PaddAttr==EfiPaddingPciRootBridge){
+ pBS->FreePool(cnf);
+ return Status;
+ }
+
+ //Check if we got a valid descriptors in cfg buffer
+ if(!ValidateDescriptorBlock(cnf, tResAll, FALSE))return EFI_INVALID_PARAMETER;
+
+ res=cnf;
+ while(res->Hdr.HDR!=ASLV_END_TAG_HDR) {
+ bar=NULL;
+ switch(res->Type){
+ case ASLRV_SPC_TYPE_BUS :
+ bar=&ext->Pad[rtBus];
+ break;
+ case ASLRV_SPC_TYPE_IO :
+ bar=&ext->Pad[rtIo16];
+ bar->Type=tBarIo16;
+ if(res->_GRA==32){
+ bar=&ext->Pad[rtIo32];
+ bar->Type=tBarIo32;
+ }
+ break;
+ case ASLRV_SPC_TYPE_MEM :
+ if(res->_GRA==32){
+ if(res->TFlags.MEM_FLAGS._MEM==ASLRV_MEM_CEPF) {
+ bar=&ext->Pad[rtMmio32p];
+ bar->Type=tBarMmio32pf;
+ } else {
+ bar=&ext->Pad[rtMmio32];
+ bar->Type=tBarMmio32;
+ }
+ } else {
+ if(res->_GRA==64){
+ if(res->TFlags.MEM_FLAGS._MEM==ASLRV_MEM_CEPF){
+ bar=&ext->Pad[rtMmio64p];
+ bar->Type=tBarMmio64pf;
+ } else {
+ bar=&ext->Pad[rtMmio64];
+ bar->Type=tBarMmio64;
+ }
+ } else return EFI_INVALID_PARAMETER; //no other options alloud
+ }
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ } //switch
+
+ bar->Length=res->_LEN;
+ bar->Gran=res->_MAX;
+ res++;
+ } //while
+ pBS->FreePool(cnf);
+ }
+ return Status;
+}
+
+//==============================================================================
+#endif
+
+//==============================================================================
+// Device Handle Helper Functions
+//==============================================================================
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MakePciDevicePath()
+//
+// Description: This function will take Parent DevPath and extand it with
+// Current ""Dev", Device Path and update pointer of the "Dev->DevPath"
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS MakePciDevicePath(PCI_DEV_INFO *Dev)
+{
+ static PCI_DEVICE_PATH pcidp;
+//-------------------------------------------
+ //we have a wonderful Lib function DPAddNode - use it!
+ pcidp.Header.SubType=HW_PCI_DP;
+ pcidp.Header.Type=HARDWARE_DEVICE_PATH;
+ SET_NODE_LENGTH(&pcidp.Header,HW_PCI_DEVICE_PATH_LENGTH);
+
+ pcidp.Function=Dev->Address.Addr.Function;
+ pcidp.Device=Dev->Address.Addr.Device;
+
+ Dev->DevicePath=DPAddNode(Dev->ParentBrg->DevicePath, &pcidp.Header);
+ if(Dev->DevicePath)return EFI_SUCCESS;
+ else return EFI_OUT_OF_RESOURCES;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindRbHandle()
+//
+// Description: This function will finds Root Bridge Device Handle for
+// the "Device".
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_HANDLE
+// !=NULL When everything is going on fine!
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_HANDLE FindRbHandle(PCI_DEV_INFO *Device){
+ EFI_HANDLE rbh=NULL;
+ PCI_DEV_INFO *dev=Device;
+//---------------------
+ while(dev->Type!=tPciRootBrg)dev=dev->ParentBrg;
+ rbh=dev->Handle;
+ return rbh;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindPciDeviceByHandleBrg()
+//
+// Description: This function Searches PCI Bridge Subsystem Database to find
+// device which have passed "Handle"
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer to PCI Bridge Device Private Data structure.
+// EFI_HANDLE Handle Device Handle to search for.
+//
+// Output: PCI_DEV_INFO
+// !=NULL When everything is going on fine!
+// ==NULL Not Found.
+//
+// Notes: This is a subordinate function of FindPciDeviceByHandle()
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+PCI_DEV_INFO *FindPciDeviceByHandleBrg(PCI_BRG_INFO *Brg, EFI_HANDLE Handle)
+{
+ PCI_DEV_INFO *dev, *res=NULL;
+ INTN i;
+//--------------------------------------------------------------------
+ if(Brg->Common.Handle==Handle) return &Brg->Common;
+
+ for(i=0; i<(INTN)Brg->Bridge.ChildCount; i++){
+ dev=Brg->Bridge.ChildList[i];
+ res=NULL;
+ if(dev->Handle==Handle) {
+ res=dev;
+ break;
+ }
+
+ if(dev->Type==tPci2PciBrg) res=FindPciDeviceByHandleBrg((PCI_BRG_INFO*)dev,Handle);
+
+ if(res) break;
+ }
+ return res;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindPciDeviceByHandle()
+//
+// Description: This function finds Pci Device by "Handle" passed
+//
+// Input:
+// EFI_HANDLE Handle PCI Device Handle.
+//
+// Output: PCI_DEV_INFO
+// !=NULL When everything is going on fine!
+// ==NULL Not Found.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+PCI_DEV_INFO *FindPciDeviceByHandle(EFI_HANDLE Handle)
+{
+ PCI_BRG_INFO *brg;
+ UINTN i,j;
+ PCI_HOST_INFO *lhst;
+ PCI_DEV_INFO *res;
+//--------------------------------------------------------------------
+ for(j=0; j<gHostCnt; j++){
+ lhst=&gPciHost[j];
+ for(i=0; i<lhst->RbCount; i++){
+ brg=(PCI_BRG_INFO*)lhst->RootBridges[i];
+ res=FindPciDeviceByHandleBrg(brg, Handle);
+ if(res) return res;
+ }
+ }
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DoPrepController()
+//
+// Description: This function will follow the rules of calling seqence of
+// Platform Preprocess Controller it will call:
+// 1.Platform PreprocessController with ChipsetEntery
+// 2.Host Brg Preprocess Controller
+// 3.Platform PreprocessController with ChipsetExit
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DoPrepController(PCI_DEV_INFO* Device)
+{
+ EFI_STATUS Status=0;
+ EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE ph;
+ EFI_HANDLE rbh=FindRbHandle(Device);
+//-----------
+ if(Device->Type==tPci2PciBrg) ph=EfiPciBeforeChildBusEnumeration;
+ else ph=EfiPciBeforeResourceCollection;
+
+ //If System has PciPlatform protocol installed
+ if(Device->HostData->PlatformProt){
+ Status=Device->HostData->PlatformProt->PlatformPrepController(
+ Device->HostData->PlatformProt, Device->HostData->HostHandle,
+ rbh,Device->Address.Addr, ph, ChipsetEntry);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ Status=Device->HostData->ResAllocProt->PreprocessController(
+ Device->HostData->ResAllocProt,rbh,Device->Address.Addr, ph);
+ ASSERT_EFI_ERROR(Status);
+
+ if(Device->HostData->PlatformProt){
+ Status=Device->HostData->PlatformProt->PlatformPrepController(
+ Device->HostData->PlatformProt, Device->HostData->HostHandle,
+ rbh, Device->Address.Addr, ph, ChipsetExit);
+ ASSERT_EFI_ERROR(Status);
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DoPciNotify()
+//
+// Description: This function will follow the rules of calling seqence of
+// Platform Notify it will call:
+// 1.Platform NotifyPhase with ChipsetEntery
+// 2.Host Brg NotifyPhase
+// 3.Platform NotifyPhase with ChipsetExit
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DoPciNotify(PCI_HOST_INFO *Host, EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase)
+{
+ EFI_STATUS Status=0;
+//-----------
+ if(Host->PlatformProt){
+ Status=Host->PlatformProt->PhaseNotify(Host->PlatformProt,Host->HostHandle,Phase,ChipsetEntry);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ Status=Host->ResAllocProt->NotifyPhase(Host->ResAllocProt,Phase);
+ ASSERT_EFI_ERROR(Status);
+
+ if(Host->PlatformProt){
+ Status=Host->PlatformProt->PhaseNotify(Host->PlatformProt,Host->HostHandle,Phase,ChipsetExit);
+ ASSERT_EFI_ERROR(Status);
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciCfg8()
+//
+// Description: Will do PCI Configuration Space Access 8 bit width
+//
+// Input:
+// ROOT_BRIDGE_IO_PROTOCOL *RbIo Pointer to PciRootBridgeIO Protocol.
+// PCI_CFG_ADDR addr PCI_CFG_ADDR filled by caller
+// BOOLEAN wr TRUE = Write FALSE = Read
+// UINT8 *buff Pointer Data Buffer.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// Referals:PCI_CFG_ADDR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciCfg8(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RbIo, PCI_CFG_ADDR addr, BOOLEAN wr, UINT8 *buff){
+ if(wr)return RbIo->Pci.Write(RbIo, EfiPciWidthUint8, addr.ADDR, 1, (VOID*)buff);
+ else return RbIo->Pci.Read(RbIo, EfiPciWidthUint8, addr.ADDR, 1, (VOID*)buff);
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciCfg16()
+//
+// Description: Will do PCI Configuration Space Access 16 bit width
+//
+// Input:
+// ROOT_BRIDGE_IO_PROTOCOL *RbIo Pointer to PciRootBridgeIO Protocol.
+// PCI_CFG_ADDR addr PCI_CFG_ADDR filled by caller
+// BOOLEAN wr TRUE = Write FALSE = Read
+// UINT16 *buff Pointer Data Buffer.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// Referals:PCI_CFG_ADDR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciCfg16(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RbIo, PCI_CFG_ADDR addr, BOOLEAN wr, UINT16 *buff){
+ EFI_STATUS Status;
+//------------
+ if(wr)Status=RbIo->Pci.Write(RbIo, EfiPciWidthUint16, addr.ADDR, 1, (VOID*)buff);
+ else Status=RbIo->Pci.Read(RbIo, EfiPciWidthUint16, addr.ADDR, 1, (VOID*)buff);
+ //it might be a Width issue on Pci Root bridge level
+ if(Status==EFI_INVALID_PARAMETER) {
+ UINT8 *b=(UINT8*)buff;
+ //--------------------
+ Status=PciCfg8(RbIo, addr, wr, b);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Check if Extended register used then Addr.Register is ignored.
+ if( addr.Addr.ExtendedRegister != 0) addr.Addr.ExtendedRegister += 1;
+ else addr.Addr.Register += 1;
+
+ b++;
+ Status=PciCfg8(RbIo, addr, wr, b);
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciCfg32()
+//
+// Description: Will do PCI Configuration Space Access 32 bit width
+//
+// Input:
+// ROOT_BRIDGE_IO_PROTOCOL *RbIo Pointer to PciRootBridgeIO Protocol.
+// PCI_CFG_ADDR addr PCI_CFG_ADDR filled by caller
+// BOOLEAN wr TRUE = Write FALSE = Read
+// UINT32 *buff Pointer Data Buffer.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// Referals:PCI_CFG_ADDR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciCfg32(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RbIo, PCI_CFG_ADDR addr, BOOLEAN wr, UINT32 *buff){
+ EFI_STATUS Status;
+//------------
+ if(wr)Status=RbIo->Pci.Write(RbIo, EfiPciWidthUint32, addr.ADDR, 1, (VOID*)buff);
+ else Status=RbIo->Pci.Read(RbIo, EfiPciWidthUint32, addr.ADDR, 1, (VOID*)buff);
+ //it might be a Width issue on Pci Root bridge level
+ if(Status==EFI_INVALID_PARAMETER) {
+ UINT16 *b=(UINT16*)buff;
+ //--------------------
+ Status=PciCfg16(RbIo, addr, wr, b);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Check if Extended register used then Addr.Register is ignored.
+ if( addr.Addr.ExtendedRegister != 0) addr.Addr.ExtendedRegister += 2;
+ else addr.Addr.Register += 2;
+
+ b++;
+ Status=PciCfg16(RbIo, addr, wr, b);
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciCfg64()
+//
+// Description: Will do PCI Configuration Space Access 64 bit width
+//
+// Input:
+// ROOT_BRIDGE_IO_PROTOCOL *RbIo Pointer to PciRootBridgeIO Protocol.
+// PCI_CFG_ADDR addr PCI_CFG_ADDR filled by caller
+// BOOLEAN wr TRUE = Write FALSE = Read
+// UINT64 *buff Pointer Data Buffer.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// Referals:PCI_CFG_ADDR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciCfg64(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RbIo, PCI_CFG_ADDR addr, BOOLEAN wr, UINT64 *buff){
+ EFI_STATUS Status;
+//------------
+ if(wr)Status=RbIo->Pci.Write(RbIo, EfiPciWidthUint64, addr.ADDR, 1, (VOID*)buff);
+ else Status=RbIo->Pci.Read(RbIo, EfiPciWidthUint64, addr.ADDR, 1, (VOID*)buff);
+ //it might be a Width issue on Pci Root bridge level
+ if((Status==EFI_INVALID_PARAMETER) && (buff!=NULL)) {
+ UINT32 *b=(UINT32*)buff;
+ //--------------------
+ Status=PciCfg32(RbIo, addr, wr, b);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Check if Extended register used then Addr.Register is ignored.
+ if( addr.Addr.ExtendedRegister != 0) addr.Addr.ExtendedRegister += 4;
+ else addr.Addr.Register += 4;
+
+ b++;
+ Status=PciCfg32(RbIo, addr, wr, b);
+ }
+ return Status;
+}
+
+
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// PCI IO Protocol Functions Implementation Protocol
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+//==================================================================================
+// PciIoProtocol Supporting Functions
+//==================================================================================
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BarCheckType()
+//
+// Description:
+// This helper function will check if Base Address Register(BAR) selected
+// for PciIo operation is of valid type and has been initialized;
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PciDevice Info structure.
+// UINT8 BarIndex Index of the BAR within PCI device
+// PCI_BAR_TYPE BarType Indicating what to check - IO or Memory.
+//
+// Output: BOOLEAN
+// TRUE BAR supports selected transaction.
+// FALSE BAR does not support selected transaction.
+//
+// Referals: PCI_DEV_INFO; PCI_BAR_TYPE
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN BarCheckType(PCI_DEV_INFO *Dev, UINT8 BarIndex, PCI_BAR_TYPE BarType)
+{
+ PCI_BAR *bar=&Dev->Bar[BarIndex];
+//-------------------------------------
+ switch(BarType){
+ case tBarMem:
+ if (bar->Type != tBarMmio32 &&
+ bar->Type != tBarMmio32pf &&
+ bar->Type != tBarMmio64 &&
+ bar->Type != tBarMmio64pf ) return FALSE;
+ break;
+
+ case tBarIo:
+ if (bar->Type != tBarIo32 && bar->Type != tBarIo16)
+ return FALSE;
+ break;
+ default: return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoCheckBar()
+//
+// Description: This helper function will check if parameters passed to the
+// PCI IO Protocol to read or write a PCI resources are correct.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PciDevice Info structure.
+// UINT8 BarInd Index of the BAR within PCI device.
+// PCI_BAR_TYPE BarType Indicating what to check - IO or Memory.
+// EFI_PCI_IO_PROTOCOL_WIDTH Width Width of transaction.
+// UINTN Count Number of bytes been transfered.
+// UINT64 *Offset Offset within BAR address space to start from.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO; PCI_BAR_TYPE;EFI_PCI_IO_PROTOCOL_WIDTH
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoCheckBar(PCI_DEV_INFO *Dev, UINT8 BarInd, PCI_BAR_TYPE Type,
+ EFI_PCI_IO_PROTOCOL_WIDTH Width, UINTN Count, UINT64 *Offset)
+{
+ if ( Width<0 || Width>=EfiPciIoWidthMaximum ) return EFI_INVALID_PARAMETER;
+
+ if (BarInd==0xFF) return EFI_SUCCESS;
+
+ if (BarInd>=MAX_PCI_BAR) return EFI_INVALID_PARAMETER;
+
+ if (!BarCheckType(Dev,BarInd,Type))return EFI_INVALID_PARAMETER;
+
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) Count = 1;
+ Width &= 0x03;
+
+ if((*Offset+Count*((UINTN)1<<Width))-1 >= Dev->Bar[BarInd].Length) return EFI_INVALID_PARAMETER;
+
+ *Offset = *Offset+(UINTN)Dev->Bar[BarInd].Base;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoCheckConfig()
+//
+// Description: This helper function will check if parameters passed to the
+// PCI IO Protocol to made a PCI Config Space Access are correct
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PciDevice Info structure.
+// EFI_PCI_IO_PROTOCOL_WIDTH Width Width of transaction been performed.
+// UINTN Count Number of bytes been transfered.
+// UINT64 *Offset Offset to start from.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO; PCI_BAR_TYPE; EFI_PCI_IO_PROTOCOL_WIDTH
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS PciIoCheckConfig(PCI_DEV_INFO *Dev, EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ UINTN Count, UINT64 *Offset)
+{
+ if(Width<0 || Width>= EfiPciIoWidthMaximum) return EFI_INVALID_PARAMETER;
+
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+ Width &= 0x03;
+ if((*Offset + Count * ((UINTN)1 << Width)) - 1 > 0xFF) return EFI_UNSUPPORTED;
+
+ *Offset=PCI_ASSEMBLE_ADDR(Dev->Address.Addr.Bus,
+ Dev->Address.Addr.Device,Dev->Address.Addr.Function,*Offset);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetIdeDevMode()
+//
+// Description: This function will Change IDE Device Mode LEGACY/NATIVE
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Device Private Data structure.
+// BOOLEAN Primary Indicate Primary/Secondary controller
+// BOOLEAN Legacy Indicate Mode to programm
+// UINT8 *Override If not NULL value to programm in PI register
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_UNSUPPORTED When device does not support mode programming.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO;
+//
+// Notes:
+// This function does not check if SecIde/PriIde Property of the Dev->HostData
+// is tacken already caller must do that before call;
+// This function does not update SecIde/PriIde Property of the Dev->HostData
+// object. Caller must do that upon successfull return.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SetIdeDevMode(PCI_DEV_INFO *Dev, BOOLEAN Primary, BOOLEAN Legacy, UINT8 *Override){
+
+ PCI_CFG_ADDR addr;
+ EFI_STATUS Status=EFI_SUCCESS;
+ UINT8 newpi=0, oldpi=Dev->Class.ProgInterface, tmp=oldpi=Dev->Class.ProgInterface;
+ BOOLEAN canprog=FALSE, needprog=FALSE;
+//--------
+ if(Dev->Class.BaseClassCode!=PCI_CL_MASS_STOR && Dev->Class.SubClassCode!=PCI_CL_MASS_STOR_SCL_IDE)
+ return EFI_INVALID_PARAMETER;
+
+ addr.ADDR=Dev->Address.ADDR;
+ addr.Addr.Register=PCI_PI_OFFSET;
+
+
+ if(Override!=NULL){
+ Status=PciCfg8(Dev->RbIo,addr,TRUE,Override);
+ if(!EFI_ERROR(Status)) {
+ UINT8 b=0;
+ //----------------
+ //read back what we have write there
+ Status=PciCfg8(Dev->RbIo,addr,FALSE,&b);
+ if(b==(*Override))Dev->Class.ProgInterface=(*Override);
+ else Status=EFI_UNSUPPORTED;
+ PCI_TRACE((TRACE_PCI, "\nPciBus: SetIdeMode(Pri=N/A, Legacy=N/A, PciPI=0x%X) @ B%X|D%X|F%X = %r,\n",*Override,
+ Dev->Address.Addr.Bus,Dev->Address.Addr.Device,Dev->Address.Addr.Function, Status));
+ }
+ } else {
+ if(Primary){
+ canprog=(Dev->Class.ProgInterface & 0x02);
+ oldpi&=(~0x01);
+ tmp&=0x01;
+ if(!Legacy) newpi|=0x01;
+ } else {
+ canprog=(Dev->Class.ProgInterface & 0x08);
+ oldpi&=(~0x04);
+ tmp&=0x04;
+ if(!Legacy) newpi|=0x04;
+ }
+ needprog = (tmp ^ newpi);
+ if(needprog){
+ if(canprog){
+ newpi|=oldpi;
+ Status=PciCfg8(Dev->RbIo,addr,TRUE,&newpi);
+ if(!EFI_ERROR(Status)) Dev->Class.ProgInterface=newpi;
+ } else Status=EFI_UNSUPPORTED;
+ }
+ PCI_TRACE((TRACE_PCI, "\nPciBus: SetIdeMode(Pri=%d, Legacy=%d, PciPI=0x%X) @ B%X|D%X|F%X = %r,\n", Primary, Legacy,
+ newpi,Dev->Address.Addr.Bus,Dev->Address.Addr.Device,Dev->Address.Addr.Function, Status));
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InCurVgaChain()
+//
+// Description: Helper function to check if device referenced as "Dev" sits
+// within Current VGA device parents bridges.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PciDevice Info structure.
+//
+// Output: BOOLEAN
+// TRUE "Dev" in Current VGA device parents bridges.
+// FALSE "Dev" is not in Current VGA device parents bridges.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN InCurVgaChain(PCI_DEV_INFO *Dev)
+{
+ PCI_DEV_INFO *d=Dev->HostData->VgaDev;
+//------------------------------------
+ if(!d) return FALSE;
+ while (d->Type!=tPciRootBrg){
+ if(d==Dev) return TRUE;
+ d=d->ParentBrg;
+ }
+ return FALSE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeviceAttributes()
+//
+// Description: Protocol Function Sets or resets PCI Device Arttributs.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PciDevice Info structure.
+// UINT64 Attributes Attributes bitmask which caller whants to change.
+// BOOLEAN Set Specifies weathere to set or reset given "Attributes".
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_UNSUPPORTED When some of the "Attributes" not supported by the "Dev".
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DeviceAttributes(PCI_DEV_INFO *Dev, UINT64 Attributes, BOOLEAN Set)
+{
+ EFI_STATUS Status=0;
+ UINT16 tmp=0;
+ PCI_CMD_REG cmd;
+ PCI_BRG_CNT_REG bc;
+ PCI_CFG_ADDR addr;
+ UINT64 newattr=0, capab=Dev->Capab; //| PCI_ALLOWED_ATTRIBUTES;
+//------------------------------
+
+ addr.ADDR=Dev->Address.ADDR;
+ bc.BRG_CNT_REG=0;
+ cmd.CMD_REG=0;
+
+ //Remove platform specific attributes...
+ //Attributes&=(~(PCI_ALLOWED_ATTRIBUTES));
+
+ //If Devices for special attributes has been selected already we can't set it for different device
+ if(Dev->HostData->VgaDev != NULL){
+ if(Dev != Dev->HostData->VgaDev){
+ if(!InCurVgaChain(Dev) ) capab&=(~PCI_VGA_ATTRIBUTES);
+ }
+ }
+
+ if((Dev->HostData->PriIde!=NULL)&& (Dev!=Dev->HostData->PriIde))
+ capab&=(~EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO);
+ if((Dev->HostData->SecIde!=NULL)&& (Dev!=Dev->HostData->SecIde))
+ capab&=(~EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO);
+
+ //If OEMs want to add some more filters...
+ Status=PciPortOemAttributes(Dev, &Attributes, capab, Set);
+
+ //if Attributes requested NOT SUPPORTED by the device...
+ if((capab & Attributes)!=Attributes) {
+ Status=EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ //if requested Attributes already match Device current Attributes
+ if( (((Dev->Attrib & Attributes)==Attributes) && Set ) || (((Dev->Attrib & Attributes)==0) && (!Set)) )
+ {
+ Status=EFI_SUCCESS;
+ goto Exit;
+ }
+
+ //So far so good - apply attributes
+
+ //For IDE controller it is a special case
+ if( Attributes & (EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO)){
+ BOOLEAN Primary=(BOOLEAN)(Attributes & EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO);
+ //--------------
+ Status=SetIdeDevMode(Dev, Primary, Set, NULL);
+ if(EFI_ERROR(Status))goto Exit;
+
+ if(Set){
+ if(Primary) Dev->HostData->PriIde=Dev;
+ else Dev->HostData->SecIde=Dev;
+ } else {
+ if(Primary) Dev->HostData->PriIde=Dev;
+ else Dev->HostData->SecIde=Dev;
+ }
+ }
+
+ //the
+ if(Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO ||
+ Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) bc.IsaEnable=1;
+
+ if(Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY ||
+ Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO){
+ DXE_SERVICES *dxe;
+ EFI_PHYSICAL_ADDRESS addr=0x3C0;
+ //-----------------------------
+ Status=LibGetDxeSvcTbl(&dxe);
+ if(EFI_ERROR(Status)) return Status;
+
+
+ bc.VgaEnable=1;
+ if (gPciSetupData->VgaPallete) cmd.VgaPaletteSnoop=1;
+
+ if(Set) Status=dxe->AllocateIoSpace(EfiGcdAllocateAddress,
+ EfiGcdIoTypeIo,
+ 0,
+ 0x20,
+ &addr,
+ gPciBusDriverBinding.ImageHandle,
+ gPciBusDriverBinding.DriverBindingHandle);
+ else Status=dxe->FreeIoSpace(addr,0x20);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI, "\nPciBus: Fail to allocate/free IO 0x3C0 ~ 0x3DF; Set=%d; Status=%r,\n", Set, Status));
+ //If it was allocated - fine just keep going.
+ Status=EFI_SUCCESS;
+ }
+ }
+
+ if(Attributes & EFI_PCI_IO_ATTRIBUTE_IO) cmd.IoSpace=1;
+
+ if(Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) cmd.MemSpace=1;
+
+ if(Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) cmd.BusMaster=1;
+
+ //Recoursevely Set attributes to all parents
+ //if Parent bridge is the RootBrg use it native function to set Attributes
+ //keep in mind that per UIEFI 2.1 Spec Bridges are suppose to be always open,
+ //so we will filter Device Enable attributes from setting/resetting them for bridges.
+ newattr=(Attributes & (~(EFI_PCI_IO_ATTRIBUTE_IO|EFI_PCI_IO_ATTRIBUTE_MEMORY|EFI_PCI_IO_ATTRIBUTE_BUS_MASTER|PCI_ALLOWED_ATTRIBUTES)));
+ if(Dev->ParentBrg->Type == tPciRootBrg )Status=Dev->RbIo->SetAttributes(Dev->RbIo,newattr,NULL,NULL);
+ else Status=DeviceAttributes(Dev->ParentBrg,newattr,Set);
+ if(EFI_ERROR(Status))goto Exit;
+
+ //bridge control register for P2P and P2C at the same place
+ if((Dev->Type==tPci2PciBrg || Dev->Type==tPci2CrdBrg) && bc.BRG_CNT_REG){
+ //update bridge control reg if we have to
+ addr.Addr.Register=PCI_BRIDGE_CNTL; //brg controll reg
+
+ //read what it has
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,&tmp);
+ if(EFI_ERROR(Status)) goto Exit;
+
+ if(Set) bc.BRG_CNT_REG=bc.BRG_CNT_REG|tmp;
+ else bc.BRG_CNT_REG=tmp&(~bc.BRG_CNT_REG);
+
+ //write updated value
+ Status=PciCfg16(Dev->RbIo,addr,TRUE,&bc.BRG_CNT_REG);
+ if(EFI_ERROR(Status)) goto Exit;
+ }
+
+ if(cmd.CMD_REG){
+ //update PCI command reg if we have to
+ addr.Addr.Register=PCI_CMD; //command reg
+
+ //read what it has
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,&tmp);
+ if(EFI_ERROR(Status)) goto Exit;
+
+ if(Set) cmd.CMD_REG=cmd.CMD_REG|tmp;
+ else cmd.CMD_REG=tmp&(~cmd.CMD_REG);
+
+ //write updated value
+ Status=PciCfg16(Dev->RbIo,addr,TRUE,&cmd.CMD_REG);
+ if(EFI_ERROR(Status)) goto Exit;
+ }
+ //Update Recorded Attributes
+ if(Set)Dev->Attrib|=Attributes;
+ else Dev->Attrib&=(~Attributes);
+
+Exit:
+ PCI_TRACE((TRACE_PCI, "\nPciBus: SetAttributes(%d) @ B%X|D%X|F%X Attr=0x%lX; Capab=0x%lX; Status=%r,\n", Set,
+ Dev->Address.Addr.Bus,Dev->Address.Addr.Device,Dev->Address.Addr.Function, Attributes, capab, Status));
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoPollMem()
+//
+// Description: Protocol Function Poll PCI Memmory
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//----------------------------------------------------------------------
+
+ if (((UINT32)Width) > ((UINT32)EfiPciIoWidthUint64)) return EFI_INVALID_PARAMETER;
+
+ Status = PciIoCheckBar(dev, BarIndex, tBarMem, Width, 1, &Offset);
+ if(EFI_ERROR(Status)) return EFI_UNSUPPORTED;
+
+ Status=dev->RbIo->PollMem(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,Offset,
+ Mask,Value,Delay,Result);
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoPollIo()
+//
+// Description: Protocol Function Poll PCI IO
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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 )
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//----------------------------------
+ if (((UINT32)Width) > ((UINT32)EfiPciIoWidthUint64)) return EFI_INVALID_PARAMETER;
+
+ Status=PciIoCheckBar(dev, BarIndex, tBarIo, Width, 1, &Offset);
+ if(EFI_ERROR(Status)) return EFI_UNSUPPORTED;
+
+ if (Width > EfiPciIoWidthUint64) return EFI_INVALID_PARAMETER;
+
+ Status=dev->RbIo->PollIo(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ Offset, Mask, Value, Delay, Result);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoMemRead()
+//
+// Description: Protocol Function Performs a PCI Memory Read Cycle
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//---------------------------------------------
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) return EFI_INVALID_PARAMETER;
+
+ Status=PciIoCheckBar(dev, BarIndex, tBarMem, Width, Count, &Offset);
+ if(EFI_ERROR(Status)) return EFI_UNSUPPORTED;
+
+ Status=dev->RbIo->Mem.Read(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ Offset, Count, Buffer);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoMemWrite()
+//
+// Description: Protocol Function Performs a PCI Memory Write Cycle
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//-------------------------------------------
+
+ if(Width<0 || Width>=EfiPciIoWidthMaximum) return EFI_INVALID_PARAMETER;
+
+ Status = PciIoCheckBar(dev, BarIndex, tBarMem, Width, Count, &Offset);
+ if (EFI_ERROR(Status)) return EFI_UNSUPPORTED;
+
+ Status=dev->RbIo->Mem.Write(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ Offset, Count, Buffer);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoIoRead()
+//
+// Description: Protocol Function Performs a PCI I/O Read Cycle
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//----------------------------------------------------
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) return EFI_INVALID_PARAMETER;
+
+ Status=PciIoCheckBar(dev, BarIndex, tBarIo, Width, Count, &Offset);
+ if (EFI_ERROR(Status))return EFI_UNSUPPORTED;
+
+ Status=dev->RbIo->Io.Read(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ Offset, Count, Buffer);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoIoWrite()
+//
+// Description: Protocol Function Performs a PCI I/O Write Cycle
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//----------------------------------------------------
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) return EFI_INVALID_PARAMETER;
+
+ Status=PciIoCheckBar(dev, BarIndex, tBarIo, Width, Count, &Offset);
+ if (EFI_ERROR(Status)) return EFI_UNSUPPORTED;
+
+ Status=dev->RbIo->Io.Write(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ Offset, Count, Buffer);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoConfigRead()
+//
+// Description: Protocol Function Performs a PCI Configuration Read Cycle
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoConfigRead(IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer)
+{
+
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+ UINT64 Address;
+//---------------------------------------------------
+ Address = Offset;
+ Status = PciIoCheckConfig(dev, Width, Count, &Address);
+ if(EFI_ERROR(Status))return Status;
+
+ Status=dev->RbIo->Pci.Read(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ Address, Count, Buffer);
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoConfigWrite()
+//
+// Description: Protocol Function Performs a PCI Configuration Write Cycle
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoConfigWrite(IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+ UINT64 Address;
+//---------------------------------------------------
+ Address = Offset;
+ Status = PciIoCheckConfig(dev, Width, Count, &Address);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status=dev->RbIo->Pci.Write(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ Address, Count, Buffer);
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoCopyMem()
+//
+// Description: Protocol Function Copyes PCI Memory
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//---------------------------------------------------
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) return EFI_INVALID_PARAMETER;
+
+ if(Width == EfiPciIoWidthFifoUint8 ||
+ Width == EfiPciIoWidthFifoUint16 ||
+ Width == EfiPciIoWidthFifoUint32 ||
+ Width == EfiPciIoWidthFifoUint64 ||
+ Width == EfiPciIoWidthFillUint8 ||
+ Width == EfiPciIoWidthFillUint16 ||
+ Width == EfiPciIoWidthFillUint32 ||
+ Width == EfiPciIoWidthFillUint64) return EFI_INVALID_PARAMETER;
+
+ Status=PciIoCheckBar(dev, DestBarIndex, tBarMem, Width, Count, &DestOffset);
+ if (EFI_ERROR(Status)) return EFI_UNSUPPORTED;
+
+ Status=PciIoCheckBar(dev, SrcBarIndex, tBarMem, Width, Count, &SrcOffset);
+ if (EFI_ERROR(Status)) return EFI_UNSUPPORTED;
+
+ Status=dev->RbIo->CopyMem(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ DestOffset, SrcOffset, Count);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoMap()
+//
+// Description: Protocol Function Maps a memory region for DMA
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//---------------------------------------------------
+
+ if(Operation<0 || Operation>=EfiPciIoOperationMaximum) return EFI_INVALID_PARAMETER;
+
+ if(HostAddress==NULL || NumberOfBytes==NULL || DeviceAddress==NULL || Mapping==NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if (dev->Attrib & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE)
+ Operation = Operation + EfiPciOperationBusMasterRead64;
+
+ Status=dev->RbIo->Map(dev->RbIo,(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Operation,
+ HostAddress, NumberOfBytes, DeviceAddress, Mapping);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoUnmap()
+//
+// Description: Protocol Function Unmaps a memory region for DMA
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoUnmap(IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//---------------------------------------------------
+
+ Status=dev->RbIo->Unmap(dev->RbIo,Mapping);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoAllocateBuffer()
+//
+// Description: Protocol Function Allocates a common buffer for DMA
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//---------------------------------------------------
+
+ if (Attributes & (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED)))
+ return EFI_UNSUPPORTED;
+
+ if (dev->Attrib & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE)
+ Attributes|=EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+
+ Status=dev->RbIo->AllocateBuffer(dev->RbIo,Type,MemoryType,Pages,HostAddress,Attributes);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoFreeBuffer()
+//
+// Description: Protocol Function Frees a common buffer
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoFreeBuffer(IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//---------------------------------------------------
+
+ Status=dev->RbIo->FreeBuffer(dev->RbIo,Pages,HostAddress);
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoFlush()
+//
+// Description: Protocol Function Flushes a DMA buffer
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoFlush (IN EFI_PCI_IO_PROTOCOL *This)
+{
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//--------------------------------------------
+ return dev->RbIo->Flush(dev->RbIo);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoGetLocation()
+//
+// Description: Protocol Function Proides Device Address on PCI BUS like
+// Bus#, Dev#, Fun# for the device who has PciIoProtocol == "This".
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoGetLocation(IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *Segment,
+ OUT UINTN *Bus,
+ OUT UINTN *Device,
+ OUT UINTN *Function)
+{
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+//--------------------------------------------
+
+ if(Segment==NULL || Bus==NULL || Device==NULL || Function==NULL)
+ return EFI_INVALID_PARAMETER;
+
+ *Segment = dev->RbIo->SegmentNumber;
+ *Bus = dev->Address.Addr.Bus;
+ *Device = dev->Address.Addr.Device;
+ *Function = dev->Address.Addr.Function;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoAttributes()
+//
+// Description: Protocol Function Provides Arttribute operation for the PCI device
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoAttributes(IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL )
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+ BOOLEAN f=FALSE;
+ UINT64 capab=dev->Capab;
+//--------------------------------------------
+
+ switch (Operation) {
+ case EfiPciIoAttributeOperationGet:
+ case EfiPciIoAttributeOperationSupported:
+ if (Result == NULL) return EFI_INVALID_PARAMETER;
+ if(Operation==EfiPciIoAttributeOperationGet)*Result = dev->Attrib;
+ else {
+
+ if(dev->HostData->VgaDev != NULL){
+ if(dev != dev->HostData->VgaDev){
+ if(!InCurVgaChain(dev) ) capab&=(~PCI_VGA_ATTRIBUTES);
+ }
+ }
+ *Result=capab;
+ }
+ return EFI_SUCCESS;
+ break;
+ case EfiPciIoAttributeOperationSet:
+ case EfiPciIoAttributeOperationEnable:
+ //only one VGA legacy resources may be decoded
+ if(Attributes&PCI_VGA_ATTRIBUTES){ //special case for VGA attr
+ if(dev->HostData->VgaDev==NULL)f=TRUE;
+ }
+ //else if (dev!=dev->HostData->VgaDev) return EFI_UNSUPPORTED;
+ Status=DeviceAttributes(dev, Attributes,TRUE);
+ if((!EFI_ERROR(Status))&& f) dev->HostData->VgaDev=dev;
+ break;
+ case EfiPciIoAttributeOperationDisable:
+ if(Attributes&PCI_VGA_ATTRIBUTES) {//special case for VGA attr
+ if(dev->HostData->VgaDev==dev)f=TRUE;
+ }
+ Status=DeviceAttributes(dev, Attributes,FALSE);
+ if((!EFI_ERROR(Status))&& f ) dev->HostData->VgaDev=NULL; //clear default VGA Device ptr somebody reset it's status
+ break;
+ default : return EFI_INVALID_PARAMETER;
+ }//switch
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoGetBarAttributes()
+//
+// Description: Protocol Function Gets respective BAR Attributes
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoGetBarAttributes(IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports, OPTIONAL
+ OUT VOID **Resources OPTIONAL )
+{
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+ ASLR_QWORD_ASD *resdsc;
+ ASLR_EndTag *enddsc;
+//--------------------------------------------
+
+ if(Supports==NULL && Resources == NULL) return EFI_INVALID_PARAMETER;
+ if(BarIndex>=MAX_PCI_BAR) return EFI_UNSUPPORTED;
+
+ if(Supports!=NULL) {
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//implement changing attributes for BAR using Cpu Protocol
+ *Supports = (dev->Capab & (BAR_ATTR));
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ }
+ if(Resources != NULL) {
+ UINTN sz=sizeof(ASLR_EndTag);
+ //------------------------------------------------
+ if(dev->Bar[BarIndex].Type!=tBarUnused)sz+=sizeof(ASLR_QWORD_ASD);
+
+ resdsc=MallocZ(sz);
+ if(!resdsc) return EFI_OUT_OF_RESOURCES;
+
+
+ if(dev->Bar[BarIndex].Type!=tBarUnused){
+
+ enddsc=(ASLR_EndTag*)(resdsc+1);
+
+ //fill BAR descriptor
+ resdsc->Hdr.Name=ASLV_RT_QWORD_ASD;
+ resdsc->Hdr.Type=ASLV_LARGE_RES;
+ resdsc->Hdr.Length=sizeof(ASLR_QWORD_ASD)-sizeof(ASLRF_L_HDR);
+ resdsc->_MIN=dev->Bar[BarIndex].Base;
+ resdsc->_LEN=dev->Bar[BarIndex].Length;
+ resdsc->_MAX=resdsc->_MIN+resdsc->_LEN-1;
+
+ switch (dev->Bar[BarIndex].DiscoveredType) {
+ case tBarIo16:
+ case tBarIo32:
+ resdsc->Type=ASLRV_SPC_TYPE_IO; // Io
+ break;
+ case tBarMmio32:
+ resdsc->Type=ASLRV_SPC_TYPE_MEM; // Mem
+ resdsc->_GRA=32; // 32 bit
+ break;
+ case tBarMmio32pf:
+ resdsc->Type=ASLRV_SPC_TYPE_MEM; // Mem
+ resdsc->TFlags.TFLAGS=0x6; // prefechable
+ resdsc->_GRA=32; // 32 bit
+ break;
+ case tBarMmio64:
+ resdsc->Type=ASLRV_SPC_TYPE_MEM; // Mem
+ resdsc->_GRA=64; // 32 bit
+ break;
+ case tBarMmio64pf:
+ resdsc->Type=ASLRV_SPC_TYPE_MEM; // Mem
+ resdsc->TFlags.TFLAGS=0x6; // prefechable
+ resdsc->_GRA=64; // 32 bit
+ break;
+ }//switch
+ } else enddsc=(ASLR_EndTag*)(resdsc);
+ //fix End tag
+ enddsc->Hdr.Name=ASLV_SR_EndTag;
+ enddsc->Hdr.Type=ASLV_SMALL_RES;
+ enddsc->Hdr.Length=sizeof(ASLR_EndTag)-sizeof(ASLRF_S_HDR);
+ enddsc->Chsum=0;
+ *Resources = resdsc;
+ }//if(Resources!=NULL)
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciIoSetBarAttributes()
+//
+// Description: Protocol Function Sets respective BAR Attributes
+//
+// Notes: See EFI Specification for detail description
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoSetBarAttributes(IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length)
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=(PCI_DEV_INFO*)This;
+ UINT64 offs, attr;
+//--------------------------------------------------
+
+ if(Offset==NULL || Length==NULL) return EFI_INVALID_PARAMETER;
+
+ if(dev->Bar[BarIndex].Type==tBarUnused) return EFI_UNSUPPORTED;
+
+ // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
+ // If Attributes is not 0, then return EFI_UNSUPPORTED.
+ attr = Attributes & (~BAR_ATTR);
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//implement changing attributes for bar trough Cpu Protocol
+ if (attr)return EFI_UNSUPPORTED;
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+
+ //Make sure the BAR range describd by BarIndex, Offset, and Length are valid for this PCI device.
+ offs = *Offset;
+ Status=PciIoCheckBar(dev, BarIndex, tBarMem, EfiPciIoWidthUint8, (UINT32)*Length, &offs);
+
+ if (EFI_ERROR(Status)) return EFI_UNSUPPORTED;
+
+ return Status;
+}
+
+
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//============================================================================
+// Pci Io Protocol Interface
+//============================================================================
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gPciIoInstance
+//
+// Description: PCI IO Protocol Instance for Child Devices of the PciBus Driver.
+//
+// Notes: EFI_PCI_IO_PROTOCOL
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+static EFI_PCI_IO_PROTOCOL gPciIoInstance = {
+ PciIoPollMem,
+ PciIoPollIo,
+ {
+ PciIoMemRead,
+ PciIoMemWrite
+ },
+ {
+ PciIoIoRead,
+ PciIoIoWrite
+ },
+ {
+ PciIoConfigRead,
+ PciIoConfigWrite
+ },
+ PciIoCopyMem,
+ PciIoMap,
+ PciIoUnmap,
+ PciIoAllocateBuffer,
+ PciIoFreeBuffer,
+ PciIoFlush,
+ PciIoGetLocation,
+ PciIoAttributes,
+ PciIoGetBarAttributes,
+ PciIoSetBarAttributes,
+ 0, //RomSize;
+ NULL //RomImage
+};
+
+
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//======================================================================
+// Here follows worker functions used for
+// PCI Bus Enumeration and Resource Allocation
+//======================================================================
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EnableDeviceDecoding()
+//
+// Description: Enables PCI Device Decoding.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Device Private Data structure.
+// PCI_SPACE_TYPE WhatSpace Type of PCI Device Space for Action.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO; PCI_SPACE_TYPE.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EnableDeviceDecoding(PCI_DEV_INFO *Dev, PCI_SPACE_TYPE WhatSpace)
+{
+ EFI_STATUS Status;
+ UINT16 b16;
+ PCI_CFG_ADDR addr;
+//------------------
+
+ if(Dev->Type<tPci2PciBrg) return EFI_SUCCESS;
+#if EFI_DEBUG || USB_DEBUG_TRANSPORT
+ if(Dev->DebugPort) return EFI_SUCCESS;
+#endif
+
+ addr.ADDR=Dev->Address.ADDR;
+ //first read Command reg contents
+ addr.Addr.Register=PCI_COMMAND_REGISTER_OFFSET;
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,&b16);
+ if(EFI_ERROR(Status)) return Status;
+
+ switch (WhatSpace){
+ case stOptRomSpace:
+ case stMemSpace: b16|=(PCI_CMD_MEMORY_SPACE); break;
+ case stIoSpace: b16|=(PCI_CMD_IO_SPACE); break;
+ case stMemIoSpace: b16|=(PCI_CMD_IO_SPACE | PCI_CMD_MEMORY_SPACE); break;
+ default: return EFI_INVALID_PARAMETER;
+ } //switch
+ //if Enabling PCI ROM space
+ if(WhatSpace==stOptRomSpace && Dev->Bar[PCI_MAX_BAR_NO].Type!=tBarUnused){
+ UINT32 b32;
+ //----------------------
+ addr.Addr.Register=Dev->Bar[PCI_MAX_BAR_NO].Offset;
+
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,&b32);
+ if(EFI_ERROR(Status)) return Status;
+
+ b32|=1;
+ Status=PciCfg32(Dev->RbIo,addr,TRUE,&b32);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ //Write Data to the Command Register
+ addr.Addr.Register=PCI_COMMAND_REGISTER_OFFSET;
+ return PciCfg16(Dev->RbIo,addr,TRUE,&b16);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DisableDeviceDecoding()
+//
+// Description: Disables PCI Device Decoding.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Device Private Data structure.
+// PCI_SPACE_TYPE WhatSpace Type of PCI Device Space for Action.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO; PCI_SPACE_TYPE.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DisableDeviceDecoding(PCI_DEV_INFO *Dev, PCI_SPACE_TYPE WhatSpace)
+{
+ EFI_STATUS Status;
+ UINT16 b16;
+ PCI_CFG_ADDR addr;
+//------------------
+ //Don't toch Host brg device as a PCI Device
+ if(Dev->Type==tPciHostDev || Dev->Type==tUncompatibleDevice) return EFI_SUCCESS;
+#if EFI_DEBUG || USB_DEBUG_TRANSPORT
+ if(Dev->DebugPort) return EFI_SUCCESS;
+#endif
+
+ addr.ADDR=Dev->Address.ADDR;
+ //first read Command reg contents
+ addr.Addr.Register=PCI_COMMAND_REGISTER_OFFSET;
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,&b16);
+ if(EFI_ERROR(Status)) return Status;
+
+ switch (WhatSpace){
+ case stOptRomSpace:
+ case stMemSpace:
+ b16 &= (~PCI_CMD_MEMORY_SPACE);
+ break;
+ case stIoSpace:
+ b16 &= (~PCI_CMD_IO_SPACE);
+ break;
+ case stMemIoSpace:
+ b16 &= (~(PCI_CMD_IO_SPACE | PCI_CMD_MEMORY_SPACE));
+ break;
+ case stDisableAll:
+ b16 &= (~(PCI_CMD_IO_SPACE | PCI_CMD_MEMORY_SPACE | PCI_CMD_BUS_MASTER));
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ } //switch
+
+ //if Disabling PCI ROM space
+ if( (WhatSpace == stOptRomSpace ) && (Dev->Bar[PCI_MAX_BAR_NO].Type!=tBarUnused)){
+ UINT32 b32;
+ //----------------------
+ addr.Addr.Register=Dev->Bar[PCI_MAX_BAR_NO].Offset;
+
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,&b32);
+ if(EFI_ERROR(Status)) return Status;
+
+ b32&=(~1);
+ Status=PciCfg32(Dev->RbIo,addr,TRUE,&b32);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ //Write Data to the Command Register
+ addr.Addr.Register=PCI_COMMAND_REGISTER_OFFSET;
+ Status=PciCfg16(Dev->RbIo,addr,TRUE,&b16);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EnableBridgeIoDecoding()
+//
+// Description: Enables PCI Bridge I/O Space Decoding.
+//
+// Input:
+// PCI_DEV_INFO *Brg Pointer to PCI Bridge Private Data structure.
+// UINT64 Base Base Address of the Bridge I/O Window.
+// UINT64 Length Length of the Bridge I/O Window.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EnableBridgeIoDecoding(PCI_DEV_INFO *Brg, UINT64 Base, UINT64 Length)
+{
+ PCI_CFG_ADDR BrgDevAddr;
+ UINT64 buff;
+ EFI_STATUS Status;
+//----------------------------------------
+ PCI_TRACE((TRACE_PCI,"PciBus: Enabling Brg I/O @ B%X|D%X|F%X\n, B=%lX; L=%lX\n",
+ Brg->Address.Addr.Bus, Brg->Address.Addr.Device,Brg->Address.Addr.Function,
+ Base, Length));
+
+ BrgDevAddr.ADDR=Brg->Address.ADDR;
+ //Set IObase to 0xFF and IO limit to 0
+ BrgDevAddr.Addr.Register=0x1C;
+ buff=Shr64(Base,8);
+
+ Status = PciCfg8(Brg->RbIo, BrgDevAddr,TRUE,(UINT8*)&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ buff=Shr64(Base,16);
+ BrgDevAddr.Addr.Register=0x30; //Upper 16 Base Reg
+
+ Status = PciCfg16(Brg->RbIo, BrgDevAddr,TRUE,(UINT16*)&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ //Set IO limit
+ buff=Shr64(Base+(Length-1),8);
+ BrgDevAddr.Addr.Register=0x1D;
+
+ Status = PciCfg8(Brg->RbIo, BrgDevAddr,TRUE,(UINT8*)&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ //Set IO limit Upper 16
+ buff=Shr64(Base+(Length-1),16);
+ BrgDevAddr.Addr.Register=0x32;
+
+ return PciCfg16(Brg->RbIo, BrgDevAddr,TRUE,(UINT16*)&buff);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DisableBridgeIoDecoding()
+//
+// Description: Disables PCI Bridge I/O Space Decoding.
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer to PCI Bridge Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_BRG_INFO.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DisableBridgeIoDecoding(PCI_BRG_INFO *Brg)
+{
+ PCI_CFG_ADDR BrgDevAddr;
+ UINT32 buff=0x00FF;
+ EFI_STATUS Status;
+//----------------------------------------
+ BrgDevAddr.ADDR=Brg->Common.Address.ADDR;
+ //Set IObase to 0xFF and IO limit to 0
+ BrgDevAddr.Addr.Register=0x1C;
+ Status = PciCfg16(Brg->Common.RbIo, BrgDevAddr,TRUE,(UINT16*)&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ //Set IO limit upper 32 base and limit to 0
+ BrgDevAddr.Addr.Register=0x30;
+ return PciCfg32(Brg->Common.RbIo, BrgDevAddr,TRUE,&buff);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EnableBridgeMmioDecoding()
+//
+// Description: Enables PCI Bridge MMIO Space Decoding.
+//
+// Input:
+// PCI_DEV_INFO *Brg Pointer to PCI Bridge Private Data structure.
+// UINT64 Base Base Address of the Bridge I/O Window.
+// UINT64 Length Length of the Bridge I/O Window.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EnableBridgeMmioDecoding(PCI_DEV_INFO *Brg, UINT64 Base, UINT64 Length)
+{
+ PCI_CFG_ADDR BrgDevAddr;
+ UINT64 buff;
+ EFI_STATUS Status;
+//----------------------------------------
+ PCI_TRACE((TRACE_PCI,"PciBus: Enabling Brg MMIO @ [B%X|D%X|F%X] --> B=%lX; L=%lX\n",
+ Brg->Address.Addr.Bus, Brg->Address.Addr.Device,Brg->Address.Addr.Function,
+ Base, Length));
+
+ BrgDevAddr.ADDR=Brg->Address.ADDR;
+ //Set Memory Base
+ BrgDevAddr.Addr.Register=PCI_MEMBASE;
+ //buff=Base>>16;
+ buff=Shr64(Base,16);
+
+ Status=PciCfg16(Brg->RbIo, BrgDevAddr,TRUE,(UINT16*)&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ //Set Memory limt
+ BrgDevAddr.Addr.Register=PCI_MEMLIMIT;
+ buff=Shr64(Base+(Length-1),16);
+ return PciCfg16(Brg->RbIo, BrgDevAddr,TRUE,(UINT16*)&buff);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DisableBridgeMmioDecoding()
+//
+// Description: Disables PCI Bridge MMIO Space Decoding.
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer to PCI Bridge Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_BRG_INFO.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DisableBridgeMmioDecoding(PCI_BRG_INFO *Brg)
+{
+ PCI_CFG_ADDR BrgDevAddr;
+ UINT32 buff=0x0000FFFF;
+//----------------------------------------
+ BrgDevAddr.ADDR=Brg->Common.Address.ADDR;
+ //Set Memory Base to FFFF and Limit to 0;
+ BrgDevAddr.Addr.Register=0x20;
+ return PciCfg32(Brg->Common.RbIo, BrgDevAddr,TRUE,&buff);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EnableBridgePfmmDecoding()
+//
+// Description: Enables PCI Bridge Prefetchable MMIO Space Decoding.
+//
+// Input:
+// PCI_DEV_INFO *Brg Pointer to PCI Bridge Private Data structure.
+// UINT64 Base Base Address of the Bridge I/O Window.
+// UINT64 Length Length of the Bridge I/O Window.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EnableBridgePfmmDecoding(PCI_DEV_INFO *Brg, UINT64 Base, UINT64 Length)
+{
+ PCI_CFG_ADDR BrgDevAddr;
+ UINT64 buff;
+ EFI_STATUS Status;
+//----------------------------------------
+ PCI_TRACE((TRACE_PCI,"PciBus: Enabling Brg PFMM @ B%X|D%X|F%X\n, B=%lX; L=%lX\n",
+ Brg->Address.Addr.Bus, Brg->Address.Addr.Device,Brg->Address.Addr.Function,
+ Base, Length));
+
+ BrgDevAddr.ADDR=Brg->Address.ADDR;
+
+ //Set Pf Memory Base
+ BrgDevAddr.Addr.Register=0x24;
+ buff=Shr64(Base,16);
+
+ Status = PciCfg16(Brg->RbIo, BrgDevAddr, TRUE,(UINT16*)&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ //Set PF Memory Limit
+ BrgDevAddr.Addr.Register=0x26;
+ buff=Shr64(Base+(Length-1),16);
+
+ Status = PciCfg16(Brg->RbIo, BrgDevAddr, TRUE, (UINT16*)&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ buff=Shr64(Base,32);
+ //Set Pf Memory Upper 32 Base
+ BrgDevAddr.Addr.Register=0x28;
+ Status = PciCfg32(Brg->RbIo, BrgDevAddr,TRUE,(UINT32*)&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ buff=Shr64(Base+(Length-1),32);
+ //Set Pf Memory Upper 32 Limit
+ BrgDevAddr.Addr.Register=0x2C;
+ return PciCfg32(Brg->RbIo, BrgDevAddr,TRUE,(UINT32*)&buff);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DisableBridgePfmmDecoding()
+//
+// Description: Disables PCI Bridge Prefetchable MMIO Space Decoding.
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer to PCI Bridge Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_BRG_INFO.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DisableBridgePfmmDecoding(PCI_BRG_INFO *Brg)
+{
+ PCI_CFG_ADDR BrgDevAddr;
+ UINT32 buff=0x0000FFFF;
+ EFI_STATUS Status;
+//----------------------------------------
+ BrgDevAddr.ADDR=Brg->Common.Address.ADDR;
+
+ //Set Pf Memory Base to FFFF Limit to 0;
+ BrgDevAddr.Addr.Register=0x24;
+ Status = PciCfg32(Brg->Common.RbIo, BrgDevAddr,TRUE,&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ buff=0;
+ //Set Pf Memory Upper 32 Base to 0;
+ BrgDevAddr.Addr.Register=0x28;
+ Status = PciCfg32(Brg->Common.RbIo, BrgDevAddr,TRUE,&buff);
+ if(EFI_ERROR(Status))return Status;
+
+ //Set Pf Memory Upper 32 Limit to 0;
+ BrgDevAddr.Addr.Register=0x2c;
+ return PciCfg32(Brg->Common.RbIo, BrgDevAddr,TRUE,&buff);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DisableBridgeDecoding()
+//
+// Description: Disables PCI Bridge Decoding of ALL resources.
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer to PCI Bridge Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_BRG_INFO.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DisableBridgeDecoding(PCI_BRG_INFO *Brg)
+{
+ EFI_STATUS Status;
+//---------------------------------------
+
+ PCI_TRACE((TRACE_PCI,"PciBus: Disabling Brg @ B%X|D%X|F%X\n",
+ Brg->Common.Address.Addr.Bus, Brg->Common.Address.Addr.Device,Brg->Common.Address.Addr.Function));
+ Status=DisableBridgeIoDecoding(Brg);
+ if(EFI_ERROR(Status))return Status;
+
+ Status=DisableBridgeMmioDecoding(Brg);
+ if(EFI_ERROR(Status))return Status;
+
+ return DisableBridgePfmmDecoding(Brg);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetSubBus()
+//
+// Description: Programm SubordinateBusNumber Register of PCI Bridge.
+//
+// Input:
+// PCI_DEV_INFO *Brg Pointer to PCI Bridge Private Data structure.
+// UINT8 SubBusNo Number to programm.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_BRG_INFO.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SetSubBus(PCI_DEV_INFO *Brg, UINT8 SubBusNo)
+{
+ PCI_CFG_ADDR addr;
+//---------------------------------------
+ addr.ADDR=Brg->Address.ADDR;
+ addr.Addr.Register=PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET; //Sub Bus No reg
+
+ return PciCfg8(Brg->RbIo, addr,TRUE,&SubBusNo);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddBusDbEntry()
+//
+// Description: Fills gPciBusDb Array in ascending order.
+//
+// Input:
+// PCI_BRG_EXT *Ext Pointer to PCI Bridge Extension Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AddBusDbEntry(PCI_BUS_XLAT_HDR *BusHdr, T_ITEM_LIST *BusDb){
+ EFI_STATUS Status;
+ UINTN i;
+ PCI_BUS_XLAT_HDR *xhdr;
+//--------------------------
+
+ if(BusDb->ItemCount==0) {
+ Status=AppendItemLst(BusDb, BusHdr);
+ } else {
+ for(i=0; i<BusDb->ItemCount; i++){
+ xhdr = (PCI_BUS_XLAT_HDR*)BusDb->Items[i];
+ if(xhdr->BusBuild > BusHdr->BusBuild){
+ return InsertItemLst(BusDb, BusHdr, i);
+ }
+ }//for
+ // if we here and didn't returned yet - BusHdr->BusBuild is the bidggest one.
+ Status = AppendItemLst(BusDb, BusHdr);
+ }
+#if AMI_BOARD_VER_COMBINED >= 100
+ //Increase BusXlatTable entry count...
+ if(!EFI_ERROR(Status)) gAmiBoardInfo->BusXlatEntries++;
+#endif
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PopulateBusDb()
+//
+// Description: Fills gPciBusDb Array in ascending order.
+//
+// Input: Nothing;
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PopulateBusDb(){
+ PCI_BUS_XLAT_HDR *xhdr=gAmiBoardInfo->BusXlatTable;
+ PCI_DEV_FUN *devf = (PCI_DEV_FUN*)(xhdr+1);
+ EFI_STATUS Status=EFI_SUCCESS;
+//--------------------------------
+ while((UINTN)devf<=(UINTN)(gAmiBoardInfo->BusXlatTable) + gAmiBoardInfo->BusXlatLength){
+ if(devf->DEV_FUN == 0xFF){
+ //if we are looking for host device it shouldn't be any other guys in it's chain.
+ Status=AddBusDbEntry(xhdr, &gPciBusDb);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ //Advance to the next record in BusXlatTbl.
+#if AMI_BOARD_VER_COMBINED >= 100
+ //Now we have AslName[5] following devf data (sizeof(PCI_DEV_FUN)==1 byte)
+ xhdr=(PCI_BUS_XLAT_HDR*)(devf+1+5);
+#else
+ xhdr=(PCI_BUS_XLAT_HDR*)(devf+1);
+#endif
+ devf = (PCI_DEV_FUN*)(xhdr+1);
+ continue;
+ } else {
+ devf++;
+ }
+ }
+ return Status;
+}
+
+/*
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindRootXlatEntry()
+//
+// Description: Finds corresponded BusXlatTable entry for the bridge.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Bridge Private Data structure.
+// PCI_BUS_XLAT_HDR *XlatHdr Double Pointer to XLAT_HEADER will be initialized by this function
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO; PCI_BRG_INFO; PCI_BRG_EXT.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindRootXlatEntry(PCI_DEV_INFO *Dev, PCI_BUS_XLAT_HDR **XlatHdr){
+ PCI_DEV_INFO *brg=Dev;
+ PCI_BRG_EXT *ext=NULL;
+//-------------------------
+ while(brg->Type==tPciRootBrg){
+ brg=brg->ParentBrg;
+ //this code just to double check the loop will be exited.
+ //
+ if(brg->ParentBrg==NULL){
+ ext=(PCI_BRG_EXT*)(brg+1);
+
+ if(ext->XlatTblEntry==NULL) return EFI_NOT_FOUND;
+
+ *XlatHdr=ext->XlatTblEntry;
+
+ break;
+ }
+ }
+
+ if(ext==NULL) return EFI_NOT_FOUND;
+
+ return EFI_SUCCESS;
+
+}
+*/
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindBridgeXlatEntry()
+//
+// Description: Finds corresponded BusXlatTable entry for the bridge.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Bridge Private Data structure.
+// PCI_BRG_EXT *Ext Pointer to PCI Bridge Extension Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO; PCI_BRG_INFO; PCI_BRG_EXT.
+//
+// Notes:
+// BaseBus = PCI_DEV_INFO->Address.Addr.Bus;
+// SecondaryBus = PCI_BRG_EXT->Res[rtBus].Base;
+// SubordinateBus = PCI_BRG_EXT->Res[rtBus].Base + PCI_BRG_EXT->Res[rtBus].Length-1;
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindBridgeXlatEntry(PCI_DEV_INFO *Dev, PCI_BRG_EXT *Ext){
+ PCI_BUS_XLAT_HDR *xhdr;
+ PCI_DEV_FUN *devf;
+ UINTN i, chncnt; //Xlat Tbl Elemnts count (number of Dev/Fn instances)
+ PCI_BRG_EXT *ext;
+//-----------------------------
+ //Now we will go trough BusXlatTbl entryes.
+ for(i=0; i<gPciBusDb.ItemCount; i++){
+ xhdr=gPciBusDb.Items[i];
+ devf = (PCI_DEV_FUN*)(xhdr+1);
+ for (chncnt=0; ; devf++,chncnt++){
+ //Got to the end of PCI device chain
+ if(devf->DEV_FUN == 0xFF){
+ //if we are looking for host device it shouldn't be any other guys in it's chain.
+ if((Dev->ParentBrg == NULL) && (chncnt==1) && (Dev->Type==tPciRootBrg)){
+ //Check first if it is a correct host.
+ if( (xhdr->BusBuild == Dev->Address.Addr.Bus) )
+ {
+ //xhdr->BusRun = Dev->Address.Addr.Bus;
+ Ext->XlatTblEntry=xhdr;
+ Ext->ChainNumber=(UINT8)chncnt;
+ Ext->ItemNumber=(UINT8)i;
+
+ PCI_TRACE((TRACE_PCI,"PciBus: Found BusXlat for Host [B%X|D%X|F%X] BusBuild=%X\n",
+ Dev->Address.Addr.Bus,Dev->Address.Addr.Device, Dev->Address.Addr.Function, xhdr->BusBuild));
+
+ return EFI_SUCCESS;
+ }
+ } else {
+ //NOT HOST Device !((Dev->ParentBrg == NULL) && (chncnt==1))
+ PCI_DEV_FUN *df=devf-1;
+ //----------------------
+ if(Dev->ParentBrg!=NULL){
+
+ //Here we will define a criteria when XLAT TBL entrie considered a match..
+ //1. ParentBrg->Ext->XlatTblEntry must be initialized
+ //2. ParentBrg->ChainNumber must be (chncnt-1) so this one will be the same elememnt
+ //3. ParentBrg->Ext->XlatTblEntry->BusBuild must not exceed THIS xhdr->BusBuild
+ //4. df->Dev==Dev->Address.Addr.Device AND df->Fun==Dev->Address.Addr.Function
+ //5. THIS Dev->Ext->XlatTbEntry must not be initialized yet..
+
+ //Get Parent Bridge ext of this device.
+ ext=(PCI_BRG_EXT*)(Dev->ParentBrg+1);
+
+ //1. ParentBrg->Ext->XlatTblEntry must be initialized
+ //2. ParentBrg->Ext->ChainNumber must be (chncnt-1) so this one will be the same elememnt in it's Chain
+ //5. THIS Dev->Ext->XlatTbEntry must not be initialized yet...
+ if((Ext->XlatTblEntry==NULL)&&(ext->XlatTblEntry!=NULL) && (ext->ChainNumber == (UINT8)chncnt-1)){
+
+ //3. ParentBrg->Ext->XlatTblEntry->BusBuild must not exceed THIS xhdr->BusBuild
+ if( xhdr->BusBuild > ext->XlatTblEntry->BusBuild ) {
+
+ //4. df->Dev==Dev->Address.Addr.Device AND df->Fun==Dev->Address.Addr.Function
+ if((Dev->Address.Addr.Device == df->Dev)&&(Dev->Address.Addr.Function == df->Fun)){
+
+ if(MemCmp((VOID*)(ext->XlatTblEntry+1),(VOID*)(xhdr+1), ext->ChainNumber)==0){
+ //xhdr->BusRun = Dev->Address.Addr.Bus;
+ Ext->XlatTblEntry=xhdr;
+ Ext->ChainNumber=(UINT8)chncnt;
+ Ext->ItemNumber=(UINT8)i;
+ PCI_TRACE((TRACE_PCI,"PciBus: Found BusXlat for Brg [B%X|D%X|F%X] BusBuild=%X\n",
+ Dev->Address.Addr.Bus,Dev->Address.Addr.Device, Dev->Address.Addr.Function, xhdr->BusBuild));
+ return EFI_SUCCESS;
+ }
+ }//Cond 4
+
+ }//cond 3;
+
+ }//cond 1;2;5;
+ }//if(Dev->ParentBrg!=NULL)
+ } //else
+ break;
+ }//devf->DEV_FUN == 0xFF
+ } //for chncnt
+ } //for i
+
+ return EFI_NOT_FOUND;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindBridgeXlatEntry()
+//
+// Description: Finds corresponded BusXlatTable entry for the next bridge
+// of the same level (same number of nodes/chain-counts).
+//
+// Input:
+// PCI_BRG_EXT *Ext Pointer to PCI Bridge Extension Private Data structure.
+//
+// Output: UINT8 Number of buses decoded by the Bridge which "Ext" passed.
+//
+// Notes:
+// BaseBus = PCI_DEV_INFO->Address.Addr.Bus;
+// SecondaryBus = PCI_BRG_EXT->Res[rtBus].Base;
+// SubordinateBus = PCI_BRG_EXT->Res[rtBus].Base + PCI_BRG_EXT->Res[rtBus].Length-1;
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8 FindNextSameLevelBrgXlatEntry(PCI_BRG_EXT *Ext){
+ PCI_BUS_XLAT_HDR *xhdr;
+ PCI_DEV_FUN *devf;
+ UINTN i, chncnt; //Xlat Tbl Elemnts count (number of Dev/Fn instances)
+//-----------------------------
+ //Now we will go trough BusXlatTbl entryes.
+ if(gPciBusDb.ItemCount <= (UINTN)(Ext->ItemNumber+1) ) return (UINT8)mMaxBusScan;
+
+ for(i=Ext->ItemNumber+1; i<gPciBusDb.ItemCount; i++){
+ xhdr=gPciBusDb.Items[i];
+ devf = (PCI_DEV_FUN*)(xhdr+1);
+ for (chncnt=0; ; devf++,chncnt++){
+ //Got to the end of PCI device chain
+ if(devf->DEV_FUN == 0xFF) break;
+ } //for chncnt
+ //here we found record terminator
+ //go and check the following.
+ //1. if this Xlat node of the same or less
+ if(chncnt<=Ext->ChainNumber) return (UINT8)(xhdr->BusBuild-1);
+ } //for i
+
+ return (UINT8)mMaxBusScan;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindDevIrqEntry()
+//
+// Description: Finds corresponded BusXlatTable entry for the bridge.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Bridge Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO; PCI_BRG_INFO; PCI_BRG_EXT.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindDevIrqEntry(PCI_DEV_INFO *Dev){
+ UINTN i, cnt;
+ PCI_DEV_INFO *brg=Dev->ParentBrg;
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(brg+1);
+ PCI_BUS_XLAT_HDR *xhdr=ext->XlatTblEntry;
+ PCI_IRQ_PIC_ROUTE *pic;
+ PCI_IRQ_APIC_ROUTE *apic;
+//-----------------------------------
+
+ //Find Matching IRQ Routing entry for PIC
+ //cnt=((UINTN)gPicIrqTblEnd-(UINTN)gPicIrqRoutTbl)/sizeof(PCI_IRQ_PIC_ROUTE)-1;
+ cnt=gAmiBoardInfo->PicRoutLength/sizeof(PCI_IRQ_PIC_ROUTE);
+
+ for(i=0; i<cnt; i++){
+ pic=&gAmiBoardInfo->PicRoutTable[i];
+ if(xhdr->BusBuild==pic->PciBusNumber){
+ //pic->PciBusNumber=xhdr->BusRun;
+
+ if( pic->DevFun.Dev == Dev->Address.Addr.Device){
+ Dev->PicIrqEntry = pic;
+ break;
+ }
+ }
+ }
+ //Find Matching IRQ Routing entry for APIC
+ //cnt=((UINTN)gApicIrqTblEnd-(UINTN)gApicIrqRoutTbl)/sizeof(PCI_IRQ_APIC_ROUTE)-1;
+ cnt=gAmiBoardInfo->ApicRoutLength/sizeof(PCI_IRQ_APIC_ROUTE);
+
+ for(i=0; i<cnt; i++){
+ apic=&gAmiBoardInfo->ApicRoutTable[i];
+ if(xhdr->BusBuild==apic->PciBusNumber){
+ //apic->PciBusNumber=xhdr->BusRun;
+
+ if( apic->DeviceNumber == Dev->Address.Addr.Device){
+ Dev->ApicIrqEntry = apic;
+ break;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: *mPicIrqSta[]; *mPicIrqSta[]
+//
+// Description: To make sure we are not updating entries we have updated
+// already, we would need array of BBOLEANs to mark updated entries.
+//
+// NOTE: BOOLEAN Aarray [IrqRoiting Table enytries Number]
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN *mPicIrqSta = NULL;
+BOOLEAN *mApicIrqSta= NULL;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateItqTbl()
+//
+// Description: Updtaes all matching entries in Irqrouting tables with
+// runtime values.
+//
+// Input:
+// PCI_BUS_XLAT_HDR *XlatHdr Updated BusTranslate table entry.
+//
+// Output: NOTHING
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UpdateIrqTables(PCI_BUS_XLAT_HDR *XlatHdr){
+ UINTN i;
+ PCI_IRQ_PIC_ROUTE *pic;
+ PCI_IRQ_APIC_ROUTE *apic;
+//------------------------------
+
+ if(mPicIrqSta==NULL) mPicIrqSta=MallocZ(gAmiBoardInfo->PicRoutLength/sizeof(PCI_IRQ_PIC_ROUTE));
+ if(mApicIrqSta==NULL) mApicIrqSta=MallocZ(gAmiBoardInfo->ApicRoutLength/sizeof(PCI_IRQ_APIC_ROUTE));
+
+ for(i=0; i<gAmiBoardInfo->PicRoutLength/sizeof(PCI_IRQ_PIC_ROUTE); i++){
+ pic=&gAmiBoardInfo->PicRoutTable[i];
+ if(pic->PciBusNumber==XlatHdr->BusBuild && mPicIrqSta[i]==FALSE) {
+ pic->PciBusNumber=XlatHdr->BusRun;
+ mPicIrqSta[i]=TRUE;
+ }
+ }
+
+ //Not likely but who knows... it could be that gAmiBoardInfo->PicRoutLength
+ //different from gAmiBoardInfo->ApicRoutLength... so teke care of that!
+ for(i=0; i<gAmiBoardInfo->ApicRoutLength/sizeof(PCI_IRQ_APIC_ROUTE); i++){
+ apic=&gAmiBoardInfo->ApicRoutTable[i];
+ if(apic->PciBusNumber==XlatHdr->BusBuild && mApicIrqSta[i]==FALSE) {
+ apic->PciBusNumber=XlatHdr->BusRun;
+ mApicIrqSta[i]=TRUE;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RemoveUnusedIrqEntries()
+//
+// Description: Removes IRQ routing entries which got there by porting mistake
+// in order not to confuse other consumers of AmiBoardInfoProtocol...
+//
+// Input: NOTHING
+//
+// Output: NOTHING
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID RemoveUnusedIrqEntries(){
+ UINTN i, j, cnt;
+ PCI_IRQ_PIC_ROUTE *tmpp;
+ PCI_IRQ_APIC_ROUTE *tmpa;
+//------------------------------
+ cnt=gAmiBoardInfo->PicRoutLength/sizeof(PCI_IRQ_PIC_ROUTE);
+ tmpp=(PCI_IRQ_PIC_ROUTE*)Malloc(gAmiBoardInfo->PicRoutLength);
+ ASSERT(tmpp);
+
+ for(j=0,i=0; j<cnt; j++){
+ if(mPicIrqSta[j]==TRUE){
+ MemCpy(&tmpp[i],&gAmiBoardInfo->PicRoutTable[j],sizeof(PCI_IRQ_PIC_ROUTE));
+ i++;
+ } else {
+ gAmiBoardInfo->PicRoutLength -= sizeof(PCI_IRQ_PIC_ROUTE);
+ PCI_TRACE((TRACE_PCI,"PciBus: Removing unused entry #%d from PIC Routing Table\n", j));
+ }
+ }
+ //Copy updated tabe from tmp buffer to AmiBoardInfo Location
+ MemCpy(&gAmiBoardInfo->PicRoutTable[0], &tmpp[0], gAmiBoardInfo->PicRoutLength);
+
+ //Not likely but who knows... it could be that gAmiBoardInfo->PicRoutLength
+ //different from gAmiBoardInfo->ApicRoutLength... so teke care of that!
+ cnt=gAmiBoardInfo->ApicRoutLength/sizeof(PCI_IRQ_APIC_ROUTE);
+ tmpa=(PCI_IRQ_APIC_ROUTE*)Malloc(gAmiBoardInfo->ApicRoutLength);
+ ASSERT(tmpa);
+
+ for(j=0,i=0; j<cnt;j++){
+ if(mApicIrqSta[j]==TRUE){
+ MemCpy(&tmpa[i],&gAmiBoardInfo->ApicRoutTable[j],sizeof(PCI_IRQ_APIC_ROUTE));
+ i++;
+ } else {
+ gAmiBoardInfo->ApicRoutLength -= sizeof(PCI_IRQ_APIC_ROUTE);
+ PCI_TRACE((TRACE_PCI,"PciBus: Removing unused entry #%d from APIC Routing Table\n", j));
+ }
+ }
+ //Copy updated tabe from tmp buffer to AmiBoardInfo Location
+ MemCpy(&gAmiBoardInfo->ApicRoutTable[0], &tmpa[0], gAmiBoardInfo->ApicRoutLength);
+
+ //free buffers allocated, functions depending on it
+ //not suppose to be called anymore.
+ if(mPicIrqSta!=NULL){
+ pBS->FreePool(mPicIrqSta);
+ mPicIrqSta=NULL;
+ }
+ if(mApicIrqSta!=NULL){
+ pBS->FreePool(mApicIrqSta);
+ mApicIrqSta=NULL;
+ }
+ if(tmpp!=NULL) pBS->FreePool(tmpp);
+ if(tmpa!=NULL) pBS->FreePool(tmpa);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MapBridgeBuses()
+//
+// Description: Maps Bridge's Primary Secondary Subordinate Bus Numbers
+// according information stored in PCI_DEV_INFO and PCI_BRG_EXT structures
+// of the PCI Bridge.
+//
+// Input:
+// PCI_DEV_INFO *Brg Pointer to PCI Bridge Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO; PCI_BRG_INFO; PCI_BRG_EXT.
+//
+// Notes:
+// BaseBus = PCI_DEV_INFO->Address.Addr.Bus;
+// SecondaryBus = PCI_BRG_EXT->Res[rtBus].Base;
+// SubordinateBus = PCI_BRG_EXT->Res[rtBus].Base + PCI_BRG_EXT->Res[rtBus].Length-1;
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS MapBridgeBuses(PCI_DEV_INFO *Brg)
+{
+ EFI_STATUS Status;
+ PCI_CFG_ADDR addr;
+ UINT8 bus;
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(Brg+1);
+//--------------------------------
+ //Get Bridge Initial Address
+ addr.ADDR=Brg->Address.ADDR;
+ //Primary bus;
+ addr.Addr.Register=PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET; //Primary BusNo
+ bus=Brg->Address.Addr.Bus;
+ Status=PciCfg8(Brg->RbIo,addr,TRUE,&bus);
+ if(EFI_ERROR(Status))return Status;
+
+ //SecondaryBus Register
+ addr.Addr.Register=PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET; //Secondary BusNo
+
+ bus=(UINT8)ext->Res[rtBus].Base;
+ Status=PciCfg8(Brg->RbIo,addr,TRUE,&bus);
+ if(EFI_ERROR(Status))return Status;
+
+ //Now Programm SubordinateBusNo reg
+ bus=(UINT8)(ext->Res[rtBus].Base+ext->Res[rtBus].Length-1);
+ return SetSubBus(Brg, bus);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckPciCompatibility()
+//
+// Description: This function will check if PCI "Device" listed in Bad PCI
+// Device Table - gBadPciDevList[].
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+// PCI_BAR_TYPE BarType Type of Bar Register.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO; PCI_BAR_TYPE.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+PCI_BAD_BAR *CheckPciCompatibility(PCI_DEV_INFO *Device, PCI_BAR *Bar, PCI_BAR_TYPE BarType) //(EIP41687)
+{
+ UINTN i;
+ PCI_BAD_BAR *bbp;
+ PCI_DEV_ID d,t;
+//-----------------------
+ d.DEV_VEN_ID=Device->DevVenId.DEV_VEN_ID;
+ for(i=0; i<gBadPciDevCount; i++){
+ bbp=&gBadPciDevList[i];
+ //(EIP41687)>
+ if(Bar) {
+ if (bbp->BarOffset) {
+ if (Bar->Offset != bbp->BarOffset) continue;
+ }
+ }
+ //<(EIP41687)
+ t.VenId=bbp->VendorId;
+ t.DevId=bbp->DeviceId & bbp->DevIdMask;
+ d.DevId=Device->DevVenId.DevId & bbp->DevIdMask;
+ if(d.DEV_VEN_ID==t.DEV_VEN_ID){
+ if(BarType) {
+ if(BarType==bbp->BarType) return bbp;
+ } else return bbp;
+ }
+ }
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AdjustBarGra()
+//
+// Description: This function will Check and Adjust PCI Device's BAR
+// Granularity according information found in gBadPciDevList[].
+//
+// Input:
+// PCI_BAR Bar Type of Bar Register.
+//
+// Output: NOTHING
+//
+// Referals: PCI_BAR; PCI_BAR_TYPE; gBadPciDevList.
+//
+// Notes:
+// This function will be invoked only if PCI Device owning this BAR is in
+// gBadPciDevList.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID AdjustBarGra(PCI_BAR *Bar){
+ UINTN i,s,e;
+ PCI_BAR_TYPE bt;
+ PCI_BAD_BAR *bbp;
+ UINT64 t=0,g=~(Bar->Gran);
+//----------------------------
+ switch(Bar->Type){
+ case tBarIo16: //2
+ case tBarIo32: //3
+ bt=tBarIo;
+ s=2;
+ break;
+ case tBarMmio32: //4
+ case tBarMmio32pf: //5
+ case tBarMmio64: //6
+ case tBarMmio64pf: //7
+ bt=tBarMem;
+ s=4;
+ break;
+ default:
+ bt=tBarUnused;
+ s=0;
+ }
+
+ bbp=CheckPciCompatibility(Bar->Owner,Bar,bt); //(EIP41687)
+ if(!bbp)bbp=CheckPciCompatibility(Bar->Owner,Bar,tBarMaxType); //(EIP41687)
+ //this function will be called only if compatibility issue exists with the device
+ //so bbp must be valid or this is not the BAR which needs Adjustment;
+ if(!bbp) return;
+ if(bbp->BarType==tBarMaxType && Bar->Offset!=bbp->BarOffset) return;
+
+ //Here let's do the adjustment...
+ switch(bbp->IncompType){
+ case icBarBad:
+ for(i=s; i<64; i++){
+ //find the very first bit set as 1;
+ t=Shl64(1,(UINT8)i);
+ if(g&t)break;
+ }
+ //Assume that all other bits must be 1
+ e=i;
+ t=0;
+ //Generate Granularity value for this BAR
+ for(i=0;i<e;i++)t|=Shl64(1,(UINT8)i);
+ if(Bar->Type!= tBarMmio64pf && Bar->Type!=tBarMmio64) t&=0xFFFFFFFF;
+ Bar->Gran=t;
+ break;
+
+ case icBarFixedSize:
+ Bar->Length=bbp->BarLength;
+ Bar->Gran=bbp->BarLength-1;
+ break;
+
+ case icNotBar :
+ Bar->Type=tBarUnused;
+ Bar->Length=0;
+ Bar->Gran=0;
+ break;
+
+ case icBad64BitBar :
+ if(Bar->Type == tBarMmio64pf) Bar->Type=tBarMmio32pf;
+ else if (Bar->Type == tBarMmio64) Bar->Type=tBarMmio32;
+ break;
+ }//switch
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: OptionRom()
+//
+// Description: This function will detect PCI Option ROMs BAR requirements.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS OptionRom(PCI_DEV_INFO *Device)
+{
+ PCI_CFG_ADDR devaddr;
+ EFI_STATUS Status=0;
+ UINT32 b32;
+ PCI_BAR *rombar;
+//---------------------------------
+ //Our Device still in disable decoding mode which it entered in
+ //Now Query Expansion ROM reg
+ // the bit0 is 0 to prevent the enabling of the Rom address decoder
+ devaddr.ADDR=Device->Address.ADDR;
+ switch (Device->Type){
+ case tPci2PciBrg : devaddr.Addr.Register=PCI_P2P_ROM_BAR;
+ break;
+ case tPciDevice :
+ case tPciHostDev :
+ devaddr.Addr.Register=PCI_DEV_ROM_BAR;
+ break;
+ case tPci2CrdBrg : //this one doesnot have ROM BAR
+ default : return EFI_SUCCESS; //other devices not suppose to be examined
+ }
+
+ rombar=&Device->Bar[PCI_MAX_BAR_NO];
+ rombar->Offset=devaddr.Addr.Register;
+
+ b32=0xFFFFFFFE;
+
+ //Write query pattern to PCI Rom Bar Register
+ Status=PciCfg32(Device->RbIo,devaddr,TRUE,&b32);
+ if(EFI_ERROR (Status)) return Status;
+
+ Status=PciCfg32(Device->RbIo,devaddr,FALSE,&b32);
+ if(EFI_ERROR (Status)) return Status;
+
+ b32&=0xFFFFFFFE;
+ if ((b32 != 0) && (b32 != 0xFFFFFFFE)){
+ rombar->Type=tBarMmio32;
+ rombar->Gran=~b32;
+ rombar->Length=(~b32)+1;
+ }
+
+ if(Device->Incompatible) AdjustBarGra(rombar);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetDeviceCapabilities()
+//
+// Description: This function will detect PCI Device Capabilities of the Device's
+// Command Cegister and Bridge Command register (if any).
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters are invalid.
+//
+// Referals: PCI_DEV_INFO.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetDeviceCapabilities(PCI_DEV_INFO *Dev)
+{
+ PCI_CFG_ADDR addr;
+ EFI_STATUS Status;
+ UINT16 oldcmd, tstcmd, oldbc, tstbc=0;
+ EFI_TPL OldTpl;
+ UINT8 z, tcls;
+//--------------------------------
+
+ if(Dev->ParentBrg)Dev->Capab=Dev->ParentBrg->Capab;
+
+ addr.ADDR=Dev->Address.ADDR;
+ tstcmd=(PCI_CMD_IO_SPACE | PCI_CMD_MEMORY_SPACE | PCI_CMD_MEMORY_WRITE_AND_INVALIDATE |
+ PCI_CMD_BUS_MASTER | PCI_CMD_VGA_PALETTE_SNOOP);
+
+ OldTpl=pBS->RaiseTPL(TPL_HIGH_LEVEL);
+
+ //Set Latency Timer to 20 and Cacheline size to 0 - just in case
+ addr.Addr.Register=0x0c;//Cacheline size & Latency Timer
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,&oldcmd);
+ //PciX devices upon reset initialize Latency Timer reg with value of 0x40
+ //regular PCI devices initialize it with 0
+ if(!(oldcmd&0xff00)){//so we will program it only for Regular PCI devices
+ oldcmd=0x2000;
+ Status=PciCfg16(Dev->RbIo,addr,TRUE,&oldcmd);
+ if(EFI_ERROR(Status))return Status;
+ }
+ addr.Addr.Register=0x04;//Command Reg
+
+ //Read initial value
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,&oldcmd);
+ if(EFI_ERROR(Status))return Status;
+
+ //Write cmdval there and see if it supports it;
+ Status=PciCfg16(Dev->RbIo,addr,TRUE,&tstcmd);
+ if(EFI_ERROR(Status))return Status;
+
+ //Read it back and see which bits remains set
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,&tstcmd);
+ if(EFI_ERROR(Status))return Status;
+
+ //Restore what was there
+ Status=PciCfg16(Dev->RbIo,addr,TRUE,&oldcmd);
+ if(EFI_ERROR(Status))return Status;
+
+ if(Dev->Type==tPci2PciBrg){
+ //Set Latency Timer to 20 and Cacheline size to 0 - just in case
+ addr.Addr.Register=0x1b;//Secondary Latency Timer
+ oldcmd=0x20;
+ Status=PciCfg8(Dev->RbIo,addr,TRUE,(UINT8*)&oldcmd);
+ if(EFI_ERROR(Status))return Status;
+
+ addr.Addr.Register=0x3E; //Bridge controll reg
+ tstbc=(P2P_BRG_CONTROL_ISA | P2P_BRG_CONTROL_VGA | P2P_BRG_CONTROL_VGA_16);
+
+ //Read initial value
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,&oldbc);
+ if(EFI_ERROR(Status))return Status;
+
+ //Write cmdval there and see if it supports it;
+ Status=PciCfg16(Dev->RbIo,addr,TRUE,&tstbc);
+ if(EFI_ERROR(Status))return Status;
+
+ //Read it back and see which bits remains set
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,&tstbc);
+ if(EFI_ERROR(Status))return Status;
+
+ //Restore what was there
+ Status=PciCfg16(Dev->RbIo,addr,TRUE,&oldbc);
+ if(EFI_ERROR(Status))return Status;
+ }
+
+ //Analize tstcmd Value and update Device->Capab;
+ if(tstcmd & PCI_CMD_IO_SPACE)Dev->Capab|=EFI_PCI_IO_ATTRIBUTE_IO;
+ else Dev->Capab&=(~EFI_PCI_IO_ATTRIBUTE_IO);
+
+ if(tstcmd & PCI_CMD_MEMORY_SPACE)Dev->Capab|=EFI_PCI_IO_ATTRIBUTE_MEMORY;
+ else Dev->Capab&=(~EFI_PCI_IO_ATTRIBUTE_MEMORY);
+
+ if(tstcmd & PCI_CMD_BUS_MASTER)Dev->Capab|=EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
+ else Dev->Capab&=(~EFI_PCI_IO_ATTRIBUTE_BUS_MASTER);
+
+ if(tstcmd & PCI_CMD_VGA_PALETTE_SNOOP)Dev->Capab|=EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+ else Dev->Capab&=(~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
+
+//BUG//BUG//BUG//BUG//BUG//BUG//BUG
+// This bits in cmd register does not identically maps to EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
+// if( (tstcmd & PCI_CMD_MEMORY_WRITE_AND_INVALIDATE)||(tstcmd & PCI_CMD_FAST_BACK_TO_BACK) )
+// Dev->Capab|= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
+
+ //Check Device Capability on CacheLine Size Register
+ Dev->Capab|=MY_PCI_IO_ATTRIBUTE_MEM_WR_INVALIDATE;
+ addr.Addr.Register=0x0c;//Cacheline size & Latency Timer
+
+ //probe Cache Line Size register if it will accept proposed Cache line size
+ tcls=0xFF;
+ Status=PciCfg8(Dev->RbIo,addr,TRUE,&tcls);
+ if(EFI_ERROR(Status))return Status;
+
+ //Read it back and see which bits remains set
+ Status=PciCfg8(Dev->RbIo,addr,FALSE,&z);
+ if(EFI_ERROR(Status))return Status;
+
+ tcls=gPciCaheLineSize;
+
+ //we have tested CLS register it will not accept any value we are proposing
+ if(!( z && (z&(tcls-1)) ))Dev->Capab&=(~MY_PCI_IO_ATTRIBUTE_MEM_WR_INVALIDATE);
+ else{
+ while(!(tcls&z)) tcls=tcls>>1; //same as div 2
+ if(tcls<gPciCaheLineSize) gPciCaheLineSize=tcls;
+ }
+ //clear the register we will program it later when resources will be allocated
+ tcls=0;
+ Status=PciCfg8(Dev->RbIo,addr,TRUE,&tcls);
+ if(EFI_ERROR(Status))return Status;
+
+ //we have additional work to do if Device is P2P bridge
+ if(Dev->Type==tPci2PciBrg){
+ if(tstbc & P2P_BRG_CONTROL_ISA)Dev->Capab|=EFI_PCI_IO_ATTRIBUTE_ISA_IO;
+ else Dev->Capab&=(~EFI_PCI_IO_ATTRIBUTE_ISA_IO);
+
+ if(tstbc & P2P_BRG_CONTROL_VGA)Dev->Capab|=( EFI_PCI_IO_ATTRIBUTE_VGA_IO |
+ EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY|EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
+ else Dev->Capab&=(~(EFI_PCI_IO_ATTRIBUTE_VGA_IO |
+ EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY|EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO));
+ if(tstbc & P2P_BRG_CONTROL_VGA_16) Dev->Capab|=( EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |
+ EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16);
+ else Dev->Capab&=(~(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16));
+
+ //bridge should support IDE attributes
+ Dev->Capab|=(EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO);
+ } else {
+ //Some special atributes could be supported by PCI devices based on class code
+ switch (Dev->Class.BaseClassCode){
+ case PCI_CL_OLD :
+ if (Dev->Class.SubClassCode==PCI_CL_OLD_SCL_VGA)
+ Dev->Capab|=(EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO);
+ else
+ Dev->Capab&=(~(EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO));
+ break;
+ case PCI_CL_DISPLAY:
+ if (Dev->Class.SubClassCode==PCI_CL_DISPLAY_SCL_VGA)
+ Dev->Capab|=(EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO);
+ else
+ Dev->Capab&=(~(EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO));
+
+ if (Dev->Class.SubClassCode==PCI_CL_DISPLAY_SCL_OTHER) //GFX device can snoop pallete
+ Dev->Capab|=EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+ else Dev->Capab&=(~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
+ break;
+ case PCI_CL_MASS_STOR :
+ if(Dev->Class.SubClassCode==PCI_CL_MASS_STOR_SCL_IDE){
+ UINT8 pib=Dev->Class.ProgInterface, pif=0;
+ //---------------
+ Dev->Capab|=(EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO|EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO);
+ //Now if device is IDE controller check PI on order determine how it was programmed
+ //Just in case overwrite bus master capab if IDE device sets bit 7 in PI Reg
+ if(Dev->Class.ProgInterface & 0x80) Dev->Capab|=EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
+
+ //primary Controller in LEGACY mode?
+ if( !(Dev->Class.ProgInterface & 0x01)){
+ if(Dev->HostData->PriIde==NULL){
+ //Set the current PCI Device attributes to LEGACY
+ Dev->Attrib|=EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
+ Dev->HostData->PriIde=Dev;
+ } else {
+ //set native mode bit since this Legacy IO space has been taken already
+ pif++;
+ pib |= 0x01;
+ }
+ }
+
+ //secondary Controller in LEGACY mode?
+ if( !(Dev->Class.ProgInterface & 0x04) ){
+ if(Dev->HostData->SecIde==NULL){
+ //Set the current PCI Device attributes to LEGACY
+ Dev->Attrib|=EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
+ Dev->HostData->SecIde=Dev;
+ } else {
+ //set native mode bit since this Legacy IO space has been taken already
+ pif++;
+ pib |= 0x04;
+ }
+ }
+ if(pif){
+ Status=SetIdeDevMode(Dev, 0,0, &pib);
+ if(!EFI_ERROR(Status)) Dev->Class.ProgInterface = pib;
+ }
+ } else Dev->Capab&=(~(EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO|EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO));
+
+ break;
+ }//switch;
+ }
+
+ //device caps should not exsceed parent;
+ if(Dev->Capab & EFI_PCI_IO_ATTRIBUTE_IO)
+ Dev->Capab|=(EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO);
+ else
+ Dev->Capab&=(~(EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO));
+
+ pBS->RestoreTPL(OldTpl);
+ PCI_TRACE((TRACE_PCI, "Supported Attributes -> 0x%lX\n", Dev->Capab));
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindFirstBit(UINT64 Value, BOOLEAN Set, BOOLEAN Right2Left)
+//
+// Description: This function will find first bit Set or Reset
+// going Left to Right.
+//
+// Input:
+// UINT64 Value Value to scan.
+// BOOLEAN Set What condition to test
+// Output:
+// UINT8 First bit set/reset
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8 FindFirstBit(UINT64 Value, BOOLEAN Set){
+ UINT64 msk=1, iv=~Value;
+ UINT8 bit;
+//---------------------
+ for(bit=0;bit<64;bit++){
+ msk=Shl64(1,bit);
+ if(Set) {
+ if( (Value & msk) == msk ) break;
+ } else {
+ if(( iv & msk ) == msk ) break;
+ }
+ }
+ if(bit==64) bit=0xFF;
+ return bit;
+}
+
+///////////////////////////////////////////////////////////////
+// Capability pointers operation Including PCI Express...
+///////////////////////////////////////////////////////////////
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetPciCapPtrs()
+//
+// Description: This function will collect information about PCI "Device"
+// Capability Headers (Including PCI Express, Hot Plug and PCI-X/X2) and
+// record them.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When Device not present in the system.
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When some of the parameters - invalid.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetPciCapPtrs(PCI_DEV_INFO *Device)
+{
+ PCI_CFG_ADDR devaddr;
+ EFI_STATUS Status=0;
+ EFI_PCI_CAPABILITY_HDR cp;
+ UINT16 sr;
+//-------------------------------
+ devaddr.ADDR=Device->Address.ADDR;
+ devaddr.Addr.Register=0x06; //Status Register;
+ //bit 4 in status register is set if device supports capabilities pointer
+ Status=PciCfg16(Device->RbIo,devaddr,FALSE,&sr);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ if(!(sr&0x10)) return Status; //no reason to continue - capabilities is not supported!
+
+ //if device Supports Capabilityes
+ cp.CAP_HDR=0;
+ if(Device->Type==tPci2CrdBrg) devaddr.Addr.Register=EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR;
+ else devaddr.Addr.Register=EFI_PCI_CAPABILITY_PTR;
+
+ Status=PciCfg8(Device->RbIo,devaddr,FALSE,&cp.NextItemPtr);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //we got something here.
+ while(cp.NextItemPtr)
+ {
+ devaddr.Addr.Register=cp.NextItemPtr;
+
+ Status=PciCfg16(Device->RbIo,devaddr,FALSE,&cp.CAP_HDR);
+ ASSERT_EFI_ERROR(Status);
+ if(cp.CapabilityID==PCI_CAP_ID_PMI) Device->PmiCapOffs=devaddr.Addr.Register;
+
+//Enables PCI Express Handling only if PCI Express Base is Defined and !=0
+#if PCI_EXPRESS_SUPPORT
+
+ if(cp.CapabilityID==PCI_CAP_ID_PCIEXP){
+ Device->PciExpress=MallocZ(sizeof(PCIE_DATA));
+ ASSERT(Device->PciExpress);
+ if(!Device->PciExpress) return EFI_OUT_OF_RESOURCES;
+
+ //Save Current Offset of PCIE Std Compatibility Registers Block
+ Device->PciExpress->PcieOffs=devaddr.Addr.Register;
+ Device->PciExpress->Owner=Device;
+ }
+#endif
+
+#if HOTPLUG_SUPPORT
+ if(cp.CapabilityID==PCI_CAP_ID_HOTPLUG){
+ //we may process this controller as root HPC so check that.
+ if(!Device->HotPlug){
+ Device->HotPlug=MallocZ(sizeof(PCI_HPC_INFO));
+ ASSERT(Device->HotPlug);
+ if(!Device->HotPlug) return EFI_OUT_OF_RESOURCES;
+
+ //Save Current Offset of PCIE Std Compatibility Registers Block
+ Device->HotPlug->HpcLocation->HpcDevicePath=Device->DevicePath;
+ Device->HotPlug->HpcLocation->HpcDevicePath=Device->DevicePath;
+ Device->HotPlug->HpcPciAddr.ADDR=Device->Address.ADDR;
+ Device->HotPlug->HpbBridge=Device;
+ Device->HotPlug->BusFound=TRUE;
+ //For SHPC it must be initialized and enabled by hardware
+ Device->HotPlug->HpcState=EFI_HPC_STATE_INITIALIZED|EFI_HPC_STATE_ENABLED;
+ Device->HotPlug->HpcOffs=devaddr.Addr.Register;
+ Device->HotPlug->Owner=Device;
+ }
+ }
+#endif
+
+//this is for feautufe use if we will support BootTime hotplug events
+#if PCI_X_SUPPORT
+ if(cp.CapabilityID==PCI_CAP_ID_PCIX){
+
+ Device->PciX=MallocZ(sizeof(PCIX_DATA));
+ ASSERT(Device->PciX);
+ if(!Device->PciX) return EFI_OUT_OF_RESOURCES;
+
+ //fill out fields within PciX structure
+ devaddr.Addr.Register=Device->PciX->PcixOffs+PCIX_DEV_STA_OFFSET;
+ Status=PciCfg32(Device->RbIo, devaddr, FALSE, &Device->PciX->PcixDevStatus.DEV_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ devaddr.Addr.Register=Device->PciX->PcixOffs+PCIX_SEC_STA_OFFSET;
+ Status=PciCfg16(Device->RbIo, devaddr, FALSE, &Device->PciX->PcixSecStatus.SEC_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ Device->PciX->PcixOffs=devaddr.Addr.Register;
+ Device->PciX->Owner=Device;
+
+ }
+#endif
+ }
+ return Status;
+}
+
+//----------------------------------------------------------------------------
+//Enable PCI Express Handling only if PCI Express Base is Defined and !=0
+#if PCI_EXPRESS_SUPPORT
+//////////////////////////////////////////////////////////////////////////////
+//----------------------------------------------------------------------------
+// PCI Express Helper Functions
+//----------------------------------------------------------------------------
+//////////////////////////////////////////////////////////////////////////////
+EFI_STATUS PcieDoubleCheckCard(PCI_DEV_INFO *Brg, PCI_CFG_ADDR *DevAddr, UINT32 *VenDevId){
+ EFI_STATUS Status;
+ PCI_CFG_ADDR addr;
+ PCIE_SLT_STA_REG slts;
+// PCIE_LNK_STA_REG lnks;
+// PCIE_DEV_STA_REG devs;
+//------------------------
+
+
+ //Read PCIe.DEV_STA_REG;
+ addr.ADDR=Brg->Address.ADDR;
+/*
+ addr.Addr.Register=Brg->PciExpress->PcieOffs+PCIE_DEV_STA_OFFSET;
+ Status=PciCfg16(Brg->RbIo, addr, FALSE, &devs.DEV_STA);
+ ASSERT_EFI_ERROR(Status);
+
+ //Read PCIe.LNK_STA_REG;
+ addr.Addr.Register=Brg->PciExpress->PcieOffs+PCIE_LNK_STA_OFFSET;
+ Status=PciCfg16(Brg->RbIo, addr, FALSE, &lnks.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+*/
+ //Read PCIe.SLT_STA_REG;
+ addr.Addr.Register=Brg->PciExpress->PcieOffs+PCIE_SLT_STA_OFFSET;
+ Status=PciCfg16(Brg->RbIo, addr, FALSE, &slts.SLT_STA);
+ ASSERT_EFI_ERROR(Status);
+
+/*
+ TRACE((-1, "\n!!!!!!DEV_STA[ 0x%X ].TrasactPend(5)=%d;\n",devs.DEV_STA, devs.TrasactPend));
+ TRACE((-1, "!!!!!!LNK_STA[0x%X].LnkTraining(11)=%d;\n",lnks.LNK_STA, lnks.LnkTraining));
+ TRACE((-1, "!!!!!!SLT_STA[%X].CardPresent(6)=%d;\n",slts.SLT_STA, slts.CardPresent));
+ TRACE((-1, "!!!!!!for the BRIDGE @ [B%X|D%X|F%X];\n",Brg->Address.Addr.Bus,Brg->Address.Addr.Device, Brg->Address.Addr.Function));
+ TRACE((-1, "!!!!!!VID/DID=%X of [B%X|D0|F0]\n",*VenDevId, addr.Addr.Bus));
+*/
+
+ //if we are here that means card did not come up first time...
+ //so try to read it one more time, before taking some invasive actions.
+ addr.ADDR = DevAddr->ADDR;
+ addr.Addr.Register=0;
+
+ //SOMETHING present there, but need some time to completely come up
+ if(slts.CardPresent != 0 || slts.PresenceDet !=0 ){
+ UINTN i;
+ //---------
+ for(i=0; i<=gPciSetupData->LnkTrRetry; i++){
+
+ Status=PciCfg32(Brg->RbIo, addr, FALSE, VenDevId);
+ ASSERT_EFI_ERROR(Status);
+ if( (*VenDevId) != 0xFFFFFFFF ) break;
+
+ //Use same setup value for retry timeut and number
+ pBS->Stall(gPciSetupData->LnkTrTimeout*100);
+ }
+// TRACE((-1, "!!!!!!VID/DID=%X after %d retry (timeout=%d) \n",*VenDevId, i+1, gPciSetupData->LnkTrTimeout*100));
+ }
+
+ //If nothing workeded just exit...
+ return Status;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//Exclude support fot PCIe GEN2 to save space in projects w/o PCIE_GEN2
+#if PCI_EXPRESS_GEN2_SUPPORT
+
+
+///////////////////////////////////////////////////////////////////////////////
+//Exclude support fot PCIe GEN3 to save space in projects w/o PCIE_GEN3
+#if PCI_EXPRESS_GEN3_SUPPORT //GEN3 support is a subset of GEN2 support!!!
+
+EFI_STATUS Pcie3EqualizeLink(PCI_DEV_INFO *Device, BOOLEAN *LnkRetrain){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_CFG_ADDR addr;
+ PCIE_LNK_CNT3_REG LnkCnt3;
+ PCIE_LNK_STA2_REG LnkSta2;
+//-----------------------------
+
+ //If device don't have GEN 3 Cap Hdr, or link is operating on lell then 8.0 GT/s speed - just exit...
+ if(Device->PciExpress->Pcie3==NULL) return EFI_SUCCESS;
+
+ //Get LNK_STA2 regiser
+ addr.ADDR=Device->Address.ADDR;
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_STA2_OFFSET;
+ Status=PciCfg16(Device->RbIo, addr, FALSE,&LnkSta2.LNK_STA2);
+ ASSERT_EFI_ERROR(Status);
+
+ //Display Content of the LNK_STA2 register.
+ PCI_TRACE((TRACE_PCI," LNK_STA2-> [R=%X|EqReq=%X|EqP3=%X|EqP2=%X|EqP1=%X|EqCompl=%X|SelDeEmp=%X]\n",
+ LnkSta2.Reserved,
+ LnkSta2.EqRequest,
+ LnkSta2.EqPhase3Ok,
+ LnkSta2.EqPhase2Ok,
+ LnkSta2.EqPhase1Ok,
+ LnkSta2.EqComplete,
+ LnkSta2.SelDeEmphasis));
+
+ //Check if equalization was requested or we are about to enter lLNK training session...
+ if(LnkSta2.EqRequest || *LnkRetrain){
+
+ PCI_TRACE((TRACE_PCI," PciE3: Equalization for Device @ [B%X|D%X|F%X] LnkRetrain=%X Before\n",
+ addr.Addr.Bus,addr.Addr.Device,addr.Addr.Function, *LnkRetrain));
+ //read Lnk Control 3 register in Sec PCIe Ext Cap Header.
+ addr.Addr.ExtendedRegister=Device->PciExpress->Pcie3->SecPcieCapOffs+PCIE_LNK_CNT3_OFFSET;
+ Status=PciCfg32(Device->RbIo, addr, FALSE,&LnkCnt3.LNK_CNT3);
+ ASSERT_EFI_ERROR(Status);
+
+ //Set Prform Equalization bit and disable Equalization Request Interrupt, just in case.
+ LnkCnt3.LnkEqReqIntEn=0;
+ LnkCnt3.PerformEqualiz=1;
+
+ //Write it back into LNK_CNT3 register.
+ Status=PciCfg32(Device->RbIo, addr, TRUE, &LnkCnt3.LNK_CNT3);
+ ASSERT_EFI_ERROR(Status);
+
+ *LnkRetrain=TRUE;
+
+ //Display Content of the LNK_CNT3 register.
+ PCI_TRACE((TRACE_PCI," LNK_CNT3-> [R=%X|LnkEqReqIntEn=%X|DoEq=%X] LnkRetrain=%X After\n",
+ LnkCnt3.Reserved,
+ LnkCnt3.LnkEqReqIntEn,
+ LnkCnt3.PerformEqualiz,
+ *LnkRetrain));
+
+ }
+ return Status;
+}
+
+
+EFI_STATUS Pcie3GetEqualizationStatus(PCI_DEV_INFO *Device){
+ PCI_CFG_ADDR addr;
+ PCIE_LNK_STA2_REG LnkSta2;
+ EFI_STATUS Status=EFI_SUCCESS;
+//-----------------------------
+
+ //If device don't have GEN 3 Cap Hdr, or link is operating on lell then 8.0 GT/s speed - just exit...
+ if(Device->PciExpress->Pcie3==NULL) return EFI_SUCCESS;
+
+ //Get LNK_STA2 regiser
+ addr.ADDR=Device->Address.ADDR;
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_STA2_OFFSET;
+ Status=PciCfg16(Device->RbIo, addr, FALSE,&LnkSta2.LNK_STA2);
+ ASSERT_EFI_ERROR(Status);
+
+ //Display Content of the LNK_STA2 register.
+ PCI_TRACE((TRACE_PCI,"Pcie3-> Checking Equalization Status...\n LNK_STA2-> [R=%X|EqReq=%X|EqP3=%X|EqP2=%X|EqP1=%X|EqCompl=%X|SelDeEmp=%X]\n",
+ LnkSta2.Reserved,
+ LnkSta2.EqRequest,
+ LnkSta2.EqPhase3Ok,
+ LnkSta2.EqPhase2Ok,
+ LnkSta2.EqPhase1Ok,
+ LnkSta2.EqComplete,
+ LnkSta2.SelDeEmphasis));
+
+ //Check equalization sesults...
+ if (LnkSta2.EqComplete) return EFI_SUCCESS;
+
+ //Check if any of the equalization phases were completed...
+ if(LnkSta2.LNK_STA2 & 0x1C) return EFI_NOT_AVAILABLE_YET;
+
+ return EFI_DEVICE_ERROR;
+}
+
+#endif //GEN3
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Pcie2GetGen2Info()
+//
+// Description: This function will collect information about PCIE GEN2 Device
+// and initialize PCIE2_DATA structure based on information collected.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Pcie2GetGen2Info(PCI_DEV_INFO *Device){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_CFG_ADDR addr;
+//-----------------------------
+ addr.ADDR=Device->Address.ADDR;
+ //PCI_TRACE((TRACE_PCI," PciE2: Device @ [B%X|D%X|F%X] is PCIE GEN2 Device:\n",
+ // addr.Addr.Bus,addr.Addr.Device,addr.Addr.Function));
+
+ //Get PCI Express Device CAP2 - 32 bit
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_DEV_CAP2_OFFSET;
+ Status=PciCfg32(Device->RbIo, addr, FALSE,&Device->PciExpress->Pcie2->DeviceCap2.DEV_CAP2);
+ ASSERT_EFI_ERROR(Status);
+
+ PCI_TRACE((TRACE_PCI," DEV_CAP2-> [R2=%X|MEEP=%X|EETP=%X|EFF=%X|R1=%X|TPH=%X|LTR=%X|NRP=%X|C128=%X|AtC64=%X|AtC32=%X|AtR=%X|Ari=%d|CTD=%X|CmTO=%X]\n",
+ Device->PciExpress->Pcie2->DeviceCap2.Reserved2,
+ Device->PciExpress->Pcie2->DeviceCap2.MaxEndEndPrefix,
+ Device->PciExpress->Pcie2->DeviceCap2.EndEndTlpPrefix,
+ Device->PciExpress->Pcie2->DeviceCap2.ExtFmtField,
+ Device->PciExpress->Pcie2->DeviceCap2.Reserved1,
+ Device->PciExpress->Pcie2->DeviceCap2.TphCompleter,
+ Device->PciExpress->Pcie2->DeviceCap2.LtrMechanism,
+ Device->PciExpress->Pcie2->DeviceCap2.NoRoPrPrPassing,
+ Device->PciExpress->Pcie2->DeviceCap2.Cas128Completer,
+ Device->PciExpress->Pcie2->DeviceCap2.AtomicOpCompl64,
+ Device->PciExpress->Pcie2->DeviceCap2.AtomicOpCompl32,
+ Device->PciExpress->Pcie2->DeviceCap2.AtomicOpRouting,
+ Device->PciExpress->Pcie2->DeviceCap2.AriForwarding,
+ Device->PciExpress->Pcie2->DeviceCap2.ComplToutDisable,
+ Device->PciExpress->Pcie2->DeviceCap2.ComplToutRanges));
+
+ //Get PCI Express Link CAP2 - 32 bit
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_CAP2_OFFSET;
+ Status=PciCfg32(Device->RbIo, addr, FALSE,&Device->PciExpress->Pcie2->LinkCap2.LNK_CAP2);
+ ASSERT_EFI_ERROR(Status);
+
+ if(Device->PciExpress->PcieCap.SlotImpl){
+ //Get PCI Express Link SLOT2 - 32 bit
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_SLT_CAP2_OFFSET;
+ Status=PciCfg32(Device->RbIo, addr, FALSE,&Device->PciExpress->Pcie2->SlotCap2.SLT_CAP2);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+#if PCI_EXPRESS_GEN3_SUPPORT
+ //Do some additional checks if device has GEN 3 Secondary PCIe Cap Header.
+ //At that point if we have discovered Sec PCIe Cap HDR Defice->PciExpress->Pcie3 must be initializad.
+ if(Device->PciExpress->Pcie3 != NULL){
+
+
+ //Update Speed encoding it is defined differently for devices Supporting V3.0 spec.
+
+ Device->PciExpress->Pcie3->MaxLanesCount=Device->PciExpress->LinkCap.MaxLnkWidth;
+
+ //Display first LNK_CAP2_REG
+ PCI_TRACE((TRACE_PCI,"PCIe3 -> Device is PCIe v3.0 Compliant!!! LNK_CAP2 present!!! \n LNK_CAP2-> [R2=%X|CrossL=%X|SuppLnkSpeedVect=%X|R1=%X]; LANE_ERR_STA->[%X]; MaxLanes=%X\n",
+ Device->PciExpress->Pcie2->LinkCap2.Reserved2,
+ Device->PciExpress->Pcie2->LinkCap2.CrossLnk,
+ Device->PciExpress->Pcie2->LinkCap2.SuppLnkSpeeds,
+ Device->PciExpress->Pcie2->LinkCap2.Reserved1,
+ Device->PciExpress->Pcie3->LaneErrSts,
+ Device->PciExpress->Pcie3->MaxLanesCount));
+
+ }
+#endif
+
+ Device->PciExpress->Pcie2->Owner=Device;
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Pcie2EnableAri()
+//
+// Description: This function will Enable ARI Forwarding in DownSream Port of
+// the device passed if
+// 1.Device referenced is an ARI device;
+// 2.Parenting Bridge supports ARI Forwarding.
+// 3.ARI Firvarding Setup Question Set to "Enabled"
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_UNSUPPORTED When Device or Parenting Bridge does not support ARI
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Pcie2EnableAri(PCI_DEV_INFO *Device){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_DEV_INFO *brg;
+ PCI_CFG_ADDR addr;
+ PCIE_DEV_CNT2_REG dcnt2;
+//-----------------------------------
+ //Setup Don't have it enabled
+ if(gPciSetupData->AriFwd == 0) {
+ PCI_TRACE((TRACE_PCI," -> Setup=%d", gPciSetupData->AriFwd));
+ return EFI_UNSUPPORTED;
+ }
+
+ if(Device->Type != tPciDevice) {
+ PCI_TRACE((TRACE_PCI," -> not tDevice Type", gPciSetupData->AriFwd));
+ return EFI_UNSUPPORTED;
+ }
+
+ if(Device->PciExpress == NULL) {
+ PCI_TRACE((TRACE_PCI," -> not PCIe Device", gPciSetupData->AriFwd));
+ return EFI_UNSUPPORTED;
+ }
+
+ //Device don't have ARI Ext Cap
+ if(Device->PciExpress->AriData==NULL){
+ PCI_TRACE((TRACE_PCI," -> non-ARI Device"));
+ return EFI_UNSUPPORTED;
+ }
+ //If we are here - device is an ARI Device. Now check if Parenting Bridge can do it...
+ brg=Device->ParentBrg;
+ //Check if Parenting Brg is Gen 2 device
+ if(brg->PciExpress->Pcie2==NULL){
+ PCI_TRACE((TRACE_PCI," -> ParentBrg non-GEN2"));
+ return EFI_UNSUPPORTED;
+ }
+
+ //Check if bridge can do ARI Forvarding
+ if(brg->PciExpress->Pcie2->DeviceCap2.AriForwarding==0){
+ PCI_TRACE((TRACE_PCI," -> ParentBrg.Cap.AriFwd=0"));
+ return EFI_UNSUPPORTED;
+ }
+
+ //Now check if this bridge has ARI Forwarding Enabled allready
+ if(brg->PciExpress->Pcie2->AriEnabled==TRUE){
+ //Set Device ARI Falg
+ Device->PciExpress->Pcie2->AriEnabled=brg->PciExpress->Pcie2->AriEnabled;
+ PCI_TRACE((TRACE_PCI," -> Parent Bridge AriEnabled=1"));
+ return EFI_SUCCESS;
+ }
+
+ //At that Point we must enable ARI.
+ addr.ADDR=brg->Address.ADDR;
+ addr.Addr.Register=brg->PciExpress->PcieOffs+PCIE_DEV_CNT2_OFFSET;
+ Status=PciCfg16(brg->RbIo, addr, FALSE,&dcnt2.DEV_CNT2);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+
+ dcnt2.AriForwarding=TRUE;
+ PCI_TRACE((TRACE_PCI," ARI -> Enabling ARI for Parent Bridge!"));
+ Status=PciCfg16(Device->RbIo, addr, TRUE,&dcnt2.DEV_CNT2);
+ ASSERT_EFI_ERROR(Status);
+
+
+ if(EFI_ERROR(Status)) return Status;
+
+ Device->PciExpress->Pcie2->AriEnabled=(BOOLEAN)dcnt2.AriForwarding;
+ brg->PciExpress->Pcie2->AriEnabled=(BOOLEAN)dcnt2.AriForwarding;
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Pcie2CheckAri()
+//
+// Description: This function will Enable ARI Forwarding in DownSream Port of
+// the device passed if
+// 1.Device referenced is an ARI device;
+// 2.Parenting Bridge supports ARI Forwarding.
+// 3.ARI Firvarding Setup Question Set to "Enabled"
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+// BOOLEAN *MultiFunc Pointer to a Flag to modify if Device is MF Device
+// BOOLEAN *AriEnabled Pointer to a Flag to modify if this function was able to ENABLE ARI.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Pcie2CheckAri(PCI_DEV_INFO *Device, BOOLEAN *MultiFunc, BOOLEAN *AriEnabled){
+ EFI_STATUS Status;
+//--------------------
+ PCI_TRACE((TRACE_PCI," PciE2: Checking ARI @ [B%X|D%X|F%X]:",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device,Device->Address.Addr.Function));
+
+ Status=Pcie2EnableAri(Device);
+ PCI_TRACE((TRACE_PCI," Status=%r\n",Status));
+
+ if((!EFI_ERROR(Status)) &&
+ (Device->PciExpress->AriData!=NULL) &&
+ (Device->PciExpress->Pcie2->AriEnabled==TRUE))
+ {
+ *MultiFunc=TRUE;
+ *AriEnabled=TRUE;
+ } else {
+ if(Status==EFI_UNSUPPORTED){
+ *AriEnabled=FALSE;
+ Status=EFI_SUCCESS;
+ }
+ }
+
+ //PCI_TRACE((TRACE_PCI," AriEn=%d %r\n\n",*AriEnabled, Status));
+
+ return Status;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Pcie2SetLnkProperties()
+//
+// Description: This function will Select values for Link Control2 register on
+// both sides of the LINK based on Setup Settings and hardware capabilities.
+//
+// Input:
+// PCI_DEV_INFO *DnStreamPort Pointer to PCI Device Private Data of Downstream Port of the link.
+// PCIE_LNK_CNT2_REG *DnLnkCnt2 Pointer to the LNK_CNT2 Reg of the Downstream Port of the link.
+// PCI_DEV_INFO *UpStreamPort Pointer to PCI Device Private Data of Upwnstream Port of the link.
+// PCIE_LNK_CNT2_REG *UpLnkCnt2 Pointer to the LNK_CNT2 Reg of the Downstream Port of the link.
+// BOOLEAN *LinkHotResetRequired Flag to modify if Link will need HOT RESET after programming.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Pcie2SetLnkProperties(PCI_DEV_INFO *DnStreamPort,
+ PCIE_LNK_CNT2_REG *DnLnkCnt2,
+ PCI_DEV_INFO *UpStreamPort,
+ PCIE_LNK_CNT2_REG *UpLnkCnt2,
+ BOOLEAN *LinkHotResetRequired,
+ BOOLEAN *LinkRetrainRequired )
+{
+ EFI_STATUS Status;
+ PCIE_LNK_STA_REG dnls, upls; //link status reg content of up and down side of the link
+ PCI_CFG_ADDR addr;
+ UINT16 ls, maxls, curls;//link speed variables
+//------------------------------
+
+ PCI_TRACE((TRACE_PCI,"PciE2: Pcie2SetLnkProperties() ENTRY:\n"));
+
+ //Get DownStream Port Properties
+ addr.ADDR=DnStreamPort->Address.ADDR;
+
+ PCI_TRACE((TRACE_PCI," DN STREAM PORT -> [B%X|D%X|F%X] <--> [B%X|D%X|F%X] <- UP STREAM PORT\n",
+ DnStreamPort->Address.Addr.Bus,DnStreamPort->Address.Addr.Device, DnStreamPort->Address.Addr.Function,
+ UpStreamPort->Address.Addr.Bus,UpStreamPort->Address.Addr.Device, UpStreamPort->Address.Addr.Function));
+
+ addr.Addr.Register=DnStreamPort->PciExpress->PcieOffs+PCIE_LNK_CNT2_OFFSET;
+ Status=PciCfg16(DnStreamPort->RbIo,addr,FALSE, &DnLnkCnt2->LNK_CNT2);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ PCI_TRACE((TRACE_PCI," LNK_CNT2-> [CmDe=%X|CmSOS=%X|ECm=%X|TrM=%X|SlDe=%X|AuSp=%X|EnCm=%X|TLS=%X]\n",
+ DnLnkCnt2->ComplDeEmphasis,
+ DnLnkCnt2->ComplianceSos,
+ DnLnkCnt2->EnterModCompl,
+ DnLnkCnt2->TrsMargin,
+ DnLnkCnt2->SelDeEmphasis,
+ DnLnkCnt2->HwAutoSpeedDis,
+ DnLnkCnt2->EnterCompliance,
+ DnLnkCnt2->TargetLnkSpeed));
+
+
+ addr.Addr.Register=DnStreamPort->PciExpress->PcieOffs+PCIE_LNK_STA_OFFSET;
+ Status=PciCfg16(DnStreamPort->RbIo,addr,FALSE, &dnls.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Get UpStream Stream Port Properties
+ addr.ADDR=UpStreamPort->Address.ADDR;
+
+ //PCI_TRACE((TRACE_PCI," UP STREAM PORT @ [B%X|D%X|F%X]:\n",
+ // addr.Addr.Bus,addr.Addr.Device, addr.Addr.Function));
+
+ addr.Addr.Register=UpStreamPort->PciExpress->PcieOffs+PCIE_LNK_CNT2_OFFSET;
+ Status=PciCfg16(UpStreamPort->RbIo,addr,FALSE, &UpLnkCnt2->LNK_CNT2);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ PCI_TRACE((TRACE_PCI," LNK_CNT2-> [CmDe=%X|CmSOS=%X|ECm=%X|TrM=%X|SlDe=%X|AuSp=%X|EnCm=%X|TLS=%X]\n ....... UPDATINNG .......\n",
+ UpLnkCnt2->ComplDeEmphasis,
+ UpLnkCnt2->ComplianceSos,
+ UpLnkCnt2->EnterModCompl,
+ UpLnkCnt2->TrsMargin,
+ UpLnkCnt2->SelDeEmphasis,
+ UpLnkCnt2->HwAutoSpeedDis,
+ UpLnkCnt2->EnterCompliance,
+ UpLnkCnt2->TargetLnkSpeed));
+
+ //Get Lnk Status Content...
+ addr.Addr.Register=UpStreamPort->PciExpress->PcieOffs+PCIE_LNK_STA_OFFSET;
+ Status=PciCfg16(UpStreamPort->RbIo,addr,FALSE, &upls.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+
+ //Check link Speed selected in Setup and calculate applcable Link speed...
+ //get max possible link speed
+ maxls=DnStreamPort->PciExpress->LinkCap.MaxLnkSpeed;
+ if(maxls>UpStreamPort->PciExpress->LinkCap.MaxLnkSpeed) maxls=UpStreamPort->PciExpress->LinkCap.MaxLnkSpeed;
+
+ //get the current speed of the link...
+ curls=DnStreamPort->PciExpress->CurrLnkSpeed;
+ //must be the same on both sides of the link
+ ASSERT(curls==UpStreamPort->PciExpress->CurrLnkSpeed);
+
+ if(maxls>=PCIE_LINK_SPEED_80G){
+ if(DnStreamPort->PciExpress->Pcie3==NULL || UpStreamPort->PciExpress->Pcie3==NULL)
+ maxls=PCIE_LINK_SPEED_50G;
+ }
+
+ //Check Link Speed setup options...
+ //AUTO==55
+ ls=curls;
+ if(gPciSetupData->LnkSpeed==55)ls=maxls;
+
+ //Force 5.0GT/s == 2
+ if(gPciSetupData->LnkSpeed==2){
+ //check if it is supported
+ if(DnStreamPort->PciExpress->Pcie2->LinkCap2.SuppLnkSpeeds!=0){
+ //if device is compatible with V3.0 spec it must report supported speeds
+ if(DnStreamPort->PciExpress->Pcie2->LinkCap2.SuppLnkSpeeds & PCIE_LINK_SPEED_VECT_50G) ls=PCIE_LINK_SPEED_50G;
+ } else {
+ //for devices compliand to spec v 2.1 check maxls value
+ if(maxls>=PCIE_LINK_SPEED_50G) ls=PCIE_LINK_SPEED_50G;
+ }
+ }
+
+ //Force 2.5GT/s == 1
+ if(gPciSetupData->LnkSpeed==1){
+ //check if it is supported
+ if(DnStreamPort->PciExpress->Pcie2->LinkCap2.SuppLnkSpeeds!=0){
+ //if device is compatible with V3.0 spec it must report supported speeds
+ if(DnStreamPort->PciExpress->Pcie2->LinkCap2.SuppLnkSpeeds & PCIE_LINK_SPEED_VECT_25G)ls=PCIE_LINK_SPEED_25G;
+ } else {
+ //for devices compliand to spec v 2.1 check maxls value
+ if(maxls>=PCIE_LINK_SPEED_25G) ls=PCIE_LINK_SPEED_25G;
+ }
+ }
+
+ PCI_TRACE((TRACE_PCI," LNK SPEED SETTINGS: MaxLS=%X; CurrentLS=%X; SelectedLS=%X; Setup=%d\n",
+ maxls,curls,ls, gPciSetupData->LnkSpeed ));
+
+ //Call porting hook to override link speed settings.
+ Status=PciPortOemSetLnkSpeed(DnStreamPort, (UINT8*)&ls, (UINT8)DnStreamPort->PciExpress->Pcie2->LinkCap2.SuppLnkSpeeds);
+ //one more time for Upstreamport
+ Status=PciPortOemSetLnkSpeed(UpStreamPort, (UINT8*)&ls, (UINT8)UpStreamPort->PciExpress->Pcie2->LinkCap2.SuppLnkSpeeds);
+
+ //now check if curls different from ls
+ if(ls<curls){
+// DnLnkCnt2->EnterCompliance=TRUE;
+// UpLnkCnt2->EnterCompliance=TRUE;
+// *LinkHotResetRequired=TRUE;
+ *LinkRetrainRequired=TRUE;
+ }
+
+ if(ls>curls){
+ *LinkRetrainRequired=TRUE;
+// *LinkHotResetRequired=TRUE;
+ }
+
+ //Set selected speed on both sides of the link
+ DnLnkCnt2->TargetLnkSpeed=ls;
+ UpLnkCnt2->TargetLnkSpeed=ls;
+
+ //Check; HwAutoSpeedDis; HwAutoWidth settings
+ DnLnkCnt2->HwAutoSpeedDis=gPciSetupData->HwAutoSpeed;
+ UpLnkCnt2->HwAutoSpeedDis=gPciSetupData->HwAutoSpeed;
+
+ PCI_TRACE((TRACE_PCI," LNK_CNT2-> [CmDe=%X|CmSOS=%X|ECm=%X|TrM=%X|SlDe=%X|AuSp=%X|EnCm=%X|TLS=%X]\n",
+ DnLnkCnt2->ComplDeEmphasis,
+ DnLnkCnt2->ComplianceSos,
+ DnLnkCnt2->EnterModCompl,
+ DnLnkCnt2->TrsMargin,
+ DnLnkCnt2->SelDeEmphasis,
+ DnLnkCnt2->HwAutoSpeedDis,
+ DnLnkCnt2->EnterCompliance,
+ DnLnkCnt2->TargetLnkSpeed));
+
+ PCI_TRACE((TRACE_PCI," LNK_CNT2-> [CmDe=%X|CmSOS=%X|ECm=%X|TrM=%X|SlDe=%X|AuSp=%X|EnCm=%X|TLS=%X]\n\n",
+ UpLnkCnt2->ComplDeEmphasis,
+ UpLnkCnt2->ComplianceSos,
+ UpLnkCnt2->EnterModCompl,
+ UpLnkCnt2->TrsMargin,
+ UpLnkCnt2->SelDeEmphasis,
+ UpLnkCnt2->HwAutoSpeedDis,
+ UpLnkCnt2->EnterCompliance,
+ UpLnkCnt2->TargetLnkSpeed));
+
+
+#if PCI_EXPRESS_GEN3_SUPPORT
+ if(DnStreamPort->PciExpress->Pcie3!=NULL && UpStreamPort->PciExpress->Pcie3!=NULL){
+
+ if(ls >=PCIE_LINK_SPEED_80G) {
+ Status=Pcie3EqualizeLink(DnStreamPort, LinkRetrainRequired);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ //Equalize link must be set for Upstream Port if it has closslink
+ if(UpStreamPort->PciExpress->Pcie2->LinkCap2.CrossLnk){
+ Status=Pcie3EqualizeLink(UpStreamPort, LinkRetrainRequired);
+ ASSERT_EFI_ERROR(Status);
+ }
+ }
+ }
+#endif
+
+ return Status;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Pcie2SelectComplTimeOut()
+//
+// Description: This function will select appropriate Completion Timeout range
+// from supported by the device.
+//
+// Input:
+// UINT32 Support Supported by Device Completion Timeout ranges.
+// BOOLEAN Short A Flag to Indicate wahat type of ranges to select Biggest or Smallest
+//
+// Output: UINT16
+// Value to be programmed in DEV_CNT2 Register.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16 Pcie2SelectComplTimeOut(UINT32 Support, BOOLEAN Short){
+ //Completion Timeout Programability is not supported by HW.
+ if(Support==0) return 0;
+
+ if(Short){
+ //It is strongly recommended that the Completion Timeout
+ //mechanism not expire in less than 10 ms
+
+ //Values available if Range A (50 mks to 10 ms) programmability range is supported:
+ // 0001b 50 mks to 100 mks; 0010b; 1 ms to 10 ms
+ if(Support & PCIE_CAP2_RANGE_A) return 0x2;
+
+ //Values available if Range B (10 ms to 250 ms) programmability range is supported:
+ // 0101b 16 ms to 55 ms; 0110b 65 ms to 210 ms
+ if(Support & PCIE_CAP2_RANGE_B) return 0x5;
+
+ //Values available if Range C (250 ms to 4 s) programmability range is supported:
+ // 1001b 260 ms to 900 ms; 1010b 1 s to 3.5 s
+ if(Support & PCIE_CAP2_RANGE_C) return 0x9;
+
+ //Values available if the Range D (4 s to 64 s) programmability range is supported:
+ // 1101b 4 s to 13 s; 1110b 17 s to 64 s
+ if(Support & PCIE_CAP2_RANGE_D) return 0xD;
+
+ } else {
+ //Values available if the Range D (4 s to 64 s) programmability range is supported:
+ // 1101b 4 s to 13 s; 1110b 17 s to 64 s
+ if(Support & PCIE_CAP2_RANGE_D) return 0xE;
+
+ //Values available if Range C (250 ms to 4 s) programmability range is supported:
+ // 1001b 260 ms to 900 ms; 1010b 1 s to 3.5 s
+ if(Support & PCIE_CAP2_RANGE_C) return 0xA;
+
+ //Values available if Range B (10 ms to 250 ms) programmability range is supported:
+ // 0101b 16 ms to 55 ms; 0110b 65 ms to 210 ms
+ if(Support & PCIE_CAP2_RANGE_B) return 0x6;
+
+ //Values available if Range A (50 mks to 10 ms) programmability range is supported:
+ // 0001b 50 mks to 100 mks; 0010b; 1 ms to 10 ms
+ if(Support & PCIE_CAP2_RANGE_A) return 0x2;
+ }
+ return 0;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Pcie2SetDevProperties()
+//
+// Description: This function will Select values for DEVICE CCONTROL2 register
+// based on Setup Settings and hardware capabilities.
+//
+// Input:
+// PCI_DEV_INFO *DnStreamPort Pointer to PCI Device Private Data of Downstream Port of the link.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Pcie2SetDevProperties(PCI_DEV_INFO *Device){
+ EFI_STATUS Status;
+ PCI_CFG_ADDR addr;
+ PCIE_DEV_CNT2_REG dcnt2;
+//------------------------------
+
+ //Get Device Properties
+ addr.ADDR=Device->Address.ADDR;
+
+ PCI_TRACE((TRACE_PCI,"PciE2: Pcie2SetDevProperties() Device @ [B%X|D%X|F%X] ENTRY:\n",
+ addr.Addr.Bus,addr.Addr.Device, addr.Addr.Function));
+
+ if (Device->PciExpress == NULL)
+ return EFI_SUCCESS;
+
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_DEV_CNT2_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr, FALSE, &dcnt2.DEV_CNT2);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ PCI_TRACE((TRACE_PCI," DEV_CNT2-> [EEPrB=%X|R=%X|LTR=%X|IDOCm=%X|IDORq=%X|AtEgB=%X|AtRq=%X|ARI=%X|CToD=%X|CTo=%X]\n ....... UPDATINNG .......\n",
+ dcnt2.EndEndTlpBlk,
+ dcnt2.Reserved,
+ dcnt2.LtrEn,
+ dcnt2.IdoComplEn,
+ dcnt2.IdoRequestEn,
+ dcnt2.AtomicOpEgresBlk,
+ dcnt2.AtomicOpRequer,
+ dcnt2.AriForwarding,
+ dcnt2.ComplToutDisable,
+ dcnt2.ComplToutRanges));
+
+ //Now check setup settingds and apply it. But do't touch ARI Forwarding it was updated earlier.
+ dcnt2.EndEndTlpBlk=gPciSetupData->E2ETlpPrBlk;
+ dcnt2.LtrEn=gPciSetupData->LtrReport;
+ dcnt2.IdoComplEn=gPciSetupData->IDOCompl;
+ dcnt2.IdoRequestEn=gPciSetupData->IDOReq;
+ dcnt2.AtomicOpEgresBlk=gPciSetupData->AtomOpEgressBlk;
+ dcnt2.AtomicOpRequer=gPciSetupData->AtomOpReq;
+
+ //Now check what ompletion Timeout ranges to select?
+ dcnt2.ComplToutDisable=FALSE;
+ dcnt2.ComplToutRanges=0; //set to default
+
+ //In Setup 0=Disable;0x55=SHORT; 0xAA=LONG; 0xFF=DEFAULT
+ if(gPciSetupData->ComplTimeOut == 0) dcnt2.ComplToutDisable=TRUE;
+ else {
+ if(gPciSetupData->ComplTimeOut == 0xFF) dcnt2.ComplToutRanges=0;
+ else{
+ //use SHORT timeout srom supported ranges option.
+ if(gPciSetupData->ComplTimeOut == 0x55)
+ dcnt2.ComplToutRanges=Pcie2SelectComplTimeOut(Device->PciExpress->Pcie2->DeviceCap2.ComplToutRanges, TRUE);
+ //use LONG timeout srom supported ranges option.
+ else
+ dcnt2.ComplToutRanges=Pcie2SelectComplTimeOut(Device->PciExpress->Pcie2->DeviceCap2.ComplToutRanges, FALSE);
+ }
+ }
+
+
+ Status=PciCfg16(Device->RbIo,addr, TRUE, &dcnt2.DEV_CNT2);
+
+ PCI_TRACE((TRACE_PCI," DEV_CNT2-> [EEPrB=%X|R=%X|LTR=%X|IDOCm=%X|IDORq=%X|AtEgB=%X|AtRq=%X|ARI=%X|CToD=%X|CTo=%X]\n\n",
+ dcnt2.EndEndTlpBlk,
+ dcnt2.Reserved,
+ dcnt2.LtrEn,
+ dcnt2.IdoComplEn,
+ dcnt2.IdoRequestEn,
+ dcnt2.AtomicOpEgresBlk,
+ dcnt2.AtomicOpRequer,
+ dcnt2.AriForwarding,
+ dcnt2.ComplToutDisable,
+ dcnt2.ComplToutRanges));
+// PCI_TRACE((TRACE_PCI,"Status = %r.\n",Status));
+
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+
+
+
+
+
+
+
+
+
+#endif
+//GEN 2 Helper Functions END
+///////////////////////////////////////////////////////////////////////////////
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieUpdateClockPm()
+//
+// Description: This function will update Device's referenced as "Func0"
+// Clock Power Management based on Setup Settings and hardware capabilities.
+//
+// Input:
+// PCI_DEV_INFO *Func0 Pointer to PCI Device Private Data structure.
+// CNT_REG *LnkCnt Pointer to the Device's LNK_CNT register data.
+//
+// Output: NOTHING
+//
+// NOTE: Must be called only for PCI Express devices (Device->PciExpress!=NULL)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID PcieUpdateClockPm(PCI_DEV_INFO *Func0, PCIE_LNK_CNT_REG *LnkCnt){
+ UINTN i;
+ PCI_DEV_INFO *dev;
+//------------------------
+ //Check if Clock PM was set for F0 than we need not to scam caps of the other devices.
+ if(LnkCnt->ClockPm == FALSE) return;
+ //we will come here if we get a multifunction NON-ARI device and Device Points @ Function 0
+ //"LnkCnt" has parameters filled in calculated for Func0 of a MF device.
+ //Func0->DevFunc[] includes all other functions except Func 0;
+ for(i=0; i<Func0->FuncCount; i++){
+ dev=Func0->DevFunc[i];
+ //For a non-ARI multi-Function device, power-managementconfiguration
+ //software must only Set this bit if all Functions of
+ //the multi-Function device indicate a 1b in the Clock Power
+ //Management bit of the Link Capabilities register. The
+ //component is permitted to use the CLKREQ# signal to power
+ //manage Link clock only if this bit is Set for all Functions.
+
+ //For ARI Devices, Clock Power Management is enabled solely by
+ //the setting in Function 0. The settings in the other Functions
+ //always return whatever value software programmed for each,
+ //but otherwise are ignored by the component.
+ if(dev->PciExpress->LinkCap.ClockPm == FALSE) {
+ LnkCnt->ClockPm=FALSE;
+ return;
+ }
+ }
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieDisableLink()
+//
+// Description: This function will Disable Link of DNSTREAM port referenced as
+// "Device" based on Setup Settings and hardware STATUS. Used to disable "EMPTY"
+// links to save some POWER or "Force" LINK to Disable state if Link can not be
+// trained correctly.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+// BOOLEAN Force Flag to indicate to disable link unconditionally.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// NOTE: Must be called only for PCI Express devices (Device->PciExpress!=NULL)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieDisableLink(PCI_DEV_INFO *Device, BOOLEAN Force){
+ EFI_STATUS Status=0;
+ PCI_CFG_ADDR addr;
+ PCIE_LNK_CNT_REG lcnt;
+ BOOLEAN val;
+//------------------------------------------
+
+ //Get Device Link Control Register
+ addr.ADDR=Device->Address.ADDR;
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+
+ Status=PciCfg16(Device->RbIo, addr, FALSE, &lcnt.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+
+ if(Force)val=TRUE;
+ else val=gPciSetupData->LnkDisable;
+
+ //Program Link only if it different from what we have.
+ if((UINT8)lcnt.LnkDisable!=val){
+ lcnt.LnkDisable=val;
+ Status=PciCfg16(Device->RbIo, addr, TRUE, &lcnt.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieProgramLink()
+//
+// Description: This function will Program Link with provided VALUEs
+// trained correctly.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+// UINT16 Data Value to put in LNK_CNT register
+// BOOLEAN Reg2 Flag to select LNK_CNT or LNK_CNT2 register.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// NOTE: Must be called only for PCI Express devices (Device->PciExpress!=NULL)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PcieProgramLink(PCI_DEV_INFO *Device, UINT16 Data, BOOLEAN Reg2){
+ EFI_STATUS Status=0;
+ PCI_CFG_ADDR addr;
+//------------------------------------------
+
+ //Get DownStream Port Properties
+ addr.ADDR=Device->Address.ADDR;
+ if(Reg2)addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_CNT2_OFFSET;
+ else addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+
+ Status=PciCfg16(Device->RbIo, addr, TRUE, &Data);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieResetLink()
+//
+// Description: This function will issue HOT RESET on a LINK referenced by "Device".
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// NOTE: Must be called only for PCI Express devices (Device->PciExpress!=NULL)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieResetLink(PCI_DEV_INFO *Device, UINT8 LnkSpeed){
+ EFI_STATUS Status=0;
+ PCI_CFG_ADDR addr;
+ PCI_BRG_CNT_REG bcnt;
+ BOOLEAN lnkrst=TRUE;
+//--------------------------------
+ //For any Root or Switch Downstream Port, setting the Secondary Bus Reset bit of the Bridge
+ //Control register associated with the Port must cause a hot reset to be sent (see Section 4.2.4.7).
+
+ PCI_TRACE((TRACE_PCI," Link RESETING (LnkSpeed=0x%X)... ",LnkSpeed));
+ addr.ADDR=Device->Address.ADDR;
+ addr.Addr.Register=PCI_BRIDGE_CNTL;
+
+#if PCI_EXPRESS_GEN3_SUPPORT
+ if(LnkSpeed>=PCIE_LINK_SPEED_80G){
+ Status=Pcie3EqualizeLink(Device, &lnkrst);
+ ASSERT_EFI_ERROR(Status);
+ }
+#endif
+
+ //Read BRG_CNT_REG
+ Status=PciCfg16(Device->RbIo, addr, FALSE, &bcnt.BRG_CNT_REG);
+ ASSERT_EFI_ERROR(Status);
+
+ //ASSERT reset Signal
+ bcnt.SecBusReset=TRUE;
+ Status=PciCfg16(Device->RbIo, addr, TRUE, &bcnt.BRG_CNT_REG);
+ ASSERT_EFI_ERROR(Status);
+ pBS->Stall(PCI_T_RST);
+
+ //DE-ASSERT reset Signal
+ bcnt.SecBusReset=FALSE;
+ Status=PciCfg16(Device->RbIo, addr, TRUE, &bcnt.BRG_CNT_REG);
+ ASSERT_EFI_ERROR(Status);
+ PCI_TRACE((TRACE_PCI,"Status = %r.\n",Status));
+ pBS->Stall(PCI_T_RST_RECOVERY);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieRetrainLink()
+//
+// Description: This function will initiate LINK training of the
+// Down Stream Port referenced as "Device".
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+// UINT16 Data Value to put in LNK_CNT register
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// NOTE: Must be called only for PCI Express devices (Device->PciExpress!=NULL)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieRetrainLink(PCI_DEV_INFO *Device, UINT16 Data, UINT8 LnkSpeed){
+ EFI_STATUS Status=0;
+ PCI_CFG_ADDR staa, cnta;
+ PCIE_LNK_STA_REG sta;
+ PCIE_LNK_CNT_REG cnt;
+ UINTN i=0, j=0;
+ BOOLEAN ltok, lnkrt=TRUE;
+//-------------------------------------
+
+ PCI_TRACE((TRACE_PCI," Link RETRAINING...(LnkSpeed=0x%X); # of retry %d ",LnkSpeed, gPciSetupData->LnkTrRetry));
+
+ staa.ADDR=Device->Address.ADDR;
+ cnta.ADDR=Device->Address.ADDR;
+ cnta.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+ staa.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_STA_OFFSET;
+
+ Status=PciCfg16(Device->RbIo, cnta, FALSE, &cnt.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+#if PCI_EXPRESS_GEN3_SUPPORT
+ if(LnkSpeed>=PCIE_LINK_SPEED_80G){
+ Status=Pcie3EqualizeLink(Device, &lnkrt);
+ ASSERT_EFI_ERROR(Status);
+ }
+#endif
+
+ //The above algorithm guarantees that Link training will be based on the Link control parameter
+ //settings that software intends.
+ for(i=0, ltok=FALSE; i<=gPciSetupData->LnkTrRetry; i++){
+ //1. Software sets the relevant Link control parameters to the desired settings without writing a 1b to
+ // the Retrain Link bit. (Was done before in PcieProgramLink routine)...
+
+ //2. Software polls the Link Training bit in the Link Status register until the value returned is 0b.
+ Status=PciCfg16(Device->RbIo, staa, FALSE, &sta.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto rEXIT;
+
+ if(sta.LnkTraining!=0){
+ for(j=0; j<=gPciSetupData->LnkTrRetry; j++){
+ Status=PciCfg16(Device->RbIo, staa, FALSE, &sta.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(sta.LnkTraining==0) break;
+ pBS->Stall(gPciSetupData->LnkTrTimeout);
+ }
+ }
+
+ //if stll link did not come from Recovery State
+ if(sta.LnkTraining!=0 && i>=gPciSetupData->LnkTrRetry){
+ PCI_TRACE((TRACE_PCI,"PciE: TRAINING FAILURE! Link can't exit Recovery State. Disabling Link!\n"));
+ Status=PcieDisableLink(Device, TRUE);
+ Status=EFI_DEVICE_ERROR;
+ ASSERT_EFI_ERROR(Status);
+ goto rEXIT;
+ } else PCI_TRACE((TRACE_PCI,"%d, ",i));
+
+
+ //3. Software writes a 1b to the Retrain Link bit without changing any other fields in the Link
+ // Control register.
+ cnt.RetrainLnk=TRUE;
+
+ Status=PciCfg16(Device->RbIo, cnta, TRUE, &cnt.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Workaround for devices which having Link Retrain bit "sticky"
+ //Spec says it always reads as "0".
+ Status=PciCfg16(Device->RbIo, cnta, FALSE, &cnt.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ if(cnt.RetrainLnk==TRUE){
+ cnt.RetrainLnk=FALSE;
+ Status=PciCfg16(Device->RbIo, cnta, TRUE, &cnt.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ //Pool link Status back again to make sure it trained well.
+ Status=PciCfg16(Device->RbIo, staa, FALSE, &sta.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto rEXIT;
+
+ if(sta.LnkTraining!=0){
+ for(j=0; j<gPciSetupData->LnkTrRetry; j++){
+ Status=PciCfg16(Device->RbIo, staa, FALSE, &sta.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(sta.LnkTraining==0) {
+ ltok=TRUE;
+ break;
+ }
+ pBS->Stall(gPciSetupData->LnkTrTimeout);
+ }
+ } else ltok=TRUE;
+
+
+ if(ltok) break;
+ }
+
+#if PCI_EXPRESS_GEN3_SUPPORT
+ if(LnkSpeed>=PCIE_LINK_SPEED_80G){
+ Status=Pcie3GetEqualizationStatus(Device);
+ if(EFI_ERROR(Status)){
+ //if equalization did not went trough retry it
+ if(Status==EFI_DEVICE_ERROR) {
+ PCI_TRACE((TRACE_PCI," EQ_STS=%r; ", Status));
+ }
+ Status=EFI_SUCCESS;
+ }
+ }
+#endif
+
+rEXIT:
+ PCI_TRACE((TRACE_PCI," %r\n", Status));
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieSetSlotProperties()
+//
+// Description: This function will Initialize SLT_CNT and SLT_STA registers
+// of the "Device".
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// NOTE: Must be called only for PCI Express devices (Device->PciExpress!=NULL)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieSetSlotProperties(PCI_DEV_INFO *Device){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_CFG_ADDR addr;
+ PCIE_SLT_CNT_REG sltc;
+ PCIE_SLT_STA_REG slts;
+//--------------------------------
+
+ PCI_TRACE((TRACE_PCI," PciE: PcieSetSlotProperties() SlotImpl=%d -> ",Device->PciExpress->PcieCap.SlotImpl));
+
+ if(Device->PciExpress->PcieCap.SlotImpl==TRUE){
+ addr.ADDR=Device->Address.ADDR;
+
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_SLT_CNT_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&sltc.SLT_CNT);
+ ASSERT_EFI_ERROR(Status);
+
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_SLT_STA_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&slts.SLT_STA);
+ ASSERT_EFI_ERROR(Status);
+
+ sltc.AttnBtnPress=0;
+ sltc.PowerFaul=0;
+ sltc.MrlSensor=0;
+ sltc.PresenceDet=0;
+ sltc.CmdCompleted=0;
+ sltc.HpIntEnable=0;
+ sltc.DllStatChEn=0;
+
+
+ //Clear all RW1C bits in status reg...
+ slts.AttnBtnPress=1;
+ slts.PowerFaul=1;
+ slts.MrlSensor=1;
+ slts.PresenceDet=1;
+ slts.CmdCompleted=1;
+ slts.DllStateChg=1;
+
+
+ //Power Up slot and set all possible indication on...
+ if(Device->PciExpress->SlotCap.AttnInd) sltc.AttnIndCnt=PCIE_SLT_INDICATOR_ON;
+ if(Device->PciExpress->SlotCap.PowerInd)sltc.PowerIndCnt=PCIE_SLT_INDICATOR_ON;
+ if(Device->PciExpress->SlotCap.PwrCntler)sltc.PowerOff=PCIE_SLT_PWR_ON;
+
+ Status=PciCfg16(Device->RbIo,addr,TRUE,&slts.SLT_STA);
+
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_SLT_CNT_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,TRUE,&sltc.SLT_CNT);
+ }
+ PCI_TRACE((TRACE_PCI,"%r\n", Status));
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieGetCaps()
+//
+// Description: This function will Collect PCI Express Capabilities Data
+// of the "Device".
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// NOTE: Must be called only for PCI Express devices (Device->PciExpress!=NULL)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieGetCaps(PCI_DEV_INFO *Device){
+ EFI_STATUS Status=0;
+ PCI_CFG_ADDR addr;
+//-------------------------------
+ addr.ADDR=Device->Address.ADDR;
+
+ PCI_TRACE((TRACE_PCI,"\n PciE: Collecting CAPs for [B%X|D%X|F%X]\n",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device,Device->Address.Addr.Function));
+
+ PCI_TRACE((TRACE_PCI," PCIE_CAP-> [R=%X|IntMsgNo=%X|SlotImpl=%X|PortType=%X|CapVer=%X]\n",
+ Device->PciExpress->PcieCap.Reserved,
+ Device->PciExpress->PcieCap.IntMsgNo,
+ Device->PciExpress->PcieCap.SlotImpl,
+ Device->PciExpress->PcieCap.PortType,
+ Device->PciExpress->PcieCap.CapVersion
+ ));
+
+ //Get PCI Express Device CAPs - 32 bit after setting clock configuration
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_DEV_CAP_OFFSET;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&Device->PciExpress->DeviceCap.DEV_CAP);
+ ASSERT_EFI_ERROR(Status);
+
+
+ //Print Content of DEV_CAP and DEV_CNT register..
+ PCI_TRACE((TRACE_PCI," DEV_CAP -> [R2=%X|FR=%X|PwrS=%X|PwrV=%X|R1=%X|RBE=%X|PI=%X|AI=%X|AB=%X|EpL1=%X|EpL0=%X|ExT=%X|PhF=%X|MPL=%X]\n",
+ Device->PciExpress->DeviceCap.Reserved2,
+ //Added in PCIe Base V2.0
+ Device->PciExpress->DeviceCap.FuncResetCap,
+ Device->PciExpress->DeviceCap.SlotPwrLimS,
+ Device->PciExpress->DeviceCap.SlotPwrLimV,
+ Device->PciExpress->DeviceCap.Reserved1,
+ //Added in PCIe Base V2.0
+ Device->PciExpress->DeviceCap.RoleBasedErr,
+ Device->PciExpress->DeviceCap.PowerInd,
+ Device->PciExpress->DeviceCap.AttnInd,
+ Device->PciExpress->DeviceCap.AttnBtn,
+ Device->PciExpress->DeviceCap.EpL1Latency,
+ Device->PciExpress->DeviceCap.EpL0Latency,
+ Device->PciExpress->DeviceCap.ExtTagFld,
+ Device->PciExpress->DeviceCap.PhantomFunc,
+ Device->PciExpress->DeviceCap.MaxPayload
+ ));
+
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_CAP_OFFSET;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&Device->PciExpress->LinkCap.LNK_CAP);
+ ASSERT_EFI_ERROR(Status);
+
+ PCI_TRACE((TRACE_PCI," LNK_CAP -> [P#=%X|R=%X|BwN=%X|DllL=%X|SDE=%X|ClkPM=%X|L1=%X|L0=%X|ASPM=%X|MaxW=%X|MaxS=%X]\n",
+ Device->PciExpress->LinkCap.PortNum,
+ Device->PciExpress->LinkCap.Reserved,
+ //Added in PCIe Base V2.0
+ Device->PciExpress->LinkCap.BandwNotify,
+ Device->PciExpress->LinkCap.DllLnkActive,
+ Device->PciExpress->LinkCap.SurpDownErr,
+ Device->PciExpress->LinkCap.ClockPm,
+ //---------------------------------
+ Device->PciExpress->LinkCap.ExL1Latency,
+ Device->PciExpress->LinkCap.ExL0Latency,
+ Device->PciExpress->LinkCap.AspmSupport,
+ Device->PciExpress->LinkCap.MaxLnkWidth,
+ Device->PciExpress->LinkCap.MaxLnkSpeed
+ ));
+
+ //Get PCI Express Slot CAPs - 32 bit it is valid only for Ports Switches and Bridges
+ if((Device->Type==tPci2PciBrg || Device->Type==tPci2CrdBrg) &&
+ Device->PciExpress->PcieCap.SlotImpl )
+ {
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_SLT_CAP_OFFSET;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&Device->PciExpress->SlotCap.SLT_CAP);
+ ASSERT_EFI_ERROR(Status);
+
+ PCI_TRACE((TRACE_PCI," SLT_CAP -> [S#=%X|NoCmdC=%X|EmLck=%X|PwrS=%X|PwrV=%X|HpC=%X|HpS=%X|PI=%X|AI=%X|MrlS=%X|PwC=%X|AB=%X]\n",
+ Device->PciExpress->SlotCap.PhisSlotNum,
+ //Added in PCIe Base V2.0
+ Device->PciExpress->SlotCap.NoCmdCompl,
+ Device->PciExpress->SlotCap.EmInterlock,
+ //----------------------------
+ Device->PciExpress->SlotCap.PwrLimScale,
+ Device->PciExpress->SlotCap.PwrLimVal,
+ Device->PciExpress->SlotCap.HpCapable,
+ Device->PciExpress->SlotCap.HpSurprise,
+ Device->PciExpress->SlotCap.PowerInd,
+ Device->PciExpress->SlotCap.AttnInd,
+ Device->PciExpress->SlotCap.MrlSensor,
+ Device->PciExpress->SlotCap.PwrCntler,
+ Device->PciExpress->SlotCap.AttnBtn
+ ));
+
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieSetLnkProperties()
+//
+// Description: This function will Select values for Link Control2 register on
+// both sides of the LINK based on Setup Settiongs and hardware capabilities.
+//
+// Input:
+// PCI_DEV_INFO *DnStreamPort Pointer to PCI Device Private Data of Downstream Port of the link.
+// PCIE_LNK_CNT2_REG *DnLnkCnt Pointer to the LNK_CNT Reg of the Downstream Port of the link.
+// PCI_DEV_INFO *UpStreamPort Pointer to PCI Device Private Data of Upwnstream Port of the link.
+// PCIE_LNK_CNT2_REG *UpLnkCnt Pointer to the LNK_CNT Reg of the Downstream Port of the link.
+// BOOLEAN *LinkTrainingRequired Flag to modify if Link will need RETRAINING after programming.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieSetLnkProperties( PCI_DEV_INFO *DnStreamPort,
+ PCIE_LNK_CNT_REG *DnLnkCnt,
+ PCI_DEV_INFO *UpStreamPort,
+ PCIE_LNK_CNT_REG *UpLnkCnt,
+ BOOLEAN *LinkTrainingRequired)
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCIE_LNK_STA_REG dnls, upls; //link status reg content of up and down side of the link
+ PCI_CFG_ADDR addr;
+ BOOLEAN cc=FALSE;
+//------------------------------
+
+ PCI_TRACE((TRACE_PCI,"PciE: PcieSetLnkProperties() ENTRY:\n"));
+
+ PCI_TRACE((TRACE_PCI," DN STREAM PORT -> [B%X|D%X|F%X] <--> [B%X|D%X|F%X] <- UP STREAM PORT\n",
+ DnStreamPort->Address.Addr.Bus,DnStreamPort->Address.Addr.Device, DnStreamPort->Address.Addr.Function,
+ UpStreamPort->Address.Addr.Bus,UpStreamPort->Address.Addr.Device, UpStreamPort->Address.Addr.Function));
+
+ //Get DownStream Port Properties
+ addr.ADDR=DnStreamPort->Address.ADDR;
+ addr.Addr.Register=DnStreamPort->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+ Status=PciCfg16(DnStreamPort->RbIo,addr,FALSE, &DnLnkCnt->LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ PCI_TRACE((TRACE_PCI," LNK_CNT -> [BwI=%X|BwMI=%X|AuWi=%X|CkPM=%X|ExS=%X|CCk=%X|Rtr=%X|LDis=%X|RCB=%X|ASPM=%X]\n",
+ DnLnkCnt->AutoBandwInt,
+ DnLnkCnt->BandwMgmtInt,
+ DnLnkCnt->HwAutoWdtDis,
+ DnLnkCnt->ClockPm,
+ DnLnkCnt->ExtSynch,
+ DnLnkCnt->CommonClk,
+ DnLnkCnt->RetrainLnk,
+ DnLnkCnt->LnkDisable,
+ DnLnkCnt->RdComplBound,
+ DnLnkCnt->AspmControl));
+
+
+
+ addr.Addr.Register=DnStreamPort->PciExpress->PcieOffs+PCIE_LNK_STA_OFFSET;
+ Status=PciCfg16(DnStreamPort->RbIo,addr,FALSE, &dnls.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Get UpStream Stream Port Properties
+ addr.ADDR=UpStreamPort->Address.ADDR;
+
+ addr.Addr.Register=UpStreamPort->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+ Status=PciCfg16(UpStreamPort->RbIo,addr,FALSE, &UpLnkCnt->LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ PCI_TRACE((TRACE_PCI," LNK_CNT -> [BwI=%X|BwMI=%X|AuWi=%X|CkPM=%X|ExS=%X|CCk=%X|Rtr=%X|LDis=%X|RCB=%X|ASPM=%X]\n ....... UPDATINNG .......\n",
+ UpLnkCnt->AutoBandwInt,
+ UpLnkCnt->BandwMgmtInt,
+ UpLnkCnt->HwAutoWdtDis,
+ UpLnkCnt->ClockPm,
+ UpLnkCnt->ExtSynch,
+ UpLnkCnt->CommonClk,
+ UpLnkCnt->RetrainLnk,
+ UpLnkCnt->LnkDisable,
+ UpLnkCnt->RdComplBound,
+ UpLnkCnt->AspmControl));
+
+ //Get Lnk Status Content... from DownSteam and UpStream Ports
+ addr.Addr.Register=UpStreamPort->PciExpress->PcieOffs+PCIE_LNK_STA_OFFSET;
+ Status=PciCfg16(UpStreamPort->RbIo,addr,FALSE, &upls.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //1.Disable ASPM for now we will set it later starting from Endpoints!
+ DnLnkCnt->AspmControl=0;
+ UpLnkCnt->AspmControl=0;
+
+ //2. Check Clock Config
+ //Check if Lnk Clk config programmed correctly by CSP Code.
+ //see if both sides can use Common Clock (Power up Default == 0)
+ if(dnls.CommonClk && upls.CommonClk) cc=TRUE;
+
+ //Verify if ClkConfig is set correctly and detect if link training is needed
+ if((DnLnkCnt->CommonClk != cc) || (UpLnkCnt->CommonClk!=cc)) *LinkTrainingRequired=TRUE;
+ DnLnkCnt->CommonClk=cc;
+ UpLnkCnt->CommonClk=cc;
+
+ //3.Extended Sinch
+ DnLnkCnt->ExtSynch=gPciSetupData->ExtendedSynch;
+ UpLnkCnt->ExtSynch=gPciSetupData->ExtendedSynch;
+
+ //4. Clock PM
+#if PCI_EXPRESS_GEN2_SUPPORT
+ if((UpStreamPort->PciExpress->LinkCap.ClockPm) && (gPciSetupData->ClockPm))
+ {
+ DnLnkCnt->ClockPm=TRUE;
+ UpLnkCnt->ClockPm=TRUE;
+ } else {
+ DnLnkCnt->ClockPm=FALSE;
+ UpLnkCnt->ClockPm=FALSE;
+ }
+#endif
+ //5. Clear Some interupt related bits.
+ DnLnkCnt->BandwMgmtInt=FALSE;
+ DnLnkCnt->AutoBandwInt=FALSE;
+
+ PCI_TRACE((TRACE_PCI," LNK_CNT -> [BwI=%X|BwMI=%X|AuWi=%X|CkPM=%X|ExS=%X|CCk=%X|Rtr=%X|LDis=%X|RCB=%X|ASPM=%X]\n",
+ DnLnkCnt->AutoBandwInt,
+ DnLnkCnt->BandwMgmtInt,
+ DnLnkCnt->HwAutoWdtDis,
+ DnLnkCnt->ClockPm,
+ DnLnkCnt->ExtSynch,
+ DnLnkCnt->CommonClk,
+ DnLnkCnt->RetrainLnk,
+ DnLnkCnt->LnkDisable,
+ DnLnkCnt->RdComplBound,
+ DnLnkCnt->AspmControl));
+
+ PCI_TRACE((TRACE_PCI," LNK_CNT -> [BwI=%X|BwMI=%X|AuWi=%X|CkPM=%X|ExS=%X|CCk=%X|Rtr=%X|LDis=%X|RCB=%X|ASPM=%X]\n\n",
+ UpLnkCnt->AutoBandwInt,
+ UpLnkCnt->BandwMgmtInt,
+ UpLnkCnt->HwAutoWdtDis,
+ UpLnkCnt->ClockPm,
+ UpLnkCnt->ExtSynch,
+ UpLnkCnt->CommonClk,
+ UpLnkCnt->RetrainLnk,
+ UpLnkCnt->LnkDisable,
+ UpLnkCnt->RdComplBound,
+ UpLnkCnt->AspmControl));
+
+ return Status;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieIsDownStreamPort()
+//
+// Description: This function will check if *PCI_DEV_INFO passed belongs to
+// PCI Express DOWNSTREAM PORT:
+// - RootPort of PCIe Root Complex;
+// - DownStream Port of PCIe Switch;
+// - PCI/PCI-X to PCIe Bridge.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Device Private Data structure.
+//
+// Output: BOOLEAN
+// TRUE When PCI_DEV_INFO passed belongs to DOWNSTREAM PORT
+// FALSE All other cases...
+//
+// NOTE: Must be called only for PCI Express devices (Device->PciExpress!=NULL)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN PcieIsDownStreamPort(PCI_DEV_INFO *Device){
+
+ if((Device->PciExpress->PcieCap.PortType == PCIE_TYPE_ROOTPORT) ||
+ (Device->PciExpress->PcieCap.PortType == PCIE_TYPE_DNS_PORT) ||
+ (Device->PciExpress->PcieCap.PortType == PCIE_TYPE_PCI_PCIE))
+ return TRUE;
+ else
+ return FALSE;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieSetSlotPower()
+//
+// Description: This function will power ON or OFF PCI Express Slot
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Device Private Data structure.
+// BOOLEAN PwrOn Tells to turn slot power ON or OFF
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieSetSlotPower(PCI_DEV_INFO* Device, BOOLEAN PwrOn){
+ PCI_CFG_ADDR addr;
+ PCIE_SLT_CNT_REG sltc;
+ EFI_STATUS Status=0;
+ UINT16 pwr=PCIE_SLT_PWR_OFF;
+//--------------------------------------------
+ if(!Device->PciExpress) return EFI_SUCCESS;
+
+ if(Device->PciExpress->SlotCap.PwrCntler){
+ addr.ADDR=Device->Address.ADDR;
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_SLT_CNT_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&sltc.SLT_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(PwrOn){
+ if(Device->PciExpress->SlotCap.PowerInd) sltc.PowerIndCnt=PCIE_SLT_INDICATOR_ON;
+ sltc.PowerOff=PCIE_SLT_PWR_ON;
+ } else {
+ if(Device->PciExpress->SlotCap.PowerInd) sltc.PowerIndCnt=PCIE_SLT_INDICATOR_OFF;
+ sltc.PowerOff=PCIE_SLT_PWR_OFF;
+ }
+ Status=PciCfg16(Device->RbIo,addr,TRUE,&sltc.SLT_CNT);
+ ASSERT_EFI_ERROR(Status);
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RestoreBridgeBuses()
+//
+// Description: This function will Reprogram Primary Secondary and Subordinate
+// bus numbers for the downsteram bridges after SEC BUS reset signal assertion.
+//
+// Input:
+// PCI_DEV_INFO *DnPort Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS RestoreBridgeBuses(PCI_DEV_INFO *DnPort){
+ UINTN i;
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(DnPort+1);
+ PCI_DEV_INFO *dev;
+ EFI_STATUS Status=EFI_SUCCESS;
+//---------------------
+ for(i=0; i< ext->ChildCount; i++){
+ dev=ext->ChildList[i];
+ if(dev->Type==tPci2PciBrg){
+ Status=MapBridgeBuses(dev);
+ if(EFI_ERROR(Status)) return Status;
+ //call recoursively to cover all hierarchy
+ Status=RestoreBridgeBuses(dev);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieInitLink()
+//
+// Description: This function will Initialize Pcie Link on both sides starting
+// fronm DownStream Port.
+//
+// Input:
+// PCI_DEV_INFO *DnPort Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieInitLink(PCI_DEV_INFO *DnPort){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_DEV_INFO *dn, *up, *f0;
+ PCI_BRG_EXT *ext;
+ PCIE_LNK_CNT_REG dnlc, uplc;
+ BOOLEAN lr=FALSE,lt=FALSE, pe2=FALSE, mf=FALSE;
+ UINT16 mpl, l0, l1;//calculated link speed
+ UINTN i=0,r=1;
+ T_ITEM_LIST *chldlst=NULL;
+ UINT8 lnkspeed=0;
+#if PCI_EXPRESS_GEN2_SUPPORT
+ PCIE_LNK_CNT2_REG dnlc2, uplc2;
+#endif
+//-------------------------------
+
+ if(DnPort->PciExpress==NULL) return EFI_SUCCESS;
+
+ //Going from DOWN STREAM PORT to EP
+ dn=DnPort;
+ ext=(PCI_BRG_EXT*)(dn+1);
+
+
+ PCI_TRACE((TRACE_PCI,"\n PciE: InitLink DNSP @ [B%X|D%X|F%X] has 0x%X Childs",
+ dn->Address.Addr.Bus,dn->Address.Addr.Device,dn->Address.Addr.Function, ext->ChildCount));
+ if(ext->ChildCount==0){
+ Status=PcieDisableLink(dn, FALSE);
+ PCI_TRACE((TRACE_PCI," - Disabe Inactive Link=%d: %r\n", gPciSetupData->LnkDisable, Status));
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ //Check if we need to initialize Pcie2 features as well
+ //it will happened if both sides of the link supports PcieGen2 spec
+#if PCI_EXPRESS_GEN2_SUPPORT
+ if(dn->PciExpress->Pcie2!=NULL)pe2=TRUE;
+ else pe2=FALSE;
+#endif
+
+ if(pe2)PCI_TRACE((TRACE_PCI," ARI=%d; ",dn->PciExpress->Pcie2->AriEnabled));
+ else PCI_TRACE((TRACE_PCI," ARI=0; "));
+
+ Status=CpyItemLst((T_ITEM_LIST*)&ext->InitialCount, &chldlst);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Went trough Bridge's Childs and...
+ for(i=0,f0=NULL; i<chldlst->ItemCount; i++){
+ up=(PCI_DEV_INFO*)chldlst->Items[i];
+
+ if(up->PciExpress==NULL)return EFI_SUCCESS;
+
+ if(IsFunc0(up)){
+ f0=up;
+ mf=IsFunc0OfMfDev(up);
+#if PCI_EXPRESS_GEN2_SUPPORT
+ //Set PCIe GEN2 Properties first it ia applicable only for Func0
+ //if both sides of the link supports it...
+ if((up->PciExpress->Pcie2!=NULL) && (pe2==TRUE)){
+ PCI_TRACE((TRACE_PCI,"GEN2=%d.\n",pe2));
+ Status=Pcie2SetLnkProperties(dn, &dnlc2, up, &uplc2, &lr, &lt);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ } else pe2 = FALSE;
+#endif
+ if(pe2==FALSE)PCI_TRACE((TRACE_PCI,"GEN2=%d.\n",pe2));
+
+ //Now Set PCIe GEN1 properties.
+ Status=PcieSetLnkProperties(dn, &dnlc, up, &uplc, &lt);
+
+ //Now remove pointer to the func 0 from DOWN STREAM PORT Child's List
+ Status=DeleteItemLst(chldlst, i, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ break;
+ }
+ }
+
+ //It must be a Child with Function == 0 there...
+ ASSERT(f0!=NULL);
+
+ //now we are here and have prepared content of LNK_CNT and LNK_CNT2 for programming.
+ //there are some rules for link initialization that differes for ARI devices and regular ones.
+ //1. If device is ARI devise (has ARI compatibility header) all programming is applicable for Function0 only.
+ // all other Link control Register bits are reserved for the functions other than 0.
+ //2. If Device is NON-ARI than:
+ // a) all functions must report same value in capabilities except ClockPM bit -
+ // it is independent but will work only if all Functions of the device reports same capability.
+ // b) all functions mus have same values in LNK_CNT for feature to work.
+ // except same old ClockPM - it can be set only if all functions support it.
+
+ //Check some condition which suppose to be true for PCI Express Devices.
+ ASSERT(chldlst->ItemCount == f0->FuncCount); //it must be the same number as FuncCount of Func0 device
+
+ //If device id NON-ARI we must programm all functions to the same values
+ if((f0!=NULL) && (f0->PciExpress->AriData == NULL) && (mf==TRUE)){
+
+ PcieUpdateClockPm(f0,&uplc);
+ //Apply Settings for each child if device is MF
+ for(i=0; i<f0->FuncCount; i++){
+ up=f0->DevFunc[i];
+
+ if(up->PciExpress==NULL) continue;
+
+ Status=PcieProgramLink(up,uplc.LNK_CNT, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+ if(pe2){
+ Status=PcieProgramLink(up,uplc2.LNK_CNT2,TRUE);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+#endif
+
+ }
+ }
+
+ //Now Program the link ....
+ //Func 0 of Upstrem port...
+ Status=PcieProgramLink(f0,uplc.LNK_CNT, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+ if(pe2){
+ Status=PcieProgramLink(f0,uplc2.LNK_CNT2, TRUE);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+#endif
+
+ //Downstream port...
+ Status=PcieProgramLink(dn,dnlc.LNK_CNT, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+ if(pe2){
+ Status=PcieProgramLink(dn,dnlc2.LNK_CNT2, TRUE);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ //All soft instances of PCIe registers updated
+ //now check update lnkspeed variable
+ if(pe2)lnkspeed=(UINT8)(dnlc2.TargetLnkSpeed);
+ else lnkspeed=1;
+#else
+ lnkspeed=1;
+#endif
+
+ //And now see do we need to Retrain link or issue a Hot Reset.
+ //If Link Speed was changed we need to do a Hot Reset of a Link.
+ //When Hot Reset issued with New Link Parameters link will be retrained anyway.
+ if(lr){
+ Status=PcieResetLink(dn, lnkspeed);
+ Status=RestoreBridgeBuses(dn);
+ }
+
+ if(lt) Status=PcieRetrainLink(dn,dnlc.LNK_CNT, lnkspeed);
+
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Update Internal Data now once we have applied all link settings
+ //It might affect some capablities of the PCIe Device.
+#if PCI_EXPRESS_GEN2_SUPPORT
+ if(pe2){
+ dn->PciExpress->Pcie2->LnkSpeed=(UINT8)dnlc2.TargetLnkSpeed;
+ f0->PciExpress->Pcie2->LnkSpeed=(UINT8)uplc2.TargetLnkSpeed;
+ }
+#endif
+
+ //Set Flag that link was progranmmed!
+ dn->PciExpress->LinkSet=TRUE;
+ f0->PciExpress->LinkSet=TRUE;
+
+
+ //If link was reseted or retrained update link capabilities
+ //since it might change besause of clock config and speed change.
+ if(lt || lr ){
+ PCI_TRACE((TRACE_PCI,"Pcie: Refresh CAPs for DNSTREAM; UPSTREAM + ALL FUNC\n"));
+ Status=PcieGetCaps(dn);
+ ASSERT_EFI_ERROR(Status);
+
+ Status=PcieGetCaps(f0);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ //For all devices interfacing with DownStream port
+ //update MaxPayLoad and L0s L1 exit Latencies once we are already here.
+ //We will use it later to Program Pcie Device Chain
+ mpl=dn->PciExpress->DeviceCap.MaxPayload;
+
+ //value of 0xFFFE indicates corresponded Lx state is not supported)
+ //value of 0xFFFF indicates corresponded Lx latency was not calculated yet.
+ if(dn->PciExpress->LinkCap.AspmSupport & PCIE_ASPM_L0_ENABLE) l0=dn->PciExpress->LinkCap.ExL0Latency;
+ if(dn->PciExpress->LinkCap.AspmSupport & PCIE_ASPM_L1_ENABLE) l1=dn->PciExpress->LinkCap.ExL1Latency;
+
+ if(mpl > f0->PciExpress->DeviceCap.MaxPayload)mpl=f0->PciExpress->DeviceCap.MaxPayload;
+ //It is stated in spec "Multi-Function devices associated with an Upstream Port must
+ //report the same value in this field for all Functions"
+ if(l0!=0xFFFF && (l0 < f0->PciExpress->LinkCap.ExL0Latency)) l0=f0->PciExpress->LinkCap.ExL0Latency;
+ if(l1 < f0->PciExpress->LinkCap.ExL1Latency) l1=f0->PciExpress->LinkCap.ExL1Latency;
+
+ for(i=0; i<f0->FuncCount; i++){
+ up=f0->DevFunc[i];
+
+ if(up->PciExpress==NULL)continue;
+
+ up->PciExpress->LinkSet=TRUE;
+#if PCI_EXPRESS_GEN2_SUPPORT
+ if(pe2) up->PciExpress->Pcie2->LnkSpeed=(UINT8)uplc2.TargetLnkSpeed;
+#endif
+ //Link Retraining or Hot Reset might change Latency values...
+ if(lt || lr ){
+ Status=PcieGetCaps(up);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ //Update MaxPL for all other functions,....spec says
+ // "The Functions of a multi-Function device are permitted to
+ // report different values for this field."
+ if(mpl>up->PciExpress->DeviceCap.MaxPayload)mpl=up->PciExpress->DeviceCap.MaxPayload;
+ up->PciExpress->MaxL0Lat=l0;
+ up->PciExpress->MaxL1Lat=l1;
+ }
+
+ //found smallest one and record it in MaxPayload field of DOWNSTREAM PORT and UPSTREAM PORT's F0;
+ f0->PciExpress->MaxPayload=mpl;
+ f0->PciExpress->MaxL0Lat=l0;
+ f0->PciExpress->MaxL1Lat=l1;
+
+ dn->PciExpress->MaxPayload=mpl;
+ dn->PciExpress->MaxL0Lat=l0;
+ dn->PciExpress->MaxL1Lat=l1;
+
+ //some house keeping;
+ ClearItemLst(chldlst, FALSE);
+ if(chldlst)pBS->FreePool(chldlst);
+
+ return Status;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CollectDeviceExtCap()
+//
+// Description: This function will Fill out structure of PciE Ext Cap data
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CollectDeviceExtCap(PCI_DEV_INFO *Device, VOID **DataPtr, UINTN DataSize, UINT32 CapHdrOffset, BOOLEAN Cap16, UINTN OffsetFromCapHdr){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_CFG_ADDR addr;
+ PCIE_EXT_DATA_HDR *dhdr;
+//---------------------------------------
+
+ //Pointer must be empty at the beginning.
+ if(*DataPtr!=NULL) {
+ ASSERT_EFI_ERROR(EFI_INVALID_PARAMETER);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *DataPtr=MallocZ(DataSize);
+
+ if(*DataPtr==NULL) {
+ ASSERT_EFI_ERROR(EFI_OUT_OF_RESOURCES);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ dhdr=(PCIE_EXT_DATA_HDR*)(*DataPtr);
+
+ dhdr->CapHdrOffset=CapHdrOffset;
+
+ addr.ADDR=Device->Address.ADDR;
+ addr.Addr.ExtendedRegister=CapHdrOffset+(sizeof(PCIE_EXT_CAP_HDR))+(UINT32)OffsetFromCapHdr;
+
+ if(Cap16)Status=PciCfg16(Device->RbIo, addr, FALSE,(UINT16*)&dhdr->CapReg);
+ else Status=PciCfg32(Device->RbIo, addr, FALSE,(UINT32*)&dhdr->CapReg);
+
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieProgramPayloadUp()
+//
+// Description: This function will reprogram Max Payload and Read Request Size
+// in upstream link if initialization code founds that one of Nodes down stream
+// has lesser Max Pay load size than currently programmed
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+// UINT32 Payload Reduced Max Payload Value.
+// UINT32 ReadRequest Reduced Read Request Value.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// Notes:
+// RootPortComplex<=>Switch0...<=>...SwitchN<=>EndPoint
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieProgramPayloadUp(PCI_DEV_INFO *Device, UINT16 MaxPayload, UINT16 MaxReadReq){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_DEV_INFO *dev=Device;
+//-------------------------
+
+ //It has to be PCIE Switch device so it must have PCI2PCI Bridge Header structure.
+ if(dev->Type!=tPci2PciBrg) return EFI_DEVICE_ERROR;
+
+ //We are cominng here if Payload and MaxReadRequest been set for the device and
+ //Device is NOT ENDPOINT Device. Means we hit switch here and it handling more then
+ //one ENDPOINT Devices. So check if MPL and MRRS is Bigger or Equal then passed Payload parameter.
+ if(dev->PciExpress->MaxPayload > MaxPayload){
+ UINTN i;
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(dev+1);
+ PCI_CFG_ADDR addr;
+ PCIE_DEV_CNT_REG devc;
+ //-------------
+ //if condition met: one or some of the upstream device(s) are capable and programmed
+ //to generate TLP bigger than current proposed programming stored in "mrr" and "mpl".
+
+ //Select Device Control Register
+ addr.ADDR= dev->Address.ADDR;
+ addr.Addr.Register=dev->PciExpress->PcieOffs+PCIE_DEV_CNT_OFFSET;
+ //Read what we have there
+ Status=PciCfg16(dev->RbIo,addr,FALSE,&devc.DEV_CNT);
+ ASSERT_EFI_ERROR(Status);
+
+ PCI_TRACE((TRACE_PCI,"PciE: Going UP @ [B%X|D%X|F%X] Updating: MPL %X to %X\n",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device, Device->Address.Addr.Function,
+ devc.MaxPayload, MaxPayload));
+
+ for(i=0;i<ext->ChildCount; i++){
+ dev=(PCI_DEV_INFO*)ext->ChildList[i];
+ if(dev->PciExpress!=NULL){
+ //Reprogram only devices we have programmed already.
+ if(dev->PciExpress->DevSet){
+ //If we have other switches in upstream link call this function recursively.
+ if(dev->Type==tPci2PciBrg) {
+ PcieProgramPayloadUp(dev, MaxPayload, MaxReadReq);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ //Select Device Control Register
+ addr.ADDR = dev->Address.ADDR;
+ addr.Addr.Register=dev->PciExpress->PcieOffs+PCIE_DEV_CNT_OFFSET;
+ //Read what we have there
+ Status=PciCfg16(dev->RbIo,addr,FALSE,&devc.DEV_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ PCI_TRACE((TRACE_PCI,"PciE: Reprogram Payload @ [B%X|D%X|F%X] Updating: MPL %X to %X\n",
+ dev->Address.Addr.Bus,dev->Address.Addr.Device, dev->Address.Addr.Function,
+ devc.MaxPayload, MaxPayload));
+
+ devc.MaxPayload=MaxPayload;
+ //Leave CHIPSET INIT value if AUTO selected.
+ if(MaxReadReq != 55) devc.MaxReadReq=MaxReadReq;
+
+ Status=PciCfg16(dev->RbIo,addr,TRUE, &devc.DEV_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ dev->PciExpress->MaxPayload=MaxPayload;
+
+ }
+ } else {
+ //Such condition MUST NOT happened, since Parent is UPSTREAM PORT and childs must be a PciE only!
+ PCI_TRACE((TRACE_PCI, "PciE: ERROR! PciE Data Uninitialized! Child#=%d. TotalChlds=%d.\n", i, ext->ChildCount));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ } else {
+ PCI_TRACE((TRACE_PCI,"PciE: NOT Going UP @ [B%X|D%X|F%X] Device's Link MPL %X <= New MPL %X\n",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device, Device->Address.Addr.Function,
+ dev->PciExpress->MaxPayload, MaxPayload));
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieConvertLatency()
+//
+// Description: This function will convert Latency value from Values read from.
+// PPCIe.LNK_CNT_REG to Nanoseconds and opposite.
+//
+// Input:
+// UINTN Latency Latency Value to convert
+// BOOLEAN L0s Tells if L0s or L1 Exit latency
+// BOOLEAN ToNs Tells how to convert:
+// TRUE - to the units of nano Seconds;
+// FALSE - to the LNK_CNT_REG.LxExitLat register value
+//
+// Output: EFI_STATUS
+// UINTN Converted Value (-1) - means Invalid Value passed;
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+//Return value in nS of Max L0s, L1 Exit latency .
+UINTN PcieConvertLatency(UINTN Latency, BOOLEAN L0s, BOOLEAN ToNs){
+ UINTN l0s[]={64,128,256,512,1000,2000,4000,8000};
+ UINTN l1[]= {1000, 2000, 4000, 8000, 16000,32000,64000,128000};
+ UINTN *a, max,i=0;
+//---------------------
+ //Init stuff
+ if(L0s) a=&l0s[0];
+ else a=&l1[0];
+
+ if (ToNs) max=7;
+ else{
+ if(L0s) max=8000;
+ else max=128000;
+ }
+
+ //Check parameters;
+ if (Latency > max){
+ return max;
+ }
+
+ if(ToNs) return a[Latency];
+ else {
+ while(i<8){
+ if(a[i]<Latency)i++;
+ else break;
+ }
+ if(i==8) i=7;
+
+ return i;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieRemoveEpFromLst()
+//
+// Description: This function will removed Device referencesd as EndPoint from
+// the gPcieEpLst data structure used as a database of available EndPoint devices.
+//
+// Input:
+// PCI_DEV_INFO *EndPoint Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND EndPoint not in the gPcieEpLst.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieRemoveEpFromLst(PCI_DEV_INFO *EndPoint){
+ PCI_DEV_INFO *dev;
+ UINTN i;
+//-------------------------
+ for(i=0; i<gPcieEpList.ItemCount; i++){
+ dev=(PCI_DEV_INFO*)gPcieEpList.Items[i];
+
+ if(dev==EndPoint){
+ DeleteItemLst(&gPcieEpList, i, FALSE);
+ PCI_TRACE((TRACE_PCI,"PciE: Removing Device [B%X|D%X|F%X] from gPcieEpList[%d]\n",
+ EndPoint->Address.Addr.Bus,EndPoint->Address.Addr.Device, EndPoint->Address.Addr.Function, i));
+ return EFI_SUCCESS;
+ }
+ }
+ PCI_TRACE((TRACE_PCI,"PciE: Can't find device [B%X|D%X|F%X] in gPcieEpList[%d]\n",
+ EndPoint->Address.Addr.Bus,EndPoint->Address.Addr.Device, EndPoint->Address.Addr.Function, gPcieEpList.ItemCount));
+
+ return EFI_NOT_FOUND;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieCalcMaxPayLoad()
+//
+// Description: This function will calculate MAX PayLoad Size needed to work
+// correctly.
+//
+// Input:
+// PCI_DEV_INFO *EndPoint Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16 PcieCalcMaxPayLoad(PCI_DEV_INFO *EndPoint){
+ UINT16 tmpl=0xFFFF, lmpl;
+ PCI_DEV_INFO *dn, *up;
+ BOOLEAN progup;
+#if EFI_DEBUG == 1 //debug
+ UINTN i=1;
+#endif
+//--------------------
+ up=EndPoint;
+ PCI_TRACE((TRACE_PCI," Calculate MPL :\n"));
+ //Down steam port and F0 holds optimal MPL for all elements on this link
+ do{
+ if(up==NULL || up->ParentBrg==NULL)break;
+ progup=FALSE;
+
+ if(!IsFunc0(up)) up=up->Func0;
+ //Init this link mpl var (dn<->up)
+ lmpl=up->PciExpress->MaxPayload;
+
+ dn=up->ParentBrg;
+ if(dn->PciExpress->MaxPayload<lmpl){
+ //if UP link has bigger MPL value then DN link
+ //Update UP link recoded value...
+ lmpl=dn->PciExpress->MaxPayload;
+
+ //set the Flag that we have to reprogramm MPL since downstream MPL has been reduced
+ progup=TRUE;
+ }
+
+ //Here lmpl holds smallest value of the link check if accomulated MPL exceeds MPL of this link...
+ if(tmpl!=lmpl) progup=TRUE;
+ if(tmpl>lmpl) tmpl=lmpl;
+
+ //PcieProgramPayloadUp has double check if MPL needs to be programmed
+ if(progup && up->PciExpress->PcieCap.PortType==PCIE_TYPE_UPS_PORT && up->PciExpress->DevSet){
+ if(gPciSetupData->MaxReadRequest!=55) PcieProgramPayloadUp(up, tmpl,gPciSetupData->MaxReadRequest);
+ else PcieProgramPayloadUp(up, tmpl, PCIE_MAXPL_512B);
+ }
+
+ up->PciExpress->MaxPayload=tmpl;
+
+#if EFI_DEBUG == 1 //debug
+ PCI_TRACE((TRACE_PCI," Link # %d, Link MPL=%X; Total MPL=%X dn->[B%X|D%X|F%X]<->[B%X|D%X|F%X]<-up;\n", i,lmpl, tmpl,
+ dn->Address.Addr.Bus,dn->Address.Addr.Device, dn->Address.Addr.Function,
+ up->Address.Addr.Bus,up->Address.Addr.Device, up->Address.Addr.Function ));
+ i++;
+#endif
+ up=dn->ParentBrg;
+ } while (up->ParentBrg->PciExpress!=NULL && up->ParentBrg->Type!=tPciRootBrg); //(EIP49743)
+
+ PCI_TRACE((TRACE_PCI," Calculated MPL %X\n\n", tmpl));
+
+ return tmpl;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieCalcLatency()
+//
+// Description: This function will calculate MAX Latency needed to exit from
+// ome of the ASPM Sattes L0s or L1.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+// BOOLEAN L0s Tells which ASPM state Latency we are calculating
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN PcieCalcLatency(PCI_DEV_INFO *EndPoint, BOOLEAN L0s){
+ PCI_DEV_INFO *dn, *up;
+ UINT16 *ll;
+ UINTN i=0, tmp=0, lat=0;
+//--------------------
+ up=EndPoint;
+ PCI_TRACE((TRACE_PCI," Calculate "));
+ if(L0s)PCI_TRACE((TRACE_PCI,"L0s:\n"));
+ else PCI_TRACE((TRACE_PCI,"L1 :\n"));
+ //Down steam port and F0 holds optimal MPL for all elements on this link
+ do{
+ if(!IsFunc0(up)) up=up->Func0;
+ dn=up->ParentBrg;
+ if(L0s)ll=&dn->PciExpress->MaxL0Lat;
+ else ll=&dn->PciExpress->MaxL1Lat;
+
+ //if PciExpress->MaxL0Lat==0xFFFF means Link does not support ASPM
+ if(*ll!=0xFFFF ) {
+ if(L0s) {
+ tmp=PcieConvertLatency(dn->PciExpress->MaxL0Lat, L0s, TRUE);
+ lat+=tmp;
+ } else {
+ tmp=PcieConvertLatency(dn->PciExpress->MaxL1Lat, L0s, TRUE);
+ if(tmp>lat) lat=tmp;
+ }
+ }
+
+ PCI_TRACE((TRACE_PCI," Link# %d Lat=%d(nS) dn->[B%X|D%X|F%X]<->[B%X|D%X|F%X]<-up;\n", i, tmp,
+ dn->Address.Addr.Bus,dn->Address.Addr.Device, dn->Address.Addr.Function,
+ up->Address.Addr.Bus,up->Address.Addr.Device, up->Address.Addr.Function ));
+ i++;
+
+ //Advance to the next link.
+ up=dn->ParentBrg;
+ } while (dn->ParentBrg->PciExpress!=NULL && dn->ParentBrg->Type!=tPciRootBrg);//(EIP49743)
+
+ //Internal delay on each Upstream Port (per spec.) MUST BE NO MORE than 1uS.
+ //so next UPSTREAM Link will start transition from L1 to L0 state in 1uS (worst case)
+ // to calculate L1 exit Latency we will use (MAX lat + 1000nS * (i-1)) where i number of links on the packet path.
+ if(!L0s && i>0) lat+=1000*(i-1);
+
+ PCI_TRACE((TRACE_PCI," Total Calclulated latency: %d (nS)\n", lat ));
+
+ return lat;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieInitVc()
+//
+// Description: This function will Initialize "Device"'s Virtual Channel properties
+// based on Setup Settings and hardware capabilities.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieInitVc(PCI_DEV_INFO *Device){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_CFG_ADDR addr;
+ VC_RES_DATA *vcrd;
+ PCIE_VC_RESCNT_REG vcrc;
+ UINTN c;
+//-------------------------
+ //Program VC configuration
+ //Limit VC TC to TC0 mapped trough VC0 and Disable all Extended VC resources on the way of the LINK.
+ //This is a device driver responcibility to allow different TCs and enable Extended VCs if link has it.
+
+ addr.ADDR=Device->Address.ADDR;
+ //Arbitration Table has to be loaded by the Chipset specific code
+ //in NBDxe.c or SBDxe.c or by device specific driver. So don't bother
+ for(c=0; c<Device->PciExpress->VcData->VcCount; c++){
+ vcrd=Device->PciExpress->VcData->VcResData[c];
+
+ //Locate VC Resource CNT reg
+ addr.Addr.ExtendedRegister=vcrd->VcResOffset+4;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&vcrc.VC_RESCNT);
+ ASSERT_EFI_ERROR(Status);
+
+ //Disable VC and TC mapping except default mapping TC0 VC0
+ if(c){
+ vcrc.Tc_VcMap=0;
+ vcrc.VcEnable=0;
+ } else {
+ //for Channel0(Default VC this bits must be RO but who knows...)
+ vcrc.Tc_VcMap=1;
+ vcrc.VcEnable=1;
+ }
+ vcrc.VcId=(UINT8)c;
+
+ //write it back
+ Status=PciCfg32(Device->RbIo,addr,TRUE,&vcrc.VC_RESCNT);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ return Status;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieSetDevProperties()
+//
+// Description: This function will Select values for DEVICE CONTROL register
+// based on Setup Settings and hardware capabilities.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data.
+// UINT16 *MaxPayload Pointer to the MaxPayload value.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieSetDevProperties(PCI_DEV_INFO *Device, UINT16 MaxPayload){
+ EFI_STATUS Status;
+ PCI_CFG_ADDR addr;
+ PCI_DEV_INFO *dev=Device;
+ PCIE_DEV_CNT_REG devc;
+//-------------------------
+
+ addr.ADDR=Device->Address.ADDR;
+
+ PCI_TRACE((TRACE_PCI,"PciE: PcieSetDevProperties() Device @ [B%X|D%X|F%X] ENTRY:\n",
+ addr.Addr.Bus,addr.Addr.Device, addr.Addr.Function));
+
+ if (Device->PciExpress == NULL)
+ return EFI_SUCCESS;
+
+ //Select Device Control Register
+ addr.Addr.Register=dev->PciExpress->PcieOffs+PCIE_DEV_CNT_OFFSET;
+ //Read what we have there
+ Status=PciCfg16(dev->RbIo,addr,FALSE,&devc.DEV_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ PCI_TRACE((TRACE_PCI," DEV_CNT -> [FrBr=%X|MRR=%X|NS=%X|APPM=%X|PhF=%X|ETg=%X|MPL=%X|RO=%X|UpRR=%X|FtEr=%X|NfEr=%X|CEr=%X]\n ....... UPDATINNG .......\n",
+ devc.FnRstBrgRtry,
+ devc.MaxReadReq,
+ devc.NoSnoop,
+ devc.AuxPwrPm,
+ devc.PhantomFunc,
+ devc.ExtTagFld,
+ devc.MaxPayload,
+ devc.RelaxOrder,
+ devc.UsupReqRep,
+ devc.FatalErrRep,
+ devc.NfErrRep,
+ devc.CorrErrRep));
+
+ //Set some bits:
+ //1.Get Maximum PayLoad Size
+ //Don't allow overwrite if it is more than supported
+ if(gPciSetupData->MaxPayload!=55 && gPciSetupData->MaxPayload < MaxPayload) devc.MaxPayload=gPciSetupData->MaxPayload;
+ else devc.MaxPayload=MaxPayload;
+
+ //2.Get Max Read Request Size
+ if(gPciSetupData->MaxReadRequest!=55) devc.MaxReadReq=gPciSetupData->MaxReadRequest;
+ //if "AUTO" selected use value already sitting there...
+// else devc.MaxReadReq=PCIE_MAXPL_512B;
+
+ //3.Enable/Disable extended tagfld per Setup Option
+ devc.ExtTagFld=0; //use 5 bit tag.
+ if(dev->PciExpress->DeviceCap.ExtTagFld)devc.ExtTagFld=gPciSetupData->ExtTagField;
+
+ //4. Set No Snoop bit per Setup Option
+ devc.RelaxOrder=gPciSetupData->RelaxedOrdering;
+ devc.NoSnoop=gPciSetupData->NoSnoop;
+
+ //Write it back
+ Status=PciCfg16(dev->RbIo,addr,TRUE,&devc.DEV_CNT);
+ ASSERT_EFI_ERROR(Status);
+
+ //Init device's VC
+ //if we have a virtual channel capability
+ if(Device->PciExpress->VcData) Status=PcieInitVc(Device);
+
+
+/*
+ //Print Content of DEV_CAP and DEV_CNT register..
+ PCI_TRACE((TRACE_PCI," DEV_CAP -> [R2=%X|FR=%X|PwrS=%X|PwrV=%X|R1=%X|RBE=%X|PI=%X|AI=%X|AB=%X|EpL1=%X|EpL0=%X|ExT=%X|PhF=%X|MPL=%X]\n",
+ dev->PciExpress->DeviceCap.Reserved2,
+ //Added in PCIe Base V2.0
+ dev->PciExpress->DeviceCap.FuncResetCap,
+ dev->PciExpress->DeviceCap.SlotPwrLimS,
+ dev->PciExpress->DeviceCap.SlotPwrLimV,
+ dev->PciExpress->DeviceCap.Reserved1,
+ //Added in PCIe Base V2.0
+ dev->PciExpress->DeviceCap.RoleBasedErr,
+ dev->PciExpress->DeviceCap.PowerInd,
+ dev->PciExpress->DeviceCap.AttnInd,
+ dev->PciExpress->DeviceCap.AttnBtn,
+ dev->PciExpress->DeviceCap.EpL1Latency,
+ dev->PciExpress->DeviceCap.EpL0Latency,
+ dev->PciExpress->DeviceCap.ExtTagFld,
+ dev->PciExpress->DeviceCap.PhantomFunc,
+ dev->PciExpress->DeviceCap.MaxPayload
+ ));
+*/
+ PCI_TRACE((TRACE_PCI," DEV_CNT -> [FrBr=%X|MRR=%X|NS=%X|APPM=%X|PhF=%X|ETg=%X|MPL=%X|RO=%X|UpRR=%X|FtEr=%X|NfEr=%X|CEr=%X]\n\n",
+ devc.FnRstBrgRtry,
+ devc.MaxReadReq,
+ devc.NoSnoop,
+ devc.AuxPwrPm,
+ devc.PhantomFunc,
+ devc.ExtTagFld,
+ devc.MaxPayload,
+ devc.RelaxOrder,
+ devc.UsupReqRep,
+ devc.FatalErrRep,
+ devc.NfErrRep,
+ devc.CorrErrRep));
+
+/*
+ PCI_TRACE((TRACE_PCI," LNK_CAP -> [P#=%X|R=%X|BwN=%X|DllL=%X|SDE=%X|ClkPM=%X|L1=%X|L0=%X|ASPM=%X|MaxW=%X|MaxS=%X]\n",
+ dev->PciExpress->LinkCap.PortNum,
+ dev->PciExpress->LinkCap.Reserved,
+ //Added in PCIe Base V2.0
+ dev->PciExpress->LinkCap.BandwNotify,
+ dev->PciExpress->LinkCap.DllLnkActive,
+ dev->PciExpress->LinkCap.SurpDownErr,
+ dev->PciExpress->LinkCap.ClockPm,
+ //---------------------------------
+ dev->PciExpress->LinkCap.ExL1Latency,
+ dev->PciExpress->LinkCap.ExL0Latency,
+ dev->PciExpress->LinkCap.AspmSupport,
+ dev->PciExpress->LinkCap.MaxLnkWidth,
+ dev->PciExpress->LinkCap.MaxLnkSpeed
+ ));
+
+#if EFI_DEBUG
+ if (Device->PciExpress->PcieCap.SlotImpl){
+
+ PCI_TRACE((TRACE_PCI," SLT_CAP -> [S#=%X|NoCmdC=%X|EmLck=%X|PwrS=%X|PwrV=%X|HpC=%X|HpS=%X|PI=%X|AI=%X|MrlS=%X|PwC=%X|AB=%X]\n",
+ dev->PciExpress->SlotCap.PhisSlotNum,
+ //Added in PCIe Base V2.0
+ dev->PciExpress->SlotCap.NoCmdCompl,
+ dev->PciExpress->SlotCap.EmInterlock,
+ //----------------------------
+ dev->PciExpress->SlotCap.PwrLimScale,
+ dev->PciExpress->SlotCap.PwrLimVal,
+ dev->PciExpress->SlotCap.HpCapable,
+ dev->PciExpress->SlotCap.HpSurprise,
+ dev->PciExpress->SlotCap.PowerInd,
+ dev->PciExpress->SlotCap.AttnInd,
+ dev->PciExpress->SlotCap.MrlSensor,
+ dev->PciExpress->SlotCap.PwrCntler,
+ dev->PciExpress->SlotCap.AttnBtn
+ ));
+ }
+#endif
+*/
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieSetAspm()
+//
+// Description: This function will Select values for Link Control2 register on
+// both sides of the LINK based on Setup Settings and hardware capabilities.
+//
+// Input:
+// PCI_DEV_INFO *DnPort Pointer to PCI Device Private Data of Downstream Port of the link.
+// PCI_DEV_INFO *UpPort Pointer to PCI Device Private Data of Upwnstream Port of the link.
+// UINT16 Aspm ASPM value to programm.
+// BOOLEAN *LinkHotResetRequired Flag to modify if Link will need HOT RESET after programming.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieSetAspm(PCI_DEV_INFO *DnPort,PCI_DEV_INFO *UpPort,UINT16 Aspm){
+ EFI_STATUS Status;
+ PCIE_LNK_CNT_REG lnkc;
+ PCI_CFG_ADDR addr;
+ UINT16 aspm=0, dnaspm, upaspm;
+//-------------------------
+
+
+ PCI_TRACE((TRACE_PCI,"\n Setting ASPM for Link...\n UP STREAM PORT -> [B%X|D%X|F%X] <--> [B%X|D%X|F%X] <- DN STREAM PORT\n",
+ UpPort->Address.Addr.Bus,UpPort->Address.Addr.Device, UpPort->Address.Addr.Function,
+ DnPort->Address.Addr.Bus,DnPort->Address.Addr.Device, DnPort->Address.Addr.Function ));
+
+ //We are coming here with UpPort as Function 0 already.
+ addr.ADDR=UpPort->Address.ADDR;
+
+ //Select lnk Control Register
+ addr.Addr.Register=UpPort->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+ //Read what we have there
+ Status=PciCfg16(UpPort->RbIo,addr,FALSE,&lnkc.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Spec tells: "ASPM L1 must be enabled by software in the Upstream
+ //component on a Link prior to enabling ASPM L1 in the
+ //Downstream component on that Link. When disabling ASPM
+ //L1, software must disable ASPM L1 in the Downstream
+ //component on a Link prior to disabling ASPM L1 in the
+ //Upstream component on that Link. ASPM L1 must only be
+ //enabled on the Downstream component if both components on
+ //a Link support ASPM L1."
+
+ //We have recorded in MaxLxLat field of the PciExpres Data Structure
+ //Link capability to support certain Lx states.
+ //value of 0xFFFF indicates corresponded Lx state is not supported.
+ //It must be the same on both sides of the link!
+ ASSERT(DnPort->PciExpress->MaxL0Lat == UpPort->PciExpress->MaxL0Lat);
+ ASSERT(DnPort->PciExpress->MaxL1Lat == UpPort->PciExpress->MaxL1Lat);
+ //If some links on the Pcie Packet Path does not support certain Lx states,
+ //they will remain in L0 state all the time. Mean while ones that supports,
+ //will transition to Lx power saving state.
+ if( (UpPort->PciExpress->MaxL0Lat == 0xFFFF) ||
+ !(UpPort->PciExpress->LinkCap.AspmSupport & PCIE_ASPM_L0_ENABLE) ||
+ !(DnPort->PciExpress->LinkCap.AspmSupport & PCIE_ASPM_L0_ENABLE) ) Aspm &=(~PCIE_ASPM_L0_ENABLE);
+ if( (UpPort->PciExpress->MaxL1Lat == 0xFFFF) ||
+ !(UpPort->PciExpress->LinkCap.AspmSupport & PCIE_ASPM_L1_ENABLE) ||
+ !(DnPort->PciExpress->LinkCap.AspmSupport & PCIE_ASPM_L1_ENABLE) ) Aspm &=(~PCIE_ASPM_L1_ENABLE);
+
+ aspm=Aspm;
+
+ //Check Setup settings "Force to L0s" must clear calculated PCIE_ASPM_L1_ENABLE;
+ //But should not affect OVERWRITE capabilities.
+ //[Disable]==0\ Auto==55 \ Force L0s==1
+ if(gPciSetupData->AspmMode == 1) aspm &= (~PCIE_ASPM_L1_ENABLE);
+ if(gPciSetupData->AspmMode == 0) aspm = 0;
+ //Now "Aspm" has calculated MAX supported ASPM value
+ //and "aspm" has Updated accordingly to setup
+ dnaspm=aspm;
+ Status=PciPortOemSetAspm(DnPort, &dnaspm);
+ PCI_TRACE((TRACE_PCI," Getting Overwr Aspm Settings for DNSTREAM PORT: Calc ASPM = %X ... Setup ASPM = %X \n",Aspm, aspm));
+
+ upaspm=aspm;
+ Status=PciPortOemSetAspm(UpPort, &upaspm);
+ PCI_TRACE((TRACE_PCI," Getting Overwr Aspm Settings for UPSTREAM PORT: Calc ASPM = %X ... Setup ASPM = %X \n",Aspm, aspm));
+
+ //check UP and DN STREAM ASPM override settings.
+ //and pick smallest one...
+ if(dnaspm<upaspm) aspm=dnaspm;
+ else aspm=upaspm;
+ PCI_TRACE((TRACE_PCI," Status = %r : Calc ASPM = %X ... Overwr ASPM = %X \n",Status,Aspm, aspm));
+
+ //Check if ASPM settings were correctly overwritten
+ //It can't be more than calculated... otherwice system might hung!
+ if (aspm>Aspm){
+ PCI_TRACE((TRACE_PCI," !![Calc ASPM = %X] LESSER THAN [Ovr ASPM = %X] - System Might HUNG. Reset to Calculated!!\n", Aspm, aspm));
+ aspm=Aspm;
+ }
+
+ PCI_TRACE((TRACE_PCI,"\n"));
+
+ if(aspm) {
+ lnkc.AspmControl=aspm;
+
+ //Set ASPM in UpStream Port First for Function 0
+ Status=PciCfg16(UpPort->RbIo,addr,TRUE,&lnkc.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //It is recommended to programm all functions even in
+ //case of ARI device Func0 is in charge for link behavior.
+ if(IsFunc0OfMfDev(UpPort)){
+ UINTN i;
+ PCI_DEV_INFO *dev;
+ //--------------------------
+ for(i=0; i<UpPort->FuncCount; i++){
+ dev=UpPort->DevFunc[i];
+
+ if(dev->PciExpress==NULL) continue;
+
+ addr.ADDR=dev->Address.ADDR;
+ addr.Addr.Register=dev->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+ //Read what we have there
+ Status=PciCfg16(dev->RbIo,addr,FALSE,&lnkc.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ lnkc.AspmControl=aspm;
+
+ Status=PciCfg16(dev->RbIo,addr,TRUE,&lnkc.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ }
+
+ //Select lnk Control Register of Down Stream port
+ addr.ADDR=DnPort->Address.ADDR;
+ addr.Addr.Register=DnPort->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+ //Read what we have there
+ Status=PciCfg16(DnPort->RbIo,addr,FALSE,&lnkc.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Set ASPM for Downstream Port
+ lnkc.AspmControl=aspm;
+
+ //Write Back
+ Status=PciCfg16(DnPort->RbIo,addr,TRUE,&lnkc.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+ }//if(Aspm)
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieApplyDevSettings()
+//
+// Description: This function will Select values for DEVICE CONTROL register
+// based on Setup Settings and hardware capabilities.
+//
+// Input:
+// PCI_DEV_INFO *EndPoint Pointer to PCI Device Private Data.
+// UINT16 MaxPayload MaxPayload value.
+// UINT16 LatencyL0s Latency L0s value.
+// UINT16 LatencyL1 Latency L1 value.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieApplyDevSettings(PCI_DEV_INFO *EndPoint, UINT16 MaxPayLoad, UINT16 LatencyL0s, UINT16 LatencyL1){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_DEV_INFO *dn, *up, *f0=NULL;
+ UINTN i;
+ UINT16 aspmc=0, mpl=0;
+#if PCI_EXPRESS_GEN2_SUPPORT == 1
+ BOOLEAN pe2=FALSE;
+#endif
+//--------------------
+ up=EndPoint;
+ if(!IsFunc0(up)) up=up->Func0;
+
+ if(up->PciExpress->DeviceCap.EpL0Latency >= LatencyL0s) aspmc |= PCIE_ASPM_L0_ENABLE;
+ if(up->PciExpress->DeviceCap.EpL1Latency >= LatencyL1) aspmc |= PCIE_ASPM_L1_ENABLE;
+
+
+ PCI_TRACE((TRACE_PCI,"\nPciE: PcieApplyDevSettings() -> Starting with Device [B%X|D%X|F%X]\n",
+ up->Address.Addr.Bus,up->Address.Addr.Device, up->Address.Addr.Function));
+
+
+ //Check if we need to initialize Pcie2 features as well
+ //it will happened if both sides of the link supports PcieGen2 spec
+#if PCI_EXPRESS_GEN2_SUPPORT
+ if((up->ParentBrg->PciExpress->Pcie2!=NULL)&&(up->PciExpress->Pcie2!=NULL))pe2=TRUE;
+#endif
+
+ do{
+ if(up==NULL || up->ParentBrg==NULL)break;
+ f0=NULL;
+ dn=up->ParentBrg;
+ //optimal MPL calculated and passed here;
+ mpl=MaxPayLoad;
+
+ //Set fetures selected in SETUP
+ PCI_TRACE((TRACE_PCI,"#---> EndPoint/UPSTREAM @ [B%X|D%X|F%X] ASPM=%X; MPL=%X;\n",
+ up->Address.Addr.Bus,up->Address.Addr.Device, up->Address.Addr.Function, aspmc, mpl));
+
+#if PCI_EXPRESS_GEN2_SUPPORT == 1
+ if(pe2){
+ //If applicable
+ //Set Device fetures for GEN2 devices
+ Status=Pcie2SetDevProperties(up);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+#endif
+
+ Status=PcieSetDevProperties(up, mpl);
+
+ //SetFlag DevProgrammed FLAG..
+ up->PciExpress->DevSet=TRUE;
+
+ //Remove processed entrie from EndPoint Database...
+ Status=PcieRemoveEpFromLst(up);
+
+
+ //If we got an EndPoint and it is a Multy Func device - go and update all it's functions...
+ if(up->PciExpress->PcieCap.PortType == PCIE_TYPE_ENDPOINT ||
+ up->PciExpress->PcieCap.PortType == PCIE_TYPE_PCIE_PCI ||
+ up->PciExpress->PcieCap.PortType == PCIE_TYPE_LEGACYEP ||
+ up->PciExpress->PcieCap.PortType == PCIE_TYPE_UPS_PORT )
+ {
+ f0=up;
+ for (i=0; i<f0->FuncCount; i++){
+ up=f0->DevFunc[i];
+
+ PCI_TRACE((TRACE_PCI,"#---> EndPoint/UPSTREAM Function @ [B%X|D%X|F%X] ASPM=%X; MPL=%X;\n",
+ up->Address.Addr.Bus,up->Address.Addr.Device, up->Address.Addr.Function, aspmc, mpl));
+
+ if(up->PciExpress==NULL) continue;
+
+#if PCI_EXPRESS_GEN2_SUPPORT == 1
+ if(pe2){
+ //If applicable
+ //Set Device fetures for GEN2 devices
+ Status=Pcie2SetDevProperties(up);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+#endif
+
+ //Set fetures selected in SETUP
+ Status=PcieSetDevProperties(up, mpl);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //SetFlag DevProgrammed FLAG..
+ up->PciExpress->DevSet=TRUE;
+
+ //Remove processed entrie from EndPoint Database...
+ Status=PcieRemoveEpFromLst(up);
+ } //for
+ }//if Mf endpoint
+
+ //Restore "up" var
+ if(f0!=NULL) up=f0;
+
+ PCI_TRACE((TRACE_PCI,"<---# RootComp/DNSTREAM @ [B%X|D%X|F%X] ASPM=%X; MPL=%X;\n",
+ dn->Address.Addr.Bus,dn->Address.Addr.Device, dn->Address.Addr.Function, aspmc, mpl));
+
+ //now do the DownStream Port... it always ONLY one device!
+#if PCI_EXPRESS_GEN2_SUPPORT == 1
+ if(pe2){
+ //If applicable
+ //Set Device fetures for GEN2 devices
+ Status=Pcie2SetDevProperties(dn);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+#endif
+ Status=PcieSetDevProperties(dn,mpl);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+
+ //Aspm is off at that point.
+ //We should turn it on first in UPSTREAM PORT, than IN DOWNSTREAM port.
+ //Since we can owerwrite Settings
+ Status=PcieSetAspm(dn,up,aspmc);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //SetFlag DevProgrammed FLAG..
+ dn->PciExpress->DevSet=TRUE;
+
+ //Remove processed entrie from EndPoint Database...
+ //Status=PcieRemoveEpFromLst(dn);
+
+ //Go to the next link if any...
+ up=dn->ParentBrg;
+ } while (up!=NULL && up->ParentBrg!=NULL && up->ParentBrg->Type!=tPciRootBrg && up->ParentBrg->PciExpress!=NULL); //(EIP49743)
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieInitDevChain()
+//
+// Description: This function will detect optimal settings and programm -
+// MaxPayLoadSize, ReadRequestSize, ASPM settings and Virtual Channels
+// for all devices in the PCIE Links Chain.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// Notes:
+// RootPortComplex<=>Switch0...<=>...SwitchN<=>EndPoint
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieInitDevChain(PCI_DEV_INFO* Device ){
+ EFI_STATUS Status=0;
+ UINT16 mpl=-1,mrr=-1;
+ UINTN lt0=0,lt1=0; //Latency in Nano Seconds.
+ UINT16 reg_lt0=0,reg_lt1=0;//Latency to be written into Register.
+#if EFI_DEBUG == 1 //debug
+//------------------------------
+ PCIE_PCIE_CAP_REG pciecap;
+ PCIE_DEV_CAP_REG devcap;
+ PCIE_LNK_CAP_REG lnkcap;
+ PCIE_SLT_CAP_REG sltcap;
+
+#if PCI_EXPRESS_GEN2_SUPPORT == 1
+ PCIE_DEV_CAP2_REG devcap2;
+ PCIE_LNK_CAP2_REG lnkcap2;
+#endif
+//-----------------------------
+#endif //debug
+//-----------------------
+
+ //Now we will programm clock config when exiting from the bridge
+ //Collect Min Supported feature at the length of the PCIE Devices Chain
+#if EFI_DEBUG == 1 //debug
+ pciecap.PCIE_CAP=Device->PciExpress->PcieCap.PCIE_CAP;
+ devcap.DEV_CAP=Device->PciExpress->DeviceCap.DEV_CAP;
+ lnkcap.LNK_CAP=Device->PciExpress->LinkCap.LNK_CAP;
+ sltcap.SLT_CAP=Device->PciExpress->SlotCap.SLT_CAP;
+#if PCI_EXPRESS_GEN2_SUPPORT == 1
+ devcap2.DEV_CAP2=Device->PciExpress->Pcie2->DeviceCap2.DEV_CAP2;
+ lnkcap2.LNK_CAP2=Device->PciExpress->Pcie2->LinkCap2.LNK_CAP2;
+#endif
+#endif//debug
+
+ //Get MaxPayLoad
+ mpl=PcieCalcMaxPayLoad(Device);
+
+ //After PcieCalcMaxPayLoad() Payload has to be adjusted DOWN STREAM already (towards EP Device)...
+ //When We come here ASPM already disabled by PcieProbeDevice() function.
+ //Since we are going to use Porting Hook to overwrite ASPM settings Calculate Latency OLWAYS
+ //and Enable it only if Setup says so...- will be done in PcieSetAspm()
+
+
+ //Get L0s L1 exit Latencies if needed...
+// if(gPciSetupData->AspmMode!=0){
+
+ lt0=PcieCalcLatency(Device,TRUE);
+
+ //now we should add CIPSET internal L0s Exit Latency to the total value
+ //For NB if any
+ if( (NbDmiAspmSupport & PCIE_ASPM_L0_ENABLE ) && (SbDmiAspmSupport & PCIE_ASPM_L0_ENABLE )){
+ if(NbDmiL0ExitLatency > SbDmiL0ExitLatency) lt0 += NbDmiL0ExitLatency;
+ else lt0 += SbDmiL0ExitLatency;
+ }
+ //and SB if any
+ reg_lt0+=(UINT16) PcieConvertLatency(lt0, TRUE, FALSE);
+
+// if(gPciSetupData->AspmMode > 1){
+ lt1=PcieCalcLatency(Device,FALSE);
+
+ //now we should add CIPSET L1 Exit Latency to the total value
+ if( (NbDmiAspmSupport & PCIE_ASPM_L1_ENABLE ) && (SbDmiAspmSupport & PCIE_ASPM_L1_ENABLE )){
+ if(NbDmiL1ExitLatency > SbDmiL1ExitLatency) lt1 += NbDmiL1ExitLatency;
+ else lt1 += SbDmiL1ExitLatency;
+ }
+ //and SB
+ lt1+=SbInternalDelay;
+ reg_lt1+=(UINT16) PcieConvertLatency(lt1, FALSE, FALSE);
+
+// } else reg_lt1=0xFFFF;
+// } else reg_lt0=0xFFFF;
+
+ //Apply collected values to the devices
+ Status=PcieApplyDevSettings(Device, mpl, reg_lt0, reg_lt1);
+
+ return Status;
+}
+
+#if SRIOV_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProbeSriovDevice()
+//
+// Description: This function will collect information about SRIOV PCIE Device
+// and initialize it based on information collected.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProbeSriovDevice(PCI_DEV_INFO *Device, UINT32 SriovCapBaseOffset){
+ EFI_STATUS Status;
+ PCIE_SRIOV_CNT_REG SrIoVControl;
+ UINT32 PageSize, i=0, incr, maxbar;
+ UINT16 InitialFv;
+ UINT16 FirstVfOffset;
+ UINT16 VfStride;
+ UINT16 RoutingId;
+ UINT8 VfMaxBus;
+
+ PCI_BAR *Bar;
+ PCI_CFG_ADDR addr;
+
+ addr.ADDR=Device->Address.ADDR;
+ addr.Addr.ExtendedRegister = SriovCapBaseOffset;
+ PCI_TRACE((TRACE_PCI,"PciBus: Found SRIOV Device @ B%X|D%X|F%X; ", addr.Addr.Bus, addr.Addr.Device, addr.Addr.Function));
+
+// Device->PciExpress->SriovData = MallocZ(sizeof(PCIE_SRIOV_DATA));
+// ASSERT(Device->PciExpress->SriovData!=NULL);
+
+ //Disable VFs before any further manipulations
+ addr.Addr.ExtendedRegister=SriovCapBaseOffset+PCIE_SRIOV_CNT_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&SrIoVControl.SRIOV_CNT);
+ ASSERT_EFI_ERROR(Status);
+ SrIoVControl.VfEnable = 0;
+ SrIoVControl.VfMse = 0;
+ Status=PciCfg16(Device->RbIo,addr,TRUE,&SrIoVControl.SRIOV_CNT);
+ ASSERT_EFI_ERROR(Status);
+
+ //Initislize System Page Size
+ //get supported page sizes
+ addr.Addr.ExtendedRegister=SriovCapBaseOffset+PCIE_SRIOV_SUPPORTED_PAGE_SIZES_OFFSET;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&PageSize);
+ ASSERT_EFI_ERROR(Status);
+ PCI_TRACE((TRACE_PCI,"PageSize: Sup=0x%X; ", PageSize));
+ if(PageSize){
+ //find the leftmost non-zero bit
+ for(i=1; (PageSize&i)==0 && i!=0; i<<=1) ;
+ ASSERT(i!=0);
+ //set page size
+ addr.Addr.ExtendedRegister=SriovCapBaseOffset+PCIE_SRIOV_SYSTEM_PAGE_SIZE_OFFSET;
+ Status=PciCfg32(Device->RbIo,addr,TRUE,&i);
+ ASSERT_EFI_ERROR(Status);
+ PageSize = 1<<(i+11);
+ }
+ PCI_TRACE((TRACE_PCI,"Progr=0x%X(0x%X); ", i, PageSize));
+
+ //Read InitialFv (number of initially associated VFs)
+ addr.Addr.ExtendedRegister=SriovCapBaseOffset+PCIE_SRIOV_INITIAL_VF_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&InitialFv);
+ ASSERT_EFI_ERROR(Status);
+ PCI_TRACE((TRACE_PCI,"InitialFv=%X; ", InitialFv));
+
+ //Calculate number of buses conumed by VF
+ //Read FirstVfOffset
+ addr.Addr.ExtendedRegister=SriovCapBaseOffset+PCIE_SRIOV_FIRST_VF_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&FirstVfOffset);
+ ASSERT_EFI_ERROR(Status);
+ PCI_TRACE((TRACE_PCI,"FirstVfOffset=%X; ", FirstVfOffset));
+ //Read VfStride
+ addr.Addr.ExtendedRegister=SriovCapBaseOffset+PCIE_SRIOV_VF_STRIDE_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&VfStride);
+ ASSERT_EFI_ERROR(Status);
+ PCI_TRACE((TRACE_PCI,"VfStride=%X; ", VfStride));
+ //Calculate number of busses conusmed by all VF
+ RoutingId = //Request ID of PF
+ (addr.Addr.Bus << 8 ) +
+ (addr.Addr.Device << 3 ) +
+ addr.Addr.Function +
+ FirstVfOffset + (InitialFv-1)*VfStride;
+ VfMaxBus = (UINT8)(RoutingId>>8);
+ PCI_TRACE((TRACE_PCI,"VfMaxBus=%X; ", VfMaxBus));
+ //reserve additional buses consumed by VF
+ mMaxBusFound=VfMaxBus;
+
+ //Read VF BARs
+ addr.Addr.ExtendedRegister=SriovCapBaseOffset+PCIE_SRIOV_VF_BAR0_OFFSET;
+ incr=0;
+ Bar = &Device->PciExpress->SriovData->Bar[0];
+ maxbar = PCI_MAX_BAR_NO;
+ for(i=0; i<maxbar; i++){
+ UINT32 old32, val32;
+ UINT64 old64, val64;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&val32);
+ if(EFI_ERROR(Status)) return Status;
+ ASSERT((val32 & 1)==0) //VF BAR must be MMIO
+ switch (val32 & 0x0F) {
+ case 0x0 :
+ Bar[i].Type=tBarMmio32;
+ Bar[i].DiscoveredType=tBarMmio32;
+ incr=4;
+ break;
+ case 0x4 :
+ Bar[i].Type=tBarMmio64;
+ Bar[i].DiscoveredType=tBarMmio64;
+ incr=8;
+ maxbar--;
+ break;
+ case 0x8 :
+#if PCI_AMI_COMBINE_MEM_PMEM32 == 1
+ Bar[i].Type=tBarMmio32;
+#else
+ Bar[i].Type=tBarMmio32pf;
+#endif
+ Bar[i].DiscoveredType=tBarMmio32pf;
+ incr=4;
+ break;
+ case 0xc :
+ Bar[i].Type=tBarMmio64pf;
+ Bar[i].DiscoveredType=tBarMmio64pf;
+ incr=8;
+ maxbar--;
+ break;
+ default : return EFI_UNSUPPORTED;
+ } //switch
+ Bar[i].ExtOffset=addr.Addr.ExtendedRegister;
+
+ val32=(~0); val64=(~0);
+
+ switch (Bar[i].Type){
+
+ case tBarMmio64pf :
+ case tBarMmio64 :
+ Status=PciCfg64(Device->RbIo,addr,FALSE,&old64);
+ if(EFI_ERROR(Status)) return Status;
+ Status=PciCfg64(Device->RbIo,addr,TRUE,&val64);
+ if(EFI_ERROR(Status)) return Status;
+ Status=PciCfg64(Device->RbIo,addr,FALSE,&val64);
+ if(EFI_ERROR(Status)) return Status;
+ val64&=(~0x0F); //Mask don't care bits
+ if(val64){
+ Bar[i].Gran=(UINTN)(~val64);
+ Bar[i].Length=Mul64((Bar[i].Gran+1),(UINT32)InitialFv);
+ } else {
+ Bar[i].Type=tBarUnused;
+ }
+ break;
+
+ case tBarMmio32pf :
+ case tBarMmio32 :
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&old32);
+ if(EFI_ERROR(Status)) return Status;
+ Status=PciCfg32(Device->RbIo,addr,TRUE,&val32);
+ if(EFI_ERROR(Status)) return Status;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&val32);
+ if(EFI_ERROR(Status)) return Status;
+ val32&=(~0x0F);
+ if(val32){
+ Bar[i].Gran=(~val32);
+ Bar[i].Length=Mul64((Bar[i].Gran+1),(UINT32)InitialFv);
+ } else{
+ Bar[i].Type=tBarUnused;
+ }
+ break;
+
+ default : Bar[i].Type=tBarUnused;
+ }//switch
+
+ //Restore Original Value value
+ if(Bar[i].Type!=tBarUnused){
+ if(Bar[i].Type==tBarMmio64pf || Bar[i].Type==tBarMmio64) Status=PciCfg64(Device->RbIo,addr,TRUE,&old64);
+ else Status=PciCfg32(Device->RbIo,addr,TRUE,&old32);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ Bar[i].Owner = Device;
+ addr.Addr.ExtendedRegister+=incr;
+ } // Bar enumeration loop
+ PCI_TRACE((TRACE_PCI,"\n"));
+ return EFI_SUCCESS;
+}
+#endif
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitDeviceVc()
+//
+// Description: This function will Init VC_DATA structure of the "Device".
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data.
+// PCI_CFG_ADDR *DevAddr Pointer to Device Address value.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InitDeviceVc(PCI_DEV_INFO *Device, PCI_CFG_ADDR *DevAddr){
+ EFI_STATUS Status;
+ VC_DATA *vcd=MallocZ(sizeof(VC_DATA));
+ VC_RES_DATA *vcrd;
+ UINTN i;
+ PCI_CFG_ADDR addr;
+//-----------------
+ addr.ADDR=DevAddr->ADDR;
+ if(!vcd) return EFI_OUT_OF_RESOURCES;
+
+ Device->PciExpress->VcData=vcd;
+ vcd->VcOffset=addr.Addr.ExtendedRegister;
+ //Read and store VC Cap 1 reg
+ addr.Addr.ExtendedRegister=vcd->VcOffset+PCIE_PORTVC_CAP1_OFFSET;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&vcd->VcCap1.PORTVC_CAP1);
+ ASSERT_EFI_ERROR(Status);
+
+ //Read and store VC Cap 2 reg
+ addr.Addr.ExtendedRegister=vcd->VcOffset+PCIE_PORTVC_CAP2_OFFSET;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&vcd->VcCap2.PORTVC_CAP2);
+ ASSERT_EFI_ERROR(Status);
+
+ //Collect VC resource info...
+ for(i=0; i<vcd->VcCap1.ExtVcCnt+vcd->VcCap1.LPExtVcCnt+1; i++){
+ vcrd=MallocZ(sizeof(VC_RES_DATA));
+ if(!vcrd) return EFI_OUT_OF_RESOURCES;
+ addr.Addr.ExtendedRegister=(UINT32)(vcd->VcOffset+PCIE_VC_RES_CAP_OFFSET(i));
+ //Record Offset of the VC resource capability register
+ vcrd->VcResOffset=addr.Addr.ExtendedRegister;
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&vcrd->VcResCap.VC_RESCAP);
+ ASSERT_EFI_ERROR(Status);
+
+ Status=AppendItemLst((T_ITEM_LIST*)&vcd->InitCnt, vcrd);
+ if(EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES;
+ }
+ return Status;
+}
+
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieProbeDevice()
+//
+// Description: This function will collect information about PCIE Device
+// and initialize it based on information collected.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// Notes: The function will do the following steps
+// 1.disable ASPM if any;
+// 2.disable PMI Generation if any;
+// 3.power up PCIE Slot (if capable) if the slot has device behind it;
+// 4.if nothing connected to slot, power it down to make it HOTPLUG READY;
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PcieProbeDevice(PCI_DEV_INFO *Device){
+ PCI_CFG_ADDR addr;
+ PCIE_DEV_CNT_REG devc;
+ PCIE_LNK_CNT_REG lnkc;
+ PCIE_EXT_CAP_HDR extcap;
+ PCIE_LNK_STA_REG lnks;
+ EFI_STATUS Status=0;
+//-------------------------------------
+
+ //init fields that not suppose to be 0
+ Device->PciExpress->MaxL0Lat=0xFFFF;
+ Device->PciExpress->MaxL1Lat=0xFFFF;
+
+ addr.ADDR=Device->Address.ADDR;
+
+ //Get PCI Express CAPs - 16 bit
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_CAP_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&Device->PciExpress->PcieCap.PCIE_CAP);
+ ASSERT_EFI_ERROR(Status);
+
+ Status=PcieGetCaps(Device);
+ ASSERT_EFI_ERROR(Status);
+
+ //Get PCI Express Slot it is valid only for Ports Switches and Bridges
+ if((Device->Type==tPci2PciBrg) || (Device->Type==tPci2CrdBrg)) PcieSetSlotProperties(Device);
+
+ //Disable Device Control Reg functions we'll not need now
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_DEV_CNT_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&devc.DEV_CNT);
+ ASSERT_EFI_ERROR(Status);
+ //Set Default values
+ devc.CorrErrRep=0; //bit 0
+ devc.NfErrRep=0; //bit 1
+ devc.FatalErrRep=0; //bit 2
+ devc.UsupReqRep=0; //bit 3
+ devc.RelaxOrder=1; //bit 4
+ devc.MaxPayload=PCIE_MAXPL_128B;//bit 5..7
+ devc.ExtTagFld=0; //bit 8
+ devc.PhantomFunc=0; //bit 9
+ devc.NoSnoop=1; //bit 11
+ //Don't touch MRR value it might be device dependent and may cause system hung
+ //devc.MaxReadReq=PCIE_MAXPL_512B;//bit 12..14
+
+ Status=PciCfg16(Device->RbIo,addr,TRUE,&devc.DEV_CNT);
+ ASSERT_EFI_ERROR(Status);
+
+ //Get common Lnk Properties from LNK_STA reg..
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_STA_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&lnks.LNK_STA);
+ ASSERT_EFI_ERROR(Status);
+
+ //Update data
+ Device->PciExpress->CurrLnkSpeed=(UINT8)lnks.LnkSpeed;
+ Device->PciExpress->CurrLnkWidth=(UINT8)lnks.LnkWidth;
+
+ //Disable ASPM
+ addr.Addr.Register=Device->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+ Status=PciCfg16(Device->RbIo,addr,FALSE,&lnkc.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+
+ lnkc.AspmControl=PCIE_ASPM_DISABLE;
+ lnkc.ExtSynch=0;
+
+ Status=PciCfg16(Device->RbIo,addr,TRUE,&lnkc.LNK_CNT);
+ ASSERT_EFI_ERROR(Status);
+
+ //Check Pci Express Extended Capability header
+ addr.Addr.ExtendedRegister=0x100;
+ //if something there advance trough EXT capabilities list to find VC Cap
+ while(addr.Addr.ExtendedRegister){
+ Status=PciCfg32(Device->RbIo,addr,FALSE,&extcap.EXT_CAP_HDR);
+ ASSERT_EFI_ERROR(Status);
+ //Check if Extended PciExpress Config Space is assessible.
+ if(extcap.ExtCapId==0xFFFF) break; //(EIP19144+)
+
+ //we've got VC Cap header
+ if(extcap.ExtCapId==PCIE_CAP_ID_VIRTUAL_CH){
+ PCI_TRACE((TRACE_PCI,"PciE2: Found VIRTUAL_CHNL Ext Cap Header @ offset 0x%X\n", addr.Addr.ExtendedRegister));
+ Status=InitDeviceVc(Device, &addr);
+ ASSERT_EFI_ERROR(Status);
+ }
+#if SRIOV_SUPPORT
+ if (extcap.ExtCapId==PCIE_CAP_ID_SRIOV){
+ PCI_TRACE((TRACE_PCI,"PciE2: Found SRIOV Ext Cap Header @ offset 0x%X\n", addr.Addr.ExtendedRegister));
+ Status=CollectDeviceExtCap(Device, &Device->PciExpress->SriovData, sizeof(PCIE_SRIOV_DATA),
+ addr.Addr.ExtendedRegister, FALSE, 0); //32 bit cap register
+ ASSERT_EFI_ERROR(Status);
+
+ Status=ProbeSriovDevice(Device, addr.Addr.ExtendedRegister);
+ ASSERT_EFI_ERROR(Status);
+ }
+#endif
+#if PCI_EXPRESS_GEN2_SUPPORT
+ //Check and collect capability (read only) data from devices
+ //1. Alternative Routing ID capabilities
+ if (extcap.ExtCapId==PCIE_CAP_ID_ARI){
+ PCI_TRACE((TRACE_PCI,"PciE2: Found ARI Ext Cap Header @ offset 0x%X\n", addr.Addr.ExtendedRegister));
+
+ Status=CollectDeviceExtCap(Device, &Device->PciExpress->AriData, sizeof(PCIE2_ARI_DATA),
+ addr.Addr.ExtendedRegister, TRUE, 0); // 16 bit cap reg
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ //2. Access Control Services
+ if (extcap.ExtCapId==PCIE_CAP_ID_ACS){
+ PCI_TRACE((TRACE_PCI," PciE2: Found ACS Ext Cap Header @ offset 0x%X\n", addr.Addr.ExtendedRegister));
+ Status=CollectDeviceExtCap(Device, &Device->PciExpress->AcsData, sizeof(PCIE2_ACS_DATA),
+ addr.Addr.ExtendedRegister, TRUE, 0); // 16 bit cap reg
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ //3. Address Translation services
+ if (extcap.ExtCapId==PCIE_CAP_ID_ATS){
+ PCI_TRACE((TRACE_PCI,"PciE2: Found ATS Ext Cap Header @ offset 0x%X\n", addr.Addr.ExtendedRegister));
+ Status=CollectDeviceExtCap(Device, &Device->PciExpress->AtsData, sizeof(PCIE2_ATS_DATA),
+ addr.Addr.ExtendedRegister, TRUE, 0); // 16 bit cap reg
+ ASSERT_EFI_ERROR(Status);
+ }
+
+#if PCI_EXPRESS_GEN3_SUPPORT
+ //check for Secondary PCIe Extended Capability header.
+ //must be implemented if device supports GEN 3 speed of 8.0 GT/s
+ if (extcap.ExtCapId==PCIE_CAP_ID_SEC_PCIE_CAP){
+ PCI_TRACE((TRACE_PCI,"PciE3: Found SEC PCIe Ext Cap Header @ offset 0x%X\n", addr.Addr.ExtendedRegister));
+ Status=CollectDeviceExtCap(Device, &Device->PciExpress->Pcie3, sizeof(PCIE3_DATA),
+ addr.Addr.ExtendedRegister, FALSE, 4); // 32 bit cap reg
+ ASSERT_EFI_ERROR(Status);
+ }
+#endif
+#endif //gen2 support
+ //4. Internal RC Link
+ if (extcap.ExtCapId==PCIE_CAP_ID_RC_INT_LNK){
+ PCI_TRACE((TRACE_PCI,"PciE2: Found INT_LINK Ext Cap Header @ offset 0x%X\n", addr.Addr.ExtendedRegister));
+ Status=CollectDeviceExtCap(Device, &Device->PciExpress->RcLnkData, sizeof(PCIE_RCLNK_DATA),
+ addr.Addr.ExtendedRegister, FALSE, 0); // 32 bit cap reg
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ addr.Addr.ExtendedRegister=extcap.NextItemPtr;
+ } //while loop serching for ext caps
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+ //if PciExpress Capability Reg if it supports PCIe 2.1
+ if(Device->PciExpress->PcieCap.CapVersion>=PCIE_CAP_VER2){
+ Device->PciExpress->Pcie2=MallocZ(sizeof(PCIE2_DATA));
+ if(Device->PciExpress->Pcie2==NULL){
+ ASSERT_EFI_ERROR(EFI_OUT_OF_RESOURCES);
+ return EFI_OUT_OF_RESOURCES;
+ } else Status=Pcie2GetGen2Info(Device);//Function Will update GEN 3 Properties as well...
+ }
+#endif
+
+ //If device is Upstream Port type add it to an EndPoint device list.
+ if(!PcieIsDownStreamPort(Device) && (Device->Type!= tPci2PciBrg) &&
+ (Device->PciExpress->PcieCap.PortType!=PCIE_TYPE_RC_INTEGR_EP) &&
+ (Device->PciExpress->PcieCap.PortType!=PCIE_TYPE_RC_EVT_COLLECT) &&
+ (Device->ParentBrg->ParentBrg != NULL))
+ {
+ Status=AppendItemLst(&gPcieEpList, Device);
+ PCI_TRACE((TRACE_PCI,"PciE: Adding Device [B%X|D%X|F%X] to gPcieEpList[%d]\n",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device, Device->Address.Addr.Function, gPcieEpList.ItemCount));
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PcieRecordBootScript()
+//
+// Description: This function will create S3 Resume Boot Script
+// for Device's Virtual Channels feature initialization if device
+// supports Virtual Channels.
+//
+// Input:
+// PCI_DEV_INFO *Brg Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID PcieRecordBootScript(PCI_DEV_INFO *Brg){
+ PCI_DEV_INFO *dev;
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(Brg+1);
+ UINTN i,c;
+ PCI_CFG_ADDR addr;
+ EFI_STATUS Status;
+ UINT64 v=0;
+//------------------------------
+ for(i=0; i<ext->ChildCount; i++){
+ dev=ext->ChildList[i];
+ if(!dev->PciExpress) continue;
+ //It could be the case when we have PCI 2 PCI bridges chain and behind
+ //them we will found PCI 2 PCIE bridge. So starting from ROOT we should not
+ //skip bridges without PCIE Capabilities but must go inside and check!
+ //if((dev->PciExpress==NULL) || (dev->Type!=tPci2PciBrg && dev->Type!=tPci2CrdBrg)) continue;
+
+ addr.ADDR=dev->Address.ADDR;
+ addr.Addr.ExtendedRegister=0;
+ //if device is PciExpress check if it has VC
+ if(dev->Type==tPci2PciBrg || dev->Type==tPci2CrdBrg){
+ //record Base bus Subordinste bus Secondary bus registers programming
+ //to have device visible on the bus
+ addr.Addr.Register=PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET;
+
+ Status=PciCfg32(dev->RbIo,addr,FALSE,(UINT32*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ addr.ADDR,1,&v); //Address, Data
+ //call the same function recoursively
+ PcieRecordBootScript(dev);
+
+ }
+ if(dev->PciExpress->VcData){
+ //if(dev->PciExpress!=NULL && dev->PciExpress->VcData!=NULL){
+ for(c=0; c<dev->PciExpress->VcData->VcCount; c++){
+ VC_RES_DATA *vcrd=dev->PciExpress->VcData->VcResData[c];
+ //---------------------------------------
+ addr.Addr.ExtendedRegister=vcrd->VcResOffset+4;
+ Status=PciCfg32(dev->RbIo,addr,FALSE,(UINT32*)&v);
+
+ BOOT_SCRIPT_S3_MEM_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ PCIE_CFG_ADDR(addr.Addr.Bus,addr.Addr.Device,addr.Addr.Function,addr.Addr.ExtendedRegister),
+ 1,&v); //Data
+ }
+ }
+
+ if (gPciSetupData->S3PciExpressScripts){
+ addr.ADDR=dev->Address.ADDR;
+ addr.Addr.Register=dev->PciExpress->PcieOffs+PCIE_DEV_CNT_OFFSET;
+ Status=PciCfg16(dev->RbIo,addr,FALSE,(UINT16*)&v);
+
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint16, //Width
+ addr.ADDR,
+ 1,&v); //Data
+
+ addr.ADDR=dev->Address.ADDR;
+ addr.Addr.Register=dev->PciExpress->PcieOffs+PCIE_LNK_CNT_OFFSET;
+ Status=PciCfg16(dev->RbIo,addr,FALSE,(UINT16*)&v);
+
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint16, //Width
+ addr.ADDR,
+ 1,&v); //Data
+
+ if(dev->PciExpress->PcieCap.SlotImpl){
+ addr.ADDR=dev->Address.ADDR;
+ addr.Addr.Register=dev->PciExpress->PcieOffs+PCIE_SLT_CNT_OFFSET;
+ Status=PciCfg16(dev->RbIo,addr,FALSE,(UINT16*)&v);
+
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint16, //Width
+ addr.ADDR,
+ 1,&v); //Data
+ }
+ if(dev->PciExpress->Pcie2){
+ addr.ADDR=dev->Address.ADDR;
+ addr.Addr.Register=dev->PciExpress->PcieOffs+PCIE_DEV_CNT2_OFFSET;
+ Status=PciCfg16(dev->RbIo,addr,FALSE,(UINT16*)&v);
+
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint16, //Width
+ addr.ADDR,
+ 1,&v); //Data
+
+ addr.ADDR=dev->Address.ADDR;
+ addr.Addr.Register=dev->PciExpress->PcieOffs+PCIE_LNK_CNT2_OFFSET;
+ Status=PciCfg16(dev->RbIo,addr,FALSE,(UINT16*)&v);
+
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint16, //Width
+ addr.ADDR,
+ 1,&v); //Data
+ }
+ } // if (gPciSetupData->S3PciExpressScripts)
+ }//for
+}
+//----------------------------------------------------------------------------
+//Enable PCI Express Handling only if PCI Express Base is Defined and !=0
+#endif //PCI_EXPRESS_SUPPORT
+//----------------------------------------------------------------------------
+
+#if S3_VIDEO_REPOST_SUPPORT == 1
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SaveBars()
+//
+// Description: This function will create S3 Resume Boot Script
+// for Device's BAR Registers.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Device Private Data structure.
+//
+// Output:
+// Nothing.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SaveBars(PCI_DEV_INFO *Dev){
+ UINTN i;
+ PCI_BAR *bar;
+ PCI_CFG_ADDR addr;
+ EFI_STATUS Status;
+ UINT64 v=0;
+ PCI_BRG_EXT *ext;
+//----------------------------
+
+ for( i=0; i < PCI_MAX_BAR_NO+1; i++){
+ bar=&Dev->Bar[i];
+ addr.ADDR=Dev->Address.ADDR;
+ addr.Addr.ExtendedRegister=0;
+
+ if( (bar->Type != tBarUnused) && (bar->Length != 0)){
+ addr.Addr.Register=bar->Offset;
+ if( (Dev->Bar[0].DiscoveredType == tBarMmio64) || (Dev->Bar[0].DiscoveredType == tBarMmio64pf)){
+ Status=PciCfg64(Dev->RbIo,addr,FALSE,&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint64, //Width
+ addr.ADDR,1,&v); //Address, Data
+ } else {
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,(UINT32*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ addr.ADDR,1,&v); //Address, Data
+ }
+ }
+ } //for
+
+ //if device is p2p bridge
+ if( Dev->Type == tPci2PciBrg){
+ //get bridge extension structure pointer
+ ext=(PCI_BRG_EXT*)(Dev+1);
+
+ //For IO 16 Resources Decoded by the bridge
+ addr.Addr.Register = ext->Res[rtIo16].Offset;
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,(UINT16*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint16, //Width
+ addr.ADDR,1,&v); //Address, Data
+ //Upper 16bits for IO window
+ addr.Addr.Register = 0x30;
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,(UINT32*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ addr.ADDR,1,&v); //Address, Data
+
+
+ //For MMIO Resources Decoded by the bridge
+ addr.Addr.Register = ext->Res[rtMmio32].Offset;
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,(UINT32*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ addr.ADDR,1,&v); //Address, Data
+
+ //For MMIO_PF
+ addr.Addr.Register = ext->Res[rtMmio32p].Offset;
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,(UINT32*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ addr.ADDR,1,&v); //Address, Data
+
+ //For MMIO_PF Upper 32 bit
+ addr.Addr.Register = 0x28;
+ Status=PciCfg64(Dev->RbIo,addr,FALSE,&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint64, //Width
+ addr.ADDR,1,&v); //Address, Data
+ }
+
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SaveDevice()
+//
+// Description: This function will create S3 Resume Boot Script
+// for Device's other than BAR Registers.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Device Private Data structure.
+//
+// Output:
+// Nothing.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SaveDevice(PCI_DEV_INFO *Dev){
+ PCI_CFG_ADDR addr;
+ EFI_STATUS Status;
+ UINT64 v=0;
+//----------------------------
+ addr.ADDR=Dev->Address.ADDR;
+ addr.Addr.ExtendedRegister=0;
+
+ //get Cache line size and Latency Timer + ProgInterface
+ addr.Addr.Register=PCI_CLS;
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,(UINT32*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ addr.ADDR,1,&v); //Address, Data
+
+ //Save content of BARs
+ SaveBars(Dev);
+
+ //get IntLine; IntPin; MaxLat; MinGnt
+ addr.Addr.Register=PCI_INTLINE;
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,(UINT32*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ addr.ADDR,1,&v); //Address, Data
+
+
+
+ //if device is Pci2PciBrg
+ if( Dev->Type == tPci2PciBrg){
+
+ //get Base bus Subordinste bus Secondary bus registers + Secondary Latency Timer
+ addr.Addr.Register=PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET;
+
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,(UINT32*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ addr.ADDR,1,&v); //Address, Data
+
+
+ } else {
+ //Get Subsystem VID; DID Just In case...
+ addr.Addr.Register=PCI_SVID;
+ Status=PciCfg32(Dev->RbIo,addr,FALSE,(UINT32*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint32, //Width
+ addr.ADDR,1,&v); //Address, Data
+
+ }
+
+ //Now get Device Control Reg
+ addr.Addr.Register=PCI_COMMAND_REGISTER_OFFSET;
+ Status=PciCfg16(Dev->RbIo,addr,FALSE,(UINT16*)&v);
+ BOOT_SCRIPT_S3_PCI_CONFIG_WRITE_MACRO(
+ gBootScriptSave, //This
+ EfiBootScriptWidthUint16, //Width
+ addr.ADDR,1,&v); //Address, Data
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RecordPriVgaBootScript()
+//
+// Description: This function will create S3 Resume Boot Script
+// for Device's on the path of primary VGA Device inclusive.
+//
+// Input:
+// Nothing
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID RecordPriVgaBootScript(IN EFI_EVENT Event, IN VOID *Context){
+ PCI_DEV_INFO *vga=NULL;
+ PCI_DEV_INFO *dev;
+ PCI_HOST_INFO *hst=&gPciHost[0];
+ PCI_BRG_EXT *ext;
+ T_ITEM_LIST VgaPath={0,0,NULL};
+ INTN i;
+ UINTN j;
+ EFI_STATUS Status;
+//------------------------------
+ for( i=0; (UINTN)i<gHostCnt; i++){
+ hst=&gPciHost[i];
+ //There might be only one legacy VGA device in the system
+ if( hst->VgaDev!=0){
+ vga=hst->VgaDev;
+ break;//there will be only one Primary VGA
+ }
+ }
+
+ //If we can't find Primery VGA device just exit
+ //Most likely we are dealing here with headless system.
+ if( vga == NULL){
+ return;
+ }
+
+ dev = vga;
+ //Save Device pointers in Current Primary Vga Path
+ while (dev!=NULL){
+ Status=AppendItemLst(&VgaPath,dev);
+ dev=dev->ParentBrg;
+ }
+
+ //Now write the boot script in opposite order for the devices stored @ VgaPath object.
+ //So the script will go from Host Bridge down to the Pri VGA device
+ for(i=VgaPath.ItemCount-1; i>=0;i--){
+ dev=(PCI_DEV_INFO*)VgaPath.Items[i];
+
+ //Save device content into BOOT SCRIPT
+ SaveDevice(dev);
+
+ //Now check if device is a multifunction device
+ //if so it's other functions needs to be saved as well
+ if( ( dev->ParentBrg !=NULL) && ( dev->Type != tPci2PciBrg)){
+
+ ext = (PCI_BRG_EXT*)(dev->ParentBrg+1);
+ //check for devices with the same Dev# but different Function# among device's ParentBridge childs...
+ for(j=0; j<ext->ChildCount; j++){
+ vga=ext->ChildList[j];
+ //Since this is one bridge childs they have to have same bus
+ if(vga->Address.Addr.Device == dev->Address.Addr.Device &&
+ vga->Address.Addr.Function != dev->Address.Addr.Function) {
+ SaveDevice(vga);
+ }
+
+ }//for j
+ }
+ }//for i
+
+ pBS->CloseEvent(Event);
+}
+#endif //S3_VIDEO_REPOST
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ResetDevicePm()
+//
+// Description: This function will turn off SMI generation on PCI PME
+// and put device in to D0 state, if device has PM capability.
+//
+// Input:
+// PCI_DEV_INFO *Brg Pointer to PCI Device Private Data structure.
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ResetDevicePm(PCI_DEV_INFO *Device)
+{
+ EFI_STATUS Status;
+ PCI_CFG_ADDR devaddr;
+ UINT16 pmcsrv=0x8000;//Turn off the PME assertion and set D0 PM State
+//-------------------------------
+
+ if(Device->PmiCapOffs){
+ devaddr.ADDR=Device->Address.ADDR;
+ devaddr.Addr.Register=(UINT8)(Device->PmiCapOffs+4); //
+ Status=PciCfg16(Device->RbIo,devaddr,TRUE,&pmcsrv);
+ ASSERT_EFI_ERROR(Status);
+ }
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: QueryPciDevice()
+//
+// Description: This function will collect all possible data about PCI Device.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS QueryPciDevice(PCI_DEV_INFO *Device)
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ UINT8 maxbar, i, incr=0;
+ UINT64 buff=0xff, oldv;
+ PCI_CFG_ADDR devaddr;
+ UINT32 *b32=&(UINT32)buff, *o32=&(UINT32)oldv;
+//------------------------------------------
+
+ //for accuracy
+ Device->Address.Addr.Register=0;
+ Device->Address.Addr.ExtendedRegister=0;
+ devaddr.ADDR=Device->Address.ADDR;
+
+ PCI_TRACE((TRACE_PCI,"PciBus: Discovered PCI Device @ [B%X|D%X|F%X]; PCI_DEV_INFO.Type=%d.\n Device Data: -> ",
+ Device->Address.Addr.Bus, Device->Address.Addr.Device,
+ Device->Address.Addr.Function, Device->Type));
+
+ //Clear Interrupt line register
+ devaddr.Addr.Register=PCI_INTLINE;
+ //P2P Bridge Spec. v1.1 requires to set INT Line Register to 0xFF
+ //PCI spec 3.0 require to set it to 0xFF - means not connected for x86 architecture.
+ //Values of 0..0x0F indicating IRQ0..15 values 0x10..0xFE reserved.
+ Status=PciCfg8(Device->RbIo,devaddr,TRUE,(UINT8*)&buff);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //We must call Preprocess Controller
+ Status=DoPrepController(Device);
+
+ Status=GetDeviceCapabilities(Device);
+
+ Status=GetPciCapPtrs(Device);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ ResetDevicePm(Device);
+
+ //Set Pci Latency Timer register according to the Setup settings;
+ devaddr.Addr.Register = 0x0d;
+ Status=PciCfg8(Device->RbIo,devaddr,TRUE,(UINT8*)&gPciSetupData->PciLatency);
+ if((Device->Type == tPci2PciBrg) || (Device->Type == tPci2CrdBrg)){
+ devaddr.Addr.Register = 0x1b;
+ Status=PciCfg8(Device->RbIo,devaddr,TRUE,(UINT8*)&gPciSetupData->PciLatency);
+ }
+
+#if PCI_X_SUPPORT
+ //Set PCI-X Latency Timer register according to the Setup settings;
+ devaddr.Addr.Register = 0x0d;
+ Status=PciCfg8(Device->RbIo,devaddr,TRUE,(UINT8*)&gPciSetupData->PciXLatency);
+ if((Device->Type == tPci2PciBrg) || (Device->Type == tPci2CrdBrg)){
+ devaddr.Addr.Register = 0x1b;
+ Status=PciCfg8(Device->RbIo,devaddr,TRUE,(UINT8*)&gPciSetupData->PciXLatency);
+ }
+#endif
+
+//Enables PCI Express Handling only if PCI Express Base is Defined and !=0
+#if PCI_EXPRESS_SUPPORT
+
+ if(Device->PciExpress) {
+ Status=PcieProbeDevice(Device);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+/*
+ //If it is end point Device or PCIE 2 PCI bridge
+ if(
+ Device->PciExpress->PcieCap.PortType==PCIE_TYPE_LEGACYEP||
+ Device->PciExpress->PcieCap.PortType==PCIE_TYPE_PCIE_PCI||
+ Device->PciExpress->PcieCap.PortType==PCIE_TYPE_RC_INTEGR_EP ||
+ Device->PciExpress->PcieCap.PortType==PCIE_TYPE_RC_EVT_COLLECT)
+ {
+ //Programm Common Clock it will affect ASPM latency of the devices
+ //So it has to be programmed first before collecting all the information about
+ //Device Max PLoad ant reqd request and ep Latency.
+ Status=PcieSetClockConfig(Device);
+ ASSERT_EFI_ERROR(Status);
+
+ //Programm MaxPayLoad, ReadRequest ASPM settings
+ Status=PcieInitDevChain(Device);
+ ASSERT_EFI_ERROR(Status);
+ }
+*/
+ }
+#endif
+
+ if(CheckPciCompatibility(Device,NULL,tBarUnused))Device->Incompatible=TRUE; //(EIP41687)
+ switch (Device->Type){
+ case tPci2PciBrg :
+ maxbar=2;
+ devaddr.Addr.Register=0x10; //first BAR starts here
+ break;
+ case tPciDevice :
+ case tPciHostDev:
+ maxbar=PCI_MAX_BAR_NO;
+ devaddr.Addr.Register=0x10; //first BAR starts here
+ break;
+ case tPci2CrdBrg :
+ maxbar=1;
+ devaddr.Addr.Register=0x10; //first BAR starts here
+ break;
+ default : return EFI_SUCCESS; //other devices not suppose to be examined????
+ }
+
+ for(i=0; i<maxbar; i++){
+ buff=0;
+ oldv=0;
+ devaddr.Addr.Register=devaddr.Addr.Register+incr;
+ Status=PciCfg32(Device->RbIo,devaddr,FALSE,b32);
+ if(EFI_ERROR(Status)) return Status;
+
+ //check if what it is...
+ if((*b32) & 1) {
+ Device->Bar[i].Type=tBarIo;
+ incr=4;
+ } else {
+ switch ((*b32) & 0x0F) {
+ case 0x0 :
+ Device->Bar[i].Type=tBarMmio32;
+ Device->Bar[i].DiscoveredType=tBarMmio32;
+ incr=4;
+ break;
+ case 0x4 :
+ Device->Bar[i].Type=tBarMmio64;
+ Device->Bar[i].DiscoveredType=tBarMmio64;
+ incr=8;
+ maxbar--;
+ break;
+ case 0x8 :
+#if PCI_AMI_COMBINE_MEM_PMEM32 == 1
+ Device->Bar[i].Type=tBarMmio32;
+#else
+ Device->Bar[i].Type=tBarMmio32pf;
+#endif
+ Device->Bar[i].DiscoveredType=tBarMmio32pf;
+ incr=4;
+ break;
+ case 0xc :
+ Device->Bar[i].Type=tBarMmio64pf;
+ Device->Bar[i].DiscoveredType=tBarMmio64pf;
+ incr=8;
+ maxbar--;
+ break;
+ default : return EFI_UNSUPPORTED;
+ } //switch
+ }// else for memory BAR
+ Device->Bar[i].Offset=devaddr.Addr.Register;
+ //Device->Bar[i].Owner=Device;
+
+ buff=(~0ULL);
+
+ switch (Device->Bar[i].Type){
+
+ case tBarMmio64pf :
+ case tBarMmio64 :
+ Status=PciCfg64(Device->RbIo,devaddr,FALSE,&oldv);
+ if(EFI_ERROR(Status)) return Status;
+ Status=PciCfg64(Device->RbIo,devaddr,TRUE,&buff);
+ if(EFI_ERROR(Status)) return Status;
+ Status=PciCfg64(Device->RbIo,devaddr,FALSE,&buff);
+ if(EFI_ERROR(Status)) return Status;
+ buff&=(~0x0F); //Mask don't care bits
+ if(buff){
+ //This workaround done for PCI Compliance Test...
+ //It could be the BAR that clames - "I'm a 64bit BAR",
+ //but implemented as 32bit register. This BAR will not hold
+ //64bit address and must be converted to 32bit BAR.
+ if(buff<=0xFFFFFFFF) {
+ buff|=0xFFFFFFFF00000000;
+ Device->Bar[i].Type-=2; //reduce tBarType to 32 bit BAR
+ }
+ Device->Bar[i].Gran=(UINTN)(~buff);
+ if(Device->Incompatible) AdjustBarGra(&Device->Bar[i]);
+ if(Device->Bar[i].Type==tBarUnused) {
+ Status=PciCfg64(Device->RbIo,devaddr,TRUE,&oldv);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ Device->Bar[i].Length=Device->Bar[i].Gran+1;
+ } else Device->Bar[i].Type=tBarUnused;
+ break;
+
+ case tBarMmio32pf :
+ case tBarMmio32 :
+ case tBarIo :
+ Status=PciCfg32(Device->RbIo,devaddr,FALSE,o32);
+ if(EFI_ERROR(Status)) return Status;
+ Status=PciCfg32(Device->RbIo,devaddr,TRUE,b32);
+ if(EFI_ERROR(Status)) return Status;
+ Status=PciCfg32(Device->RbIo,devaddr,FALSE,b32);
+ if(EFI_ERROR(Status)) return Status;
+ if(Device->Bar[i].Type==tBarIo){
+ (*b32)&=(~0x03);
+ if(*b32){
+ //We got something here try to determine is it 32 bit addressing IO
+ //of 16 bit addressing
+ if(*b32&0xFFFF0000) {
+ Device->Bar[i].Type=tBarIo32;
+ Device->Bar[i].DiscoveredType=tBarIo32;
+ } else {
+ (*b32)|=(0xffff0000);
+ Device->Bar[i].Type=tBarIo16;
+ Device->Bar[i].DiscoveredType=tBarIo16;
+ }
+ }
+ } else (*b32)&=(~0x0F);
+ if(*b32){
+ Device->Bar[i].Gran=(~(*b32));
+ if(Device->Incompatible) AdjustBarGra(&Device->Bar[i]);
+ if(Device->Bar[i].Type==tBarUnused) {
+ Status=PciCfg32(Device->RbIo,devaddr,TRUE,o32);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ Device->Bar[i].Length=Device->Bar[i].Gran+1;
+ //Doing work around for resource requirements for I/O
+ //where request is lesser than 16 bytes. I'll just make it 16
+ //it might be some compatibility issues if I/O resourtce alignment will be
+ // lesser than 8 byte
+ if((Device->Bar[i].Type==tBarIo32 || Device->Bar[i].Type==tBarIo16)&&
+ Device->Bar[i].Length<0x10)
+ {
+ Device->Bar[i].Length=0x10;
+ Device->Bar[i].Gran=0x0F;
+ }
+
+ } else Device->Bar[i].Type=tBarUnused;
+ break;
+
+ default : Device->Bar[i].Type=tBarUnused;
+ }//switch
+
+ //Restore Original Value value
+ if(Device->Bar[i].Type!=tBarUnused){
+ if(Device->Bar[i].Type==tBarMmio64pf || Device->Bar[i].Type==tBarMmio64) Status=PciCfg64(Device->RbIo,devaddr,TRUE,&oldv);
+ else Status=PciCfg32(Device->RbIo,devaddr,TRUE,o32);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+//Check that all MMIO is allocated in 4k aligned chanks IVT-d requirements
+#if( (defined iVTd_SUPPORT && iVTd_SUPPORT == 1) || ( PCI_4K_RESOURCE_ALIGNMENT == 1 ) || (SRIOV_SUPPORT == 1) )
+//---------------------------------------------
+ if((Device->Bar[i].Type==tBarMmio64pf || Device->Bar[i].Type==tBarMmio64 ||
+ Device->Bar[i].Type==tBarMmio32pf || Device->Bar[i].Type==tBarMmio32) &&
+ Device->Bar[i].Length<0x1000 ) {
+ Device->Bar[i].Length=0x1000;
+ Device->Bar[i].Gran=0xFFF;
+ }
+//---------------------------------------------
+#endif
+
+ } // Bar enumeration loop
+
+ if(Device->Type==tPci2CrdBrg){
+ //Clear Brg Control Reg bits 8 & 9 to signify that Mem Window 1&2 is not PF
+ devaddr.Addr.Register=PCI_BRIDGE_CONTROL_REGISTER_OFFSET;
+ Status=PciCfg16(Device->RbIo,devaddr,FALSE,(UINT16*)&buff);
+ ASSERT_EFI_ERROR(Status);
+ buff&=(~(BIT09 | BIT08)); //Memory Window 2 is nonPF
+ Status=PciCfg16(Device->RbIo,devaddr,TRUE,(UINT16*)&buff);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ //now we're going to check if any Option ROM present
+ Status=OptionRom(Device);
+#if EFI_DEBUG
+ for(i=0; i<=PCI_MAX_BAR_NO; i++){
+
+ if((Device->Bar[i].Type>0) && (Device->Bar[i].Length>0))
+ {
+ PCI_TRACE((TRACE_PCI,"BAR Index=%d;\tType=%d;\tGRA=0x%lX;\tLEN=0x%lX;\tOffset=0x%X;\n",
+ i, Device->Bar[i].Type, Device->Bar[i].Gran,
+ Device->Bar[i].Length, Device->Bar[i].Offset));
+ }
+ }
+ PCI_TRACE((TRACE_PCI,"\n"));
+#endif
+
+ Device->Discovered=TRUE;
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ApplyCrdPadding()
+//
+// Description: This function applys default Card Bus Bridge Padding.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to PCI Device Private Data structure.
+// MRES_TYPE ResType Type of resource padding is applied.
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ApplyCrdPadding(PCI_DEV_INFO *Device, MRES_TYPE ResType){
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(Device+1);
+ PCI_BAR *bbar=&ext->Res[ResType];
+//---------------
+
+ bbar->Type=ResType+1;
+ switch(ResType){
+ case rtIo16:
+ bbar->Length+=0x1000;
+ if(bbar->Gran < 0xFFF) bbar->Gran=0xFFF;
+ break;
+
+ case rtIo32:
+ if(CPU_MAX_IO_SIZE <= 0x10000) {
+ bbar->Type=tBarUnused;
+ bbar=&ext->Res[ResType-1];
+ }
+ bbar->Length+=0x1000;
+ if(bbar->Gran < 0xFFF) bbar->Gran=0xFFF;
+ break;
+
+ case rtMmio32:
+ bbar->Length+=0x1400000;
+ if(bbar->Gran < 0xFFFFF) bbar->Gran=0xFFFFF;
+ break;
+
+ case rtMmio32p:
+ if (gAllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) {
+ bbar->Type=tBarUnused;
+ bbar=&ext->Res[ResType-1];
+ }
+ bbar->Length+=0x1400000;
+ if(bbar->Gran < 0xFFFFF) bbar->Gran=0xFFFFF;
+ break;
+ case rtMmio64:
+ case rtMmio64p:
+ bbar->Type=tBarUnused;
+ break;
+ }
+
+ ext->Padded=TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Cmp128Int()
+//
+// Description: This function compares 2 128 bit integers.
+//
+// Input:
+// VOID* pDestination *Pointer to the 128bit Integer to compare.
+// VOID* pSource *Pointer to the 128bit Integer to compare.
+//
+// Output: INTN
+// == 0 Destination and are Source equal;
+// > 0 Destination is bigger than Source;
+// < 0 Destination is lesser than Source;
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+INTN Cmp128Int(VOID* pDestination, VOID* pSource){
+ INT64 r;
+ UINT64 *d=(UINT64*)pDestination;
+ UINT64 *s=(UINT64*)pSource;
+//----------------------------------
+ r = d[1] - s[1];
+ if( r == 0){
+ r = d[0] - s[0];
+ }
+ return (r>0) ? 1 : (r<0) ? -1 : 0;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Cmp128IntRR()
+//
+// Description: This function compares 2 128 bit integers with respect to EFI
+// Database Engine Record to Record comparation Routine.
+// When position of record gets determined.
+//
+// Input:
+// VOID* pContext Pointer to the DBE_OFFSET_KEY_CONTEXT structure
+// VOID* pRecord1 Pointer to the 128bit Integer to compare.
+// VOID* pRecord2 Pointer to the 128bit Integer to compare.
+//
+// Output: INTN
+// == 0 pRecord1 and are pRecord2 equal;
+// > 0 pRecord1 is bigger than pRecord2;
+// < 0 pRecord2 is lesser than pRecord2;
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+INTN Cmp128IntRR(IN VOID *pContext, VOID *pRecord1, VOID *pRecord2)
+{
+ DBE_OFFSET_KEY_CONTEXT *pOffsetKey = (DBE_OFFSET_KEY_CONTEXT*)pContext;
+//--------------------------
+ return Cmp128Int((VOID*)((INT8*)pRecord1+pOffsetKey->Offset),(VOID*)((INT8*)pRecord2+pOffsetKey->Offset));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Cmp128IntKR()
+//
+// Description: This function compares 2 128 bit integers with respect to EFI
+// Database Engine Key to Record comparation Routine.
+// When search for record is conducted.
+//
+// Input:
+// VOID* pContext Pointer to the DBE_OFFSET_KEY_CONTEXT structure
+// VOID* pRecord1 Pointer to the 128bit Integer to compare.
+// VOID* pRecord2 Pointer to the 128bit Integer to compare.
+//
+// Output: INTN
+// == 0 pRecord1 and are pRecord2 equal;
+// > 0 pRecord1 is bigger than pRecord2;
+// < 0 pRecord2 is lesser than pRecord2;
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+INTN Cmp128IntKR(IN DBE_OFFSET_KEY_CONTEXT *pContext, VOID *pKey, VOID *pRecord)
+{
+ DBE_OFFSET_KEY_CONTEXT *pOffsetKey = (DBE_OFFSET_KEY_CONTEXT*)pContext;
+//------------------------------
+ return Cmp128Int((VOID*)pKey,(VOID*)((INT8*)pRecord+pOffsetKey->Offset));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FreeResDb()
+//
+// Description: This function suppore to free memory allocated for index array
+// pool of the EFI Database Engine DATABASE.
+//
+// Input:
+// DBE_DATABASE* Db Pointer to the EFI Database Engine DATABASE.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS if everything OK;
+// an EFI_ERROR if an ERROR
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FreeResDb(DBE_DATABASE *Db){
+ if(Db->IndexArray!=NULL)return pBS->FreePool(Db->IndexArray);
+ else return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitResDb()
+//
+// Description: This function suppore to initialize EFI Database Engine DATABASE
+// with PCI_BAR pointers in decending order.
+//
+// Input:
+// DBE_DATABASE* Db Pointer to the EFI Database Engine DATABASE.
+// PCI_DEV_INFO* Brg, Bridge whose BARs must be stuffed in DATABASE.
+// MRES_TYPE ResType Resource type of the BARs.
+// BOOLEAN Dev We are filling DATABASE with Bridges or Devices.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS if everything OK;
+// an EFI_ERROR if an ERROR
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InitResDb(DBE_DATABASE *Db, PCI_DEV_INFO *Brg, MRES_TYPE ResType, BOOLEAN Dev){
+ EFI_STATUS Status=0;
+ PCI_DEV_INFO *dev;
+ PCI_BRG_EXT *Ext=(PCI_BRG_EXT*)(Brg+1);
+ UINTN i,j;
+//------------------------------------
+
+ //Initialize Optimization Database
+ Db->KeyCount=1;
+ Db->KeyField=&gBarKey;
+ Db->MemoryType=EfiBootServicesData;
+ Db->RecordCount=0;
+
+ if(Dev)Db->InitialCount=0x30; //least likely it would be more than 48 BARs of the same type
+ else Db->InitialCount=0x10; //same 16 for the bridges, but anyway it would be realocated...
+
+ Status=pBS->AllocatePool(Db->MemoryType,sizeof(VOID*)*Db->InitialCount,&Db->IndexArray);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Now we will stuff the database with resource requirements sorted in assending order
+ for(i=0; i<Ext->ChildCount; i++){
+ dev=Ext->ChildList[i];
+
+ if(dev->OutOfResRemove) continue;
+
+ if(Dev){
+ for( j=0; j<PCI_MAX_BAR_NO+1; j++){
+ //Use ResType+1 Since CountBars() takes diferent type of parameter -
+ //PCI_BAR_TYPE. It mapps to MRES_TYPE as MRES_TYPE+1
+ if ((dev->Bar[j].Type==ResType+1) && dev->Bar[j].Length){
+ Status=DbeInsert(Db,&dev->Bar[j]);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ }//bar loop
+#if SRIOV_SUPPORT
+ if (dev->PciExpress!=NULL && dev->PciExpress->SriovData!=NULL){
+ PCI_BAR *VfBar = &dev->PciExpress->SriovData->Bar[0];
+ for( j=0; j<PCI_MAX_BAR_NO; j++){
+ //Use ResType+1 Since CountBars() takes diferent type of parameter -
+ //PCI_BAR_TYPE. It mapps to MRES_TYPE as MRES_TYPE+1
+ if ((VfBar[j].Type==ResType+1) && VfBar[j].Length){
+ Status=DbeInsert(Db,&VfBar[j]);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ }//bar loop
+ }
+#endif
+ } else {
+ //take care of the bridge
+ if(dev->Type==tPci2PciBrg || dev->Type==tPci2CrdBrg){
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(dev+1);
+ //-----------------------
+ //Don't add empry bridge BARs
+ if((ext->Res[ResType].Type==ResType+1) && ext->Res[ResType].Length ){
+ Status=DbeInsert(Db,&ext->Res[ResType]);
+ if(EFI_ERROR(Status)) Status;
+ }
+ }
+ }
+ } //child loop
+
+// if(!Db->RecordCount)Status=EFI_NOT_FOUND;
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AppendBarOrder()
+//
+// Description: This function suppore to fill array of BAR ORDER with actual
+// order of PCI_BARs behind the Bridge and remove added BAR structure from
+// the BAR DATABASE.
+//
+// Input:
+// DBE_DATABASE* Db Pointer to the EFI Database Engine DATABASE.
+// BRG_RES_ORDER* BrgResOrder Pointer to the Bridge Resource order structure.
+// PCI_BAR Bar Pointer to the BAR structure to be added.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS if everything OK;
+// an EFI_ERROR if an ERROR
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AppendBarOrder(DBE_DATABASE *Db, BRG_RES_ORDER *BrgResOrder, PCI_BAR *Bar){
+ EFI_STATUS Status;
+//--------------------------
+ Status=AppendItemLst((T_ITEM_LIST*)BrgResOrder, Bar);
+ if(EFI_ERROR(Status))return Status;
+
+ //Remove copied record from Database it not suppose to clear the *bar variable;
+ Status=DbeDelete(Db,Bar,FALSE);
+
+ PCI_TRACE((TRACE_PCI," BAR: Len=0x%lX;\t Gra=0x%lX;\t Ofs=0x%X; Owner->[B%X|D%X|F%X] DEV_TYPE=%d\n",
+ Bar->Length, Bar->Gran, Bar->Offset, Bar->Owner->Address.Addr.Bus,
+ Bar->Owner->Address.Addr.Device, Bar->Owner->Address.Addr.Function, Bar->Owner->Type));
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: OptimizeBrgResource()
+//
+// Description: This function arrange Bridge resource request in a way it will
+// consume a optimal amount of resources.
+//
+// Input:
+// PCI_DEV_INFO* Brg, Bridge whose BARs must be stuffed in DATABASE.
+// MRES_TYPE ResType Resource type we are doing optimization for.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS if everything OK;
+// an EFI_ERROR if an ERROR
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS OptimizeBrgResource(PCI_DEV_INFO *Brg, MRES_TYPE ResType){
+ EFI_STATUS Status=0;
+ PCI_DEV_INFO *dev; //Device Dtata used for iteration,
+ PCI_DEV_INFO *brg; //Bridge Device used to identify Bridge resources with uneven Granularity.
+ PCI_BRG_EXT *Ext=(PCI_BRG_EXT*)(Brg+1),*ext; //This Bridge Bridge Extension Data.
+ UINTN i;
+ PCI_BAR *bar,*bbar,*nbbar,*nextbar; //temp BAR used in iterations, This Bridge child who is the bridge.
+ BRG_ALIGN_INFO *balign;
+ PCI_BAR *ebar;
+ BRG_RES_ORDER *ResOrd=&Ext->BarOrder[ResType]; //This Bridge this bridge Resource Alignment information
+ DBE_DATABASE DevDb={0,0,0,0,NULL,NULL},BrgDb={0,0,0,0,NULL,NULL};
+ INT8 v;
+ UINT64 val;
+ UINT8 bit;
+//------------------------------------
+
+ //No childs behind the bridge, no optimization...
+ if(!Ext->ChildCount)return EFI_SUCCESS;
+ PCI_TRACE((TRACE_PCI,"PciBus: OptimizeBrgRes() Bridge->[B%X|D%X|F%X] PCI_BRG_EXT.Res[%d] :\n",
+ Brg->Address.Addr.Bus, Brg->Address.Addr.Device, Brg->Address.Addr.Function, ResType));
+
+
+ //Start the optimization
+ //1. Create Assending Sorted Database of all PCI Devices BARs behind the Brg of ResType.
+ Status=InitResDb(&DevDb, Brg, ResType, TRUE);
+ if(EFI_ERROR(Status)) goto ExitLbl;
+
+ Status=InitResDb(&BrgDb, Brg, ResType, FALSE);
+ if(EFI_ERROR(Status)) goto ExitLbl;
+
+ PCI_TRACE((TRACE_PCI," BAR(s) Order for %d Device BAR(s); %d Bridge BAR(s) of BAR_TYPE=%d\n",
+ DevDb.RecordCount, BrgDb.RecordCount, ResType+1));
+
+ //2. Start Populating Resource Array Brg->BarOrder[ResType]
+ while(DevDb.RecordCount || BrgDb.RecordCount){
+
+ if(BrgDb.RecordCount){
+ Status=DbeGoToIndex(&BrgDb,0,BrgDb.RecordCount-1,&bbar);
+ if(EFI_ERROR(Status)){
+ if(!((Status==EFI_DBE_EOF) || (Status==EFI_DBE_BOF))){
+ ASSERT_EFI_ERROR(Status);
+ goto ExitLbl;
+ }
+ }
+ } else bbar=NULL;
+
+ if(DevDb.RecordCount){
+ Status=DbeGoToIndex(&DevDb,0,DevDb.RecordCount-1,&bar);
+ if(EFI_ERROR(Status)){
+ if(!((Status==EFI_DBE_EOF) || (Status==EFI_DBE_BOF))){
+ ASSERT_EFI_ERROR(Status);
+ goto ExitLbl;
+ }
+ }
+ } else bar=NULL;
+
+ //Check if THIS Bridge has a bridge childs
+ if((bar!=NULL) && (bbar!=NULL)){
+ //This case when we have bridge resourses among regular device resources
+ brg=bbar->Owner;
+ dev=bar->Owner;
+ ext=(PCI_BRG_EXT*)(brg+1);
+ balign=&ext->Align[ResType];
+
+ //1. Check first if Biggest resource in "BrgDb" - "bbar" has the same or lesser
+ //Alignment Requirements as a Biggest one in "DevDb" - "bar". balign->MaxGran
+ if(bar->Gran >= balign->MaxGran){
+ Status=AppendBarOrder(&DevDb,ResOrd, bar);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto ExitLbl;
+ } else {
+ //This is the case when we should use PCI_BRG_EXT.ExtraRes[ResType] information to accomodate
+ //resources with lower granularity to utilize spase used to adjust uneven bridge granularity
+ Status=AppendBarOrder(&BrgDb,ResOrd, bbar);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto ExitLbl;
+
+ //Determine how much Extra resources we will use here
+ ebar=&balign->ExtraRes;
+ if(bbar->Length & bbar->Gran){
+ //Here we have add the biggest bridge resource to the BarOrdedr DB.
+ //We have yet Biggrest Dev Resource. Let's see if there are any Bridge resources left
+ if(BrgDb.RecordCount){
+ Status=DbeGoToIndex(&BrgDb,0,BrgDb.RecordCount-1,&nbbar);
+ if(EFI_ERROR(Status)){
+ if(!((Status==EFI_DBE_EOF) || (Status==EFI_DBE_BOF))){
+ ASSERT_EFI_ERROR(Status);
+ goto ExitLbl;
+ }
+ }
+ } else nbbar=NULL;
+ //Now see which bar (nbbar-NextBridgeBar) if any, or bar-DeviceBar will be the next
+ //member in BarOrder Database.
+ if(nbbar!=NULL){
+ if(bar->Gran>=nbbar->Gran)nextbar=bar;
+ else nextbar=nbbar;
+ } else nextbar=bar;
+
+ //Determine how much Extra resources we will use here
+ //if we got here - the Bridge resource request, we just added to the BarOrder DB, has uneven alignment
+ //Here we have:
+ //bbar - already added to the BarOrder DB;
+ //nextbar - biggest resource following by the bbar;
+ //bar - biggest Device Bar evenly aligned ;
+ if(nextbar->Gran <= balign->ResGran) {
+ //if next biggest bar has Alignment requirements lesser or equal to the bbar just added
+ //GREAT! We will just add it and forget it;
+ if(nextbar==bar)Status=AppendBarOrder(&DevDb,ResOrd, nextbar);
+ else Status=AppendBarOrder(&BrgDb,ResOrd, nextbar);
+
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto ExitLbl;
+
+ } else {
+ ebar->Length=(( bbar->Length | nextbar->Gran )+1)-bbar->Length;
+ bit=FindFirstBit(ebar->Length-1,FALSE);
+ ebar->Gran=Shr64((~0ULL),64 - bit);
+ }
+ }
+
+ //bar->Gran here < "bbar" MaxGran, so "bar" holds next biggest Gran after the bridge
+ //we will try to adjust Extra Space requested by the bridge, analizing bar->Gran information
+ if(ebar->Length) {
+ while( ebar->Length >= (ebar->Gran+1) ){
+ VOID* p;
+ //-----------------------
+
+ if(!DevDb.RecordCount)break;
+
+ bar=NULL;
+ val=ebar->Gran+1;
+ Status=DbeLocateKey(&DevDb,0,&val,&p,&v, &i);
+
+
+ if(EFI_ERROR(Status)){
+ if(!((Status==EFI_DBE_EOF) || (Status==EFI_DBE_BOF) || (Status==EFI_NOT_FOUND))){
+ ASSERT_EFI_ERROR(Status);
+ goto ExitLbl;
+ }
+ }
+
+ Status=DbeGoToIndex(&DevDb,0,i,&bar);
+ if(EFI_ERROR(Status)){
+ if(!((Status==EFI_DBE_EOF) || (Status==EFI_DBE_BOF))){
+ ASSERT_EFI_ERROR(Status);
+ goto ExitLbl;
+ }
+ }
+
+ //if DevDb (who has even sizes) has resource that smaller or equal
+ //we will try to fill Extra Gap...
+ if((v == -1) && (bar!=NULL)){
+ //Database sorted in ascending order. DbeLocateKey() function, parameter "v" tells how close the result is.
+ //if DBE couldn't find exact match, it will return pointer at first element bigger than Parameter Passed.
+ //There fore, if this is the case, we need to go down one index to get a smaller element than Parameter Passed.
+ if(i>0){
+ bar=NULL;
+ Status=DbeGoToIndex(&DevDb,0,i-1,&bar);
+ if(EFI_ERROR(Status)){
+ if(!((Status==EFI_DBE_EOF) || (Status==EFI_DBE_BOF))){
+ ASSERT_EFI_ERROR(Status);
+ goto ExitLbl;
+ }
+ }
+ } else break; //this will break "while(DevDb.RecordCount || BrgDb.RecordCount)" loop
+ } //if(v==-1 && bar!=NULL)
+
+ if(bar!=NULL && bar->Gran<=ebar->Gran){
+ Status=AppendBarOrder(&DevDb,ResOrd,bar);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto ExitLbl;
+
+ //Adjust ebar->Length and Gran since we have filled out some extra space...
+ ebar->Length-=bar->Length;
+ if(ebar->Length!=0){
+ bit=FindFirstBit(ebar->Length-1,FALSE);
+ ebar->Gran=Shr64((~0ULL),64-bit);
+ } else break; //this will break "while( ebar->Length >= (ebar->Gran+1) )" loop
+ } else break; //this will break "while( ebar->Length >= (ebar->Gran+1) )" loop
+
+ } //while( ebar->Length >= (ebar->Gran+1)
+
+ //if after all efforts we still have extra resources left
+ //Mark ebar->Offset as 0xFF to notify routine which will programm the BARs
+ //Not to toughch this one, but just add ebar->Length before next valid BAR.
+
+ PCI_TRACE((TRACE_PCI," EBAR: Len=0x%lX;\t Gra=0x%lX;\t Ofs=0x%X; Owner [B%X|D%X|F%X] Type=%d\n",
+ ebar->Length, ebar->Gran, ebar->Offset, ebar->Owner->Address.Addr.Bus,
+ ebar->Owner->Address.Addr.Device, ebar->Owner->Address.Addr.Function, ebar->Owner->Type));
+ if(ebar->Length!=0){
+ ebar->Offset=0xFF;
+ ebar->Type=ResType+1;
+ ebar->DiscoveredType=ebar->Type;
+
+ Status=AppendItemLst((T_ITEM_LIST*)ResOrd, ebar);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto ExitLbl;
+ }
+ }//if(ebar->Length)
+ }//else of "if(bar->Gran >= balign->MaxGran)"
+ } else { //"if((bar!=NULL) && (bbar!=NULL))"
+ //This case when we have only one type of resources most likely it would be regular device resources
+ //But just in case do the check
+ if(bbar==NULL) Status=AppendBarOrder(&DevDb,ResOrd,bar);
+ else {
+ ebar=NULL;
+ //If we got only bridges (more than one) behind parent bridge we might got uneven alignment!
+ //So we have to check if Granuilarity requirements satisfactory for them and padd resources if needed.
+ if(BrgDb.RecordCount>1){
+ UINT64 resgran;
+ //---------------------
+ PCI_TRACE((TRACE_PCI," Bridges ONLY found!!! \n"));
+ brg=bbar->Owner;
+ ext=(PCI_BRG_EXT*)(brg+1);
+ balign=&ext->Align[ResType];
+
+ bit=FindFirstBit(bbar->Length-1,FALSE);
+ resgran=Shr64((~0ULL),64-bit);
+
+ if(bbar->Gran>resgran){
+ //get next record
+ Status=DbeGoToIndex(&BrgDb,0,BrgDb.RecordCount-2,&nextbar);
+ if(EFI_ERROR(Status)){
+ if(!((Status==EFI_DBE_EOF) || (Status==EFI_DBE_BOF))){
+ ASSERT_EFI_ERROR(Status);
+ goto ExitLbl;
+ }
+ }
+ //determine extra resource size...
+ ebar=&ext->Align[ResType].ExtraRes;
+ ebar->Length=(( bbar->Length | nextbar->Gran )+1)-bbar->Length;
+ if(ebar->Length!=0){
+ bit=FindFirstBit(ebar->Length-1,FALSE);
+ ebar->Gran=Shr64((~0ULL),64-bit);
+ }
+ }//if(balign->MaxGran>balign->ResGran)
+ }//if(BrgDb.RecordCount>1)
+ Status=AppendBarOrder(&BrgDb,ResOrd,bbar);
+ if(ebar!=NULL && ebar->Length){
+ ebar->Offset=0xFF;
+ ebar->Type=ResType+1;
+ ebar->DiscoveredType=ebar->Type;
+ PCI_TRACE((TRACE_PCI," EBAR: Len=0x%lX;\t Gra=0x%lX;\t Ofs=0x%X; Owner [B%X|D%X|F%X] Type=%d\n",
+ ebar->Length, ebar->Gran, ebar->Offset, ebar->Owner->Address.Addr.Bus,
+ ebar->Owner->Address.Addr.Device, ebar->Owner->Address.Addr.Function, ebar->Owner->Type));
+
+ Status=AppendItemLst((T_ITEM_LIST*)ResOrd, ebar);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto ExitLbl;
+ }
+
+ ASSERT_EFI_ERROR(Status);
+ }
+ if(EFI_ERROR(Status)) goto ExitLbl;
+ }
+
+ }//while(DevDb.RecordCount || BrgDb.RecordCount)
+
+ExitLbl:
+ //Free Memory allocated...
+ FreeResDb(&DevDb);
+ FreeResDb(&BrgDb);
+
+ //if there was an ERROR clear Bridge Resource Ortder Array.
+ if(EFI_ERROR(Status)){
+ ClearItemLst((T_ITEM_LIST*)ResOrd,FALSE);
+ PCI_TRACE((TRACE_PCI,"PciBus: OptimizeBrgResource() returning ERROR=%r\n", Status));
+ }
+
+ return Status;
+
+}
+
+VOID ClearBrgResources(PCI_DEV_INFO *Brg){
+ EFI_STATUS Status=0;
+ PCI_DEV_INFO *dev;
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(Brg+1);
+ UINTN i;
+//-------------------------------
+
+ for (i=0; i<ext->ChildCount; i++){
+ dev=ext->ChildList[i];
+
+ if((dev->Type==tPci2PciBrg || dev->Type==tPci2CrdBrg) )
+ ClearBrgResources(dev);
+ } //child loop
+
+ //Once here that means all recourcive calls are done and
+ //all BridgeChilds Bridges - clean....
+ //Clear ThisBridge Res[], Pad[], Align[]...
+ for(i=rtIo16; i<rtMaxRes; i++) {
+ PCI_DEV_INFO *owner;
+ //----------------------
+ owner=ext->Res[i].Owner;
+ pBS->SetMem(&ext->Res[i], sizeof(PCI_BAR),0);
+ ext->Res[i].Owner=owner;
+
+ owner=ext->Align[i].ExtraRes.Owner;
+ pBS->SetMem(&ext->Align[i], sizeof(BRG_ALIGN_INFO),0);
+ ext->Align[i].ExtraRes.Owner=owner;
+#if HOTPLUG_SUPPORT
+ owner=ext->Pad[i].Owner;
+ pBS->SetMem(&ext->Pad[i], sizeof(PCI_BAR),0);
+ ext->Pad[i].Owner=owner;
+#endif
+ if(ext->BarOrder[i].BarCount) ClearItemLst((T_ITEM_LIST*)&ext->BarOrder[i], FALSE);
+ }
+}
+
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CalculateBrgResources()
+//
+// Description: The objective of this routine is to select the biggest
+// possible Granularity/Alignment for the Bridge by adding all Child's
+// resources of the same type together.
+//
+// Input:
+// PCI_DEV_INFO *Brg Pointer to PCI Device Private Data structure.
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CalculateBrgResources(PCI_DEV_INFO *Brg)
+{
+ EFI_STATUS Status=0;
+ PCI_DEV_INFO *dev;
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(Brg+1);
+ UINTN i,j,k;
+ PCI_BAR *bar, *bbar;
+ UINT8 bit;
+ BRG_RES_ORDER *resord;
+#if HOTPLUG_SUPPORT
+ PCI_BAR *pbar;
+#endif
+ BRG_ALIGN_INFO *balign;
+ BOOLEAN paddingappl;
+ MRES_TYPE LowResType=rtMaxRes;
+//-----------------------------------------------
+ //Tell what we are doing
+ PCI_TRACE((TRACE_PCI,"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"));
+ PCI_TRACE((TRACE_PCI,"PciBus: "));
+ if(gPciOutOfRes) PCI_TRACE((TRACE_PCI," RE_"));
+ PCI_TRACE((TRACE_PCI,"CalculateBrgResources() Bridge->[B%X|D%X|F%X] ---> BEGIN \n",
+ Brg->Address.Addr.Bus, Brg->Address.Addr.Device, Brg->Address.Addr.Function));
+ PCI_TRACE((TRACE_PCI,"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"));
+
+ //Init initial Alignment fields for the special Bridge BARs
+ //every P2P brg has 4k IO and 1M MMMIO alignment
+ //Init Initial Granularity array
+ if(Brg->Type==tPciRootBrg){
+ //in case of Host Bridge Granularity Values should be provided by Root Brg
+ for(i=1; i<rtMaxRes; i++) ext->Align[i].MinGran=1; //just don't care now
+ } else {
+ //in case of P2P Brg use default settings
+ ext->Align[1].MinGran=P2P_BRG_IO_GRA;
+ ext->Align[2].MinGran=P2P_BRG_IO_GRA;
+ ext->Align[3].MinGran=P2P_BRG_MEM_GRA;
+ ext->Align[4].MinGran=P2P_BRG_MEM_GRA;
+ ext->Align[5].MinGran=P2P_BRG_MEM_GRA;
+ ext->Align[6].MinGran=P2P_BRG_MEM_GRA;
+ }
+
+ //Initialize fields in Bridge info Structure
+ ext->Res[rtIo16].Gran=P2P_BRG_IO_GRA;
+ ext->Res[rtIo32].Gran=P2P_BRG_IO_GRA;
+ ext->Res[rtMmio32].Gran=P2P_BRG_MEM_GRA;
+ ext->Res[rtMmio32p].Gran=P2P_BRG_MEM_GRA;
+ ext->Res[rtMmio64].Gran=P2P_BRG_MEM_GRA;
+ ext->Res[rtMmio64p].Gran=P2P_BRG_MEM_GRA;
+
+ //Init Bridge Bar offset fields
+ if(Brg->Type==tPci2PciBrg){
+ //For IO 16 Resources Decoded by the bridge
+ ext->Res[rtIo16].Offset=0x1C;
+ //For IO 32 Resources Decoded by the bridge
+ ext->Res[rtIo32].Offset=0x1C;
+ //For MMIO32
+ ext->Res[rtMmio32].Offset=0x20;
+ //For MMIO32 PF
+ ext->Res[rtMmio32p].Offset=0x24;
+ //For MMIO64
+ ext->Res[rtMmio64].Offset=0x20; //P2PBridge doesnot have any MMIO64
+ //For MMIO64 PF
+ ext->Res[rtMmio64p].Offset=0x24;
+ }
+
+ //Init Card Bus Bridge Bar offset fields
+ if(Brg->Type==tPci2CrdBrg){
+ //For IO 16 Resources Decoded by the bridge
+ ext->Res[rtIo16].Offset=0x2C;
+ //For IO 32 Resources Decoded by the bridge
+ ext->Res[rtIo32].Offset=0x34;
+ //For MMIO32
+ ext->Res[rtMmio32].Offset=0x1C;
+ //For MMIO32 PF
+ ext->Res[rtMmio32p].Offset=0x24;
+ //For MMIO64
+ ext->Res[rtMmio64].Offset=0x1C; //P2Crd Bridge doesnot have any MMIO64
+ //For MMIO64 PF
+ ext->Res[rtMmio64p].Offset=0x24;//P2Crd Bridge doesnot have any MMIO64PF
+ }
+
+ if(gPciOutOfRes){
+//OUT_OF_RES!!
+ //Get AmiOutOfResVar (suppose to be created by ROOT BRG Generic code or Custom HbCspAllocateResources())
+ Status=AmiPciOutOfRes(&gPciOutOfResData, TRUE);
+ ASSERT_EFI_ERROR(Status); //should not fail at that point!
+
+ //gPciOutOfResData.Resource.Type can't be ASLRV_SPC_TYPE_BUS
+ //Update resource type
+ if(gPciOutOfResData.Resource.Type==ASLRV_SPC_TYPE_IO) LowResType=rtIo16;
+
+ if(gPciOutOfResData.Resource.Type==ASLRV_SPC_TYPE_MEM){
+ if(gPciOutOfResData.Resource._GRA==32){
+ LowResType=rtMmio32;
+ if(gPciOutOfResData.Resource.TFlags.MEM_FLAGS._MEM!=ASLRV_MEM_UC)LowResType=rtMmio32p;
+ }
+ if(gPciOutOfResData.Resource._GRA==64){
+ LowResType=rtMmio64;
+ if(gPciOutOfResData.Resource.TFlags.MEM_FLAGS._MEM!=ASLRV_MEM_UC)LowResType=rtMmio64p;
+ }
+ }
+ }
+
+ //Start adding resources for all childs behind that bridge
+ for (i=0; i<ext->ChildCount; i++){
+ dev=ext->ChildList[i];
+
+ //if we got Out Of resources condition call Platforn function to determine
+ //priority list for devices Platform wants to IGNORE.
+ //Pick just ONe device at a time.
+ if(gPciOutOfRes && !gPciOutOfResHit && !dev->OutOfResRemove){
+ Status=PciPortOutOfResourcesRemoveDevice(dev, gPciOutOfResData.Count, LowResType);
+ if(!EFI_ERROR(Status)){
+ gPciOutOfResHit=TRUE;
+ dev->OutOfResRemove=TRUE;
+
+ PCI_TRACE((TRACE_PCI,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"));
+ PCI_TRACE((TRACE_PCI,"\nPciBus: OutOfRes Hit #%d!!! Removing Device [B%X|D%X|F%X]->",
+ gPciOutOfResData.Count, dev->Address.Addr.Bus, dev->Address.Addr.Device, dev->Address.Addr.Function));
+
+ if(dev->PicIrqEntry!=NULL) PCI_TRACE((TRACE_PCI,"Slt #%d\n", dev->PicIrqEntry->SlotNum));
+ else PCI_TRACE((TRACE_PCI,"Slt N/A\n"));
+ PCI_TRACE((TRACE_PCI,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"));
+
+ //We must remove all it's functions also since f0 defines persence of the rest.
+ if(IsFunc0OfMfDev(dev)&& dev->Type!=tPci2PciBrg) {
+ PCI_TRACE((TRACE_PCI," AND ALL IT's %d FUNCTIONS!!!\n",dev->FuncCount));
+ for(j=0;j<dev->FuncCount;j++){
+ dev->DevFunc[j]->OutOfResRemove=TRUE;
+ DisableDeviceDecoding(dev->DevFunc[j], stDisableAll);
+ }
+ }
+ //if we hit device from remove list - shut it down...
+ DisableDeviceDecoding(dev, stDisableAll);
+ if(dev->Type==tPci2PciBrg) DisableBridgeDecoding((PCI_BRG_INFO*)dev);
+
+ //save OUT_OF_RES_VAR
+ Status=AmiPciOutOfRes(&gPciOutOfResData, FALSE);
+
+ }
+ }
+
+ if(dev->OutOfResRemove) continue;
+ //here we have to check if the Child device is P2P brg -
+ //it requires a special handling
+ if(dev->Type==tPci2PciBrg || dev->Type==tPci2CrdBrg)
+ CalculateBrgResources(dev);
+ } //child loop
+
+ PCI_TRACE((TRACE_PCI,"=>>>Resource Requirements for Bridge->[B%X|D%X|F%X] :<<<=\n",
+ Brg->Address.Addr.Bus, Brg->Address.Addr.Device, Brg->Address.Addr.Function));
+ PCI_TRACE((TRACE_PCI,"ResType: 1=rtIo16; 2=rtIo32; 3=rtMmio32; 4=rtMmio32p; 5=rtMmio64; 6=rtMmio64p\n\n"));
+
+
+ for(j=rtIo16; j<rtMaxRes; j++){
+ //Init variables.
+ paddingappl=FALSE;
+ bbar=&ext->Res[j];
+ balign=&ext->Align[j];
+ resord=&ext->BarOrder[j];
+ balign->MaxGran=bbar->Gran;
+
+ Status=OptimizeBrgResource(Brg, j);
+ ASSERT_EFI_ERROR(Status);
+
+ for(k=0; k<resord->BarCount; k++){
+ bar=resord->BarList[k];
+ //add children's resources to the bridge decoding
+ if(bbar->Gran < bar->Gran)bbar->Gran=bar->Gran;
+ bbar->Length+=bar->Length;
+ bbar->Type=bar->Type;
+ }
+
+#if HOTPLUG_SUPPORT
+ pbar=&ext->Pad[j];
+ //if this is the bridge with hotplug capabilities it might supports Resource Padding
+ //Apply padding and padding alignment if it is bigger than this bridge is currently requesting
+ if(pbar->Length){
+ if(pbar->Length > bbar->Length) bbar->Length = pbar->Length;
+ if(bbar->Gran < pbar->Gran) bbar->Gran=pbar->Gran;
+ bbar->Type=pbar->Type;
+ paddingappl=TRUE;
+ }
+#endif
+ //if we have a card bus brg and hotplug is disabled we will APPLY default padding
+ if(Brg->Type==tPci2CrdBrg && !paddingappl) {
+ PCI_TRACE((TRACE_PCI,"->>>Applying CRD BUS Default Padding for Pci2CrdBrg [B%X|D%X|F%X]\n",
+ Brg->Address.Addr.Bus, Brg->Address.Addr.Device, Brg->Address.Addr.Function));
+ ApplyCrdPadding(Brg, j);
+ }
+
+ //if Brg have resource request
+ balign->MaxGran=bbar->Gran;
+ if(bbar->Length){
+ if( (bbar->Length < (balign->MinGran + 1)) || ((bbar->Length & balign->MinGran)) )
+ bbar->Length=(bbar->Length | balign->MinGran)+1;
+ //Figure out Resource Delivered Granularity
+ bit=FindFirstBit(bbar->Length-1,FALSE);
+ balign->ResGran=Shr64((~0ULL),64-bit);
+ }
+ //Report Bridge Parameters
+ PCI_TRACE((TRACE_PCI,"->ResType=%X; Len=%lX; Gran=%lX; MaxGran=%lX; ResGran=%lX; MinGran=%lX\n\n",
+ j, bbar->Length, bbar->Gran, balign->MaxGran, balign->ResGran, balign->MinGran));
+ PCI_TRACE((TRACE_PCI,"------------------------------------------------------------------------\n"));
+
+ } //for(j=rtIo16; j<rtMaxRes; j++)..
+
+ //Tell what we are doing
+ PCI_TRACE((TRACE_PCI,"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"));
+ PCI_TRACE((TRACE_PCI,"PciBus: CalculateBrgResources() Bridge->[B%X|D%X|F%X] ---> END \n",
+ Brg->Address.Addr.Bus, Brg->Address.Addr.Device, Brg->Address.Addr.Function));
+ PCI_TRACE((TRACE_PCI,"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n"));
+
+ //We did it ... EXIT!
+}
+
+//================================================
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: NewDevice()
+//
+// Description: Allocats Space nedded for New PCI_Device Instance and inits
+// some of it's Fields
+//
+// Input:
+// BOOLEAN BrgDevice Indicator that New Device is a BRIDGE Device.
+// PCI_CFG_ADDR *DevArrd Device Address on PCI Bus.
+//
+// Output: PCI_DEV_INFO*
+// Pointer to the Created PCI Device Private Data structure.
+// NULL, if there was an ERROR.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+PCI_DEV_INFO* NewDevice(BOOLEAN BrgDevice, PCI_CFG_ADDR *DevAddr)
+{
+ UINTN i;
+ PCI_DEV_INFO *dev;
+ PCI_BRG_EXT *ext;
+//------------------------------------
+ PCI_TRACE((TRACE_PCI,"\n==========================================================================\n"));
+ if(BrgDevice)i=sizeof(PCI_BRG_INFO);
+ else i=sizeof(PCI_DEV_INFO);
+
+ dev=MallocZ(i);
+ if(!dev) return dev;
+
+ //Specify Owner for BusSpecific Override Protocol
+ dev->BusOvrData.Owner=dev;
+#if ((defined EFI_SPECIFICATION_VERSION) && (EFI_SPECIFICATION_VERSION >= 0x2001F))
+ dev->LoadFileData.Owner=dev;
+#endif
+ dev->Signature=AMI_PCI_SIG;
+ dev->MajorVersion = PCI_BUS_MAJOR_VER;
+ dev->MinorVersion = PCI_BUS_MINOR_VER;
+ dev->Revision = PCI_BUS_REVISION;
+
+ //init some fields which must not be ZERO
+ for(i=0; i<PCI_MAX_BAR_NO+1; i++)dev->Bar[i].Owner=dev;
+ if(DevAddr){
+ dev->Address.ADDR=DevAddr->ADDR;
+ dev->Address.Addr.Register=0;
+ } else dev->Address.ADDR=0;
+
+ //Initialize some static fields
+ if(BrgDevice){
+ dev->Type=tPci2PciBrg;
+ ext=(PCI_BRG_EXT*)(dev+1);
+ for(i=0; i<rtMaxRes; i++) {
+ ext->Res[i].Owner=dev;
+ ext->Align[i].ExtraRes.Owner=dev;
+ }
+ } else dev->Type=tPciDevice;
+
+ return dev;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BridgeAddChild()
+//
+// Description: Adds Pointer at the child PCI Device to the "Bridge"
+// T_ITEM_LIST Child List Structure of the BRG_EXT.
+// some of it's Fields
+//
+// Input:
+// PCI_DEV_INFO *Brgidge Pointer to PCI Device Private Data structure
+// of the Parent Bridge.
+// PCI_DEV_INFO *Child Pointer to PCI Device Private Data structure.
+// of the Child Device.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS BridgeAddChild(PCI_DEV_INFO *Bridge,PCI_DEV_INFO *Child)
+{
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(Bridge+1);
+//-------------------------------------------------
+ return AppendItemLst((T_ITEM_LIST*)&ext->InitialCount,Child);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitDeviceData()
+//
+// Description: Initializes missing fields in PCI_DEV_INFO structure.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer to PCI Device Private Data structure
+// to initialize.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InitDevData(PCI_DEV_INFO *Dev, PCI_DEV_INFO *Parent, UINT32 VenDevId, UINT32 ClassCodes, PCI_DEV_INFO *Func0){
+ EFI_STATUS Status;
+ PCI_CFG_ADDR addr;
+//-------------------------
+ //Get CMD Register's safe value per UEFI 2.1 spec
+ addr.ADDR=Dev->Address.ADDR;
+
+ Dev->ParentBrg=Parent;
+ Dev->DevVenId.DEV_VEN_ID=VenDevId;
+ Dev->Class.DEV_CLASS=ClassCodes;
+ Dev->HostData=Parent->HostData;
+ Dev->RbIo=Parent->RbIo;
+ Dev->Func0=Func0;
+
+ //If (Func0==NULL && FuncCount==0) function is a single function device, following fields are not used and reserved;
+ //If (Func0!=NULL && FuncCount==0) function is one of the Func1..Func7 of multi-func device, Func0 points on DevFunc0;
+ //If (Func0!=NULL && (FuncCount!=0 || FuncInitCnt!=0)) function is Func0 of multyfunc device DevFunc holds pointers at all other Func1..7 found yet
+
+ //If (Func0==NULL && FuncCount!=0) Illehgal combination - reserved!
+ if(Func0!=NULL){
+ if (Func0!=Dev){
+ //This is func 1..7 of the device... add it to the list.
+ Status=AppendItemLst((T_ITEM_LIST*)&Func0->FuncInitCnt,Dev);
+ ASSERT_EFI_ERROR(Status)
+ if(EFI_ERROR(Status)) return Status;
+ } else {
+ //This is Func 0 if the device.. init Func0->FuncInitCnt with 8
+ Func0->FuncInitCnt=8;
+ }
+ }
+
+ addr.Addr.Register=PCI_CMD;
+ Status=PciCfg16( Dev->RbIo, addr, FALSE, &Dev->CmdReg.CMD_REG);
+ ASSERT_EFI_ERROR(Status)
+ if(EFI_ERROR(Status)) return Status;
+
+ Status=MakePciDevicePath(Dev);
+ if(EFI_ERROR(Status)) return Status;
+
+ Status=PciPortSkipThisDevice(Dev);
+ if(!EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"PciBus: Device @ [B%X|D%X|F%X], VID=%X, DID=%X SKIPPED from enumeration.\n\n",
+ Dev->Address.Addr.Bus, Dev->Address.Addr.Device, Dev->Address.Addr.Function,
+ Dev->DevVenId.VenId, Dev->DevVenId.DevId));
+ Dev->SkipDevice=TRUE;
+ }else Status=EFI_SUCCESS;
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EnumerateBus()
+//
+// Description: Enumerate the PCI BUSes behind the "ParentBrg" and determine
+// how much resources nedded for all its Child devices.
+//
+// Input:
+// PCI_DEV_INFO *ParentBrg Pointer to PCI Device Private Data structure
+// of the Parent Bridge.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EnumerateBus(PCI_DEV_INFO *ParentBrg)
+{
+ EFI_STATUS Status, Status1=EFI_NOT_FOUND;
+ PCI_CFG_ADDR pcidev;
+ BOOLEAN mf,ari; //multi-function flag; ARI Flag
+ UINT32 id, cc; //Device ID Vendor ID reg
+ UINT8 ht; //Header type reg
+ PCI_BRG_EXT *ext, *parext;
+ PCI_DEV_INFO *dev, *func0;
+ UINT8 omb=0;
+#if PCI_DEV_REVERSE_SCAN_ORDER
+ UINT8 DevBuff;
+#endif
+//----------------------------------
+ PROGRESS_CODE(DXE_PCI_BUS_ENUM);
+ //Root Bridges Will have Same Number for Primary and Secondary bus
+ pcidev.ADDR=PCI_VID;
+ parext=(PCI_BRG_EXT*)(ParentBrg+1);
+ pcidev.Addr.Bus=(UINT8)parext->Res[rtBus].Base;
+ func0=NULL;
+ ari=FALSE;
+
+ for(pcidev.Addr.Device=0; pcidev.Addr.Device<=PCI_MAX_DEVICE; pcidev.Addr.Device++){
+#if PCI_DEV_REVERSE_SCAN_ORDER
+ DevBuff = pcidev.Addr.Device;
+ pcidev.Addr.Device = PCI_MAX_DEVICE - pcidev.Addr.Device;
+#endif
+ //if ARI Detected and Enabled we should scan all devices and functions
+ //but in ARI Mode Dev0..31 and Func0..7 will be translted for PCIe as Dev0 Func 0...255
+ //So Func0 must be the same as we have detected when started from Actual Function 0
+ //And we should not reset MF flag for ARI device when we reach Func 7 of the device.
+ if(ari == FALSE){
+ mf=FALSE;
+ func0=NULL;
+ }
+
+ for(pcidev.Addr.Function=0; pcidev.Addr.Function<=PCI_MAX_FUNC; pcidev.Addr.Function++){
+ //read devid-vendid register pare,
+ id=0;
+ pcidev.Addr.Register=PCI_VID;
+
+ ///
+ /// A config write is required in order for the device to re-capture the Bus number,
+ /// according to PCI Express Base Specification, 2.2.6.2
+ /// Write to a read-only register VendorID to not cause any side effects.
+ ///
+ Status=PciCfg32(ParentBrg->RbIo,pcidev,TRUE,&id);
+
+ Status=PciCfg32(ParentBrg->RbIo,pcidev,FALSE,&id);
+ if(EFI_ERROR(Status)) return Status; //Error happend - can't continue
+ //Check if all Ones
+#if PCI_EXPRESS_SUPPORT
+ if( (id == 0xFFFFFFFF)&& //oinly if first attemt of CFG read did not find anything
+ (ParentBrg->PciExpress!=NULL) && //and device is PCIe capable
+#if PCI_DEV_REVERSE_SCAN_ORDER
+ (DevBuff==0) && (pcidev.Addr.Function==0) && //for PCIe dev0 func0 is only option
+#else
+ (pcidev.Addr.Device==0) && (pcidev.Addr.Function==0) && //for PCIe dev0 func0 is only option
+#endif
+ (ParentBrg->PciExpress->PcieCap.SlotImpl)) //and we have a slot there...
+ {
+ //Some cards does not reply on configuration transactions
+ //for some time after opening config space behind the bridge.
+ //If slot is implemented behind the bridge -
+ //doiblecheck if card present using PCIe facilities (SLOT_STATUS reg)
+ //we will save time on skipping DEV 1..31 though
+ Status=PcieDoubleCheckCard(ParentBrg,&pcidev,&id);
+ ASSERT_EFI_ERROR(Status);
+ }
+#endif
+ if(id == 0xFFFFFFFF || id==0){
+ if (!mf)break; //devX.fun0.reg=0 returns 0xFFFFFFFF nothing is there
+ else continue; //if device was identified as multifunc keep scanning
+ }
+ //here we got something alive there
+ Status1=EFI_SUCCESS;
+ ht=0;
+ //read the HeaderType Reg
+ pcidev.Addr.Register=EFI_FIELD_OFFSET(PCI_COMMON_REG,HeaderType);
+ Status=PciCfg8(ParentBrg->RbIo,pcidev,FALSE,&ht);
+ if(EFI_ERROR(Status)) return Status; //Error happend cant continue
+
+ if(ari==FALSE){
+ if(pcidev.Addr.Function==0) {
+ if(ht & HDR_TYPE_MULTIFUNC)mf=TRUE; //this is multifunc device
+ }
+ }
+
+ ht&=3;
+
+ //Get the class code and revision Id
+ pcidev.Addr.Register=PCI_RID; //Rev ID and Class Code
+ Status=PciCfg32(ParentBrg->RbIo,pcidev,FALSE,&cc);
+ if(EFI_ERROR(Status)) return Status; //Error happend can't continue
+
+ switch (ht){
+ case HDR_TYPE_DEVICE :
+ //Allocate Space to accomodate found device
+ dev=NewDevice(FALSE,&pcidev);
+ if(!dev) return EFI_OUT_OF_RESOURCES;
+
+ if((ari==FALSE) && (mf) && (pcidev.Addr.Function==0))func0=dev;
+ Status=InitDevData(dev, ParentBrg, id, cc, func0);
+ if(EFI_ERROR(Status)) goto EEXIT;
+ //Test the class code to mark host brg device
+ if( dev->Class.SubClassCode==0 &&
+ dev->Class.BaseClassCode==6 &&
+ dev->Class.ProgInterface==0 )
+ {
+ dev->Type=tPciHostDev;
+ }
+ //Check if we got a debug port here
+#if EFI_DEBUG || USB_DEBUG_TRANSPORT
+ if(
+ (gDbgPortHob && (
+ (gDbgPortInfo.DebugPortType==USB2_EHCI) ||
+ (gDbgPortInfo.DebugPortType==USB2_UHCI) ||
+ (gDbgPortInfo.DebugPortType==USB2_OHCI) )
+ ) && (
+ (pcidev.Addr.Function==gDbgPortInfo.Address.Addr.Function) &&
+ (pcidev.Addr.Device==gDbgPortInfo.Address.Addr.Device) &&
+ (pcidev.Addr.Bus==gDbgPortInfo.Address.Addr.Bus)
+ )
+ )
+ {
+ dev->Bar[gDbgPortInfo.BarIndex].Length =gDbgPortInfo.Length;
+ dev->Bar[gDbgPortInfo.BarIndex].Gran =gDbgPortInfo.Length-1;
+ dev->Bar[gDbgPortInfo.BarIndex].Offset =gDbgPortInfo.BarOffset;
+ dev->Bar[gDbgPortInfo.BarIndex].Type =gDbgPortInfo.BarType;
+ dev->DebugPort=TRUE;
+ dev->Enumerated=TRUE;
+ dev->Discovered=TRUE;
+ }
+ else
+#endif
+ {
+ if(dev->SkipDevice){
+ //if porting hook tells us to skip this device.
+ //We will just start it
+ dev->Assigned=TRUE;
+ dev->Discovered=TRUE;
+ dev->Enumerated=TRUE;
+ dev->Incompatible=TRUE;
+ } else {
+ //Vars we need here
+ UINTN i;
+ UINT64 tl32, tl64, tlIO;
+ //-------------
+ //make sure - Device is disabled
+ Status=DisableDeviceDecoding(dev, stMemIoSpace);
+ if(EFI_ERROR(Status)) goto EEXIT;
+
+ //Try to determine how mutch resources Device consumes
+ Status=QueryPciDevice(dev);
+ if(EFI_ERROR(Status)) goto EEXIT;
+
+ //Find IRQ Routing Entry for discovered device
+ Status = FindDevIrqEntry(dev);
+
+ //This workaround done for PCI Compliance Test...
+ //32 bit, 64bit and IO resource request excides certain length.
+ for(i=0,tlIO=0,tl32=0,tl64=0; i<PCI_MAX_BAR_NO+1; i++){
+ if((dev->Bar[i].Type!=tBarUnused) && (dev->Bar[i].Length!=0) ){
+ switch (dev->Bar[i].Type){
+ case tBarIo16:
+ case tBarIo32:
+ tlIO+=dev->Bar[i].Length;
+ break;
+ case tBarMmio32:
+ case tBarMmio32pf:
+ tl32+=dev->Bar[i].Length;
+ break;
+ case tBarMmio64:
+ case tBarMmio64pf:
+ tl64+=dev->Bar[i].Length;
+ }//switch
+ }//if not empty
+ } //for
+
+ //Check if Calculated total resource request falls in acceptable range
+ if( (tlIO>=PCI_DEVICE_IO_RESOURCE_THRESHOLD) ||
+ (tl32>=PCI_DEVICE_32BIT_RESOURCE_THRESHOLD) ||
+ (tl64>=PCI_DEVICE_64BIT_RESOURCE_THRESHOLD)
+ )
+ {
+ //Zero out all BARs and ROM BAR.
+ for(i=PCI_BAR0, id=0; i<PCI_CAPP; i+=4){
+ pcidev.Addr.Register=(UINT8)i;
+ Status=PciCfg32(ParentBrg->RbIo,pcidev,TRUE,&id);
+ if(EFI_ERROR(Status)) goto EEXIT;
+ }
+ //Clear CMD_REG
+ pcidev.Addr.Register=(UINT8)PCI_CMD;
+ Status=PciCfg16(ParentBrg->RbIo,pcidev,TRUE,(UINT16*)(&id));
+ if(EFI_ERROR(Status)) goto EEXIT;
+
+ //Clear All collected resource information for that device
+ //to avoid them to be added to the system's resource request.
+ for(i=0; i<PCI_MAX_BAR_NO+1; i++){
+ dev->Bar[i].Type=tBarUnused;
+ dev->Bar[i].DiscoveredType=tBarUnused;
+ dev->Bar[i].Length=0;
+ dev->Bar[i].Gran=0;
+ }
+ //Setting Flags telling not to install PciIo protocol instance
+ //on this device and don't touch device at all!
+ dev->Started=TRUE;
+ dev->Assigned=TRUE;
+ dev->Discovered=TRUE;
+ dev->Enumerated=TRUE;
+ dev->RomBarError=TRUE;
+ dev->Incompatible=TRUE;
+ } //if .. Device requests too much resources.
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+ //Check if we have to enable ARI here.
+ if(IsFunc0(dev)){
+ Status=Pcie2CheckAri(dev,&mf,&ari);
+ if(EFI_ERROR(Status)) goto EEXIT;
+ }
+#endif
+ dev->Enumerated=TRUE;
+
+ }
+ }
+ break;
+
+ case HDR_TYPE_P2P_BRG :
+ case HDR_TYPE_P2C_BRG :
+ //Allocate space for new bridge struct
+ dev=NewDevice(TRUE,&pcidev);
+ if(!dev) return EFI_OUT_OF_RESOURCES;
+
+ ext=(PCI_BRG_EXT*)(dev+1);
+ if(ht==HDR_TYPE_P2C_BRG)dev->Type=tPci2CrdBrg;
+
+ //Record some properties of the discovered device
+ if(pcidev.Addr.Function==0 && mf)func0=dev;
+ Status=InitDevData(dev, ParentBrg, id, cc, func0);
+ if(EFI_ERROR(Status)) goto EEXIT;
+
+ if(dev->SkipDevice){
+ //if porting hook tells us to skip this device.
+ //We will just start it
+ dev->Assigned=TRUE;
+ dev->Discovered=TRUE;
+ dev->Enumerated=TRUE;
+ dev->Incompatible=TRUE;
+ } else {
+ //make sure - Device is disabled
+ if(dev->Type == tPci2PciBrg) DisableBridgeDecoding((PCI_BRG_INFO*)dev);
+ Status=DisableDeviceDecoding(dev, stMemIoSpace);
+ if(EFI_ERROR(Status)) goto EEXIT;
+
+ //Try to determine how mutch resources Device consumes
+ Status=QueryPciDevice(dev);
+ //this call must fill Bar[0..1]
+ if(EFI_ERROR(Status)) goto EEXIT;
+ }
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+ //Check if we have to enable Ari in case of
+ if((dev->PciExpress!=0) && (PcieIsDownStreamPort(dev)==FALSE)){
+
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ if(dev->SkipDevice==0){
+#endif
+ Status=Pcie2CheckAri(dev,&mf,&ari);
+ if(EFI_ERROR(Status)) goto EEXIT;
+
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ }
+#endif
+ }
+#endif
+
+ //Find PCI Bus Xlat entry corresponded to this bridge
+ Status=FindBridgeXlatEntry(dev, ext);
+ //Find IRQ Routing Entry for discovered device
+ Status = FindDevIrqEntry(dev);
+
+ //KeepUpdating NewBrg
+ //Programm Primary and Secondary I/F Bus Numbers
+ //To store Bridge SecondaryBusNo and SubordinateBusNo we will use PCI_BAR structure
+ //Device.Address.Addr.Bus will have PrimaryBusNo
+ //Bar.Base will be used for SecondaryBusNo and
+ //Bar.Base +Bar.Length-1 will give us SubordinateBusNo.
+ //So Record the Secondary Bus we will use for this Bridge..
+
+ //Set Bridge Bus register Proprties
+ ext->Res[rtBus].Type=tBarBus;
+ ext->Res[rtBus].Offset=PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET; //SecondaryBusOffset
+
+ //If fixed bus assignment we should handle situation differenty
+ if( FixedBusAssign && ext->XlatTblEntry != NULL ){
+ //get sceondary bus number from BusXlat Table
+ mMaxBusFound = ext->XlatTblEntry->BusBuild;
+ } else {
+ //Bridge has been found just increase bus counter
+ mMaxBusFound++;
+ }
+
+ ext->Res[rtBus].Base = mMaxBusFound;
+ //Set Sub Bus # for this bridge to max # available
+ ext->Res[rtBus].Length=mMaxBusScan-ext->Res[rtBus].Base;
+ if(ext->XlatTblEntry){
+ ext->XlatTblEntry->BusRun=mMaxBusFound;
+ }
+
+ if(mMaxBusReport < mMaxBusFound) mMaxBusReport=mMaxBusFound;
+
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ if(dev->SkipDevice==0){
+#endif
+ Status=MapBridgeBuses(dev);
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ }
+#endif
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto EEXIT;
+
+//Exclude Hotplug support
+#if HOTPLUG_SUPPORT
+ omb=mMaxBusFound; //save the old number of buses found only in case of hotplug
+ //this will try to init Root HPC siting behind this bridge if any...
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ if(dev->SkipDevice==0){
+#endif
+ Status=CheckRootHotplug(dev);
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ }
+#endif
+ ASSERT_EFI_ERROR(Status);
+ //if root hpc init fail for any reason we just must keep going
+#endif
+
+ //Enter a Recursive call in both cases
+ //Only in case Device is identifyes itself as Bridge
+ if(dev->Class.BaseClassCode == PCI_CL_BRIDGE){
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ if(dev->SkipDevice==0){
+#endif
+ Status = EnumerateBus(dev);
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ }
+#endif
+
+ if(Status!=EFI_NOT_FOUND){
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto EEXIT;
+ } else Status=EFI_SUCCESS;
+ //After we come back from enumeration update all IRQ Tables entries
+ //From BusBuild to BusRun (actual bus number)
+ if(ext->XlatTblEntry){
+ UpdateIrqTables(ext->XlatTblEntry);
+ PCI_TRACE((TRACE_PCI,"PciBus: Update Bus# for Brg [B%X|D%X|F%X] - Bld %X -> Run %X\n",
+ dev->Address.Addr.Bus,dev->Address.Addr.Device,dev->Address.Addr.Function,
+ ext->XlatTblEntry->BusBuild,ext->XlatTblEntry->BusRun));
+ }
+ }
+
+//-------------------------------------------------------------------------
+//Exclude Hotplug support
+#if HOTPLUG_SUPPORT
+ //here if this is the bridge who has hotplugable slots
+ //we must appy resource padding to it
+ if(dev->HotPlug){
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ if(dev->SkipDevice==0){
+#endif
+ Status=GetHpbResPadding(dev);
+
+ //Here we come with information about resources padding
+ //dev->Hotplug->Padd[rtBus].Length will have Bus numbers needed to pad for this bridge
+ //mMaxBusFound will have number of buses actualy present behind this bridge
+ //take care of buses now the rest of resources will be taken care of when
+ //CalculateBridge resources will be called
+ if(ext->PaddAttr==EfiPaddingPciBus){
+ //EIP 19106 If 1 Bus set to padding in Setup it did not do the padding.
+ if(ext->Pad[rtBus].Length && ext->Pad[rtBus].Length>mMaxBusFound-ext->Res[rtBus].Base){
+ mMaxBusFound=omb+(UINT8)ext->Pad[rtBus].Length;
+ }
+ }
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ }
+#endif
+
+ }
+#endif
+//-------------------------------------------------------------------------
+ //when we come back from EnumerateBus and have applyed padding for Bus Resources
+ // - mMaxBusFound will effectively reflect subordinate bus number for this Bridge so...
+
+ //If fixed bus assignment we should handle situation differenty
+ if( FixedBusAssign &&
+ (ext->XlatTblEntry != NULL) &&
+ (ext->ItemNumber < gPciBusDb.ItemCount-1))
+ {
+ UINT8 busnum;
+ //-------------------------
+ busnum=FindNextSameLevelBrgXlatEntry(ext);
+
+ if( mMaxBusFound <= busnum )mMaxBusFound = busnum;
+ else {
+ //With Fixed Bus allocation this condition signifies an error if we here
+ //that means that we have found more buses than allowed buy fixed bus layout
+ //So scream about it.
+ PCI_TRACE((TRACE_PCI,"PciBus: Can't apply Fixed Buses for the Bridge @ [B%X|D%X|F%X]:\n Actual MAX Bus Discovered =%X; Proposed MAX Bus in BusXlatTbl = %X\n",
+ dev->Address.Addr.Bus, dev->Address.Addr.Device, dev->Address.Addr.Function,
+ mMaxBusFound, busnum));
+ ASSERT(FALSE);
+ }
+
+ }
+ ext->Res[rtBus].Length=mMaxBusFound-ext->Res[rtBus].Base+1;
+
+ if(mMaxBusReport < mMaxBusFound) mMaxBusReport=mMaxBusFound;
+
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ if(dev->SkipDevice==0){
+#endif
+ Status=SetSubBus(dev,mMaxBusFound);
+#if PCI_BUS_SKIP_BRG_RECURSIVELY
+ }
+#endif
+
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto EEXIT;
+
+//-------------------------------------------------------------------------
+//Enables PCI Express Handling only if PCI Express Base is Defined and !=0
+#if PCI_EXPRESS_SUPPORT
+ //Now when we come back we can power off PCIExpress Empty slot to make it
+ //cpable for Hot Plugging
+ if(dev->PciExpress!=NULL){
+ //Check if we hit a DOWN STREAM type device,
+ //and Initialize PciE link properties if so.
+ if(PcieIsDownStreamPort(dev)){
+ Status=PcieInitLink(dev);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto EEXIT;
+ } else {
+ //Add to the gPcieEpLst Orphan Upstream Ports of Switches and PCIe2PCI bridgers.
+ if((dev->PciExpress->PcieCap.PortType==PCIE_TYPE_UPS_PORT) ||
+ (dev->PciExpress->PcieCap.PortType==PCIE_TYPE_PCIE_PCI)){
+
+ Status=AppendItemLst(&gPcieEpList, dev);
+ PCI_TRACE((TRACE_PCI,"PciE: Adding Device [B%X|D%X|F%X] to gPcieEpList[%d]\n",
+ dev->Address.Addr.Bus,dev->Address.Addr.Device, dev->Address.Addr.Function, gPcieEpList.ItemCount));
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) goto EEXIT;
+ }
+ }
+ }
+#endif
+//-------------------------------------------------------------------------
+ //Finally we got here this bridge is done for now!!! we will use
+ //information collected, when we will programm the resources
+ dev->Enumerated=TRUE;
+ break;
+
+ default :
+ Status=EFI_UNSUPPORTED;
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ } //switch;
+ //Now update ParentBridge ChildList and Count
+ Status=BridgeAddChild(ParentBrg,dev);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) goto EEXIT;
+ //and so on
+ if( !mf ) break;
+ } //function loop
+#if PCI_DEV_REVERSE_SCAN_ORDER
+ pcidev.Addr.Device=DevBuff;
+#endif
+ } //device loop
+ return Status1;
+///////////////////////////////////////////
+//Emergency Exit Label
+EEXIT:
+ if(dev){
+ if(dev->PciExpress){
+ if(dev->PciExpress->Pcie2) pBS->FreePool(dev->PciExpress->Pcie2);
+ if(dev->PciExpress->VcData) {
+ if(dev->PciExpress->VcData->VcCount)ClearItemLst((T_ITEM_LIST*)&dev->PciExpress->VcData->InitCnt, TRUE);
+ pBS->FreePool(dev->PciExpress->VcData);
+ }
+ if(dev->PciExpress->SriovData) pBS->FreePool(dev->PciExpress->SriovData);
+ if(dev->PciExpress->AriData) pBS->FreePool(dev->PciExpress->AriData);
+ if(dev->PciExpress->AcsData) pBS->FreePool(dev->PciExpress->AcsData);
+ if(dev->PciExpress->AtsData) pBS->FreePool(dev->PciExpress->AtsData);
+ if(dev->PciExpress->RcLnkData) pBS->FreePool(dev->PciExpress->RcLnkData);
+ if(dev->PciExpress->Pcie3) pBS->FreePool(dev->PciExpress->Pcie3);
+
+ pBS->FreePool(dev->PciExpress);
+ }
+
+ if(dev->PciX) pBS->FreePool(dev->PciX);
+ if(dev->HotPlug)pBS->FreePool(dev->HotPlug);
+ pBS->FreePool(dev);
+ }
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProgramBar()
+//
+// Description: Programm PCI BAR Register with the Resource Address
+// provided by the "bar" parameter.
+//
+// Input:
+// PCI_BAR *bar Pointer at PCI BAR register information
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProgramBar(PCI_BAR *bar)
+{
+ EFI_STATUS Status=0;
+ PCI_CFG_ADDR addr;
+ PCI_DEV_INFO *owner=bar->Owner;
+//------------------------------------
+ addr.ADDR=bar->Owner->Address.ADDR;
+ addr.Addr.Register=bar->Offset;
+ addr.Addr.ExtendedRegister=bar->ExtOffset;
+
+#if EFI_DEBUG || USB_DEBUG_TRANSPORT
+ if(owner->DebugPort){
+ gDbgPortInfo.BaseAddress=bar->Base;
+ Status=gDbgPortHob->SetDebugPortResources(gDbgPortHob, pBS, &gDbgPortInfo);
+ ASSERT_EFI_ERROR(Status);
+ owner->Assigned=TRUE;
+ return Status;
+ }
+#endif
+
+ PCI_TRACE((TRACE_PCI,"PciBus: Device [B%X|D%X|F%X] Type=%X Bar.Offs=%Xh, Bar.Type=%d \n Assigned Base=%lX, Size=%lX \n",
+ owner->Address.Addr.Bus, owner->Address.Addr.Device,
+ owner->Address.Addr.Function, owner->Type,
+ ((bar->ExtOffset==0) ? bar->Offset : bar->ExtOffset),
+ bar->Type, bar->Base, bar->Length));
+ //EIP 26787 +
+ //Forgot to exclude P2P Bridge ROM BAR, it belongs to primary interface!
+ //if(owner->Type==tPci2PciBrg && (bar->Offset > 0x14 ){
+ if(owner->Type==tPci2PciBrg && ( (bar->Offset > PCI_BAR1) && (bar->Offset < PCI_EROM) ) ){
+ //EIP 26787 -
+
+ //we got special P2P bridge BAR
+ switch (bar->Type){
+ case tBarIo16 :
+ case tBarIo32 :
+ Status=EnableBridgeIoDecoding(owner, (UINT64)bar->Base, (UINT64)bar->Length);
+ //if(EFI_ERROR(Status)) return Status;
+ break;
+
+ case tBarMmio32:
+ case tBarMmio64:
+ Status=EnableBridgeMmioDecoding(owner, (UINT64)bar->Base, (UINT64)bar->Length);
+ //if(EFI_ERROR(Status)) return Status;
+ break;
+
+ case tBarMmio32pf:
+ case tBarMmio64pf:
+ Status=EnableBridgePfmmDecoding(owner, (UINT64)bar->Base, (UINT64)bar->Length);
+ //if(EFI_ERROR(Status)) return Status;
+ break;
+ }//switch
+
+ } else {
+ if(owner->Type==tPci2CrdBrg && bar->Offset > PCI_BAR0 ){
+ //here goes special Memory and IO windows of CardBus Bridge
+ UINT32 buffer=(UINT32)bar->Base;
+ //--------------------
+ Status=PciCfg32(owner->RbIo,addr,TRUE,(UINT32*)&buffer); //Base
+
+ addr.Addr.Register+=4; //Limit
+ buffer=(UINT32)(bar->Base+bar->Length-1);
+ Status=PciCfg32(owner->RbIo,addr,TRUE,(UINT32*)&buffer);
+
+ //Program Brg Control Reg to notify that Bridge Mem Window is PF
+ if(bar->Type==tBarMmio32pf || bar->Type==tBarMmio64pf){
+
+ addr.Addr.Register=PCI_BRIDGE_CONTROL_REGISTER_OFFSET;
+ Status=PciCfg16(owner->RbIo,addr,FALSE,(UINT16*)&buffer);
+
+ if(bar->Offset==0x1C) buffer|=BIT08; //Memory Window 1 is PF
+ if(bar->Offset==0x24) buffer|=BIT09; //Memory Window 2 is PF
+
+ Status=PciCfg16(owner->RbIo,addr,TRUE,(UINT16*)&buffer);
+ }
+ } else {
+ //do regular device BAR programming
+ UINT64 buffer=bar->Base;
+ //--------------------
+ if(bar->DiscoveredType == tBarMmio64 || bar->DiscoveredType == tBarMmio64pf)
+ Status=PciCfg64(owner->RbIo,addr,TRUE,&buffer);
+ else Status=PciCfg32(owner->RbIo,addr,TRUE,(UINT32*)&buffer);
+ }
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AssignBridgeResources()
+//
+// Description: Sorts, Aligns, and Programms Resources requested by devices
+// residing behind its Parent PCI Bridge - "Brg".
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer to PCI Device Private Data structure
+// of the Parent Bridge.
+// MRES_TYPE rt Type of PCI Bus resources to work with.
+// See definition of MRES_TYPE for detail.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AssignBridgeResources(PCI_BRG_INFO *Brg, MRES_TYPE rt)
+{
+ EFI_STATUS Status=EFI_NOT_FOUND;
+ UINT64 min=Brg->Bridge.Res[rt].Base;
+ UINT64 max=(min+Brg->Bridge.Res[rt].Length);
+ PCI_BAR *bar=NULL;
+ BRG_RES_ORDER *ord=&Brg->Bridge.BarOrder[rt];
+ UINTN i;//,j;
+//---------------------------------------
+
+ if(ord->BarCount == 0) return EFI_SUCCESS;
+
+ //Assign Io resources to all of Bridge childs
+ for(i=0; i<ord->BarCount; i++){
+ if(min>=max) {
+ Status=EFI_UNSUPPORTED;
+ PCI_TRACE((TRACE_PCI,"PciBus: ERROR Assign Res: MIN_ADDR(0x%lX) >= MAX_ADDR(0x%lX)\n", min, max));
+ break;
+ }
+ bar=ord->BarList[i];
+//(EIP45278)>
+#if PCI_MMIO_RES_TOP_ALLIGN == 1
+ if(rt==rtIo16)
+#endif
+ bar->Base=min;
+#if PCI_MMIO_RES_TOP_ALLIGN == 1
+ else
+ bar->Base=max-bar->Length;
+#endif
+//<(EIP45278)
+ if(bar->Offset!=0xFF){
+ Status=ProgramBar(bar);
+ if(EFI_ERROR(Status)) break;
+ }
+//(EIP45278)>
+#if PCI_MMIO_RES_TOP_ALLIGN == 1
+ if(rt==rtIo16)
+#endif
+ min+=(bar->Length);
+#if PCI_MMIO_RES_TOP_ALLIGN == 1
+ else
+ max-=(bar->Length);
+#endif
+//<(EIP45278)
+ }
+
+ if(EFI_ERROR(Status)&& bar!=NULL){
+ PCI_TRACE((TRACE_PCI,"PciBus: ERROR Assign Res for BAR(T=%X O=%X) @ [ B%X|D%X|F%X ]",
+ bar->Type, bar->Offset, bar->Owner->Address.Addr.Bus,
+ bar->Owner->Address.Addr.Device,bar->Owner->Address.Addr.Function));
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ClearBar()
+//
+// Description: Clears/zeros contents of PCI_BAR structure.
+//
+// Input:
+// PCI_BAR *Bar Pointer to PCI_BAR structure to clear.
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ClearBar(PCI_BAR *Bar)
+{
+ Bar->Type=tBarUnused;
+ Bar->Gran=0;
+ Bar->Length=0;
+ Bar->Base=0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindBarByType()
+//
+// Description: Checks if PCI BAR register of a particular "BarType" present
+// behind the PCI Bridge.
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer to PCI Device Private Data structure
+// of the Parent Bridge.
+// PCI_BAR_TYPE BarType Bar Type to search for.
+//
+// Output: BOOLEAN
+// TRUE if BAR of "BarType" present Behind the "Brg".
+// FALSE if otherwice.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN FindBarByType(PCI_BRG_INFO* Brg, PCI_BAR_TYPE BarType)
+{
+ UINTN i,j;
+ BOOLEAN res;
+ PCI_DEV_INFO *dev;
+//---------------------
+ for(i=0; i<Brg->Bridge.ChildCount; i++){
+ dev=Brg->Bridge.ChildList[i];
+ if(dev->Type<tPciHostDev && dev->Type>=tPciRootBrg){
+ //go inside the bridge...
+ res=FindBarByType((PCI_BRG_INFO*)dev,BarType);
+ if(res) return res;
+ }
+
+ for(j=0; j<PCI_MAX_BAR_NO+1; j++) if(dev->Bar[j].Type==BarType) return TRUE;
+#if SRIOV_SUPPORT
+//SRIOV Support adds some more bars ito the picture
+ if( (dev->PciExpress != NULL) && (dev->PciExpress->SriovData != NULL)){
+ for(j=0; j<PCI_MAX_BAR_NO; j++) if(dev->PciExpress->SriovData->Bar[j].Type==BarType) return TRUE;
+ }
+#endif
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConvertResources()
+//
+// Description: Converts Resources Requested by the Devices behind the
+// PCI Bridge of "ResType" using "ConvType" method of conversion
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer to PCI Device Private Data structure
+// of the Parent Bridge.
+// PCI_BAR_TYPE ResType Resource Type to convert. Accepted values are
+// tBarIo, tBarMem, tBarMemPf,
+// all other values are invalid.
+// RES_CONV_TYPE ConvType Type of Conversion to be performed.
+//
+// Output: Nothing
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ConvertResources(PCI_BRG_INFO *Brg, PCI_BAR_TYPE ResType, RES_CONV_TYPE ConvType, BOOLEAN CombineMemPmem)
+{
+ PCI_BRG_EXT *ext=&Brg->Bridge;
+ PCI_DEV_INFO *dev;
+ UINTN i,j;
+ BOOLEAN cnv=FALSE;
+ PCI_BAR_TYPE nt, wt;
+ RES_CONV_TYPE p2pct;
+//----------------------------
+
+ //Pick Brg Bars to convert
+ switch (ResType) {
+ case tBarIo:
+ nt=tBarIo16;
+ wt=tBarIo32;
+ p2pct=rcOneOf;
+ if(Brg->Common.Type==tPci2CrdBrg)p2pct=rcBoth;
+ break;
+
+ case tBarMem:
+ nt=tBarMmio32;
+ wt=tBarMmio64;
+ p2pct=rcNarrow;
+ if(Brg->Common.Type==tPci2CrdBrg)p2pct=rcNarrow;
+ break;
+
+ case tBarMemPf:
+ nt=tBarMmio32pf;
+ wt=tBarMmio64pf;
+ p2pct=rcOneOf;
+ if(Brg->Common.Type==tPci2CrdBrg)p2pct=rcNarrow;
+ break;
+
+ default : return; //no other combinations supported
+ }//switch
+
+ switch (ConvType){
+ case rcNone:
+ cnv=TRUE;
+ break;
+ case rcOneOf:
+ cnv=FindBarByType(Brg,nt);
+ break;
+ case rcNarrow:
+ cnv=FindBarByType(Brg,wt);
+ break;
+ case rcBoth: cnv=FALSE;
+ }//switch
+
+ //Take care about Padding behind the bridge if CombineMemPmem Attribute is set
+ if(ext->Pad[rtMmio32p].Length && CombineMemPmem){
+ ext->Pad[rtMmio32].Length+=ext->Pad[rtMmio32p].Length;
+ ext->Pad[rtMmio32p].Length=0;
+ }
+ if(ext->Pad[rtMmio64p].Length && CombineMemPmem){
+ ext->Pad[rtMmio64].Length+=ext->Pad[rtMmio64p].Length;
+ ext->Pad[rtMmio64p].Length=0;
+ }
+
+ for(i=0; i<ext->ChildCount; i++) {
+ dev=ext->ChildList[i];
+ for(j=0; j<PCI_MAX_BAR_NO; j++){
+ if(cnv){
+ switch(ConvType){
+ case rcNone:
+ if(dev->Bar[j].Type==wt) ClearBar(&dev->Bar[j]);
+ break;
+ case rcOneOf:
+ case rcNarrow:
+ if(dev->Bar[j].Type==wt) dev->Bar[j].Type=nt;
+ break;
+ }
+ } //if cnv
+ if(CombineMemPmem){
+ if( dev->Bar[j].Type==tBarMmio32pf ) dev->Bar[j].Type=tBarMmio32;
+ if( dev->Bar[j].Type==tBarMmio64pf ) dev->Bar[j].Type=tBarMmio64;
+ }
+ }//for j
+
+#if SRIOV_SUPPORT
+//SRIOV Support adds some more bars ito the picture
+ if( (dev->PciExpress != NULL) && (dev->PciExpress->SriovData != NULL)){
+ for(j=0; j<PCI_MAX_BAR_NO; j++){
+ if(cnv){
+ switch(ConvType){
+ case rcNone:
+ if(dev->PciExpress->SriovData->Bar[j].Type==wt){
+ ClearBar(&dev->PciExpress->SriovData->Bar[j]);
+ }
+ break;
+ case rcOneOf:
+ case rcNarrow:
+ if(dev->PciExpress->SriovData->Bar[j].Type==wt){
+ dev->PciExpress->SriovData->Bar[j].Type=nt;
+ }
+ break;
+ }//switch
+ } //if cnv
+ if(CombineMemPmem){
+ if( dev->PciExpress->SriovData->Bar[j].Type==tBarMmio32pf )
+ dev->PciExpress->SriovData->Bar[j].Type=tBarMmio32;
+ if( dev->PciExpress->SriovData->Bar[j].Type==tBarMmio64pf )
+ dev->PciExpress->SriovData->Bar[j].Type=tBarMmio64;
+ }
+ }//for j
+ }
+#endif
+
+ //recoursively call to convert child resources behind other brg
+ if(dev->Type==tPci2PciBrg || dev->Type==tPci2CrdBrg){
+ if(cnv){
+ //Unconditionally convert all resources to narrow because parent requested resource conversion
+ if(ConvType)ConvertResources((PCI_BRG_INFO*)dev, ResType, rcNarrow, CombineMemPmem);
+ else ConvertResources((PCI_BRG_INFO*)dev, ResType, ConvType, CombineMemPmem);
+ } else ConvertResources((PCI_BRG_INFO*)dev, ResType, p2pct, CombineMemPmem);
+ }
+ } //Child loop
+ //we did it!!!
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AssignBusResources()
+//
+// Description: Sorts, Aligns, and Programms Resources requested by devices
+// on the PCI Bus created by the PCI Bridge - "Brg".
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer to PCI Device Private Data structure
+// of the Bridge who creates the bus.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// Notes:
+// Assigns Resources by filling Device Bar structure
+// and programm all Bridge Childs Bars
+// and Enables Bridge devices to decode their resources
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AssignBusResources(PCI_BRG_INFO *Brg)
+{
+ EFI_STATUS Status=0;
+ UINT8 i;
+ PCI_DEV_INFO *dev;
+//----------------------------------
+ //First Check if Resources Assigned don't do it multiple times
+ if(Brg->Common.Assigned) return EFI_SUCCESS;
+
+ if(Brg->Common.Type == tPci2PciBrg || Brg->Common.Type == tPci2CrdBrg){
+ Status=DisableDeviceDecoding(&Brg->Common,stDisableAll);
+ Brg->Common.Attrib=0;
+ }
+
+ //Start with IO
+ if (Brg->Bridge.Res[rtIo32].Length) Status=AssignBridgeResources(Brg,rtIo32);
+ if(EFI_ERROR(Status)) return Status;
+
+ if (Brg->Bridge.Res[rtIo16].Length) Status=AssignBridgeResources(Brg,rtIo16);
+ if(EFI_ERROR(Status)) return Status;
+
+
+ //Now MMIO 64 PF
+ if(Brg->Bridge.Res[rtMmio64p].Length)Status=AssignBridgeResources(Brg,rtMmio64p);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Now MMIO 64
+ if(Brg->Bridge.Res[rtMmio64].Length)Status=AssignBridgeResources(Brg, rtMmio64);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Now MMIO 32 PF
+ if(Brg->Bridge.Res[rtMmio32p].Length)Status=AssignBridgeResources(Brg,rtMmio32p);
+ if(EFI_ERROR(Status)) return Status;
+
+ //And MMIO 32
+ if(Brg->Bridge.Res[rtMmio32].Length)Status=AssignBridgeResources(Brg, rtMmio32);
+ if(EFI_ERROR(Status)) return Status;
+
+
+ //So far so good - resources has been assigned on this Bridge level
+ //now check if we have any p2p brg among this brg childs...
+ //if so we will call this function recoursively...
+ for(i=0; i<Brg->Bridge.ChildCount; i++ ){
+ PCI_CFG_ADDR a;
+ PCI_CMD_REG cmdreg;
+ //-----------------
+ Status=EFI_SUCCESS;
+
+ dev=Brg->Bridge.ChildList[i];
+ a.ADDR=dev->Address.ADDR;
+
+ //Now take care of CacheLine Size register
+ if(dev->Capab&MY_PCI_IO_ATTRIBUTE_MEM_WR_INVALIDATE){
+ a.Addr.Register=PCI_CLS; // Cache Line Size
+
+ Status=PciCfg8(dev->RbIo,a,TRUE,&gPciCaheLineSize);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+
+ if(dev->Type==tPci2PciBrg ||dev->Type==tPci2CrdBrg) Status=AssignBusResources((PCI_BRG_INFO*)dev);
+
+ //disable decoding fo the PCI devices unles PciPortSkipThisDevice()
+ //says to Skip it. The Device Specific driver should enable it using Attributes() function.
+ if(!dev->SkipDevice){
+ Status=DisableDeviceDecoding(dev,stDisableAll);
+ dev->Attrib=0;
+ }
+
+ if (EFI_ERROR(Status)) return Status;
+ dev->Assigned=TRUE;
+ //UEFI 2.1 - we must leave BRIDGES open (decoding it's ranges)
+ if(dev->Type==tPci2PciBrg ||dev->Type==tPci2CrdBrg){
+ PCI_BRG_CNT_REG bc;
+ //---------------------------
+ Status=DeviceAttributes(dev, dev->Capab & (EFI_PCI_DEVICE_ENABLE), TRUE);
+ ASSERT_EFI_ERROR(Status);
+
+ a.Addr.Register=PCI_BRIDGE_CNTL; //Bridge Control Reg
+
+ Status=PciCfg16(dev->RbIo,a,FALSE,&bc.BRG_CNT_REG);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Set VGA16 enable to avoid forwarding ISA VGA Aliases
+ bc.Vga16Enable=1;
+
+ //Programm device's BRG_CTL_REG to forward #SERR and #PERR to the primary Interface.
+ if(gPciSetupData->SerrEnable) bc.SerrEnable=1;
+ else bc.SerrEnable=0;
+
+ if(gPciSetupData->PerrEnable) bc.PerrEnable=1;
+ else bc.PerrEnable=0;
+
+
+ Status=PciCfg16(dev->RbIo,a,TRUE,&bc.BRG_CNT_REG);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ //Programm device's PCI_CMD_REG to generate #SERR and #PERR according to Setup.
+ a.Addr.Register=PCI_CMD; //PCI Command Reg
+
+ Status=PciCfg16(dev->RbIo,a,FALSE,&cmdreg.CMD_REG);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ if(gPciSetupData->SerrEnable) cmdreg.SerrEnable=1;
+ else cmdreg.SerrEnable=0;
+
+ if(gPciSetupData->PerrEnable) cmdreg.ParityErrorResp=1;
+ else cmdreg.ParityErrorResp=0;
+
+ Status=PciCfg16(dev->RbIo,a,TRUE,&cmdreg.CMD_REG);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ } //for
+ Brg->Common.Assigned=TRUE;
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateRootResDsc()
+//
+// Description: Creates an ACPI QWORD Resource Descriptors set to reflect
+// this "RootBrg" resource request
+//
+// Input:
+// PCI_BRG_INFO *RootBrg Pointer to PCI Device Private Data structure
+// of the Bridge who creates the bus.
+// IN OUT VOID* *ResDsc ACPI QWORD Resource Descriptors set.
+// See definition of ASLR_QWORD_ASD for details.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//
+// Notes:
+// Meaning of QWORD Resource Descriptor Fields for this function
+// _LEN => Set to the size of the aperture that is requested.
+// _GRA => Used to differentiate between a 32-bit memory request and a
+// 64-bit memory request. For a 32-bit memory request,
+// this field should be set to 32. For a 64-bit memory request,
+// this field should be set to 64. All other values result in
+// this function returning the error code of EFI_INVALID_PARAMETER.
+// _MAX => Used to specify the alignment requirement.
+// All other fields are ignored.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CreateRootResDsc(PCI_DEV_INFO *RootBrg, VOID **ResDsc){
+ UINTN i, rc=0;
+ ASLR_QWORD_ASD *rd;
+ PCI_BRG_EXT *ext=(PCI_BRG_EXT*)(RootBrg+1);
+//-----------------------------------------------------
+ //First count how many rd suppose to be
+ for(i=rtIo16; i<rtMaxRes; i++){
+ if(ext->Res[i].Type && ext->Res[i].Length) rc++;
+ }
+
+ //If RB don't have any resource requests fill out END_TAG_DESCRIPTOR and return.
+ if(!rc){
+ rd=MallocZ(sizeof(ASLR_EndTag));
+ rd->Hdr.HDR=ASLV_END_TAG_HDR;
+ *ResDsc=rd;
+ return EFI_SUCCESS;
+ }
+
+ //get some memory
+ rd=MallocZ(sizeof(ASLR_QWORD_ASD)*rc+sizeof(ASLR_EndTag));
+ ASSERT(rd);
+ if(!rd) return EFI_OUT_OF_RESOURCES;
+
+ *ResDsc=rd;
+ for(i=rtIo16; i<rtMaxRes; i++){
+ if(!(ext->Res[i].Type && ext->Res[i].Length)) continue ;
+ switch(ext->Res[i].Type){
+ case tBarIo16:
+ rd->Type=ASLRV_SPC_TYPE_IO;
+ rd->_GRA=16;
+ break;
+ case tBarIo32:
+ rd->Type=ASLRV_SPC_TYPE_IO;
+ rd->_GRA=32;
+ break;
+ case tBarMmio32pf:
+ rd->TFlags.MEM_FLAGS._MEM=ASLRV_MEM_CEPF;
+ //no break intentionally!! DON'T CHANGE
+ case tBarMmio32:
+ rd->Type=ASLRV_SPC_TYPE_MEM;
+ rd->_GRA=32;
+ rd->TFlags.MEM_FLAGS._RW=1;
+ break;
+ case tBarMmio64pf:
+ rd->TFlags.MEM_FLAGS._MEM=ASLRV_MEM_CEPF;
+ //no break intentionally!! DON'T CHANGE
+ case tBarMmio64:
+ rd->Type=ASLRV_SPC_TYPE_MEM;
+ rd->_GRA=64;
+ rd->TFlags.MEM_FLAGS._RW=1;
+ break;
+ default : continue;
+ }
+ rd->Hdr.HDR=0x8A;
+ rd->GFlags.GFLAGS=0x0C; //Means _MIN and _MAX is fixed
+ rd->Hdr.Length=0x2B;
+ rd->_MAX=ext->Res[i].Gran;
+ rd->_LEN=ext->Res[i].Length + ext->Align[i].ExtraRes.Length;
+
+ if(rd->Type==ASLRV_SPC_TYPE_MEM){
+ //Check to Memory Resource Size Align on 4K
+ if(rd->_LEN & (EFI_PAGE_SIZE-1))rd->_LEN=(rd->_LEN | (EFI_PAGE_SIZE-1))+1;
+ }
+
+ PCI_TRACE((TRACE_PCI,"CreateRD QWD: T=%X; GF=%X; TF=%X; _MN=%lX; _MX=%lX; _LN=%lX;_GR=%lX;\n",
+ rd->Type, rd->GFlags.GFLAGS, rd->TFlags.TFLAGS, rd->_MIN, rd->_MAX, rd->_LEN, rd->_GRA));
+
+ rd++;
+ }
+ rd->Hdr.HDR=ASLV_END_TAG_HDR;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConvertResources()
+//
+// Description: Converts Resource information from QWORD ACPI ResDesc
+// to internal format and store it within PCI_DEV_INFO structure.
+//
+// Input:
+// PCI_BRG_EXT *RbExt Pointer to PCI Device Private Data structure
+// of the Root Bridge. (PCI_BRG_EXT part)
+// ASLR_QWORD_ASD *Resources Pointer to the set
+
+// RES_CONV_TYPE ConvType Type of Conversion to be prformed.
+//
+// Output: Nothing
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ApplyAcpiResources(PCI_BRG_EXT *RbExt, ASLR_QWORD_ASD *Resources){
+ ASLR_QWORD_ASD *res=Resources;
+ PCI_BAR *bar;
+ UINTN i, s, e;
+//------------------------------------
+ while(res->Hdr.HDR!=ASLV_END_TAG_HDR) {
+ bar=NULL;
+ PCI_TRACE((TRACE_PCI,"ApplyRD QWD: T=%X; GF=%X; TF=%X; _MN=%lX; _MX=%lX; _LN=%lX;_GR=%lX;\n",
+ res->Type, res->GFlags.GFLAGS, res->TFlags.TFLAGS, res->_MIN, res->_MAX, res->_LEN, res->_GRA));
+
+ if(res->Type==ASLRV_SPC_TYPE_IO){
+ s=rtIo16;
+ e=rtMmio32;
+ } else {
+ if(res->Type==ASLRV_SPC_TYPE_MEM){
+ s=rtMmio32;
+ e=rtMaxRes;
+ } else {
+ res++;
+ continue;
+ }
+ }
+
+ for(i=s; i<e; i++){
+ UINT64 len;
+ //--------------------
+ bar=&RbExt->Res[i];
+ len=bar->Length+RbExt->Align[i].ExtraRes.Length;
+
+ if( (res->Type==ASLRV_SPC_TYPE_MEM) && (len&(EFI_PAGE_SIZE-1)) )
+ len=(len|(EFI_PAGE_SIZE-1))+1;
+
+ //It might be an empty descriptor (i.e. System has MMIO32, but does not have MMIO32PF)
+ //This might cause to break early. w/o searching through 64bit resources
+ //take care of this condition by adding check (bar->Length != 0)
+ if((bar->Base == 0) && (bar->Length != 0) && (len <= res->_LEN)) break;
+ else bar=NULL;
+ }
+
+ if(bar)bar->Base=res->_MIN;
+ res++;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitPciDb()
+//
+// Description: Creates all anckor structures and Initialize PCI Database.
+//
+// Input:
+// EFI_HANDLE Controller Controller Handle passed to the PCI Bus Driver
+// Start Function.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InitPciDb(EFI_HANDLE Controller){
+ EFI_STATUS Status;
+ EFI_HANDLE *hBuff, htmp=NULL;
+ EFI_DEVICE_PATH_PROTOCOL *rbdp;
+ UINTN i, cnt=0;
+ PCI_DEV_INFO *rb;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *rbio;
+
+//Exclude Hotplug support
+#if HOTPLUG_SUPPORT
+ UINTN ghpccnt=0, j;
+ EFI_HPC_LOCATION *ghpclst=NULL;
+#endif
+
+//------------------------
+ Status=PopulateBusDb();
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ Status=pBS->HandleProtocol(Controller,&gPciRootBridgeIoProtocolGuid,&rbio);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return EFI_INVALID_PARAMETER;
+ if(gPciHost && gPciHost[0].Updated) return EFI_SUCCESS;
+
+
+ //Try to figure out how many instances of PCI HostBridge Resource Allocation Protocol
+ //exists, this will give us an idea how many PCI_ROOT_INFO instances to create...
+ Status=pBS->LocateHandleBuffer(
+ ByProtocol, // SearchType,
+ &gEfiPciHostBrgResAllocProtocolGuid, //*Protocol OPTIONAL,
+ NULL, //*SearchKey OPTIONAL,
+ &gHostCnt, //*NoHandles,
+ &hBuff); //**Buffer
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Now we know how many Host Bridges the System has
+ gPciHost=MallocZ(sizeof(PCI_HOST_INFO)*gHostCnt);
+
+ //record Host Bridge Properties
+ for(i=0; i<gHostCnt; i++){
+ gPciHost[i].HostHandle=hBuff[i];
+ //Get Resource Alloc Protocol and Record It
+ Status=pBS->HandleProtocol(hBuff[i],&gEfiPciHostBrgResAllocProtocolGuid,&gPciHost[i].ResAllocProt);
+ //it has to be there or plaform is not Framework compliant
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ //now will locate some optional protocols which must be used if present during PCI enumeration
+ //as per spec - only one instance of this protocols should be present
+ if(i==0){
+//Exclude Hotplug support
+#if HOTPLUG_SUPPORT
+ pBS->LocateProtocol(&gEfiPciHotPlugInitProtocolGuid, NULL, &gPciHost[i].HpInitProt);
+#endif
+ pBS->LocateProtocol(&gEfiPciPlatformProtocolGuid, NULL, &gPciHost[i].PlatformProt);
+ pBS->LocateProtocol(&gEfiIncompatiblePciDeviceProtocolGuid, NULL, &gPciHost[i].IncompDevProt);
+ } else {
+//Exclude Hotplug support
+#if HOTPLUG_SUPPORT
+ gPciHost[i].HpInitProt=gPciHost[0].HpInitProt;
+#endif
+ gPciHost[i].PlatformProt=gPciHost[0].PlatformProt;
+ gPciHost[i].IncompDevProt=gPciHost[0].IncompDevProt;
+ }
+ gPciHost[i].Updated=TRUE;
+ }
+
+//Exclude Hotplug support
+#if HOTPLUG_SUPPORT
+
+ //If HpInitProtocol Exists get RootHpcList
+ if(gPciHost[0].HpInitProt ){
+ Status=gPciHost[0].HpInitProt->GetRootHpcList(gPciHost[0].HpInitProt,&ghpccnt,&ghpclst);
+ ASSERT_EFI_ERROR(Status);
+ }
+#endif
+
+ //Now get all RbIo Protocol Handlers and find the right place for it Protocol Instance.
+ Status=pBS->HandleProtocol(Controller,&gPciRootBridgeIoProtocolGuid,&rbio);
+ //RBIoProtocol has to be installed on Controller Handle
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Select Right Host Brg for this RootBrg Io Protocol Handler
+ for(i=0; i<gHostCnt; i++){
+ //if(gPciHost[i].HostHandle==rbio->ParentHandle) gCurHost=i;
+
+ htmp=NULL;
+ //Now we will fill Pci Root infrastructure in the right order
+ while(!Status){
+ //get Root Bridge Handle of this Host
+ Status=gPciHost[i].ResAllocProt->GetNextRootBridge(gPciHost[i].ResAllocProt, &htmp);
+ if(EFI_ERROR(Status)) break;
+
+
+ //Create New PCI_BRG_INFO structure;
+ rb=NewDevice(TRUE,NULL);
+ if(!rb) return EFI_OUT_OF_RESOURCES;
+
+ //Get the Resource Allocation Attributes
+ //Status=gPciHost[i].ResAllocProt->GetAllocAttributes(gPciHost[i].ResAllocProt, htmp, &rb->Attrib);
+ //if(EFI_ERROR(Status)) break;
+
+
+ //Add it to the Root Bridge Item List
+ Status=AppendItemLst((T_ITEM_LIST*)&gPciHost[i].RbInitCnt, rb);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //now I'll get DevicePath and RootBridgeIo protocols Associated with this Handle
+ //Status=pBS->HandleProtocol(htmp,&gPciRootBridgeIoProtocolGuid,&rb->RbIo);
+ //This Protocol will remain opened untill PciBusStop is Called.
+ Status=pBS->OpenProtocol(htmp,
+ &gPciRootBridgeIoProtocolGuid,(VOID **)&rb->RbIo,
+ gPciBusDriverBinding.DriverBindingHandle,htmp,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ ASSERT_EFI_ERROR(Status); //it MUST have this
+ if(EFI_ERROR(Status)) return Status;
+
+ Status=pBS->HandleProtocol(htmp,&gDevicePathProtocolGuid,&rbdp);
+ ASSERT_EFI_ERROR(Status); //it MUST have this
+ if(EFI_ERROR(Status)) return Status;
+
+ //Fill out some missing and incorrectly filled fields
+ rb->DevicePath=DPCopy(rbdp);
+ rb->Type=tPciRootBrg;
+ rb->HostData=&gPciHost[i];
+ rb->Handle=htmp;
+ rb->ParentBrg=NULL;
+
+//Exclude Hotplug support
+#if HOTPLUG_SUPPORT
+
+ //sort out Root Hot Plug Controlers list items to where they belongs
+ PCI_TRACE((TRACE_PCI,"PciBus: Get Location - HpcLocCount=%d; RbDp=[HID(%X)UID(%X)]\n",
+ ghpccnt,((ACPI_HID_DEVICE_PATH*)rbdp)->HID,((ACPI_HID_DEVICE_PATH*)rbdp)->UID));
+ PCI_TRACE((TRACE_PCI,"-------------------------------------------------\n"));
+
+ for (j=0; j<ghpccnt; j++){
+
+ if( !MemCmp(rbdp, ghpclst[j].HpcDevicePath, sizeof(ACPI_HID_DEVICE_PATH)) ){
+ PCI_HPC_INFO *rhpc;
+ //-----------------------------
+ rhpc=MallocZ(sizeof(PCI_HPC_INFO));
+ ASSERT(rhpc);
+ if(!rhpc) return EFI_OUT_OF_RESOURCES;
+ //Init PCI_ROOT_HPC structure
+ rhpc->Root=TRUE;
+ rhpc->HpcLocation=&ghpclst[j];
+
+ PCI_TRACE((TRACE_PCI,"HpcDP=[HID(%X)UID(%X)]; HpbDP[HID(%X)UID(%X)]\n",
+ ((ACPI_HID_DEVICE_PATH*)rhpc->HpcLocation->HpcDevicePath)->HID,((ACPI_HID_DEVICE_PATH*)rhpc->HpcLocation->HpcDevicePath)->UID,
+ ((ACPI_HID_DEVICE_PATH*)rhpc->HpcLocation->HpbDevicePath)->HID,((ACPI_HID_DEVICE_PATH*)rhpc->HpcLocation->HpbDevicePath)->UID));
+
+ Status=AppendItemLst((T_ITEM_LIST*)&rb->HostData->RhpcInitCnt,rhpc);
+ ASSERT_EFI_ERROR(Status); //it MUST have this
+ if(EFI_ERROR(Status)) return Status;
+ }
+ }
+ PCI_TRACE((TRACE_PCI,"-------------------------------------------------\n"));
+#endif
+
+ }
+ if(Status!=EFI_NOT_FOUND) return Status;
+ }
+
+ //Don't forget to free handle Buffer;
+ pBS->FreePool(hBuff);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EnumerateAll()
+//
+// Description: This is Main function to start PCI Bus Enumeration Process.
+//
+// Input:
+// EFI_HANDLE Controller Controller Handle passed to the PCI Bus Driver
+// Start Function.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EnumerateAll(EFI_HANDLE Controller){
+ EFI_STATUS Status=EFI_SUCCESS;
+ UINTN i, j;
+ UINT8 StartBus, EndBus;
+ RES_CONV_TYPE ct;
+ PCI_HOST_INFO *lhst;
+ PCI_DEV_INFO *rb;
+ PCI_BRG_EXT *ext;
+ ASLR_QWORD_ASD *rres;
+//-------------------------------
+ //Init Pci Local Data if it wasn't initialized yet
+ if(gPciHost==NULL){
+ Status=InitPciDb(Controller);
+ ASSERT_EFI_ERROR(Status);
+ }
+ //Check if we have enumerated VERY FIRST ROOT we done.
+ //That means all roots were enumerated alredy, don't spend eny more time here...
+ if(gPciHost[0].Enumerated) return EFI_SUCCESS;
+
+ //We will do enumeration for all PCI infrastructure, as soon as we got very first
+ //Root Bridge Handle. and then will start only devices belonging to the RootBridge
+ //who's handle we have received as a Controller Handle.
+ mMaxBusFound=0;
+ mMaxBusReport=0;
+
+ for(j=0; j<gHostCnt; j++){
+ lhst=&gPciHost[j]; //init local host pointer
+
+ //will circle trough Root bridges system has starting from _UID=0
+ for(i=0; i<lhst->RbCount; i++){
+ rb=lhst->RootBridges[i];
+ ext=(PCI_BRG_EXT*)(rb+1);
+
+#if BoardPciRes_SUPPORT
+ gPciOutOfRes=FALSE;
+#endif
+ //check if we have this Root Bridge Enumerated already
+ if(rb->Enumerated) continue;
+// ClearItemLst(&res, TRUE);
+
+ //6. Notify the host bridge driver that PCI enumeration is about to begin by calling
+ //NotifyPhase (EfiPciHostBridgeBeginEnumeration). This member function
+ //must be the first one that gets called. PCI enumeration has two steps: bus enumeration and
+ //resource enumeration.
+ Status=DoPciNotify(lhst, EfiPciHostBridgeBeginEnumeration);
+ ASSERT_EFI_ERROR(Status);
+
+ //7. Notify the host bridge driver that bus enumeration is about to begin by calling
+ //NotifyPhase (EfiPciHostBridgeBeginBusAllocation).
+ Status=DoPciNotify(lhst, EfiPciHostBridgeBeginBusAllocation);
+ ASSERT_EFI_ERROR(Status);
+
+ //8. Do the following for every PCI root bridge handle:
+ // a. Call StartBusEnumeration (This,RootBridgeHandle).
+ Status=lhst->ResAllocProt->StartBusEnumeration(lhst->ResAllocProt, rb->Handle, &rres);
+ ASSERT_EFI_ERROR(Status);
+
+ //Check if it is NULL descriptor..
+ if(rres->_MIN==0 && rres->_MAX==0 && rres->_LEN==0) {
+ Status=DoPciNotify(lhst, EfiPciHostBridgeEndBusAllocation);
+ Status=DoPciNotify(lhst, EfiPciHostBridgeBeginResourceAllocation);
+ continue;
+ }
+
+ //Check if we've received correct descriptors
+ if(!ValidateDescriptorBlock(rres,tResBus,FALSE)) {
+ ASSERT(0);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //we have reseived BUS configuration information in "rres"
+ //_MIN Bus# has to be Updated with respect of previous pass
+ StartBus=(UINT8)rres->_MIN;
+ mMaxBusFound=StartBus;
+
+ rb->Address.Addr.Bus=StartBus;
+ mMaxBusScan=(UINTN)(StartBus+rres->_LEN-1);
+ //Maximum bus number must not exceed 0xFF buses!
+ if(mMaxBusScan > 0xFF) ASSERT_EFI_ERROR(EFI_DEVICE_ERROR);
+ //Match Busxlat Entry to the current Host Bridge
+ Status=FindBridgeXlatEntry(rb, ext);
+ //It's a seriouse error if it returns NOT_FOUND need to ASSERT here.
+ ASSERT_EFI_ERROR(Status);
+
+ ext->Res[rtBus].Type=tBarBus;
+ ext->Res[rtBus].Base=StartBus;
+ ext->Res[rtBus].Length=rres->_LEN;
+ //Get Attributes to see what this RB could support
+ Status=rb->RbIo->GetAttributes(rb->RbIo,&rb->Capab,&rb->Attrib);
+ ASSERT_EFI_ERROR(Status);
+
+//Exclude Hotplug support
+#if HOTPLUG_SUPPORT
+ //this will try to init Root HPC siting behind this bridge if any...
+ Status=CheckRootHotplug(rb);
+ ASSERT_EFI_ERROR(Status);
+ //if root hpc init fail for any reason we just must keep going
+#endif
+ // b. Make sure each PCI root bridge handle supports the
+ // EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ // c. Allocate memory to hold resource requirements. These resources can be two resource trees:
+ // one to hold bus requirements and another to hold the I/O and memory requirements.
+ //
+ // e. Scan all the devices in the specified bus range and on the specified segment. If it is a PCIto-
+ // PCI bridge, update the bus numbers and program the bus number registers in the PCI-to-
+ // PCI bridge hardware. If it is an ordinary device, collect the resource request and add up all
+ // of these requests in multiple pools (e.g., I/O, 32-bit prefetchable memory). Combine
+ // different types of memory requests at an appropriate level based on the PCI root bridge
+ // attributes. Update the resource requirement information accordingly. On every PCI root
+ // bridge, reserve space to cover the largest expansion ROMs on that bus, which will allow
+ // the PCI bus driver to retrieve expansion ROMs from the PCI card or device without having
+ // to reprogram the PCI host bridge. Because the memory and I/O resource collection step
+ // does not call any member function of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL,
+ // it can be performed at a later time.
+ // f. Once the number of PCI buses under this PCI root bridge is known, call
+ // SetBusNumbers() with this information.
+
+ //Go and do the job!
+ mMaxBusReport=StartBus;
+ PCI_TRACE((TRACE_PCI,"PciBus: Root#%d; ScanFullBusRange=%d; Scanning ",i, ScanFullBusRange));
+ if(ScanFullBusRange) {
+ EndBus=(UINT8)(mMaxBusScan);
+ PCI_TRACE((TRACE_PCI,"Bus Range 0x%X...0x%X \n", StartBus, EndBus));
+ } else {
+ EndBus=StartBus;
+ PCI_TRACE((TRACE_PCI,"Buses Starting from 0x%X \n", StartBus));
+ }
+
+ if(ext->XlatTblEntry) ext->XlatTblEntry->BusRun=StartBus;
+
+ do{
+ Status=EnumerateBus((PCI_DEV_INFO*)rb);
+ if(EFI_ERROR(Status)){
+ if(Status != EFI_NOT_FOUND) return Status;
+ } else {
+ if(mMaxBusReport < rb->Address.Addr.Bus) mMaxBusReport = rb->Address.Addr.Bus;
+ rb->Address.Addr.Bus = mMaxBusReport;
+ ext->Res[rtBus].Base = mMaxBusReport;
+ }
+
+ //Bus is UINT8 to avoid deadloop here check
+ //for condition to berak the loop.
+ if(rb->Address.Addr.Bus==0xFF) break;
+ rb->Address.Addr.Bus++;
+ ext->Res[rtBus].Base++;
+ } while (rb->Address.Addr.Bus <= EndBus);
+
+#if PCI_EXPRESS_SUPPORT
+ //We have collected all Upstream Ports information
+ //Now init it from EndPoint up to RootPort
+ while(gPcieEpList.ItemCount!=0){
+ PCI_DEV_INFO *epdev;
+ //---------------------
+ epdev=(PCI_DEV_INFO*)gPcieEpList.Items[0];
+
+ Status=PcieInitDevChain(epdev);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+#endif
+ //Restore old values
+ rb->Address.Addr.Bus = StartBus;
+ ext->Res[rtBus].Base = StartBus;
+ if(ext->XlatTblEntry){
+ UpdateIrqTables(ext->XlatTblEntry);
+ PCI_TRACE((TRACE_PCI,"PciBus: Update Bus# for RootBrg [B%X|D%X|F%X] - Bld %X -> Run %X\n",
+ rb->Address.Addr.Bus,rb->Address.Addr.Device,rb->Address.Addr.Function,
+ ext->XlatTblEntry->BusBuild,ext->XlatTblEntry->BusRun));
+ }
+
+ //we got lucky!!! finally we are here with information about all resources we need
+ //in the Root Bridge device the following fields will reflect ACPI Resource descriptor fields
+ // rb->Address.Bus = Primary Bus Number _MIN
+ // ext->Res[rtBus].Base = Subordinate Bus Number = _MAX
+ // ext->Res[rtBus].Len = _MAX+1
+ ext->Res[rtBus].Base=mMaxBusReport; //that how much this root brg has buses
+ ext->Res[rtBus].Length=mMaxBusReport-StartBus+1;
+
+ //Update discovered Bus Numbers and report Bus Resources to the HOST
+ rres->_LEN=ext->Res[rtBus].Length;
+ rres->_MAX=rres->_MIN+rres->_LEN-1;
+ Status=lhst->ResAllocProt->SetBusNumbers(lhst->ResAllocProt, rb->Handle, rres);
+ ASSERT_EFI_ERROR(Status);
+ //if everything OK free memory given by StartBusEnumeration function
+ pBS->FreePool(rres);
+
+
+
+ //Here we have to convert some resourcers which we have discovered but RB doesn't supports
+ //Get Allocation Attributes for this Root Bridge it will let us know how to convert resources for this Root bridge
+//???????????????????????????????????????????????????????????????????????????????????????????????????
+//Currently resource allocation attributes reflects only capability of RB to decode 64 bit address
+//but still will not give any clue weathere it is single window or RB has a separate BAR to decode it.
+//If the bar is single and it decodes eather 32 or 64 bit resources the "rcOneOf" must be selected
+//???????????????????????????????????????????????????????????????????????????????????????????????????
+ Status=lhst->ResAllocProt->GetAllocAttributes(lhst->ResAllocProt,rb->Handle,&gAllocationAttributes);
+ ASSERT_EFI_ERROR(Status);
+
+ //Notify HB and CSP
+ Status=DoPciNotify(lhst, EfiPciHostBridgeEndBusAllocation);
+ ASSERT_EFI_ERROR(Status);
+
+ PROGRESS_CODE(DXE_PCI_BUS_REQUEST_RESOURCES);
+
+ //First do IO - Any PCI Root Bridge supports only Io16
+ ConvertResources((PCI_BRG_INFO*)rb,tBarIo,rcNarrow,(BOOLEAN)(gAllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM));
+
+ //than do MMIO
+ if(gAllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE)ct=rcBoth;
+ else ct=rcNarrow;
+ ConvertResources((PCI_BRG_INFO*)rb,tBarMem,ct,(BOOLEAN)(gAllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM));
+
+ //than do pfMMIO
+ if(gAllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE)ct=rcBoth;
+ else ct=rcNarrow;
+ ConvertResources((PCI_BRG_INFO*)rb,tBarMemPf,ct,(BOOLEAN)(gAllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM));
+
+//???????????????????????????????????????????????????????????????????????????????????????????????????
+// Attempt to boot with reduced number of PCI Cards if resources will be not enough
+//??has to be called consequently
+//??or create RecalculateBrgResources()...
+//////////////////////////////////////////////////////////////////
+//???????????????????????????????????????????????????????????????????????????????????????????????????
+#if BoardPciRes_SUPPORT
+
+ do{
+//OUT_OF_RES!!
+ //Reset Flag to stop calling Platform function to select PCI device selected
+ // to be removed from enumeration for this pass. It will be SET in CalculateBrgResources().
+ gPciOutOfResHit=FALSE;
+ ext=(PCI_BRG_EXT*)(rb+1);
+ if(gPciOutOfRes) ClearBrgResources(rb);
+#endif
+ //Calculate resources Consumed by this Root bridge
+ CalculateBrgResources(rb);
+ rb->Discovered=TRUE;
+
+ //Notify HB and CSP
+ Status=DoPciNotify(lhst, EfiPciHostBridgeBeginResourceAllocation);
+ ASSERT_EFI_ERROR(Status);
+
+ //Status=AllocateRootResources(gPciRoot.RootBrg[i], &mRootRes);
+ //Create Resource information to report to the HOST BRG
+ Status=CreateRootResDsc(rb,&rres);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"PciBus: CreateRootResDsc() returned %r \n ",Status));
+ return Status;
+ }
+
+ //Not Found Condition is Normal for RB it does not have enything behind it.
+ //Skip Calling SubmitResources() since nothing to Submit
+ Status=lhst->ResAllocProt->SubmitResources(lhst->ResAllocProt, rb->Handle, rres);
+ if(EFI_ERROR(Status)) {
+ VOID *Configuration; //This is a dummy parameter.
+#if BoardPciRes_SUPPORT
+#if PCI_OUT_OF_RESOURCE_SETUP_SUPPORT
+ //Declare Boot flow variable GUID...
+ EFI_GUID BootFlowVariableGuid = BOOT_FLOW_VARIABLE_GUID;
+ UINT32 BootFlow = BOOT_FLOW_CONDITION_PCI_OUT_OF_RESOURCE;
+ //------------------------------
+ Status=pRS->SetVariable(L"BootFlow",&BootFlowVariableGuid,EFI_VARIABLE_BOOTSERVICE_ACCESS,sizeof(BootFlow),&BootFlow);
+#endif
+
+ //Give Platform Policy Driver to handle OUT_OF_RESOURCES situation
+ //by itself (it just might want to BEEP and HUNG the system)
+ gPciOutOfRes=TRUE;
+
+#endif
+ lhst->ResAllocProt->GetProposedResources(
+ lhst->ResAllocProt,
+ rb->Handle,
+ &Configuration);
+#if BoardPciRes_SUPPORT
+#else
+ ERROR_CODE(DXE_PCI_BUS_OUT_OF_RESOURCES,EFI_ERROR_MAJOR);
+ ASSERT_EFI_ERROR(Status);
+#endif
+ pBS->FreePool(rres);
+#if BoardPciRes_SUPPORT
+ } else gPciOutOfRes=FALSE;
+ } while(gPciOutOfRes); //while resources found
+#else
+ return Status;
+ }
+#endif
+ } //loop (i) on submiting resources
+#if BoardPciRes_SUPPORT
+ //Check if we suppose to beep and report "OUT OF_RESOURCES" condition
+ Status=AmiPciOutOfRes(NULL, TRUE);
+ if(!EFI_ERROR(Status)) ERROR_CODE(DXE_PCI_BUS_OUT_OF_RESOURCES,EFI_ERROR_MAJOR);
+#endif
+ //Notify HB and CSP
+ Status=DoPciNotify(lhst, EfiPciHostBridgeAllocateResources);
+ PROGRESS_CODE(DXE_PCI_BUS_ASSIGN_RESOURCES);
+
+
+ ASSERT_EFI_ERROR(Status);
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+// if Allocate Resources Notify Phase returns an ERROR
+// Here suppose to be the following logic :
+// a. Make do with the smaller ranges.
+// b. Call GetProposedResources() to retrieve the proposed settings and examine the
+// differences. Prioritize various requests and drop lower-priority requests. Call
+// NotifyPhase (EfiPciHostBridgeFreeResources) to undo the previous
+// allocation. Go back to step 11 with reduced requirements, which includes resubmitting
+// requests for all the root bridges.
+
+
+// It easy to say, but hard to implement!!!!!
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+
+ Status=DoPciNotify(lhst, EfiPciHostBridgeSetResources);
+ ASSERT_EFI_ERROR(Status);
+
+ //now enter the loop where we will get resource windows selected by the Root Bridge
+ //and programm it in to PCI subsystem BARs
+ for(i=0; i<lhst->RbCount; i++){
+ rb=lhst->RootBridges[i];
+ ext=(PCI_BRG_EXT*)(rb+1);
+
+ //Get Copy of updated resources to see if our call worked
+ Status=rb->RbIo->Configuration(rb->RbIo,(VOID**)&rres);
+ if (Status==EFI_NOT_AVAILABLE_YET) continue;
+
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ ApplyAcpiResources(ext, rres);
+
+ //now we have to assign PCI bus resources, and PciRoot will be the special case.
+ //We should not touch the device which adressed as gPciRoot.RootBrg[i].Address
+ //because it is controlled by PciRootBridge Driver and we must not directly access it
+ //So AssignBusResources routine has a checking of such condition
+ Status=AssignBusResources((PCI_BRG_INFO*)rb);
+ if(EFI_ERROR(Status)) return Status;
+
+#if PCI_EXPRESS_SUPPORT
+ //Record PciEcpress Boot Script since not all OSs knows about it
+ PcieRecordBootScript(rb);
+#endif
+
+ //Set Started Flag for RootBridge device in order not to install PCI IO on it later
+ rb->Started=TRUE;
+ }//loop (i) for root bridge
+ Status=DoPciNotify(lhst, EfiPciHostBridgeEndResourceAllocation);
+ ASSERT_EFI_ERROR(Status);
+
+ lhst->Enumerated=TRUE;
+ } //loop (j)
+#if S3_VIDEO_REPOST_SUPPORT == 1
+// if( (gPciSetupData->S3ResumeVideoRepost==1) && S3VideoRepost ){
+ // Register the event handling function to Record Primary VGA BootScript.
+ Status = CreateReadyToBootEvent (
+ TPL_CALLBACK,
+ RecordPriVgaBootScript,
+ NULL,
+ &gVgaS3Event);
+// }
+#endif
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckPciDevicePath()
+//
+// Description: Checks if "DevicePath" is a PCI_DEVICE_PATH.
+//
+// Input:
+// EFI_DEVICE_PATH_PROTOCOL *DevicePath Device Path Pointer.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_UNSUPPORTED When "DevicePath" is not a PCI_DEVICE_PATH.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CheckPciDevicePath(EFI_DEVICE_PATH_PROTOCOL *DevicePath)
+{
+ // Check if the RemainingDevicePath is valid
+ if (DevicePath->Type != HARDWARE_DEVICE_PATH ||
+ DevicePath->SubType != HW_PCI_DP &&
+ NODE_LENGTH(DevicePath) != sizeof (PCI_DEVICE_PATH))
+ return EFI_UNSUPPORTED;
+ else return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DoubleCheckOpRom()
+//
+// Description: This function called when PciRomHdr->InitializationSize and
+// Pcir->ImageSize has different values and Pcir->Indicator bit 7 is not set.
+// It evaluets whch one is correct by Searching for 0x55AA signature that is
+// must present in the beginning of next OptROM image.
+//
+// Input:
+// LEGACY_OPT_ROM_HEADER *PciRomHdr Pointer to Legacy Option ROM Header(0x55AA).
+// PCI_DATA_STRUCTURE *Pcir Pointer to PCI ROM header ("PCIR")
+//
+// Output: EFI_STATUS
+// UINTN Size of the ROM in bytes;
+// Note: PCIR and OptROM signatures assumed to be valid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN DoubleCheckOpRom(VOID *PciRomHdr, PCI_DATA_STRUCTURE *Pcir){
+ UINT8 *p;
+ UINTN sz=0;
+ UINTN hsz=0;
+//---------------------------------
+ //EFI Compatible ROM headers have 16 bit Length field...
+ if( ((PCI_EFI_OPT_ROM_HEADER*)PciRomHdr)->EfiSignature == PCI_OPT_ROM_EFISIG) hsz=((PCI_EFI_OPT_ROM_HEADER*)PciRomHdr)->InitializationSize; //16 bit size
+ else hsz=((LEGACY_OPT_ROM_HEADER*)PciRomHdr)->Size512;
+
+ if(hsz == Pcir->ImageLength ) return (hsz*512);
+
+ p=(UINT8*)PciRomHdr;
+
+ if(hsz < Pcir->ImageLength ) {
+ sz= Pcir->ImageLength*512;
+ if( ((LEGACY_OPT_ROM_HEADER*)(p+sz))->Signature==PCI_OPT_ROM_SIG) return sz;
+ if(Pcir->Indicator&0x80) return sz; //(EIP37774+)
+ }
+
+ sz=hsz*512;
+ if( ((LEGACY_OPT_ROM_HEADER*)(p+sz))->Signature==PCI_OPT_ROM_SIG) return sz;
+ else {
+ if(Pcir->Indicator&0x80) return sz;//(EIP37774+)
+ if ( ((LEGACY_OPT_ROM_HEADER*)PciRomHdr)->Signature==PCI_OPT_ROM_SIG ) return sz;
+ return 512;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetOptRom()
+//
+// Description: Validate and copy PCI Option ROM Image From ADD ON CARD to
+// the System Memory.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer PCI Devicse Private Data.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_DEVICE_ERROR When driver fails access PCI Bus.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetOptRom(PCI_DEV_INFO *Dev)
+{
+ EFI_STATUS Status=EFI_NOT_FOUND, ExitStatus=0;
+ PCI_BAR *rombar=&Dev->Bar[PCI_MAX_BAR_NO];
+ //UINT8 RomBuff[20];
+ UINTN OptRomSize = 0;
+ UINT32 trs=0;
+ PCI_DATA_STRUCTURE Pcir;
+ PCI_STD_OPT_ROM_HEADER PciRomHdr;
+ PCI_EFI_OPT_ROM_HEADER *EfiRomHdr=(PCI_EFI_OPT_ROM_HEADER*)&PciRomHdr;
+#if CSM_SUPPORT
+ VOID *EmbRom;
+#endif
+ BOOLEAN ff=TRUE;
+ UINT64 base=rombar->Base;
+ UINTN sz=0;
+//-------------------------------------
+ //we got Opt ROM to check...
+ if(Dev->Bar[PCI_MAX_BAR_NO].Type!=tBarUnused){
+ //Enable RomBar Decoding
+ //We will use PciIo->SetAttributes here to enable device Memory Space.
+ //If device sits behind some P2P brg Attributes will enable it all the way down
+ //Per UEFI 2.1 spec bridges must be open and decoding it's resources.
+ //Status=DeviceAttributes(Dev, EFI_PCI_IO_ATTRIBUTE_MEMORY, TRUE);
+ //if(EFI_ERROR(Status))return Status;
+
+ Status=EnableDeviceDecoding(Dev,stOptRomSpace);
+ if(EFI_ERROR(Status))return Status;
+
+ for(;;){
+ if(base+trs+512 >= rombar->Base+rombar->Length) break;
+
+ // Get the first 20 bytes of the ROM header
+ Status=Dev->RbIo->Mem.Read(Dev->RbIo, EfiPciWidthUint8, base+trs,
+ sizeof(PCI_STD_OPT_ROM_HEADER), &PciRomHdr);
+ if(EFI_ERROR(Status))goto ExitLbl;
+
+ // Check the validity of the ROM
+ if ((PciRomHdr.Signature != PCI_OPT_ROM_SIG) || (PciRomHdr.PcirOffset == 0) ){
+ if(ff) {
+ Status=EFI_NOT_FOUND;
+ goto ExitLbl;
+ } else {
+ //base+=512;
+ trs+=512;
+ continue;
+ }
+ }
+ ff=FALSE;
+
+ Status=Dev->RbIo->Mem.Read(Dev->RbIo, EfiPciWidthUint8, base+trs+PciRomHdr.PcirOffset,
+ sizeof(PCI_DATA_STRUCTURE), &Pcir);
+ if(EFI_ERROR(Status))goto ExitLbl;
+
+ if(Pcir.Signature!=PCI_PCIR_SIG){
+ //Status=EFI_NOT_FOUND;
+ //goto ExitLbl;
+ continue;
+ }
+
+ OptRomSize=trs;
+
+ sz=DoubleCheckOpRom((VOID*)(base+trs), &Pcir);
+ OptRomSize+=sz;
+
+/*
+ //Figure out the size of image. Some of the cards has PCI_STD_OPT_ROM_HEADER.Size value
+ //bigger then in PCIR PCI_DATA_STRUCTURE.ImageLength field.
+ if(Pcir.CodeType == 0){
+ if(PciRomHdr.Reserved[0] < Pcir.ImageLength) OptRomSize+=(Pcir.ImageLength*512);
+ else OptRomSize+=(PciRomHdr.Reserved[0]*512);
+ }
+ //Open Firmware Standard for PCI
+ if(Pcir.CodeType == 1){
+ OptRomSize+=(Pcir.ImageLength*512);
+ }
+
+ //In case of EFI Option ROM Header
+ if(Pcir.CodeType == 3) {
+ if(EfiRomHdr->InitializationSize < Pcir.ImageLength) OptRomSize+=(Pcir.ImageLength*512);
+ else OptRomSize+=(EfiRomHdr->InitializationSize*512);
+ }
+*/
+ trs=(UINT32)OptRomSize;
+
+ if(Pcir.Indicator & 0x80) break;
+ }//for(;;)
+
+ //Allocate Memory For Opt Rom Image Buffer
+ Dev->PciIo.RomImage=Malloc(OptRomSize);
+ if(Dev->PciIo.RomImage==NULL){
+ Status=EFI_OUT_OF_RESOURCES;
+ goto ExitLbl;
+ }
+
+ //Copy Rom image into memory
+// Status=Dev->RbIo->Mem.Read(Dev->RbIo, EfiPciWidthUint8,rombar->Base,
+// OptRomSize,Dev->PciIo.RomImage);
+// if(EFI_ERROR(Status)) goto ExitLbl;
+
+ MemCpy32(Dev->PciIo.RomImage, (VOID*)(rombar->Base), OptRomSize);
+
+ //We didnot parse OPT ROM buffer yet so RomSize will have temp value
+ Dev->PciIo.RomSize=OptRomSize;
+
+ExitLbl:
+ //Disable decoding option rom again
+ //Per UEFI 2.1 spec bridges must be open and decoding it's resources.
+ //ExitStatus=DeviceAttributes(Dev, EFI_PCI_IO_ATTRIBUTE_MEMORY, FALSE);
+ ExitStatus=DisableDeviceDecoding(Dev,stOptRomSpace);
+ } //if(Dev->Bar[PCI_MAX_BAR_NO].Type!=tBarUnused)
+ //We tryed to Find PCI Off Board Card Option ROM because it's ROM BAR was valid.
+ //But Some On Board Devices Implements ROM BAR but It does not have a valid ROM
+ //So I will check for embeded Option ROM if Status==EFI_NOT_FOUND and ExitStatus==EFI_SUCCES
+#if CSM_SUPPORT
+ if((Status==EFI_NOT_FOUND)&&(ExitStatus==EFI_SUCCESS)){
+ //Here we'll try to locate Embeded rom For Onboard devices.
+ //we'll use CSM Ext Protocol to do so.
+ if(gLegacyBiosExt==NULL) Status=EFI_NOT_FOUND;
+ else {
+ //Got Protocol. Will try to use it.
+ Status=gLegacyBiosExt->GetEmbeddedRom(0x20,Dev->DevVenId.VenId,
+ Dev->DevVenId.DevId,&EmbRom, &OptRomSize);
+ if(EFI_ERROR(Status)) {
+ Dev->PciIo.RomImage=NULL;
+ Dev->PciIo.RomSize=0;
+ } else {
+ //Check if Embeded Op ROM is valid...
+ if(*((UINT16*)EmbRom)!=PCI_OPT_ROM_SIG) Status=EFI_NOT_FOUND;
+ else{
+ //Allocate buffer for ROM Image.
+ Dev->PciIo.RomImage=Malloc(OptRomSize);
+ if(Dev->PciIo.RomImage==NULL) Status=EFI_OUT_OF_RESOURCES;
+ else {
+ MemCpy(Dev->PciIo.RomImage,EmbRom,OptRomSize);
+ Dev->PciIo.RomSize=OptRomSize;
+ Dev->Capab |= (EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE + EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM);
+ Dev->Attrib |= (EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE + EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM);
+ }
+ }
+ }
+ }
+ }
+#endif
+ if(EFI_ERROR(ExitStatus)) return ExitStatus;
+//(EIP42750+)
+ //Calling OEM Hook to override Option Rom content...
+ Status=PciPortOemGetOptRom(Dev, &Dev->PciIo.RomImage, &Dev->PciIo.RomSize);
+ //if porting hook not implemented, adjust Status, otherwice return whatever we got
+ if(Status==EFI_UNSUPPORTED) Status=EFI_SUCCESS;
+//(EIP42750-)
+ return Status;
+}
+
+
+#if ((defined EFI_SPECIFICATION_VERSION) && (EFI_SPECIFICATION_VERSION >= 0x2001F))
+EFI_STATUS LoadRomFile( IN EFI_LOAD_FILE2_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN BOOLEAN BootPolicy,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer OPTIONAL)
+{
+ PCI_LOAD_FILE_DATA *lfdata=(PCI_LOAD_FILE_DATA*)This;
+ PCI_DEV_INFO *dev=lfdata->Owner;
+ EFI_STATUS Status;
+ UINTN i;
+ MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *dp=(MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH*)FilePath;
+ PCI_ROM_IMAGE_DATA *romdata;
+ BOOLEAN found=FALSE;
+ VOID *imgb=NULL;
+ UINT32 imgsz;
+//---------------------
+
+ //Check input parameters first...
+ if( (dev->Signature != AMI_PCI_SIG) ||
+ (FilePath==NULL) || (BufferSize==NULL) ||
+ (dp->Header.Type!=MEDIA_DEVICE_PATH)||
+ (dp->Header.Type!=MEDIA_RELATIVE_OFFSET_RANGE_DP)||
+ (dev->EfiRomCount==0) ) return EFI_INVALID_PARAMETER;
+
+ if(BootPolicy==TRUE) return EFI_UNSUPPORTED;
+
+ for(i=0;i<dev->EfiRomCount; i++){
+ romdata=dev->EfiRomImages[i];
+ //verify that relative odffset corresponds to the images stored.
+ if(MemCmp(dp,&romdata->RomImageDP,sizeof(MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH))==0){
+ found=TRUE;
+ break;
+ }
+ }
+
+ if(!found) return EFI_NOT_FOUND;
+
+ if((romdata->ActualSize<*BufferSize)||(Buffer==NULL)){
+ *BufferSize=romdata->ActualSize;
+ if(Buffer==NULL)return EFI_SUCCESS;
+ else return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //here we have checked everything Time to read file ...
+ Status=ReadEfiRom(dev, romdata,&imgb,&imgsz);
+ if(EFI_ERROR(Status)) return Status;
+
+ MemCpy(Buffer,imgb,imgsz);
+
+ pBS->FreePool(imgb);
+ return Status;
+
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: OvrGetDriver()
+//
+// Description: PCI Bus Specific Override Protocol Get Override Driver
+// function implementation of the PCI Bus Driver.
+//
+// Input:
+// EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL **This Pointer PCI Devicse's
+// Bus Specific Override
+// Protocol Interface.
+// EFI_HANDLE IN OUT *DriverImageHandle Image Handle of the Option
+// ROM EFI Driver.
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When there are no more handles to override.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS OvrGetDriver(IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
+ IN OUT EFI_HANDLE *DriverImageHandle )
+{
+ PCI_BUS_OVERRIDE_DATA *ovr=(PCI_BUS_OVERRIDE_DATA*)This;
+ UINTN i;
+ EFI_HANDLE himg=NULL;
+ PCI_DEV_INFO *dev=ovr->Owner;
+ PCI_ROM_IMAGE_DATA *romdata;
+//------------------------------------------------------------------
+
+ if((DriverImageHandle==NULL)||(dev->EfiRomCount==0))return EFI_INVALID_PARAMETER;
+
+ //Here we know dev->EfiRomCount>0
+ if(*DriverImageHandle==NULL) {
+ romdata=dev->EfiRomImages[0];
+ himg=romdata->RomImgHandle;
+ } else {
+ for(i=0; i<dev->EfiRomCount; i++){
+ romdata=dev->EfiRomImages[i];
+ if(*DriverImageHandle==romdata->RomImgHandle)break;
+ }
+
+ if(i==dev->EfiRomCount) return EFI_INVALID_PARAMETER;
+
+ if(i<dev->EfiRomCount-1)himg=romdata->RomImgHandle;
+ else return EFI_NOT_FOUND;
+ }
+
+ *DriverImageHandle=himg;
+ return EFI_SUCCESS;
+}
+
+/*
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddOvrHandle()
+//
+// Description: Adds EFI_HANDLE of the Addon Card Option ROM image to the
+// PCI Bus Driver Private Data.
+//
+// Input:
+// PCI_BUS_OVERRIDE_DATA *OvrData Pointer to the PCI Devicse's Bus
+// Override data inside PCI_DEV_INFO
+// EFI_HANDLE OvrHandle Handle to add.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AddOvrHandle( PCI_DEV_INFO *Device, EFI_HANDLE OvrHandle, UINTN StartOffset, UINTN EndOffset)
+{
+ PCI_ROM_IMAGE_DATA *romdata;
+//-------------------------------------------------
+ if(Device->BusOvrData.BusOverride.GetDriver==NULL)Device->BusOvrData.BusOverride.GetDriver=OvrGetDriver;
+
+
+ //Get the space needed
+ romdata=MallocZ(sizeof(PCI_ROM_IMAGE_DATA));
+ if (romdata==NULL) return EFI_OUT_OF_RESOURCES;
+
+ romdata->RomImgHandle=OvrHandle;
+ romdata->RelOffsStart=StartOffset;
+ romdata->RelOffsEnd=EndOffset;
+
+ return AppendItemLst((T_ITEM_LIST*)&Device->RomInitCnt, romdata);
+}
+*/
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DecompressOptRom()
+//
+// Description: Decompresses Option ROM Image if it is Compressed.
+//
+// Input:
+// VOID *Image Pointer at the compressed Option ROM Image.
+// UINT32 ImageLength Length of the Compressed Image.
+// OUT VOID **DecompImage Place holder to return pointer to the
+// Decopressed Image.
+// OUT UINT32 ImageLength Length of the Decompressed Image.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DecompressOptRom( VOID *Image, UINT32 ImageLength, VOID** DecompImage, UINT32 *DecompSize)
+{
+ EFI_STATUS Status;
+ EFI_DECOMPRESS_PROTOCOL *dcp;
+ UINT32 scrsz, imgsz;
+ VOID *imgb, *scrb;
+//--------------------------------
+ //Check for parameter first
+ if(!DecompImage) return EFI_INVALID_PARAMETER;
+
+ Status = pBS->LocateProtocol(&gEfiDecompressProtocolGuid, NULL,(VOID**)&dcp);
+ if(EFI_ERROR(Status))return Status;
+
+ Status = dcp->GetInfo(dcp,Image,ImageLength, &imgsz, &scrsz);
+ if (EFI_ERROR (Status)) return Status;
+
+ Status=pBS->AllocatePool(EfiBootServicesData, imgsz,&imgb);
+ if(EFI_ERROR(Status)) return Status;
+
+ Status=pBS->AllocatePool(EfiBootServicesData, scrsz,&scrb);
+ if(EFI_ERROR(Status)) return Status;
+
+ Status=dcp->Decompress(dcp,Image,ImageLength,imgb,imgsz,scrb,scrsz);
+ pBS->FreePool(scrb);
+
+ if(!EFI_ERROR(Status)){
+ *DecompImage=imgb;
+ *DecompSize=imgsz;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS ReadEfiRom(PCI_DEV_INFO *Dev, PCI_ROM_IMAGE_DATA *RomData, VOID **ImgBase, UINT32 *ImgSize){
+ EFI_STATUS Status=EFI_SUCCESS;
+ VOID *imgb;
+ UINT32 imgsz;
+//-------------------
+
+ imgb=(VOID*)((UINTN)Dev->PciIo.RomImage+(UINTN)RomData->RomImageDP.StartingOffset);
+ imgsz=(UINT32)(RomData->RomImageDP.EndingOffset-RomData->RomImageDP.StartingOffset+1);
+
+ if (RomData->RomHeader->CompressionType){
+ Status=DecompressOptRom((UINT8*)RomData->RomHeader+RomData->RomHeader->EfiImageOffset,imgsz,&imgb,&imgsz);
+ }
+
+ if(!(EFI_ERROR(Status))){
+ *ImgBase=imgb;
+ *ImgSize=imgsz;
+ }
+ return Status;
+
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InstallEfiOpRom()
+//
+// Description: Loads and Starts Native EFI PCI Option ROM.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer PCI Devicse Private Data.
+// PCI_EFI_OPT_ROM_HEADER *RomHeader Pointer at PCI Option ROM Header
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InstallEfiOpRom( PCI_DEV_INFO *Dev,
+ PCI_EFI_OPT_ROM_HEADER *RomHeader,
+ PCI_DATA_STRUCTURE *Pcir)
+{
+ EFI_STATUS Status=0;
+ VOID *imgb;
+ UINT32 imgsz;
+ PCI_ROM_IMAGE_DATA *romdata;
+ EFI_DEVICE_PATH_PROTOCOL *romdp=NULL;
+
+//-------------------------------------------
+
+ if ((RomHeader->EfiSubsystem != EFI_IMAGE_BS_DRIVER) &&
+ (RomHeader->EfiSubsystem != EFI_IMAGE_RT_DRIVER))
+ return EFI_NOT_FOUND;
+
+ // decompress it if needed
+ if (RomHeader->CompressionType > 1) return EFI_INVALID_PARAMETER;
+
+ //Get the space needed
+ romdata=MallocZ(sizeof(PCI_ROM_IMAGE_DATA));
+ if (romdata==NULL) return EFI_OUT_OF_RESOURCES;
+
+ //Fill RomData Parts
+ romdata->RomHeader=RomHeader;
+ //Init RELATIVE OFFS DP Header...
+ romdata->RomImageDP.Header.Type=MEDIA_DEVICE_PATH;
+ romdata->RomImageDP.Header.SubType=MEDIA_RELATIVE_OFFSET_RANGE_DP;
+ SET_NODE_LENGTH(&romdata->RomImageDP.Header, sizeof(MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH));
+
+ //imgsz=RomHeader->InitializationSize*512-RomHeader->EfiImageOffset;
+ imgsz=(UINT32)DoubleCheckOpRom((VOID*)RomHeader, Pcir);
+ imgsz-=RomHeader->EfiImageOffset;
+
+ //Get Start..End offsets of Rom File...
+ imgb=(VOID*)((UINT8*)RomHeader+RomHeader->EfiImageOffset);
+ romdata->RomImageDP.StartingOffset=(UINT64)((UINTN)imgb-(UINTN)Dev->PciIo.RomImage);
+ romdata->RomImageDP.EndingOffset=romdata->RomImageDP.StartingOffset+imgsz-1;
+
+ Status=ReadEfiRom(Dev, romdata, &imgb, &imgsz);
+ if(EFI_ERROR(Status)) return Status;
+
+ //update Actual File size..
+ romdata->ActualSize=imgsz;
+
+ //Form Rom Image Device Path from Dev->DevicePath + romdata->RomImgDP+DP_END...
+ romdp=DPAddNode((VOID*)Dev->DevicePath, (VOID*)&romdata->RomImageDP);
+ if(romdp==NULL) return EFI_OUT_OF_RESOURCES;
+
+ //load image and start image
+ Status=pBS->LoadImage(FALSE,gPciBusDriverBinding.ImageHandle,romdp,imgb,imgsz,&romdata->RomImgHandle);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status=pBS->StartImage(romdata->RomImgHandle,NULL,NULL);
+ if (EFI_ERROR(Status)) return Status;
+
+ //Add romdata to the EfiRomList...
+ Status=AppendItemLst((T_ITEM_LIST*)&Dev->RomInitCnt, romdata);
+ if(EFI_ERROR(Status)) return Status;
+
+ //update BusOvr Data...
+ if(Dev->BusOvrData.BusOverride.GetDriver==NULL)Dev->BusOvrData.BusOverride.GetDriver=OvrGetDriver;
+
+#if ((defined EFI_SPECIFICATION_VERSION) && (EFI_SPECIFICATION_VERSION >= 0x2001F))
+ //Update LoadFile Data
+ if(Dev->LoadFileData.LoadFile2.LoadFile==NULL)Dev->LoadFileData.LoadFile2.LoadFile=LoadRomFile;
+#endif
+
+ if(romdp!=NULL)pBS->FreePool(romdp);
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckPciRomDevId()
+//
+// Description: PCI Firmware Spec 3.0 defines some reserved field in PCIR
+// Structure as Device List Pointer. This function checks additional Device IDs
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer PCI Devicse Private Data.
+// PCI_DATA_STRUCTURE *PciRomStruct Pointer at PCIR ROM Header
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_UNSUPPORTED When ROM is not compatible with device.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CheckPciRomDevId(PCI_DEV_INFO *Dev, PCI_DATA_STRUCTURE *PciRomStruct){
+ UINT16 *did;
+//--------------------------
+ if(Dev->DevVenId.VenId != PciRomStruct->VendorId) return EFI_NOT_FOUND;
+
+ if(Dev->DevVenId.DevId != PciRomStruct->DeviceId){
+ //Dev->DevVenId.DevId ==0x0000 special case - (Service ROM like PXE, iSCIS boot agent)
+ if(Dev->DevVenId.DevId==0) return EFI_SUCCESS;
+
+ //Check Device List if any...
+ if(PciRomStruct->Reserved0 == 0) return EFI_UNSUPPORTED;
+
+ did=(UINT16*)((UINT8*)PciRomStruct + PciRomStruct->Reserved0);
+
+ while(*did != 0){
+ if(Dev->DevVenId.DevId==*did) return EFI_SUCCESS;
+ did++; // next device list entry
+ }
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ExecuteUefiRom()
+//
+// Description: This function decide to launch or not UEFI compatible
+// Option ROM
+//
+// Input:
+// UINT8 PciClass PCI Class Code Of the Device.
+//
+// Output: BOOLEAN
+// TRUE Launch UEFI Option ROM
+// FALSE NOT Launch UEFI Option ROM
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN ExecuteUefiRom(PCI_DEV_INFO *Dev)
+{
+ EFI_STATUS Status;
+ AMI_OPROM_POLICY_PROTOCOL *AmiOpromPolicyProtocol;
+ static EFI_GUID AmiOpromPolicyProtocolGuid = AMI_OPROM_POLICY_PROTOCOL_GUID;
+
+ Status = pBS->LocateProtocol(&AmiOpromPolicyProtocolGuid, NULL, &AmiOpromPolicyProtocol);
+ if(EFI_ERROR(Status)) //if CSM OptOut is disabled we should always launch UEFI OpROM
+ return TRUE;
+
+ Status = AmiOpromPolicyProtocol->CheckUefiOpromPolicy(AmiOpromPolicyProtocol, Dev->Handle);
+ return (EFI_ERROR(Status)) ? FALSE : TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ActivateOptRom()
+//
+// Description: This function parses Option ROM Image to decide which
+// Image to give control to and updates PciIO->OptioRom and
+// PciIO->OptioRomSize with Correct values.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer PCI Devicse Private Data.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_NOT_FOUND When Device does not have any ROMs.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ActivateOptRom(PCI_DEV_INFO *Dev)
+{
+ UINT8 *cp;
+ UINTN roms=0;
+ UINTN romc;
+ PCI_EFI_OPT_ROM_HEADER *rh;
+ PCI_DATA_STRUCTURE *pcir;
+ BOOLEAN ff=TRUE;//, fnd=FALSE;
+ BOOLEAN efior=FALSE;
+ BOOLEAN notarom=FALSE;
+ UINTN sz=0;
+ INT64 rsz=(INT64)Dev->PciIo.RomSize;
+ EFI_STATUS Status=EFI_SUCCESS;
+ BOOLEAN RomMatch=FALSE;
+//------------------------
+ if (!Dev->PciIo.RomImage) return EFI_NOT_FOUND;
+
+ cp=(UINT8*)Dev->PciIo.RomImage;
+ for(romc=0;;romc++){
+ rsz-=sz;
+ if(rsz<=0)return Status;
+ cp=cp+sz;
+
+ rh=(PCI_EFI_OPT_ROM_HEADER*)cp;
+ //Check if a valid signarture here
+ if(ff){//first time here
+ if(rh->Signature!=PCI_OPT_ROM_SIG){
+ notarom=TRUE;
+ break;
+ }
+ roms=(UINTN)rh;
+ } else {
+ //here is the case when we can not find a valid signature for the next image
+ //withing the Option ROM
+ if(rh->Signature!=PCI_OPT_ROM_SIG){
+ sz=512;
+ continue;
+ }
+ }
+ ff=FALSE;
+
+ //Check if it is EFI Opt ROM
+ if(rh->EfiSignature==PCI_OPT_ROM_EFISIG) efior=TRUE;
+ else efior=FALSE;
+
+ //we got what we were looking for...
+ pcir=(PCI_DATA_STRUCTURE*)(cp+rh->PcirOffset);
+ if(pcir->Signature!=PCI_PCIR_SIG) continue;
+
+ //Here is some more conditions to check.
+ //some ROMs has Different Sizes filled in 0x55AA ROM Header and in PCIR structure.
+ //So check which size is right by looking one
+
+ //PCI Firmware Spec 3.0 defines some reserved field in PCIR Structure as Device List Pointer
+ Status=CheckPciRomDevId(Dev, pcir);
+ if(EFI_ERROR(Status)) {
+ if(Status==EFI_NOT_FOUND){
+ PCI_TRACE((TRACE_PCI," ROM Img #%d Dev.VID!=PCIR.VID ", romc));
+ } else PCI_TRACE((TRACE_PCI," ROM Img #%d Dev.DID!=PCIR.DID ", romc));
+ } else RomMatch=TRUE;
+
+ //Check Setup option which Option ROM to post Legacy = 0 \[EFI Compatible = 1]
+ if( ExecuteUefiRom(Dev) ) {
+ //here we go...let's see what it is
+ //check conditions under which we must process EFI OptROM
+ if( efior && pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE && RomMatch)
+ {
+ PCI_TRACE((TRACE_PCI,"(Install EFI ROM="));
+ Status=InstallEfiOpRom(Dev,rh, pcir);
+ PCI_TRACE((TRACE_PCI,"%r)", Status));
+ }
+ }
+
+ if(pcir->Indicator&0x80) {
+ break;
+ }
+ //else keep circling until we reach the end...
+ sz=DoubleCheckOpRom((VOID*)rh, pcir);
+ }
+
+ if(notarom || !RomMatch){
+ Status=pBS->FreePool(Dev->PciIo.RomImage);
+ Dev->PciIo.RomImage=NULL;
+ Dev->PciIo.RomSize=0;
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InstallPciDevice()
+//
+// Description: This function performs the following operations
+// 1. Register Device with CORE by getting a brand new handle
+// 2. Install PciIo Protocol Interface on This Device
+// 3. Generates EFI_DEVICE_PPATH protocol instance for "Dev"ice
+// 4. Installs DevicePath Protocol on Created Handle
+// 5. If Device has Option ROM copy it to the Memory Buffer
+// 6. If 5 is TRUE and if Opt ROM has EFI compliant Image
+// installs Bus Override protocol.
+//
+// Input:
+// EFI_HANDLE ControllerHandle Device's Controller Handle.
+// PCI_DEV_INFO *Dev Pointer PCI Devicse Private Data.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS InstallPciDevice(EFI_HANDLE ControllerHandle, PCI_DEV_INFO *Dev)
+{
+ EFI_STATUS Status=0;
+ EFI_STATUS OpRomStatus = EFI_NOT_FOUND;
+ BOOLEAN ndp=FALSE;//NewDevicePath
+#if ((defined EFI_SPECIFICATION_VERSION) && (EFI_SPECIFICATION_VERSION >= 0x2001F))
+ VOID *buff[8]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+#else
+ VOID *buff[6]={NULL,NULL,NULL,NULL,NULL,NULL};
+#endif
+ UINTN offs=0;
+ BOOLEAN cr=TRUE;
+//-----------------------------------
+
+ PCI_TRACE((TRACE_PCI,"PciBus: Installing PCI IO for B%X|D%X|F%X; ->->->->\n", Dev->Address.Addr.Bus,
+ Dev->Address.Addr.Device,Dev->Address.Addr.Function));
+
+ //Check if Device Has Been already started
+ if(Dev->Started) {
+ Status=EFI_ALREADY_STARTED;
+ PCI_TRACE((TRACE_PCI," -> Dev.Started=1; -> %r\n",Status));
+ return Status;
+ }
+
+ if(Dev->Type==tPciRootBrg) ndp=FALSE;
+ else ndp=TRUE;
+
+ if(Dev->PciIo.PollMem!=gPciIoInstance.PollMem){
+ pBS->CopyMem(&Dev->PciIo, &gPciIoInstance, sizeof(EFI_PCI_IO_PROTOCOL));
+ } else cr=FALSE;
+ buff[offs]=&gPciIoProtocolGuid;
+ buff[offs+1]=&Dev->PciIo;
+ offs+=2;
+
+ //Install Device Path Protocol on newly created Handle
+ if(ndp){
+ buff[offs]=&gDevicePathProtocolGuid;
+ buff[offs+1]=Dev->DevicePath;
+ offs+=2;
+ }
+ //Check if Device has Opton ROM ...
+ if(cr)
+ OpRomStatus=GetOptRom(Dev);
+ else if(Dev->PciIo.RomImage != NULL && Dev->PciIo.RomSize != 0) //OpROM was initialized earlier
+ OpRomStatus = EFI_SUCCESS;
+
+ Status=pBS->InstallMultipleProtocolInterfaces(
+ &Dev->Handle,
+ buff[0],buff[1], //PciIO GUID - I/F pare
+ buff[2],buff[3], //DevPath GUID - I/F pare
+ NULL, NULL );
+ PCI_TRACE((TRACE_PCI,"/nPciBus: Installing DP; PCIO Status=%r",Status));
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //update offset it might be ==2 if ndp==FALSE, but we need it as 4 after this point.
+ offs=4;
+
+ PCI_TRACE((TRACE_PCI,":GetRom="));
+
+ if(EFI_ERROR(OpRomStatus)){
+ Dev->RomBarError=TRUE;
+ Dev->PciIo.RomImage=NULL;
+ Dev->PciIo.RomSize=0;
+ PCI_TRACE((TRACE_PCI,"%r\n", OpRomStatus));
+ } else {
+ //Print Status from GetOptRom()
+ PCI_TRACE((TRACE_PCI,"%r :ActivateRom", OpRomStatus));
+ if(cr) Status=ActivateOptRom(Dev);
+ PCI_TRACE((TRACE_PCI,"=%r\n", Status));
+ if(EFI_ERROR(Status)){
+ if(Status==EFI_NOT_FOUND) Status=EFI_SUCCESS; //just there are no any EFI Opt ROMs
+ else return Status;
+ }
+
+ //Check if Override handle count gets changed..
+ //then install Bus Override protocol interface
+ if(Dev->BusOvrData.BusOverride.GetDriver!=NULL){
+ buff[offs]=&gBusSpecificDriverOverrideProtocolGuid;
+ buff[offs+1]=&Dev->BusOvrData.BusOverride;
+ }
+
+#if ((defined EFI_SPECIFICATION_VERSION) && (EFI_SPECIFICATION_VERSION >= 0x2001F))
+ offs+=2;
+ if(Dev->LoadFileData.LoadFile2.LoadFile!=NULL){
+ buff[offs]=&gEfiLoadFile2ProtocolGuid;
+ buff[offs+1]=&Dev->LoadFileData.LoadFile2;
+ }
+#endif
+
+ }
+
+
+ //Now Before installing Protocol Interface for THIS device.
+ //Call Porting Hook to do OEM Custom Programming of the device.
+ //PciIo and all the stuff been updated for this device.
+ //But NO notification yet for PciIO installation dispatchetd
+ Status=PciPortOemProgDevice(Dev);
+
+ PCI_TRACE((TRACE_PCI,":PciBus: Calling PciPortOemProgDevice() >Status=%r\n", Status));
+
+ if(buff[5]!=NULL){
+ Status=pBS->InstallMultipleProtocolInterfaces(
+ &Dev->Handle,
+ buff[4],buff[5], //PciIO GUID - I/F pare
+#if ((defined EFI_SPECIFICATION_VERSION) && (EFI_SPECIFICATION_VERSION >= 0x2001F))
+ buff[6],buff[7], //LoadFile2 GUID - I/F pare if present
+#endif
+ NULL, NULL );
+
+ PCI_TRACE((TRACE_PCI," -> Installing BusOvr and LoadFile2 -> %r\n", Status));
+
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ if(Dev->Type>tPciRootBrg){//Don't Open Rb Protocol for itself
+ Status=pBS->OpenProtocol(
+ ControllerHandle, &gPciRootBridgeIoProtocolGuid,
+ (VOID**)&Dev->RbIo, gPciBusDriverBinding.DriverBindingHandle,
+ Dev->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+ }
+
+ //Set Started Flag...
+ Dev->Started=TRUE;
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StartPciChildDevice()
+//
+// Description: Starts PCI Devices Behind the Bridge. (Called recoursively)
+// This function performs the following operations
+// 1. Register Device with CORE by getting a brand new handle
+// 2. Install PciIo Protocol Interface on This Device
+// 3. Generates EFI_DEVICE_PPATH protocol instance for "Dev"ice
+// 4. Installs DevicePath Protocol on Created Handle
+// 5. If Device has Option ROM copy it to the Memory Buffer
+// 6. If 5 is TRUE and if Opt ROM has EFI compliant Image
+// installs Bus Override protocol.
+//
+// Input:
+// EFI_HANDLE ControllerHandle Device's Controller Handle.
+// PCI_BRG_INFO *Brg Pointer at PCI Bridge Private Data.
+// EFI_DEVICE_PATH_PROTOCOL *RemainingDp Pointer at PCI Device Path
+// Protocol Instance or NULL.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS StartPciChildDevice(EFI_HANDLE ControllerHandle,PCI_BRG_INFO *Brg, PCI_DEVICE_PATH *RemainingDp)
+{
+ PCI_DEV_INFO *dev;
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ UINTN i;
+ PCI_DEVICE_PATH *pcidp=RemainingDp;
+ BOOLEAN Started=FALSE, Success=FALSE;
+//-------------------------------
+
+ PCI_TRACE((TRACE_PCI, "PciBus: StartPciChildDevice -> Bridge has %d Child Devices \n",Brg->Bridge.ChildCount));
+
+ //Check if Device Path is a valid PCI Device Path
+ if (pcidp!=NULL){
+ //Check if remaining device path is a valid PCI device path
+ if( EFI_ERROR(CheckPciDevicePath(&pcidp->Header)) ) return EFI_INVALID_PARAMETER;
+ //If remaining device path is provided, we must find the device.
+ }
+
+ if(!Brg->Bridge.ChildCount) return Status;
+
+ for(i=0; i<Brg->Bridge.ChildCount; i++){
+ dev=Brg->Bridge.ChildList[i];
+ if(dev->OutOfResRemove) continue;
+ //if Remaining Device Path provided start only specified device
+ if(pcidp)
+ {
+ if(pcidp->Device != dev->Address.Addr.Device ||
+ pcidp->Function != dev->Address.Addr.Function
+ ) continue;
+ // The Device Path of this Device matches provided
+ Status=InstallPciDevice(ControllerHandle, dev);
+ if (EFI_ERROR(Status)){
+ if(Status==EFI_ALREADY_STARTED) Started=TRUE;
+ else return Status;
+ } else Success=TRUE;
+
+ //if Device is P2P bridge than BDS might like to start next DP node
+ //So recousively call this function to find desired Device
+ pcidp++;
+ if(dev->Type==tPci2PciBrg && !isEndNode(&pcidp->Header))
+ Status=StartPciChildDevice(ControllerHandle,(PCI_BRG_INFO*)dev,pcidp);
+
+
+ //if(!EFI_ERROR(Status) && Status == EFI_NOT_FOUND){
+ // if(Started && !Success) Status=EFI_ALREADY_STARTED;
+ //}
+ return Status;
+ }
+ else //if no Remaining Device Path provided start all devices
+ {
+ Status=InstallPciDevice(ControllerHandle, dev);
+ if (EFI_ERROR(Status)){
+ if(Status==EFI_ALREADY_STARTED){
+ Started=TRUE;
+ Status=EFI_SUCCESS;
+ } else return Status;
+ } else Success=TRUE;
+
+ //if Device is P2P bridge recousively call this function
+ if(dev->Type==tPci2PciBrg){
+ Status=StartPciChildDevice(ControllerHandle,(PCI_BRG_INFO*)dev,pcidp);
+ if(EFI_ERROR(Status)){
+ //StartPciChildDevice() could return EFI_ALREADY_STARTED or EFI_NOT_FOUND
+ //this is if we have started this device already, of Bridge don't have any
+ //childs behind it. This is normal and we shouldn't break the loop.
+ //All other ERROR Statuses suppose to break the loop and raise an ERROR.
+ if(Status==EFI_ALREADY_STARTED || Status==EFI_NOT_FOUND){
+ Started=TRUE;
+ Status=EFI_SUCCESS;
+ } else return Status;
+ } else Success=TRUE;
+ }
+ }
+ }//for
+
+ if(!EFI_ERROR(Status)){
+ if(Started && !Success) Status=EFI_ALREADY_STARTED;
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StartPciDevices()
+//
+// Description: Installs PCI Io Protocol Instance on all or some PCI Devices
+// in the System
+//
+// Input:
+// EFI_HANDLE ControllerHandle Device's Controller Handle.
+// EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath Pointer at PCI Device Path
+// Protocol Instance or NULL.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS StartPciDevices(IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINTN i, j;
+ PCI_DEV_INFO *rbrg;
+ PCI_HOST_INFO *lhst; //local host
+ EFI_DEVICE_PATH_PROTOCOL *rdp=RemainingDevicePath;
+//---------------------------------------------
+ PCI_TRACE((TRACE_PCI, "\n====================================================================\n"));
+ PCI_TRACE((TRACE_PCI, "PciBus: StartPciDevices Called -> hCtrl=0x%X; RemainingDp=0x%X;\n",ControllerHandle,RemainingDevicePath));
+
+ //Check if RemainingDevicePath is valid
+ if(rdp!=NULL){
+
+ if (isEndNode(rdp)) {
+ PCI_TRACE((TRACE_PCI, "PciBus: RemainingDp==EndOfDpNode\n"));
+ return EFI_SUCCESS;
+ } else {
+ Status=CheckPciDevicePath(rdp);
+ PCI_TRACE((TRACE_PCI, "PciBus: START CheckPciDp -> %r\n",Status));
+ if(EFI_ERROR(Status)) goto ExitLbl;
+ }
+ }
+
+ //find Root Bridge first
+ for(j=0; j<gHostCnt; j++){
+ lhst=&gPciHost[j];
+ for(i=0; i<lhst->RbCount; i++){
+ rbrg=lhst->RootBridges[i];
+
+ if(rbrg->Handle==ControllerHandle){
+
+ Status=pBS->OpenProtocol(rbrg->Handle,
+ &gPciRootBridgeIoProtocolGuid,(VOID **)&rbrg->RbIo,
+ gPciBusDriverBinding.DriverBindingHandle,rbrg->Handle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if(EFI_ERROR(Status)){
+ if( Status!=EFI_ALREADY_STARTED ) return Status;
+ else Status=EFI_SUCCESS;
+ }
+
+ Status=StartPciChildDevice(ControllerHandle,(PCI_BRG_INFO*)rbrg,(PCI_DEVICE_PATH*)rdp);
+ break;
+ }
+ }
+ }
+ExitLbl:
+
+ PCI_TRACE((TRACE_PCI, "PciBus: StartPciChildDevice -> %r\n",Status));
+ PCI_TRACE((TRACE_PCI, "====================================================================\n"));
+
+ return Status;
+}
+
+EFI_STATUS LocateDevHandle(PCI_DEV_INFO *Dev, T_ITEM_LIST *PciHnd){
+ UINTN i;
+ EFI_HANDLE h;
+//------------------------
+ for(i=0; i<PciHnd->ItemCount; i++){
+ h=*(EFI_HANDLE*)(PciHnd->Items[i]);
+ if(Dev->Handle==h){
+ DeleteItemLst(PciHnd, i, FALSE);
+ Dev->Handle=NULL;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StopPciDevice()
+//
+// Description: Stops PCI Device referenced as "Dev". Called From
+// StopPciDeviceBrg() function.
+//
+// Input:
+// PCI_DEV_INFO *Dev Pointer PCI Devicse Private Data.
+// EFI_HANDLE Controller Device's Controller Handle.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS StopPciDevice(PCI_DEV_INFO *Dev,EFI_HANDLE Controller, T_ITEM_LIST *HndDb)
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ UINTN offs=0;
+ BOOLEAN ndp;
+#if ((defined EFI_SPECIFICATION_VERSION) && (EFI_SPECIFICATION_VERSION >= 0x2001F))
+ VOID *buff[8]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+#else
+ VOID *buff[6]={NULL,NULL,NULL,NULL,NULL,NULL};
+#endif
+//--------------------------------------------------------------------
+
+ //Check if Device Has been Stopped already...
+ if(Dev->Started==FALSE) return EFI_SUCCESS;
+
+ if(Dev->Type==tPciRootBrg) {
+ Dev->Started=FALSE;
+ return EFI_SUCCESS;
+ }
+
+ PCI_TRACE((TRACE_PCI,"\nPciBusStop: Hnd=%X [B%X|D%X|F%X]->",Dev->Handle,
+ Dev->Address.Addr.Bus,Dev->Address.Addr.Device, Dev->Address.Addr.Function));
+ //Close Root Brg Protocol we've opened at the beginning.
+ //Avoid Closing Protocol for RootBridge Device - we didn't open it.
+ if(Dev->Handle!=Controller){
+ Status=pBS->CloseProtocol(Controller,&gPciRootBridgeIoProtocolGuid,
+ gPciBusDriverBinding.DriverBindingHandle, Dev->Handle);
+ ndp=TRUE;
+ PCI_TRACE((TRACE_PCI,"Close(RbIo)=%r;\n",Status));
+ } else {
+ ndp=FALSE;
+ }
+
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ buff[offs]=&gPciIoProtocolGuid;
+ buff[offs+1]=&Dev->PciIo;
+ offs+=2;
+
+ //Same for Device Path: we did'not create device path for RootBridge device
+ if(ndp){
+ buff[offs]=&gDevicePathProtocolGuid;
+ buff[offs+1]=Dev->DevicePath;
+ offs+=2;
+ }
+
+ //Now take care of BusSpecific Override Protocol
+ //If it was installed
+ if(Dev->BusOvrData.BusOverride.GetDriver!=NULL){
+ buff[offs]=&gBusSpecificDriverOverrideProtocolGuid;
+ buff[offs+1]=&Dev->BusOvrData.BusOverride;
+ }
+
+#if ((defined EFI_SPECIFICATION_VERSION) && (EFI_SPECIFICATION_VERSION >= 0x2001F))
+ //LoadFile2 Protocol
+ offs+=2;
+ if(Dev->LoadFileData.LoadFile2.LoadFile!=NULL){
+ buff[offs]=&gEfiLoadFile2ProtocolGuid;
+ buff[offs+1]=&Dev->LoadFileData.LoadFile2;
+ }
+#endif
+ Status=pBS->UninstallMultipleProtocolInterfaces(
+ Dev->Handle,
+ buff[0],buff[1], //PciIO GUID - I/F pare
+ buff[2],buff[3], //DevPath GUID - I/F pare
+ buff[4],buff[5], //BusOwerride GUID - I/F pare if present
+#if ((defined EFI_SPECIFICATION_VERSION) && (EFI_SPECIFICATION_VERSION >= 0x2001F))
+ buff[6],buff[7], //LoadFile2 GUID - I/F pare if present
+#endif
+ NULL, NULL );
+
+ PCI_TRACE((TRACE_PCI,"\nPciBusStop: Hnd=%X [B%X|D%X|F%X]->",Dev->Handle,
+ Dev->Address.Addr.Bus,Dev->Address.Addr.Device, Dev->Address.Addr.Function));
+ PCI_TRACE((TRACE_PCI,"Uninst(PciIo,DP,BusOvr)=%r;\n",Status));
+//DEBUG????
+ if(!EFI_ERROR(Status)){
+//DEBUG????
+ Dev->Started=FALSE;
+ if(HndDb!=NULL) Status=LocateDevHandle(Dev, HndDb);
+ Dev->Handle=NULL;
+//DEBUG????
+ }
+//DEBUG????
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StopPciDeviceBrg()
+//
+// Description: Stops - Uninstalls PCI Io Protocol Instance from PCI Devices
+// behind the PCI Bridge referenced as "Brg"
+//
+// Input:
+// PCI_BRG_INFO *Brg Pointer PCI Devicse Private Data.
+// EFI_HANDLE Controller Device's Controller (Parent) Handle.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_OUT_OF_RESOURCES When system runs out of resources.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS StopPciDeviceBrg(PCI_BRG_INFO *Brg, EFI_HANDLE Controller, T_ITEM_LIST *HndDb)
+{
+ PCI_DEV_INFO *dev;
+ UINTN i;
+ EFI_STATUS Status;
+//--------------------------------------------------------------------
+ for(i=0; i<Brg->Bridge.ChildCount; i++){
+ dev=Brg->Bridge.ChildList[i];
+ //recoursive calling ourselfs
+ if(dev->Type==tPci2PciBrg) Status=StopPciDeviceBrg((PCI_BRG_INFO*)dev,Controller, HndDb);
+ else Status=StopPciDevice(dev, Controller, HndDb);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ //After we done with the childs - Stop this Bridge itself
+ Status=StopPciDevice(&Brg->Common, Controller, HndDb);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+
+//==============================================================================
+//
+// EFI Drver Binding Protocol Functions
+//
+//==============================================================================
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciBusSupported()
+//
+// Description: Supported Function of the EFI_DRIVER_BINDING_PROTOCOL
+// for PCI Bus Driver.
+//
+// Notes:
+// See EFI Specification for detail description
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciBusSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ EFI_DEVICE_PATH_PROTOCOL *rdp=RemainingDevicePath;
+//-----------------------------------------------
+
+
+ //Check if it is valid Device Path
+ if (rdp != NULL){
+ if (isEndNode(rdp)) rdp=NULL;
+ else {
+ Status=CheckPciDevicePath(rdp);
+ if (EFI_ERROR (Status)) return Status;
+ }
+ }
+
+ //Open the IO Abstraction(s) needed to perform the supported test
+ Status=pBS->OpenProtocol(Controller,
+ &gDevicePathProtocolGuid,
+ (VOID **)&ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if (Status == EFI_ALREADY_STARTED)return EFI_SUCCESS;
+ if (EFI_ERROR (Status)) return Status;
+
+ pBS->CloseProtocol(Controller,&gDevicePathProtocolGuid,This->DriverBindingHandle,
+ Controller);
+
+ Status=pBS->OpenProtocol( Controller,
+ &gPciRootBridgeIoProtocolGuid,
+ (VOID **)&PciRootBridgeIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if(Status==EFI_ALREADY_STARTED) return EFI_SUCCESS;
+
+ pBS->CloseProtocol(Controller,&gPciRootBridgeIoProtocolGuid,This->DriverBindingHandle,
+ Controller);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciBusStart()
+//
+// Description: Start Function of the EFI_DRIVER_BINDING_PROTOCOL
+// for PCI Bus Driver
+//
+// Notes:
+// See EFI Specification for detail description
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciBusStart(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath )
+{
+ EFI_STATUS Status;
+ BOOLEAN ft=FALSE;
+//------------------------------------------------
+ PROGRESS_CODE(DXE_PCI_BUS_BEGIN);
+
+ PCI_TRACE((TRACE_PCI,"\n"));
+
+ //Locate Boot Script protocol we will need it to record Extd PCIExpress Config Space Programing
+ if(gBootScriptSave==NULL){
+ Status = pBS->LocateProtocol(&gEfiBootScriptSaveGuid, NULL, &gBootScriptSave);
+ if(EFI_ERROR(Status)) {
+ PCI_TRACE((TRACE_PCI,"PciBus: Unable to find EfiBootScriptSave Protocol! Status=%r EXITING!\n", Status));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+#if CSM_SUPPORT
+ //Locate Legacy BIOS Extended protocol, we will need it to record Extd PCIExpress Config Space Programing
+ if(gLegacyBiosExt==NULL){
+ Status = pBS->LocateProtocol(&gEfiLegacyBiosExtProtocolGuid, NULL, &gLegacyBiosExt);
+ if(EFI_ERROR(Status)) {
+ PCI_TRACE((TRACE_PCI,"PciBus: Unable to find Legacy Bios Extension Protocol! Status=%r\n", Status));
+ gLegacyBiosExt=NULL;
+ }
+ }
+#endif
+
+ //Locate Ami Board Info Protocol
+ if(gAmiBoardInfo==NULL){
+ Status = pBS->LocateProtocol(&gAmiBoardInfoProtocolGuid, NULL, &gAmiBoardInfo);
+ if(EFI_ERROR(Status)) {
+ PCI_TRACE((TRACE_PCI,"PciBus: Unable to find AMI Board Info Protocol! Status=%r\n", Status));
+ return Status;
+ }
+ ft=TRUE;
+ }
+
+ //Create Pci Setup Data Buffer;
+ if(gPciSetupData==NULL){
+ gPciSetupData=MallocZ(sizeof(PCI_SETUP_DATA));
+ if (gPciSetupData==NULL) return EFI_OUT_OF_RESOURCES;
+ //Call Board Specific function from PciPort.c to fill PCI Setup data buffer
+ BrdGetPciSetupData(gPciSetupData);
+ }
+
+ // Enumerate the entire host bridge
+ Status = EnumerateAll(Controller);
+ if(ft){
+#if EFI_DEBUG
+ //Print Bus Xlat table
+ UINTN i;
+ PCI_IRQ_PIC_ROUTE *ir;
+ PCI_IRQ_APIC_ROUTE *ar;
+ //-----------
+ PCI_TRACE((TRACE_PCI,"PciBus: Printing PIC $PIR table, %d entries \n", gAmiBoardInfo->PicRoutLength/sizeof(PCI_IRQ_PIC_ROUTE) ));
+ PCI_TRACE((TRACE_PCI,"============================================================\n"));
+ PCI_TRACE((TRACE_PCI," # Bus D|F PIRQ A PIRQ B PIRQ C PIRQ D Slt#\n"));
+ PCI_TRACE((TRACE_PCI,"------------------------------------------------------------\n"));
+ for(i=0; i<(gAmiBoardInfo->PicRoutLength/sizeof(PCI_IRQ_PIC_ROUTE));i++){
+ ir=&gAmiBoardInfo->PicRoutTable[i];
+ PCI_TRACE((TRACE_PCI,"%02d %02X %02X|%X %02X->%04X %02X->%04X %02X->%04X %02X->%04X %02X\n", i,
+ ir->PciBusNumber, ir->DevFun.Dev,ir->DevFun.Fun,
+ ir->PciIrq[0].ChipsetReg, ir->PciIrq[0].IrqMask,
+ ir->PciIrq[1].ChipsetReg, ir->PciIrq[1].IrqMask,
+ ir->PciIrq[2].ChipsetReg, ir->PciIrq[2].IrqMask,
+ ir->PciIrq[3].ChipsetReg, ir->PciIrq[3].IrqMask,
+ ir->SlotNum));
+ }
+ PCI_TRACE((TRACE_PCI,"============================================================\n"));
+ PCI_TRACE((TRACE_PCI,"\nPciBus: Printing APIC table, %d entries \n", gAmiBoardInfo->ApicRoutLength/sizeof(PCI_IRQ_APIC_ROUTE) ));
+ PCI_TRACE((TRACE_PCI,"============================================================\n"));
+ PCI_TRACE((TRACE_PCI," # Bus Dev PIRQ A PIRQ B PIRQ C PIRQ D\n"));
+ PCI_TRACE((TRACE_PCI,"------------------------------------------------------------\n"));
+ for(i=0; i<(gAmiBoardInfo->ApicRoutLength/sizeof(PCI_IRQ_APIC_ROUTE));i++){
+ ar=&gAmiBoardInfo->ApicRoutTable[i];
+ PCI_TRACE((TRACE_PCI,"%02d %02X %02X %02X ID=%02X %02X ID=%02X %02X ID=%02X %02X ID=%02X\n", i,
+ ar->PciBusNumber, ar->DeviceNumber,
+ ar->Intn[0].IoApicItin, ar->Intn[0].IoApicId,
+ ar->Intn[1].IoApicItin, ar->Intn[1].IoApicId,
+ ar->Intn[2].IoApicItin, ar->Intn[2].IoApicId,
+ ar->Intn[3].IoApicItin, ar->Intn[3].IoApicId));
+ }
+ PCI_TRACE((TRACE_PCI,"============================================================\n"));
+
+#endif
+ RemoveUnusedIrqEntries();
+ gAmiBoardInfo->DataValid=TRUE;
+ }
+
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR (Status)) return Status;
+
+ //If Enumeration is OK install Extended PCI BUS Protocol Interface NOW.
+ //Only if we have not done it before. It is only single instance on PciBusExt possible.
+ if(gAmiExtPciBusProtocol.PciExtHanle==NULL){
+ Status=pBS->InstallMultipleProtocolInterfaces( &gAmiExtPciBusProtocol.PciExtHanle,
+ &gAmiExtPciBusProtocolGuid, &gAmiExtPciBusProtocol, NULL);
+ }
+
+ if (EFI_ERROR (Status)){
+ PCI_TRACE((TRACE_PCI,"PciBus: Unable to INSTALL Extended PCI Bus Protocol! Status=%r\n", Status));
+ }
+ ASSERT_EFI_ERROR(Status);
+
+ // Enable PCI device specified by remaining device path. BDS or other driver can call the
+ // start more than once.
+ Status=StartPciDevices (Controller, RemainingDevicePath);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciBusStop()
+//
+// Description: Stop Function of the EFI_DRIVER_BINDING_PROTOCOL
+// for PCI Bus Driver.
+//
+// Notes:
+// See EFI Specification for detail description
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciBusStop(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer)
+{
+ EFI_STATUS Status=0;
+ PCI_DEV_INFO *dev=NULL;
+ UINTN i;
+ T_ITEM_LIST PciHndDb={0,0,NULL};
+ EFI_HANDLE hnd;
+//------------------------------------------------
+ PCI_TRACE((TRACE_PCI,"\nPciBusStop: NumberOfChildren=0x%X, Controller=0x%X\n",NumberOfChildren, Controller));
+
+ if (NumberOfChildren == 0) {
+ // Close the bus driver
+ //mST->BootServices->CloseProtocol(Controller,&gDevicePathProtocolGuid,
+ // This->DriverBindingHandle, Controller);
+ dev=FindPciDeviceByHandle(Controller);
+ if(dev) Status=StopPciDeviceBrg((PCI_BRG_INFO*)dev, Controller, NULL);
+ else Status=EFI_NOT_FOUND;
+ ASSERT_EFI_ERROR(Status);
+ //Close PCI Rooty Bridge Protocol we opened BY_DRIVER
+ pBS->CloseProtocol(Controller,&gPciRootBridgeIoProtocolGuid,
+ This->DriverBindingHandle,Controller);
+ } else {
+ //Populate PciHandle Database we need to stop. If we will enter recoursive
+ //call we need to rtemove stopped handles from DB inside recoursive call
+ //to avoid getting EFI_INVALID_PARAMETER trying to Stop already stopped devices.
+ for(i=0; i<NumberOfChildren; i++){
+ AppendItemLst(&PciHndDb, &ChildHandleBuffer[i]);
+ PCI_TRACE((TRACE_PCI,"Hnd #%X: %X \n", i, ChildHandleBuffer[i]));
+ }
+
+ //Stopping all the childs
+ while(PciHndDb.ItemCount){
+ hnd=*(EFI_HANDLE*)(PciHndDb.Items[0]);
+ dev=FindPciDeviceByHandle(hnd);
+ if(dev){
+ //If device a bridge stop all its childs first
+ if(dev->Type==tPci2PciBrg)Status=StopPciDeviceBrg((PCI_BRG_INFO*)dev,Controller, &PciHndDb);
+ else Status=StopPciDevice(dev,Controller,&PciHndDb);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status))return Status;
+ } else {
+ Status=EFI_NOT_FOUND;
+ break;
+ }
+ ASSERT_EFI_ERROR(Status);
+ }//while...
+ }
+
+ if(gAmiExtPciBusProtocol.PciExtHanle!=NULL){
+ Status=pBS->UninstallMultipleProtocolInterfaces( gAmiExtPciBusProtocol.PciExtHanle,
+ &gAmiExtPciBusProtocolGuid, &gAmiExtPciBusProtocol, NULL);
+ if (!EFI_ERROR(Status)) {
+ gAmiExtPciBusProtocol.PciExtHanle=NULL;
+ }
+ }
+
+ //Cleanup used memory...
+ ClearItemLst(&PciHndDb, FALSE);
+ return Status;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//----------------------------------------------------------------------------
+// PCI BUS Extended Protocol Function Implementation
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciExtGetDevice()
+//
+// Description: Locates PCI_DEV_INFO using passed PCI Device Handle or PciIo
+// Protocol pointer.
+// Input:
+// EFI_HANDLE PciDeviceHandle Handle of the PCI Device to check.
+// EFI_PCI_IO_PROTOCOL* PciIo Pointer to the instance of PCI IO Protocol (OPTIONAL)
+//
+// Output:
+// PCI_DEV_INFO* When everything is going on fine!
+// NULL If no such device exists.
+//
+// Note:
+// If PciDeviceHandle == NULL, PciIo must be valid.
+// If *PciIo == NULL PciDeviceHandle must be valid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+PCI_DEV_INFO* PciExtGetDevice(EFI_HANDLE PciDeviceHandle, EFI_PCI_IO_PROTOCOL *PciIo){
+ PCI_DEV_INFO *dev=NULL;
+//------------------------------------
+ if(PciDeviceHandle == NULL){
+ if(PciIo!=NULL){
+ dev=(PCI_DEV_INFO*)PciIo;
+ if(dev->Signature != AMI_PCI_SIG) return NULL;
+ } else return NULL;
+ } else dev=FindPciDeviceByHandle(PciDeviceHandle);
+
+ return dev;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciExtIsPciExpresss()
+//
+// Description: Checks if PciDeviceHandle, or PciIO passed belongs to
+// PCI Express device.
+// Input:
+// AMI_PCI_EXT_PROTOCOL* This Pointer to the PciBusExtended protocol.
+// EFI_HANDLE PciDeviceHandle Handle of the PCI Device to check.
+// EFI_PCI_IO_PROTOCOL* PciIo Pointer to the instance of PCI IO Protocol (OPTIONAL)
+// PCIE_DATA** PciExpData Double Pointer to the PCIE_DATA Structure (OPTIONAL)
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND If Device is not PCI Express device.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+// Note:
+// If PciDeviceHandle == NULL, PciIo must be valid.
+// If *PciIo == NULL PciDeviceHandle must be valid.
+// **PciExpData if not needed must be NULL;
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciExtIsPciExpresss(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCIE_DATA **PciExpData OPTIONAL
+)
+{
+ PCI_DEV_INFO *dev=NULL;
+//------------------------------------
+ dev=PciExtGetDevice(PciDeviceHandle, PciIo);
+
+ if(dev) {
+ if(dev->PciExpress != NULL){
+ //if we have to update pointer
+ if(PciExpData != NULL){
+ *PciExpData = dev->PciExpress;
+ }
+ return EFI_SUCCESS;
+ } else return EFI_NOT_FOUND;
+ } else return EFI_INVALID_PARAMETER;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciExtIsPciX()
+//
+// Description: Checks if PciDeviceHandle, or PciIO passed belongs to
+// PCI Express device.
+// Input:
+// AMI_PCI_EXT_PROTOCOL* This Pointer to the PciBusExtended protocol.
+// EFI_HANDLE PciDeviceHandle Handle of the PCI Device to check.
+// EFI_PCI_IO_PROTOCOL* PciIo Pointer to the instance of PCI IO Protocol (OPTIONAL)
+// PCIX_DATA** PciXData Double Pointer to the PCIX_DATA Structure (OPTIONAL)
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND If Device is not PCI X device.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+// Note:
+// If PciDeviceHandle == NULL, PciIo must be valid.
+// If *PciIo == NULL PciDeviceHandle must be valid.
+// **PciXData if not needed must be NULL;
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciExtIsPciX(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCIX_DATA **PciXData OPTIONAL
+)
+{
+ PCI_DEV_INFO *dev=NULL;
+//------------------------------------
+ dev=PciExtGetDevice(PciDeviceHandle, PciIo);
+
+ if(dev) {
+ if(dev->PciX != NULL){
+ //if we have to update pointer
+ if(PciXData != NULL){
+ *PciXData = dev->PciX;
+ }
+ return EFI_SUCCESS;
+ } else return EFI_NOT_FOUND;
+ } else return EFI_INVALID_PARAMETER;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciExtIsPciBrg()
+//
+// Description: Checks if PciDeviceHandle, or PciIO passed belongs to
+// PCI 2 PCI Bridge device.
+// Input:
+// AMI_PCI_EXT_PROTOCOL* This Pointer to the PciBusExtended protocol.
+// EFI_HANDLE PciDeviceHandle Handle of the PCI Device to check.
+// EFI_PCI_IO_PROTOCOL* PciIo Pointer to the instance of PCI IO Protocol (OPTIONAL)
+// PCI_BRG_EXT** PciBrgExt Double Pointer to the PCI_BRG_EXT Structure (OPTIONAL)
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND If Device is not PCI 2 PCI Bridge device.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+// Note:
+// If PciDeviceHandle == NULL, PciIo must be valid.
+// If *PciIo == NULL PciDeviceHandle must be valid.
+// **PciBrgExt if not needed must be NULL;
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciExtIsPciBrg(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_BRG_EXT **BrgData OPTIONAL
+)
+{
+ PCI_DEV_INFO *dev=NULL;
+//------------------------------------
+ dev=PciExtGetDevice(PciDeviceHandle, PciIo);
+
+ if(dev) {
+ if(dev->Type == tPci2PciBrg){
+ //if we have to update pointer
+ if(BrgData != NULL){
+ *BrgData = (PCI_BRG_EXT*)(dev+1);
+ }
+ return EFI_SUCCESS;
+ } else return EFI_NOT_FOUND;
+ } else return EFI_INVALID_PARAMETER;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciExtIsCrdBrg()
+//
+// Description: Checks if PciDeviceHandle, or PciIO passed belongs to
+// PCI 2 Card Bridge device.
+// Input:
+// AMI_PCI_EXT_PROTOCOL* This Pointer to the PciBusExtended protocol.
+// EFI_HANDLE PciDeviceHandle Handle of the PCI Device to check.
+// EFI_PCI_IO_PROTOCOL* PciIo Pointer to the instance of PCI IO Protocol (OPTIONAL)
+// PCI_BRG_EXT** PciBrgExt Double Pointer to the PCI_BRG_EXT Structure (OPTIONAL)
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND If Device is not PCI 2 Card Bridge device.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+// Note:
+// If PciDeviceHandle == NULL, PciIo must be valid.
+// If *PciIo == NULL PciDeviceHandle must be valid.
+// **PciBrgExt if not needed must be NULL;
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciExtIsCrdBrg(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_BRG_EXT **BrgData OPTIONAL
+)
+{
+ PCI_DEV_INFO *dev=NULL;
+//------------------------------------
+ dev=PciExtGetDevice(PciDeviceHandle, PciIo);
+
+ if(dev) {
+ if(dev->Type == tPci2CrdBrg){
+ //if we have to update pointer
+ if(BrgData != NULL){
+ *BrgData = (PCI_BRG_EXT*)(dev+1);
+ }
+ return EFI_SUCCESS;
+ } else return EFI_NOT_FOUND;
+ } else return EFI_INVALID_PARAMETER;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciExtIsDevice()
+//
+// Description: Checks if PciDeviceHandle, or PciIO passed belongs to
+// Regular PCI device.
+// Input:
+// AMI_PCI_EXT_PROTOCOL* This Pointer to the PciBusExtended protocol.
+// EFI_HANDLE PciDeviceHandle Handle of the PCI Device to check.
+// EFI_PCI_IO_PROTOCOL* PciIo Pointer to the instance of PCI IO Protocol (OPTIONAL)
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND If Device is not Regular PCI device.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+// Note:
+// If PciDeviceHandle == NULL, PciIo must be valid.
+// If *PciIo == NULL PciDeviceHandle must be valid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciExtIsDevice(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL
+)
+{
+ PCI_DEV_INFO *dev=NULL;
+//------------------------------------
+ dev=PciExtGetDevice(PciDeviceHandle, PciIo);
+
+ if(dev){
+ if(dev->Type == tPciDevice) return EFI_SUCCESS;
+ else return EFI_NOT_FOUND;
+ } else return EFI_INVALID_PARAMETER;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciExtClassCodes()
+//
+// Description: Returns device's Class code; Sub Class code; Programing Interface
+// and Revision Id information.
+//
+// Input:
+// AMI_PCI_EXT_PROTOCOL* This Pointer to the PciBusExtended protocol.
+// EFI_HANDLE PciDeviceHandle Handle of the PCI Device to check.
+// EFI_PCI_IO_PROTOCOL* PciIo Pointer to the instance of PCI IO Protocol (OPTIONAL)
+// PCI_DEV_CLASS* CassCodes Pointer to the PCI_DEV_CLASS to fill.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+// Note:
+// If PciDeviceHandle == NULL, PciIo must be valid.
+// If *PciIo == NULL PciDeviceHandle must be valid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciExtClassCodes(
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_DEV_CLASS *CassCodes
+)
+{
+ PCI_DEV_INFO *dev=NULL;
+//------------------------------------
+ dev=PciExtGetDevice(PciDeviceHandle, PciIo);
+
+ if(dev){
+ *CassCodes=dev->Class;
+ return EFI_SUCCESS;
+ } else return EFI_INVALID_PARAMETER;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciExtPicIrqRout()
+//
+// Description: Returns device's corresponded PIC IRQ routing entry from OEMPIR.INC
+// table created by the BUILD process.
+// If function returns EFI_SUCCESS the "PicIrqTblEntry" updated with corresponded PIC
+// IRQ Table entry pointer. "ParentDevices" == NULL and "EntryCount"==0
+// Function will return EFI_NOT_FOUND if there a no entry for the Device HANDLE passed.
+//
+// But it will return update the array of EFI_PCI_CONFIGURATION_ADDRESS structures with
+// PCI Addresses of parenti
+//
+// Input:
+// AMI_PCI_EXT_PROTOCOL* This Pointer to the PciBusExtended protocol.
+// EFI_HANDLE PciDeviceHandle Handle of the PCI Device to check.
+// EFI_PCI_IO_PROTOCOL* PciIo Pointer to the instance of PCI IO Protocol (OPTIONAL)
+// PCI_IRQ_PIC_ROUTE** PicIrqTblEntry Double pointer to the corresponded PCI_IRQ_PIC_ROUTE entry
+// EFI_PCI_CONFIGURATION_ADDRESS** ParentDevices Pointer to an array of parent Devices
+// for which was not found a valid PCI_IRQ_PIC_ROUTE entry.
+// UINTN* EntryCount Number of elements in an array above.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND If no PIRQ entry was found for this device.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+// Note:
+// If PciDeviceHandle == NULL, PciIo must be valid.
+// If *PciIo == NULL PciDeviceHandle must be valid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciExtPicIrqRout (
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_IRQ_PIC_ROUTE **PicIrqTblEntry,
+ OUT EFI_PCI_CONFIGURATION_ADDRESS **ParentDevices,
+ OUT UINTN *EntryCount )
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=NULL;
+ PCI_DEV_INFO *parent;
+ T_ITEM_LIST ParentLst={0,0,NULL};
+ INTN i,j;
+ EFI_PCI_CONFIGURATION_ADDRESS *pa=NULL;
+//------------------------------------
+ dev=PciExtGetDevice(PciDeviceHandle, PciIo);
+
+ if(dev != NULL ){
+ if( dev->PicIrqEntry != NULL ){
+ *PicIrqTblEntry = dev->PicIrqEntry;
+ ParentDevices = NULL;
+ EntryCount = 0;
+ return EFI_SUCCESS;
+ } else {
+ parent=dev;
+ do{
+ parent=parent->ParentBrg;
+ Status=AppendItemLst(&ParentLst, parent);
+ }while( (parent->PicIrqEntry == NULL) || (parent->Type != tPciRootBrg));
+
+ if( parent->PicIrqEntry != NULL ){
+ *PicIrqTblEntry=parent->PicIrqEntry;
+ //Create the array of addresses in order from Device which has IRQ endtry down to this Device parent
+ if(ParentLst.ItemCount){
+ pa=Malloc(sizeof(EFI_PCI_CONFIGURATION_ADDRESS)*(ParentLst.ItemCount));
+ for(i=(INTN)ParentLst.ItemCount-1, j=0; i<=0; i--,j++){
+ parent = (PCI_DEV_INFO*)ParentLst.Items[i];
+ pa[j] = parent->Address.Addr;
+ }
+ }
+ *ParentDevices=pa;
+ *EntryCount=ParentLst.ItemCount;
+ } else {
+ *PicIrqTblEntry=NULL;
+ ParentDevices=NULL;
+ EntryCount=0;
+ }
+ return EFI_NOT_FOUND;
+ }
+ }
+ else return EFI_INVALID_PARAMETER;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciExtApicIrqRout()
+//
+// Description: Returns device's corresponded APIC IRQ routing entry from MPPCIIRQ.INC
+// table created by the BUILD process.
+// If function returns EFI_SUCCESS the "ApicIrqTblEntry" updated with corresponded PIC
+// IRQ Table entry pointer. "ParentDevices" == NULL and "EntryCount"==0
+// Function will return EFI_NOT_FOUND if there a no entry for the Device HANDLE passed.
+//
+// But it will return update the array of EFI_PCI_CONFIGURATION_ADDRESS structures with
+// PCI Addresses of parenti
+//
+// Input:
+// AMI_PCI_EXT_PROTOCOL* This Pointer to the PciBusExtended protocol.
+// EFI_HANDLE PciDeviceHandle Handle of the PCI Device to check.
+// EFI_PCI_IO_PROTOCOL* PciIo Pointer to the instance of PCI IO Protocol (OPTIONAL)
+// PCI_IRQ_PIC_ROUTE** ApicIrqTblEntry Double pointer to the corresponded PCI_IRQ_PIC_ROUTE entry
+// EFI_PCI_CONFIGURATION_ADDRESS** ParentDevices Pointer to an array of parent Devices
+// for which was not found a valid PCI_IRQ_PIC_ROUTE entry.
+// UINTN* EntryCount Number of elements in an array above.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND If no PIRQ entry was found for this device.
+// EFI_INVALID_PARAMETER When Parameter passed is invalid.
+//
+// Note:
+// If PciDeviceHandle == NULL, PciIo must be valid.
+// If *PciIo == NULL PciDeviceHandle must be valid.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciExtApicIrqRout (
+ IN AMI_PCI_EXT_PROTOCOL *This,
+ IN EFI_HANDLE PciDeviceHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo OPTIONAL,
+ OUT PCI_IRQ_APIC_ROUTE **ApicIrqTblEntry,
+ OUT EFI_PCI_CONFIGURATION_ADDRESS **ParentDevices,
+ OUT UINTN *EntryCount )
+{
+ EFI_STATUS Status;
+ PCI_DEV_INFO *dev=NULL;
+ PCI_DEV_INFO *parent;
+ T_ITEM_LIST ParentLst={0,0,NULL};
+ INTN i,j;
+ EFI_PCI_CONFIGURATION_ADDRESS *pa=NULL;
+//------------------------------------
+ dev=PciExtGetDevice(PciDeviceHandle, PciIo);
+
+ if(dev != NULL ){
+ if( dev->ApicIrqEntry != NULL ){
+ *ApicIrqTblEntry = dev->ApicIrqEntry;
+ ParentDevices = NULL;
+ EntryCount = 0;
+ return EFI_SUCCESS;
+ } else {
+ parent=dev;
+ do{
+ parent=parent->ParentBrg;
+ Status=AppendItemLst(&ParentLst, parent);
+ }while( (parent->ApicIrqEntry == NULL) || (parent->Type != tPciRootBrg));
+
+ if( parent->ApicIrqEntry != NULL ){
+ *ApicIrqTblEntry=parent->ApicIrqEntry;
+ //Create the array of addresses in order from Device which has IRQ endtry down to this Device parent
+ if(ParentLst.ItemCount){
+ pa=Malloc(sizeof(EFI_PCI_CONFIGURATION_ADDRESS)*(ParentLst.ItemCount));
+ for(i=(INTN)ParentLst.ItemCount-1, j=0; i<=0; i--,j++){
+ parent = (PCI_DEV_INFO*)ParentLst.Items[i];
+ pa[j] = parent->Address.Addr;
+ }
+ }
+ *ParentDevices=pa;
+ *EntryCount=ParentLst.ItemCount;
+ } else {
+ *ApicIrqTblEntry=NULL;
+ ParentDevices=NULL;
+ EntryCount=0;
+ }
+ return EFI_NOT_FOUND;
+ }
+ }
+ else return EFI_INVALID_PARAMETER;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/PCI/PciBus.chm b/Core/EM/PCI/PciBus.chm
new file mode 100644
index 0000000..2acd504
--- /dev/null
+++ b/Core/EM/PCI/PciBus.chm
Binary files differ
diff --git a/Core/EM/PCI/PciBus.cif b/Core/EM/PCI/PciBus.cif
new file mode 100644
index 0000000..8546bd1
--- /dev/null
+++ b/Core/EM/PCI/PciBus.cif
@@ -0,0 +1,19 @@
+<component>
+ name = "PciBus"
+ category = ModulePart
+ LocalRoot = "Core\EM\PCI\"
+ RefName = "PciBus"
+[files]
+"PciBus.sdl"
+"PciBus.mak"
+"PciBus.sd"
+"PciBus.uni"
+"PciBusSetup.c"
+"PciRootBridge.dxs"
+"PciPort.c"
+"PciSetup.h"
+"PciPort.h"
+"PciBus.chm"
+[parts]
+"PciBusIncludes"
+<endComponent>
diff --git a/Core/EM/PCI/PciBus.mak b/Core/EM/PCI/PciBus.mak
new file mode 100644
index 0000000..945fa2f
--- /dev/null
+++ b/Core/EM/PCI/PciBus.mak
@@ -0,0 +1,152 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2007, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/BIN/Core/Modules/PciBus/PciBus.mak 13 4/05/11 11:08a Yakovlevs $
+#
+# $Revision: 13 $
+#
+# $Date: 4/05/11 11:08a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Core/Modules/PciBus/PciBus.mak $
+#
+# 13 4/05/11 11:08a Yakovlevs
+# [TAG] EIP38174
+# [Category] New Feature
+# [Description] Added generic support to handle
+# [Files] PciBus.c; PciHostBridge.c; PciBus.h; PciHostBridge.c;
+# PciPort.c;
+#
+# 12 1/28/11 2:58p Yakovlevs
+# [TAG] EIP43879
+# [Category] New Feature
+# [Description] Added PciPortOemGetOptRom() OEM Hook to override
+# content of the PCI Device Option ROM.
+# [Files] PciBus.c; PciPort.c; PciPort.h; PciBus.mak; PciBus.sdl
+#
+# 11 8/16/10 1:11p Yakovlevs
+# Added OEM_PCI_DEVICE_SET_ASPM for custom Aspm Programming.
+#
+# 10 9/22/09 6:01p Yakovlevs
+# 1. Added Definitions for OEM_PCI_PROGRAM_DEVICE_CALLBACK_LIST;
+# OEM_PCI_SKIP_DEVICE_CALLBACK_LIST and OEM_PCI_DEVICE_ATTRIBUTES_LIST to
+# support addingh porting hooks trough eLinks
+#
+# 9 4/28/09 3:49p Yakovlevs
+# Changes related to AmiBoardInfo protocol and Multiplatform support.
+#
+# 8 11/14/08 1:31p Yakovlevs
+# Added unconditionaly PciRoot it installs AMI Board Info Protocol
+#
+# 7 10/01/08 7:09p Yakovlevs
+# Updated AMI FUNC HEADER information.
+#
+# 6 9/25/08 11:45a Yakovlevs
+# Changes in build structure to support new features.
+#
+# 5 10/18/07 11:22a Felixp
+# PciPort.c added
+#
+# 4 8/22/07 6:56p Felixp
+# Exlude PciBusSetup.c from the list of files compiled during PciBus and
+# PciRootBridge build (set OBJECTS to blank string).
+#
+# 3 4/18/07 11:11p Felixp
+#
+# 2 4/12/07 3:53p Yakovlevs
+# Removed unused libraryes from module link process.
+#
+# 1 3/12/07 12:07p Yakovlevs
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: PciBus.mak
+#
+# Description: Make file to build PciBus Driver
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : PciBus
+
+PciBus : $(BUILD_DIR)\PciBus.mak PciBusBin
+
+!IF "$(AMI_ROOT_BRIDGE_SUPPORT)"=="1"
+PciBus : PciRootBridgeBin
+!ENDIF
+
+$(BUILD_DIR)\PciBus.mak : $(PCIBUS_DIR)\$(@B).cif $(PCIBUS_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(PCIBUS_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+PciBusBin : $(AMIDXELIB) $(AMICSPLib) $(PCIBUSSRCLIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\PciBus.mak all\
+ MAKEFILE=$(PCIBUS_DIR)\PciBus.mak \
+ GUID=3C1DE39F-D207-408a-AACC-731CFB7F1DD7\
+ ENTRY_POINT=PciBusEntryPoint\
+ TYPE=BS_DRIVER DEPEX1= LIBRARIES=\
+ "CFLAGS=$(CFLAGS) /D\"OEM_PCI_PROGRAM_DEVICE_CALLBACK_LIST=$(OEM_PROGRAM_PCI_DEVICE)\" \
+ /D\"OEM_PCI_SKIP_DEVICE_CALLBACK_LIST=$(OEM_SKIP_PCI_DEVICE)\" \
+ /D\"OEM_PCI_DEVICE_SET_ASPM_CALLBACK_LIST=$(OEM_PCI_DEVICE_SET_ASPM)\" \
+ /D\"OEM_PCI_DEVICE_SET_LNK_SPEED_CALLBACK_LIST=$(OEM_PCI_DEVICE_SET_LNK_SPEED)\" \
+ /D\"OEM_PCI_DEVICE_GET_OPT_ROM_CALLBACK_LIST=$(OEM_PCI_DEVICE_GET_OPT_ROM)\" \
+ /D\"OEM_PCI_DEVICE_OUT_OF_RESOURCES_CALLBACK_LIST=$(OEM_PCI_DEVICE_OUT_OF_RESOURCES)\" \
+ /D\"OEM_PCI_DEVICE_ATTRIBUTE_CALLBACK_LIST=$(OEM_PCI_ATTRIBUTES)\"" \
+ "OBJECTS=$(BUILD_DIR)\$(PCIBUS_DIR)\PciPort.obj"\
+ COMPRESS=1\
+
+!IF "$(AMI_ROOT_BRIDGE_SUPPORT)"=="1"
+PciRootBridgeBin : $(AMIDXELIB) $(AMICSPLib) $(PCIBUSSRCLIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\PciBus.mak all\
+ NAME=PciRootBridge\
+ MAKEFILE=$(PCIBUS_DIR)\PciBus.mak \
+ GUID=80E66E0A-CCD1-43fa-A7B1-2D5EE0F13910 \
+ ENTRY_POINT=InitializePCIHostBridge \
+ DEPEX1=$(PCIBUS_DIR)\PciRootBridge.DXS \
+ TYPE=BS_DRIVER LIBRARIES= \
+ "OBJECTS=$(BUILD_DIR)\$(PCIBUS_DIR)\PciPort.obj"\
+ COMPRESS=1\
+!ENDIF
+
+#---------------------------------------------------------------------------
+# Create PCI Bus Setup Screens
+#---------------------------------------------------------------------------
+SetupSdbs : $(BUILD_DIR)\PciBus.mak PCIBUSSDB
+SetupBin : $(BUILD_DIR)\PciBusSetup.obj
+
+PCIBUSSDB :
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\PciBus.mak all\
+ TYPE=SDB NAME=PciBus MAKEFILE=$(BUILD_DIR)\PciBus.Mak STRING_CONSUMERS=$(PCIBUS_DIR)\PciBus.sd
+$(BUILD_DIR)\PciBusSetup.obj : $(PCIBUS_DIR)\PciBusSetup.c $(BUILD_DIR)\SetupStrTokens.h
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(PCIBUS_DIR)\PciBusSetup.c
+#---------------------------------------------------------------------------
+
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2007, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#********************************************************************** \ No newline at end of file
diff --git a/Core/EM/PCI/PciBus.sd b/Core/EM/PCI/PciBus.sd
new file mode 100644
index 0000000..404482b
--- /dev/null
+++ b/Core/EM/PCI/PciBus.sd
@@ -0,0 +1,1067 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/PciBus/PciBus.sd 22 9/10/12 12:54p Yakovlevs $
+//
+// $Revision: 22 $
+//
+// $Date: 9/10/12 12:54p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/PciBus/PciBus.sd $
+//
+// 22 9/10/12 12:54p Yakovlevs
+// [TAG] EIP93341
+// [Category] Improvement
+// [Description] Preserve PCI DEV/LNK/SLT control register in S3 resume
+// path.
+// [Files] PciBus.c PciBus.sd PciBus.uni PciSetup.h PciPort.c
+//
+// 21 2/27/12 6:39p Artems
+// EIP 83608: Added MANUFACTURING flag to setup controls
+//
+// 20 11/09/11 1:54p Yakovlevs
+// [TAG] EIP71380
+// [Category] New Feature
+// [Description] Core support for CSM opt-out feature
+// [Files] PciBus.c; PciPort.c; PciBus.sd; PciBus.uni; PciSetup.h;
+// PciBusSetup.c;
+//
+// 18 4/05/11 11:21a Yakovlevs
+// [TAG] EIP53475
+// [Category] New Feature
+// [Description] PCI Express 3.0 support added. And minor bug fix.
+// [Files] PciBus.c; PciHostBridge.c; PciBus.h; PciHostBridge.c;
+// PciPort.c;
+//
+// 17 1/20/11 3:13p Yakovlevs
+// [TAG] EIP48181
+// [Category] Improvement
+// [Description] Update the PciBus eModule to utilize Setup
+// Customization
+// [Files] PciBus.sd
+//
+// 16 12/08/10 3:18p Yakovlevs
+// Removed Setup Option "Selectable DeEmphasis" since it is HwInit Bit.
+//
+// 15 11/22/10 10:44a Yakovlevs
+// Removed STR_HORIZONTAL_D_LINE string since it creates problems with
+// reduced screen resolution.
+//
+// 14 10/01/10 12:27p Felixp
+// Link Training Defaults changed.
+//
+// 13 4/13/10 12:02p Yakovlevs
+// Changed Default ADPM settings to disable.
+//
+// 12 3/01/10 6:09p Yakovlevs
+// Pci Express V2.1 Support Added.
+//
+// 10 12/04/09 12:00p Felixp
+// UEFI 2.1 support.
+//
+// 9 3/23/09 4:57p Yakovlevs
+// Added generic support for PCI Express Hot-Plug.
+//
+// 8 10/16/08 6:13p Fasihm
+// Also added the MANUFACTURING flag to the setup questions.
+//
+// 7 9/25/08 11:47a Yakovlevs
+// Added Pci Bus Driver version display.
+//
+// 5 3/30/07 5:19p Robert
+// Updated Strings
+//
+// 4 3/30/07 2:57p Robert
+//
+// 3 3/14/07 2:04p Yakovlevs
+// Hode PciOption Rom Option from PCI Setup Screen
+//
+// 2 3/13/07 8:32p Yakovlevs
+//
+// 1 3/12/07 12:07p Yakovlevs
+//
+
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: PCIBus.sd
+//
+// Description: PCI/PCIExpress/PCIX settings
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#ifdef SETUP_DATA_DEFINITION
+/***********************************************************/
+/* Put NVRAM data definitions here.
+/* For example: UINT8 Data1;
+/* These definitions will be converted by the build process
+/* to a definitions of SETUP_DATA fields.
+/***********************************************************/
+#if ABOVE_4G_PCI_DECODE
+ UINT8 Above4gDecode; //[Disable]\ Enable
+#endif
+
+ //General PCI Settings: [] - default
+ UINT8 PciLatency; //[32]\ 64 \ 96 \ 128 \ 160 \ 192 \ 224 \ 248
+ UINT8 VgaPallete; //[Disable]\ Enable
+ UINT8 PerrEnable; //[Disable]\ Enable
+ UINT8 SerrEnable; //[Disable]\ Enable
+
+#if PCI_X_SUPPORT
+ UINT8 PciXLatency; // 32 \[64]\ 96 \ 128 \ 160 \ 192 \ 224 \ 248
+#endif
+
+#if PCI_EXPRESS_SUPPORT
+ //PCI Express Device Settings: [] - default
+ UINT8 RelaxedOrdering; //[Disable]\ Enable
+ UINT8 ExtTagField; //[Disable]\ Enable
+ UINT8 NoSnoop; // Disable \[Enable]
+ UINT8 MaxPayload; //[Auto]\ 128 \ 256 \ 512 \ 1024 \ 2048 \ 4096 (in bytes)
+ UINT8 MaxReadRequest; //[Auto]\ 128 \ 256 \ 512 \ 1024 \ 2048 \ 4096 (in bytes)
+ //PCI Express Link settings: [] - default
+ UINT8 AspmMode; //[Disable]\ Auto \ Force L0
+ UINT8 ExtendedSynch; //[Disable]\ Enable
+ UINT8 LnkTrRetry; //[Disable]\ 2 \ 3 \ 5
+ UINT16 LnkTrTimeout; //[1...1000] (Microseconds uS)
+ UINT8 LnkDisable; //[Keep ON == 0] / Disable ==1
+ UINT8 S3PciExpressScripts; //[Disable]\ Enable
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+ //Gen2 Device Settings
+ UINT8 ComplTimeOut; //[Disable]\ Default \ SHORT \ LONG
+ UINT8 AriFwd; //[Disable]\ Enable
+ UINT8 AtomOpReq; //[Disable]\ Enable
+ UINT8 AtomOpEgressBlk; //[Disable]\ Enable
+ UINT8 IDOReq; //[Disable]\ Enable
+ UINT8 IDOCompl; //[Disable]\ Enable
+ UINT8 LtrReport; //[Disable]\ Enable
+ UINT8 E2ETlpPrBlk; //[Disable]\ Enable
+
+ //Gen2 Link Settings
+ UINT8 LnkSpeed; //[Auto]\ Forse to 5.0 GT/s \Force to 2.5 GT/s
+ UINT8 DeEmphasis; //[-3.5 dB]\ -6.0 dB
+ UINT8 ClockPm; //[Disable]\ Enable
+ UINT8 ComplSos; //[Disable]\ Enable
+ UINT8 HwAutoWidth; //[Enable]\ Disable LNK_CNT_REG #1
+ UINT8 HwAutoSpeed; //[Enable]\ Disable
+#endif
+
+#endif
+
+//Hotplug stuff.
+#if AMI_HOTPLUG_INIT_SUPPORT
+ UINT8 HotPlugEnable; // Disable \[Enable]
+ UINT8 BusPadd; // Disable \[1]\ 2 \ 3 \ 4 \ 5
+ //Following field stored in units of KB
+ UINT8 IoPadd; // Disable \[ 4K]\ 8K \ 16K \ 32K
+ //Following fields stored in units of MB
+ UINT8 Mmio32Padd; // Disable \ 1M \ 4M \ 8M \[16M]\ 32M \ 64M \128M
+ UINT8 Mmio32PfPadd; // Disable \ 1M \ 4M \ 8M \[16M]\ 32M \ 64M \128M
+ //for 512 and 1G 1 byte storege is not enough...
+ UINT16 Mmio64Padd; //[Disable]\ 1M \ 4M \ 8M \ 16M \ 32M \ 64M \ 128M \ 256M \ 512M \ 1G
+ UINT16 Mmio64PfPadd; //[Disable]\ 1M \ 4M \ 8M \ 16M \ 32M \ 64M \ 128M \ 256M \ 512M \ 1G
+#endif
+
+#endif //SETUP_DATA_DEFINITION
+
+#if defined(VFRCOMPILE) && !defined(CONTROLS_ARE_DEFINED)
+#define CONTROL_DEFINITION
+#endif
+
+#ifdef CONTROL_DEFINITION
+
+#if ABOVE_4G_PCI_DECODE
+#define PCIBUS_ONEOF_ABOVE4GDECODE\
+ oneof varid = SETUP_DATA.Above4gDecode,\
+ prompt = STRING_TOKEN(STR_PCI_4G_PROMPT),\
+ help = STRING_TOKEN(STR_PCI_4G_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+#else
+#define PCIBUS_ONEOF_ABOVE4GDECODE
+#endif // #if ABOVE_4G_PCI_DECODE
+
+#define PCIBUS_ONEOF_PCILATENCY\
+ oneof varid = SETUP_DATA.PciLatency,\
+ prompt = STRING_TOKEN(STR_PCI_LATENCY_PROMPT),\
+ help = STRING_TOKEN(STR_PCI_LATENCY_HELP),\
+ option text = STRING_TOKEN(STR_PCI_32), value = 32, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_64), value = 64, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_96), value = 96, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_128), value = 128, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_160), value = 160, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_192), value = 192, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_224), value = 224, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_248), value = 248, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_VGAPALLETE\
+ oneof varid = SETUP_DATA.VgaPallete,\
+ prompt = STRING_TOKEN(STR_PCI_VGASNOOP_PROMPT),\
+ help = STRING_TOKEN(STR_PCI_VGASNOOP_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_PERRENABLE\
+ oneof varid = SETUP_DATA.PerrEnable,\
+ prompt = STRING_TOKEN(STR_PCI_PERR_PROMPT),\
+ help = STRING_TOKEN(STR_PCI_PERR_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_SERRENABLE\
+ oneof varid = SETUP_DATA.SerrEnable,\
+ prompt = STRING_TOKEN(STR_PCI_SERR_PROMPT),\
+ help = STRING_TOKEN(STR_PCI_SERR_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#if PCI_X_SUPPORT
+#define PCIBUS_ONEOF_PCIXLATENCY\
+ oneof varid = SETUP_DATA.PciXLatency,\
+ prompt = STRING_TOKEN(STR_PCIX_LATENCY_PROMPT),\
+ help = STRING_TOKEN(STR_PCI_LATENCY_HELP),\
+ option text = STRING_TOKEN(STR_PCI_32), value = 32, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_64), value = 64, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_96), value = 96, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_128), value = 128, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_160), value = 160, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_192), value = 192, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_224), value = 224, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_PCI_248), value = 248, flags = RESET_REQUIRED;\
+ endoneof;
+#else
+#define PCIBUS_ONEOF_PCIXLATENCY
+#endif // #if PCI_X_SUPPORT
+
+#if PCI_EXPRESS_SUPPORT
+
+#define PCIBUS_ONEOF_RELAXEDORDERING\
+ oneof varid = SETUP_DATA.RelaxedOrdering,\
+ prompt = STRING_TOKEN(STR_PCIE_RELAXEDORDERING_PROMPT),\
+ help = STRING_TOKEN(STR_PCIE_RELAXEDORDERING_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_EXTTAGFIELD\
+ oneof varid = SETUP_DATA.ExtTagField,\
+ prompt = STRING_TOKEN(STR_PCIE_EXTTAGFLD_PROMPT),\
+ help = STRING_TOKEN(STR_PCIE_EXTTAGFLD_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_NOSNOOP\
+ oneof varid = SETUP_DATA.NoSnoop,\
+ prompt = STRING_TOKEN(STR_PCIE_NOSNOOP_PROMPT),\
+ help = STRING_TOKEN(STR_PCIE_NOSNOOP_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_MAXPAYLOAD\
+ oneof varid = SETUP_DATA.MaxPayload,\
+ prompt = STRING_TOKEN(STR_PCIE_MAXPAYLOAD_PROMPT),\
+ help = STRING_TOKEN(STR_PCIE_MAXPAYLOAD_HELP),\
+ option text = STRING_TOKEN(STR_AUTO), value = 55, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP128), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP256), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP512), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP1024), value = 3, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP2048), value = 4, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP4096), value = 5, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_MAXREADREQUEST\
+ oneof varid = SETUP_DATA.MaxReadRequest,\
+ prompt = STRING_TOKEN(STR_PCIE_MAXREADREQUEST_PROMPT),\
+ help = STRING_TOKEN(STR_PCIE_MAXREADREQUEST_HELP),\
+ option text = STRING_TOKEN(STR_AUTO), value = 55, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP128), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP256), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP512), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP1024), value = 3, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP2048), value = 4, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_MP4096), value = 5, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_ASPMMODE\
+ oneof varid = SETUP_DATA.AspmMode,\
+ prompt = STRING_TOKEN(STR_PCIE_ASPM_PROMPT),\
+ help = STRING_TOKEN(STR_PCIE_ASPM_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_AUTO), value = 55, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_FORCE_L0), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_EXTENDEDSYNCH\
+ oneof varid = SETUP_DATA.ExtendedSynch,\
+ prompt = STRING_TOKEN(STR_PCIE_EXTD_SYNCH_PROMPT),\
+ help = STRING_TOKEN(STR_PCIE_EXTD_SYNCH_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_LNKTRRETRY\
+ oneof varid = SETUP_DATA.LnkTrRetry,\
+ prompt = STRING_TOKEN(STR_LNK_TR_RETRY_PROMPT),\
+ help = STRING_TOKEN(STR_LNK_TR_RETRY_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_2), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_3), value = 3, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_5), value = 5, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_NUM_LNKTRTIMEOUT\
+ numeric varid = SETUP_DATA.LnkTrTimeout,\
+ prompt = STRING_TOKEN(STR_LNK_TR_TIMEOUT_PROMPT),\
+ help = STRING_TOKEN(STR_LNK_TR_TIMEOUT_HELP),\
+ flags = RESET_REQUIRED,\
+ minimum = 10,\
+ maximum = 10000,\
+ step = 10,\
+ option text = STRING_TOKEN(STR_EMPTY), value = 100, flags = DEFAULT | MANUFACTURING;\
+ endnumeric;
+
+#define PCIBUS_ONEOF_LNKDISABLE\
+ oneof varid = SETUP_DATA.LnkDisable,\
+ prompt = STRING_TOKEN(STR_LNK_UNPOPULATED_PROMPT),\
+ help = STRING_TOKEN(STR_LNK_UNPOPULATED_HELP),\
+ option text = STRING_TOKEN(STR_KEEP_ON), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_DISABLE), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_S3PCIEXPRESSSCRIPTS\
+ oneof varid = SETUP_DATA.S3PciExpressScripts,\
+ prompt = STRING_TOKEN(STR_DEV_S3_PCIE_SCRIPTS_PROMPT),\
+ help = STRING_TOKEN(STR_DEV_S3_PCIE_SCRIPTS_HELP),\
+ option text = STRING_TOKEN(STR_ENABLED), value = 0xFF, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0x00, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ endoneof;
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+#define PCIBUS_ONEOF_COMPLTIMEOUT\
+ oneof varid = SETUP_DATA.ComplTimeOut,\
+ prompt = STRING_TOKEN(STR_DEV_COMPL_TIMEOUT_PROMPT),\
+ help = STRING_TOKEN(STR_DEV_COMPL_TIMEOUT_HELP),\
+ option text = STRING_TOKEN(STR_DEFAULT), value = 0xFF, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_SHORT), value = 0x55, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_LONG), value = 0xAA, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_DISABLED),value = 0x00, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_ARIFWD\
+ oneof varid = SETUP_DATA.AriFwd,\
+ prompt = STRING_TOKEN(STR_DEV_ARI_PROMPT),\
+ help = STRING_TOKEN(STR_DEV_ARI_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_ATOMOPREQ\
+ oneof varid = SETUP_DATA.AtomOpReq,\
+ prompt = STRING_TOKEN(STR_DEV_AOP_REQ_PROMPT),\
+ help = STRING_TOKEN(STR_DEV_AOP_REQ_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_ATOMOPEGRESSBLK\
+ oneof varid = SETUP_DATA.AtomOpEgressBlk,\
+ prompt = STRING_TOKEN(STR_DEV_AOP_EGRESS_BLK_PROMPT),\
+ help = STRING_TOKEN(STR_DEV_AOP_EGRESS_BLK_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_IDOREQ\
+ oneof varid = SETUP_DATA.IDOReq,\
+ prompt = STRING_TOKEN(STR_DEV_IDO_REQ_PROMPT),\
+ help = STRING_TOKEN(STR_DEV_IDO_REQ_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_IDOCOMPL\
+ oneof varid = SETUP_DATA.IDOCompl,\
+ prompt = STRING_TOKEN(STR_DEV_IDO_COMPL_PROMPT),\
+ help = STRING_TOKEN(STR_DEV_IDO_COMPL_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_LTRREPORT\
+ oneof varid = SETUP_DATA.LtrReport,\
+ prompt = STRING_TOKEN(STR_DEV_LTR_REPORT_PROMPT),\
+ help = STRING_TOKEN(STR_DEV_LTR_REPORT_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_E2ETLPPRBLK\
+ oneof varid = SETUP_DATA.E2ETlpPrBlk,\
+ prompt = STRING_TOKEN(STR_DEV_E2E_TLP_BLK_PROMPT),\
+ help = STRING_TOKEN(STR_DEV_E2E_TLP_BLK_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+
+#define PCIBUS_ONEOF_LNKSPEED\
+ oneof varid = SETUP_DATA.LnkSpeed,\
+ prompt = STRING_TOKEN(STR_LNK_SPEED_PROMPT),\
+ help = STRING_TOKEN(STR_LNK_SPEED_HELP),\
+ option text = STRING_TOKEN(STR_AUTO), value = 55, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_2_5G), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_5_0G), value = 2, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_CLOCKPM\
+ oneof varid = SETUP_DATA.ClockPm,\
+ prompt = STRING_TOKEN(STR_LNK_CLOCK_PM_PROMPT),\
+ help = STRING_TOKEN(STR_LNK_CLOCK_PM_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_COMPLSOS\
+ oneof varid = SETUP_DATA.ComplSos,\
+ prompt = STRING_TOKEN(STR_LNK_COMPL_SOS_PROMPT),\
+ help = STRING_TOKEN(STR_LNK_COMPL_SOS_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_HWAUTOWIDTH\
+ oneof varid = SETUP_DATA.HwAutoWidth,\
+ prompt = STRING_TOKEN(STR_LNK_HW_AUTO_WIDTH_PROMPT),\
+ help = STRING_TOKEN(STR_LNK_HW_AUTO_WIDTH_HELP),\
+ option text = STRING_TOKEN(STR_ENABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_DISABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_HWAUTOSPEED\
+ oneof varid = SETUP_DATA.HwAutoSpeed,\
+ prompt = STRING_TOKEN(STR_LNK_HW_AUTO_SPEED_PROMPT),\
+ help = STRING_TOKEN(STR_LNK_HW_AUTO_SPEED_HELP),\
+ option text = STRING_TOKEN(STR_ENABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_DISABLED), value = 1, flags = RESET_REQUIRED;\
+ endoneof;
+#else
+
+#define PCIBUS_ONEOF_COMPLTIMEOUT
+#define PCIBUS_ONEOF_ARIFWD
+#define PCIBUS_ONEOF_ATOMOPREQ
+#define PCIBUS_ONEOF_ATOMOPEGRESSBLK
+#define PCIBUS_ONEOF_IDOREQ
+#define PCIBUS_ONEOF_IDOCOMPL
+#define PCIBUS_ONEOF_LTRREPORT
+#define PCIBUS_ONEOF_E2ETLPPRBLK
+#define PCIBUS_ONEOF_LNKSPEED
+#define PCIBUS_ONEOF_CLOCKPM
+#define PCIBUS_ONEOF_COMPLSOS
+#define PCIBUS_ONEOF_HWAUTOWIDTH
+#define PCIBUS_ONEOF_HWAUTOSPEED
+
+#endif//PCI_EXPRESS_GEN2_SUPPORT
+
+#else
+#define PCIBUS_ONEOF_RELAXEDORDERING
+#define PCIBUS_ONEOF_EXTTAGFIELD
+#define PCIBUS_ONEOF_NOSNOOP
+#define PCIBUS_ONEOF_MAXPAYLOAD
+#define PCIBUS_ONEOF_MAXREADREQUEST
+#define PCIBUS_ONEOF_ASPMMODE
+#define PCIBUS_ONEOF_EXTENDEDSYNCH
+#define PCIBUS_ONEOF_LNKTRRETRY
+#define PCIBUS_NUM_LNKTRTIMEOUT
+#define PCIBUS_ONEOF_LNKDISABLE
+#define PCIBUS_ONEOF_S3PCIEXPRESSSCRIPTS
+
+#endif // #if PCI_EXPRESS_SUPPORT
+
+#if AMI_HOTPLUG_INIT_SUPPORT
+#define PCIBUS_ONEOF_HOTPLUGENABLE\
+ oneof varid = SETUP_DATA.HotPlugEnable,\
+ prompt = STRING_TOKEN(STR_HOTPLUG_ENABLE_PROMPT),\
+ help = STRING_TOKEN(STR_HOTPLUG_ENABLE_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_BUSPADD\
+ oneof varid = SETUP_DATA.BusPadd,\
+ prompt = STRING_TOKEN(STR_BUS_PADD_PROMPT),\
+ help = STRING_TOKEN(STR_BUS_PADD_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_1), value = 1, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_2), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_3), value = 3, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_4), value = 4, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_5), value = 5, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_IOPADD\
+ oneof varid = SETUP_DATA.IoPadd,\
+ prompt = STRING_TOKEN(STR_IO_PADD_PROMPT),\
+ help = STRING_TOKEN(STR_IO_PADD_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_4K), value = 4, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_8K), value = 8, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_16K), value = 16, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_32K), value = 32, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_MMIO32PADD\
+ oneof varid = SETUP_DATA.Mmio32Padd,\
+ prompt = STRING_TOKEN(STR_MMIO32_PADD_PROMPT),\
+ help = STRING_TOKEN(STR_MMIO32_PADD_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_1M), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_2M), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_4M), value = 4, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_8M), value = 8, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_16M), value = 16, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_32M), value = 32, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_64M), value = 64, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_128M),value = 128, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_MMIO32PFPADD\
+ oneof varid = SETUP_DATA.Mmio32PfPadd,\
+ prompt = STRING_TOKEN(STR_MMIO32PF_PADD_PROMPT),\
+ help = STRING_TOKEN(STR_MMIO32PF_PADD_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_1M), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_2M), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_4M), value = 4, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_8M), value = 8, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_16M), value = 16, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_32M), value = 32, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_64M), value = 64, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_128M),value = 128, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_MMIO64PADD\
+ oneof varid = SETUP_DATA.Mmio64Padd,\
+ prompt = STRING_TOKEN(STR_MMIO64_PADD_PROMPT),\
+ help = STRING_TOKEN(STR_MMIO64_PADD_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_1M), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_2M), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_4M), value = 4, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_8M), value = 8, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_16M), value = 16, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_32M), value = 32, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_64M), value = 64, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_128M),value = 128, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_256M), value = 256, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_512M), value = 512, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_1G), value = 1024, flags = RESET_REQUIRED;\
+ endoneof;
+
+#define PCIBUS_ONEOF_MMIO64PFPADD\
+ oneof varid = SETUP_DATA.Mmio64PfPadd,\
+ prompt = STRING_TOKEN(STR_MMIO64PF_PADD_PROMPT),\
+ help = STRING_TOKEN(STR_MMIO64PF_PADD_HELP),\
+ option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_1M), value = 1, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_2M), value = 2, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_4M), value = 4, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_8M), value = 8, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_16M), value = 16, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_32M), value = 32, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_64M), value = 64, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_128M), value = 128, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_256M), value = 256, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_512M), value = 512, flags = RESET_REQUIRED;\
+ option text = STRING_TOKEN(STR_1G), value = 1024, flags = RESET_REQUIRED;\
+ endoneof;
+
+#else
+#define PCIBUS_ONEOF_HOTPLUGENABLE
+#define PCIBUS_ONEOF_BUSPADD
+#define PCIBUS_ONEOF_IOPADD
+#define PCIBUS_ONEOF_MMIO32PADD
+#define PCIBUS_ONEOF_MMIO32PFPADD
+#define PCIBUS_ONEOF_MMIO64PADD
+#define PCIBUS_ONEOF_MMIO64PFPADD
+#endif
+
+#endif //#ifdef CONTROL_DEFINITION
+
+#ifdef CONTROLS_WITH_DEFAULTS
+ // PCIBUS_FORM_PCI
+ PCIBUS_ONEOF_ABOVE4GDECODE
+ PCIBUS_ONEOF_PCILATENCY
+ PCIBUS_ONEOF_VGAPALLETE
+ PCIBUS_ONEOF_PERRENABLE
+ PCIBUS_ONEOF_SERRENABLE
+ PCIBUS_ONEOF_PCIXLATENCY
+
+ //PCIBUS_FORM_PCI_EXPRESS
+ PCIBUS_ONEOF_RELAXEDORDERING
+ PCIBUS_ONEOF_EXTTAGFIELD
+ PCIBUS_ONEOF_NOSNOOP
+ PCIBUS_ONEOF_MAXPAYLOAD
+ PCIBUS_ONEOF_MAXREADREQUEST
+ PCIBUS_ONEOF_ASPMMODE
+ PCIBUS_ONEOF_EXTENDEDSYNCH
+ PCIBUS_ONEOF_LNKTRRETRY
+ PCIBUS_NUM_LNKTRTIMEOUT
+ PCIBUS_ONEOF_LNKDISABLE
+ PCIBUS_ONEOF_S3PCIEXPRESSSCRIPTS
+
+ // PCIBUS_FORM_PCI_EXPRESS2
+#if PCI_EXPRESS_GEN2_SUPPORT
+ PCIBUS_ONEOF_COMPLTIMEOUT
+ PCIBUS_ONEOF_ARIFWD
+ PCIBUS_ONEOF_ATOMOPREQ
+ PCIBUS_ONEOF_ATOMOPEGRESSBLK
+ PCIBUS_ONEOF_IDOREQ
+ PCIBUS_ONEOF_IDOCOMPL
+ PCIBUS_ONEOF_LTRREPORT
+ PCIBUS_ONEOF_E2ETLPPRBLK
+ PCIBUS_ONEOF_LNKSPEED
+ PCIBUS_ONEOF_CLOCKPM
+ PCIBUS_ONEOF_COMPLSOS
+ PCIBUS_ONEOF_HWAUTOWIDTH
+ PCIBUS_ONEOF_HWAUTOSPEED
+#endif
+
+ // PCIBUS_FORM_PCIHP
+ PCIBUS_ONEOF_HOTPLUGENABLE
+ PCIBUS_ONEOF_BUSPADD
+ PCIBUS_ONEOF_IOPADD
+ PCIBUS_ONEOF_MMIO32PADD
+ PCIBUS_ONEOF_MMIO32PFPADD
+ PCIBUS_ONEOF_MMIO64PADD
+ PCIBUS_ONEOF_MMIO64PFPADD
+
+#endif //#ifdef CONTROLS_WITH_DEFAULTS
+
+
+#ifdef ADVANCED_FORM_SET
+
+ #ifndef SUPPRESS_GRAYOUT_ENDIF //old Core
+ #define SUPPRESS_GRAYOUT_ENDIF endif;
+ #endif
+
+ #ifdef FORM_SET_ITEM
+ // Define controls to be added to the main page of the formset
+ #endif
+
+ #ifdef FORM_SET_GOTO
+ // Define goto commands for the forms defined in this file
+ goto PCI_FORM_ID,
+ prompt = STRING_TOKEN(STR_PCI_FORM),
+ help = STRING_TOKEN(STR_PCI_FORM_HELP);
+ #endif
+
+
+#ifdef FORM_SET_FORM
+//
+// Define forms
+//
+
+//////////////////////////////////////////////////////////////
+//============================================================
+//Main PCI Form START
+//------------------------------------------------------------
+#ifndef PCIBUS_FORM_PCI
+#define PCIBUS_FORM_PCI
+//------------------------------------------------------------
+
+ form formid = AUTO_ID(PCI_FORM_ID),
+ title = STRING_TOKEN(STR_PCI_FORM);
+
+ //Display PCI Bus Driver Version.
+ text
+ help = STRING_TOKEN(STR_PCI_FORM_HELP),
+ text = STRING_TOKEN(STR_PCI_DRIVER_VER_PROMPT),
+ text = STRING_TOKEN(STR_PCI_DRIVER_VER),
+ flags = 0,
+ key = 0;
+
+ SEPARATOR
+
+#if ABOVE_4G_PCI_DECODE == 1
+ SEPARATOR
+ //Display PCI 64 bit Handling Subtitle
+ SUBTITLE(STRING_TOKEN(STR_PCI_64_SUB))
+// UINT8 Above4gDecode //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_ABOVE4GDECODE
+ endif;
+#endif
+
+
+ SEPARATOR
+
+ SUBTITLE(STRING_TOKEN(STR_PCI_SETTINGS))
+
+// UINT8 PciLatency; //[32]\ 64 \ 96 \ 128 \ 160 \ 192 \ 224 \ 248
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_PCILATENCY
+ endif;
+
+// UINT8 VgaPallete; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_VGAPALLETE
+ endif;
+
+// UINT8 PerrEnable //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_PERRENABLE
+ endif;
+
+// UINT8 SerrEnable //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_SERRENABLE
+ endif;
+
+
+#if PCI_X_SUPPORT
+ SEPARATOR
+ SUBTITLE(STRING_TOKEN(STR_PCIX))
+// UINT8 PciXLatency; // 32 \[64]\ 96 \ 128 \ 160 \ 192 \ 224 \ 248
+
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_PCIXLATENCY
+ endif;
+#endif
+
+#if PCI_EXPRESS_SUPPORT
+
+ SEPARATOR
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ goto PCI_PCIE1_FORM_ID,
+ prompt = STRING_TOKEN(STR_PCI_PCIE1_FORM),
+ help = STRING_TOKEN(STR_PCI_PCIE1_FORM_HELP);
+ endif;
+
+#if PCI_EXPRESS_GEN2_SUPPORT == 1
+ SEPARATOR
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ goto PCI_PCIE2_FORM_ID,
+ prompt = STRING_TOKEN(STR_PCI_PCIE2_FORM),
+ help = STRING_TOKEN(STR_PCI_PCIE2_FORM_HELP);
+ endif;
+#endif
+
+
+#endif
+
+#if AMI_HOTPLUG_INIT_SUPPORT
+
+ SEPARATOR
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ goto PCI_HP_FORM_ID,
+ prompt = STRING_TOKEN(STR_PCI_HP_FORM),
+ help = STRING_TOKEN(STR_PCI_HP_FORM_HELP);
+ endif;
+
+#endif
+
+endform; // PCI_FORM_ID
+//------------------------------------------------------------
+#endif //PCIBUS_FORM_PCI
+//------------------------------------------------------------
+
+//------------------------------------------------------------
+//Main PCI Form END
+//============================================================
+
+//============================================================
+//PCI Express Form START
+//------------------------------------------------------------
+#if PCI_EXPRESS_SUPPORT
+
+#ifndef PCIBUS_FORM_PCI_EXPRESS
+#define PCIBUS_FORM_PCI_EXPRESS
+
+ // Define PCIe Settings Form
+ form formid = AUTO_ID(PCI_PCIE1_FORM_ID),
+ title = STRING_TOKEN(STR_PCI_PCIE1_FORM);
+
+//PCI Express Device Settings: [] - default
+ SUBTITLE(STRING_TOKEN(STR_PCIE_DEVICE))
+
+// UINT8 RelaxedOrdering; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_RELAXEDORDERING
+ endif;
+// UINT8 ExtTagField; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_EXTTAGFIELD
+ endif;
+
+// UINT8 NoSnoop; // Disable \[Enable]
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_NOSNOOP
+ endif;
+
+
+// UINT8 MaxPayload //[Auto]\ 128 \ 256 \ 512 \ 1024 \ 2048 \ 4096 (in bytes)
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_MAXPAYLOAD
+ endif;
+
+
+// UINT8 MaxReadRequest //[Auto]\ 128 \ 256 \ 512 \ 1024 \ 2048 \ 4096 (in bytes)
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_MAXREADREQUEST
+ endif;
+
+//PCI Express Link settings: [] - default
+ SEPARATOR
+ SUBTITLE(STRING_TOKEN(STR_PCIE_LINK))
+// UINT8 AspmMode; //[Disabled]\ Auto \ Force L0
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_ASPMMODE
+ endif;
+
+ SUBTITLE(STRING_TOKEN(STR_PCIE_LINK_WARN3))
+ SUBTITLE(STRING_TOKEN(STR_PCIE_LINK_WARN4))
+
+
+// UINT8 ExtendedSynch //[Disable]\ Enable
+
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_EXTENDEDSYNCH
+ endif;
+
+ SEPARATOR
+// UINT8 LnkTrRetry; //[Disable]\ 2 \ 3 \ 5
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_LNKTRRETRY
+ endif;
+
+// UINT8 LnkTrTimeout; //[10...1000] uS
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_NUM_LNKTRTIMEOUT
+ endif;
+
+// UINT8 EmptyLnkDisable //[Enable]\ Disable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_LNKDISABLE
+ endif;
+// UINT8 S3PciExpressScripts; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_S3PCIEXPRESSSCRIPTS
+ endif;
+
+ endform; //PCI_PCIE2_FORM_ID
+#endif //PCIBUS_FORM_PCI_EXPRESS
+//------------------------------------------------------------
+//PCI Express Form END
+//============================================================
+
+
+#if PCI_EXPRESS_GEN2_SUPPORT == 1
+//============================================================
+//PCI Express Gen II Form START
+//------------------------------------------------------------
+
+#ifndef PCIBUS_FORM_PCI_EXPRESS2
+#define PCIBUS_FORM_PCI_EXPRESS2
+
+ form formid = AUTO_ID(PCI_PCIE2_FORM_ID),
+ title = STRING_TOKEN(STR_PCI_PCIE2_FORM);
+
+ SUBTITLE(STRING_TOKEN(STR_PCIE2_DEVICE))
+// UINT8 ComplTimeOut; //[Disable]\ Auto \ Default
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_COMPLTIMEOUT
+ endif;
+
+// UINT8 AriFwd; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_ARIFWD
+ endif;
+
+// UINT8 AtomOpReq; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_ATOMOPREQ
+ endif;
+
+// UINT8 AtomOpEgressBlk; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_ATOMOPEGRESSBLK
+ endif;
+
+// UINT8 IDOReq; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_IDOREQ
+ endif;
+
+// UINT8 IDOCompl; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_IDOCOMPL
+ endif;
+
+// UINT8 LtrReport; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_LTRREPORT
+ endif;
+
+
+// UINT8 E2ETlpPrBlk; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_E2ETLPPRBLK
+ endif;
+//============================================================
+
+ SEPARATOR
+ SUBTITLE(STRING_TOKEN(STR_PCIE2_LINK))
+//Gen2 Link Settings
+// UINT8 LnkSpeed; //[Auto]\ Force to 2.5 GHz
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_LNKSPEED
+ endif;
+
+
+// UINT8 ComplSos; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_CLOCKPM
+ endif;
+
+
+// UINT8 ComplSos; //[Disable]\ Enable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_COMPLSOS
+ endif;
+
+// UINT8 HwAutoWidth; //[Enable]\ Disable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_HWAUTOWIDTH
+ endif;
+
+// UINT8 HwAutoSpeed; //[Enable]\ Disable
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_HWAUTOSPEED
+ endif;
+ endform; //PCIBUS_FORM_PCI_EXPRESS2
+
+#endif//PCIBUS_FORM_PCI_EXPRESS2
+
+#endif//PCI_EXPRESS_GEN2_SUPPORT
+
+#endif//PCI_EXPRESS_SUPPORT
+//PCI Express Form END
+//-----------------------------------------------------------
+
+//-----------------------------------------------------------
+//Hotplug Form
+#if AMI_HOTPLUG_INIT_SUPPORT == 1
+ // Define HOTPLUG form
+
+#ifndef PCIBUS_FORM_PCIHP
+#define PCIBUS_FORM_PCIHP
+
+ form formid = AUTO_ID(PCI_HP_FORM_ID),
+ title = STRING_TOKEN(STR_PCI_HP_FORM);
+
+ SEPARATOR
+ SUBTITLE(STRING_TOKEN(STR_PCI_HP_FORM))
+ SEPARATOR
+
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_HOTPLUGENABLE
+ endif;
+
+ SEPARATOR
+
+#if PCI_FIXED_BUS_ASSIGNMENT == 0
+ suppressif ideqval SETUP_DATA.HotPlugEnable == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_BUSPADD
+ SUPPRESS_GRAYOUT_ENDIF
+#endif
+
+ //UINT8 IoPadd; // Disable \[ 4K]\ 8K \ 16K \ 32K
+ suppressif ideqval SETUP_DATA.HotPlugEnable == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_IOPADD
+ SUPPRESS_GRAYOUT_ENDIF
+
+ //Following fields stored in units of MB
+ //UINT8 Mmio32Padd; // Disable \ 1M \ 2M \4M \ 8M \[16M]\ 32M \ 64M \128M
+ suppressif ideqval SETUP_DATA.HotPlugEnable == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_MMIO32PADD
+ SUPPRESS_GRAYOUT_ENDIF
+
+ //UINT8 Mmio32PfPadd; // Disable \ 1M \ 4M \ 8M \[16M]\ 32M \ 64M \128M
+ suppressif ideqval SETUP_DATA.HotPlugEnable == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_MMIO32PFPADD
+ SUPPRESS_GRAYOUT_ENDIF
+
+
+//-----------------------------------------------------------
+#if ABOVE_4G_PCI_DECODE == 1
+
+ //for 512 and 1G 1 byte storege is not enough...
+ //UINT16 Mmio64Padd; //[Disable]\ 1M \ 4M \ 8M \ 16M \ 32M \ 64M \ 128M \ 256M \ 512M \ 1G
+ suppressif ideqval SETUP_DATA.HotPlugEnable == 0 OR
+ ideqval SETUP_DATA.Above4gDecode == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_MMIO64PADD
+ SUPPRESS_GRAYOUT_ENDIF
+
+ //UINT16 Mmio64PfPadd; //[Disable]\ 1M \ 4M \ 8M \ 16M \ 32M \ 64M \ 128M \ 256M \ 512M \ 1G
+ suppressif ideqval SETUP_DATA.HotPlugEnable == 0 OR
+ ideqval SETUP_DATA.Above4gDecode == 0;
+ grayoutif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ PCIBUS_ONEOF_MMIO64PFPADD
+ SUPPRESS_GRAYOUT_ENDIF
+
+#endif //ABOVE_4G_PCI_DECODE
+
+ endform; //PCI_HP_FORM_ID
+#endif // #ifndef PCIBUS_FORM_PCIHP
+
+#endif //HOTPLUG_SUPPORT
+//-----------------------------------------------------------
+
+//-----------------------------------------------------------
+#endif // FORM_SET_FORM
+
+//-----------------------------------------------------------
+#endif // ADVANCED_FORM_SET
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/PCI/PciBus.sdl b/Core/EM/PCI/PciBus.sdl
new file mode 100644
index 0000000..951bb78
--- /dev/null
+++ b/Core/EM/PCI/PciBus.sdl
@@ -0,0 +1,351 @@
+TOKEN
+ Name = "PciBus_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable PciBus support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "AMI_ROOT_BRIDGE_SUPPORT"
+ Value = "1"
+ Help = "The switch to include/exclude AMI Native PCI Root Bridge Implementation.\Set this switch to 'OFF' when using 3rd party PCI Root Bridgr Driver."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "AMI_HOTPLUG_INIT_SUPPORT"
+ Value = "0"
+ Help = "The switch to include/exclude AMI Root Hotplug Controller Initialization Protocol automatic creation.\Set this switch to 'OFF' when using 3rd party Root Hotplug Controller Initialization Protocol Driver."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "AMI_ROOT_BRIDGE_SUPPORT" "=" "1"
+ Token = "PCI_EXPRESS_SUPPORT" "=" "1"
+ Token = "HOTPLUG_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "PCI_BUS_MAJOR_VER"
+ Value = "02"
+ Help = "PCI BUS Module Major Version Number.\ DO NOT CHANGE THIS VALUE"
+ TokenType = Integer
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "PCI_BUS_MINOR_VER"
+ Value = "05"
+ Help = "PCI BUS Module Minor Version Number.\ DO NOT CHANGE THIS VALUE"
+ TokenType = Integer
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "PCI_BUS_REVISION"
+ Value = "02"
+ Help = "PCI BUS Module Major Version Number.\ DO NOT CHANGE THIS VALUE"
+ TokenType = Integer
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "PCI_BUS_VER_COMBINED"
+ Value = "$(PCI_BUS_MAJOR_VER)*100+ $(PCI_BUS_MINOR_VER)*10+$(PCI_BUS_REVISION)"
+ TokenType = Integer
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "HOTPLUG_SUPPORT"
+ Value = "0"
+ Help = "Enables / Disables Pci Bus Driver Native PCI Hotplug support"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PCI_EXPRESS_SUPPORT"
+ Value = "1"
+ Help = "Enables / Disables Pci Bus Driver Native PCI Express support"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PCI_EXPRESS_GEN2_SUPPORT"
+ Value = "1"
+ Help = "Enables / Disables Pci Bus Driver Native PCI Express Gen2 support"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "PCI_EXPRESS_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "PCI_EXPRESS_GEN3_SUPPORT"
+ Value = "1"
+ Help = "Enables / Disables Pci Bus Driver Native PCI Express Gen3 support"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Token = "PCI_EXPRESS_SUPPORT" "=" "1"
+ Token = "PCI_EXPRESS_GEN2_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "PCI_X_SUPPORT"
+ Value = "0"
+ Help = "Enables / Disables Pci Bus Driver Native PCI-X support"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PCI_FIXED_BUS_ASSIGNMENT"
+ Value = "0"
+ Help = "Forces PCI Bus driver try to assign buses \according to the settings in Veb PCI Wizard"
+ TokenType = Boolean
+ TargetH = Yes
+ Range = "On/Off"
+End
+
+TOKEN
+ Name = "PCI_DEV_REVERSE_SCAN_ORDER"
+ Value = "0"
+ Help = "Forces PCI Bus driver to scan PCI devices on the bus in opposite order.\If set to ON scan from Dev 31 down to 0.\If Set to OFF scan from Dev 0 up to 31."
+ TokenType = Boolean
+ TargetH = Yes
+ Range = "On/Off"
+End
+
+TOKEN
+ Name = "PCI_SCAN_FULL_BUS_RANGE"
+ Value = "0"
+ Help = "Forces PCI Bus driver Scan ALL PCI Buses in the\Bus Range provided by the Root Bridge driver.\If disabled will scan only consecutive PCI Buses\spawn buy the Root Bridge and save some boot \time on scanning nonexistent buses."
+ TokenType = Boolean
+ TargetH = Yes
+ Range = "On/Off"
+End
+
+TOKEN
+ Name = "PCI_4K_RESOURCE_ALIGNMENT"
+ Value = "1"
+ Help = "Forces PCI Bus driver to allocate at least 4K \resource buffer for each resource request lesser \than 4K."
+ TokenType = Boolean
+ TargetH = Yes
+ Range = "On/Off"
+End
+
+TOKEN
+ Name = "SRIOV_SUPPORT"
+ Value = "0"
+ Help = "Enables Single Root IO Virtualization (SRIOV) Support."
+ TokenType = Boolean
+ TargetH = Yes
+ Range = "On/Off"
+ Token = "PCI_EXPRESS_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "PCI_DEVICE_IO_RESOURCE_THRESHOLD"
+ Value = "0xFFFF"
+ Help = "Forces PCI Bus driver to disable Device if it's IO resource request exceeds this value"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "Up to 64K"
+End
+
+TOKEN
+ Name = "PCI_DEVICE_32BIT_RESOURCE_THRESHOLD"
+ Value = "0xFFFFFFFF"
+ Help = "Forces PCI Bus driver to disable Device if it's 32bit resource request exceeds this value"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "Up to 4G"
+End
+
+TOKEN
+ Name = "PCI_DEVICE_64BIT_RESOURCE_THRESHOLD"
+ Value = "0x3FFFFFFFF"
+ Help = "Forces PCI Bus driver to disable Device if it's 64bit resource request exceeds this value"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "Up to 16G"
+End
+
+TOKEN
+ Name = "ABOVE_4G_PCI_DECODE"
+ Value = "0"
+ Help = "Tells if Chipset supports decoding of PCI\resources in Above 4G Address Space.\Sets EFI_PCI_HOST_BRIDGE_MEM64_DECODE in Allocation Attributes."
+ TokenType = Boolean
+ TargetH = Yes
+ Range = "ON or OFF"
+End
+
+TOKEN
+ Name = "COMBINE_MEM_PMEM"
+ Value = "0"
+ Help = "Tells if Chipset correctly supports PF MMIO\if set PF MMIO will be decoded through the same resource\window as NONE PF MMIO. PF MEM BASE and PF MEM LIMIT register pare will not be used."
+ TokenType = Boolean
+ TargetH = Yes
+ Range = "ON or OFF. Default is OFF!"
+End
+
+TOKEN
+ Name = "PCI_MMIO_RES_TOP_ALLIGN"
+ Value = "0"
+ Help = "Tells what resource allocation rule to use.\ OFF - Biggest resource alligned to the bottom of the window,\ ON - to the TOP."
+ TokenType = Boolean
+ TargetH = Yes
+ Range = "ON or OFF. Default is OFF!"
+End
+
+TOKEN
+ Name = "PCI_AMI_COMBINE_MEM_PMEM32"
+ Value = "0"
+ Help = "Tells to map 32 bit sized PF MMIO BARs trough NON PF MMIO Bridge registers."
+ TokenType = Boolean
+ TargetH = Yes
+ Range = "ON or OFF. Default is OFF!"
+End
+
+TOKEN
+ Name = "PCI_T_RST"
+ Value = "1000"
+ Help = "Defines duration of SEC_BUS_RESET signal assertion in nS"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PCI_T_RST_RECOVERY"
+ Value = "100000"
+ Help = "Defines duration of RESET_RECOVERY after SEC_BUS_RESETsignal DE-assertion in nS"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEBS"
+ Value = "$(PCIEX_BASE_ADDRESS)"
+ Help = "Pci Express Base Aliase to use in PCIeAccess.ASL"
+ TokenType = Integer
+ TargetASL = Yes
+ Token = "AMI_ROOT_BRIDGE_SUPPORT" "=" "1"
+ Token = "PCI_EXPRESS_SUPPORT" "=" "1"
+ Token = "HOTPLUG_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "PCIBOARDLIB"
+ Value = "$(BUILD_DIR)\PciBoard.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "PCIBUS_DIR"
+End
+
+MODULE
+ Help = "Includes PciBus.mak to Project"
+ File = "PciBus.mak"
+End
+
+ELINK
+ Name = "$(PCIBUS_DIR)\PciBus.sd"
+ Parent = "SETUP_DEFINITIONS"
+ Priority = 0
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PciBus.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "InitPciBusStrings,"
+ Parent = "SetupStringInit"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PciBus.sdb"
+ Parent = "SETUP_SDBS"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PciRootBridge.ffs"
+ Parent = "FV_MAIN"
+ Token = "AMI_ROOT_BRIDGE_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "PCIBUSSRCLIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(PCIBUS_DIR)\PciBusSrc$(ARCH).lib"
+ Parent = "PCIBUSSRCLIB"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "OEM_SKIP_PCI_DEVICE"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "OEM_PROGRAM_PCI_DEVICE"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "OEM_PCI_DEVICE_SET_ASPM"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "OEM_PCI_DEVICE_SET_LNK_SPEED"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "OEM_PCI_DEVICE_GET_OPT_ROM"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "OEM_PCI_ATTRIBUTES"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "OEM_PCI_DEVICE_OUT_OF_RESOURCES"
+ InvokeOrder = ReplaceParent
+End
diff --git a/Core/EM/PCI/PciBus.uni b/Core/EM/PCI/PciBus.uni
new file mode 100644
index 0000000..a7fa8ee
--- /dev/null
+++ b/Core/EM/PCI/PciBus.uni
Binary files differ
diff --git a/Core/EM/PCI/PciBusSetup.c b/Core/EM/PCI/PciBusSetup.c
new file mode 100644
index 0000000..8f44c20
--- /dev/null
+++ b/Core/EM/PCI/PciBusSetup.c
@@ -0,0 +1,97 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/PciBus/PciBusSetup.c 2 9/25/08 11:54a Yakovlevs $
+//
+// $Revision: 2 $
+//
+// $Date: 9/25/08 11:54a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/PciBus/PciBusSetup.c $
+//
+// 2 9/25/08 11:54a Yakovlevs
+// Added PciBus Driver version display and Screen update routines.
+//
+// 1 3/12/07 12:07p Yakovlevs
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: PciBusSetup.c
+//
+// Description: Pci Bus Setup Routines
+//
+// NOTE: Use this hook to dynamically change PCI BUS Driver Setup screen
+// Strings.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <AmiLib.h>
+#include <AmiDxeLib.h>
+#include <Setup.h>
+#include <SetupStrTokens.h>
+#include <Protocol\PciIo.h>
+#include <Token.h>
+
+// Function Definitions
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitBoardStrings
+//
+// Description: This function initializes the board related setup option values
+//
+// Input: HiiHandle Handle to HII database
+// Class Indicates the setup class
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+InitPciBusStrings(
+ EFI_HII_HANDLE HiiHandle,
+ UINT16 Class
+)
+{
+ if(Class == ADVANCED_FORM_SET_CLASS){
+ InitString(HiiHandle, STRING_TOKEN(STR_PCI_DRIVER_VER), L"V %d.%02d.%02d",
+ PCI_BUS_MAJOR_VER, PCI_BUS_MINOR_VER, PCI_BUS_REVISION);
+ }
+ return;
+}
+
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/PCI/PciBusSrc.chm b/Core/EM/PCI/PciBusSrc.chm
new file mode 100644
index 0000000..3c64f7c
--- /dev/null
+++ b/Core/EM/PCI/PciBusSrc.chm
Binary files differ
diff --git a/Core/EM/PCI/PciBusSrc.cif b/Core/EM/PCI/PciBusSrc.cif
new file mode 100644
index 0000000..53f1371
--- /dev/null
+++ b/Core/EM/PCI/PciBusSrc.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "PciBus Sources"
+ category = ModulePart
+ LocalRoot = "Core\EM\PCI\"
+ RefName = "PciBusSrc"
+[files]
+"PciBusSrc.chm"
+"PciBusSrc.sdl"
+"PciBusSrc.mak"
+"PciBus.c"
+"PciHostBridge.c"
+"DeviceIo.c"
+<endComponent>
diff --git a/Core/EM/PCI/PciBusSrc.mak b/Core/EM/PCI/PciBusSrc.mak
new file mode 100644
index 0000000..0842d12
--- /dev/null
+++ b/Core/EM/PCI/PciBusSrc.mak
@@ -0,0 +1,82 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Core/Modules/PciBus/PciBusSrc.mak 5 1/13/10 3:25p Felixp $
+#
+# $Revision: 5 $
+#
+# $Date: 1/13/10 3:25p $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Core/Modules/PciBus/PciBusSrc.mak $
+#
+# 5 1/13/10 3:25p Felixp
+# Dependency from token.h is added
+#
+# 4 4/28/09 5:51p Yakovlevs
+#
+# 3 11/14/08 1:16p Yakovlevs
+# Changed the way PciRootBridge Module gets build.
+#
+# 2 10/01/08 7:12p Yakovlevs
+# Updated AMI FUNC HEADER information
+#
+# 1 3/12/07 12:02p Yakovlevs
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: PsiBusSrc.mak
+#
+# Description: Make file to build PciBus Driver Sources.
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+PCIBUS_SOURCE_OBJECTS=\
+$(BUILD_DIR)\$(PCIBUS_DIR)\PciBus.obj\
+!IF "$(AMI_ROOT_BRIDGE_SUPPORT)"=="1"
+$(BUILD_DIR)\$(PCIBUS_DIR)\PciHostBridge.obj\
+$(BUILD_DIR)\$(PCIBUS_DIR)\DeviceIo.obj\
+!ENDIF
+
+$(PCIBUSSRCLIB) : PciBusSrc
+
+PciBusSrc : $(BUILD_DIR)\PciBusSrc.mak PciBusSrcBin
+
+$(BUILD_DIR)\PciBusSrc.mak : $(PCIBUS_DIR)\$(@B).cif $(PCIBUS_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(PCIBUS_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+PciBusSrcBin :
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\PciBusSrc.mak all\
+ MAKEFILE=$(PCIBUS_DIR)\PciBusSrc.mak\
+ "OBJECTS=$(PCIBUS_SOURCE_OBJECTS)"\
+ "EXT_HEADERS=$(BUILD_DIR)\token.h"\
+ TYPE=LIBRARY
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#********************************************************************** \ No newline at end of file
diff --git a/Core/EM/PCI/PciBusSrc.sdl b/Core/EM/PCI/PciBusSrc.sdl
new file mode 100644
index 0000000..8d50c1f
--- /dev/null
+++ b/Core/EM/PCI/PciBusSrc.sdl
@@ -0,0 +1,37 @@
+TOKEN
+ Name = "PciBusSrc_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable PciBusSrs support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "PCI_BUS_DEBUG_MESSAGES"
+ Value = "0"
+ Help = "A switch to enable PciBus Driver Debug messages over Serial Port."
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEBUG_CODE" "=" "1"
+End
+
+TOKEN
+ Name = "PCI_BUS_SKIP_BRG_RECURSIVELY"
+ Value = "0"
+ Help = "A switch to Disable enumeration for all Bridge children if bridge set to be skipped from enumeration."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+MODULE
+ Help = "Includes PciBusSrs.mak to Project"
+ File = "PciBusSrc.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PciBusSrc.lib"
+ Parent = "$(PCIBUS_DIR)\PciBusSrc$(ARCH).lib"
+ InvokeOrder = ReplaceParent
+End
diff --git a/Core/EM/PCI/PciHostBridge.c b/Core/EM/PCI/PciHostBridge.c
new file mode 100644
index 0000000..873101a
--- /dev/null
+++ b/Core/EM/PCI/PciHostBridge.c
@@ -0,0 +1,3814 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/PciBus/PciHostBridge.c 48 9/10/12 12:49p Yakovlevs $
+//
+// $Revision: 48 $
+//
+// $Date: 9/10/12 12:49p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/PciBus/PciHostBridge.c $
+//
+// 48 9/10/12 12:49p Yakovlevs
+// Minor changes fix for multi host system
+//
+// 47 7/17/12 1:48p Yakovlevs
+//
+// 45 7/16/12 3:10p Yakovlevs
+// [TAG] EIP90378
+// [Category] Improvement
+// [Description] Pci Root bridge driver should be able to access MMIO
+// above 4G
+// [Files] PciHostBridge.c
+//
+// 44 6/26/12 6:24p Yakovlevs
+// [TAG] EIP90378
+// [Category] Improvement
+// [Description] Pci Root bridge driver should be able to access MMIO
+// above 4G
+// [Files] PciHostBridge.c
+//
+// 43 5/22/12 4:50p Yakovlevs
+// Removing wrong comment
+//
+// 42 5/01/12 5:05p Yakovlevs
+// [TAG] EIP84986
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Yellow mark issue in windows device manager on
+// PCIe slots if only 2 CPU for potter city platform.
+// [RootCause] For multy root system where root socets partialy
+// populated SDL data interfered with
+// Actual Hardware configuration.
+// [Solution] Allow control flow keep going when certain
+// ERROR_STATUS received.
+// [Files] PciBus.c; PciHostBridge.c
+//
+// 41 2/27/12 4:47p Yakovlevs
+//
+// 40 11/23/11 11:08a Yakovlevs
+// [TAG] EIP76109
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] VIA VX900 / VX11 CopyMem issue
+// [RootCause] When Src and Dst buffers overlaps
+// size of copy operation was determined incorrectly.
+// [Solution] Added additional cases with negative increments
+// [Files] PciHostBridge.c
+//
+// 39 11/10/11 12:26p Yakovlevs
+// [TAG] EIP72122
+// [Category] Improvement
+// [Description] If system uses UEFI GOP driver, then BIOS does not
+// report legacy VGA resources to ACPI.
+//
+// [Files] PciHostBridge.c
+//
+// 38 8/30/11 2:27p Yakovlevs
+// [TAG] EIP68120
+// [Category] Bug Fix
+// [Symptom] When new PCIe card be plugged, It hangs at 0x94 before
+// adjusting new memory ceiling to nvram with CORE4651.
+// [RootCause] AdjustMmioOverlap() was not called if builtin allocation
+// function returned EFI_ERROR.
+// [Solution] Reorganize code to call this function before returning
+// ERROR Status.
+// [Files] PciHostBridge.c
+//
+// 37 8/02/11 4:13p Yakovlevs
+// [TAG] EIP66216
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Hotplug resource padding not working for ROOT bridges other
+// than 0
+// [RootCause] Hot plug slots was incorrectly associated alvays withthe
+// RootBridge #0
+// [Solution] Changed algorithm to beter distinguish between Root
+// Bridges. Added debug messagers to monitor HPC_LOCATION_DATA.
+// [Files] PciBus.c; PciHostBridge.c.
+//
+// 36 7/08/11 5:00p Yakovlevs
+// [TAG] EIP64414
+// [Category] Improvement
+// [Description] During PCIOUTOF RESOURCE Condition,resource freeing is
+// not done
+// [Files] PciHostBridge.c
+//
+// 35 6/28/11 5:29p Yakovlevs
+// [TAG] EIP 60123
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Resource padding is not functional for PCIe hot-plug.
+// [RootCause] In hot plug function was missed changes in BusXlat
+// Structure.
+// [Solution] Xlat header gets incremented based on AMI_BOARD_INFO
+// driver wersion.
+// [Files] PciHostBridge.c
+//
+// 34 5/04/11 6:15p Yakovlevs
+// Fixed potential issue with EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE
+// attribute some drivers may set.
+//
+// 33 4/05/11 11:40a Yakovlevs
+// [TAG] EIP 38174
+// [Category] New Feature
+// [Description] Generic support to handle PCI OUT OF RESOURDCES added.
+// [Files] PciBus.c; PciHostBridge.c;
+//
+// 32 1/20/11 3:07p Yakovlevs
+// [TAG] EIP45278
+// [Category] Improvement
+// [Description] Added PCI_MMIO_RES_TOP_ALLIGN token to control Resource
+// allocation algorithm selection.
+// [Files] PciBus.c; PciHostBridge.c; PciBus.sdl.
+//
+// 31 1/13/11 1:30p Yakovlevs
+//
+// 30 1/13/11 1:28p Yakovlevs
+// [TAG] EIP45278
+// [Category] Improvement
+// [Description] Changed default resource allocation algorithm to work
+// more efficiently.
+// [Files] PciBus.c; PciHostBridge.c
+//
+// 28 8/23/10 12:29p Yakovlevs
+// Fixed issue with incorrect settings COMPATIBILITY ATTRIBUTES was
+// missing Legacy VGA_ATTRIBUTES.
+//
+// 27 8/16/10 1:07p Yakovlevs
+// Updated ClaimMmioResources to use MMIO resources as-is if AllocType is
+// set to EfiGcdAllocateAddress. For this chipset, each root bridge is
+// programmed with base and limit values for 32bit and 64bit MMIO. The
+// root bridge will only decode addresses within these ranges. For this
+// reason, the Base and Limit values passed to the PCI Bus driver should
+// be used as-is and not modified.
+//
+// 26 3/01/10 6:18p Yakovlevs
+// Generic Multi-ROOT Support Added.
+//
+// 25 9/22/09 6:10p Yakovlevs
+// 3. Generic support for multiple root bridges resources reporting to
+// ACPI DSDT Root Bridge Object (EIP 23548 Support MMIO allocation above
+// 4GB, if devices are capable)
+//
+// 24 8/21/09 4:25p Yakovlevs
+// Added Print out Message in DEBUG_MODE with PCI BUS Driver Version.
+// Added Initialization of ImageHandle field in Host Bridge and Root
+// Bridge Structures. New PciHostBridge.h required.
+//
+// 23 4/28/09 5:50p Yakovlevs
+// Ami Board Info Protocol moved into separate Core\AmiBoardInfo
+// subcomponent.
+//
+// 22 3/27/09 11:48a Yakovlevs
+//
+// 21 3/23/09 2:27p Yakovlevs
+// ADDED support for PCI Root HPC INit Protocol generation based on AMI
+// SDL output.
+//
+// 20 1/30/09 1:01p Yakovlevs
+// Changed gPciHost to gPciRbHost to avoid name collision gPCiHost
+// variable name been differently used in PciBus.c
+//
+// 19 11/21/08 7:01p Yakovlevs
+//
+// 18 11/14/08 3:34p Yakovlevs
+// Removed EFI_DEADLOOP() used for debug
+//
+// 17 11/14/08 1:28p Yakovlevs
+// Implemented AMI Board Info Protocol which has *.inc OUTPUTs generated
+// by AMISDL tool. To keep it in one place and Make PciBus Driver use it.
+//
+// 16 11/03/08 2:35p Yakovlevs
+//
+// 15 11/03/08 2:33p Yakovlevs
+// Fixed EIP 17068: AdjustMmioOverlap() has to be called each boot.
+//
+// 14 10/01/08 7:12p Yakovlevs
+// Updated AMI FUNC HEADER information
+//
+// 13 9/24/08 6:08p Yakovlevs
+// New features added. Multy host support using VeB wizard. No initial
+// porting required.
+//
+// 12 4/29/08 6:56p Yakovlevs
+// Added mechanism to suppress PCI BUs driver debug messages(Latest
+// PciBus.sdl and PciBus.h required).
+//
+// 11 2/19/08 3:38p Felixp
+//
+// 10 2/13/08 1:02p Yakovlevs
+// Fixed issue with incorrect usage of GCD AllocateXX services.
+//
+// 9 10/23/07 5:30p Felixp
+// VC8 warnings fixed
+//
+// 8 8/07/07 2:45p Felixp
+// Additional Status Codes added
+//
+// 7 4/19/07 12:59p Felixp
+// Added Chipset specific call to set RB Attributes
+//
+// 5 4/17/07 11:55a Yakovlevs
+//
+// 4 4/17/07 11:19a Yakovlevs
+//
+// 3 4/17/07 11:18a Yakovlevs
+// Added Chipset specific call to set RB Attributes
+//
+// 2 4/13/07 6:23p Yakovlevs
+// make use of LibGetDxeSvcTbl() instead of manualy getting the DXE Svc
+// Tbl pointer.
+//
+// 1 3/12/07 12:02p Yakovlevs
+//
+// 9 12/28/06 7:20p Yakovlevs
+//
+// 8 12/19/06 12:07p Yakovlevs
+// PciRb->Map; Unmap implementation fixes
+//
+// 7 10/24/06 12:18p Yakovlevs
+// Removed EFI_MEMORY_RUNTIME attribute from PCI BUS resource request.
+//
+// 6 9/20/06 4:47p Felixp
+// x64 warnings fixed
+//
+// 5 6/01/06 12:17p Yakovlevs
+// Handling of memceil logic added.
+//
+// 4 5/23/06 12:59a Felixp
+// Bug fix in HbResAllocStartBusEnumeration - invalid error condition
+// check
+//
+// 3 5/19/06 10:51p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 2 4/07/06 2:33p Felixp
+// Bug fix in resource allocation (AllocateResources): Attributes for
+// Prefetchable memory changed from WB to WT
+//
+// 1 4/03/06 5:32p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: PciHostBridge.c
+//
+// Description: AMI's Native Root Bridge Protocol Implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Token.h>
+#include <AmiDxeLib.h>
+#include <PciHostBridge.h>
+#include <Protocol\DevicePath.h>
+#include <AmiCspLib.h>
+#include "PciPort.h"
+#include "PciSetup.h"
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gAmiBoardProtocol
+//
+// Description: Ami Board Info Protocol Instance.
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+AMI_BOARD_INFO_PROTOCOL *gAmiBoardInfoProtocol=NULL;
+
+
+
+//**********************************************************************
+//Global Vars and Constants been used
+//**********************************************************************
+
+//GUIDs
+EFI_GUID gHbResAllocProtocolGuid=EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GUID;
+EFI_GUID gRbIoProtocolGuid=EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID;
+EFI_GUID gDevPathProtocolGuid=EFI_DEVICE_PATH_PROTOCOL_GUID;
+EFI_GUID gDeviceIoProtocolGuid=DEVICE_IO_PROTOCOL;
+EFI_GUID gAmiBoardInfoGuid=AMI_BOARD_INFO_PROTOCOL_GUID;
+
+#if AMI_HOTPLUG_INIT_SUPPORT == 1
+EFI_GUID gHotPlugInitProtocolGuid=EFI_PCI_HOT_PLUG_INIT_PROTOCOL_GUID;
+#endif
+
+
+
+//**********************************************************************
+//Variables
+
+T_ITEM_LIST gRootBusDb={0,0,NULL};
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: gPciHost
+//
+// Description: Array of PCI Host Bridge Data Sructures.
+// Initial data point for PCI Subsystem.
+//
+// Notes: See PCI_HOST_BRG_DATA. Number of elements in gPciHost[] array
+// defined by NB_NUMBER_OF_HOST_BRG in NB.sdl
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+PCI_HOST_BRG_DATA gPciRbHost[NB_NUMBER_OF_HOST_BRG];
+
+//TODO//TODO //TODO //TODO //TODO
+//Change this to reference VeB output EIP 24469
+//TEMP Hardcoding of ASL RB Device Object NAME
+#if AMI_BOARD_VER_COMBINED < 100
+CHAR8 *RbAslName[]={"PCI0","PCFF"};
+#endif
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: *gPciSetupData; PciSetupDataBuffer
+//
+// Description: Global Setup Variable to get the setup settings pointer.
+//
+// Notes: PCI_SETUP_DATA
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+PCI_SETUP_DATA gRbSetupData;
+
+UINT64 TmpBot[raMaxRes]={0,0,0,0};
+UINT64 TmpTop[raMaxRes]={0,0,0,0};
+
+//**********************************************************************
+//Function Prototypes needed forward declaration
+//**********************************************************************
+EFI_STATUS ConvertMemoryMap(EFI_HANDLE ImgHandle, EFI_HANDLE CntrHandle OPTIONAL);
+EFI_STATUS CreateRootBusData();
+EFI_STATUS HpcInitProtocol(PCI_HOST_BRG_DATA *HostBrg);
+BOOLEAN IsPowerOfTwo(UINT64 Value);
+VOID RbReadyToBoot(IN EFI_EVENT Event, IN VOID *Context);
+
+
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//PCI Root Bridge Driver Entry Point
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitializePCIHostBridge()
+//
+// Description: This function is the entry point for PCI Root Bridge Driver.
+// Since PCI Root Bridge Driver follows EFI 1.1 driver model in it's entry
+// point it will initialize some global data and install
+// EFI_DRIVER_BINDING_PROTOCOL.
+//
+// Input:
+// EFI_HANDLE ImageHandle Image handle.
+// EFI_SYSTEM_TABLE *SystemTable Pointer to the EFI system table.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS When everything is going on fine!
+// EFI_NOT_FOUND When something required is not found!
+// EFI_DEVICE_ERROR When the device is not responding!
+//
+// Notes:
+// Entry Points are used to locate or install protocol interfaces and
+// notification events.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InitializePCIHostBridge(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ UINTN i,j,n;
+ PCI_HOST_BRG_DATA *hb;
+ PCI_ROOT_BRG_DATA *rb;
+ EFI_EVENT ReadyToBootEvent=NULL;
+//-----------------------------------------
+
+ //Init Lib globals...
+ InitAmiLib(ImageHandle,SystemTable);
+ PROGRESS_CODE(DXE_NB_HB_INIT);
+
+ //Print PCI Bus Driver Version
+ PCI_TRACE((TRACE_PCI,"\nPciRootBrg: Initializing... PCI Driver Version %d.%d.%d\n", PCI_BUS_MAJOR_VER, PCI_BUS_MINOR_VER, PCI_BUS_REVISION));
+
+ Status = pBS->LocateProtocol(&gAmiBoardInfoGuid, NULL,(VOID**)&gAmiBoardInfoProtocol);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Fail to Locate AMI_BOARD_INFO_PROTOCOL Status=%r\n",Status));
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ //Zerouot Privete HOST BRG data structure and Setup Data Buffer
+ pBS->SetMem(&gPciRbHost[0], sizeof(gPciRbHost), 0);
+ pBS->SetMem(&gRbSetupData, sizeof(PCI_SETUP_DATA), 0);
+
+ //Get Setup Data it has some Root Brg related features
+ BrdGetPciSetupData(&gRbSetupData);
+
+ //Update GCD resource map with static Chipset Specific Resources decoded.
+ Status=ConvertMemoryMap(ImageHandle,NULL);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Parse BusXlatTable extracting ROOT BRIDGE data from there.
+ Status=CreateRootBusData();
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //try to map available roots from gRootBusDb.Items to
+ //the corresponded HOST abstraction
+ //each HOST has to have a separate instance of ResourceAllocation Protocol
+ //each ROOT will have a separate instance of RootBridgeIo Protocol.
+ //This "FOR" loop will construcr HOST/ROOT bridge infrastructure and will
+ //try to map each root collected in call CreateRootBusData() to it's correcponded HOST
+ //using HbCspMapRootBrgToHost() CSP hook. For MULTY-HOST systems this hook must be ported
+ for(i=0;i<gRootBusDb.ItemCount; i++){
+ PCI_BUS_XLAT_HDR *roothdr=(PCI_BUS_XLAT_HDR*)gRootBusDb.Items[i];
+ PCI_BUS_XLAT_HDR *nexthdr=NULL;
+ ASLR_QWORD_ASD *busrd;
+ UINT64 aa=0, ra=0;
+ //---------------------------------------
+ //fill Allocation Atributes Property.
+ //Based on Token values of COMBINE_MEM_PMEM and ABOVE_4G_PCI_DECODE
+ if(COMBINE_MEM_PMEM) aa |= EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;
+ if(ABOVE_4G_PCI_DECODE){
+ aa |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
+ ra |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+ }
+
+ if(roothdr->BusBuild ==0) ra |= (PCI_ROOT_COMPATIBILITY_ATTRIBUTES | PCI_ROOT_VGA_ATTRIBUTES);
+
+ //Call Chipset Specific function to map this ROOT to HOST.
+ //And override Allocation attributes based on TOKEN VALUES.
+ //Have no clue how to do it automatically though..........
+ j=HbCspMapRootBrgToHost(roothdr, &aa, &ra);
+
+ //If we got NUMBER
+ if(j>=NB_NUMBER_OF_HOST_BRG) {
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Root2Host mapping [HOST=%d >= MAX_HOSTs=%d; ROOT %X|%X \n ",
+ j, NB_NUMBER_OF_HOST_BRG, roothdr->BusBuild, roothdr->BusRun ));
+ ASSERT_EFI_ERROR(EFI_INVALID_PARAMETER);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ hb=&gPciRbHost[j];
+
+ //Check if setup allows us to decode PCI Space above 4G
+ if( gRbSetupData.Above4gDecode == 0 ) aa &= (~(EFI_PCI_HOST_BRIDGE_MEM64_DECODE));
+
+ hb->AllocAttrib=aa;
+
+ //Allocate memory for Root Bridge Data structure;
+ rb=MallocZ(sizeof(PCI_ROOT_BRG_DATA));
+ ASSERT(rb);
+ if(!rb)return EFI_OUT_OF_RESOURCES;
+
+ //Save BusXlatEntry for this Root
+ rb->BusXlatEntry=roothdr;
+
+#if AMI_BOARD_VER_COMBINED >= 100
+ //Change this to reference VeB output EIP 24469
+ rb->RbAslName=(CHAR8*)((UINT8*)(roothdr+1)+2); //Including DEV_FN 1Byte + terminator 1 byte.
+#endif
+
+ //Save returned Attributes
+ rb->Supports=ra;
+
+ //Get Next root header to determine current root Build Bus range
+ if(i<gRootBusDb.ItemCount-1) nexthdr=(PCI_BUS_XLAT_HDR*)gRootBusDb.Items[i+1];
+
+ //Get memory for Bus Resource Descriptor
+ busrd=MallocZ(sizeof(ASLR_QWORD_ASD));
+ //fill Bus Resource descriptor fields
+ busrd->Hdr.HDR=0x8A;
+ busrd->Hdr.Length=0x2B;
+ busrd->Type=ASLRV_SPC_TYPE_BUS;
+ busrd->_GRA=1;
+ busrd->_MIN=roothdr->BusBuild;
+ //if this is last ROOT xlat entry make it MAX Bus Number;
+ if(nexthdr == NULL) busrd->_MAX = 0xFF;
+ else busrd->_MAX=nexthdr->BusBuild-1;
+ busrd->_LEN = busrd->_MAX - busrd->_MIN + 1;
+
+ Status=AppendItemLst((T_ITEM_LIST*)&hb->RbInitCnt,rb);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ Status=AppendItemLst((T_ITEM_LIST*)&rb->ResInitCnt,busrd);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ //Init Number of nitial Host Bridge Structures;
+ for(i=0,n=0; i<NB_NUMBER_OF_HOST_BRG; i++){
+ hb=&gPciRbHost[i];
+ hb->ImageHandle=ImageHandle;
+ //Init Host Bridge Private Data instance
+ //here goes Allocation Arrtibutes
+ //hb->AllocAttrib=gHbAllocAttribTbl[i];
+
+ //Init Prtocol Functions
+ hb->ResAllocProtocol.NotifyPhase=HbResAllocNotifyPhase;
+ hb->ResAllocProtocol.GetNextRootBridge=HbResAllocGetNextRootBridge;
+ hb->ResAllocProtocol.GetAllocAttributes=HbResAllocGetAllocAttributes;
+ hb->ResAllocProtocol.StartBusEnumeration=HbResAllocStartBusEnumeration;
+ hb->ResAllocProtocol.SetBusNumbers=HbResAllocSetBusNumbers;
+ hb->ResAllocProtocol.SubmitResources=HbResAllocSubmitResources;
+ hb->ResAllocProtocol.GetProposedResources=HbResAllocGetProposedResources;
+ hb->ResAllocProtocol.PreprocessController=HbResAllocPreprocessController;
+
+ hb->AllocPhase=-1;
+ //hb->PciSegment=HbCspGetPicSegment();
+
+ //Install HB res Alloc Protocol on this HOST BRG
+ Status=pBS->InstallMultipleProtocolInterfaces(
+ &hb->HbHandle, //it was NULL so it going to be a new handle
+ &gHbResAllocProtocolGuid, &hb->ResAllocProtocol,//RbIo Protocol GUID - I/F pare
+ NULL); //terminator
+
+
+ //Init Root Bridge objects of Current Host Bridge
+ //hb->RbInitCnt=gRbCountTbl[i]+1;
+ for(j=0; j<hb->RootBridgeCount; j++,n++){
+ ACPI_HID_DEVICE_PATH *rbdp;
+ //-----------------------------------
+ //Reinit rb pointer for this loop
+ rb=hb->RootBridges[j];
+ rb->ImageHandle=ImageHandle;
+
+#if AMI_BOARD_VER_COMBINED < 100
+ //Change this to reference VeB output EIP 24469
+ rb->RbAslName=RbAslName[j];
+#endif
+
+ //Init Root Bridge Private Data instance
+ rbdp=Malloc(sizeof(ACPI_HID_DEVICE_PATH)+sizeof(EFI_DEVICE_PATH_PROTOCOL));
+ ASSERT(rbdp);
+ if(!rbdp)return EFI_OUT_OF_RESOURCES;
+
+ rb->DevPath=&rbdp->Header;
+ //generate RB device path
+ rbdp->Header.Type=ACPI_DEVICE_PATH;
+ rbdp->Header.SubType=ACPI_DP;
+ SET_NODE_LENGTH(&rbdp->Header,ACPI_DEVICE_PATH_LENGTH);
+ rbdp->HID=EISA_PNP_ID(0x0A03);
+ rbdp->UID=(UINT32)j;
+
+ rbdp++;
+ rbdp->Header.Type=END_DEVICE_PATH;
+ rbdp->Header.SubType=END_ENTIRE_SUBTYPE;
+ SET_NODE_LENGTH(&rbdp->Header,END_DEVICE_PATH_LENGTH);
+
+ //FillOut Capabilities
+ //rb->Supports=gRbSupportsTbl[n];
+ //if Host bridge has capability to decode 64 bit address space we
+ //will add EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE Capability bit
+ //to the RootBridge Supported features Set.
+ if(hb->AllocAttrib & EFI_PCI_HOST_BRIDGE_MEM64_DECODE)
+ rb->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+
+ //Fill out Protocol Interface for RB Protocol Member functions
+ rb->RbIoProtocol.ParentHandle=hb->HbHandle;
+ rb->RbIoProtocol.PollMem=PollMem;
+ rb->RbIoProtocol.PollIo=PollIo;
+ rb->RbIoProtocol.Mem.Read=PciMemRead;
+ rb->RbIoProtocol.Mem.Write=PciMemWrite;
+ rb->RbIoProtocol.Io.Read=PciIoRead;
+ rb->RbIoProtocol.Io.Write=PciIoWrite;
+ rb->RbIoProtocol.Pci.Read=PciRead;
+ rb->RbIoProtocol.Pci.Write=PciWrite;
+ rb->RbIoProtocol.CopyMem=CopyMem;
+ rb->RbIoProtocol.Map=Map;
+ rb->RbIoProtocol.Unmap=Unmap;
+ rb->RbIoProtocol.AllocateBuffer=AllocateBuffer;
+ rb->RbIoProtocol.FreeBuffer=FreeBuffer;
+ rb->RbIoProtocol.Flush=Flush;
+ rb->RbIoProtocol.GetAttributes=GetAttributes;
+ rb->RbIoProtocol.SetAttributes=SetAttributes;
+ rb->RbIoProtocol.Configuration=Configuration;
+ rb->RbIoProtocol.SegmentNumber=(UINT32)HbCspGetPciSegment(i,j);
+ rb->Owner=hb;
+
+ rb->DevIoProtocol=ConstructDeviceIoProtocol(&rb->RbIoProtocol, rb->DevPath);
+ ASSERT(rb->DevIoProtocol);
+ if(!rb->DevIoProtocol) return EFI_OUT_OF_RESOURCES;
+
+ Status=pBS->InstallMultipleProtocolInterfaces(
+ &rb->RbHandle, //it was NULL so it going to be a new handle
+ &gRbIoProtocolGuid, &rb->RbIoProtocol, //RbIo Protocol GUID - I/F pare
+ &gDevPathProtocolGuid, rb->DevPath, //DevPath Protocol GUID - I/F pare
+ &gDeviceIoProtocolGuid, rb->DevIoProtocol,
+ NULL); //terminator
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ } //rb loop
+ //Here we must initialize and install PciHotPlugControllerInit Protocol
+ //based on VeB provided OUTPUT, IRQ_ASM_APIC output registy can do that.
+
+#if AMI_HOTPLUG_INIT_SUPPORT
+ if(gRbSetupData.HotPlug == 1){
+ Status = HpcInitProtocol(hb);
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: HpcInitProtocol() call returned %r\n", Status));
+
+ if(!EFI_ERROR(Status)){
+ // Install HB res Alloc Protocol on this HOST BRG
+ Status=pBS->InstallMultipleProtocolInterfaces(
+ &hb->HbHandle, //it is NOT NULL now
+ &gHotPlugInitProtocolGuid, &hb->HpcData->RootHotplugProtocol,
+ NULL); //terminator
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Install PCI RHPC Init Protocol call - returned %r\n", Status));
+ } else {
+ if (Status!=EFI_NOT_FOUND) ASSERT_EFI_ERROR(Status);
+
+ }
+
+ }//if Setup allows (gRbSetupData.HotPlug==1)...
+#endif
+
+ } //hb loop
+
+ Status = CreateReadyToBootEvent(TPL_CALLBACK,
+ RbReadyToBoot,
+ NULL,
+ &ReadyToBootEvent);
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Create ReadyToBootEvent - returned %r\n", Status));
+ ASSERT_EFI_ERROR(Status);
+
+ //Call Chipset Hook aftert we have initialized Pci Host bridge.
+ Status=HbCspBasicChipsetInit(&gPciRbHost[0]);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+
+//**********************************************************************
+//HelperFunctions
+//**********************************************************************
+#if AMI_HOTPLUG_INIT_SUPPORT == 1
+
+BOOLEAN HpcCheckHpBus(PCI_HOST_BRG_DATA *HostBrg, UINT8 HpSlotBus,
+ OUT PCI_ROOT_BRG_DATA **RootBrg, OUT PCI_BUS_XLAT_HDR **HlatHdr){
+ UINTN i;
+ PCI_ROOT_BRG_DATA *rb=NULL;
+ PCI_DEV_FUN *rootdf=NULL;
+ UINT8 maxbus;
+//---------------
+ if(RootBrg==NULL || HlatHdr == NULL) return FALSE;
+
+ PCI_TRACE((TRACE_PCI,"PciHp: Locating RB for Slot @ bus 0x%X ... ", HpSlotBus));
+
+ for(i=0; i<HostBrg->RootBridgeCount; i++){
+ PCI_BUS_XLAT_HDR *xhdr=gAmiBoardInfoProtocol->BusXlatTable;
+ PCI_DEV_FUN *devf = (PCI_DEV_FUN*)(xhdr+1);
+ //-----------------------------
+
+ //Init Data...
+ rb=HostBrg->RootBridges[i];
+
+ //See how many buses this root decodes...
+ if(i < HostBrg->RootBridgeCount-1) maxbus=HostBrg->RootBridges[i+1]->BusXlatEntry->BusBuild-1;
+ else maxbus=0xFF;
+
+ //Check if it HpSlotBus falls in this RB bus range.
+ if( (HpSlotBus > maxbus) || (rb->BusXlatEntry->BusBuild > HpSlotBus) )continue;
+
+
+ rootdf=(PCI_DEV_FUN*)(rb->BusXlatEntry+1);
+
+ while((UINTN)devf<=(UINTN)(gAmiBoardInfoProtocol->BusXlatTable)+gAmiBoardInfoProtocol->BusXlatLength){
+ //Terminator found...
+ if(devf->DEV_FUN == 0xFF){
+ //Check if BusBuild # of Xlat entry matches the HpSlotBus
+ if(xhdr->BusBuild == HpSlotBus){
+ PCI_DEV_FUN *rdf=(PCI_DEV_FUN*)(xhdr+1); //Root DevFunc is the first node after header.
+ //-----------------
+ if(rootdf->DEV_FUN == rdf->DEV_FUN ){
+ *RootBrg=rb;
+ *HlatHdr=xhdr;
+ PCI_TRACE((TRACE_PCI,"FOUND! Rb #%d; maxbus=0x%X minbus=0x%X\n ",i, maxbus, rb->BusXlatEntry->BusBuild));
+ return TRUE;
+ }
+ }
+ //Advance to the next record in BusXlatTbl.
+#if AMI_BOARD_VER_COMBINED >= 100
+ //Now we have AslName[5] following devf data
+ xhdr=(PCI_BUS_XLAT_HDR*)(devf+1+5);
+#else
+ xhdr=(PCI_BUS_XLAT_HDR*)(devf+1);
+#endif
+ devf = (PCI_DEV_FUN*)(xhdr+1);
+ continue;
+ } else {
+ devf++;
+ }
+ }
+ //Search through all the ROOTs..
+ } //for
+
+ //we can't find
+ *RootBrg=NULL;
+ *HlatHdr=NULL;
+
+ PCI_TRACE((TRACE_PCI,"NOT FOUND! Rb #%d; maxbus=0x%X minbus=0x%X\n",i, maxbus, rb->BusXlatEntry->BusBuild));
+ return FALSE;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HpcFindHpSlots
+//
+// Description:
+// This function find
+// information and initialize an instance of PCI Root Hotplug Controller
+// Initialization Protocol.
+//
+// Input: PCI_HOST_BRG_DATA *HostBrg - Pointer on Private Data
+// structure for which PCI Hot Plug Init Protocol going to
+// be initialized
+//
+// Output: EFI_SUCCESS is OK
+// EFI_NOT_FOUND no Hotplug slots where found.
+//
+// Notes: CHIPSET AND/OR BOARD PORTING NEEDED
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HpcFindSlots(PCI_HOST_BRG_DATA *HostBrg){
+ EFI_STATUS Status=EFI_NOT_FOUND;
+ UINTN i;
+ PCI_IRQ_PIC_ROUTE *picr=NULL;
+ PCI_IRQ_APIC_ROUTE *apicr=NULL;
+ PCI_DEVICE_PATH pcidp;
+ UINTN hpscnt=0;
+//-------------------------
+ //Check The conditions and validity of a call...using PIC HP Slots Information...
+ hpscnt=gAmiBoardInfoProtocol->HpSltPicLength/sizeof(PCI_IRQ_PIC_ROUTE);
+
+ PCI_TRACE((TRACE_PCI,"PciHp: Found 0x%X HP Slots; processing...:\n", hpscnt));
+
+ if(hpscnt != (gAmiBoardInfoProtocol->HpSltApicLength/sizeof(PCI_IRQ_APIC_ROUTE)) ){
+ PCI_TRACE((TRACE_PCI,"PciHp: APIC HP Slot count != PIC HPC Slot Count: exiting - EFI_INVALID_PARAMETER\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ //init PCI Device Path variable we will not touch header data there..
+ pcidp.Header.SubType=HW_PCI_DP;
+ pcidp.Header.Type=HARDWARE_DEVICE_PATH;
+ SET_NODE_LENGTH(&pcidp.Header,HW_PCI_DEVICE_PATH_LENGTH);
+
+ //Now look for Hotplug slots we know it must be there...
+ for(i=0,picr=gAmiBoardInfoProtocol->HpSltTablePic; i<hpscnt; i++, picr++){
+ PCI_ROOT_BRG_DATA *hprb=NULL;
+ PCI_BUS_XLAT_HDR *hpsh=NULL;
+ //--------------------------
+
+ //Our helper function identified the Slot and ROOT where it belongs.
+ //We are assuming PCI Express Hotplug. So the Bridge is the HPC and Bus It produces is HPB.
+ if( HpcCheckHpBus(HostBrg, picr->PciBusNumber, &hprb, &hpsh)){
+ HPC_LOCATION_DATA *locdata=NULL;
+ EFI_DEVICE_PATH_PROTOCOL *tmpdp=NULL;
+ PCI_DEV_FUN *df;
+ //----------------
+ PCI_TRACE((TRACE_PCI,"PciHp: Found HP Slot #0x%X (%d dec) at BusBuild #0x%X\n",picr->SlotNum, picr->SlotNum, picr->PciBusNumber));
+
+ //Generate the device path for the HPController\HPBus we have pci device path reserved there.
+ tmpdp=DPCopy(hprb->DevPath);
+ if(tmpdp==NULL) {
+ Status=EFI_OUT_OF_RESOURCES;
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ df=(PCI_DEV_FUN*)(hpsh+1);
+ df+=1; //One node is for ROOT bridge
+
+ while (df->DEV_FUN != 0xFF){
+ VOID *oldp=tmpdp;
+ //---------
+ pcidp.Function=df->Fun;
+ pcidp.Device=df->Dev;
+ tmpdp=DPAddNode(tmpdp, (EFI_DEVICE_PATH_PROTOCOL*)&pcidp);
+
+ if(tmpdp==NULL) {
+ Status=EFI_OUT_OF_RESOURCES;
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+ df+=1;
+ if(oldp!=NULL)pBS->FreePool(oldp);
+ }
+ //Here DevicePath Is Ready.
+
+ //Store data returned by HpcCheckHpBus in private structures.
+ locdata=MallocZ(sizeof(HPC_LOCATION_DATA));
+ if(locdata==NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ } else Status=EFI_SUCCESS;
+
+ locdata->Owner=hprb;
+ locdata->SlotHdr=hpsh;
+
+ //For SHPC and PCIExpress Hotplug HPC==HPB = tmpdp.
+ //make a copy of generated DP into hpclocation buffer
+ locdata->HpcLocation.HpcDevicePath=DPCopy(tmpdp);
+ locdata->HpcLocation.HpbDevicePath=DPCopy(tmpdp);
+
+ pBS->FreePool(tmpdp);
+
+ if(locdata->HpcLocation.HpbDevicePath==NULL || locdata->HpcLocation.HpcDevicePath==NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ //fill out Padding Information for this slot...
+ locdata->Padding[ptBus] = gRbSetupData.BusPadd;
+ locdata->Padding[ptIo ] = gRbSetupData.IoPadd;
+ locdata->Padding[ptMmio32] = gRbSetupData.Mmio32Padd;
+ locdata->Padding[ptMmio32pf]= gRbSetupData.Mmio32PfPadd;
+ locdata->Padding[ptMmio64] = gRbSetupData.Mmio64Padd;
+ locdata->Padding[ptMmio64pf]= gRbSetupData.Mmio64PfPadd;
+
+ Status=AppendItemLst((T_ITEM_LIST*)&HostBrg->HpcData->HpclInitCnt, locdata);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) break;
+ }
+ if((UINTN)picr>((UINTN)gAmiBoardInfoProtocol->HpSltTablePic+gAmiBoardInfoProtocol->HpSltPicLength)) break;
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HpcInitGetRootHpcList
+//
+// Description: GetRootHpcList() Function of the PCI Root Hotplug Controller
+// Initialization Protocol. See PI 1.1 Spec or details
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HpcInitGetRootHpcList(IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This,
+ OUT UINTN *HpcCount,
+ OUT EFI_HPC_LOCATION **HpcList)
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ UINTN i;
+ EFI_HPC_LOCATION *hpcl=NULL, *lp=NULL;
+ PCI_HPC_DATA *hpcdata=NULL;
+
+//------------------------
+ hpcdata=(PCI_HPC_DATA*)This;
+
+ PCI_TRACE((TRACE_PCI,"PciHb: Get Location - HpcLocCount=%d\n", hpcdata->HpcLocCount));
+ PCI_TRACE((TRACE_PCI,"-------------------------------------------------\n"));
+
+ //Allocate Buffer for HPC List
+ hpcl=MallocZ(sizeof(EFI_HPC_LOCATION) * hpcdata->HpcLocCount);
+
+ //Check conditions
+ if(hpcl==NULL){
+ Status=EFI_OUT_OF_RESOURCES;
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ //Fill data in RHPC List Data...
+ for(i=0, lp=hpcl; i<hpcdata->HpcLocCount; i++, lp++){
+ HPC_LOCATION_DATA *locdata=hpcdata->HpcLocData[i];
+ //----------------
+ MemCpy(lp, &locdata->HpcLocation, sizeof(EFI_HPC_LOCATION));
+ PCI_TRACE((TRACE_PCI," lp->HpcDP=[HID(%X)UID(%X)]; lp->HpbDP[HID(%X)UID(%X)]\n",
+ ((ACPI_HID_DEVICE_PATH*)lp->HpcDevicePath)->HID,((ACPI_HID_DEVICE_PATH*)lp->HpcDevicePath)->UID,
+ ((ACPI_HID_DEVICE_PATH*)lp->HpbDevicePath)->HID,((ACPI_HID_DEVICE_PATH*)lp->HpbDevicePath)->UID));
+ }
+ PCI_TRACE((TRACE_PCI,"-------------------------------------------------\n"));
+
+ *HpcCount=hpcdata->HpcLocCount;
+ *HpcList=hpcl;
+
+ return Status;
+}
+
+
+EFI_STATUS FindHpcLocData( IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ IN PCI_HPC_DATA *HpcData,
+ OUT HPC_LOCATION_DATA **HpcLocData )
+{
+ UINTN i;
+ HPC_LOCATION_DATA *locdata;
+//------------------
+
+ for(i=0; i< HpcData->HpcLocCount; i++){
+ locdata=HpcData->HpcLocData[i];
+ if(DPCmp(HpcDevicePath, locdata->HpcLocation.HpcDevicePath) == 0 ){
+ *HpcLocData=locdata;
+ return EFI_SUCCESS;
+ }
+ }
+
+ PCI_TRACE((TRACE_PCI,"PciHp: Can't find matching HPC for DevicePath @ 0x%X \n",HpcDevicePath));
+
+ return EFI_NOT_FOUND;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HpcInitInitializeRootHpc
+//
+// Description: InitializeRootHpc() Function of the PCI Root Hotplug Controller
+// Initialization Protocol. See PI 1.1 Spec or details
+//
+// NOTE:
+// This function call will be used to overwrite default resource Padding settings.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HpcInitInitializeRootHpc(IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ IN UINT64 HpcPciAddress,
+ IN EFI_EVENT Event, OPTIONAL
+ OUT EFI_HPC_STATE *HpcState)
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_HPC_DATA *hpcdata=NULL;
+ HPC_LOCATION_DATA *locdata;
+//------------------------
+ hpcdata=(PCI_HPC_DATA*)This;
+
+ //Find which exactly HPC PCI BUS Driver means..
+ Status=FindHpcLocData(HpcDevicePath, hpcdata,&locdata);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Call Porting function to overwrite HP Padding Settings if needed;
+ PciPortSetOemPadding(hpcdata, locdata, HpcPciAddress);
+
+ *HpcState=(EFI_HPC_STATE_INITIALIZED|EFI_HPC_STATE_ENABLED);
+
+ return EFI_SUCCESS;
+}
+
+VOID HpcFillDescriptor(ASLR_QWORD_ASD *Descriptor, HP_PADD_RES_TYPE PaddType, UINT64 Length){
+
+//---------------------
+
+ Descriptor->Hdr.HDR=0x8A;
+ Descriptor->Hdr.Length=0x2B;
+
+ Descriptor->_LEN=Length;
+ if(PaddType==ptBus)Descriptor->_MAX=1;
+ else{
+ if(IsPowerOfTwo(Length))Descriptor->_MAX=Length-1;
+ else Descriptor->_MAX=1;
+ }
+
+ Descriptor->GFlags._MIF=1;
+ Descriptor->GFlags._MAF=1;
+ Descriptor->TFlags.TFLAGS=0;
+
+ switch(PaddType){
+ case ptBus:
+ Descriptor->Type=ASLRV_SPC_TYPE_BUS;
+ break;
+ case ptIo:
+ Descriptor->Type=ASLRV_SPC_TYPE_IO;
+ break;
+ case ptMmio32:
+ Descriptor->Type=ASLRV_SPC_TYPE_MEM;
+ Descriptor->_GRA=32;
+ break;
+ case ptMmio32pf:
+ Descriptor->Type=ASLRV_SPC_TYPE_MEM;
+ Descriptor->TFlags.TFLAGS=0x06;
+ Descriptor->_GRA=32;
+ break;
+ case ptMmio64: //4
+ Descriptor->Type=ASLRV_SPC_TYPE_MEM;
+ Descriptor->_GRA=64;
+ break;
+ case ptMmio64pf: //5
+ Descriptor->Type=ASLRV_SPC_TYPE_MEM;
+ Descriptor->TFlags.TFLAGS=0x06;
+ Descriptor->_GRA=64;
+ break;
+ }
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HpcInitInitializeRootHpc
+//
+// Description: InitializeRootHpc() Function of the PCI Root Hotplug Controller
+// Initialization Protocol. See PI 1.1 Spec or details
+//
+// NOTE:
+// This function call will be used to overwrite default resource Padding settings.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HpcGetResourcePadding(IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ IN UINT64 HpcPciAddress,
+ OUT EFI_HPC_STATE *HpcState,
+ OUT VOID **Padding,
+ OUT EFI_HPC_PADDING_ATTRIBUTES *Attributes)
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_HPC_DATA *hpcdata=NULL;
+ HPC_LOCATION_DATA *locdata;
+ UINTN i, cnt;
+ ASLR_QWORD_ASD *pd, *qw;
+//----------------------------------------------
+ hpcdata=(PCI_HPC_DATA*)This;
+
+ //Find which exactly HPC PCI BUS Driver means..
+ Status=FindHpcLocData(HpcDevicePath, hpcdata,&locdata);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Calculate how many ACPI_QW_DESC we need for Padding Info.
+ for(i=0, cnt=0; i<ptMaxType; i++){
+ if(locdata->Padding[i]!=0) cnt++;
+ }
+
+ //Get memory for it.
+ pd=MallocZ(sizeof(ASLR_QWORD_ASD)*cnt+sizeof(ASLR_EndTag));
+ if (pd==NULL) {
+ Status=EFI_OUT_OF_RESOURCES;
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ //fill out QW Resopurce Descriptors for resource requirements.
+ for(i=0, qw=pd; i<ptMaxType; i++){
+ if(locdata->Padding[i]!=0){
+ HpcFillDescriptor(qw, (HP_PADD_RES_TYPE)i, locdata->Padding[i]);
+ qw++;
+ }
+ }
+
+ ((ASLR_EndTag*)qw)->Hdr.HDR=ASLV_END_TAG_HDR;
+ ((ASLR_EndTag*)qw)->Chsum=0;
+
+ *Padding=pd;
+ *HpcState=(EFI_HPC_STATE_INITIALIZED|EFI_HPC_STATE_ENABLED);
+ *Attributes=EfiPaddingPciBus;
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HpcInitProtocol
+//
+// Description: This function will collect all information HP related
+// information and initialize an instance of PCI Root Hotplug Controller
+// Initialization Protocol.
+//
+// Input: PCI_HOST_BRG_DATA *HostBrg - Pointer on Private Data
+// structure for which PCI Hot Plug Init Protocol going to
+// be initialized
+//
+// Output: EFI_SUCCESS is OK
+// EFI_NOT_FOUND no Hotplug slots where found.
+//
+// Notes: CHIPSET AND/OR BOARD PORTING NEEDED
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HpcInitProtocol(PCI_HOST_BRG_DATA *HostBrg){
+ EFI_STATUS Status=EFI_NOT_FOUND;
+// PCI_HPC_DATA *HpcData;
+//---------------------------
+
+ HostBrg->HpcData=MallocZ(sizeof(PCI_HPC_DATA));
+ if(HostBrg->HpcData==NULL){
+ Status=EFI_OUT_OF_RESOURCES;
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+ HostBrg->HpcData->Owner=HostBrg;
+
+ //Get HP Slots information and Device Path.
+ Status=HpcFindSlots(HostBrg);
+ if(EFI_ERROR(Status)) return Status;
+
+ //So far so good... Init Protocol Instance Functions
+ HostBrg->HpcData->RootHotplugProtocol.GetRootHpcList=HpcInitGetRootHpcList;
+ HostBrg->HpcData->RootHotplugProtocol.InitializeRootHpc=HpcInitInitializeRootHpc;
+ HostBrg->HpcData->RootHotplugProtocol.GetResourcePadding=HpcGetResourcePadding;
+
+
+ return Status;
+}
+
+#endif //AMI_HOTPLUG_INIT_SUPPORT == 1
+
+EFI_STATUS FindRbBusData(PCI_ROOT_BRG_DATA *RootBrg, ASLR_QWORD_ASD **ResDsc){
+ UINTN i;
+ ASLR_QWORD_ASD *res;
+//----------------------------
+
+ //Init return walue with NOT_FOUND result
+ *ResDsc=NULL;
+
+ for(i=0;i<RootBrg->ResCount;i++){
+
+ res=RootBrg->RbRes[i];
+ if(res->Type== ASLRV_SPC_TYPE_BUS){
+ *ResDsc=res;
+ return EFI_SUCCESS;
+ }
+ }//for k
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS ClaimMmioResources(PCI_ROOT_BRG_DATA *CurRootBrg, PCI_ROOT_BRG_DATA *NextRootBrg, ACPI_RES_TYPE ResType){
+ EFI_STATUS Status;
+ DXE_SERVICES *dxe=NULL;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR mem;
+ UINT64 top, bot, tmp, ct, cb;
+ ACPI_RES_DATA *car, *nar;
+//--------------------------------
+ // Get GCD's Memory Space and IO Space Maps
+ Status=LibGetDxeSvcTbl(&dxe);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Fail to Get DXE Services Table Pointer - %r\n", Status));
+ ASSERT_EFI_ERROR(Status);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if(ResType==raMmio32)car=&CurRootBrg->AcpiRbRes[raMmio32];
+ else car=&CurRootBrg->AcpiRbRes[raMmio64];
+
+ if(car->Len==0) return EFI_NOT_FOUND;
+
+ // Use MMIO resources as-is if AllocType is set to EfiGcdAllocateAddress.
+ if(car->AllocType == EfiGcdAllocateAddress) return EFI_SUCCESS;
+
+ if(NextRootBrg!=NULL) {
+ if(ResType==raMmio32)nar=&NextRootBrg->AcpiRbRes[raMmio32];
+ else nar=&NextRootBrg->AcpiRbRes[raMmio64];
+ }else nar=NULL;
+
+
+ if( nar==NULL ) {
+ if(ResType==raMmio32){
+ top=MAX_PCI_MMIO32;
+ bot=MIN_PCI_MMIO32;
+ } else {
+ top=MAX_PCI_MMIO64;
+ bot=MIN_PCI_MMIO64;
+ }
+ } else {
+ if(car->AllocType<=EfiGcdAllocateAddress){
+ top=nar->Min-1;
+ bot=car->Min;
+ } else {
+ top=car->Max;
+ if(ResType==raMmio32) bot=MIN_PCI_MMIO32;
+ else bot=MIN_PCI_MMIO64;
+ }
+ }
+
+ if( TmpTop[ResType] != 0 ) bot=TmpTop[ResType]+1;
+// if( TmpBot[ResType] != 0 ) bot=TmpBot[ResType];
+
+ cb=car->Min;
+ ct=car->Max;
+
+ PCI_TRACE((TRACE_PCI," Ajusting ACPI MMIO MAP [0x%lX...[0x%lX...0x%lX]...0x%lX]\n",bot,cb,ct,top));
+
+ PCI_TRACE((TRACE_PCI," Searching from "));
+
+ if(car->AllocType<=EfiGcdAllocateAddress) {
+ tmp=ct+1;
+ PCI_TRACE((TRACE_PCI,"0x%lX ==> UP.....to 0x%lX\n", tmp, top));
+ } else {
+ tmp=cb-1;
+ PCI_TRACE((TRACE_PCI,"0x%lX <== DOWN...to 0x%lX\n", tmp, bot));
+ }
+
+ //All IO map's EfiGcdIoTypeNonExistent IO type, must be converted to EfiGcdIoTypeIo
+ while(TRUE){
+ Status=dxe->GetMemorySpaceDescriptor(tmp,&mem);
+
+ //Check if we reach end of GCD Space map...
+ if(EFI_ERROR(Status)) break;
+
+ //Check if we hit another RB
+ if(mem.DeviceHandle!=NULL && mem.DeviceHandle!=CurRootBrg->RbHandle) break;
+
+ //Check if we hit system memory...
+ if(mem.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) break;
+
+ PCI_TRACE((TRACE_PCI," MemDsc: BAS=0x%lX; LEN=0x%lX; TYP=%d; IH=0x%X; DX=0x%X; %r\n",
+ mem.BaseAddress, mem.Length, mem.GcdMemoryType, mem.ImageHandle, mem.DeviceHandle, Status));
+
+ if(car->AllocType<=EfiGcdAllocateAddress){
+ ct=mem.BaseAddress+mem.Length-1;
+ } else {
+ cb=mem.BaseAddress;
+ }
+
+ if(car->AllocType<=EfiGcdAllocateAddress){
+ //if we are searching bottom to top...
+ if(ct>=top){
+ ct=top;
+ break;
+ }
+ } else {
+ //if we are searching top to bottom...
+ if(cb<=bot){
+ cb=bot;
+ break;
+ }
+ }
+
+ if(car->AllocType<=EfiGcdAllocateAddress) tmp=ct+1;
+ else tmp=cb-1;
+ }
+
+ car->Max=ct;
+ car->Min=cb;
+ car->Len=ct-cb+1;
+
+ TmpTop[ResType]=ct;
+ TmpBot[ResType]=cb;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS ClaimIoResources(PCI_ROOT_BRG_DATA *CurRootBrg, PCI_ROOT_BRG_DATA *NextRootBrg){
+ EFI_STATUS Status;
+ DXE_SERVICES *dxe=NULL;
+ EFI_GCD_IO_SPACE_DESCRIPTOR io;
+ UINT64 top, bot, tmp, ct, cb;
+ ACPI_RES_DATA *car, *nar;
+//--------------------------------
+ // Get GCD's Memory Space and IO Space Maps
+ Status=LibGetDxeSvcTbl(&dxe);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Fail to Get DXE Services Table Pointer - %r\n", Status));
+ ASSERT_EFI_ERROR(Status);
+ return EFI_DEVICE_ERROR;
+ }
+
+ car=&CurRootBrg->AcpiRbRes[raIo];
+
+ if(car->Len==0) return EFI_NOT_FOUND;
+
+ if(NextRootBrg!=NULL) nar=&NextRootBrg->AcpiRbRes[raIo];
+ else nar=NULL;
+
+ if( nar==NULL ) {
+ top=MAX_PCI_IO;
+ bot=MIN_PCI_IO;
+ } else {
+ if(car->AllocType<=EfiGcdAllocateAddress){
+ top=nar->Min-1;
+ bot=car->Min;
+ } else {
+ top=car->Max;
+ bot=MIN_PCI_IO;
+ }
+ }
+
+ if( TmpTop[raIo] != 0 ) bot=TmpTop[raIo]+1;
+ //if( TmpBot[raIo] != 0 ) bot=TmpBot[raIo];
+
+ cb=car->Min;
+ ct=car->Max;
+
+ PCI_TRACE((TRACE_PCI," Ajusting ACPI IO MAP [0x%lX...[0x%lX...0x%lX]...0x%lX]\n",bot,cb,ct,top));
+
+ PCI_TRACE((TRACE_PCI," Searching from "));
+
+ if(car->AllocType<=EfiGcdAllocateAddress) {
+ tmp=ct+1;
+ PCI_TRACE((TRACE_PCI,"0x%lX ==> UP.....to 0x%lX\n", tmp, top));
+ } else {
+ tmp=cb-1;
+ PCI_TRACE((TRACE_PCI,"0x%lX <== DOWN...to 0x%lX\n", tmp, bot));
+ }
+
+ //All IO map's EfiGcdIoTypeNonExistent IO type, must be converted to EfiGcdIoTypeIo
+ while(TRUE){
+ Status=dxe->GetIoSpaceDescriptor(tmp,&io);
+
+ //Check if we reach end of GCD Space map...
+ if(EFI_ERROR(Status)) break;
+
+ //Check if we hit another RB
+ if(io.DeviceHandle!=NULL && io.DeviceHandle!=CurRootBrg->RbHandle) break;
+
+ PCI_TRACE((TRACE_PCI," IoDes: BAS=0x%lX; LEN=0x%lX; TYP=%d; IH=0x%X; DX=0x%X; %r\n",
+ io.BaseAddress, io.Length, io.GcdIoType, io.ImageHandle, io.DeviceHandle, Status));
+
+ if(car->AllocType<=EfiGcdAllocateAddress){
+ ct=io.BaseAddress+io.Length-1;
+ } else {
+ cb=io.BaseAddress;
+ }
+ if(car->AllocType<=EfiGcdAllocateAddress){
+ //if we are searching bottom to top...
+ if(ct>=top){
+ ct=top;
+ break;
+ }
+ } else {
+ //if we are searching top to bottom...
+ if(cb<=bot){
+ cb=bot;
+ break;
+ }
+ }
+
+ if(car->AllocType<=EfiGcdAllocateAddress) tmp=ct+1;
+ else tmp=cb-1;
+ }
+
+ car->Max=ct;
+ car->Min=cb;
+ car->Len=ct-cb+1;
+
+ TmpTop[raIo]=ct;
+ TmpBot[raIo]=cb;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS AjustAcpiResource(UINTN HostIndex, UINTN RootIndex, ACPI_RES_TYPE ResType){
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_HOST_BRG_DATA *hb, *nexthb;
+ PCI_ROOT_BRG_DATA *rb, *nextrb;
+ ASLR_QWORD_ASD *res, *nextres;
+//--------------------
+
+ //Get pointers to the main data structures we are going to work with.
+ hb=&gPciRbHost[HostIndex];
+ rb=hb->RootBridges[RootIndex];
+
+ //Check if system has NEXT entity available...
+ if(NB_NUMBER_OF_HOST_BRG>HostIndex+1) nexthb=&gPciRbHost[HostIndex+1];
+ else nexthb=NULL;
+
+ if(hb->RootBridgeCount>RootIndex+1)nextrb=hb->RootBridges[RootIndex+1];
+ else {
+ if(nexthb!=NULL) nextrb=nexthb->RootBridges[0];
+ else nextrb=NULL;
+ }
+
+ //Start parsing resources...
+ switch(ResType){
+ case raBus:
+ //Trying to make bus ranges among the bridges be decoded consistently
+ //even RB0 decodes buses 0..5 and RB1 decodes 0x80..0x82 for ACPI
+ //make it decode 0..0x7F and 80..0xFF correspondently.
+ Status=FindRbBusData(rb, &res);
+ //BUS resources must be there
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ //fill ACPI Resource properties
+ rb->AcpiRbRes[raBus].Min=res->_MIN;
+ rb->AcpiRbRes[raBus].Gra=1;
+ if (nextrb!=NULL) {
+ Status=FindRbBusData(nextrb, &nextres);
+ //BUS resources must be there
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+ //Check if NULL bus descriptor...
+ if(nextres->_MIN==0 && nextres->_MAX==0 && nextres->_LEN==0)
+ rb->AcpiRbRes[raBus].Max=MAX_PCI_BUSES;
+ else
+ rb->AcpiRbRes[raBus].Max=nextres->_MIN-1;
+ } else {
+ rb->AcpiRbRes[raBus].Max=MAX_PCI_BUSES;
+ }
+ rb->AcpiRbRes[raBus].Len=rb->AcpiRbRes[raBus].Max-rb->AcpiRbRes[raBus].Min+1;
+
+ PCI_TRACE((TRACE_PCI," Ajusting ACPI BUS MAP [0x%lX...[0x%lX...0x%lX]...0x%lX]\n",
+ rb->AcpiRbRes[raBus].Min,res->_MIN,res->_MIN+res->_LEN-1,rb->AcpiRbRes[raBus].Max));
+ PCI_TRACE((TRACE_PCI," ACPI BUS MAP Set to [0x%lX...0x%lX]\n",
+ rb->AcpiRbRes[raBus].Min,rb->AcpiRbRes[raBus].Max));
+ break;
+
+ case raIo:
+ //With IO picture is much worse. we should scan and assume any unallocated IO to the
+ //corresponded RB keeping in mind boundary between RB0..RB1..RBn decoding ranges.
+ //IO resources may not be there ISA res 0...0xFFF is taken care of automatically
+ //If system don't have second root bridge and does not decode any IO, assume all IO
+ //from 0x1000...Fset decoded by
+ Status=ClaimIoResources(rb, nextrb);
+ PCI_TRACE((TRACE_PCI," ACPI IO MAP Set to [0x%lX...0x%lX] %r\n",
+ rb->AcpiRbRes[raIo].Min,rb->AcpiRbRes[raIo].Max,Status));
+ break;
+ case raMmio32:
+ Status=ClaimMmioResources(rb, nextrb, raMmio32);
+ PCI_TRACE((TRACE_PCI," ACPI MEM32 MAP Set to [0x%lX...0x%lX] %r\n",
+ rb->AcpiRbRes[raMmio32].Min,rb->AcpiRbRes[raMmio32].Max, Status));
+
+ break;
+ case raMmio64:
+ Status=ClaimMmioResources(rb, nextrb, raMmio64);
+ PCI_TRACE((TRACE_PCI," ACPI MEM64 MAP Set to [0x%lX...0x%lX] %r\n",
+ rb->AcpiRbRes[raMmio64].Min,rb->AcpiRbRes[raMmio64].Max, Status));
+ break;
+ default: return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RbReadyToBoot
+//
+// Description: This function will create ReadyToBoot Event to update each
+// Root Bridge ASL Object with corresponded resources decoded.
+//
+// Input: Nothing
+//
+// Output: EFI_SUCCESS is OK
+//
+//
+// Notes: CHIPSET AND/OR BOARD PORTING NEEDED
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID RbReadyToBoot(IN EFI_EVENT Event, IN VOID *Context){
+ EFI_STATUS Status;
+ UINTN i,j,k;
+ PCI_HOST_BRG_DATA *hb;
+ PCI_ROOT_BRG_DATA *rb;
+ ACPI_HDR *dsdt;
+ EFI_PHYSICAL_ADDRESS a;
+ BOOLEAN vga=FALSE;
+//-----------------------------
+
+// EFI_DEADLOOP();
+
+ //Get DSDT.. we have to update it.
+ Status=LibGetDsdt(&a,EFI_ACPI_TABLE_VERSION_ALL);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Fail to Get DSDT - returned %r\n", Status));
+ ASSERT_EFI_ERROR(Status);
+ return;
+ } else dsdt=(ACPI_HDR*)a;
+
+ //Collect currently programed resource requirements, we will need to ajust it
+ //to clame all Unallocated IO/MMIO to report it to OS.
+ for(i=0; i<NB_NUMBER_OF_HOST_BRG; i++){
+ hb=&gPciRbHost[i];
+ for(j=0; j<hb->RootBridgeCount; j++){
+ rb=hb->RootBridges[j];
+
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Host[ %d ].Root[ %d ] \n", i, j));
+
+ for(k=raBus; k<raMaxRes; k++){
+ Status=AjustAcpiResource(i,j,k);
+ }//for k
+ }//for j
+ }//for i
+
+ //after collectinfg and ajusting all Rb decoding info info
+ //Update place holders in each Rb Device Scope in DSDT.
+ for(i=0; i<NB_NUMBER_OF_HOST_BRG; i++){
+ hb=&gPciRbHost[i];
+ for(j=0; j<hb->RootBridgeCount; j++){
+ rb=hb->RootBridges[j];
+
+ //Check if this is a Compatibility Root Bridge.
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Updating ASL Device Object '%s': ...\n", rb->RbAslName));
+
+ if(rb->Supports & (PCI_ROOT_COMPATIBILITY_ATTRIBUTES)){
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "CPRB", 1);
+ PCI_TRACE((TRACE_PCI," =>'CPRB'= 1 -> %r;\n", Status));
+ } else {
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "CPRB", 0);
+ PCI_TRACE((TRACE_PCI," =>'CPRB'= 0 -> %r;\n", Status));
+ }
+
+ if(rb->Attributes & (PCI_ROOT_VGA_ATTRIBUTES)){
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "LVGA", 1);
+ PCI_TRACE((TRACE_PCI," =>'LVGA'= 1 -> %r;\n", Status));
+ vga=TRUE;
+ } else {
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "LVGA", 0);
+ PCI_TRACE((TRACE_PCI," =>'LVGA'= 0 -> %r;\n", Status));
+ }
+
+ //Now Update place holders fit in collected system resource consumption.
+
+ //0. Update device Status
+ if( rb->NotPresent ) Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "STAV", 0x00);
+ PCI_TRACE((TRACE_PCI," =>'SATV'=%d -> %r;\n", !rb->NotPresent, Status));
+
+ //1.Update Bus Object
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "BRB", rb->AcpiRbRes[raBus].Min);
+ PCI_TRACE((TRACE_PCI," =>'BRB_'=0x%lX -> %r; ",rb->AcpiRbRes[raBus].Min, Status));
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "BRL", rb->AcpiRbRes[raBus].Len);
+ PCI_TRACE((TRACE_PCI," 'BRL_'=0x%lX -> %r;\n",rb->AcpiRbRes[raBus].Len, Status));
+
+ //2.Update IO Object
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "IOB", rb->AcpiRbRes[raIo].Min);
+ PCI_TRACE((TRACE_PCI," =>'IOB_'=0x%lX -> %r; ",rb->AcpiRbRes[raIo].Min, Status));
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "IOL", rb->AcpiRbRes[raIo].Len);
+ PCI_TRACE((TRACE_PCI," 'IOL_'=0x%lX -> %r;\n",rb->AcpiRbRes[raIo].Len, Status));
+
+ //3.Update MMIO32 Object
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MBB", rb->AcpiRbRes[raMmio32].Min);
+ PCI_TRACE((TRACE_PCI," =>'MBB_'=0x%lX -> %r; ",rb->AcpiRbRes[raMmio32].Min, Status));
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MBL", rb->AcpiRbRes[raMmio32].Len);
+ PCI_TRACE((TRACE_PCI," 'MBL_'=0x%lX -> %r;\n",rb->AcpiRbRes[raMmio32].Len, Status));
+
+ //3.Update MMIO64 Object
+ //3.1 Update LO part of _MIN
+ a=rb->AcpiRbRes[raMmio64].Min & 0xFFFFFFFF;
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MABL", a);
+ PCI_TRACE((TRACE_PCI," =>'MABL'=0x%lX -> %r; ", a, Status));
+
+ //3.2 Update HI part of _MIN
+ a=Shr64(rb->AcpiRbRes[raMmio64].Min, 32);
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MABH", a);
+ PCI_TRACE((TRACE_PCI,"'MABH'=0x%lX -> %r;\n", a, Status));
+
+ //3.3 Update LO part of MAX
+ a=rb->AcpiRbRes[raMmio64].Max & 0xFFFFFFFF;
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MAML", a);
+ PCI_TRACE((TRACE_PCI," =>'MAML'=0x%lX -> %r; ", a, Status));
+
+ //3.4 Update HI part of _MAX
+ a=Shr64(rb->AcpiRbRes[raMmio64].Max, 32);
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MAMH", a);
+ PCI_TRACE((TRACE_PCI,"'MAMH'=0x%lX -> %r;\n", a, Status));
+
+ //3.3 Update LO part of MAX
+ a=rb->AcpiRbRes[raMmio64].Len & 0xFFFFFFFF;
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MALL", a);
+ PCI_TRACE((TRACE_PCI," =>'MALL'=0x%lX -> %r; ", a, Status));
+
+ //3.4 Update HI part of _MAX
+ a=Shr64(rb->AcpiRbRes[raMmio64].Len, 32);
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "MALH", a);
+ PCI_TRACE((TRACE_PCI,"'MALH'=0x%lX -> %r;\n", a, Status));
+
+ }//j
+ }//i
+
+ //if PCI_ROOT_VGA_ATTRIBUTES were not set by drivers we have to clame Legacy VGS IO and MEM Space.
+ if(!vga){
+ hb=&gPciRbHost[0];
+ rb=hb->RootBridges[0];
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Legacy VGA Attributes were not set!!!\n"));
+ PCI_TRACE((TRACE_PCI," Setting 'LVGA'=1 of Device Object '%s' for Hb[0].Rb[0] -> ", rb->RbAslName));
+ Status=UpdateAslNameOfDevice(dsdt, rb->RbAslName, "LVGA", 1);
+ PCI_TRACE((TRACE_PCI,"%r;\n", Status));
+ }
+
+ //Checksum
+ dsdt->Checksum = 0;
+ dsdt->Checksum = ChsumTbl((UINT8*)dsdt, dsdt->Length);
+
+ // Check for invalid Pci RootBridge Handle.
+ //If Rootbridge handle is invalid, then uninstall PCI Rootbridge IO protocol on this handle.
+ for(i=0; i<NB_NUMBER_OF_HOST_BRG; i++){
+ hb=&gPciRbHost[i];
+ for(j=0; j<hb->RootBridgeCount; j++){
+ rb=hb->RootBridges[j];
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Host[ %d ].Root[ %d ] \n", i, j));
+
+ if(rb->NotPresent) {
+ PCI_TRACE((TRACE_PCI,"Hb.SetBusNumbers - Invalid RB Hndle Passed\n"));
+ Status = pBS->UninstallMultipleProtocolInterfaces (
+ rb->RbHandle,
+ &gRbIoProtocolGuid, &rb->RbIoProtocol,
+ &gDevPathProtocolGuid, rb->DevPath,
+ NULL
+ );
+
+ PCI_TRACE((TRACE_PCI,"Uninstall RbIoProtocol Status %r; \n", Status));
+ rb->RbHandle=NULL;
+ }//if
+ }//for j
+ }//for i
+
+ pBS->CloseEvent(Event);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateRootBusData
+//
+// Description: This function will parse NusXlat Table looking for HostBridge
+// entries (one who has Bus IN == Bus OUT) and populate gRootBusDb
+// Structure.
+//
+// Input: Nothing
+//
+// Output: EFI_SUCCESS is OK
+//
+//
+// Notes: CHIPSET AND/OR BOARD PORTING NEEDED
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CreateRootBusData(){
+ PCI_BUS_XLAT_HDR *xhdr=gAmiBoardInfoProtocol->BusXlatTable;
+ PCI_DEV_FUN *devf = (PCI_DEV_FUN*)(xhdr+1);
+ UINTN i=0;
+ EFI_STATUS Status;
+//--------------------------------
+ while((UINTN)devf<=(UINTN)(gAmiBoardInfoProtocol->BusXlatTable)+gAmiBoardInfoProtocol->BusXlatLength){
+ if(devf->DEV_FUN == 0xFF){
+ //if we are looking for host device it shouldn't be any other guys in it's chain.
+ if(i==1) {
+ Status=AddBusDbEntry(xhdr, &gRootBusDb);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ //Advance to the next record in BusXlatTbl.
+#if AMI_BOARD_VER_COMBINED >= 100
+ //Now we have AslName[5] following devf data
+ xhdr=(PCI_BUS_XLAT_HDR*)(devf+1+5);
+#else
+ xhdr=(PCI_BUS_XLAT_HDR*)(devf+1);
+#endif
+ devf = (PCI_DEV_FUN*)(xhdr+1);
+ i=0;
+ } else {
+ devf++;
+ i++;
+ }
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConvertMemoryMap
+//
+// Description: This function will adjust the final GCD resource map and
+// convert all NonrExistant Memory resources into MMIO.
+//
+// Input: ImgHandle Image handle
+// CntrHandle Controller Handle
+//
+// Output: None
+//
+// Notes: CHIPSET AND/OR BOARD PORTING NEEDED
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ConvertMemoryMap(EFI_HANDLE ImgHandle, EFI_HANDLE CntrHandle)
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *pMap;
+ EFI_GCD_IO_SPACE_DESCRIPTOR *pIo;
+ UINTN Size, i;
+ DXE_SERVICES *dxe;
+//----------------------------------------------------------------------
+
+ // Convert All Nonexistent Memory space to MMIO
+ // Once GCD and Memory manager gets initialized
+ Status=LibGetDxeSvcTbl(&dxe);
+ if(EFI_ERROR(Status)) return Status;
+
+
+ Status=dxe->GetMemorySpaceMap(&Size, &pMap);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ for(i=0; i<Size; i++)
+ if (pMap[i].GcdMemoryType == EfiGcdMemoryTypeNonExistent ){
+ Status=dxe->AddMemorySpace(EfiGcdMemoryTypeMemoryMappedIo,
+ pMap[i].BaseAddress,pMap[i].Length, GCD_COMMON_MMIO_CAPS);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ pBS->FreePool(pMap);
+
+ //Convert all non-existant IO to existant IO
+ Status=dxe->GetIoSpaceMap(&Size, &pIo);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ for(i=0; i<Size; i++)
+ if (pIo[i].GcdIoType == EfiGcdIoTypeNonExistent){
+ Status=dxe->AddIoSpace(EfiGcdIoTypeIo,pIo[i].BaseAddress,pIo[i].Length);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ pBS->FreePool(pIo);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsResSubmited()
+//
+// Description:
+// Will check if all root bridges belonging to the "Host" has submitted
+// it's resources
+//
+// Input:
+// PCI_HOST_BRG_DATA *Host Pointer to HOST Bridge private data
+// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured
+// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor
+// EFI_PCI_CONFIGURATION_ADDRESS PciBusAddress Address of the controller on the PCI bus
+// EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase The Phase during resource allocation
+//
+// Output: BOOLEAN
+// TRUE all root bridges belonging to the "Host" has its resources submitted
+// FALSE opposite ...
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsResSubmited(PCI_HOST_BRG_DATA *Host){
+ PCI_ROOT_BRG_DATA *rb;
+ UINTN i;
+//---------------------
+ for(i=0; i<NB_NUMBER_OF_HOST_BRG; i++){
+ rb=Host->RootBridges[i];
+ if(!rb->ResSubmited) return FALSE;
+ }
+ return TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetRbByHandle()
+//
+// Description:
+// Lokates
+//
+// Input:
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance
+// EFI_HANDLE RbHandle PCI Root Bridge Handle to get Private data for.
+// UINTN *Index Updated Index of the Found Root Bridge private data
+//
+// Output: PCI_ROOT_BRG_DATA
+// Not NULL if Root was found.
+// NULL if Root was not found.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+PCI_ROOT_BRG_DATA *GetRbByHandle(EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ EFI_HANDLE RbHandle,
+ UINTN *Index OPTIONAL)
+{
+ PCI_HOST_BRG_DATA *hbdata=(PCI_HOST_BRG_DATA*)This;
+ PCI_ROOT_BRG_DATA *rbdata;
+ UINTN i;
+//----------------------------------
+ for(i=0;i<hbdata->RootBridgeCount;i++){
+ rbdata=hbdata->RootBridges[i];
+ if(rbdata->RbHandle==RbHandle){
+ if(Index)(*Index)=i;
+// hbdata->CurrentRb=i;
+ return rbdata;
+ }
+ }
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetResources()
+//
+// Description:
+// This function will generate Resource descriptors block based on information
+// stored in RootBridge->RbRes array
+//
+// Input:
+// PCI_HOST_BRG_DATA *Host Pointer to HOST Bridge private data
+// ASLR_QWORD_ASD **Resources Resource List in a form of ACPI QWORD Resource Descriptor.
+// ASLR_TYPE_ENUM ResType Describes what type of resources we are getting.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_OUT_OF_RESOURCES - If SubmitResources ( ) could not allocate resources
+// EFI_NOT_READY - This phase cannot be entered at this time
+// EFI_DEVICE_ERROR - SetResources failed due to HW error.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetResources(PCI_ROOT_BRG_DATA *RootBrg, ASLR_QWORD_ASD **Resources, ASLR_TYPE_ENUM ResType)
+{
+ UINTN i,cnt=0;
+ ASLR_QWORD_ASD *qw;
+ BOOLEAN cpy;
+//---------------------------------1
+ //count descriptors first
+ if(ResType==tResAll) cnt=RootBrg->ResCount;
+ else {
+ for(i=0;i<RootBrg->ResCount;i++){
+ if(ResType==tResBus){
+ if(RootBrg->RbRes[i]->Type == ASLRV_SPC_TYPE_BUS)cnt++;
+ } else {
+ if(RootBrg->RbRes[i]->Type < ASLRV_SPC_TYPE_BUS) cnt++;
+ }
+ }
+ }
+ //if(!cnt) return EFI_NOT_FOUND;
+
+ //Allocate memory for ASL Resource Descriptors
+ qw=Malloc(sizeof(ASLR_QWORD_ASD)*cnt+sizeof(ASLR_EndTag));
+ if(!qw) return EFI_OUT_OF_RESOURCES;
+
+ *Resources=qw;
+
+ //Copy Resource information
+ for(i=0; i<RootBrg->ResCount; i++, cpy=FALSE){
+ if(ResType==tResAll) cpy=TRUE;
+ else {
+ if(ResType==tResBus){
+ if(RootBrg->RbRes[i]->Type == ASLRV_SPC_TYPE_BUS)cpy=TRUE;
+ } else {
+ if(RootBrg->RbRes[i]->Type < ASLRV_SPC_TYPE_BUS) cpy=TRUE;
+ }
+ }
+ if(cpy){
+ MemCpy(qw,RootBrg->RbRes[i],sizeof(ASLR_QWORD_ASD));
+ qw++;
+ }
+ }
+ ((ASLR_EndTag*)qw)->Hdr.HDR=ASLV_END_TAG_HDR;
+ ((ASLR_EndTag*)qw)->Chsum=0;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetResources()
+//
+// Description:
+// This function will update RootBridge->RbRes array with Descriptors
+// prowided with *Resources parameter
+//
+// Input:
+// PCI_HOST_BRG_DATA *Host Pointer to HOST Bridge private data
+// ASLR_QWORD_ASD *Resources Resource List in a form of ACPI QWORD Resource Descriptor.
+// ASLR_TYPE_ENUM ResType Describes what type of resources we are getting.
+// BOOLEAN Replace if TRUE function will Remove all descriptors of "ResType" before adding.
+// if FALSE function will just add "Resources"
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_OUT_OF_RESOURCES - If SubmitResources ( ) could not allocate resources
+// EFI_NOT_READY - This phase cannot be entered at this time
+// EFI_DEVICE_ERROR - SetResources failed due to HW error.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SetResources(PCI_ROOT_BRG_DATA *RootBrg, ASLR_QWORD_ASD *Resources,
+ ASLR_TYPE_ENUM ResType, BOOLEAN Replace)
+{
+ UINTN i, len, cnt;
+ ASLR_QWORD_ASD *res;
+//---------------------------------
+
+ len=ValidateDescriptorBlock((ASLR_QWORD_ASD*)Resources, ResType, FALSE);
+ if(!len) return EFI_INVALID_PARAMETER;
+
+ cnt=(len-sizeof(ASLR_EndTag))/sizeof(ASLR_QWORD_ASD);
+ //We have received Empty descriptor nothing to do just return.
+ if(!cnt) return EFI_SUCCESS;
+
+ if(Replace){
+ if(ResType==tResAll) ClearItemLst((T_ITEM_LIST*)&RootBrg->ResInitCnt, TRUE);
+ else {
+ i=RootBrg->ResCount;
+ while(i){
+ i--;
+ if(ResType==tResBus){
+ if(RootBrg->RbRes[i]->Type == ASLRV_SPC_TYPE_BUS)
+ DeleteItemLst((T_ITEM_LIST*)&RootBrg->ResInitCnt, i,TRUE);
+ } else {
+ if(RootBrg->RbRes[i]->Type < ASLRV_SPC_TYPE_BUS)
+ DeleteItemLst((T_ITEM_LIST*)&RootBrg->ResInitCnt, i,TRUE);
+ }
+ }
+ }
+ }
+
+ //Update Bus Resources in rbdata
+ for(i=0; i<cnt; i++,Resources++) {
+ res=Malloc(sizeof(ASLR_QWORD_ASD));
+ if(!res) return EFI_OUT_OF_RESOURCES;
+
+ MemCpy(res,Resources,sizeof(ASLR_QWORD_ASD));
+
+ if(EFI_ERROR(AppendItemLst((T_ITEM_LIST*)&RootBrg->ResInitCnt,res))) return EFI_OUT_OF_RESOURCES;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsPowerOfTwo()
+//
+// Description:
+// Checks if value passed makes "POWER OF TWO"
+//
+// Input:
+// UINT64 Value Value to check.
+//
+// Output: BOOLEAN
+// TRUE or FALSE based on value passed.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsPowerOfTwo(UINT64 Value){
+ UINTN i;
+ UINT64 t;
+//--------------
+ for(i=0; i<64; i++){
+ t=Shl64(1,(UINT8)i);
+ if(Value&t) {
+ if(Value&(~t))return FALSE;
+ else return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//(EIP45278)>
+#if PCI_MMIO_RES_TOP_ALLIGN == 1
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AllocateMemoryResource()
+//
+// Description:
+// This function will try to Allocate from GCD set of resources requested by
+// input Length and Alignment.
+//
+// Input:
+// UINTN Alignment Align with 2^Alignment
+// UINT64 Length Length to allocate
+// EFI_PHYSICAL_ADDRESS *BaseAddress Base address to allocate
+// EFI_HANDLE ImageHandle The image handle consume the allocated space.
+// EFI_HANDLE DeviceHandle The device handle consume the allocated space.
+//
+// Output: EFI_STATUS
+// EFI_INVALID_PARAMETER Invalid parameter.
+// EFI_NOT_FOUND No descriptor contains the desired space.
+// EFI_SUCCESS Memory space successfully allocated.
+//
+// EFI_PHYSICAL_ADDRESS *BaseAddress Base address to be allocated
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AllocateMemoryResource (
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle
+)
+{
+ EFI_STATUS Status;
+ DXE_SERVICES *dxe;
+ EFI_PHYSICAL_ADDRESS AlignmentMask;
+
+ Status=LibGetDxeSvcTbl(&dxe);
+ if(EFI_ERROR(Status)) return Status;
+
+ AlignmentMask = (1 << Alignment) - 1;
+ // Search an unused for fit the length
+ while (((*BaseAddress + Length) & AlignmentMask)) {
+ Status = dxe->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ 0,
+ Length,
+ BaseAddress,
+ ImageHandle,
+ DeviceHandle);
+ if(EFI_ERROR(Status)) break;
+ // Check if the space is under Alignment
+ if (((*BaseAddress + Length) & AlignmentMask)) {
+ Status = dxe->FreeMemorySpace (*BaseAddress, Length);
+ if(EFI_ERROR(Status)) break;
+ *BaseAddress = ((*BaseAddress + Length) & (~AlignmentMask)) - Length;
+ }
+ }
+ return Status;
+}
+#endif
+//<(EIP45278)
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AlignFromGra()
+//
+// Description:
+// Converts C passed into Alignment format
+//
+// Input:
+// UINTN g AlignFromGra Value to convert
+//
+// Output: UINTN
+// Converted Alignment value.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN AlignFromGra(UINTN g){
+ UINTN a=0;
+//------------
+ while(g&1){
+ a++;
+ g=g>>1;
+ }
+ return a;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AllocateResources()
+//
+// Description:
+// This function will try to Allocate from GCD set of resources requested by
+// PCI BUS driver in "*Resources" buffer.
+//
+// Input:
+// PCI_ROOT_BRG_DATA *RootBrg Pointer to ROOT Bridge private data
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_OUT_OF_RESOURCES - If could not allocate resources
+// EFI_DEVICE_ERROR - failed due to HW error.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AllocateResources(PCI_ROOT_BRG_DATA *RootBrg){
+ EFI_STATUS Status=0;
+ EFI_STATUS ReturnStatus = 0;
+ UINTN i;
+ ASLR_QWORD_ASD *res;
+ ACPI_RES_DATA *ar;
+ UINT64 a=0;
+ DXE_SERVICES *dxe;
+//OUT_OF_RES HANDLING++ must be added in Custom Res allocate function.
+#if BoardPciRes_SUPPORT
+ AMI_OUT_OF_RES_VAR OutOfResVar;
+//--------------------------------------
+ //Check if OUT_OF_RES_VAR was already created.
+ Status=AmiPciOutOfRes(&OutOfResVar, TRUE);
+ if(EFI_ERROR(Status)) pBS->SetMem(&OutOfResVar,sizeof(AMI_OUT_OF_RES_VAR),0);
+ else OutOfResVar.Count++;
+#endif
+//OUT_OF_RES HANDLING-- must be added in Custom Res allocate function.
+
+ Status=LibGetDxeSvcTbl(&dxe);
+ if(EFI_ERROR(Status)) return Status;
+
+
+ for(i=0; i<RootBrg->ResCount; i++){
+ res=RootBrg->RbRes[i];
+ if(res->Type==ASLRV_SPC_TYPE_BUS) continue;
+ //Check if Alignment
+ if(!IsPowerOfTwo(res->_MAX+1)) return EFI_INVALID_PARAMETER;
+ switch(res->_GRA){
+ case 16 : a=0xFFFF;//-res->_LEN;
+ break;
+ case 32 : a=0xFFFFFFFF;//-res->_LEN;
+ break;
+ case 64 : a=0xFFFFFFFFFFFFFFFF;//-res->_LEN+1;
+ break;
+ default :ASSERT(0); return EFI_INVALID_PARAMETER;
+ }
+
+ PCI_TRACE((TRACE_PCI,"PciRootBrg:AllocateResources In -> _MIN=0x%lX; _MAX=0x%lX; _LEN=0x%lX; _GRA=0x%lX\n",
+ res->_MIN,res->_MAX,res->_LEN,res->_GRA));
+
+
+ //Allocate IO
+ if(res->Type==ASLRV_SPC_TYPE_IO){
+
+ ar=&RootBrg->AcpiRbRes[raIo];
+ ar->AddrUsed=a;
+ ar->AllocType=EfiGcdAllocateMaxAddressSearchTopDown;
+
+ Status=dxe->AllocateIoSpace(EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdIoTypeIo,
+ AlignFromGra((UINTN)res->_MAX),
+ res->_LEN,
+ &a,
+ RootBrg->ImageHandle, RootBrg->RbHandle);
+
+ if(EFI_ERROR(Status)) {
+ ReturnStatus = Status;
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: IO Allocation Failed: Length: %lX\n",res->_LEN));
+//++OUT_OF_RES!! IO
+#if BoardPciRes_SUPPORT
+ OutOfResVar.Resource=*res;
+ Status=AmiPciOutOfRes(&OutOfResVar, FALSE);
+ return ReturnStatus;
+//--OUT_OF_RES!! IO
+#else
+ continue;
+#endif
+ }
+
+ }
+ //Allocate MMIO
+ else if( res->Type==ASLRV_SPC_TYPE_MEM){
+
+ if(res->_GRA==32)ar=&RootBrg->AcpiRbRes[raMmio32];
+ else ar=&RootBrg->AcpiRbRes[raMmio64];
+ ar->AddrUsed=a;
+ ar->AllocType=EfiGcdAllocateMaxAddressSearchTopDown;
+//(EIP45278)>
+#if PCI_MMIO_RES_TOP_ALLIGN == 1
+ Status = AllocateMemoryResource(
+ AlignFromGra((UINTN)res->_MAX),
+ res->_LEN,
+ &a,
+ RootBrg->ImageHandle,
+ RootBrg->RbHandle);
+#else
+ Status=dxe->AllocateMemorySpace(EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ AlignFromGra((UINTN)res->_MAX),
+ res->_LEN,
+ &a,
+ RootBrg->ImageHandle, RootBrg->RbHandle);
+#endif
+//<(EIP45278)
+
+ if(EFI_ERROR(Status)) {
+ ReturnStatus = Status;
+ PCI_TRACE((TRACE_PCI,"PciRootBrg: Memory Allocation Failed: Length: %lX\n",res->_LEN));
+//++OUT_OF_RES!! MEM
+#if BoardPciRes_SUPPORT
+ OutOfResVar.Resource=*res;
+ Status=AmiPciOutOfRes(&OutOfResVar, FALSE);
+ return ReturnStatus;
+#else
+//--OUT_OF_RES!! MEM
+ continue;
+#endif
+ }
+
+ //Set this region as WT cache if it is PREFETCHABLE
+ if(res->TFlags.MEM_FLAGS._MEM!=ASLRV_MEM_UC)
+ {
+ //Status=gDxeSvcTbl->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_WT|EFI_MEMORY_RUNTIME);
+ Status=dxe->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_WT);
+ //if attempt to set WT attributes has filed, let's try UC
+ if(EFI_ERROR(Status))
+ {
+ PCI_TRACE((TRACE_DXE_CHIPSET,"PciHostBridge: Setting of WT attributes for prefetchable memory has failed(%r). UC is used.\n",Status));
+ //Status=gDxeSvcTbl->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_UC|EFI_MEMORY_RUNTIME);
+ Status=dxe->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_UC);
+ }
+ }
+ else Status=dxe->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_UC);
+ // Status=gDxeSvcTbl->SetMemorySpaceAttributes(a,res->_LEN,EFI_MEMORY_UC|EFI_MEMORY_RUNTIME);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ }
+ res->_MIN=a;
+
+
+ PCI_TRACE((TRACE_PCI,"PciRootBrg:AllocateResources Out-> _MIN=0x%lX; _MAX=0x%lX; _LEN=0x%lX; _GRA=0x%lX\n",
+ res->_MIN,res->_MAX,res->_LEN,res->_GRA));
+
+ //Do some calculation for ACPI _CRS update.
+ if (ar->Min==0) ar->Min=res->_MIN;
+ else {
+ if(ar->Min > res->_MIN)ar->Min=res->_MIN;
+ }
+//(EIP45278+)>
+#if PCI_MMIO_RES_TOP_ALLIGN == 1
+ ar->Gra = 0;
+#else
+ if (ar->Gra==0) ar->Gra=res->_MAX;
+ else {
+ if(ar->Gra<res->_MAX)ar->Gra=res->_MAX;
+ }
+#endif
+//<(EIP45278+)
+ if(ar->Len==0){
+ ar->Len=res->_LEN;
+ if(ar->Len & ar->Gra) ar->Len=(ar->Len |ar->Gra)+1;
+ ar->Max=ar->Min+ar->Len-1;
+ } else {
+ UINT64 max;
+ //--------
+ max=res->_MIN + res->_LEN - 1;
+ if(max>ar->Max)ar->Max=max;
+ ar->Len=ar->Max - ar->Min + 1;
+ if(ar->Len & ar->Gra) ar->Len=(ar->Len |ar->Gra)+1;
+ ar->Max=ar->Min+ar->Len-1;
+ }
+ PCI_TRACE((TRACE_PCI,"PciRootBrg:AcpiResources Min=0x%lX; Max=0x%lX; Len=0x%lX; Gra=0x%lX, AdrUsed=0x%lX\n\n",
+ ar->Min,ar->Max,ar->Len,ar->Gra, ar->AddrUsed));
+
+ //Don't need to set this to actual value it could be calculated using commented formula.
+ //More important to preserve alignment requirements of the resource window.
+ //res->_MAX=res->_MIN+res->_LEN-1;
+ }
+ return ReturnStatus;
+}
+
+
+
+
+//**********************************************************************
+//Pci Host Bridge Resource Allocation Protocol function Implementation
+//**********************************************************************
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HbResAllocNotifyPhase()
+//
+//Description: Enter a certain phase of the PCI enumeration process
+//
+// Input:
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase The phase during enumeration
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_OUT_OF_RESOURCES - If SubmitResources ( ) could not allocate resources
+// EFI_NOT_READY - This phase cannot be entered at this time
+// EFI_DEVICE_ERROR - SetResources failed due to HW error.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HbResAllocNotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase )
+{
+ PCI_HOST_BRG_DATA *hbdata=(PCI_HOST_BRG_DATA*)This;
+ EFI_STATUS Status=0;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **pp;
+ UINTN i;
+//--------------------------------------------------------
+ pp=Malloc(sizeof(VOID*)*hbdata->RootBridgeCount);
+ ASSERT(pp);
+ if(!pp) return EFI_INVALID_PARAMETER;
+
+ for(i=0; i<hbdata->RootBridgeCount; i++) pp[i]=&hbdata->RootBridges[i]->RbIoProtocol;
+
+ switch(Phase){
+ case EfiPciHostBridgeBeginEnumeration:
+ //if(hbdata->AllocPhase!=EfiPciHostBridgeBeginEnumeration) return EFI_INVALID_PARAMETER;
+ Status=HbNotifyCspBeforeEnumeration(&hbdata->ResAllocProtocol, &pp[0], hbdata->RootBridgeCount);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ break;
+ case EfiPciHostBridgeBeginBusAllocation:
+ Status=HbNotifyCspBeginBusAllocation(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount);
+ ASSERT_EFI_ERROR(Status);
+ break;
+ case EfiPciHostBridgeEndBusAllocation:
+ if(hbdata->AllocPhase+1!=Phase) return EFI_INVALID_PARAMETER;
+ Status=HbNotifyCspEndBusAllocation(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount);
+ ASSERT_EFI_ERROR(Status);
+ break;
+ case EfiPciHostBridgeBeginResourceAllocation:
+ if(hbdata->AllocPhase+1!=Phase) return EFI_INVALID_PARAMETER;
+ Status=HbNotifyCspBeginResourceAllocation(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount);
+ ASSERT_EFI_ERROR(Status);
+ break;
+ case EfiPciHostBridgeAllocateResources:
+ if(hbdata->AllocPhase+1!=Phase) return EFI_INVALID_PARAMETER;
+ if(!IsResSubmited(hbdata)) return EFI_NOT_READY;
+ Status=HbNotifyCspAllocateResources(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount);
+ ASSERT_EFI_ERROR(Status);
+ break;
+ case EfiPciHostBridgeSetResources:
+ if(hbdata->AllocPhase+1!=Phase) return EFI_INVALID_PARAMETER;
+ if(!IsResSubmited(hbdata)) return EFI_NOT_READY;
+ Status=HbNotifyCspSetResources(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount);
+ ASSERT_EFI_ERROR(Status);
+ break;
+ case EfiPciHostBridgeFreeResources:
+ return EFI_UNSUPPORTED;
+ break;
+ case EfiPciHostBridgeEndResourceAllocation:
+ if(hbdata->AllocPhase+2!=Phase) return EFI_INVALID_PARAMETER;
+ Status=HbNotifyCspEndResourceAllocation(&hbdata->ResAllocProtocol, &pp[0],hbdata->RootBridgeCount);
+ ASSERT_EFI_ERROR(Status);
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ }
+
+ if(EFI_ERROR(Status)) return Status;
+ hbdata->AllocPhase=Phase;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HbResAllocGetNextRootBridge()
+//
+// Description:
+// Return the device handle of the next PCI root bridge that is
+// associated with this Host Bridge.
+//
+// Input:
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance
+// EFI_HANDLE *RootBridgeHandle Returns the device handle
+// of the next PCI Root Bridge. On input, it holds the RootBridgeHandle
+// returned by the most recent call to GetNextRootBridge().
+// The handle for the first PCI Root Bridge is returned if RootBridgeHandle
+// is NULL on input.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HbResAllocGetNextRootBridge(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle)
+{
+ PCI_HOST_BRG_DATA *hbdata=(PCI_HOST_BRG_DATA*)This;
+ PCI_ROOT_BRG_DATA *rbdata;
+ UINTN i=0;
+//--------------------------------------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+ if(*RootBridgeHandle==NULL) {
+ rbdata=hbdata->RootBridges[i];
+ *RootBridgeHandle=rbdata->RbHandle;
+ return EFI_SUCCESS;
+ } else {
+ rbdata=GetRbByHandle(This,*RootBridgeHandle,&i);
+ if(!rbdata) return EFI_INVALID_PARAMETER;
+ if(hbdata->RootBridgeCount-1>i){
+ rbdata=hbdata->RootBridges[i+1];
+ *RootBridgeHandle=rbdata->RbHandle;
+ return EFI_SUCCESS;
+ } else return EFI_NOT_FOUND;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HbResAllocGetAllocAttributes()
+//
+// Description:
+// Returns the attributes of a PCI Root Bridge.
+//
+// Input:
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance
+// EFI_HANDLE RootBridgeHandle The device handle of the PCI Root Bridge
+// that the caller is interested in
+// UINT64 Attribute The pointer to attributes of the PCI Root Bridge
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid
+// EFI_INVALID_PARAMETER - Attributes is NULL
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HbResAllocGetAllocAttributes(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes)
+{
+ PCI_ROOT_BRG_DATA *rbdata;
+//----------------------------------
+ if(!This || !Attributes) return EFI_INVALID_PARAMETER;
+ rbdata=GetRbByHandle(This,RootBridgeHandle,NULL);
+ if(!rbdata)return EFI_INVALID_PARAMETER;
+ else *Attributes=rbdata->Owner->AllocAttrib;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HbResAllocStartBusEnumeration()
+//
+// Description:
+// This is the request from the PCI enumerator to set up
+// the specified PCI Root Bridge for bus enumeration process.
+//
+// Input:
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This PROTOCOL instance
+// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured
+// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid
+// EFI_DEVICE_ERROR - Request failed due to hardware error
+// EFI_OUT_OF_RESOURCES - Request failed due to lack of resources
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HbResAllocStartBusEnumeration(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration)
+{
+ PCI_ROOT_BRG_DATA *rbdata;
+ UINTN i;
+ EFI_STATUS Status;
+ ASLR_QWORD_ASD *qw;
+//-----------------------------
+ if(!Configuration || !This) return EFI_INVALID_PARAMETER;
+
+
+ rbdata=GetRbByHandle(This,RootBridgeHandle,&i);
+ if(!rbdata){
+ PCI_TRACE((TRACE_PCI,"Hb.StartBusEnumeration - Invalid Rb Handle Passed\n"));
+ ASSERT(rbdata);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //ThisCSP Function MIGHT Update rbdata->RbRes[] with bus ranges to scan
+ //and program corresponded RB registers to decode this ranges.
+ //If function overwrites BUS ranges this ROOT decodes IT MUST UPDATE rbdata->RbRes[]!
+ //If NOT it should not touch BUS resource descriptor.
+ Status=HbCspStartBusEnumeration((PCI_HOST_BRG_DATA*)This, rbdata,i);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"Hb.StartBusEnumeration - HbCspUpdateBusesBefore returned ERROR!\n"));
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ Status=GetResources(rbdata, (ASLR_QWORD_ASD**)Configuration, tResBus);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"Hb.StartBusEnum - RB Resources Invalid!\n"));
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ qw=(ASLR_QWORD_ASD*)*Configuration;
+
+ PCI_TRACE((TRACE_PCI,"PciRb#%d: Enumerating Buses 0x%lX - 0x%lX \n", i, qw->_MIN, qw->_MIN+qw->_LEN-1));
+ PCI_TRACE((TRACE_PCI,"=====================================================================\n\n"));
+
+
+ ((PCI_HOST_BRG_DATA*)This)->EnumStarted=TRUE;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HbResAllocSetBusNumbers()
+//
+// Description:
+// This function programs the PCI Root Bridge hardware so that
+// it decodes the specified PCI bus range
+//
+//Input:
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance
+// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured
+// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid
+// EFI_INVALID_PARAMETER - Configuration is NULL
+// EFI_INVALID_PARAMETER - Configuration does not point to a valid ACPI resource descriptor
+// EFI_INVALID_PARAMETER - Configuration contains one or more memory or IO ACPI resource descriptor
+// EFI_INVALID_PARAMETER - Address Range Minimum or Address Range Length fields in Configuration
+// are invalid for this Root Bridge.
+// EFI_INVALID_PARAMETER - Configuration contains one or more invalid ACPI resource descriptor
+// EFI_DEVICE_ERROR - Request failed due to hardware error
+// EFI_OUT_OF_RESOURCES - Request failed due to lack of resources
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HbResAllocSetBusNumbers(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration)
+{
+ PCI_ROOT_BRG_DATA *rbdata;
+ UINTN i;
+ EFI_STATUS Status;
+ ASLR_QWORD_ASD *qw=(ASLR_QWORD_ASD*)Configuration;
+//-----------------------------
+ if(!Configuration || !This) return EFI_INVALID_PARAMETER;
+
+ rbdata=GetRbByHandle(This,RootBridgeHandle,&i);
+ if(!rbdata) {
+ PCI_TRACE((TRACE_PCI,"Hb.SetBusNumbers - Invalid RB Hndle Passed\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status=SetResources(rbdata, Configuration, tResBus, TRUE);
+
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"Hb.SetBusNumbers - Invalid Resoutce Descriptor(s) Passed\n"));
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ //Call CSP function to update RB Buses accordinaly submited information
+ Status=HbCspSetBusNnumbers((PCI_HOST_BRG_DATA*)This, rbdata, i);
+
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"Hb.SetBusNumbers - HbCspUpdateBusesAfter returned ERROR!\n"));
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ PCI_TRACE((TRACE_PCI,"PciRb#%d: Assigning Buses 0x%lX - 0x%lX \n", i, qw->_MIN, qw->_MIN+qw->_LEN-1));
+
+
+ rbdata->BusesSet=TRUE;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FreeUsedResources()
+//
+// Description:
+// Cleans internal RB data and free resources allocated trough GCD.
+//
+// Input:
+// PCI_ROOT_BRG_DATA *RootBrg Pointer to RB Private data.
+//
+// Output: NONE
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID FreeUsedResources(PCI_ROOT_BRG_DATA *RootBrg){
+ ASLR_QWORD_ASD *res;
+ UINTN i;
+ DXE_SERVICES *dxe;
+ EFI_STATUS Status;
+//------------------------------
+ Status=LibGetDxeSvcTbl(&dxe);
+ ASSERT_EFI_ERROR(Status);
+
+ for(i=0; i<RootBrg->ResCount; i++){
+ res=RootBrg->RbRes[i];
+
+ //Clean only IO and MMIO resources buses was submitted in different call and must stay.
+ if(res->Type < ASLRV_SPC_TYPE_BUS){
+ if(res->_MIN != 0){
+ //Free IO
+ if(res->Type==ASLRV_SPC_TYPE_IO){
+ Status=dxe->FreeIoSpace(res->_MIN, res->_LEN);
+ } else {
+ Status=dxe->FreeMemorySpace(res->_MIN, res->_LEN);
+ }
+ ASSERT_EFI_ERROR(Status);
+ } //res_MIN
+ //Don't free resource list, it will be reupdated with RPLACE option.
+ }
+ } //for
+
+ //Almost done now clean AcpiRbRes[] data
+ pBS->SetMem(&RootBrg->AcpiRbRes[0], sizeof(RootBrg->AcpiRbRes),0);
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HbResAllocSubmitResources()
+//
+// Description:
+// Submits the I/O and memory resource requirements for the specified PCI Root Bridge
+//
+// Input:
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance
+// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured
+// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid
+// EFI_INVALID_PARAMETER - Configuration is NULL
+// EFI_INVALID_PARAMETER - Configuration does not point to a valid ACPI resource descriptor
+// EFI_INVALID_PARAMETER - Configuration includes a resource descriptor of unsupported type
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HbResAllocSubmitResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration)
+{
+ PCI_ROOT_BRG_DATA *rbdata;
+ UINTN i, sz=sizeof(UINT32);
+ EFI_STATUS Status,AllocStatus;
+// UINT32 mc; //MemCeil Variable Available?
+// EFI_GUID gvg = EFI_GLOBAL_VARIABLE;
+ ASLR_EndTag *endtag=(ASLR_EndTag*)Configuration;
+//-----------------------------
+ if(!Configuration || !This) return EFI_INVALID_PARAMETER;
+
+ rbdata=GetRbByHandle(This,RootBridgeHandle,&i);
+ if(!rbdata) {
+ PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - Invalid RB Hndle Passed\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //Update Internal data structures with Resource Request
+ Status=SetResources(rbdata, Configuration, tResIoMem, TRUE);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - Invalid Resoutce Descriptor(s) Passed\n"));
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+
+ //Call CSP function to update RB Resources Windows
+ Status=HbCspSubmitResources((PCI_HOST_BRG_DATA*)This, rbdata,i);
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - HbCspSubmitResources return an ERROR!\n"));
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+ rbdata->ResSubmited=TRUE; //set the FLAG
+
+ //Check if we are able to accomodate resource request
+ //CSP Routine First...
+ PCI_TRACE((TRACE_PCI,"PciRb: Calling CSP HbCspAllocateResources() - returned "));
+ AllocStatus=HbCspAllocateResources((PCI_HOST_BRG_DATA*)This, rbdata,i);
+ PCI_TRACE((TRACE_PCI,"%r\n", AllocStatus));
+
+ if(EFI_ERROR(AllocStatus)){
+ if( AllocStatus==EFI_UNSUPPORTED ){
+ PCI_TRACE((TRACE_PCI,"PciRb: Calling Generic AllocateResources() routine; returned "));
+ AllocStatus=AllocateResources(rbdata);
+ PCI_TRACE((TRACE_PCI,"%r\n", AllocStatus));
+ }
+ //If custom function Fails or Generic on report it.
+ if(EFI_ERROR(AllocStatus)){
+ PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - Fail to allocate resources AllocStatus=%r\n",AllocStatus));
+ }
+ } else {
+ //Custom function Returned Correct Status:
+ //Check if Above 4G Memory was correctly updated by custom function
+ //and if it match with Above4g setup question?
+ if((gRbSetupData.Above4gDecode==0) && (rbdata->AcpiRbRes[raMmio64].Len!=0)){
+ rbdata->AcpiRbRes[raMmio64].Min=0;
+ rbdata->AcpiRbRes[raMmio64].Max=0;
+ rbdata->AcpiRbRes[raMmio64].Len=0;
+ rbdata->AcpiRbRes[raMmio64].AddrUsed=0;
+ rbdata->AcpiRbRes[raMmio64].AllocType=0;
+ PCI_TRACE((TRACE_PCI,"PciRB: PCI Above 4G Decode Setup Settings and Custom Alloc Function Data Mismatched\n"));
+ }
+ }
+
+ //Check if we can use previoce MRC settings
+ //if(!mc || EFI_ERROR(Status)){
+ Status = HbCspAdjustMemoryMmioOverlap((PCI_HOST_BRG_DATA*)This, rbdata,i );
+
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"Hb.SubmitResources - AdjustMmioOverlap() returned %r\n",Status));
+ //AdjustMmioOverlap() must return SUCCESS or Reset the system...
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ //Reflecting What TYPE and HOW MUCH of resouces is not enough...
+ if(EFI_ERROR(AllocStatus)) {
+ ((PCI_HOST_BRG_DATA*)This)->AllocPhase--;
+ FreeUsedResources(rbdata);
+ Status=AllocStatus;
+ }
+
+ if(EFI_ERROR(Status))return Status;
+
+ rbdata->ResAsquired=TRUE; //set the FLAG
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HbResAllocGetProposedResources()
+//
+// Description:
+// This function returns the proposed resource settings for the specified
+// PCI Root Bridge
+//
+// Input:
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance
+// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured
+// VOID **Configuration Pointer to the pointer to the PCI bus resource descriptor
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid
+// EFI_DEVICE_ERROR - Request failed due to hardware error
+// EFI_OUT_OF_RESOURCES - Request failed due to lack of resources
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HbResAllocGetProposedResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration)
+{
+/*
+ PCI_ROOT_BRG_DATA *rbdata;
+ UINTN i;
+ EFI_STATUS Status;
+//-----------------------------
+ if(!Configuration || !This) return EFI_INVALID_PARAMETER;
+
+ rbdata=GetRbByHandle(This,RootBridgeHandle,&i);
+ if(!rbdata) {
+ PCI_TRACE((TRACE_PCI,"Hb.GetProposedResources - Invalid RB Hndle Passed\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //Call CSP function to update RB Resources Windows
+ Status=HbCspGetProposedResources((PCI_HOST_BRG_DATA*)This, rbdata,i);
+
+ if(EFI_ERROR(Status)){
+ PCI_TRACE((TRACE_PCI,"Hb.GetProposedResources - HbCspGetProposedResources return an ERROR!\n"));
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+*/
+
+
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//
+// implement this function
+//
+//
+//
+//
+//
+//
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//
+
+
+ return EFI_UNSUPPORTED;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HbResAllocPreprocessController()
+//
+// Description:
+// This function is called for all the PCI controllers that the PCI
+// bus driver finds. Can be used to Preprogram the controller.
+//
+//Arguments:
+// Input:
+// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This Protocol instance
+// EFI_HANDLE RootBridgeHandle PCI Root Bridge to be configured
+// EFI_PCI_CONFIGURATION_ADDRESS PciBusAddress Address of the controller on the PCI bus
+// EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase The Phase during resource allocation
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Success
+// EFI_INVALID_PARAMETER - RootBridgeHandle is invalid
+// EFI_DEVICE_ERROR - Device pre-initialization failed due to hardware error.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HbResAllocPreprocessController(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_CONFIGURATION_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase)
+{
+// EFI_STATUS Status=0;
+ UINTN i;
+ PCI_ROOT_BRG_DATA *rb;
+//-----------------------------------
+ rb=GetRbByHandle(This,RootBridgeHandle,&i);
+ ASSERT(rb)
+ if(!rb) return EFI_INVALID_PARAMETER;
+ //Call CSP function...
+ return HbCspPreprocessController((PCI_HOST_BRG_DATA*)This,rb,i,PciAddress,Phase);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetTmr()
+//
+// Description:
+// Enables timer event to poll PCI IO and MEMORY.
+//
+//Arguments:
+// Input:
+// UINT64 Delay Delay value in us
+//
+// Output: EFI_EVENT if Success
+// NULL if unable to set timer event.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_EVENT SetTmr(UINT64 Delay)
+{
+ EFI_STATUS Status;
+ EFI_EVENT evt;
+//--------------------------------------------
+ Status=pBS->CreateEvent(EVT_TIMER,TPL_NOTIFY,NULL,NULL,&evt);
+ if (EFI_ERROR(Status)) return NULL;
+
+
+ Status = pBS->SetTimer(evt, TimerRelative, Delay);
+ if (EFI_ERROR(Status)){
+ pBS->CloseEvent(evt);
+ evt=NULL;
+ }
+ return evt;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: KillTmr()
+//
+// Description:
+// Disables and Clear timer event to poll PCI IO and MEMORY.
+//
+//Arguments:
+// Input:
+// EFI_EVENT TmrEvt Timer event to close.
+//
+// Output: Nothing
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+void KillTmr(EFI_EVENT TmrEvt)
+{
+ pBS->CloseEvent(TmrEvt);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PollMem
+//
+// Description: Poll Memory for a value or until times out.
+//
+// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Memory Width
+// IN UINT64 - Memory Address
+// IN UINT64 - Bit Mask
+// IN UINT64 - Value for exit
+// IN UINT64 - Timout
+// OUT UINT64 * - Contents of memory
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Found value
+// EFI_TIMEOUT - Did not find value.
+// EFI_INVALID_PARAMETER
+//
+// Modified: None
+//
+// Referrals: None
+//
+// Notes: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PollMem (
+ 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 Status;
+ EFI_EVENT Event;
+
+ if (Result==NULL ||((UINTN)Width>=(UINTN)EfiPciWidthFifoUint8)) return EFI_INVALID_PARAMETER;
+
+ Status = PciMemRead(This, Width, Address, 1, Result); //Read memory at least once.
+ if (EFI_ERROR(Status)) return Status;
+
+ if ((*Result & Mask)==Value) return EFI_SUCCESS; //If correct value, exit.
+ if (Delay == 0) return EFI_TIMEOUT;
+
+ Event=SetTmr(Delay);
+ if (!Event) return EFI_NOT_AVAILABLE_YET;
+
+ while(pBS->CheckEvent(Event)==EFI_NOT_READY){
+ Status = PciMemRead(This, Width, Address, 1, Result);
+ if (EFI_ERROR(Status)) break;
+ if ((*Result & Mask)==Value){
+ Status = EFI_SUCCESS;
+ break;
+ } else Status=EFI_TIMEOUT; //correct value?
+ }
+ KillTmr(Event); //Correct value not read, in time alloted.
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PollIo
+//
+// Description: Poll IO for a value or until times out.
+//
+// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Memory Width
+// IN UINT64 - Memory Address
+// IN UINT64 - Bit Mask
+// IN UINT64 - Value for exit
+// IN UINT64 - Timout
+// OUT UINT64 * - Contents of IO
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Found value
+// EFI_TIMEOUT - Did not find value.
+// EFI_INVALID_PARAMETER
+//
+// Modified: None
+//
+// Referrals: None
+//
+// Notes: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PollIo (
+ 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 Status;
+ EFI_EVENT Event;
+
+ if (Result==NULL) return EFI_INVALID_PARAMETER;
+ if ((UINTN)Width >= (UINTN)EfiPciWidthFifoUint8) return EFI_INVALID_PARAMETER;
+
+
+ Status = PciIoRead(This, Width, Address, 1, Result); //Read memory at least once.
+ if (EFI_ERROR(Status)) return Status;
+
+ if ((*Result & Mask)==Value) return EFI_SUCCESS; //If correct value, exit.
+ if (Delay == 0) return EFI_TIMEOUT;
+
+ Event=SetTmr(Delay);
+ if (!Event) return EFI_NOT_AVAILABLE_YET;
+
+ while(pBS->CheckEvent(Event)==EFI_NOT_READY){
+ Status = PciIoRead(This, Width, Address, 1, Result);
+ if (EFI_ERROR(Status)) break;
+ if ((*Result & Mask)==Value){
+ Status = EFI_SUCCESS;
+ break;
+ } else Status=EFI_TIMEOUT; //correct value?
+ }
+ KillTmr(Event); //Correct value not read, in time alloted.
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PciMemRead
+//
+// Description: Read memory IO into buffer.
+//
+// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Memory Width
+// IN UINT64 - Memory Address
+// IN UINTN - Number of width reads.
+// IN OUT VOID * - Buffer where memory is read into.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful read.
+// EFI_INVALID_PARAMETER
+//
+// Modified: None
+//
+// Referrals: None
+//
+// Notes: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciMemRead (
+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)
+{
+ UINTN IncrementType = Width & ~3;
+ UINT8 IncrementValue = 1 << (Width & 3); //1st 2 bits currently define width. Other bits define type.
+ UINT8 IncrementBuffer = 0;
+ UINT8 IncrementAddress = 0;
+
+ if (Buffer==NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER;
+ if (IncrementType > 16 || IncrementValue > 8) return EFI_INVALID_PARAMETER;
+
+ if(sizeof(UINTN)==8){
+ if (( 0xffffffffffffffff - Count * IncrementValue) <= Address)
+ return EFI_INVALID_PARAMETER;
+ } else {
+ if ((Address + Count * IncrementValue) > 0xffffffff)
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (IncrementType)
+ {
+ case 0: //EfiPciWidthUintxx
+ IncrementAddress = IncrementBuffer = IncrementValue;
+ break;
+ case 4: //EfiPciWidthFifoUintxx
+ IncrementBuffer = IncrementValue;
+ break;
+ default: //EfiPciWidthFillUintxx
+ IncrementAddress = IncrementValue;
+ }
+
+ while(Count--)
+ {
+ switch(IncrementValue)
+ {
+ case 1: //byte
+ *(UINT8*) Buffer = *(UINT8*)Address;
+ break;
+ case 2: //word
+ *(UINT16*) Buffer = *(UINT16*)Address;
+ break;
+ case 4: //dword
+ *(UINT32*) Buffer = *(UINT32*)Address;
+ break;
+ case 8: //dword
+ *(UINT64*) Buffer = *(UINT64*)Address;
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ }
+ (UINT8*) Buffer += IncrementBuffer;
+ Address += IncrementAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PciMemWrite
+//
+// Description: Write memory IO from buffer.
+//
+// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Memory Width
+// IN UINT64 - Memory Address
+// IN UINTN - Number of width writes.
+// IN OUT VOID * - Buffer where memory is written from.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful write.
+// EFI_INVALID_PARAMETER
+//
+// Modified: None
+//
+// Referrals: None
+//
+// Notes: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciMemWrite (
+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)
+{
+ UINTN IncrementType = Width & ~3;
+ UINT8 IncrementValue = 1 << (Width & 3); //1st 2 bits currently define width. Other bits define type.
+ UINT8 IncrementBuffer = 0;
+ UINT8 IncrementAddress = 0;
+
+ if (Buffer==NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER;
+ if (IncrementType > 16 || IncrementValue > 8) return EFI_INVALID_PARAMETER;
+
+ if ((Address + Count * IncrementValue) > 0xffffffff)
+ return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge.
+
+ switch (IncrementType)
+ {
+ case 0: //EfiPciWidthUintxx
+ IncrementAddress = IncrementBuffer = IncrementValue;
+ break;
+ case 4: //EfiPciWidthFifoUintxx
+ IncrementBuffer = IncrementValue;
+ break;
+ default: //EfiPciWidthFillUintxx
+ IncrementAddress = IncrementValue;
+ }
+
+ while(Count--)
+ {
+ switch(IncrementValue)
+ {
+ case 1: //byte
+ *(UINT8*) Address = *(UINT8*)Buffer;
+ break;
+ case 2: //word
+ *(UINT16*) Address = *(UINT16*)Buffer;
+ break;
+ case 4: //dword
+ *(UINT32*) Address = *(UINT32*)Buffer;
+ break;
+ case 8: //dword
+ *(UINT64*) Address = *(UINT64*)Buffer;
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ }
+ (UINT8*) Buffer += IncrementBuffer;
+ Address += IncrementAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PciIoRead
+//
+// Description: Read IO into buffer.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * - This
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH - Io Width
+// IN UINT64 - Io Address
+// IN UINTN - Number of width reads.
+// IN OUT VOID * - Buffer where Io is read into.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful read.
+// EFI_INVALID_PARAMETER
+//
+// Modified: None
+//
+// Referrals: None
+//
+// Notes: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoRead (
+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)
+{
+ UINTN IncrementType = Width & ~3;
+ UINT8 IncrementValue = 1 << (Width & 3); //1st 2 bits currently define width. Other bits define type.
+ UINT8 IncrementBuffer = 0;
+ UINT8 IncrementAddress = 0;
+
+ if (Buffer==NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER;
+ if (IncrementType > 16 || IncrementValue > 8) return EFI_INVALID_PARAMETER;
+
+ if ((Address + Count * IncrementValue) > 0xffff)
+ return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge.
+
+ switch (IncrementType)
+ {
+ case 0: //EfiPciWidthUintxx
+ IncrementAddress = IncrementBuffer = IncrementValue;
+ break;
+ case 4: //EfiPciWidthFifoUintxx
+ IncrementBuffer = IncrementValue;
+ break;
+ default: //EfiPciWidthFillUintxx
+ IncrementAddress = IncrementValue;
+ }
+
+ while(Count--)
+ {
+ switch(IncrementValue)
+ {
+ case 1: //byte
+ *(UINT8*) Buffer = IoRead8((UINT16)Address);
+ break;
+ case 2: //word
+ *(UINT16*) Buffer = IoRead16((UINT16)Address);
+ break;
+ case 4: //dword
+ *(UINT32*) Buffer = IoRead32((UINT16)Address);
+ break;
+ case 8:
+ *(UINT32*) Buffer = IoRead32((UINT16)Address);
+ *((UINT32*)((UINT32*)Buffer+1)) = IoRead32((UINT16)(Address+4));
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ }
+ (UINT8*) Buffer += IncrementBuffer;
+ Address += IncrementAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PciIoWrite
+//
+// Description: Write IO from buffer.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol instance
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Pci Width
+// IN UINT64 Address IO Address
+// IN UINTN Count Number of width writes.
+// IN OUT VOID *Buffer where Pci registers are written from.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful write.
+// EFI_INVALID_PARAMETER
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciIoWrite (
+ 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)
+{
+ UINTN IncrementType = Width & ~3;
+ UINT8 IncrementValue = 1 << (Width & 3); //1st 2 bits currently define width. Other bits define type.
+ UINT8 IncrementBuffer = 0;
+ UINT8 IncrementAddress = 0;
+
+ if (Buffer==NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER;
+ if (IncrementType > 16 || IncrementValue > 4) return EFI_INVALID_PARAMETER;
+
+ if ((Address + Count * IncrementValue) > 0xffff)
+ return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge.
+
+ switch (IncrementType)
+ {
+ case 0: //EfiPciWidthUintxx
+ IncrementAddress = IncrementBuffer = IncrementValue;
+ break;
+ case 4: //EfiPciWidthFifoUintxx
+ IncrementBuffer = IncrementValue;
+ break;
+ default: //EfiPciWidthFillUintxx
+ IncrementAddress = IncrementValue;
+ }
+
+ while(Count--)
+ {
+ switch(IncrementValue)
+ {
+ case 1: //byte
+ IoWrite8((UINT16)Address,*(UINT8*) Buffer);
+ break;
+ case 2: //word
+ IoWrite16((UINT16)Address,*(UINT16*) Buffer);
+ break;
+ default: //dword
+ IoWrite32((UINT16)Address,*(UINT32*) Buffer);
+ break;
+ }
+ (UINT8*) Buffer += IncrementBuffer;
+ Address += IncrementAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CopyMem
+//
+// Description: Copy PCI memory to PCI memory in bridge.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol instance
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Pci Width
+// IN UINT64 DestAddress Pci Address
+// IN UINT64 SrcAddress Pci Address
+// IN UINTN Count Number of width writes.
+// IN OUT VOID *Buffer where Pci registers are written from.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful copy.
+// EFI_INVALID_PARAMETER
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CopyMem (
+ 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)
+{
+ INTN IncrementValue;
+
+ if ((SrcAddress == 0) || (DestAddress==0)) return EFI_INVALID_PARAMETER;
+ if ((UINTN)Width > (UINTN)EfiPciWidthUint64) return EFI_INVALID_PARAMETER;
+
+ IncrementValue = (INTN)1<<(Width&3);
+ if ((SrcAddress + Count * IncrementValue) > 0xffffffff)
+ return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge.
+
+ if ((DestAddress + Count * IncrementValue) > 0xffffffff)
+ return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge.
+
+
+ if (SrcAddress==DestAddress) return EFI_SUCCESS; //Nothing to do.
+
+
+ if ( (DestAddress > SrcAddress) && (SrcAddress + Count * IncrementValue) ) {
+ SrcAddress += (Count-1) * IncrementValue; //End of source
+ DestAddress += (Count-1) * IncrementValue; //End of destination
+ IncrementValue = -IncrementValue; //Count backwards.
+ } //If Destination addres and after and overlapps Source Address, Copy backwards.
+
+ switch(IncrementValue)
+ {
+ case 1:
+ case -1:
+ while (Count--)
+ {
+ *(UINT8*) DestAddress = *(UINT8*)SrcAddress;
+ SrcAddress += IncrementValue;
+ DestAddress += IncrementValue;
+ }
+ break;
+ case 2:
+ case -2:
+ while (Count--)
+ {
+ *(UINT16*) DestAddress = *(UINT16*)SrcAddress;
+ SrcAddress += IncrementValue;
+ DestAddress += IncrementValue;
+ }
+ break;
+ default:
+ while (Count--)
+ {
+ *(UINT32*) DestAddress = *(UINT32*)SrcAddress;
+ SrcAddress += IncrementValue;
+ DestAddress += IncrementValue;
+ }
+ break;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PciRead()
+//
+// Description:
+// Read Pci registers into buffer.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol instance
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Pci Width
+// IN UINT64 Address Pci Address
+// IN UINTN Count Number of width writes.
+// IN OUT VOID *Buffer where Pci registers are written from.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful read.
+// EFI_INVALID_PARAMETER
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciRead (
+ 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_BRG_DATA *Private = (PCI_ROOT_BRG_DATA*)This;
+
+ if (Buffer == NULL ||((UINTN)Width>=(UINTN)EfiPciWidthMaximum) ) return EFI_INVALID_PARAMETER;
+
+ return RootBridgeIoPciRW (Private, Width, Address, Count, Buffer, FALSE);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PciWrite()
+//
+// Description:
+// Write Pci registers from buffer.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol instance
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Pci Width
+// IN UINT64 Address Pci Address
+// IN UINTN Count Number of width writes.
+// IN OUT VOID *Buffer where Pci registers are written from.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful write.
+// EFI_INVALID_PARAMETER
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciWrite (
+ 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_BRG_DATA *Private = (PCI_ROOT_BRG_DATA*)This;
+
+ if (Buffer == NULL || ((UINTN)Width>=(UINTN)EfiPciWidthMaximum)) return EFI_INVALID_PARAMETER;
+
+ Private = (PCI_ROOT_BRG_DATA *) This;
+
+ return RootBridgeIoPciRW (Private, Width, Address, Count, Buffer, TRUE);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: Map()
+//
+// Description:
+// Provide addresses required to access system memory from a DMA
+// bus master.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation
+// IN VOID *HostAddress Host address
+// IN OUT UINTN **NumberOfBytes Number of bytes
+// OUT EFI_PHYSICAL_ADDRESS *DeviceAddress Device Address
+// OUT VOID **Mapping
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful map
+//
+// Modified: None
+//
+// Referrals: None
+//
+// Notes: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Map (
+ 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 Status;
+// PCI_ROOT_BRIDGE_MAPPING *mapping;
+ EFI_PHYSICAL_ADDRESS addr;
+//-------------------------------------------------
+
+ if ( !HostAddress || !NumberOfBytes || !DeviceAddress || !Mapping )
+ return EFI_INVALID_PARAMETER;
+
+ if ((UINT32)Operation >= (UINT32)EfiPciOperationMaximum ) return EFI_INVALID_PARAMETER;
+
+ *Mapping=NULL;
+
+ addr=(EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+
+ if ((addr + *NumberOfBytes) > 0xffffffff)Status=RbCspIoPciMap((PCI_ROOT_BRG_DATA*)This,
+ Operation, addr, NumberOfBytes, DeviceAddress, Mapping);
+ else *DeviceAddress = addr;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: Unmap
+//
+// Description: Remove mapping
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance
+// IN VOID *Mapping Pointer to Mapping formation to Unmap
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful unmapping.
+// EFI_INVALID_PARAMETER
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Unmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping)
+
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ PCI_ROOT_BRIDGE_MAPPING *mapping=(PCI_ROOT_BRIDGE_MAPPING*)Mapping;
+//-------
+
+ if (mapping!=NULL) Status=RbCspIoPciUnmap((PCI_ROOT_BRG_DATA*)This,mapping);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AllocateBuffer
+//
+// Description: Allocate buffer for PCI use.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance
+// IN EFI_ALLOCATE_TYPE Type Alloocation Type (ignored and uses AllocateMaxAddress)
+// IN EFI_MEMORY_TYPE MemoryType Memory Type (ex. EfiBootServicesData)
+// IN UINTN Pages Number of pages to allocate.
+// OUT VOID **HostAddress Host Address
+// IN UINT64 Attributes Allocation Attributes.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful allocation.
+// EFI_UNSUPPORTED - Attribute not supported.
+// EFI_INVALID_PARAMETER
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+#define BUFF_ATTR (EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |\
+ EFI_PCI_ATTRIBUTE_MEMORY_CACHED |\
+ EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE)
+//---------------------------------------------------------------
+EFI_STATUS AllocateBuffer (
+ 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)
+
+{
+ //PCI_ROOT_BRIDGE_STRUCT *Private = (PCI_ROOT_BRIDGE_STRUCT *)This;
+
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS addr;
+
+ if (HostAddress == NULL) return EFI_INVALID_PARAMETER;
+
+ // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
+ if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData)
+ return EFI_INVALID_PARAMETER;
+
+ //Check if legal Attributes for this function is passed
+ //Check if any other Attributes set except supported
+ if( Attributes & ~BUFF_ATTR ) return EFI_UNSUPPORTED;
+
+
+ //865 chipset does not support any of Attributes above so as spec. says ignore it
+ //and Allocate buffer
+ // Limit allocations to memory below 4GB
+ addr = 0xffffffff;
+
+ Status = pBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &addr);
+ if (EFI_ERROR(Status)) return Status;
+
+ *HostAddress = (VOID *)(UINTN)addr;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: FreeBuffer()
+//
+// Description: Frees buffer
+//
+// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance
+// IN UINTN Pages Number of pages to free.
+// IN VOID* HostAddress Host Address
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful free.
+// EFI_INVALID_PARAMETER
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress)
+
+{
+ return pBS->FreePages((EFI_PHYSICAL_ADDRESS) HostAddress, Pages);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: Flush()
+//
+// Description:
+// Flush buffer used by PCI DMA Transfere.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful flushing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Flush (IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This)
+{
+ return EFI_SUCCESS; //Doesn't need buffer to be flushed.
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: GetAttributes()
+//
+// Description: Get Supported and Current Root Bridge Attributes.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance
+// OUT UINT64 *Supported Supported Attributes
+// OUT UINT64 *Attributes Current Attributes
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Successful reading attributes.
+// EFI_INVALID_PARAMETER - If both for attributes are invalid.
+//
+// Notes: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes)
+{
+ PCI_ROOT_BRG_DATA *Private = (PCI_ROOT_BRG_DATA*) This;
+
+ if (Attributes == NULL && Supported == NULL) return EFI_INVALID_PARAMETER;
+
+ if (Supported) *Supported = Private->Supports;
+ if (Attributes) *Attributes = Private->Attributes;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: GetAttributes()
+//
+// Description: Get Supported and Current Root Bridge Attributes.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance
+// IN UINT64 Attributes
+// IN OUT UINT64 *ResourceBase Resource Base (optional, unused)
+// IN OUT UINT64 *ResourceLength Resource Length (optional, unused)
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS Successful setting attributes.
+// EFI_UNSUPPORTED Unsupported attributes
+//
+// Notes: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength)
+{
+ EFI_STATUS Status;
+ PCI_ROOT_BRG_DATA *Private = (PCI_ROOT_BRG_DATA *) This;
+//------------------------------------
+
+
+ //First Check if RB supports passed Attributes
+ if((Attributes & Private->Supports)!=Attributes)return EFI_UNSUPPORTED;
+
+ //Note: Only some attributes can be both enabled and disabled.
+
+ Status=RbCspIoPciAttributes(Private, Attributes, ResourceBase, ResourceLength);
+
+ if(EFI_ERROR(Status)) return Status;
+
+ //Update the attributes property
+ //Private->Attributes&=Attributes; //reset all bits that has to be reseted
+ Private->Attributes |= Attributes; //set bits that has to be seted
+
+ return Status;
+}
+//--------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: Configuration()
+//
+// Description: Returns, using ACPI 2.0 Descriptors, resources allocated.
+//
+// Input: IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+// IN VOID *Resources
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Configuration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources)
+{
+ PCI_ROOT_BRG_DATA *rb=(PCI_ROOT_BRG_DATA*)This;
+ EFI_STATUS Status=0;
+//---------------------
+ if(rb->ResAsquired)
+ Status=GetResources((PCI_ROOT_BRG_DATA*)This, (ASLR_QWORD_ASD**)Resources, tResAll);
+ else Status=EFI_NOT_AVAILABLE_YET;
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: PciRw()
+//
+// Description: Provides Read and Write access to the PCI Configuration Space.
+//
+// Input:
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This Protocol Instance
+// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width Data Width.
+// IN UINT64 Address PCI Config Address
+// IN UINT32 Mask Mask for the bits to be preserved
+// IN UINT32 Value Data to be written
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - OK
+// EFI_DEVICE_ERROR - HW ERROR
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID PciRw (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT32 Mask,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data;
+
+ Status = This->Pci.Read (This,Width,Address,1,&Data);
+ ASSERT_EFI_ERROR (Status);
+
+ Data = (Data & Mask) | Value;
+ Status = This->Pci.Write (This,Width,Address,1,&Data);
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/PCI/PciPort.c b/Core/EM/PCI/PciPort.c
new file mode 100644
index 0000000..aa6b5c4
--- /dev/null
+++ b/Core/EM/PCI/PciPort.c
@@ -0,0 +1,926 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/PciBus/PciPort.c 22 9/10/12 12:54p Yakovlevs $
+//
+// $Revision: 22 $
+//
+// $Date: 9/10/12 12:54p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/PciBus/PciPort.c $
+//
+// 22 9/10/12 12:54p Yakovlevs
+// [TAG] EIP93341
+// [Category] Improvement
+// [Description] Preserve PCI DEV/LNK/SLT control register in S3 resume
+// path.
+// [Files] PciBus.c PciBus.sd PciBus.uni PciSetup.h PciPort.c
+//
+// 21 11/09/11 1:55p Yakovlevs
+// [TAG] EIP71380
+// [Category] New Feature
+// [Description] Core support for CSM opt-out feature
+// [Files] PciBus.c; PciPort.c; PciBus.sd; PciBus.uni; PciSetup.h;
+// PciBusSetup.c;
+//
+// 20 4/11/11 10:42a Yakovlevs
+// SkipDevice() changed.
+//
+// 19 4/05/11 11:26a Yakovlevs
+// [TAG] EIP 38174; EIP 53475;
+// [Description] 38174 Generic support to handle PCI OUT OF RESOURDCES
+// added.
+// 53475 PCI Express 3.0 support added.
+// [Files] PciBus.c; PciBus.mak; PciHostBridge.c; PciBus.h;
+// PciHostBridge.c; PciPort.c;
+//
+// 17 1/31/11 2:33p Yakovlevs
+// [TAG] EIP43879
+// [Category] New Feature
+// [Description] Added new conditions to have Overwrite Option ROM hook
+// called for every device.
+// [Files] PciPort.c
+//
+// 16 1/28/11 3:01p Yakovlevs
+// [TAG] EIP43879
+// [Category] New Feature
+// [Description] Added PciPortOemGetOptRom() OEM Hook to override
+// content of the PCI Device Option ROM.
+// [Files] PciBus.c; PciPort.c; PciPort.h; PciBus.mak; PciBus.sdl
+//
+// 15 12/08/10 3:22p Yakovlevs
+// Removed Setup Option "Selectable DeEmphasis" since it is HwInit Bit.
+//
+// 14 11/11/10 11:58a Yakovlevs
+//
+// 13 10/18/10 1:23p Yakovlevs
+// Link Training retry and Timeout moved in #if PCI_EXPRESS_SUPPORT scope.
+//
+// 12 8/16/10 1:12p Yakovlevs
+// Added ASPM Programming cipset hook
+//
+// 11 3/01/10 6:12p Yakovlevs
+// Pci Express V2.1 Support Added.
+//
+// 10 9/22/09 6:02p Yakovlevs
+// 1. Added infrastructure to ELINKs as porting Functions delivered from
+// Platform and Chipset files. Now you can port PCI Bus driver without
+// modifying Core files
+//
+// 9 4/28/09 3:49p Yakovlevs
+// Changes related to AmiBoardInfo protocol and Multiplatform support.
+//
+// 8 3/23/09 4:57p Yakovlevs
+// Added generic support for PCI Express Hot-Plug.
+//
+// 7 2/03/09 1:28p Yakovlevs
+//
+// 6 1/30/09 12:47p Yakovlevs
+// Added Porting functoion to skip PCI Device from enumeration.
+//
+// 5 10/01/08 7:10p Yakovlevs
+// Updated AMI FUNC HEADER information.
+//
+// 4 10/01/08 12:34p Yakovlevs
+//
+// 3 9/25/08 12:00p Yakovlevs
+//
+// 1 6/05/08 7:14p Yakovlevs
+//
+// 1 6/05/08 7:06p Yakovlevs
+//
+// 1 6/05/08 6:46p Yakovlevs
+//
+// 2 10/23/07 12:59p Felixp
+//
+// 1 10/18/07 11:22a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: PciPort.c
+//
+// Description: PCI porting
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <EFI.h>
+#include <Dxe.h>
+#include <Token.h>
+#include <PciBus.h>
+#include <PciHostBridge.h>
+#include <Setup.h>
+#include "PciSetup.h"
+#include "PciPort.h"
+
+//----------------------------------------------------------------------
+//Define Variables == TOKENS to be able to use binary
+// See token help for details
+//----------------------------------------------------------------------
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: NbDmiL0ExitLatency;
+//
+// Description: Variable to replace NB_DMI_L0_EXIT_LATENCY token.
+//
+// Notes: const UINT16
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const UINT16 NbDmiL0ExitLatency =
+#ifdef NB_DMI_L0_EXIT_LATENCY
+ NB_DMI_L0_EXIT_LATENCY
+#else
+ 0
+#endif
+ ;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: NbDmiL1ExitLatency;
+//
+// Description: Variable to replace NB_DMI_L1_EXIT_LATENCY token.
+//
+// Notes: const UINT16
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const UINT16 NbDmiL1ExitLatency =
+#ifdef NB_DMI_L1_EXIT_LATENCY
+ NB_DMI_L1_EXIT_LATENCY
+#else
+ 0
+#endif
+ ;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: SbDmiL0ExitLatency;
+//
+// Description: Variable to replace SB_DMI_L0_EXIT_LATENCY token.
+//
+// Notes: const UINT16
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const UINT16 SbDmiL0ExitLatency =
+#ifdef SB_DMI_L0_EXIT_LATENCY
+ SB_DMI_L0_EXIT_LATENCY
+#else
+ 0
+#endif
+ ;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: SbDmiL1ExitLatency;
+//
+// Description: Variable to replace SB_DMI_L1_EXIT_LATENCY token.
+//
+// Notes: const UINT16
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const UINT16 SbDmiL1ExitLatency =
+#ifdef SB_DMI_L1_EXIT_LATENCY
+ SB_DMI_L1_EXIT_LATENCY
+#else
+ 0
+#endif
+ ;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: NbDmiAspmSupport;
+//
+// Description: Variable to replace NB_DMI_ASPM_SUPPORT token.
+//
+// Notes: const UINT16
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const UINT16 NbDmiAspmSupport =
+#ifdef NB_DMI_ASPM_SUPPORT
+ NB_DMI_ASPM_SUPPORT
+#else
+ 0
+#endif
+ ;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: SbDmiAspmSupport;
+//
+// Description: Variable to replace SB_DMI_ASPM_SUPPORT token.
+//
+// Notes: const UINT16
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const UINT16 SbDmiAspmSupport =
+#ifdef SB_DMI_ASPM_SUPPORT
+ SB_DMI_ASPM_SUPPORT
+#else
+ 0
+#endif
+ ;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: SbInternalDelay;
+//
+// Description: Variable to replace SB_INTERNAL_DELAY token.
+//
+// Notes: const UINT16
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const UINT16 SbInternalDelay =
+#ifdef SB_INTERNAL_DELAY
+ SB_INTERNAL_DELAY
+#else
+ 0
+#endif
+ ;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: S3VideoRepost;
+//
+// Description: Variable to replace S3_VIDEO_REPOST_SUPPORT token.
+//
+// Notes: const BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const BOOLEAN S3VideoRepost =
+#ifdef S3_VIDEO_REPOST_SUPPORT
+ S3_VIDEO_REPOST_SUPPORT
+#else
+ 0
+#endif
+;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: FixedBusAssign;
+//
+// Description: Variable to replace PCI_FIXED_BUS_ASSIGNMENT token.
+//
+// Notes: const BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const BOOLEAN FixedBusAssign =
+#ifdef PCI_FIXED_BUS_ASSIGNMENT
+ PCI_FIXED_BUS_ASSIGNMENT
+#else
+ 0
+#endif
+;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: ScanFullBusRange;
+//
+// Description: Variable to replace PCI_SCAN_FULL_BUS_RANGE token.
+//
+// Notes: const BOOLEAN
+// This option exists for testing purposes. If System will have additional
+// PCI devices which don't have tree strucuture it might be Pci Device Path
+// conflict
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const BOOLEAN ScanFullBusRange =
+#ifdef PCI_SCAN_FULL_BUS_RANGE
+ PCI_SCAN_FULL_BUS_RANGE
+#else
+ 0
+#endif
+;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: PciExpressSupport;
+//
+// Description: Variable to replace PCI_EXPRESS_SUPPORT token.
+//
+// Notes: const BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const BOOLEAN PciExpressSupport =
+#ifdef PCI_EXPRESS_SUPPORT
+ PCI_EXPRESS_SUPPORT
+#else
+ 0
+#endif
+;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: HotPlugSupport;
+//
+// Description: Variable to replace HOTPLUG_SUPPORT token.
+//
+// Notes: const BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const BOOLEAN HotPlugSupport =
+#ifdef HOTPLUG_SUPPORT
+ HOTPLUG_SUPPORT
+#else
+ 0
+#endif
+;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: PciXSupport;
+//
+// Description: Variable to replace PCI_X_SUPPORT token.
+//
+// Notes: const BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const BOOLEAN PciXSupport =
+#ifdef PCI_X_SUPPORT
+ PCI_X_SUPPORT
+#else
+ 0
+#endif
+;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: SriovSupport;
+//
+// Description: Variable to replace SRIOV_SUPPORT token.
+//
+// Notes: const BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const BOOLEAN SriovSupport =
+#ifdef SRIOV_SUPPORT
+ SRIOV_SUPPORT
+#else
+ 0
+#endif
+;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: Use4KBar;
+//
+// Description: Variable to replace PCI_4K_RESOURCE_ALIGNMENT token.
+//
+// Notes: const BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+const BOOLEAN Use4KBar =
+#ifdef PCI_4K_RESOURCE_ALIGNMENT
+ PCI_4K_RESOURCE_ALIGNMENT
+#else
+ 0
+#endif
+;
+
+
+//----------------------------------------------------------------------
+//Define Bord Porting Functions (Hooks) Herte...
+//----------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BrdGetPciSetupData()
+//
+// Description: Porting function which collects all PCI Bus Driver specific
+// SETUP configuration data and returns it to the PCI Bus Driver.
+//
+// Input:
+// PCI_SETUP_DATA* PciSetupData Pointer to the Pci Bus specific setup data buffer.
+//
+// Output: Nothing
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID BrdGetPciSetupData(PCI_SETUP_DATA *PciSetupData){
+ EFI_GUID SetupGuid = SETUP_GUID;
+ EFI_STATUS Status;
+ UINTN sz=sizeof(SETUP_DATA);
+ SETUP_DATA *SetupData=MallocZ(sizeof(SETUP_DATA));
+//-------------------------------------
+ //Get Setup Data
+ if ( SetupData==NULL) return;
+
+//Initially ALL Setup Data will be initialized with ZEROs
+//So id Defs
+
+ //Zero out PCI_SETUP_DATA buffer
+ pBS->SetMem(PciSetupData, sizeof(PCI_SETUP_DATA), 0);
+
+ //Get global setup variable
+ Status=GetEfiVariable(L"Setup",&SetupGuid, NULL, &sz, &SetupData);
+ if(EFI_ERROR(Status)){
+ //General PCI Settings: [] - default
+ //UINT8 PciLatency; //[32]\ 64 \ 96 \ 128 \ 160 \ 192 \ 224 \ 248
+ PciSetupData->PciLatency=32;
+#if PCI_X_SUPPORT
+ //UINT8 PciXLatency; // 32 \[64]\ 96 \ 128 \ 160 \ 192 \ 224 \ 248
+ PciSetupData->PciXLatency=64;
+#endif
+#if PCI_EXPRESS_SUPPORT
+ //PCI Express Device Settings: [] - default
+ //UINT8 RelaxedOrdering; //[Disable]\ Enable
+ //UINT8 ExtTagField; //[Disable]\ Enable
+ //UINT8 NoSnoop; // Disable \[Enable]
+ PciSetupData->NoSnoop=1;
+
+ //UINT8 MaxPayload; //[Auto]\ 128 \ 256 \ 512 \ 1024 \ 2048 \ 4096 (in bytes)
+ PciSetupData->MaxPayload=55;
+ //UINT8 MaxReadRequest; //[Auto]\ 128 \ 256 \ 512 \ 1024 \ 2048 \ 4096 (in bytes)
+ PciSetupData->MaxReadRequest=55;
+ //PCI Express Link settings: [] - default
+ //UINT8 AspmMode; //[Disable]\ Auto \ Forse L0
+ //UINT8 ExtendedSynch; //[Disable]\ Enable
+
+ //Fill in Default Values... (buffer was initialized with ZEROs)
+ //UINT8 LnkTrRetry; //Disable\ 2 \ 3 \[5]
+ PciSetupData->LnkTrRetry=5;
+ //UINT16 LnkTrTimout; //<1.[2]..100> (Microseconds uS)
+ PciSetupData->LnkTrTimeout=0x10;
+ //UINT8 LnkDisable; //[Keep ON == 0] / Disable ==1
+ PciSetupData->S3PciExpressScripts = 0;
+#endif
+ //UINTN S3ResumeVideoRepost //[Disable]\ Enable
+
+ //UINT8 Above4gDecode; //[Disable]\ Enable
+ //General PCI Settings: [] - default
+ //UINT8 VgaPallete; //[Disable]\ Enable
+ //UINT8 PerrEnable; //[Disable]\ Enable
+ //UINT8 SerrEnable; //[Disable]\ Enable
+#if AMI_HOTPLUG_INIT_SUPPORT
+ //INT8 HotPlug; // Disable \[Enable]
+ PciSetupData->HotPlug=1;
+ //UINT8 BusPadd; // Disable \[1]\ 2 \ 3 \ 4 \ 5
+ PciSetupData->BusPadd=1; // 0 1 2 3 4
+ //UINT8 IoPadd; // Disable \[ 4K]\ 8K \ 16K \ 32K
+ PciSetupData->IoPadd=0x1000; // 0 1 2 3 4 5 6 7
+ //UINT8 Mmio32Padd; // Disable \ 1M \ 4M \ 8M \[16M]\ 32M \ 64M \128M
+ PciSetupData->Mmio32Padd=0x1000000;
+ //UINT8 Mmio32PfPadd; // Disable \ 1M \ 4M \ 8M \[16M]\ 32M \ 64M \128M
+ PciSetupData->Mmio32PfPadd=0x1000000;
+ //UINT8 Mmio64Padd; //[Disable]\ 1M \ 4M \ 8M \ 16M \ 32M \ 64M \ 128M \ 256M \ 512M \ 1G
+ //UINT8 Mmio64PfPadd; //[Disable]\ 1M \ 4M \ 8M \ 16M \ 32M \ 64M \ 128M \ 256M \ 512M \ 1G
+#endif
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+ //Gen2 Device Settings
+
+ //UINT8 ComplTimeOut; //[Disable]\ Default \ 50 - 100 us \ 1ms - 10ms \ 16...
+
+ //UINT8 AriFwd; //[Disable]\ Enable
+ //UINT8 AtomOpReq; //[Disable]\ Enable
+ //UINT8 AtomOpEgressBlk; //[Disable]\ Enable
+ //UINT8 IDOReq; //[Disable]\ Enable
+ //UINT8 IDOCompl; //[Disable]\ Enable
+ //UINT8 LtrReport; //[Disable]\ Enable
+ //UINT8 E2ETlpPrBlk; //[Disable]\ Enable
+
+ //Gen2 Link Settings
+ //UINT8 LnkSpeed; //[Auto]\ 5.0 GHz \ 2.5 GHz
+ PciSetupData->LnkSpeed=55;
+ //UINT8 DeEmphasis; //[Disable]\ Enable
+ //UINT8 ClockPm; //[Disable]\ Enable
+ //UINT8 ComplSos; //[Disable]\ Enable
+
+ //UINT8 HwAutoWidth; //[Enable]\ Disable
+ //PciSetupData->HwAutoWidth=0;
+ //UINT8 HwAutoSpeed; //[Enable]\ Disable
+ //PciSetupData->HwAutoSpeed=0;
+#endif
+
+ } else {
+ //General PCI Settings: [] - default
+ PciSetupData->PciLatency = SetupData->PciLatency;
+#if PCI_X_SUPPORT
+ PciSetupData->PciXLatency = SetupData->PciXLatency;
+#endif
+#if PCI_EXPRESS_SUPPORT
+ //PCI Express Device Settings: [] - default
+ PciSetupData->RelaxedOrdering = SetupData->RelaxedOrdering;
+ PciSetupData->ExtTagField = SetupData->ExtTagField;
+ PciSetupData->NoSnoop = SetupData->NoSnoop;
+ PciSetupData->MaxPayload = SetupData->MaxPayload;
+ PciSetupData->MaxReadRequest = SetupData->MaxReadRequest;
+ //PCI Express Link settings: [] - default
+ PciSetupData->AspmMode = SetupData->AspmMode;
+ PciSetupData->ExtendedSynch = SetupData->ExtendedSynch;
+
+ //Fill in Default Values... (buffer was initialized with ZEROs)
+ //UINT8 LnkTrRetry; //[Disable]\ 2 \ 3 \ 5
+ PciSetupData->LnkTrRetry=SetupData->LnkTrRetry;
+ PciSetupData->LnkTrTimeout=SetupData->LnkTrTimeout;
+ PciSetupData->LnkDisable=SetupData->LnkDisable; //[Keep ON == 0] / Disable ==1
+ //UINT8 S3PciExpressScripts //[Disable]\ Enable
+ PciSetupData->S3PciExpressScripts = SetupData->S3PciExpressScripts;
+
+#endif
+#if S3_VIDEO_REPOST_SUPPORT
+ PciSetupData->S3ResumeVideoRepost = SetupData->S3ResumeVideoRepost;
+#endif
+ //General2 PCI Settings: [] - default
+ PciSetupData->VgaPallete = SetupData->VgaPallete;
+ PciSetupData->PerrEnable = SetupData->PerrEnable;
+ PciSetupData->SerrEnable = SetupData->SerrEnable;
+#if ABOVE_4G_PCI_DECODE
+ PciSetupData->Above4gDecode = SetupData->Above4gDecode;
+#endif
+
+#if AMI_HOTPLUG_INIT_SUPPORT
+ //INT8 HotPlug; // Disable \[Enable]
+ PciSetupData->HotPlug=SetupData->HotPlugEnable;
+ //if HP Enabled...
+ if(PciSetupData->HotPlug){
+ PciSetupData->BusPadd=SetupData->BusPadd;
+ PciSetupData->IoPadd=SetupData->IoPadd*0x400; //Stored in units of KB
+ PciSetupData->Mmio32Padd=SetupData->Mmio32Padd*0x100000;
+ PciSetupData->Mmio32PfPadd=SetupData->Mmio32PfPadd*0x100000;
+ if(PciSetupData->Above4gDecode == 1){
+ PciSetupData->Mmio64Padd=SetupData->Mmio64Padd*0x100000;
+ PciSetupData->Mmio64PfPadd=SetupData->Mmio64PfPadd*0x100000;
+ } else {
+ PciSetupData->Mmio64Padd=0;
+ PciSetupData->Mmio64PfPadd=0;
+ }
+ }
+#endif
+
+#if PCI_EXPRESS_GEN2_SUPPORT
+ //Gen2 Device Settings
+ //UINT8 ComplTimeOut; //[Disable]\ Default \ 50 - 100 us \ 1ms - 10ms \ 16...
+ PciSetupData->ComplTimeOut=SetupData->ComplTimeOut;
+ //UINT8 AriFwd; //[Disable]\ Enable
+ PciSetupData->AriFwd=SetupData->AriFwd;
+ //UINT8 AtomOpReq; //[Disable]\ Enable
+ PciSetupData->AtomOpReq=SetupData->AtomOpReq;
+ //UINT8 AtomOpEgressBlk; //[Disable]\ Enable
+ PciSetupData->AtomOpEgressBlk=SetupData->AtomOpEgressBlk;
+ //UINT8 IDOReq; //[Disable]\ Enable
+ PciSetupData->IDOReq=SetupData->IDOReq;
+ //UINT8 IDOCompl; //[Disable]\ Enable
+ PciSetupData->IDOCompl=SetupData->IDOCompl;
+ //UINT8 LtrReport; //[Disable]\ Enable
+ PciSetupData->LtrReport=SetupData->LtrReport;
+ //UINT8 E2ETlpPrBlk; //[Disable]\ Enable
+ PciSetupData->E2ETlpPrBlk=SetupData->E2ETlpPrBlk;
+
+ //Gen2 Link Settings
+ //UINT8 LnkSpeed; //[Auto]\ 5.0 GHz \ 2.5 GHz
+ PciSetupData->LnkSpeed=SetupData->LnkSpeed;
+ //UINT8 ComplSos; //[Disable]\ Enable
+ PciSetupData->ComplSos=SetupData->ComplSos;
+ //UINT8 ClockPm; //[Disable]\ Enable
+ PciSetupData->ClockPm=SetupData->ClockPm;
+ //UINT8 HwAutoWidth; //[Enable]\ Disable
+ PciSetupData->HwAutoWidth=SetupData->HwAutoWidth;
+ //UINT8 HwAutoSpeed; //[Enable]\ Disable
+ PciSetupData->HwAutoSpeed=SetupData->HwAutoSpeed;
+#endif
+ }
+ pBS->FreePool(SetupData);
+
+}
+
+//To avoid compilation error define STRUCT delivered trough eLink as extern function.
+#define OEM_PCI_DEVICE_CALLBACK( VendorId, DeviceId, Callback ) Callback
+extern OEM_PCI_PROGRAM_DEVICE_FUNCTION OEM_PCI_PROGRAM_DEVICE_CALLBACK_LIST EndOfList;
+extern OEM_PCI_PROGRAM_DEVICE_FUNCTION OEM_PCI_SKIP_DEVICE_CALLBACK_LIST EndOfList;
+extern OEM_PCI_PROGRAM_DEVICE_FUNCTION OEM_PCI_DEVICE_SET_ASPM_CALLBACK_LIST EndOfList;
+extern OEM_PCI_PROGRAM_DEVICE_FUNCTION OEM_PCI_DEVICE_SET_LNK_SPEED_CALLBACK_LIST EndOfList;
+extern OEM_PCI_PROGRAM_DEVICE_FUNCTION OEM_PCI_DEVICE_ATTRIBUTE_CALLBACK_LIST EndOfList;
+extern OEM_PCI_PROGRAM_DEVICE_FUNCTION OEM_PCI_DEVICE_OUT_OF_RESOURCES_CALLBACK_LIST EndOfList;
+extern OEM_PCI_PROGRAM_DEVICE_FUNCTION OEM_PCI_DEVICE_GET_OPT_ROM_CALLBACK_LIST EndOfList;
+#undef OEM_PCI_DEVICE_CALLBACK
+
+
+#define OEM_PCI_DEVICE_CALLBACK( VendorId, DeviceId, Callback ) { VendorId, DeviceId, &Callback }
+OEM_PCI_DEVICE_PROGRAM_CALLBACK OemSkipPciDevice[] =
+ { OEM_PCI_SKIP_DEVICE_CALLBACK_LIST { 0, 0, NULL } };
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PciPortSkipThisDevice()
+//
+// Description: Porting function which collects all Pci Specific configuration
+// data return it to the PCI Bus Driver.
+//
+// Input:
+// PCI_DEV_INFO *Device Pointer to the Pci Bus Driver Private data buffer.
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - SKIP this device, do not touch PCI Command register.
+// EFI_UNSUPPORTED - DON'T SKIP this device do complete enumeration as usual.
+//
+// NOTE:
+// If device decodes or requires some resources to function properely,
+// allocating and and reporting this reaources to GCD is a total responsibility
+// of this hook. If this FUNCTION RETURNS EFI_SUCCESS PciBus Driver assumes that
+// RESOURCES ARE ALLOCATED AND REPORTED TO THE GCD DXE SERVICES.
+// Reporting resources to GCD Services is important to avoid same resource range
+// been allocated twice.
+// If device you want to skip is PCI2PCI or PCI2CRD bus bridge 1 bus will be allocated
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PciPortSkipThisDevice(PCI_DEV_INFO *Device){
+ EFI_STATUS Status=EFI_UNSUPPORTED;
+ OEM_PCI_DEVICE_PROGRAM_CALLBACK *List = OemSkipPciDevice;
+ EFI_STATUS retStatus=EFI_UNSUPPORTED;
+//-------------------
+ while(List->Callback)
+ {
+ OEM_PCI_PROGRAM_DEVICE_FUNCTION *CallBack=(OEM_PCI_PROGRAM_DEVICE_FUNCTION*)List->Callback;
+ //--------------------------------
+ if((List->VendorId == Device->DevVenId.VenId && List->DeviceId == Device->DevVenId.DevId)||
+ (List->VendorId == 0 && List->DeviceId == 0))
+ {
+ PCI_TRACE((TRACE_PCI, "PciBus: OEM Skip Device Callback @ B%X|D%X|F%X VID=0x%X; DID=0x%X;",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device,Device->Address.Addr.Function,
+ Device->DevVenId.VenId, Device->DevVenId.DevId));
+
+ Status = CallBack(Device);
+ PCI_TRACE((TRACE_PCI, " %r,\n", Status));
+ if( EFI_ERROR(Status) && (Status!=EFI_UNSUPPORTED))return Status;
+ else if(Status==EFI_SUCCESS)retStatus=Status;
+ }
+ //if(List->VendorId == 0 && List->DeviceId == 0) break;
+ List++;
+ }
+
+ return retStatus;
+}
+
+
+#define OEM_PCI_DEVICE_CALLBACK( VendorId, DeviceId, Callback ) { VendorId, DeviceId, &Callback }
+OEM_PCI_DEVICE_PROGRAM_CALLBACK OemProgramPciDevice[] =
+ { OEM_PCI_PROGRAM_DEVICE_CALLBACK_LIST { 0, 0, NULL } };
+
+EFI_STATUS PciPortOemProgDevice(PCI_DEV_INFO *Device){
+ EFI_STATUS Status=EFI_SUCCESS;
+ OEM_PCI_DEVICE_PROGRAM_CALLBACK *List = OemProgramPciDevice;
+//-------------------
+ while(List->Callback)
+ {
+ OEM_PCI_PROGRAM_DEVICE_FUNCTION *CallBack=(OEM_PCI_PROGRAM_DEVICE_FUNCTION*)List->Callback;
+ //--------------------------------
+ if((List->VendorId == Device->DevVenId.VenId && List->DeviceId == Device->DevVenId.DevId)||
+ (List->VendorId == 0 && List->DeviceId == 0))
+ {
+ PCI_TRACE((TRACE_PCI, "PciBus: OEM Programm Device Callback @ B%X|D%X|F%X VID=0x%X; DID=0x%X;",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device,Device->Address.Addr.Function,
+ Device->DevVenId.VenId, Device->DevVenId.DevId));
+
+ Status = CallBack(Device);
+ PCI_TRACE((TRACE_PCI, " %r,\n", Status));
+ if( EFI_ERROR(Status) )
+ return Status;
+ }
+ List++;
+ }
+
+ return Status;
+}
+
+//To avoid compilation error define Srtuct delivered trough eLink as extern function.
+#define OEM_PCI_DEVICE_CALLBACK( VendorId, DeviceId, Callback ) { VendorId, DeviceId, &Callback }
+OEM_PCI_DEVICE_PROGRAM_CALLBACK OemSetAspmPciDevice[] =
+ { OEM_PCI_DEVICE_SET_ASPM_CALLBACK_LIST { 0, 0, NULL } };
+
+
+//Suppose to be called 2 times for UpStream and DownStream component of a LINK.
+EFI_STATUS PciPortOemSetAspm(PCI_DEV_INFO *Device, VOID *AspmMode){
+ EFI_STATUS Status=EFI_SUCCESS;
+ OEM_PCI_DEVICE_PROGRAM_CALLBACK *List = OemSetAspmPciDevice;
+//-------------------
+ while(List->Callback)
+ {
+ OEM_PCI_DEVICE_SET_ASPM_FUNCTION *CallBack =(OEM_PCI_DEVICE_SET_ASPM_FUNCTION*)List->Callback;
+ //--------------------------------
+
+ if((List->VendorId == Device->DevVenId.VenId && List->DeviceId == Device->DevVenId.DevId)||
+ (List->VendorId == 0 && List->DeviceId == 0))
+ {
+ PCI_TRACE((TRACE_PCI, "PciBus: OEM Device Set ASPM Callback @ B%X|D%X|F%X VID=0x%X; DID=0x%X;",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device,Device->Address.Addr.Function,
+ Device->DevVenId.VenId, Device->DevVenId.DevId));
+
+ Status = CallBack(Device, AspmMode);
+ PCI_TRACE((TRACE_PCI, " %r,\n", Status));
+ if( EFI_ERROR(Status))
+ return Status;
+ }
+ List++;
+ }
+
+ return Status;
+}
+
+//To avoid compilation error define Srtuct delivered trough eLink as extern function.
+#define OEM_PCI_DEVICE_CALLBACK( VendorId, DeviceId, Callback ) { VendorId, DeviceId, &Callback }
+OEM_PCI_DEVICE_PROGRAM_CALLBACK OemSetLnkSpeedPciDevice[] =
+ { OEM_PCI_DEVICE_SET_LNK_SPEED_CALLBACK_LIST { 0, 0, NULL } };
+
+//Suppose to be called 2 times for UpStream and DownStream component of a LINK.
+EFI_STATUS PciPortOemSetLnkSpeed(PCI_DEV_INFO *Device, UINT8 *LnkSpeed, UINT8 SuppSpeeds){
+ EFI_STATUS Status=EFI_SUCCESS;
+ OEM_PCI_DEVICE_PROGRAM_CALLBACK *List = OemSetLnkSpeedPciDevice;
+//-------------------
+ while(List->Callback)
+ {
+ OEM_PCI_DEVICE_SET_LNK_SPEED_FUNCTION *CallBack =(OEM_PCI_DEVICE_SET_LNK_SPEED_FUNCTION*)List->Callback;
+ //--------------------------------
+
+ if((List->VendorId == Device->DevVenId.VenId && List->DeviceId == Device->DevVenId.DevId)||
+ (List->VendorId == 0 && List->DeviceId == 0))
+ {
+ PCI_TRACE((TRACE_PCI, "PciBus: OEM Device Set LNK SPEED Callback @ B%X|D%X|F%X VID=0x%X; DID=0x%X;",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device,Device->Address.Addr.Function,
+ Device->DevVenId.VenId, Device->DevVenId.DevId));
+
+ Status = CallBack(Device, LnkSpeed, SuppSpeeds);
+ PCI_TRACE((TRACE_PCI, " %r,\n", Status));
+ if( EFI_ERROR(Status))
+ return Status;
+ }
+ List++;
+ }
+
+ return Status;
+}
+
+//To avoid compilation error define Srtuct delivered trough eLink as extern function.
+#define OEM_PCI_DEVICE_CALLBACK( VendorId, DeviceId, Callback ) { VendorId, DeviceId, &Callback }
+OEM_PCI_DEVICE_PROGRAM_CALLBACK OemGetOptRomPciDevice[] =
+ { OEM_PCI_DEVICE_GET_OPT_ROM_CALLBACK_LIST { 0, 0, NULL } };
+
+
+
+EFI_STATUS PciPortOemGetOptRom(PCI_DEV_INFO *Device, VOID **OptRom, UINT64 *OptRomSize){
+ EFI_STATUS Status=EFI_SUCCESS;
+ OEM_PCI_DEVICE_PROGRAM_CALLBACK *List = OemGetOptRomPciDevice;
+//-------------------
+ while(List->Callback)
+ {
+ OEM_PCI_DEVICE_GET_OPT_ROM_FUNCTION *CallBack =(OEM_PCI_DEVICE_GET_OPT_ROM_FUNCTION*)List->Callback;
+ //--------------------------------
+
+ if((List->VendorId == Device->DevVenId.VenId && List->DeviceId == Device->DevVenId.DevId)||
+ (List->VendorId == 0 && List->DeviceId == 0))
+ {
+ PCI_TRACE((TRACE_PCI, "PciBus: OEM Device Get Opt ROM Callback @ B%X|D%X|F%X VID=0x%X; DID=0x%X;",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device,Device->Address.Addr.Function,
+ Device->DevVenId.VenId, Device->DevVenId.DevId));
+
+ Status = CallBack(Device, OptRom, OptRomSize);
+ PCI_TRACE((TRACE_PCI, " %r,\n", Status));
+ if( EFI_ERROR(Status))
+ return Status;
+ }
+ List++;
+ }
+
+ return Status;
+}
+
+
+
+//To avoid compilation error define Srtuct delivered trough eLink as extern function.
+#define OEM_PCI_DEVICE_CALLBACK( VendorId, DeviceId, Callback ) { VendorId, DeviceId, &Callback }
+OEM_PCI_DEVICE_PROGRAM_CALLBACK OemPciOutOfResourcesRemoveDevice[] =
+ { OEM_PCI_DEVICE_OUT_OF_RESOURCES_CALLBACK_LIST { 0, 0, NULL } };
+
+EFI_STATUS PciPortOutOfResourcesRemoveDevice(PCI_DEV_INFO *Device, UINTN Count, UINTN LowResType){
+ EFI_STATUS Status=EFI_UNSUPPORTED;
+ OEM_PCI_DEVICE_PROGRAM_CALLBACK *List = OemPciOutOfResourcesRemoveDevice;
+//-----------------------------
+
+ //must be only one + TERMIONATOR.
+ while(List->Callback)
+ {
+ OEM_PCI_DEVICE_OUT_OF_RESOURCES_FUNCTION *CallBack =(OEM_PCI_DEVICE_OUT_OF_RESOURCES_FUNCTION*)List->Callback;
+ //-----------------------------
+
+ PCI_TRACE((TRACE_PCI, "\nPciBus: OEM PCI OUT OF RESOURCES Callback @ B%X|D%X|F%X VID=0x%X; DID=0x%X;",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device,Device->Address.Addr.Function,
+ Device->DevVenId.VenId, Device->DevVenId.DevId));
+
+ Status = CallBack(Device, Count, LowResType);
+ PCI_TRACE((TRACE_PCI, " %r,\n\n", Status));
+
+ List++;
+
+ }
+ return Status;
+}
+
+
+//To avoid compilation error define Srtuct delivered trough eLink as extern function.
+#define OEM_PCI_DEVICE_CALLBACK( VendorId, DeviceId, Callback ) { VendorId, DeviceId, &Callback }
+OEM_PCI_DEVICE_PROGRAM_CALLBACK OemAttributesPciDevice[] =
+ { OEM_PCI_DEVICE_ATTRIBUTE_CALLBACK_LIST { 0, 0, NULL } };
+
+
+
+EFI_STATUS PciPortOemAttributes(PCI_DEV_INFO *Device, UINT64 *Attr, UINT64 Capab, BOOLEAN Set){
+ EFI_STATUS Status=EFI_SUCCESS;
+ OEM_PCI_DEVICE_PROGRAM_CALLBACK *List = OemAttributesPciDevice;
+//-------------------
+ while(List->Callback)
+ {
+ OEM_PCI_DEVICE_ATTRIBUTE_FUNCTION *CallBack =(OEM_PCI_DEVICE_ATTRIBUTE_FUNCTION*)List->Callback;
+ //--------------------------------
+
+ if((List->VendorId == Device->DevVenId.VenId && List->DeviceId == Device->DevVenId.DevId)||
+ (List->VendorId == 0 && List->DeviceId == 0))
+ {
+ PCI_TRACE((TRACE_PCI, "PciBus: OEM Device Attributes Callback @ B%X|D%X|F%X VID=0x%X; DID=0x%X;",
+ Device->Address.Addr.Bus,Device->Address.Addr.Device,Device->Address.Addr.Function,
+ Device->DevVenId.VenId, Device->DevVenId.DevId));
+
+ Status = CallBack(Device, Attr, Capab, Set);
+ PCI_TRACE((TRACE_PCI, " %r,\n", Status));
+ if( EFI_ERROR(Status))
+ return Status;
+ }
+ List++;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS PciPortSetOemPadding(VOID *HpcData, VOID *HpcLocationData, UINT64 PciAddress){
+ EFI_STATUS Status=EFI_SUCCESS;
+//ADD VARIABLES HERE..
+
+//-----------------
+
+//PORTING START//PORTING START//PORTING START//PORTING START//PORTING START
+//ADD PORTING CODE HERE...
+/*
+ //VOID *HpcData, VOID *HpcLocationData could be typecasted to
+ // (PCI_HPC_DATA*)HpcData and (HPC_LOCATION_DATA*)HpcLocationData.
+ //Update Padding requirements if needed HERE.
+ //PCI_HPC_DATA *HpcData has pointer to the PCI_HOST_BRG_DATA* HpcData->Owner
+ //And number of HPC in subsystem of this HOST - HpcData->HpcLocCount.
+ //HPC_LOCATION_DATA *HpcLocationData has information about Location and Paddin for this
+ //Particular HPC. If system has more than ONE HPC checking needs to be done to
+ //detect correct if PASSED the data from correct HPC.
+
+
+ //Do something like this.
+
+ HpcLocationData->Padding[ptBus]=10;
+
+*/
+//PORTING END//PORTING END//PORTING END//PORTING END//PORTING END//PORTING END
+//DO NOT WRITE BELOW THIS LINE FOR THIS PORTING FUNCTION
+
+ return Status;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/PCI/PciPort.h b/Core/EM/PCI/PciPort.h
new file mode 100644
index 0000000..3e7e53c
--- /dev/null
+++ b/Core/EM/PCI/PciPort.h
@@ -0,0 +1,136 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/PciBus/PciPort.h 5 4/05/11 11:28a Yakovlevs $
+//
+// $Revision: 5 $
+//
+// $Date: 4/05/11 11:28a $
+//**********************************************************************
+// Revision History
+// ----------------
+//$Log: /Alaska/BIN/Core/Modules/PciBus/PciPort.h $
+//
+// 5 4/05/11 11:28a Yakovlevs
+// [TAG] EIP 38174; EIP 53475;
+// [Description] 38174 Generic support to handle PCI OUT OF RESOURDCES
+// added.
+// 53475 PCI Express 3.0 support added.
+//
+// [Files] PciBus.c; PciBus.mak; PciHostBridge.c; PciBus.h;
+// PciHostBridge.c; PciPort.c;
+//
+// 4 1/28/11 3:02p Yakovlevs
+// [TAG] EIP43879
+// [Category] New Feature
+// [Description] Added PciPortOemGetOptRom() OEM Hook to override
+// content of the PCI Device Option ROM.
+// [Files] PciBus.c; PciPort.c; PciPort.h; PciBus.mak; PciBus.sdl
+//
+// 3 8/16/10 1:12p Yakovlevs
+// ASPM Custom Programming.
+//
+// 2 9/22/09 6:02p Yakovlevs
+// 1. Added infrastructure to ELINKs as porting Functions delivered from
+// Platform and Chipset files. Now you can port PCI Bus driver without
+// modifying Core files
+//
+// 1 4/28/09 3:47p Yakovlevs
+
+#ifndef PCI_PORT_H_
+#define PCI_PORT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Efi.h>
+
+
+//----------------------------------------------------------------------------------
+//PCI Bus Porting Constants definitions
+const UINT16 NbDmiL0ExitLatency;
+const UINT16 NbDmiL1ExitLatency;
+const UINT16 SbDmiL0ExitLatency;
+const UINT16 SbDmiL1ExitLatency;
+const UINT16 NbDmiAspmSupport;
+const UINT16 SbDmiAspmSupport;
+const UINT16 SbInternalDelay;
+//PCI Bus Configuration Constants definitions
+const BOOLEAN S3VideoRepost;
+const BOOLEAN FixedBusAssign;
+const BOOLEAN ScanFullBusRange;
+const BOOLEAN PciExpressSupport;
+const BOOLEAN HotPlugSupport;
+const BOOLEAN PciXSupport;
+const BOOLEAN SriovSupport;
+const BOOLEAN Use4KBar;
+
+//Define OEM_PCI_DEVICE_PROGRAM_CALLBACK
+typedef EFI_STATUS (OEM_PCI_PROGRAM_DEVICE_FUNCTION)(VOID *PciIoProtocol);
+typedef EFI_STATUS (OEM_PCI_DEVICE_ATTRIBUTE_FUNCTION)(VOID *PciIoProtocol, UINT64 *Attr, UINT64 Capab, BOOLEAN Set);
+typedef EFI_STATUS (OEM_PCI_DEVICE_SET_ASPM_FUNCTION)(VOID *PciIoProtocol, VOID *AspmMode);
+typedef EFI_STATUS (OEM_PCI_DEVICE_SET_LNK_SPEED_FUNCTION)(VOID *PciIoProtocol, UINT8 *LnkSpeed, UINT8 SuppSpeeds);
+typedef EFI_STATUS (OEM_PCI_DEVICE_GET_OPT_ROM_FUNCTION)(VOID *PciIoProtocol, VOID **OptRom, UINT64 *OptRomSize);
+typedef EFI_STATUS (OEM_PCI_DEVICE_OUT_OF_RESOURCES_FUNCTION)(VOID *PciIoProtocol, UINTN Count, UINTN ResType);
+typedef EFI_STATUS (OEM_PCI_PADDING_FUNCTION)(VOID *HpcData, VOID *HpcLocationData, UINT64 PciAddress);
+
+//Data structure of CallBack delivered trough eLink
+typedef struct{
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ VOID *Callback;
+} OEM_PCI_DEVICE_PROGRAM_CALLBACK;
+
+
+
+//PCI Bus Porting Function Prototypes
+EFI_STATUS PciPortSkipThisDevice(VOID *Device);
+
+EFI_STATUS PciPortOemProgDevice(VOID *Device);
+
+EFI_STATUS PciPortOemAttributes(VOID *Device, UINT64 *Attr, UINT64 Capab, BOOLEAN Set);
+
+EFI_STATUS PciPortOemSetAspm(PCI_DEV_INFO *Device, VOID *AspmMode);
+
+EFI_STATUS PciPortOemSetLnkSpeed(PCI_DEV_INFO *Device, UINT8 *LnkSpeed, UINT8 SuppSpeeds);
+
+EFI_STATUS PciPortSetOemPadding(VOID *HpcData, VOID *HpcLocationData, UINT64 PciAddress);
+
+EFI_STATUS PciPortOemGetOptRom(PCI_DEV_INFO *Device, VOID **OptRom, UINT64 *OptRomSize);
+
+EFI_STATUS PciPortOutOfResourcesRemoveDevice(PCI_DEV_INFO *Device, UINTN Count, UINTN LowResType);
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif //PCI_BOARD_H_
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
diff --git a/Core/EM/PCI/PciRootBridge.dxs b/Core/EM/PCI/PciRootBridge.dxs
new file mode 100644
index 0000000..7f57b62
--- /dev/null
+++ b/Core/EM/PCI/PciRootBridge.dxs
@@ -0,0 +1,67 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/PciBus/PciRootBridge.dxs 3 4/28/09 3:49p Yakovlevs $
+//
+// $Revision: 3 $
+//
+// $Date: 4/28/09 3:49p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/PciBus/PciRootBridge.dxs $
+//
+// 3 4/28/09 3:49p Yakovlevs
+// Changes related to AmiBoardInfo protocol and Multiplatform support.
+//
+// 2 3/13/07 8:32p Yakovlevs
+//
+// 1 3/12/07 12:08p Yakovlevs
+//
+// 2 7/25/05 4:26p Markw
+// Add Variable services.
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: PciRootBridge_dxs
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <Protocol\Variable.h>
+#include <Protocol\CPU.h>
+#include <Protocol\AmiBoardInfo.h>
+DEPENDENCY_START
+ EFI_CPU_ARCH_PROTOCOL_GUID AND
+ EFI_VARIABLE_ARCH_PROTOCOL_GUID AND
+ EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID AND
+ AMI_BOARD_INFO_PROTOCOL_GUID
+DEPENDENCY_END
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/PCI/PciSetup.h b/Core/EM/PCI/PciSetup.h
new file mode 100644
index 0000000..90d6cb8
--- /dev/null
+++ b/Core/EM/PCI/PciSetup.h
@@ -0,0 +1,155 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/PciBus/PciSetup.h 6 9/10/12 12:54p Yakovlevs $
+//
+// $Revision: 6 $
+//
+// $Date: 9/10/12 12:54p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/PciBus/PciSetup.h $
+//
+// 6 9/10/12 12:54p Yakovlevs
+// [TAG] EIP93341
+// [Category] Improvement
+// [Description] Preserve PCI DEV/LNK/SLT control register in S3 resume
+// path.
+// [Files] PciBus.c PciBus.sd PciBus.uni PciSetup.h PciPort.c
+//
+// 5 11/09/11 1:55p Yakovlevs
+// [TAG] EIP71380
+// [Category] New Feature
+// [Description] Core support for CSM opt-out feature
+// [Files] PciBus.c; PciPort.c; PciBus.sd; PciBus.uni; PciSetup.h;
+// PciBusSetup.c;
+//
+// 4 12/08/10 3:22p Yakovlevs
+// Removed Setup Option "Selectable DeEmphasis" since it is HwInit Bit.
+//
+// 3 3/01/10 6:12p Yakovlevs
+// Pci Express V2.1 Support Added.
+//
+// 2 3/23/09 4:57p Yakovlevs
+// Added generic support for PCI Express Hot-Plug.
+//
+// 1 9/25/08 11:35a Yakovlevs
+//
+// 1 6/05/08 7:14p Yakovlevs
+//
+// 1 6/05/08 7:06p Yakovlevs
+//
+// 1 6/05/08 6:46p Yakovlevs
+//
+// 1 3/18/07 5:23p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: PciSetup.h
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef __PCI_SETUP__H__
+#define __PCI_SETUP__H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(push)
+//---------------------------------------------------------------------------------
+//Structure Defines PCI Releated data stored in GLOBAL SETUP_DATA NVRAM variable
+typedef struct _PCI_SETUP_DATA {
+ //General PCI Settings: [] - default
+ UINT8 PciLatency; //[32]\ 64 \ 96 \ 128 \ 160 \ 192 \ 224 \ 248
+ UINT8 PciXLatency; // 32 \[64]\ 96 \ 128 \ 160 \ 192 \ 224 \ 248
+ //PCI Express Device Settings: [] - default
+ UINT8 RelaxedOrdering; //[Disable]\ Enable
+ UINT8 ExtTagField; //[Disable]\ Enable
+ UINT8 NoSnoop; // Disable \[Enable]
+ UINT8 MaxPayload; //[Auto]\ 128 \ 256 \ 512 \ 1024 \ 2048 \ 4096 (in bytes)
+ UINT8 MaxReadRequest; //[Auto]\ 128 \ 256 \ 512 \ 1024 \ 2048 \ 4096 (in bytes)
+ //PCI Express Link settings: [] - default
+ UINT8 AspmMode; //[Disable]\ Auto \ Force L0
+ UINT8 ExtendedSynch; //[Disable]\ Enable
+ //Acpi related questions
+ UINT8 S3ResumeVideoRepost;
+//new stuff added in PCI BUS 2.2.0
+ UINT8 Above4gDecode; //[Disable]\ Enable
+ //General PCI Settings: [] - default
+ UINT8 VgaPallete; //[Disable]\ Enable
+ UINT8 PerrEnable; //[Disable]\ Enable
+ UINT8 SerrEnable; //[Disable]\ Enable
+ //Hotlpug Related Settings visible if PCI_HOTPLUG_SUPPORT == 1 && PCI_EXPRESS_SUPPORT == 1
+ UINT8 HotPlug; // Disable \[Enable]
+ UINT8 BusPadd; // Disable \[1]\ 2 \ 3 \ 4 \ 5
+ UINT64 IoPadd; // Disable \[ 4K]\ 8K \ 16K \ 32K
+ UINT64 Mmio32Padd; // Disable \ 1M \ 4M \ 8M \[16M]\ 32M \ 64M \ 128M
+ UINT64 Mmio32PfPadd; // Disable \ 1M \ 4M \ 8M \[16M]\ 32M \ 64M \ 128M
+ UINT64 Mmio64Padd; //[Disable]\ 1M \ 4M \ 8M \ 16M \ 32M \ 64M \ 128M \ 256M \ 512M \ 1G
+ UINT64 Mmio64PfPadd; //[Disable]\ 1M \ 4M \ 8M \ 16M \ 32M \ 64M \ 128M \ 256M \ 512M \ 1G
+
+ UINT8 LnkTrRetry; //[Disable]\ 2 \ 3 \ 5
+ UINT16 LnkTrTimeout; //[1...1000] (Microseconds uS)
+ UINT8 LnkDisable; //[Keep ON == 0] / Disable ==1
+
+ UINT8 S3PciExpressScripts; //[Disable]\ Enable
+
+//PCI_EXPRESS_GEN2_SUPPORT
+ //Gen2 Device Settings
+ UINT8 ComplTimeOut; //[Disable]\ Default \ 50 - 100 us \ 1ms - 10ms \ 16...
+ UINT8 AriFwd; //[Disable]\ Enable
+ UINT8 AtomOpReq; //[Disable]\ Enable
+ UINT8 AtomOpEgressBlk; //[Disable]\ Enable
+ UINT8 IDOReq; //[Disable]\ Enable
+ UINT8 IDOCompl; //[Disable]\ Enable
+ UINT8 LtrReport; //[Disable]\ Enable
+ UINT8 E2ETlpPrBlk; //[Disable]\ Enable
+
+ //Gen2 Link Settings
+ UINT8 LnkSpeed; //[Auto]\ 5.0 GHz \ 2.5 GHz
+ UINT8 ClockPm; //[Disable]\ Enable
+ UINT8 ComplSos; //[Disable]\ Enable
+ UINT8 HwAutoWidth; //[Enable]\ Disable //LNK_CNT_REG #1
+ UINT8 HwAutoSpeed; //[Enable]\ Disable
+
+} PCI_SETUP_DATA;
+
+#pragma pack(pop)
+
+//Function Prototypes
+VOID BrdGetPciSetupData(PCI_SETUP_DATA *PciSetupData);
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************