summaryrefslogtreecommitdiff
path: root/Core/EM/UsbRecovery
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/UsbRecovery
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/UsbRecovery')
-rw-r--r--Core/EM/UsbRecovery/AmiMapping.h102
-rw-r--r--Core/EM/UsbRecovery/EhciPEI/EhciPei.c1847
-rw-r--r--Core/EM/UsbRecovery/EhciPEI/EhciPei.cif10
-rw-r--r--Core/EM/UsbRecovery/EhciPEI/EhciPei.h592
-rw-r--r--Core/EM/UsbRecovery/EhciPEI/EhciPeiBoard.c108
-rw-r--r--Core/EM/UsbRecovery/HubPeim.h317
-rw-r--r--Core/EM/UsbRecovery/OhciPEI/OhciPei.c1455
-rw-r--r--Core/EM/UsbRecovery/OhciPEI/OhciPei.cif12
-rw-r--r--Core/EM/UsbRecovery/OhciPEI/OhciPei.h909
-rw-r--r--Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c508
-rw-r--r--Core/EM/UsbRecovery/PeiUsbLib.c825
-rw-r--r--Core/EM/UsbRecovery/PeiUsbLib.h171
-rw-r--r--Core/EM/UsbRecovery/USBRecoverySrc.chmbin0 -> 150255 bytes
-rw-r--r--Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.c3575
-rw-r--r--Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.h865
-rw-r--r--Core/EM/UsbRecovery/UhcPeimSrc/UhcPeimSrc.cif11
-rw-r--r--Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.c376
-rw-r--r--Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.cif10
-rw-r--r--Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.c482
-rw-r--r--Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.h201
-rw-r--r--Core/EM/UsbRecovery/UsbBotPeimSrc/PeiAtapi.c832
-rw-r--r--Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.c726
-rw-r--r--Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.cif14
-rw-r--r--Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.dxs106
-rw-r--r--Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.h362
-rw-r--r--Core/EM/UsbRecovery/UsbBotPeimSrc/atapi.h418
-rw-r--r--Core/EM/UsbRecovery/UsbPeim.h244
-rw-r--r--Core/EM/UsbRecovery/UsbPeimSrc/HubPeim.c889
-rw-r--r--Core/EM/UsbRecovery/UsbPeimSrc/UsbIoPeim.c334
-rw-r--r--Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c1006
-rw-r--r--Core/EM/UsbRecovery/UsbPeimSrc/UsbPeimSrc.cif12
-rw-r--r--Core/EM/UsbRecovery/UsbRecov.mak457
-rw-r--r--Core/EM/UsbRecovery/UsbRecov.sdl237
-rw-r--r--Core/EM/UsbRecovery/UsbRecovery.cif24
-rw-r--r--Core/EM/UsbRecovery/XhciPEI/XhciPei.c2314
-rw-r--r--Core/EM/UsbRecovery/XhciPEI/XhciPei.cif9
-rw-r--r--Core/EM/UsbRecovery/XhciPEI/XhciPei.h1245
-rw-r--r--Core/EM/UsbRecovery/usb.h511
38 files changed, 22116 insertions, 0 deletions
diff --git a/Core/EM/UsbRecovery/AmiMapping.h b/Core/EM/UsbRecovery/AmiMapping.h
new file mode 100644
index 0000000..0307957
--- /dev/null
+++ b/Core/EM/UsbRecovery/AmiMapping.h
@@ -0,0 +1,102 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/AmiMapping.h 3 7/10/08 6:33p Michaela $
+//
+// $Revision: 3 $
+//
+// $Date: 7/10/08 6:33p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/AmiMapping.h $
+//
+// 3 7/10/08 6:33p Michaela
+// Updated to support OHCI controllers
+//
+// 2 4/16/07 1:08p Sivagarn
+// - Updated as per coding standard
+//
+// 1 Initial checkin
+//
+//**********************************************************************
+
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: AMIMAPPING.H
+//
+// Description: This file is the mapping header file that maps Tiano related
+// equates to AMI equates
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+#ifndef __AMI_MAPPING__H__
+#define __AMI_MAPPING__H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define STATIC static
+#define EFI_PPI_DEFINITION( a ) EFI_STRINGIZE(Ppi/a.h)
+#define EFI_STRINGIZE( a ) #a
+//Compatibility
+// PPI's
+#define PEI_CPU_IO_PPI EFI_PEI_CPU_IO_PPI
+#define PEI_STALL_PPI EFI_PEI_STALL_PPI
+#define PEI_STALL_PPI_GUID EFI_PEI_STALL_PPI_GUID
+//
+// Define macros to build data structure signatures from characters.
+//
+#define EFI_SIGNATURE_16( A, B ) ( (A) | (B << 8) )
+#define EFI_SIGNATURE_32( A, B, C, D ) ( EFI_SIGNATURE_16( A, B ) | \
+ (EFI_SIGNATURE_16( C, D ) << 16) )
+#define EFI_SIGNATURE_64( A, B, C, D, E, F, G, H ) \
+ ( EFI_SIGNATURE_32( A, B, C, D ) | ( (UINT64) \
+ ( EFI_SIGNATURE_32 \ (E, F, G,\
+ H) ) << 32 ) )
+
+#define PEI_CR( Record, TYPE, Field, Signature ) \
+ _CR( Record, TYPE, Field )
+//
+// CONTAINING_RECORD - returns a pointer to the structure
+// from one of it's elements.
+//
+#define _CR( Record, TYPE, Field ) ( (TYPE *) \
+ ( (CHAR8 *) (Record) -\
+ (CHAR8 *) &( ( (TYPE *) 0 )->Field ) ) )
+
+#define EFI_D_ERROR 0x80000000 // Error
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/EhciPEI/EhciPei.c b/Core/EM/UsbRecovery/EhciPEI/EhciPei.c
new file mode 100644
index 0000000..a5f617f
--- /dev/null
+++ b/Core/EM/UsbRecovery/EhciPEI/EhciPei.c
@@ -0,0 +1,1847 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/EhciPei.c 14 11/24/12 5:44a Ryanchou $
+//
+// $Revision: 14 $
+//
+// $Date: 11/24/12 5:44a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/EhciPei.c $
+//
+// 14 11/24/12 5:44a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 13 9/28/12 2:56a Roberthsu
+// [TAG] EIP99922
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System hanged on CP:9C during USB Recovery from cold
+// boot.
+// [RootCause] Usb controller need reset when pei exit.
+// [Solution] Reset usb controller when pei exit
+// [Files] EhciPei.c
+//
+// 12 8/23/12 9:57p Wilsonlee
+// [TAG] EIP97069
+// [Category] Improvement
+// [Description] Reset root port algorythm update.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// UhcPeim.h, UsbPeim.c, usb.h
+//
+// 11 8/09/11 4:59p Yul
+// [TAG] EIP60439
+// [Category] Improvement
+// [Description] Generically handle the assignments of MMIO base address
+// from Rx and UsbRecovery modules.
+// [Files] EhciPei.c
+//
+// 10 1/18/11 12:52a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 9 1/11/11 11:12a Olegi
+// [TAG] EIP51517
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Recovery fails when using USB port behind HUB
+// [RootCause] Port Power was not set
+// [Solution] Set Port Power if Port Power Control bit is 1.
+// [Files] EHCIPEI.C
+//
+// 8 10/11/10 4:51p Olegi
+// XHCI support added.
+//
+// 7 4/26/10 4:16p Krishnakumarg
+// DebugRx causes the system to hang in Recovery mode EIP#34401
+//
+// 6 10/20/09 9:15a Olegi
+// EIP#28255: EhciHcGetRootHubPortStatus returns proper status.
+//
+// 5 7/30/09 6:23p Krishnakumarg
+// Symptom :During recovery,system hangs while entering setup.
+// RootCause:USB Host controller Status registers are not cleared and HC
+// is not HALTed after loading recovery capsule.
+// Solution: HC is set to HALT state after loading recovery module so USB
+// driver clears the status Registers.
+//
+// 4 4/29/09 1:56p Rameshr
+// EHCIStopAsyncSchedule gets called always when the
+// EHCIStartAsyncSchedule function is called
+//
+// 3 3/17/09 5:08p Olegi
+// Added TransactionTranslator for slow/full speed devices behind USB2
+// hub.
+//
+// 2 3/04/09 11:56a Olegi
+//
+// 1 3/03/09 7:28p Olegi
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EhciPei.c
+//
+// Description:
+// This file is the main source file for the EHCI PEI USB
+// recovery module. Its entry point at EhciPeiUsbEntryPoint
+// will be executed from the UsbRecoveryInitialize INIT_LIST.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <PEI.h>
+#include <AmiPeiLib.h>
+#include <token.h>
+#include <PPI\PeiGetUCtrl.h>
+#include <PPI\stall.h>
+#include "Ppi\UsbHostController.h"
+#include "UsbPeim.h"
+#include "EhciPei.h"
+#include "usb.h"
+
+extern EFI_GUID gPeiStallPpiGuid;
+extern EFI_GUID gPeiUsbHostControllerPpiGuid;
+
+EFI_STATUS EhciPeiBoardInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ EFI_PEI_PCI_CFG_PPI *PciCfgPpi,
+ EFI_PEI_STALL_PPI *StallPpi );
+
+UINT32 gEhciControllerPciTable[] = PEI_EHCI_PCI_BDFS;
+UINT16 gEhciControllerCount = \
+ sizeof(gEhciControllerPciTable) / sizeof(UINT32);
+
+UINT32 gEhciControllerBaseAddress[] = PEI_EHCI_MEM_BASE_ADDRESSES;
+
+EFI_GUID guidEndOfPei = EFI_PEI_END_OF_PEI_PHASE_PPI_GUID;
+
+EFI_STATUS
+EFIAPI NotifyOnRecoveryCapsuleLoaded (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *InvokePpi );
+
+
+static EFI_PEI_NOTIFY_DESCRIPTOR lNotifyList = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &guidEndOfPei,
+ NotifyOnRecoveryCapsuleLoaded
+};
+
+BOOLEAN EHCIDbg_PortUsed = FALSE;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciGetOperationalRegisterBase
+//
+// Description:
+// This function uses ControllerIndex and the global PCI_BUS_DEV_FUNCTION
+// array to access a particular controller's PCI configuration space in
+// order to obtain the Operational Register base address.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- PEI Sevices table pointer
+// IN UINT16 ControllerIndex
+// -- Index of the controller in the global
+// PCI_BUS_DEV_FUNCTION array
+//
+// Output:
+// UINT32 (Return Value)
+// = Base address for this controller's operational
+// registers.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32 EhciGetOperationalRegisterBase (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT16 ControllerIndex )
+{
+ UINT32 EhciBaseAddress;
+
+ (*PeiServices)->PciCfg->Read(
+ PeiServices,
+ (*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint32,
+ gEhciControllerPciTable[ControllerIndex] + EHCI_BASE_ADDR_REG,
+ &EhciBaseAddress
+ );
+
+ return EhciBaseAddress;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: Update_EHCIDbg_PortUsed
+//
+// Description:
+// Check debugport of a controlller is in use or not.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- PEI Sevices table pointer
+// IN UINT16 ControllerIndex
+// -- Index of the controller in the global
+// PCI_BUS_DEV_FUNCTION array
+//
+// Output :
+//
+// Note : EHCIDbg_PortUsed used to maintain the debugport usage of
+// CURRENT processing controller.
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID Update_EHCIDbg_PortUsed(EFI_PEI_SERVICES **PeiServices,UINT8 Index)
+{
+ UINT8 CmdReg = 0;
+ UINT16 DebugBase = 0;
+ UINT32 EhciBaseMem = 0;
+
+//
+// Read Command register and check MMIO enabled or not
+//
+ (*PeiServices)->PciCfg->Read( PeiServices, (*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint8,
+ gEhciControllerPciTable[Index] + EHCI_CMD_REGISTER,
+ &CmdReg );
+
+ if(!(CmdReg & 2)){ //MMIO is disabled
+ EHCIDbg_PortUsed = FALSE;
+ return;
+ }
+//
+// Retrieve the debugport base offset address
+//
+ (*PeiServices)->PciCfg->Read( PeiServices, (*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint16,
+ gEhciControllerPciTable[Index] + DEBUG_BASE,
+ &DebugBase );
+
+ DebugBase = DebugBase & 0x1FFF; // Bar number hardwired to 001b
+
+ EhciBaseMem = EhciGetOperationalRegisterBase(PeiServices,Index);
+
+//
+// Check ENABLED_CNT bit of DEBUG status register
+//
+ if ((*(volatile UINT32*)(UINTN)(EhciBaseMem + DebugBase)) & BIT28){
+ EHCIDbg_PortUsed = TRUE;
+ }else{
+ EHCIDbg_PortUsed = FALSE;
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciPeiUsbEntryPoint
+//
+// Description:
+// This is the entry point into the EHCI controller initialization
+// subsystem.
+//
+// Input:
+// IN EFI_FFS_FILE_HEADER *FfsHeader
+// -- EFI_FFS_FILE_HEADER pointer
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EhciPeiUsbEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ UINT8 Index;
+ UINTN MemPages;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ PEI_EHCI_DEV *EhciDevPtr;
+ EFI_PEI_STALL_PPI *StallPpi;
+ UINT8 ByteData;
+
+ //-------------------------------------------
+ // Initialize the EFI_PEI_STALL_PPI interface
+ //-------------------------------------------
+ Status = (**PeiServices).LocatePpi( PeiServices, &gPeiStallPpiGuid,
+ 0, NULL, &StallPpi );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //-----------------------------------------
+ // board specific initialization to program
+ // PCI bridges and enable MMIO
+ //-----------------------------------------
+
+ Status = EhciPeiBoardInit(
+ PeiServices,
+ (*PeiServices)->PciCfg,
+ StallPpi );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //----------------------------------------------------------
+ // Allocate EHCI DEVICE OBJECT that holds all necessary
+ // information for the Host Controller operational registers
+ // for each controller. Initialze the controller and setup
+ // data structures for ready for operation
+ //----------------------------------------------------------
+
+ for (Index = 0; Index < gEhciControllerCount; Index++)
+ {
+
+
+ if(!(EhciGetOperationalRegisterBase( PeiServices, Index ))){
+ // Program PCI BAR and command register
+ (*PeiServices)->PciCfg->Write( PeiServices, (*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint32,
+ gEhciControllerPciTable[Index] + EHCI_BASE_ADDR_REG,
+ &gEhciControllerBaseAddress[Index] );
+ }
+
+ ByteData = 6; // Enable MMIO and BusMaster
+ (*PeiServices)->PciCfg->Write( PeiServices, (*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint8,
+ gEhciControllerPciTable[Index] + EHCI_CMD_REGISTER,
+ &ByteData );
+
+
+ Update_EHCIDbg_PortUsed(PeiServices,Index);
+
+ // PAGESIZE = 0x1000
+ MemPages = sizeof (PEI_EHCI_DEV) / 0x1000 + 1;
+ Status = (**PeiServices).AllocatePages(
+ PeiServices,
+ EfiConventionalMemory,
+ MemPages,
+ &TempPtr
+ );
+ if ( EFI_ERROR( Status ) )
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ (**PeiServices).SetMem((VOID*)TempPtr, sizeof (PEI_EHCI_DEV), 0);
+
+ EhciDevPtr = (PEI_EHCI_DEV *) ( (UINTN) TempPtr );
+ EhciDevPtr->Signature = PEI_EHCI_DEV_SIGNATURE;
+ EhciDevPtr->PeiServices = PeiServices;
+ EhciDevPtr->CpuIoPpi = (*PeiServices)->CpuIo;
+ EhciDevPtr->StallPpi = StallPpi;
+ EhciDevPtr->PciCfgPpi = (*PeiServices)->PciCfg;
+
+ EhciDevPtr->UsbHostControllerBaseAddress =
+ EhciGetOperationalRegisterBase( PeiServices, Index );
+
+ //Initialize the EHCI Controller for operation
+
+ EhciInitHC( PeiServices, EhciDevPtr );
+
+ //Setup PPI entry point
+ EhciDevPtr->UsbHostControllerPpi.ControlTransfer = EhciHcControlTransfer;
+ EhciDevPtr->UsbHostControllerPpi.BulkTransfer = EhciHcBulkTransfer;
+ EhciDevPtr->UsbHostControllerPpi.GetRootHubPortNumber = EhciHcGetRootHubPortNumber;
+ EhciDevPtr->UsbHostControllerPpi.GetRootHubPortStatus = EhciHcGetRootHubPortStatus;
+ EhciDevPtr->UsbHostControllerPpi.SetRootHubPortFeature = EhciHcSetRootHubPortFeature;
+ EhciDevPtr->UsbHostControllerPpi.ClearRootHubPortFeature = EhciHcClearRootHubPortFeature;
+
+ EhciDevPtr->UsbHostControllerPpi.DebugPortUsed = EHCIDbg_PortUsed;
+ EhciDevPtr->UsbHostControllerPpi.PreConfigureDevice = NULL;
+ EhciDevPtr->UsbHostControllerPpi.EnableEndpoints = NULL;
+
+ EhciDevPtr->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ EhciDevPtr->PpiDescriptor.Guid = &gPeiUsbHostControllerPpiGuid;
+ EhciDevPtr->PpiDescriptor.Ppi = &EhciDevPtr->UsbHostControllerPpi;
+
+ //Now is the time to install the PPI
+ Status = (**PeiServices).InstallPpi( PeiServices, &EhciDevPtr->PpiDescriptor );
+ if ( EFI_ERROR( Status ) )
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ }
+ (**PeiServices).NotifyPpi (PeiServices, &lNotifyList);
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciInitHC
+//
+// Description: EHCI controller initialization.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_EHCI_DEV *EhciDevPtr
+// -- PEI_EHCI_DEV pointer
+// IN UINT8 Index
+// -- Index of this controller in the global
+// PCI_BUS_DEV_FUNCTION array
+//
+// Output:
+// VOID (Return Value)
+//
+// Note:
+// EhciDevPtr->UsbHostControllerBaseAddress is is initialized
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EhciInitHC (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_EHCI_DEV *EhciDevPtr)
+{
+ UINT8 *pPtr;
+ UINTN MemPages;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ EHCI_HC_CAP_REG *EhciHcCapReg =
+ (EHCI_HC_CAP_REG *)(UINTN)EhciDevPtr->UsbHostControllerBaseAddress;
+ EHCI_HC_OPER_REG *EhciHcOpReg;
+ EHCI_DESC_PTRS *pstEHCIDescPtrs;
+
+
+ // Allocate memory for control transfers and bulk transfers
+ // Allocate a block of memory and define/initialize
+ // Setup Control and Bulk EDs/TDs
+ pstEHCIDescPtrs = &(EhciDevPtr->stEHCIDescPtrs);
+
+ MemPages = (( 4 * sizeof (EHCI_QTD) ) + (2 * sizeof(EHCI_QH) )) / 0x1000 + 1;
+ Status = (**PeiServices).AllocatePages(
+ PeiServices,
+ EfiConventionalMemory,
+ MemPages,
+ &TempPtr
+ );
+
+ pPtr = (UINT8 *) ( (UINTN) TempPtr );
+ if (pPtr == NULL) {
+ return;
+ }
+ MemSet( pPtr, 4 * sizeof (EHCI_QTD) + 2 * sizeof(EHCI_QH), 0 );
+
+ pstEHCIDescPtrs->fpQHControl = (EHCI_QH*) pPtr;
+ pPtr += sizeof (EHCI_QH);
+ pstEHCIDescPtrs->fpqTDControlSetup = (EHCI_QTD*) pPtr;
+ pPtr += sizeof (EHCI_QTD);
+ pstEHCIDescPtrs->fpqTDControlData = (EHCI_QTD*) pPtr;
+ pPtr += sizeof (EHCI_QTD);
+ pstEHCIDescPtrs->fpqTDControlStatus = (EHCI_QTD*) pPtr;
+ pPtr += sizeof (EHCI_QTD);
+ pstEHCIDescPtrs->fpQHBulk = (EHCI_QH*) pPtr;
+ pPtr += sizeof (EHCI_QH);
+ pstEHCIDescPtrs->fpqTDBulkData = (EHCI_QTD*) pPtr;
+
+ // Store number of downstream ports into PEI_EHCI_DEV struct
+ EhciDevPtr->bNumPorts = (UINT8)(EhciHcCapReg->HcsParams.Field.NumberOfPorts);
+
+ // Read the Capability Registers Length to find the Offset address for the
+ // beginning of the operational registers
+ EhciHcOpReg = (EHCI_HC_OPER_REG *)((UINTN)EhciHcCapReg + EhciHcCapReg->CapLength);
+ EhciDevPtr->EhciHcOpReg = EhciHcOpReg;
+
+ EhciDevPtr->HcStatus = 0;
+
+ // Do a Host Controller reset first
+ if(!EHCIDbg_PortUsed)
+ EhciHcReset( PeiServices, EhciDevPtr );
+
+ // Do not do any periodic schedule related initialization
+
+ // Clear status register - all R/WC bits
+ EhciHcOpReg->UsbSts.AllBits =
+ (EHCI_USB_INTERRUPT | // Interrupt
+ EHCI_USB_ERROR_INTERRUPT | // Error interrupt
+ EHCI_PORT_CHANGE_DETECT | // Port Change Detect
+ EHCI_FRAME_LIST_ROLLOVER | // Frame List Rollover
+ EHCI_HOST_SYSTEM_ERROR | // Host System Error
+ EHCI_INT_ASYNC_ADVANCE); // Interrupt on Async Advance
+
+ // Turn HC on
+ EhciHcOpReg->UsbCmd.AllBits = EHCI_RUNSTOP | EHCI_INTTHRESHOLD;
+
+ // Disconnect all ports from companion HC (if any) and route them to EHCI
+ EhciHcOpReg->ConfigFlag = 1;
+
+ EHCI_FIXED_DELAY_MS(EhciDevPtr, 100); // 100msec delay to stabilize
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciHcReset
+//
+// Description:
+// This function performs a software reset of the host controller.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_EHCI_DEV *EhciDevPtr
+// -- PEI_EHCI_DEV pointer
+//
+// Output:
+// VOID (Return Value)
+//
+// Notes:
+// It is assumed that all necessary operational register data has been
+// saved prior to calling this function.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EhciHcReset (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_EHCI_DEV *EhciDevPtr )
+{
+ UINT32 UsbCmd;
+ UINT8 Count;
+
+ // Check HC is halted: attempting to reset an actively running HC will
+ // result in undefined behavior.
+ if (EhciDevPtr->EhciHcOpReg->UsbSts.Field.HCHalted == 0)
+ {
+ PEI_TRACE ((EFI_D_ERROR, PeiServices, "EHCI HC RESET ERROR: HC is running.\n"));
+ EhciDevPtr->HcStatus = EHCI_RESET_ERROR;
+ return;
+ }
+
+ // Issue reset
+ UsbCmd = EhciDevPtr->EhciHcOpReg->UsbCmd.AllBits | EHCI_HCRESET;
+ EhciDevPtr->EhciHcOpReg->UsbCmd.AllBits = UsbCmd;
+
+ // EHCI_HCRESET bit is set to zero by the Host Controller when the reset
+ // process is complete.
+ for (Count = 0; Count < 10; Count++)
+ {
+ EHCI_FIXED_DELAY_MS( EhciDevPtr, 10); // 10msec delay
+ if (EhciDevPtr->EhciHcOpReg->UsbCmd.Field.HcReset == 0)
+ {
+ return;
+ }
+ }
+
+ PEI_TRACE ((EFI_D_ERROR, PeiServices, "EHCI HC RESET ERROR: timeout.\n"));
+ EhciDevPtr->HcStatus = EHCI_RESET_ERROR;
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EhciReleasePortOwner
+//
+// Description:
+//
+// Input:
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+EhciReleasePortOwner (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_EHCI_DEV *EhciDevPtr,
+ UINT8 PortNumber
+)
+{
+ EHCI_PORTSC *PortScReg = &EhciDevPtr->EhciHcOpReg->PortSC[PortNumber - 1];
+ UINT8 i = 0;
+
+ // Clear connect status change bit
+ PortScReg->Field.ConnectStatusChange = 1;
+
+ // Release port owner
+ PortScReg->Field.PortOwner = 1;
+ for (i = 0; i < 20; i++) {
+ if (PortScReg->Field.ConnectStatusChange != 0) {
+ break;
+ }
+ EHCI_FIXED_DELAY_MS( EhciDevPtr, 1); // 1 msec delay
+ }
+
+ PortScReg->Field.ConnectStatusChange = 1;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciHcGetRootHubPortStatus
+//
+// Description:
+// This function obtains the port status and port change status for
+// a port specified by PortNumber and updates the EFI_USB_PORT_STATUS
+// data structure as specified the the PortStatus pointer parameter.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 PortNumber
+// -- Port number for which status is requested
+// OUT EFI_USB_PORT_STATUS *PortStatus
+// -- EFI_USB_PORT_STATUS pointer's data is updated
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EhciHcGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus )
+{
+ PEI_EHCI_DEV *EhciDevPtr = PEI_RECOVERY_USB_EHCI_DEV_FROM_THIS( This );
+ EHCI_PORTSC *PortScReg = &EhciDevPtr->EhciHcOpReg->PortSC[PortNumber - 1];
+ UINT8 i = 0;
+
+ if (PortNumber > EhciDevPtr->bNumPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //PEI_TRACE((-1, PeiServices, "EHCI port[%d] status: %08x\n", PortNumber, PortScReg->AllBits));
+ PortStatus->PortStatus = 0;
+ PortStatus->PortChangeStatus = 0;
+
+ if (PortScReg->Field.CurrentConnectStatus != 0 &&
+ PortScReg->Field.PortEnable == 0 &&
+ PortScReg->Field.LineStatus == 0x1) {
+ EhciReleasePortOwner(PeiServices, EhciDevPtr, PortNumber);
+ }
+
+ if (PortScReg->Field.CurrentConnectStatus != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
+ if (PortScReg->Field.PortEnable != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
+ PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
+ }
+ }
+ if (PortScReg->Field.ConnectStatusChange != 0) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+ if (PortScReg->Field.PortEnableChange != 0) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
+ }
+ if (PortScReg->Field.OvercurrentActive != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
+ }
+ if (PortScReg->Field.OvercurrentChange != 0) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
+ }
+ if (PortScReg->Field.Suspend != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+ if (PortScReg->Field.PortReset != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_RESET;
+ }
+ if (PortScReg->Field.PortPower != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_POWER;
+ }
+ if (PortScReg->Field.PortOwner != 1) {
+ PortStatus->PortStatus |= USB_PORT_STAT_OWNER;
+ }
+ if (EhciDevPtr->PortResetStatusChangeMap & (1 << (PortNumber - 1))) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciHcGetRootHubPortNumber
+//
+// Description:
+// This function returns the number of downstream ports as specified
+// in the HcRhDescriptorA operational register.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// OUT UINT8 *PortNumber
+// -- Number of downstream ports
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EhciHcGetRootHubPortNumber (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *PortNumber )
+{
+
+ PEI_EHCI_DEV *EhciDevPtr = PEI_RECOVERY_USB_EHCI_DEV_FROM_THIS( This );
+
+ if (PortNumber == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *PortNumber = EhciDevPtr->bNumPorts;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciHcSetRootHubPortFeature
+//
+// Description:
+// This function sets port feature as specified by
+// PortFeature for the port specified by PortNumber.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 PortNumber
+// -- Port number whose feature is to be set
+// IN EFI_USB_PORT_FEATURE PortFeature
+// -- Feature to set
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EhciHcSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature )
+{
+ PEI_EHCI_DEV *EhciDevPtr = PEI_RECOVERY_USB_EHCI_DEV_FROM_THIS( This );
+ EHCI_PORTSC *PortScReg = &EhciDevPtr->EhciHcOpReg->PortSC[PortNumber - 1];
+ UINT32 PortSc = 0;
+ UINT8 i = 0;
+
+ if (PortNumber > EhciDevPtr->bNumPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PortSc = PortScReg->AllBits;
+ PortSc &= ~(EHCI_CONNECTSTATUSCHANGE | EHCI_PORTENABLESTATUSCHANGE | EHCI_OVERCURRENTCAHGE);
+
+ switch (PortFeature) {
+ case EfiUsbPortEnable:
+ break;
+
+ case EfiUsbPortSuspend:
+ PortSc |= EHCI_SUSPEND;
+ break;
+
+ case EfiUsbPortReset:
+ PortSc = PortScReg->AllBits;
+ PortSc &= ~(EHCI_CONNECTSTATUSCHANGE | EHCI_PORTENABLESTATUSCHANGE | EHCI_OVERCURRENTCAHGE);
+ PortScReg->AllBits = (PortSc & ~EHCI_PORTENABLE) | EHCI_PORTRESET;
+ EHCI_FIXED_DELAY_MS( EhciDevPtr, 50); // 50 msec delay
+
+ PortSc = PortScReg->AllBits;
+ PortSc &= ~(EHCI_PORTRESET | EHCI_CONNECTSTATUSCHANGE | EHCI_PORTENABLESTATUSCHANGE |
+ EHCI_OVERCURRENTCAHGE);
+ PortScReg->AllBits = PortSc;
+
+ for (i = 0; i < 10; i++) {
+ if (PortScReg->Field.PortReset == 0) {
+ break;
+ }
+ EHCI_FIXED_DELAY_MS( EhciDevPtr, 1); // 50 msec delay
+ }
+
+ if (PortScReg->Field.PortEnable != 0) {
+ EhciDevPtr->PortResetStatusChangeMap |= (1 << (PortNumber - 1));
+ } else {
+ EhciReleasePortOwner(PeiServices, EhciDevPtr, PortNumber);
+ }
+ //break;
+ return EFI_SUCCESS;
+
+ case EfiUsbPortPower:
+ PortSc |= EHCI_PORTPOWER;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ PortScReg->AllBits = PortSc;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciHcClearRootHubPortFeature
+//
+// Description:
+// This function clears an EHCI specification port feature as specified
+// by PortFeature for the port specified by PortNumber.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 PortNumber
+// -- Port number whose feature is to be set
+// IN EFI_USB_PORT_FEATURE PortFeature
+// -- Feature to set
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EhciHcClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature )
+{
+ PEI_EHCI_DEV *EhciDevPtr = PEI_RECOVERY_USB_EHCI_DEV_FROM_THIS( This );
+ UINT32 PortSc = 0;
+
+ if (PortNumber > EhciDevPtr->bNumPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PortSc = EhciDevPtr->EhciHcOpReg->PortSC[PortNumber - 1].AllBits;
+ PortSc &= ~(EHCI_CONNECTSTATUSCHANGE | EHCI_PORTENABLESTATUSCHANGE | EHCI_OVERCURRENTCAHGE);
+
+ switch (PortFeature) {
+ case EfiUsbPortEnable:
+ PortSc &= ~EHCI_PORTENABLE;
+ break;
+
+ case EfiUsbPortSuspend:
+ PortSc |= EHCI_FORCEPORTRESUME;
+ break;
+
+ case EfiUsbPortReset:
+ PortSc &= ~EHCI_PORTRESET;
+ break;
+
+ case EfiUsbPortPower:
+ PortSc &= ~EHCI_PORTPOWER;
+ break;
+
+ case EfiUsbPortOwner:
+ //PortSc |= EHCI_PORTOWNER;
+ EhciReleasePortOwner(PeiServices, EhciDevPtr, PortNumber);
+ //break;
+ return EFI_SUCCESS;
+
+ case EfiUsbPortConnectChange:
+ PortSc |= EHCI_CONNECTSTATUSCHANGE;
+ break;
+
+ case EfiUsbPortEnableChange:
+ PortSc |= EHCI_PORTENABLESTATUSCHANGE;
+ break;
+
+ case EfiUsbPortSuspendChange:
+ break;
+
+ case EfiUsbPortOverCurrentChange:
+ PortSc |= EHCI_OVERCURRENTCAHGE;
+ break;
+
+ case EfiUsbPortResetChange:
+ EhciDevPtr->PortResetStatusChangeMap &= ~(1 << (PortNumber - 1));
+ //break;
+ return EFI_SUCCESS;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ EhciDevPtr->EhciHcOpReg->PortSC[PortNumber - 1].AllBits = PortSc;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EHCIInitializeQueueHead
+//
+// Description: This function initializes the queue head with default values
+//
+// Input: fpQH Pointer to queue head
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+EHCIInitializeQueueHead(EHCI_QH *fpQH)
+{
+ fpQH->dNextqTDPtr = 1;
+ fpQH->dAltNextqTDPtr = 1;
+ fpQH->dCurqTDPtr = 1;
+
+ fpQH->dEndPntCap = QH_ONE_XFER;
+ fpQH->dToken = 0;
+ fpQH->dEndPntCharac = 0;
+ fpQH->dBufferPtr0 = 0;
+ fpQH->dBufferPtr1 = 0;
+ fpQH->dBufferPtr2 = 0;
+ fpQH->dBufferPtr3 = 0;
+ fpQH->dBufferPtr4 = 0;
+ fpQH->bErrorStatus = 0;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EHCISetQTDBufferPointers
+//
+// Description: This function will set the 5 buffer pointer in the qTD
+// appropriately depending upon the input size
+//
+// Input: fpQtd - Pointer to the qTD
+// fpBuf - 32bit absolute buffer pointer
+// wSize - Amount of data to be transferred
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+EHCISetQTDBufferPointers(
+ EHCI_QTD *fpQtd,
+ UINT8 *fpBuf,
+ UINT32 dSize
+)
+{
+ UINT16 wBufSize;
+ UINT8 *fpBuffer = fpBuf;
+ UINT32 *fpBufferPtr;
+ UINT16 w4KRemainder;
+
+ //
+ // Fill the buffer pointers with 0s
+ //
+ fpQtd->dBufferPtr0 = 0;
+ fpQtd->dBufferPtr1 = 0;
+ fpQtd->dBufferPtr2 = 0;
+ fpQtd->dBufferPtr3 = 0;
+ fpQtd->dBufferPtr4 = 0;
+ fpQtd->dAltNextqTDPtr = 1;
+
+ //
+ // If size to transfer is 0 skip updating pointers
+ //
+ if (!dSize)
+ {
+ return;
+ }
+
+ //
+ // Make sure the amount of data to be xferred is 16K or less
+ //
+ wBufSize = (UINT16)((dSize > PEI_MAX_EHCI_DATA_SIZE) ? PEI_MAX_EHCI_DATA_SIZE : dSize);
+
+ fpBufferPtr = &fpQtd->dBufferPtr0;
+
+ for (;;)
+ {
+ *fpBufferPtr = (UINT32)(UINTN)fpBuffer;
+ //
+ // Calculate the number of bytes that can be transferred using current
+ // buffer pointer
+ //
+ w4KRemainder = (UINT16)((((UINT32)((UINTN)fpBuffer+0x1000)) & 0xFFFFF000) -
+ (UINT32)(UINTN)fpBuffer);
+
+ //
+ // Check whether all the bytes can be accomadated in the current buffer
+ //
+ if (w4KRemainder >= wBufSize)
+ {
+ break; // Yes. Current Buffer is sufficient for the rest of data
+ }
+
+ //
+ // We have more data to transfer - adjust data and store it in the next pointer
+ //
+ wBufSize = (UINT16)(wBufSize - w4KRemainder); // Amount of data remaining
+ fpBuffer = fpBuffer + w4KRemainder; // Adjust buffer (4K bound)
+ fpBufferPtr++; // Next buffer pointer
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIStartAsyncSchedule
+//
+// Description: This function starts the asynchronous schedule
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EHCIStartAsyncSchedule(
+ EHCI_HC_OPER_REG *HcOpReg
+)
+{
+ // Start the Async schedule
+ HcOpReg->UsbCmd.AllBits |= EHCI_ASYNC_SCHED_ENABLE;
+
+ // Make sure the HC started the async. execution
+ for (;HcOpReg->UsbSts.Field.AsyncSheduleStatus == 0;) {}
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIStopAsyncSchedule
+//
+// Description: This function stops the asynchronous transfer and sets the
+// asynchronous pointer to null
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EHCIStopAsyncSchedule(
+ EHCI_HC_OPER_REG *HcOpReg
+)
+{
+ // Stop the Async schedule
+ HcOpReg->UsbCmd.AllBits &= ~EHCI_ASYNC_SCHED_ENABLE;
+
+ // Make sure the HC stopped the async. execution
+ for (;HcOpReg->UsbSts.Field.AsyncSheduleStatus != 0;) {}
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EHCIProcessQH
+//
+// Description: This function whether all the TD's in the QH is completed
+//
+// Input: fpQH - Pointer to the QH which has to be completed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EHCIProcessQH(
+ EHCI_QH *fpQH
+)
+{
+ EHCI_QTD *fpQTD = fpQH->fpFirstqTD;
+
+ for (;;) {
+ //
+ // Check whether the qTD is active, if so. Exit!
+ //
+ if (fpQTD->dToken & QTD_ACTIVE) {
+ return; // Not complete
+ }
+
+ //
+ // Check for halt condition, if halted - exit
+ //
+ if (fpQTD->dToken & QTD_HALTED) {
+ //
+ // Set the QH halted status
+ //
+ fpQH->bErrorStatus = QTD_HALTED;
+ //
+ // Set the QH as in-active
+ //
+ fpQH->bActive = FALSE;
+
+ return; // Complete
+ }
+ //
+ // qTD is not active and not halted. That is it is completed successfully
+ // Check whether this qTD is the last one in the list
+ //
+ if (fpQTD->dNextqTDPtr & EHCI_TERMINATE) {
+ //
+ // Set the QH as in-active
+ //
+ fpQH->bActive = FALSE;
+ return; // Complete
+ }
+ //
+ // More qTDs are in the list. Process next qTD
+ //
+ fpQTD = (EHCI_QTD*)(UINTN)fpQTD->dNextqTDPtr;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EHCIWaitForAsyncTransferComplete
+//
+// Description: This function waits for asynchronous transfer completion.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EHCIWaitForAsyncTransferComplete (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_EHCI_DEV *EhciDevPtr,
+ EHCI_QH *QHead
+)
+{
+ UINT32 Count;
+ UINT32 TimeOut = 15000; // 5 sec
+
+ for(Count = 0; Count < TimeOut; Count++)
+ {
+ EHCIProcessQH(QHead);
+
+ if(QHead->bActive == FALSE)
+ {
+ return;
+ }
+ EHCI_FIXED_DELAY_MS( EhciDevPtr, 1); // 1 msec delay
+ }
+
+ PEI_TRACE ((EFI_D_ERROR, PeiServices, "EHCI Time-Out:\n"));
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciHcControlTransfer
+//
+// Description:
+// This function intiates a USB control transfer and waits on it to
+// complete.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 bDeviceAddress
+// -- USB address of the device for which the control
+// transfer is to be issued
+// IN UINT8 DeviceSpeed
+// -- Not used
+// IN UINT8 MaximumPacketLength
+// -- Maximum number of bytes that can be sent to or
+// received from the endpoint in a single data packet
+// IN EFI_USB_DEVICE_REQUEST *Request
+// -- EFI_USB_DEVICE_REQUEST pointer
+// IN EFI_USB_DATA_DIRECTION TransferDirection
+// -- Direction of transfer
+// OPTIONAL IN OUT VOID *DataBuffer
+// -- Pointer to source or destination buffer
+// OPTIONAL IN OUT UINTN *DataLength
+// -- Length of buffer
+// IN UINTN TimeOut
+// -- Not used
+// OUT UINT32 *TransferResult
+// -- Not used
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EhciHcControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 bDeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *DataBuffer OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult )
+{
+ UINT16 WordRequest;
+ UINT16 WordIndex;
+ UINT16 WordValue;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+
+ PEI_EHCI_DEV *EhciDevPtr = PEI_RECOVERY_USB_EHCI_DEV_FROM_THIS( This );
+ EHCI_HC_OPER_REG *HcOpReg = EhciDevPtr->EhciHcOpReg;
+ EHCI_DESC_PTRS *DescPtrs = &EhciDevPtr->stEHCIDescPtrs;
+ UINT16 wLength = (DataLength != NULL)? (UINT16) *DataLength : 0;
+ EHCI_QH *fpQHCtl;
+ EHCI_QTD *fpQTDCtlSetup, *fpQTDCtlData, *fpQTDCtlStatus;
+
+ UINT32 dTmp, dTmp1;
+
+ WordRequest = (Request->Request << 8) | Request->RequestType;
+ WordValue = Request->Value;
+ WordIndex = Request->Index;
+
+ //
+ // Intialize the queue head with null pointers
+ //
+ fpQHCtl = DescPtrs->fpQHControl;
+ EHCIInitializeQueueHead(fpQHCtl);
+
+ //
+ // Assume as a high speed device
+ //
+ dTmp = QH_HIGH_SPEED; // 10b - High speed
+
+ if (DeviceSpeed != USB_HIGH_SPEED_DEVICE && TransactionTranslator != 0)
+ {
+ // Low/Full speed device OR device is connected to a root port
+ // DeviceSpeed = 1 (low) or 2 (full)
+ dTmp = (UINT32)((DeviceSpeed & 1) << 12); // Bit 12 = full/low speed flag
+ dTmp |= QH_CONTROL_ENDPOINT;
+ //
+ // Set the hub address and port number
+ //
+ dTmp1 = (TransactionTranslator << 16) | (BIT10+BIT11+BIT12); // Split complete Xaction
+ fpQHCtl->dEndPntCap |= dTmp1;
+ }
+
+ dTmp |= (QH_USE_QTD_DT | QH_HEAD_OF_LIST);
+ dTmp |= (UINT32)bDeviceAddress;
+
+ //
+ // dTmp[Bits 6:0] = Dev. Addr
+ // dTmp[Bit7] = I bit(0)
+ // dTmp[Bits11:8] = Endpoint (0)
+ //
+ dTmp1 = MaximumPacketLength;
+ dTmp |= (dTmp1 << 16); // Tmp[Bits26:16] = device's packet size
+ fpQHCtl->dEndPntCharac = dTmp;
+
+ //
+ // Fill in various fields in the qTDControlSetup.
+ //
+ fpQTDCtlSetup = DescPtrs->fpqTDControlSetup;
+
+ //
+ // The token field will be set so
+ // Direction PID = QTD_SETUP_TOKEN,
+ // Size = size of the data,
+ // Data Toggle = QTD_SETUP_TOGGLE,
+ // Error Count = QTD_NO_ERRORS,
+ // Status code = QTD_DO_OUT + QTD_ACTIVE
+ // The buffer pointers field will point to the aControlSetupData buffer
+ // which was before initialized to contain a DeviceRequest struc.
+ // The dNextqTDPtr field will point to the qTDControlData if data will
+ // be sent/received or to the qTDControlStatus if no data is expected.
+ // The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+ //
+ fpQTDCtlSetup->dToken = QTD_SETUP_TOKEN | QTD_SETUP_TOGGLE | QTD_IOC_BIT |
+ QTD_NO_ERRORS | QTD_DO_OUT | QTD_ACTIVE |
+ (8 << 16); // Data size
+
+ //
+ // Update buffer pointers
+ //
+ EHCISetQTDBufferPointers(fpQTDCtlSetup,
+ (UINT8*)Request,
+ 8);
+ fpQTDCtlData = DescPtrs->fpqTDControlData;
+
+ if (wLength != 0 && DataBuffer != NULL) // br if no data to transfer
+ {
+ //
+ // Fill in various fields in the qTDControlData
+ //
+ // The token field will be set so
+ // Direction PID = QTD_OUT_TOKEN/QTD_IN_TOKEN,
+ // Size = size of the data,
+ // Data Toggle = QTD_DATA1_TOGGLE,
+ // Error Count = QTD_NO_ERRORS,
+ // Status code = QTD_DO_OUT(if it is out) + QTD_ACTIVE
+ // The buffer pointers field will point to the fpBuffer buffer
+ // which was before initialized to contain a DeviceRequest struc.
+ // The dNextqTDPtr field will point to the qTDControlSetup
+ // The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+ //
+ fpQTDCtlData->dToken = QTD_IN_TOKEN |
+ QTD_DATA1_TOGGLE | QTD_IOC_BIT |
+ QTD_NO_ERRORS | QTD_ACTIVE;
+ if ((WordRequest & BIT7) == 0) // Br if host sending data to device (OUT)
+ {
+ fpQTDCtlData->dToken = QTD_OUT_TOKEN |
+ QTD_DATA1_TOGGLE | QTD_IOC_BIT |
+ QTD_NO_ERRORS | QTD_DO_OUT | QTD_ACTIVE;
+ }
+
+ //
+ // Set length
+ //
+ fpQTDCtlData->dToken |= ((UINT32)wLength << 16);
+
+ //
+ // Update buffer pointers
+ //
+ EHCISetQTDBufferPointers(fpQTDCtlData,
+ (UINT8*)DataBuffer,
+ (UINT32)wLength);
+ }
+
+ //
+ // Fill in various fields in the qTDControlStatus
+ //
+ fpQTDCtlStatus = DescPtrs->fpqTDControlStatus;
+
+ //
+ // The token field will be set so
+ // Direction PID = QTD_OUT_TOKEN/QTD_IN_TOKEN,
+ // Size = 0,
+ // Data Toggle = QTD_DATA1_TOGGLE,
+ // Error Count = QTD_NO_ERRORS,
+ // Status code = QTD_DO_OUT(if it is out) + QTD_ACTIVE
+ // The buffer pointers field will be 0
+ // The dNextqTDPtr field will set to EHCI_TERMINATE
+ // The dAltNextqTDPtr field will be set to EHCI_TERMINATE
+ //
+ // For OUT control transfer status should be IN and
+ // for IN cotrol transfer, status should be OUT
+ //
+ fpQTDCtlStatus->dToken = QTD_IN_TOKEN |
+ QTD_DATA1_TOGGLE | QTD_IOC_BIT |
+ QTD_NO_ERRORS | QTD_ACTIVE;
+ if((WordRequest & BIT7) != 0)
+ {
+ fpQTDCtlStatus->dToken = QTD_OUT_TOKEN |
+ QTD_DATA1_TOGGLE | QTD_IOC_BIT |
+ QTD_NO_ERRORS | QTD_DO_OUT | QTD_ACTIVE;
+ }
+
+ EHCISetQTDBufferPointers(fpQTDCtlStatus, NULL, 0);
+
+ //
+ // Link the qTD formed now and connect them with the control queue head
+ //
+ fpQHCtl->fpFirstqTD = fpQTDCtlSetup;
+ fpQHCtl->dNextqTDPtr = (UINT32)(UINTN)fpQTDCtlSetup;
+
+ if (wLength != 0)
+ {
+ fpQTDCtlSetup->dNextqTDPtr = (UINT32)(UINTN)fpQTDCtlData;
+ fpQTDCtlData->dNextqTDPtr = (UINT32)(UINTN)fpQTDCtlStatus;
+ }
+ else
+ {
+ fpQTDCtlSetup->dNextqTDPtr = (UINT32)(UINTN)fpQTDCtlStatus;
+ }
+
+ fpQTDCtlStatus->dNextqTDPtr = EHCI_TERMINATE;
+
+ //
+ // Set the ASYNCLISTADDR register to point to the QHControl
+ //
+ HcOpReg->AsyncListAddr = (UINT32)(UINTN)fpQHCtl;
+
+ //
+ // Set next QH pointer to itself (circular link)
+ //
+ fpQHCtl->dLinkPointer = (UINT32)((UINTN)fpQHCtl | EHCI_QUEUE_HEAD);
+ fpQHCtl->bActive = TRUE;
+
+ //
+ // Now put the control setup, data and status into the HC's schedule by
+ // setting the Async. schedule enabled field of USBCMD register
+ // This will cause the HC to execute the transaction in the next active frame.
+ //
+ EHCIStartAsyncSchedule(HcOpReg);
+
+ EHCIWaitForAsyncTransferComplete(PeiServices, EhciDevPtr, fpQHCtl);
+
+ //
+ // Stop the Async transfer
+ //
+ EHCIStopAsyncSchedule(HcOpReg);
+
+ //
+ // Check whether the QH stopped or timed out
+ //
+ if (fpQHCtl->bActive == TRUE)
+ {
+
+ fpQHCtl->bActive = FALSE;
+ }
+ else
+ {
+ //
+ // Check for the stall condition
+ //
+ if (fpQHCtl->bErrorStatus & QTD_HALTED)
+ {
+ //
+ // Command stalled set the error bit appropriately
+ //
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ fpQHCtl->fpFirstqTD = 0;
+ fpQHCtl->dNextqTDPtr = EHCI_TERMINATE;
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: EhciHcBulkTransfer
+//
+// Description:
+// This function intiates a USB bulk transfer and waits on it to
+// complete.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 DeviceAddress
+// -- USB address of the device for which the control
+// transfer is to be issued
+// IN UINT8 EndPointAddress
+// -- Particular endpoint for the device
+// IN UINT8 MaximumPacketLength
+// -- Maximum number of bytes that can be sent to or
+// received from the endpoint in a single data packet
+// OPTIONAL IN OUT VOID *DataBuffer
+// -- Pointer to source or destination buffer
+// OPTIONAL IN OUT UINTN *DataLength
+// -- Length of buffer
+// IN OUT UINT8 *DataToggle
+// -- Used to update the control/status DataToggle field
+// of the Transfer Descriptor
+// IN UINTN TimeOut
+// -- Not used
+// OUT UINT32 *TransferResult
+// -- Not used
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EhciHcBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT16 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN OUT VOID *DataBuffer,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult )
+{
+ PEI_EHCI_DEV *EhciDevPtr = PEI_RECOVERY_USB_EHCI_DEV_FROM_THIS( This );
+ EHCI_HC_OPER_REG *HcOpReg = EhciDevPtr->EhciHcOpReg;
+ EHCI_DESC_PTRS *DescPtrs = &EhciDevPtr->stEHCIDescPtrs;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 dBytesToTransfer;
+ UINT32 dTmp, dTmp1;
+ EHCI_QH *fpQHBulk;
+ EHCI_QTD *fpQTDBulkData;
+
+//PEI_TRACE ((EFI_D_ERROR, PeiServices, "bulk..%x, device address %d\n", *DataLength, DeviceAddress));
+
+ dBytesToTransfer =
+ (*DataLength < PEI_MAX_EHCI_DATA_SIZE)? (UINT32)*DataLength : PEI_MAX_EHCI_DATA_SIZE;
+
+ //
+ // Set the QH's dNextqTDPtr field to bulk data qTD and dAltqTDPtr field to
+ // EHCI_TERMINATE. Also set QH's link pointer to itself
+ //
+ fpQHBulk = DescPtrs->fpQHBulk;
+ fpQTDBulkData = DescPtrs->fpqTDBulkData;
+
+ //
+ // Intialize the queue head
+ //
+ EHCIInitializeQueueHead(fpQHBulk);
+
+ //
+ // Set the first qTD pointer
+ //
+ fpQHBulk->fpFirstqTD = fpQTDBulkData;
+ fpQHBulk->dNextqTDPtr = (UINT32)(UINTN)fpQTDBulkData;
+ fpQHBulk->dLinkPointer = (UINT32)((UINTN)fpQHBulk | EHCI_QUEUE_HEAD);
+
+ //
+ // Device address, Endpoint, max packet size, data toggle control
+ //
+ dTmp = (UINT32)(DeviceAddress | (EndPointAddress << 8));
+ dTmp |= ((UINT32)MaximumPacketLength << 16);
+ dTmp |= (QH_USE_QTD_DT | QH_HEAD_OF_LIST);
+
+ //
+ // Assume as a high speed device
+ //
+ dTmp |= QH_HIGH_SPEED; // 10b - High speed
+
+ if (DeviceSpeed != USB_HIGH_SPEED_DEVICE && TransactionTranslator != 0)
+ {
+ // Note: low speed bulk endpoints are not supported
+ dTmp1 = BIT12; // Bit 12 = full speed flag
+ dTmp &= ~(QH_ENDPOINT_SPEED);
+ dTmp |= dTmp1;
+ //
+ // Set the hub address and port number
+ //
+ dTmp1 = (TransactionTranslator << 16) | BIT14; // Hispeed hub port number & device number
+ fpQHBulk->dEndPntCap |= dTmp1; // Split complete Xaction
+ }
+
+ //
+ // Update the endpoint characteristcs field with the data formed
+ //
+ fpQHBulk->dEndPntCharac = dTmp;
+
+ //
+ // Fill the bulk data qTD with relevant information
+ //
+ if ((EndPointAddress & BIT7) != 0)
+ {
+ fpQTDBulkData->dToken = QTD_IN_TOKEN |
+ QTD_IOC_BIT |
+ QTD_NO_ERRORS | QTD_ACTIVE;
+ }
+ else
+ {
+ fpQTDBulkData->dToken = QTD_OUT_TOKEN |
+ QTD_IOC_BIT |
+ QTD_NO_ERRORS | QTD_DO_OUT | QTD_ACTIVE;
+ }
+
+ //
+ // Set the data toggle depending on the DatToggle value
+ //
+ fpQTDBulkData->dToken |= ((UINT32)(*DataToggle)) << 31;
+
+ //
+ // Set length
+ //
+ fpQTDBulkData->dToken |= (dBytesToTransfer << 16);
+
+ //
+ // Update buffer pointers
+ //
+ EHCISetQTDBufferPointers(
+ fpQTDBulkData, (UINT8*)DataBuffer, dBytesToTransfer);
+
+ //
+ // Update next & alternate next qTD pointers
+ //
+ fpQTDBulkData->dNextqTDPtr = EHCI_TERMINATE;
+ fpQTDBulkData->dAltNextqTDPtr = EHCI_TERMINATE;
+
+ //
+ // Set the ASYNCLISTADDR register to point to the QHBulk
+ //
+ HcOpReg->AsyncListAddr = (UINT32)(UINTN)fpQHBulk;
+
+ fpQHBulk->bActive = TRUE;
+
+ //
+ // Now put the bulk QH into the HC's schedule by
+ // setting the Async. schedule enabled field of USBCMD register
+ // This will cause the HC to execute the transaction in the next active frame.
+ //
+ EHCIStartAsyncSchedule(HcOpReg);
+
+ EHCIWaitForAsyncTransferComplete(PeiServices, EhciDevPtr, fpQHBulk);
+
+ //
+ // Stop the Async transfer
+ //
+ EHCIStopAsyncSchedule(HcOpReg);
+
+ dTmp = 0; // Return value
+
+ //
+ // Check whether the QH stopped or timed out
+ //
+ if(fpQHBulk->bActive == TRUE)
+ {
+
+ fpQHBulk->bActive = FALSE;
+
+ //
+ // TODO: Set time out status
+ //
+ Status = EFI_DEVICE_ERROR;
+ }
+ else
+ {
+ //
+ // Check for the error conditions - if possible recover from them
+ //
+ if (fpQHBulk->bErrorStatus & QTD_HALTED)
+ {
+ //
+ // TODO:: Indicate Stall condition
+ //
+ Status = EFI_DEVICE_ERROR;
+ }
+ else
+ {
+ dTmp = 0xFFFFFFFF; // Indicate success
+ }
+ }
+ if (dTmp != 0)
+ {
+ *DataToggle = (UINT8)(((fpQHBulk->dToken & QH_DATA_TOGGLE) >> 31) & 1);
+ //
+ // Get the size of data transferred
+ //
+ dTmp = (fpQTDBulkData->dToken & ~(QTD_DATA_TOGGLE)) >> 16;
+ dTmp = (dTmp != 0)? dBytesToTransfer-dTmp : dBytesToTransfer;
+ }
+
+ fpQHBulk->fpFirstqTD = 0;
+ fpQHBulk->dNextqTDPtr = EHCI_TERMINATE;
+
+ *DataLength = (UINTN)dTmp;
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DwordReadMem
+//
+// Description: This routine reads a DWORD from the specified Memory Address
+//
+// Input: dBaseAddr - Memory address to read
+// bOffset - Offset of dBaseAddr
+//
+// Output: Value read
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+DwordReadMem(UINT32 dBaseAddr, UINT16 wOffset)
+{
+ return *(volatile UINT32*)(UINTN)(dBaseAddr+wOffset);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DwordWriteMem
+//
+// Description: This routine writes a DWORD to a specified Memory Address
+//
+// Input: dBaseAddr - Memory address to write
+// bOffset - Offset of dBaseAddr
+// dValue - Data to write
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+DwordWriteMem(UINT32 dBaseAddr, UINT16 wOffset, UINT32 dValue)
+{
+ *(volatile UINT32*)(UINTN)(dBaseAddr+wOffset) = dValue;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: NotifyOnRecoveryCapsuleLoaded
+//
+// Description: This routine halts the all available EHCI host controller
+//
+// Input: PeiServices
+// dMemAddr - EHCI HC Mem_Base address
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS NotifyOnRecoveryCapsuleLoaded (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *InvokePpi )
+{
+ //(EIP99922)>
+ EFI_PEI_STALL_PPI *StallPpi = NULL;
+ EFI_GUID gPeiStallPpiGuid = EFI_PEI_STALL_PPI_GUID;
+ EFI_STATUS Status;
+ UINT8 ControllerIndex = 0;
+ EHCI_HC_CAP_REG *EhciHcCapReg;
+ EHCI_HC_OPER_REG *EhciHcOpReg;
+ UINTN i;
+ UINT8 ByteData;
+ UINT32 EhciBaseAddress;
+
+ // Locate PeiStall
+ Status = (**PeiServices).LocatePpi (
+ PeiServices,
+ &gPeiStallPpiGuid,
+ 0,
+ NULL,
+ &StallPpi
+ );
+
+ for ( ControllerIndex = 0; ControllerIndex < gEhciControllerCount; ControllerIndex++) {
+
+ EhciBaseAddress = EhciGetOperationalRegisterBase(PeiServices, ControllerIndex);
+
+ //
+ // Read the Capability Registers Length to find the Offset address for the
+ // beginning of the operational registers and set bMemAddr to its offset
+ //
+ EhciHcCapReg = (EHCI_HC_CAP_REG*)EhciBaseAddress;
+ EhciHcOpReg = (EHCI_HC_OPER_REG *)((UINTN)EhciHcCapReg + EhciHcCapReg->CapLength);
+
+ // Stop periodic schedule
+ EhciHcOpReg->UsbCmd.AllBits &= ~EHCI_PER_SCHED_ENABLE;
+ for (i = 0; i < 100; i++) {
+ StallPpi->Stall (PeiServices, StallPpi, 10); // 10us delay
+ if (EhciHcOpReg->UsbSts.Field.PeriodicSheduleStatus == 0) {
+ break;
+ }
+ }
+ EhciHcOpReg->PeriodicListBase = 0;
+
+ // Clear USB status register
+ EhciHcOpReg->UsbSts.AllBits = EhciHcOpReg->UsbSts.AllBits;
+ //
+ // Check HC is runnning, if so STOP before proceeding
+ //
+ if (EhciHcOpReg->UsbSts.Field.HCHalted == 0) {
+ EhciHcOpReg->UsbCmd.AllBits &= ~(EHCI_RUNSTOP | EHCI_PER_SCHED_ENABLE);
+ for (i = 0; i < 16; i++) {
+ StallPpi->Stall (PeiServices, StallPpi, 125); // 125us delay
+ if (EhciHcOpReg->UsbSts.Field.HCHalted) {
+ break;
+ }
+ }
+ }
+
+ // Reset controller
+ EhciHcOpReg->UsbCmd.Field.HcReset = 1;
+ for (i = 0; i < 100; i++) {
+ StallPpi->Stall (PeiServices, StallPpi, 1000); // 1ms delay
+ if (EhciHcOpReg->UsbCmd.Field.HcReset == 0) {
+ break;
+ }
+ }
+
+ ByteData= 0;
+ (*PeiServices)->PciCfg->Write( PeiServices, (*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint8,
+ gEhciControllerPciTable[ControllerIndex] + EHCI_CMD_REGISTER,
+ &ByteData);
+
+ EhciBaseAddress = 0;
+ (*PeiServices)->PciCfg->Write( PeiServices, (*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint32,
+ gEhciControllerPciTable[ControllerIndex] + EHCI_BASE_ADDR_REG,
+ &EhciBaseAddress);
+ }//end of for
+ //<(EIP99922)
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/EhciPEI/EhciPei.cif b/Core/EM/UsbRecovery/EhciPEI/EhciPei.cif
new file mode 100644
index 0000000..6bc2930
--- /dev/null
+++ b/Core/EM/UsbRecovery/EhciPEI/EhciPei.cif
@@ -0,0 +1,10 @@
+<component>
+ name = "EhciPei"
+ category = ModulePart
+ LocalRoot = "core\em\UsbRecovery\EhciPEI\"
+ RefName = "EhciPei"
+[files]
+"EhciPei.c"
+"EhciPei.h"
+"EhciPeiBoard.c"
+<endComponent>
diff --git a/Core/EM/UsbRecovery/EhciPEI/EhciPei.h b/Core/EM/UsbRecovery/EhciPEI/EhciPei.h
new file mode 100644
index 0000000..7f7c2c6
--- /dev/null
+++ b/Core/EM/UsbRecovery/EhciPEI/EhciPei.h
@@ -0,0 +1,592 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/EhciPei.h 8 11/24/12 5:44a Ryanchou $
+//
+// $Revision: 8 $
+//
+// $Date: 11/24/12 5:44a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/EhciPei.h $
+//
+// 8 11/24/12 5:44a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 7 8/23/12 9:58p Wilsonlee
+// [TAG] EIP97069
+// [Category] Improvement
+// [Description] Reset root port algorythm update.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// UhcPeim.h, UsbPeim.c, usb.h
+//
+// 6 1/18/11 12:53a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 5 4/26/10 4:16p Krishnakumarg
+// DebugRx causes the system to hang in Recovery mode EIP#34401
+//
+// 4 7/30/09 6:23p Krishnakumarg
+// Symptom :During recovery,system hangs while entering setup.
+// RootCause:USB Host controller Status registers are not cleared and HC
+// is not HALTed after loading recovery capsule.
+// Solution: HC is set to HALT state after loading recovery module so USB
+// driver clears the status Registers.
+//
+// 3 5/01/09 9:27a Rameshr
+// Symptom :Sometime system hang on recovery path.
+// Issue: Optimization makes Usbstatus value not updated from memory
+// everytime before checking it.
+// Solution: UsbStatus made as Volatile to get the current data from
+// memory before checking.
+//
+// 2 3/17/09 5:08p Olegi
+// Added TransactionTranslator for slow/full speed devices behind USB2
+// hub.
+//
+// 1 3/03/09 7:28p Olegi
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EhciPei.h
+//
+// Description: This file is the main header file for the EHCI PEI USB
+// recovery module. It contains generic constant and type
+// declarations/definitions.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef _EHCIPEI_H
+#define _EHCIPEI_H
+
+#include "Efi.h"
+#include "Pei.h"
+#include "Ppi\UsbHostController.h"
+#include "AmiMapping.h"
+
+//----------------------------------------------------------------------------
+// EHCI_FIXED_DELAY_MS( EhciDevPtr, milliseconds )
+//
+// invokes a delay specified in milliseconds using the PEI_EHCI_DEV.StallPpi
+// member interface pointer, which is initialized from a EFI_PEI_STALL_PPI
+// interface.
+#define EHCI_FIXED_DELAY_MS( EhciDevPtr, milliseconds ) \
+ EhciDevPtr->StallPpi->Stall( EhciDevPtr->PeiServices, \
+ EhciDevPtr->StallPpi, milliseconds * 1000 );
+
+
+//----------------------------------------------------------------------------
+// PEI_RECOVERY_USB_EHCI_DEV_FROM_THIS( a )
+//
+// uses the _CR macro to obtain a pointer to a PEI_EHCI_DEV structure from
+// a PEI_USB_HOST_CONTROLLER_PPI interface pointer
+#define _CR( Record, TYPE, Field ) \
+ ( (TYPE *) ( (CHAR8 *) (Record) - (CHAR8 *) &( ( (TYPE *) 0 )->Field ) ) )
+#define PEI_RECOVERY_USB_EHCI_DEV_FROM_THIS( a ) \
+ _CR( a, PEI_EHCI_DEV, UsbHostControllerPpi )
+
+
+//----------------------------------------------------------------------------
+// Constants
+//
+// Notes:
+// 1) These constants are not associated with a particular structure
+// and are used globally withing EHCI-specific code
+//----------------------------------------------------------------------------
+
+
+
+// Standard EHCI PCI configuration space registers
+#define EHCI_BASE_ADDR_REG 0x10 // EHCI BAR register
+#define EHCI_CMD_REGISTER 0x04 // EHCI command register
+#define DEBUG_BASE 0x5A // DEBUG_BASE offset address
+
+// EHCI controller status definitions
+#define EHCI_RESET_ERROR BIT0
+#define EHCI_VERCAPLENGTH 0 // Interface Version and Capability
+#define EHCI_USBCMD_REG 0 // USB Command
+
+// Bit definition for queue transfer descriptor token fields
+//-------------------------------------------------------------------------
+#define QTD_DATA_TOGGLE 0x80000000 // BIT 31
+ #define QTD_SETUP_TOGGLE 0x00000000
+ #define QTD_DATA0_TOGGLE 0x00000000
+ #define QTD_DATA1_TOGGLE 0x80000000
+ #define QTD_STATUS_TOGGLE 0x80000000
+#define QTD_XFER_DATA_SIZE 0x7FFF0000 // BIT 30:16
+#define QTD_IOC_BIT 0x00008000 // BIT 15
+#define QTD_ERROR_COUNT 0x00000C00
+ #define QTD_NO_ERRORS 0x00000000
+ #define QTD_ONE_ERROR 0x00000400
+ #define QTD_TWO_ERRORS 0x00000800
+ #define QTD_THREE_ERRORS 0x00000C00
+#define QTD_DIRECTION_PID 0x00000300
+ #define QTD_OUT_TOKEN 0x00000000
+ #define QTD_IN_TOKEN 0x00000100
+ #define QTD_SETUP_TOKEN 0x00000200
+#define QTD_STATUS_FIELD 0x000000FF
+ #define QTD_ACTIVE 0x00000080
+ #define QTD_HALTED 0x00000040
+ #define QTD_BUFFER_ERROR 0x00000020
+ #define QTD_BABBLE 0x00000010
+ #define QTD_XACT_ERROR 0x00000008
+ #define QTD_MISSED_UFRAME 0x00000004
+ #define QTD_SPLIT_XSTATE 0x00000002
+ #define QTD_START_SPLIT 0x00000000
+ #define QTD_COMPLETE_SPLIT 0x00000002
+ #define QTD_SPLIT_ERROR 0x00000001
+ #define QTD_PING_STATE 0x00000001
+ #define QTD_DO_OUT 0x00000000
+ #define QTD_DO_PING 0x00000001
+//-------------------------------------------------------------------------
+
+#define QH_I_BIT 0x00000080 // BIT 7
+#define QH_ENDPOINT_SPEED 0x00003000 // BIT 13:12
+ #define QH_FULL_SPEED 0x00000000
+ #define QH_LOW_SPEED 0x00001000
+ #define QH_HIGH_SPEED 0x00002000
+#define QH_DATA_TOGGLE_CONTROL 0x00004000 // BIT 14
+ #define QH_IGNORE_QTD_DT 0x00000000
+ #define QH_USE_QTD_DT 0x00004000
+#define QH_HEAD_OF_LIST 0x00008000 // BIT 15
+#define QH_CONTROL_ENDPOINT 0x08000000 // BIT 27
+#define QH_DATA_TOGGLE 0x80000000 // BIT 31
+
+#define QH_MULT_SETTING 0xC0000000 // BIT 31:30
+ #define QH_ONE_XFER 0x40000000
+ #define QH_TWO_XFER 0x80000000
+ #define QH_THREE_XFER 0xC0000000
+
+#define EHCI_QUEUE_HEAD 2 // Queue head id
+
+
+#define EHCI_TERMINATE 1
+
+//----------------------------------------------------------------------------
+// Structure types
+//
+// Notes:
+// 1) Constants that are associated with a particular structure
+// are defined locally within the structure to facilitate easier
+// maintenance.
+//----------------------------------------------------------------------------
+
+#pragma pack(push,1)
+
+
+//
+// Notes:
+// To ensure proper updating, follow these guidelines:
+//
+// 1) Write all bits using the AllBits union element
+// (OR bit-constants if modifying multiple fields).
+//
+// * Writing individual bits may have adverse
+// effects.
+//
+// 2) Typically you will read individual bits using the
+// Field union element.
+//
+// 3) Writing a zero to any field in this register has
+// no effect.
+//
+
+typedef struct _EHCI_HCS_PARAMS
+{
+ union {
+ UINT32 AllBits;
+ #define EHCI_HCSP_N_PORTS (BIT0+BIT1+BIT2+BIT3)
+ #define EHCI_HCSP_PPC BIT4
+ #define EHCI_HCSP_PRR BIT7
+ #define EHCI_HCSP_N_PCC (BIT8+BIT9+BIT10+BIT11)
+ #define EHCI_N_CC (BIT12+BIT13+BIT14+BIT15)
+ #define EHCI_P_INDICATOR BIT16
+ #define EHCI_DEBUG_N (BIT20+BIT21+BIT22+BIT23)
+ struct
+ {
+ UINT32 NumberOfPorts : 4; // [3:0]
+ UINT32 PortPowerControl : 1; // [4]
+ UINT32 Reserved1 : 2; // [6:5]
+ UINT32 PortRoutingRules : 1; // [7]
+ UINT32 PortPerCompanion : 4; // [11:8]
+ UINT32 NumberOfCompanions : 4; // [15:12]
+ UINT32 PortIndicators : 1; // [16]
+ UINT32 Reserved2 : 3; // [19:17]
+ UINT32 DebugPortNumber : 4; // [23:20]
+ UINT32 Reserved3 : 8; // [31:24]
+ } Field;
+ };
+} EHCI_HCS_PARAMS;
+
+typedef struct _EHCI_HCC_PARAMS
+{
+ union {
+ UINT32 AllBits;
+ #define EHCI_64BIT_CAP 0x01 // 64-bit addressing capability
+ #define EHCI_PFLFLAG 0x02 // Programmable Frame List Flag
+ #define EHCI_ASP_CAP 0x04 // Asynchronous Schedule Park Capability
+ #define EHCI_IST 0xF0 // Isochronous Scheduling Threshold
+ #define EHCI_EECP 0xFF00 // EHCI Extended Capabilities Pointer
+ struct
+ {
+ UINT32 AddressingCap64 : 1; // [0]
+ UINT32 FrameListFlag : 1; // [1]
+ UINT32 AsyncShedParkCap : 1; // [2]
+ UINT32 Reserved1 : 1; // [3]
+ UINT32 IsochShedThreshold : 4; // [7:4]
+ UINT32 ExtCapPointer : 8; // [15:8]
+ UINT32 Reserved2 : 16; // [31:8]
+ } Field;
+ };
+} EHCI_HCC_PARAMS;
+
+typedef struct _EHCI_HC_CAP_REG {
+ UINT8 CapLength;
+ UINT8 Reserved;
+ UINT16 HciVersion;
+ EHCI_HCS_PARAMS HcsParams;
+ EHCI_HCC_PARAMS HccParams;
+ UINT8 HcspPortRoute[15];
+} EHCI_HC_CAP_REG;
+
+
+typedef struct _EHCI_USBCMD
+{
+ union {
+ UINT32 AllBits;
+ #define EHCI_RUNSTOP BIT0
+ #define EHCI_HCRESET BIT1
+ #define EHCI_FRM1024 0 // Reset BIT2 and BIT3 before
+ #define EHCI_FRM512 BIT2 // setting the new Frame List Size
+ #define EHCI_FRM256 BIT3
+ #define EHCI_PER_SCHED_ENABLE BIT4
+ #define EHCI_ASYNC_SCHED_ENABLE BIT5
+ #define EHCI_INT_ASYNC_ADVANCE_ENABLE BIT6
+ #define EHCI_INTTHRESHOLD (8 << 16)
+ struct
+ {
+ UINT32 RunStop : 1; // [0]
+ UINT32 HcReset : 1; // [1]
+ UINT32 FrameListSize : 2; // [3:2]
+ UINT32 PeriodicSheduleEnable : 1; // [4]
+ UINT32 AsyncSheduleEnable : 1; // [5]
+ UINT32 IntAsyncAdvDorbell : 1; // [6]
+ UINT32 LightHcReset : 1; // [7]
+ UINT32 Reserved1 : 8; // [16:8]
+ UINT32 IntThresholdCtl : 8; // [23:16]
+ UINT32 Reserved2 : 8; // [31:24]
+ } Field;
+ };
+} EHCI_USBCMD;
+
+typedef struct _EHCI_USBSTS
+{
+ union {
+ UINT32 AllBits;
+ #define EHCI_USB_INTERRUPT BIT0 // Interrupt
+ #define EHCI_USB_ERROR_INTERRUPT BIT1 // Error interrupt
+ #define EHCI_PORT_CHANGE_DETECT BIT2 // Port Change Detect
+ #define EHCI_FRAME_LIST_ROLLOVER BIT3 // Frame List Rollover
+ #define EHCI_HOST_SYSTEM_ERROR BIT4 // Host System Error
+ #define EHCI_INT_ASYNC_ADVANCE BIT5 // Interrupt on Async Advance
+ #define EHCI_HCHALTED BIT12 // HCHalted
+ #define EHCI_RECLAIM BIT13 // Reclamation
+ #define EHCI_PER_SCHED_STATUS BIT14 // Periodic Schedule Status
+ #define EHCI_ASYNC_SCHED_STATUS BIT15 // Asynchronous Schedule Status
+ struct
+ {
+ UINT32 UsbInt : 1; // [0]
+ UINT32 UsbErrInt : 1; // [1]
+ UINT32 PortChangeDetect : 1; // [2]
+ UINT32 FrameListRollover : 1; // [3]
+ UINT32 HostSystemError : 1; // [4]
+ UINT32 IntOnAsyncAdvance : 1; // [5]
+ UINT32 Reserved1 : 6; // [11:6]
+ UINT32 HCHalted : 1; // [12]
+ UINT32 Reclamation : 1; // [13]
+ UINT32 PeriodicSheduleStatus : 1; // [14]
+ UINT32 AsyncSheduleStatus : 1; // [15]
+ UINT32 Reserved2 : 16; // [31:16]
+ } Field;
+ };
+} EHCI_USBSTS;
+
+typedef struct _EHCI_USBINTR
+{
+ union {
+ UINT32 AllBits;
+ #define EHCI_USBINT_EN BIT0 // Interrupt Enable
+ #define EHCI_USBERRINT_EN BIT1 // Error Interrupt Enable
+ #define EHCI_PCDINT_EN BIT2 // Port Change Detect Interrupt Enable
+ #define EHCI_FLRINT_EN BIT3 // Frame List Rollover Interrupt Enable
+ #define EHCI_HSEINT_EN BIT4 // Host System Error Interrupt Enable
+ #define EHCI_IAAINT_EN BIT5 // Interrupt on Async Advance Enable
+ struct
+ {
+ UINT32 UsbIntEnable : 1; // [0]
+ UINT32 UsbErrIntEnable : 1; // [1]
+ UINT32 PortChangeIntEnable : 1; // [2]
+ UINT32 FrameListRolloverEnable : 1; // [3]
+ UINT32 HostSystemErrorEnable : 1; // [4]
+ UINT32 IntOnAsyncAdvanceEnable : 1; // [5]
+ UINT32 Reserved : 26; // [31:6]
+ } Field;
+ };
+} EHCI_USBINTR;
+
+typedef struct _EHCI_PORTSC
+{
+ union {
+ UINT32 AllBits;
+ #define EHCI_CURRENTCONNECTSTATUS BIT0
+ #define EHCI_CONNECTSTATUSCHANGE BIT1
+ #define EHCI_PORTENABLE BIT2
+ #define EHCI_PORTENABLESTATUSCHANGE BIT3
+ #define EHCI_OVERCURRENTACTIVE BIT4
+ #define EHCI_OVERCURRENTCAHGE BIT5
+ #define EHCI_FORCEPORTRESUME BIT6
+ #define EHCI_SUSPEND BIT7
+ #define EHCI_PORTRESET BIT8
+ #define EHCI_DMINUSBIT BIT10
+ #define EHCI_DPLUSBIT BIT11
+ #define EHCI_PORTPOWER BIT12
+ #define EHCI_PORTOWNER BIT13
+ #define EHCI_WKCNNT_E BIT20 // Wake On Connect Enable
+ #define EHCI_WKDSCNNT_E BIT21 // Wake On Disconnect Enable
+ #define EHCI_WKOC_E BIT22 // Wake On Over-current Enable
+ struct
+ {
+ UINT32 CurrentConnectStatus : 1; // [0]
+ UINT32 ConnectStatusChange : 1; // [1]
+ UINT32 PortEnable : 1; // [2]
+ UINT32 PortEnableChange : 1; // [3]
+ UINT32 OvercurrentActive : 1; // [4]
+ UINT32 OvercurrentChange : 1; // [5]
+ UINT32 ForcePortResume : 1; // [6]
+ UINT32 Suspend : 1; // [7]
+ UINT32 PortReset : 1; // [8]
+ UINT32 Reserved1 : 1; // [9]
+ UINT32 LineStatus : 2; // [11:10]
+ UINT32 PortPower : 1; // [12]
+ UINT32 PortOwner : 1; // [13]
+ UINT32 PortIndicatorControl : 2; // [15:14]
+ UINT32 PortTestControl : 4; // [19:16]
+ UINT32 WakeOnConnectEnable : 1; // [20]
+ UINT32 WakeOnDisconnectEnable : 1; // [21]
+ UINT32 WakeOnOvercurrentEnable : 1; // [22]
+ UINT32 Reserved2 : 9; // [31:23]
+ } Field;
+ };
+} EHCI_PORTSC;
+
+
+
+typedef struct _EHCI_HC_OPER_REG {
+ EHCI_USBCMD UsbCmd;
+ volatile EHCI_USBSTS UsbSts;
+ EHCI_USBINTR UsbIntr;
+ UINT32 FrIndex;
+ UINT32 CtrlDsSegment;
+ UINT32 PeriodicListBase;
+ UINT32 AsyncListAddr;
+ UINT8 Reserved[36];
+ UINT32 ConfigFlag;
+ EHCI_PORTSC PortSC[16];
+} EHCI_HC_OPER_REG;
+
+
+typedef struct {
+ UINT32 dNextqTDPtr;
+ UINT32 dAltNextqTDPtr;
+ UINT32 dToken;
+ UINT32 dBufferPtr0;
+ UINT32 dBufferPtr1;
+ UINT32 dBufferPtr2;
+ UINT32 dBufferPtr3;
+ UINT32 dBufferPtr4;
+ UINT32 dReserved[8];
+} EHCI_QTD;
+
+
+typedef struct {
+ UINT32 dLinkPointer;
+ UINT32 dEndPntCharac;
+ UINT32 dEndPntCap;
+ UINT32 dCurqTDPtr;
+ UINT32 dNextqTDPtr;
+ UINT32 dAltNextqTDPtr;
+ UINT32 dToken;
+ UINT32 dBufferPtr0;
+ UINT32 dBufferPtr1;
+ UINT32 dBufferPtr2;
+ UINT32 dBufferPtr3;
+ UINT32 dBufferPtr4;
+ UINT32 dReserved[8];
+ VOID *fpCallBackFunc;
+ EHCI_QTD *fpFirstqTD;
+ UINT8 bActive;
+ UINT8 bErrorStatus;
+ UINT8 *fpDevInfoPtr;
+ UINT8 aDataBuffer[8];
+ UINT8 Pad[38-3*sizeof(VOID*)]; // sizeof(EHCI_QH)should be divisible by 32
+} EHCI_QH; // because of 32 bin pointers; the size of
+ // the structure has to be 32 bytes aligned
+
+typedef struct _EHCI_DESC_PTRS_
+{
+ EHCI_QH *fpQHControl;
+ EHCI_QTD *fpqTDControlSetup;
+ EHCI_QTD *fpqTDControlData;
+ EHCI_QTD *fpqTDControlStatus;
+ EHCI_QH *fpQHBulk;
+ EHCI_QTD *fpqTDBulkData;
+
+} EHCI_DESC_PTRS;
+
+typedef struct _PEI_EHCI_DEV
+{
+ UINTN Signature;
+ #define PEI_EHCI_DEV_SIGNATURE EFI_SIGNATURE_32( 'p', 'e', 'h', 'c' )
+ EFI_PEI_SERVICES **PeiServices;
+ PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi;
+ EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
+ EFI_PEI_CPU_IO_PPI *CpuIoPpi;
+ EFI_PEI_STALL_PPI *StallPpi;
+ EFI_PEI_PCI_CFG_PPI *PciCfgPpi;
+ UINT32 UsbHostControllerBaseAddress;
+ EHCI_HC_OPER_REG *EhciHcOpReg;
+ UINT8 bNumPorts;
+ UINT32 HcStatus;
+ EHCI_DESC_PTRS stEHCIDescPtrs;
+ UINT16 PortResetStatusChangeMap;
+ UINT16 HiSpeedDevicesMap;
+
+} PEI_EHCI_DEV;
+
+#pragma pack(pop)
+
+#define PEI_MAX_EHCI_DATA_SIZE 20 * 1024
+
+//----------------------------------------------------------------------------
+// Function prototypes
+//----------------------------------------------------------------------------
+
+
+
+EFI_STATUS InitializeUsbHC (
+ PEI_EHCI_DEV *UhcDev );
+
+VOID EhciInitHC (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_EHCI_DEV *pEhcDev );
+
+VOID EhciHcReset (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_EHCI_DEV *pEhcDev );
+
+
+VOID EhciHcEnableRootHub (
+ PEI_EHCI_DEV *EhciDevPtr,
+ UINT8 PortNumber );
+
+VOID EHCIWaitForAsyncTransferComplete (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_EHCI_DEV *EhciDevPtr,
+ EHCI_QH *QHead);
+
+EFI_STATUS EhciHcControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult );
+
+EFI_STATUS EhciHcBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT16 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult );
+
+EFI_STATUS EhciHcGetRootHubPortNumber (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *PortNumber );
+
+EFI_STATUS EhciHcGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus );
+
+EFI_STATUS EhciHcSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature );
+
+EFI_STATUS EhciHcClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature );
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/EhciPEI/EhciPeiBoard.c b/Core/EM/UsbRecovery/EhciPEI/EhciPeiBoard.c
new file mode 100644
index 0000000..a883ac2
--- /dev/null
+++ b/Core/EM/UsbRecovery/EhciPEI/EhciPeiBoard.c
@@ -0,0 +1,108 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/EhciPeiBoard.c 1 3/03/09 7:28p Olegi $
+//
+// $Revision: 1 $
+//
+// $Date: 3/03/09 7:28p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/EhciPeiBoard.c $
+//
+// 1 3/03/09 7:28p Olegi
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EhciPeiBoard.c
+//
+// Description: This file contains routines that are board specific for
+// initializing the EHCI controller in the USB Recovery module.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <PEI.h>
+#include <AmiPeiLib.h>
+#include <token.h>
+#include <PPI/PeiGetUCtrl.h>
+#include <PPI/OhciPPI.h>
+#include <PPI/stall.h>
+#include "EhciPei.h"
+
+
+//----------------------------------------------------------------------------
+// Porting Steps:
+//
+// 1) define/undefine the appropriate southbridge type
+// 2) define registers and their set/clear bits for each register to be
+// modified in each controller's PCI configuration space
+// 3) do not do any generic initialization - programming of BAR and command
+// register is done generically
+//
+//----------------------------------------------------------------------------
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: EhciPeiBoardInit
+//
+// Description:
+// This is a porting hook for board-specific EHCI controller
+// initialization
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices -
+// IN EFI_PEI_PCI_CFG_PPI *Pci -
+// IN EFI_PEI_STALL_PPI *StallPpi -
+//
+// Output:
+// VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EhciPeiBoardInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PCI_CFG_PPI *Pci,
+ IN EFI_PEI_STALL_PPI *StallPpi )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ return Status;
+
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/HubPeim.h b/Core/EM/UsbRecovery/HubPeim.h
new file mode 100644
index 0000000..7f0a114
--- /dev/null
+++ b/Core/EM/UsbRecovery/HubPeim.h
@@ -0,0 +1,317 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/HubPeim.h 4 11/24/12 5:42a Ryanchou $
+//
+// $Revision: 4 $
+//
+// $Date: 11/24/12 5:42a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/HubPeim.h $
+//
+// 4 11/24/12 5:42a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 3 1/18/11 12:55a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 2 7/10/08 6:33p Michaela
+// Updated to support OHCI controllers
+//
+// 1 9/22/06 4:06p Sivagarn
+// - Initial Check-in
+// - Included Recovery code in Source
+// - Included appropriate headers for flies and functions
+// - Updated copyright messages
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: HubPeim.H
+//
+// Description: This file belongs to "Framework" and included here for
+// compatibility purposes. This file is modified by AMI to include
+// copyright message, appropriate header and integration code
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//
+// This file contains 'Framework Code' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may not be modified, except as allowed by
+// additional terms of your license agreement.
+//
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ HubPeim.h
+
+ Abstract:
+
+ Constants definitions for Usb Hub Peim
+
+ Revision History
+
+ --*/
+
+#ifndef _PEI_HUB_PEIM_H
+#define _PEI_HUB_PEIM_H
+
+#include "Efi.h"
+#include "Pei.h"
+#include "usb.h"
+#include "usbpeim.h"
+
+#include "Ppi\UsbIo.h"
+//
+// Hub feature numbers
+//
+#define C_HUB_LOCAL_POWER 0
+#define C_HUB_OVER_CURRENT 1
+
+
+//
+// Hub class code & sub class code
+//
+#define CLASS_CODE_HUB 0x09
+#define SUB_CLASS_CODE_HUB 0
+
+//
+// Hub Status & Hub Change bit masks
+//
+#define HUB_STATUS_LOCAL_POWER 0x0001
+#define HUB_STATUS_OVERCURRENT 0x0002
+
+#define HUB_CHANGE_LOCAL_POWER 0x0001
+#define HUB_CHANGE_OVERCURRENT 0x0002
+
+//
+// Hub Characteristics
+//
+#define HUB_CHAR_LPSM 0x0003
+#define HUB_CHAR_COMPOUND 0x0004
+#define HUB_CHAR_OCPM 0x0018
+
+//
+// Hub specific request
+//
+#define HUB_CLEAR_FEATURE 0x01
+#define HUB_CLEAR_FEATURE_REQ_TYPE 0x20
+
+#define HUB_CLEAR_FEATURE_PORT 0x01
+#define HUB_CLEAR_FEATURE_PORT_REQ_TYPE 0x23
+
+#define HUB_GET_BUS_STATE 0x02
+#define HUB_GET_BUS_STATE_REQ_TYPE 0xa3
+
+#define HUB_GET_DESCRIPTOR 0x06
+#define HUB_GET_DESCRIPTOR_REQ_TYPE 0xa0
+
+#define HUB_GET_HUB_STATUS 0x00
+#define HUB_GET_HUB_STATUS_REQ_TYPE 0xa0
+
+#define HUB_GET_PORT_STATUS 0x00
+#define HUB_GET_PORT_STATUS_REQ_TYPE 0xa3
+
+#define HUB_SET_DESCRIPTOR 0x07
+#define HUB_SET_DESCRIPTOR_REQ_TYPE 0x20
+
+#define HUB_SET_HUB_FEATURE 0x03
+#define HUB_SET_HUB_FEATURE_REQ_TYPE 0x20
+
+#define HUB_SET_HUB_DEPTH 0x0C
+#define HUB_SET_HUB_DEPTH_REQ_TYPE 0x20
+
+#define HUB_SET_PORT_FEATURE 0x03
+#define HUB_SET_PORT_FEATURE_REQ_TYPE 0x23
+
+// Hub port status and port change status bits
+#define HUB_PORT_CONNECTION 0x0001
+#define HUB_PORT_ENABLE 0x0002
+#define HUB_PORT_SUSPEND 0x0004
+#define HUB_PORT_OVER_CURRENT 0x0008
+#define HUB_PORT_RESET 0x0010
+#define HUB_PORT_POWER 0x0100
+#define HUB_PORT_LOW_SPEED 0x0200
+#define HUB_PORT_HIGH_SPEED 0x0400
+#define HUB_PORT_TEST 0x0800
+#define HUB_PORT_INDICATOR 0x1000
+
+#define HUB_C_PORT_CONNECTION 0x0001
+#define HUB_C_PORT_ENABLE 0x0002
+#define HUB_C_PORT_SUSPEND 0x0004
+#define HUB_C_PORT_OVER_CURRENT 0x0008
+#define HUB_C_PORT_RESET 0x0010
+
+// Super speed hub definition
+#define SS_HUB_PORT_CONNECTION 0x0001
+#define SS_HUB_PORT_ENABLE 0x0002
+#define SS_HUB_PORT_OVER_CURRENT 0x0008
+#define SS_HUB_PORT_RESET 0x0010
+#define SS_HUB_PORT_LINK_STATE 0x01E0
+#define SS_HUB_PORT_POWER 0x0200
+#define SS_HUB_PORT_SPEED 0x1800
+
+#define SS_HUB_C_PORT_CONNECTION 0x0001
+#define SS_HUB_C_PORT_ENABLE 0x0002
+#define SS_HUB_C_PORT_SUSPEND 0x0004
+#define SS_HUB_C_PORT_OVER_CURRENT 0x0008
+#define SS_HUB_C_PORT_RESET 0x0010
+#define SS_HUB_C_BH_PORT_RESET 0x0020
+#define SS_HUB_C_PORT_LINK_STATE 0x0040
+#define SS_HUB_C_PORT_CONFIG_ERROR 0x0080
+
+#pragma pack(1)
+typedef struct usb_hub_status
+{
+ UINT16 HubStatus;
+ UINT16 HubChange;
+} EFI_USB_HUB_STATUS;
+
+typedef struct {
+ struct {
+ UINT16 Connected :1;
+ UINT16 Enabled :1;
+ UINT16 Reserved :1;
+ UINT16 OverCurrent :1;
+ UINT16 Reset :1;
+ UINT16 LinkState :4;
+ UINT16 Power :1;
+ UINT16 Speed :3;
+ UINT16 Reserved1 :3;
+ } PortStatus;
+ struct {
+ UINT16 ConnectChange :1;
+ UINT16 Reserved :2;
+ UINT16 OverCurrentChange :1;
+ UINT16 ResetChange :1;
+ UINT16 BhResetChange :1;
+ UINT16 LinkStateChange :1;
+ UINT16 ConfigErrorChange :1;
+ UINT16 Reserved1 :8;
+ } PortChange;
+} USB3_HUB_PORT_STATUS;
+
+#pragma pack()
+
+EFI_STATUS
+PeiHubGetPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ OUT UINT32 *PortStatus );
+
+EFI_STATUS
+PeiHubSetPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ IN UINT8 Value );
+
+EFI_STATUS
+PeiHubSetHubFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Value );
+
+EFI_STATUS
+PeiHubGetHubStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ OUT UINT32 *HubStatus );
+
+EFI_STATUS
+PeiHubClearPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ IN UINT8 Value );
+
+EFI_STATUS
+PeiHubClearHubFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Value );
+
+EFI_STATUS
+PeiSetHubDepth (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 HubDepth);
+
+EFI_STATUS
+PeiGetHubDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINTN DescriptorSize,
+ OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor );
+
+EFI_STATUS
+PeiDoHubConfig (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice );
+
+VOID
+PeiResetHubPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ UINT8 PortNum );
+
+#endif
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/UsbRecovery/OhciPEI/OhciPei.c b/Core/EM/UsbRecovery/OhciPEI/OhciPei.c
new file mode 100644
index 0000000..7ecb23d
--- /dev/null
+++ b/Core/EM/UsbRecovery/OhciPEI/OhciPei.c
@@ -0,0 +1,1455 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/OhciPei.c 12 11/24/12 5:44a Ryanchou $
+//
+// $Revision: 12 $
+//
+// $Date: 11/24/12 5:44a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/OhciPei.c $
+//
+// 12 11/24/12 5:44a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 11 8/23/12 9:59p Wilsonlee
+// [TAG] EIP97069
+// [Category] Improvement
+// [Description] Reset root port algorythm update.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// UhcPeim.h, UsbPeim.c, usb.h
+//
+// 10 1/18/11 12:59a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 9 10/11/10 4:51p Olegi
+// XHCI support added.
+//
+// 8 3/17/09 5:09p Olegi
+// Added TransactionTranslator for slow/full speed devices behind USB2
+// hub.
+//
+// 7 3/03/09 7:26p Olegi
+// MaximumPacketLength changed from UINT8 to UINT16.
+//
+// 6 10/21/08 5:57p Michaela
+// Added EHCI-related fixes for issues
+// that may occur if EHCI is used before
+// USB Recovery is invoked:
+// Added SDL Tokens:
+// PEI_EHCI_PCI_BDFS and
+// PEI_EHCI_MEM_BASE_ADDRESSES.
+//
+// Removed/modified some debugging
+// development code:
+// Removed SDL Tokens:
+// USBR_DEBUG_SUPPORT and
+// USBR_SERIAL_PORT_AVAILABLE
+// Removed Elinks:
+// UsbRecoveryDebug_DIR and
+// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+// Modified SDL Token:
+// FORCE_RECOVERY to default value of 0.
+//
+// (See this module's Help documentation
+// for more information.)
+//
+// 5 7/29/08 5:50p Michaela
+// 1) Updated code to move most porting tasks to SDL
+// 2) Added more debug break points and improved interactive
+// debugging capability for when a serial port is not available.
+// 3) Updated help files
+//
+// 4 7/18/08 5:04p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 3 7/10/08 6:36p Michaela
+// Updated to support OHCI controllers
+//
+// 2 9/22/06 12:23p Sivagarn
+// - Included appropriate headers for flies and functions
+// - Updated copyright messages
+// - Merged multiple MAK and SDL files into one MAK and SDL file
+// - Removed unnecessary files
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: OhciPei.c
+//
+// Description:
+// This file is the main source file for the OHCI PEI USB
+// recovery module. Its entry point at OhciPeiUsbEntryPoint
+// will be executed from the UsbRecoveryInitialize INIT_LIST.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <PEI.h>
+#include <AmiPeiLib.h>
+#include <token.h>
+#include <PPI\PeiGetUCtrl.h>
+#include <PPI\OhciPPI.h>
+#include <PPI\stall.h>
+#include "Ppi\UsbHostController.h"
+#include "OhciPei.h"
+#include "usb.h"
+
+// List of PCI addresses for OHCI controllers
+extern PCI_BUS_DEV_FUNCTION gOhciControllerPciTable[];
+extern UINT16 gOhciControllerCount;
+
+extern EFI_GUID gPeiStallPpiGuid;
+extern EFI_GUID gPeiUsbHostControllerPpiGuid;
+extern EFI_STATUS OhciPeiBoardInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ EFI_PEI_PCI_CFG_PPI *PciCfgPpi,
+ EFI_PEI_STALL_PPI *StallPpi );
+extern VOID ZeroMem (
+ OUT VOID *Buffer,
+ IN UINTN Size );
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciGetOperationalRegisterBase
+//
+// Description:
+// This function uses ControllerIndex and the global PCI_BUS_DEV_FUNCTION
+// array to access a particular controller's PCI configuration space in
+// order to obtain the Operational Register base address.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- PEI Sevices table pointer
+// IN UINT16 ControllerIndex
+// -- Index of the controller in the global
+// PCI_BUS_DEV_FUNCTION array
+//
+// Output:
+// UINT32 (Return Value)
+// = Base address for this controller's operational
+// registers.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32 OhciGetOperationalRegisterBase (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT16 ControllerIndex )
+{
+ UINT32 OhciBaseAddress;
+
+ (*PeiServices)->PciCfg->Read(
+ PeiServices,
+ (*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint32,
+ OHCI_PCI_ADDRESS( ControllerIndex, OHCI_BASE_ADDR_REG ),
+ &OhciBaseAddress
+ );
+
+
+ return OhciBaseAddress &= 0xfffffff0; // Mask lower bits
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciPeiUsbEntryPoint
+//
+// Description:
+// This is the entry point into the OHCI controller initialization
+// subsystem.
+//
+// Input:
+// IN EFI_FFS_FILE_HEADER *FfsHeader
+// -- EFI_FFS_FILE_HEADER pointer
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS OhciPeiUsbEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ UINT8 Index;
+ UINTN MemPages;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ PEI_OHCI_DEV *OhciDevPtr;
+ EFI_PEI_STALL_PPI *StallPpi;
+
+ //-------------------------------------------
+ // Initialize the EFI_PEI_STALL_PPI interface
+ //-------------------------------------------
+ Status = (**PeiServices).LocatePpi( PeiServices, &gPeiStallPpiGuid,
+ 0, NULL, &StallPpi );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //-----------------------------------------
+ // board specific initialization to program
+ // PCI bridges and enable MMIO
+ //-----------------------------------------
+
+ Status = OhciPeiBoardInit(
+ PeiServices,
+ (*PeiServices)->PciCfg,
+ StallPpi );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //----------------------------------------------------------
+ // Allocate OHCI DEVICE OBJECT that holds all necessary
+ // information for the Host Controller operational registers
+ // for each controller. Initialze the controller and setup
+ // data structures for ready for operation
+ //----------------------------------------------------------
+
+ for (Index = 0; Index < gOhciControllerCount; Index++)
+ {
+
+ // PAGESIZE = 0x1000
+ MemPages = sizeof (PEI_OHCI_DEV) / 0x1000 + 1;
+ Status = (**PeiServices).AllocatePages(
+ PeiServices,
+ EfiConventionalMemory,
+ MemPages,
+ &TempPtr
+ );
+ if ( EFI_ERROR( Status ) )
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ OhciDevPtr = (PEI_OHCI_DEV *) ( (UINTN) TempPtr );
+ OhciDevPtr->Signature = PEI_OHCI_DEV_SIGNATURE;
+ OhciDevPtr->PeiServices = PeiServices;
+ OhciDevPtr->CpuIoPpi = (*PeiServices)->CpuIo;
+ OhciDevPtr->StallPpi = StallPpi;
+ OhciDevPtr->PciCfgPpi = (*PeiServices)->PciCfg;
+ ;
+ OhciDevPtr->UsbHostControllerBaseAddress =
+ OhciGetOperationalRegisterBase( PeiServices, Index );
+
+ //Initialize the OHCI Controller for operation
+
+ OhciInitHC( PeiServices, OhciDevPtr, Index ); // 0xff03
+
+ //Setup PPI entry point
+ OhciDevPtr->UsbHostControllerPpi.ControlTransfer =
+ OhciHcControlTransfer;
+ OhciDevPtr->UsbHostControllerPpi.BulkTransfer =
+ OhciHcBulkTransfer;
+ OhciDevPtr->UsbHostControllerPpi.GetRootHubPortNumber =
+ OhciHcGetRootHubPortNumber;
+ OhciDevPtr->UsbHostControllerPpi.GetRootHubPortStatus =
+ OhciHcGetRootHubPortStatus;
+ OhciDevPtr->UsbHostControllerPpi.SetRootHubPortFeature =
+ OhciHcSetRootHubPortFeature;
+ OhciDevPtr->UsbHostControllerPpi.ClearRootHubPortFeature =
+ OhciHcClearRootHubPortFeature;
+ OhciDevPtr->UsbHostControllerPpi.PreConfigureDevice = NULL;
+ OhciDevPtr->UsbHostControllerPpi.EnableEndpoints = NULL;
+
+ OhciDevPtr->PpiDescriptor.Flags =
+ (EFI_PEI_PPI_DESCRIPTOR_PPI |
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ OhciDevPtr->PpiDescriptor.Guid = &gPeiUsbHostControllerPpiGuid;
+ OhciDevPtr->PpiDescriptor.Ppi = &OhciDevPtr->UsbHostControllerPpi;
+
+ //Now is the time to install the PPI
+ Status = (**PeiServices).InstallPpi(
+ PeiServices, &OhciDevPtr->PpiDescriptor );
+ if ( EFI_ERROR( Status ) )
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciInitHcca
+//
+// Description:
+// This routine allocates memory for the the Host Controller
+// Communications Area (HCCA), aligned on a 256 byte boundary,
+// and updates the HcHcca operational register pointer, as
+// well as the corresponding PEI_OHCI_DEV.pFrameList
+// pointer.
+//
+// Input:
+// IN PEI_OHCI_DEV *OhciDevPtr
+// -- This is a pointer to a PEI_OHCI_DEV structure
+// for an OHCI controller.
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS OhciInitHcca (
+ IN PEI_OHCI_DEV *OhciDevPtr )
+{
+ OHCI_HC_REGISTERS *OhciHcReg =
+ (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress;
+
+ // Allocate 256 byte aligned Communication Channel area
+ // to the PEI_OHCI_DEV.pFrameList pointer.
+ ABORT_ON_ERROR(
+ (*OhciDevPtr->PeiServices)->AllocatePages(
+ OhciDevPtr->PeiServices,
+ EfiConventionalMemory,
+ (UINTN) (256 / 0x1000) + 1,
+ (EFI_PHYSICAL_ADDRESS *) &OhciDevPtr->pFrameList )
+ );
+
+ // Zero the memory and update the HcHCCA Host Controller
+ // Operational Register.
+ ZeroMem((VOID*)OhciDevPtr->pFrameList, sizeof(HC_HCCA));
+ OhciHcReg->HcHcca = (HC_HCCA*) OhciDevPtr->pFrameList;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciInitHC
+//
+// Description: All leading whitespace on this line is removed by Helpbuilder
+// Description of this function can be block aligned in this section.
+// The first tab that Helpbuilder will recognize will be at tab stop 21,
+// which will indent 4 spaces in Helpbuilder.
+//
+// This text is indented 4 spaces in Helpbuilder
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_OHCI_DEV *OhciDevPtr
+// -- PEI_OHCI_DEV pointer
+// IN UINT8 Index
+// -- Index of this controller in the global
+// PCI_BUS_DEV_FUNCTION array
+//
+// Output:
+// VOID (Return Value)
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID OhciInitHC (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_OHCI_DEV *OhciDevPtr,
+ IN UINT8 Index )
+{
+ UINT8 bPortNum;
+ UINT8 *pPtr;
+ UINTN MemPages;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ EFI_PEI_PCI_CFG_PPI *PciCfgPpi = OhciDevPtr->PciCfgPpi;
+ POHCI_DESC_PTRS pstOHCIDescPtrs = &(OhciDevPtr->stOHCIDescPtrs);
+ OHCI_HC_REGISTERS *OhciHcReg =
+ (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress;
+
+ OhciDevPtr->wAsyncListSize = 0; // not used
+ OhciDevPtr->dMaxBulkDataSize = MAX_OHCI_BULK_DATA_SIZE;
+ //OhciDevPtr->wEndp0MaxPacket = 0x40;
+ //OhciDevPtr->bEndpointSpeed = USBSPEED_FULL;
+
+
+ // Do a Host Controller reset first
+ OhciHcReset( PeiServices, OhciDevPtr );
+
+
+ //-----------------------------------------------------------------
+ // Allocate and initialize the Host Controller Communication
+ // area aligned on a 256 byte boundary.
+ //
+ // This is needed only to poll the HccaDoneHead register
+ // in the HCCA, as the periodic list is not implemented.
+ //-----------------------------------------------------------------
+
+ // Store number of downstream ports into PEI_OHCI_DEV struct
+ OhciDevPtr->bNumPorts =
+ OhciHcReg->HcRhDescriptorA.Field.NumberDownstreamPorts;
+
+ // Program root hub characteristics:
+ OhciHcReg->HcRhDescriptorA.AllBits =
+ (NO_OVERCURRENT_PROTECTION | // No over current protection
+ POWERED_INDIVIDUALLY | // Ports powered individually
+ POWER_SWITCHED); // Ports individually power switched
+ OhciHcReg->HcRhDescriptorB.AllBits =
+ (ALL_REMOVEABLE | // All devices are removbale
+ ALL_PER_PORT_POWER_SWITCHED); // Power control is per-port
+
+ OhciHcReg->HcRhStatus.Field.LocalPowerStatusChange =
+ SET_GLOBAL_POWER; // Turn on power to all ports
+
+ // Initialize the frame interval register
+ OhciHcReg->HcFmInterval.Field.FrameInterval =
+ FM_INTERVAL_DEFAULT; // Between Start of Frames (SOFs)
+ OhciHcReg->HcFmInterval.Field.FsLargestDataPacket =
+ FS_LARGEST_PACKET_DEFAULT; // Largest for single transaction
+
+ // Enable the host controller list processing (Bulk/Control only)
+ OhciHcReg->HcControl.Field.BulkListEnable = TRUE;
+ OhciHcReg->HcControl.Field.ControlListEnable = TRUE;
+
+ // Set the operational bit in the host controller so that power
+ // can be applied to the ports.
+ OhciHcReg->HcControl.Field.HostControllerFunctionalState =
+ SET_USB_OPERATIONAL;
+
+ // Enable all the ports.
+ for ( bPortNum = 0; bPortNum < OhciDevPtr->bNumPorts; bPortNum++ ) {
+ OhciHcReg->HcRhPortStatus[bPortNum].AllBits = SET_PORT_POWER;
+ }
+
+ // Allocate a block of memory and define/initialize
+ // Setup Control and Bulk EDs/TDs
+ pstOHCIDescPtrs = &(OhciDevPtr->stOHCIDescPtrs);
+
+ MemPages = ( 3 *
+ sizeof (OHCI_ED) ) + ( 5 * sizeof(OHCI_TD) ) / 0x1000 + 1;
+ Status = (**PeiServices).AllocatePages(
+ PeiServices,
+ EfiConventionalMemory,
+ MemPages,
+ &TempPtr
+ );
+
+ pPtr = (UINT8 *) ( (UINTN) TempPtr );
+ MemSet( pPtr, 3 * sizeof (OHCI_ED) + 5 * sizeof(OHCI_TD), 0 );
+ if (!pPtr) {
+ return;
+ }
+ pstOHCIDescPtrs->pstEDControl = (POHCI_ED) pPtr;
+ pPtr += sizeof (OHCI_ED); //This should be okay
+ pstOHCIDescPtrs->pstTDControlSetup = (POHCI_TD) pPtr;
+ pPtr += sizeof (OHCI_TD);
+ pstOHCIDescPtrs->pstTDControlData = (POHCI_TD) pPtr;
+ pPtr += sizeof (OHCI_TD);
+ pstOHCIDescPtrs->pstTDControlStatus = (POHCI_TD) pPtr;
+ pPtr += sizeof (OHCI_TD);
+ pstOHCIDescPtrs->pstEDBulk = (POHCI_ED) pPtr;
+ pPtr += sizeof (OHCI_ED);
+ pstOHCIDescPtrs->pstTDBulkData = (POHCI_TD) pPtr;
+ pPtr += sizeof (OHCI_TD);
+ pstOHCIDescPtrs->pstEDInterrupt = (POHCI_ED) pPtr;
+ pPtr += sizeof (OHCI_ED);
+ pstOHCIDescPtrs->pstTDInterruptData = (POHCI_TD) pPtr;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciHcReset
+//
+// Description:
+// This function performs a software reset of the host controller.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_OHCI_DEV *OhciDevPtr
+// -- PEI_OHCI_DEV pointer
+//
+// Output:
+// VOID (Return Value)
+//
+// Notes:
+// It is assumed that all necessary operational register data has been
+// saved prior to calling this function.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID OhciHcReset (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_OHCI_DEV *OhciDevPtr )
+{
+ OHCI_HC_REGISTERS *OhciHcReg =
+ (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress;
+
+ // Initiate a software reset
+ OhciHcReg->HcCommandStatus.AllBits = SET_CONTROLLER_RESET;
+
+ //Wait for 2ms
+ OHCI_FIXED_DELAY_MS( OhciDevPtr, 2);
+
+ //Do USBRESET to reset roothub and downstream port
+ OhciHcReg->HcControl.Field.HostControllerFunctionalState = SET_USB_RESET;
+
+ //wait for 10ms
+ OHCI_FIXED_DELAY_MS( OhciDevPtr, 10);
+
+ // Note: HcInterruptStatus.Field.RootHubStatusChange bit should
+ // now be set if any devices are connected to a port
+ // on this controller.
+
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciHcGetRootHubPortStatus
+//
+// Description:
+// This function obtains the port status and port change status for
+// a port specified by PortNumber and updates the EFI_USB_PORT_STATUS
+// data structure as specified the the PortStatus pointer parameter.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 PortNumber
+// -- Port number for which status is requested
+// OUT EFI_USB_PORT_STATUS *PortStatus
+// -- EFI_USB_PORT_STATUS pointer's data is updated
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS OhciHcGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus )
+{
+ PEI_OHCI_DEV *OhciDevPtr =
+ PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This );
+ HC_RH_PORT_STATUS HcPortStatus;
+
+ HcPortStatus = ( (OHCI_HC_REGISTERS *)
+ OhciDevPtr->UsbHostControllerBaseAddress )->
+ HcRhPortStatus[PortNumber - 1];
+
+ PortStatus->PortStatus = 0;
+ PortStatus->PortChangeStatus = 0;
+
+ if (HcPortStatus.Field.CurrentConnectStatus) {
+ PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+ if (HcPortStatus.Field.PortEnableStatus) {
+ PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
+ }
+ if (HcPortStatus.Field.PortSuspendStatus) {
+ PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+ if (HcPortStatus.Field.PortResetStatus) {
+ PortStatus->PortStatus |= USB_PORT_STAT_RESET;
+ }
+ if (HcPortStatus.Field.LowSpeedDeviceAttached) {
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+ }
+ if (HcPortStatus.Field.ConnectStatusChange) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+ if (HcPortStatus.Field.PortEnableStatusChange) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
+ }
+ if (HcPortStatus.Field.CurrentConnectStatus) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciHcGetRootHubPortNumber
+//
+// Description:
+// This function returns the number of downstream ports as specified
+// in the HcRhDescriptorA operational register.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// OUT UINT8 *PortNumber
+// -- Number of downstream ports
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS OhciHcGetRootHubPortNumber (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *PortNumber )
+{
+
+ PEI_OHCI_DEV *OhciDevPtr = PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This );
+ OHCI_HC_REGISTERS *OhciHcReg =
+ (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress;
+
+ if (PortNumber == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *PortNumber = OhciHcReg->HcRhDescriptorA.Field.NumberDownstreamPorts;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciHcSetRootHubPortFeature
+//
+// Description:
+// This function sets an OHCI specification port feature as specified by
+// PortFeature for the port specified by PortNumber.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 PortNumber
+// -- Port number whose feature is to be set
+// IN EFI_USB_PORT_FEATURE PortFeature
+// -- Feature to set
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS OhciHcSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature )
+{
+ PEI_OHCI_DEV *OhciDevPtr =
+ PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This );
+ OHCI_HC_REGISTERS *OhciHcReg =
+ (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress;
+
+ if (PortNumber > OhciHcReg->HcRhDescriptorA.Field.NumberDownstreamPorts){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (PortFeature)
+ {
+
+ case EfiUsbPortSuspend:
+ OhciHcReg->HcRhPortStatus[PortNumber - 1].AllBits = SET_PORT_SUSPEND;
+ break;
+
+ case EfiUsbPortReset:
+ OhciHcReg->HcRhPortStatus[PortNumber - 1].AllBits = SET_PORT_RESET;
+ break;
+
+ case EfiUsbPortPower:
+ break;
+
+ case EfiUsbPortEnable:
+ OhciHcReg->HcRhPortStatus[PortNumber - 1].AllBits = SET_PORT_ENABLE;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciHcClearRootHubPortFeature
+//
+// Description:
+// This function clears an OHCI specification port feature as specified
+// by PortFeature for the port specified by PortNumber.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 PortNumber
+// -- Port number whose feature is to be set
+// IN EFI_USB_PORT_FEATURE PortFeature
+// -- Feature to set
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS OhciHcClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature )
+{
+ PEI_OHCI_DEV *OhciDevPtr =
+ PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This );
+ OHCI_HC_REGISTERS *OhciHcReg =
+ (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress;
+ HC_RH_PORT_STATUS *Pstatus;
+
+ if (PortNumber > OhciHcReg->HcRhDescriptorA.Field.NumberDownstreamPorts){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Pstatus = &OhciHcReg->HcRhPortStatus[PortNumber - 1];
+
+ switch (PortFeature)
+ {
+ // clear PORT_ENABLE feature means disable port.
+ // This is accomplished by writing a 1 to the CurrentConnectStatus
+ // field.
+ case EfiUsbPortEnable:
+ Pstatus->AllBits = CLEAR_PORT_ENABLE;
+ break;
+
+ // clear PORT_SUSPEND feature means resume the port.
+ // (cause a resume on the specified port if in suspend mode)
+ // This is accomplished by writing a 1 to the PortOverCurrentIndicator
+ // field.
+ case EfiUsbPortSuspend:
+ Pstatus->AllBits = CLEAR_SUSPEND_STATUS;
+ break;
+
+ case EfiUsbPortPower:
+ break;
+
+
+ // clear PORT_RESET means clear the reset signal.
+ // This is accomplished by writing a 1 to the PortResetStatusChange
+ // field. No assumption is made that the appropriate delay
+ // was implemented.
+ case EfiUsbPortReset:
+
+ break;
+
+ // clear connect status change by writing
+ // a 1 to the ConnectStatusChange field
+ case EfiUsbPortConnectChange:
+ Pstatus->AllBits = CLEAR_CONNECT_STATUS_CHANGE;
+ break;
+
+ // clear enable/disable status change by writing
+ // a 1 to the PortEnableStatusChange field
+ case EfiUsbPortEnableChange:
+ Pstatus->AllBits = CLEAR_PORT_ENABLE_STATUS_CHANGE;
+ break;
+
+ // root hub does not support these requests
+ case EfiUsbPortSuspendChange:
+ case EfiUsbPortOverCurrentChange:
+ case EfiUsbPortResetChange:
+ Pstatus->AllBits = CLEAR_PORT_RESET_STATUS_CHANGE;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciHcControlTransfer
+//
+// Description:
+// This function intiates a USB control transfer and waits on it to
+// complete.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 bDeviceAddress
+// -- USB address of the device for which the control
+// transfer is to be issued
+// IN UINT8 DeviceType
+// -- Not used
+// IN UINT8 MaximumPacketLength
+// -- Maximum number of bytes that can be sent to or
+// received from the endpoint in a single data packet
+// IN EFI_USB_DEVICE_REQUEST *Request
+// -- EFI_USB_DEVICE_REQUEST pointer
+// IN EFI_USB_DATA_DIRECTION TransferDirection
+// -- Direction of transfer
+// OPTIONAL IN OUT VOID *DataBuffer
+// -- Pointer to source or destination buffer
+// OPTIONAL IN OUT UINTN *DataLength
+// -- Length of buffer
+// IN UINTN TimeOut
+// -- Not used
+// OUT UINT32 *TransferResult
+// -- Not used
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+typedef struct _D_REQUEST
+{
+ UINT8 RequestType;
+ UINT8 Request;
+ UINT16 Value;
+ UINT16 Index;
+ UINT16 Length;
+} D_REQUEST;
+
+EFI_STATUS OhciHcControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 bDeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *DataBuffer OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult )
+{
+ UINT16 *fpData;
+ POHCI_ED fpED;
+ POHCI_TD fpTD;
+ UINT32 DwordData;
+ UINT16 WordData;
+ UINT16 WordRequest;
+ UINT16 WordIndex;
+ UINT16 WordValue;
+ EFI_STATUS Status = EFI_SUCCESS;
+ PEI_OHCI_DEV *OhciDevPtr =
+ PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This );
+ POHCI_DESC_PTRS fpDescPtrs =
+ &(OhciDevPtr->stOHCIDescPtrs);
+ OHCI_HC_REGISTERS *HcReg =
+ (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress;
+
+ // 5 ms delay is necessary for OHCI host controllers
+ OHCI_FIXED_DELAY_MS( OhciDevPtr, 5 );
+
+ WordRequest = (Request->Request << 8) | Request->RequestType;
+ WordValue = Request->Value;
+ WordIndex = Request->Index;
+
+ //
+ // Build the device request in the data area of the control setup qTD
+ //
+ fpData = (UINT16 *) fpDescPtrs->pstTDControlSetup->aSetupData;
+ *fpData++ = WordRequest;
+ *fpData++ = WordValue;
+ *fpData++ = WordIndex;
+ *fpData++ = (UINT16) *DataLength;
+ *(UINT32 *) fpData = (UINT32) DataBuffer;
+
+ //
+ // Prepare some registers that will be used in building the TDs below.
+ // wLength contains the data length.
+ // fpBuffer contains the absolute address of the data buffer.
+ // WordRequest contains the request type (bit 7 = 0/1 for Out/In).
+ // fpDevInfo will contain a pointer to the DeviceInfo structure for
+ // the given device.
+ //
+ // Ready the EDControl for the control transfer.
+ //
+ fpED = fpDescPtrs->pstEDControl;
+ //
+ // The ED control field will be set so
+ // Function address & Endpoint number = ESI,
+ // Direction = From TD,
+ // Speed = DeviceInfo.bEndpointSpeed,
+ // Skip = 1, Format = 0,
+ // Max packet size = DeviceInfo.wEndp0MaxPacket
+ // The HeadPointer field will be set to TDControlSetup
+ // The TailPointer field will be set to OHCI_TERMINATE
+ // The LinkPointer field will be set to OHCI_TERMINATE
+ //
+
+ // if wEndp0MaxPacket is NULL, then use default
+ // packet size
+ DwordData = MaximumPacketLength;
+
+ // Force the max packet size to 64 bytes
+ if (DwordData > 0x40 || DwordData == 0) {
+ DwordData = 0x40;
+ }
+ DwordData <<= 16; // DwordData[26:16] = device's packet size
+ WordData = (UINT16) DeviceSpeed; // 00/01/10 for HI/LO/FULL
+ WordData = (WordData & 1) << 13; // WordData[13] = full/low speed flag
+ WordData |= bDeviceAddress | ED_SKIP_TDQ;
+ fpED->dControl = DwordData | WordData;
+ fpED->fpTailPointer = 0;
+ fpED->fpEDLinkPointer = 0;
+
+ fpTD = fpDescPtrs->pstTDControlSetup;
+ //
+ // The ControlStatus field will be set so
+ // Buffer Rounding = 1,
+ // Direction PID = GTD_SETUP_PACKET,
+ // Delay Interrupt = GTD_INTD,
+ // Data Toggle = GTD_SETUP_TOGGLE,
+ // Error Count = GTD_NO_ERRORS,
+ // Condition Code = GTD_NOT_ACCESSED
+ // The CurrentBufferPointer field will point to the TD's SetupData buffer
+ // which was before initialized to contain a DeviceRequest struc.
+ // The BufferEnd field will point to the last byte of the TD's SetupData
+ // buffer.
+ // The LinkPointer field will point to the TDControlData if data will
+ // be sent/received or to the TDControlStatus if no data is expected.
+ // The CSReloadValue field will contain 0 because this is a "one shot"
+ // packet.
+ // The pCallback will be set to point to the OHCI_ControlTDCallback
+ // routine.
+ // The ActiveFlag field will be set to TRUE.
+ // The DeviceAddress field does not need to be set since the Control TDs
+ // do not need rebinding to the EDControl.
+ //
+ fpTD->dControlStatus = (UINT32) ( GTD_BUFFER_ROUNDING |
+ GTD_SETUP_PACKET | GTD_SETUP_TOGGLE |
+ GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28) );
+
+ fpTD->fpCurrentBufferPointer = fpTD->aSetupData;
+ fpTD->fpBufferEnd = fpTD->aSetupData + 7; // size of aSetupData - 1
+
+ if (*DataLength) { // some data to transfer
+
+ // Fill in various fields in the TDControlData.
+ fpTD = fpDescPtrs->pstTDControlData;
+ //
+ // The ControlStatus field will be set so
+ // Buffer Rounding = 1,
+ // Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET,
+ // Delay Interrupt = GTD_INTD,
+ // Data Toggle = GTD_DATA1_TOGGLE,
+ // Error Count = GTD_NO_ERRORS,
+ // Condition Code = GTD_NOT_ACCESSED
+ // The CurrentBufferPointer field will point to the caller's buffer
+ // which is now in EBP.
+ // The BufferEnd field will point to the last byte of the caller's
+ // buffer.
+ // The LinkPointer field will point to the TDControlStatus.
+ // The CSReloadValue field will contain 0 because this is a
+ // "one shot" packet.
+ // The pCallback will be set to point to the OHCI_ControlTDCallback
+ // routine.
+ // The ActiveFlag field will be set to TRUE.
+ // The DeviceAddress field does not need to be set since the Control
+ // TDs do not need rebinding to the EDControl.
+ // The CSReloadValue field will contain 0 because this is a
+ // "one shot" packet.
+ // The pCallback will be set to point to the OHCI_ControlTDCallback
+ // routine.
+ // The ActiveFlag field will be set to TRUE. return USB_SUCCESS;
+ // The DeviceAddress field does not need to be set since the Control
+ // TDs do not need rebinding to the EDControl.
+ //
+ DwordData = (UINT32) ( GTD_BUFFER_ROUNDING | GTD_DATA1_TOGGLE
+ | GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28) );
+ DwordData = (WordRequest & BIT7)
+ ? (DwordData | GTD_IN_PACKET | GTD_INTD)
+ : (DwordData | GTD_OUT_PACKET);
+ fpTD->dControlStatus = DwordData;
+ fpTD->fpCurrentBufferPointer = (UINT8 *) DataBuffer;
+
+ WordData = (*DataLength < MAX_CONTROL_DATA_SIZE)
+ ? *DataLength
+ : MAX_CONTROL_DATA_SIZE;
+ fpTD->fpBufferEnd = (UINT8 *) DataBuffer + WordData - 1;
+ }
+
+ // Fill in various fields in the TDControlStatus.
+ fpTD = fpDescPtrs->pstTDControlStatus;
+ //
+ // The ControlStaus field will be set so
+ // Buffer Rounding = 1,
+ // Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET,
+ // Delay Interrupt = GTD_INTD,
+ // Data Toggle = GTD_DATA1_TOGGLE,
+ // Error Count = GTD_NO_ERRORS,
+ // Condition Code = GTD_NOT_ACCESSED
+ // The CurrentBufferPointer field will point to NULL
+ // The BufferEnd field will point to NULL.
+ // The LinkPointer field will point to OHCI_TERMINATE.
+ // The CSReloadValue field will contain 0 because this is a
+ // "one shot" packet.
+ // The pCallback will be set to point to the OHCI_ControlTdCallback
+ // routine.
+ // The ActiveFlag field will be set to TRUE.
+ // The DeviceAddress field does not need to be set since the Control
+ // TDs do not need rebinding to the EdControl.
+ //
+ // Note: For OUT control transfer status should be IN and
+ // for IN cotrol transfer, status should be OUT.
+ //
+ DwordData = (UINT32) ( GTD_BUFFER_ROUNDING | GTD_DATA1_TOGGLE
+ | GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28) );
+ DwordData = (WordRequest & BIT7)
+ ? (DwordData | GTD_OUT_PACKET)
+ : (DwordData | GTD_IN_PACKET | GTD_INTD);
+ fpTD->dControlStatus = DwordData;
+ fpTD->fpCurrentBufferPointer = NULL;
+ fpTD->fpBufferEnd = NULL;
+ fpTD->fpLinkPointer = NULL;
+
+ //
+ // Link all the pointers together
+ //
+ fpTD = fpDescPtrs->pstTDControlSetup;
+ fpED->fpHeadPointer = fpTD;
+ if (*DataLength) { // chain in data TD
+ fpTD->fpLinkPointer = (UINT8 *) fpDescPtrs->pstTDControlData;
+ fpTD = fpDescPtrs->pstTDControlData;
+ }
+ fpTD->fpLinkPointer = (UINT8 *) fpDescPtrs->pstTDControlStatus;
+
+ fpDescPtrs->pstTDControlStatus->fpLinkPointer = NULL;
+
+ fpTD = fpDescPtrs->pstTDControlSetup;
+ do {
+ fpTD->dCSReloadValue = 0;
+ fpTD->bActiveFlag = TRUE;
+ fpTD = (POHCI_TD) fpTD->fpLinkPointer;
+ } while (fpTD);
+
+ // clear the WriteBackDoneHead status bit in
+ // the HcInterruptStatus register
+ HcReg->HcInterruptStatus.Field.WriteBackDoneHead = HCINT_STATUS_CLEAR;
+
+ //
+ // Now control queue is complete, so set ED_SKIP_TDQ=0
+ //
+ fpED->dControl &= ~ED_SKIP_TDQ;
+ //
+ // Set the HcControlHeadED register to point to the EDControl.
+ //
+ HcReg->HcControlHeadEd = (UINTN) fpED;
+
+ //
+ // Now put the control setup, data and status into the HC's schedule by
+ // setting the ControllListFilled field of HcCommandStatus reg.
+ // This will cause the HC to execute the transaction in the next
+ // active frame.
+ //
+ HcReg->HcCommandStatus.AllBits = SET_CONTROL_LIST_FILLED;
+
+ //
+ // Now wait for the control status TD to complete. When it has completed,
+ // the OHCI_ControlTDCallback will set its active flag to FALSE.
+ Status = OhciHcWaitForTransferComplete( PeiServices, OhciDevPtr,
+ fpDescPtrs->pstTDControlStatus );
+
+ //
+ // Stop the HC from processing the EDControl by setting its Skip bit.
+ //
+ fpED->dControl |= ED_SKIP_TDQ;
+
+ //
+ // Finally check for any error bits set in both the TDControlStatus.
+ // If the TD did not complete successfully, return STC.
+ //
+
+ // DwordData[3:0] = Completion status
+ DwordData = fpDescPtrs->pstTDControlStatus->dControlStatus >> 28;
+
+ return ( (UINT8) DwordData == 0 ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+ //TODO: CHange the return status more meaningfull
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciHcBulkTransfer
+//
+// Description:
+// This function intiates a USB bulk transfer and waits on it to
+// complete.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 DeviceAddress
+// -- USB address of the device for which the control
+// transfer is to be issued
+// IN UINT8 EndPointAddress
+// -- Particular endpoint for the device
+// IN UINT8 MaximumPacketLength
+// -- Maximum number of bytes that can be sent to or
+// received from the endpoint in a single data packet
+// OPTIONAL IN OUT VOID *DataBuffer
+// -- Pointer to source or destination buffer
+// OPTIONAL IN OUT UINTN *DataLength
+// -- Length of buffer
+// IN OUT UINT8 *DataToggle
+// -- Used to update the control/status DataToggle field
+// of the Transfer Descriptor
+// IN UINTN TimeOut
+// -- Not used
+// OUT UINT32 *TransferResult
+// -- Not used
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS OhciHcBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT16 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN OUT VOID *DataBuffer,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult )
+{
+ UINT32 DwordData;
+ UINT8 ByteData;
+ UINT16 wMaxPkt;
+ EFI_STATUS Status;
+ UINT8 bEndp;
+ UINT8 Toggle;
+ PEI_OHCI_DEV *OhciDevPtr =
+ PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This );
+ POHCI_DESC_PTRS fpDescPtrs = &(OhciDevPtr->stOHCIDescPtrs);
+ OHCI_HC_REGISTERS *HcReg =
+ (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress;
+
+ wMaxPkt = MaximumPacketLength;
+
+ if (wMaxPkt == 0) {
+ *DataLength = 0;
+ return EFI_NOT_FOUND;
+ }
+
+ //Clear Bulk ED and TD
+ MemSet( fpDescPtrs->pstEDBulk, sizeof(OHCI_ED), 0 );
+ MemSet( fpDescPtrs->pstTDBulkData, sizeof(OHCI_TD), 0 );
+ //
+ // Set the SKIP bit in the EdBulk to avoid accidental scheduling
+ //
+ fpDescPtrs->pstEDBulk->dControl = ED_SKIP_TDQ;
+ //
+ // Set the ED's head pointer field to bulk data TD and tail pointer
+ // field to OHCI_TERMINATE. Also set ED's link pointer to
+ // OHCI_TERMINATE.
+ //
+ fpDescPtrs->pstEDBulk->fpHeadPointer = fpDescPtrs->pstTDBulkData;
+ fpDescPtrs->pstEDBulk->fpTailPointer = OHCI_TERMINATE;
+ fpDescPtrs->pstEDBulk->fpEDLinkPointer = OHCI_TERMINATE;
+ //
+ // Form the data needed for ED's control field with the available
+ // information
+ //
+ bEndp = EndPointAddress & 0x7f;
+ DwordData = (EndPointAddress & 0x80) ? ED_IN_PACKET : ED_OUT_PACKET;
+ DwordData |= DeviceAddress;
+ DwordData |= (UINT16) bEndp << 7;
+ DwordData |= (UINT32) wMaxPkt << 16;
+
+ //
+ // Update the ED's control field with the data formed
+ // ASSUME ALL MASS DEVICES ARE FULL SPEED DEVICES.
+ //
+ fpDescPtrs->pstEDBulk->dControl = DwordData;
+ //
+ // Fill the general bulk data TD with relevant information. Set the
+ // TD's control field with buffer rounding set to 1, direction PID to
+ // don't care, delay interrupt to INTD, data toggle to the latest data
+ // toggle value, error count to no errors and condition code to not
+ // accessed.
+ //
+ // Set the data toggle to DATA0 (SETUP_TOGGLE)
+ fpDescPtrs->pstTDBulkData->dControlStatus = (UINT32) (
+ GTD_BUFFER_ROUNDING |
+ GTD_IN_PACKET |
+ GTD_INTD |
+ GTD_SETUP_TOGGLE |
+ GTD_NO_ERRORS |
+ (GTD_NOT_ACCESSED << 28)
+ );
+ fpDescPtrs->pstTDBulkData->dControlStatus |= (UINT32) *DataToggle << 24;
+
+ //
+ // GTD current buffer pointer field will point to the caller's buffer which
+ // now in the variable fpBuffer
+ //
+ fpDescPtrs->pstTDBulkData->fpCurrentBufferPointer = (UINT8 *) DataBuffer;
+ fpDescPtrs->pstTDBulkData->fpBufferEnd = (UINT8 *) DataBuffer +
+ *DataLength - 1;
+ fpDescPtrs->pstTDBulkData->fpLinkPointer = OHCI_TERMINATE;
+ //
+ // GTD's CSReloadValue field will contain 0 because this is a
+ // "one shot" packet
+ //
+ fpDescPtrs->pstTDBulkData->dCSReloadValue = 0;
+ fpDescPtrs->pstTDBulkData->bActiveFlag = TRUE;
+
+ // Set the HCBulkHeadED register to point to the bulk ED
+ fpDescPtrs->pstEDBulk->dControl &= ~ED_SKIP_TDQ;
+ HcReg->HcBulkHeadEd = (UINT32) fpDescPtrs->pstEDBulk;
+
+ // Enable the bulk list processing
+ HcReg->HcCommandStatus.AllBits = SET_BULK_LIST_FILLED;
+
+ Status = OhciHcWaitForTransferComplete( PeiServices, OhciDevPtr,
+ fpDescPtrs->pstTDBulkData );
+ //
+ // Stop the HC from processing the EDBulk by setting its Skip bit.
+ //
+ fpDescPtrs->pstEDBulk->dControl |= ED_SKIP_TDQ;
+ //
+ // Update the data toggle value into the mass info structure
+ //
+
+ *DataToggle = (UINT8) ( ( (fpDescPtrs->pstTDBulkData->dControlStatus &
+ GTD_DATA_TOGGLE) >> 24 ) & 1 );
+ Toggle = (UINT8) ( (fpDescPtrs->pstTDBulkData->dControlStatus &
+ GTD_DATA_TOGGLE) >> 24 );
+ if ( (Toggle & 0x02) == 0 )
+ {
+ //Use the Carry
+ DwordData = (UINT32) fpDescPtrs->pstEDBulk->fpHeadPointer;
+ DwordData &= 0x00000002;
+ DwordData = DwordData >> 1;
+ DwordData &= 0x00000001;
+ *DataToggle = DwordData;
+ }
+ //
+ // Check for the error conditions - if possible recover from them
+ //
+ ByteData = (UINT8) (fpDescPtrs->pstTDBulkData->dControlStatus >> 28);
+ if (ByteData) {
+ if (ByteData == GTD_DEVICE_NOT_RESPOND) {
+ //TODO fpUSBData->bLastCommandStatus |= USB_BULK_TIMEDOUT;
+ *DataLength = 0;
+ return EFI_NOT_FOUND;
+ }
+ if (ByteData == GTD_STALL) {
+ //TODO fpUSBData->bLastCommandStatus |= USB_BULK_STALLED;
+ *DataLength = 0;
+ return EFI_NOT_FOUND;
+ }
+ }
+ //
+ // Get the size of data transferred
+ //
+ // Size transferred is calculated by subtracting end address with current
+ // buffer pointer and subtracting that value from the total size
+ //
+ if (!fpDescPtrs->pstTDBulkData->fpCurrentBufferPointer)
+ {
+ //All data are transfered.
+ return EFI_SUCCESS;
+ }
+ DwordData = (UINT32) fpDescPtrs->pstTDBulkData->fpBufferEnd;
+ DwordData = DwordData -
+ (UINT32) fpDescPtrs->pstTDBulkData->fpCurrentBufferPointer;
+ if (DwordData != 0)
+ {
+ *DataLength = *DataLength - DwordData - 1;
+ }
+ else {
+ ;
+ }
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: OhciHcWaitForTransferComplete
+//
+// Description:
+// This function waits for a tranfer to complete by polling the
+// HcInterruptStatus register's WritebackDoneHead field.
+//
+// Input:
+// IN PEI_OHCI_DEV *OhciDevPtr
+// -- PEI_OHCI_DEV pointer
+// IN POHCI_TD Td
+// -- Not used
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS OhciHcWaitForTransferComplete (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_OHCI_DEV *OhciDevPtr,
+ IN POHCI_TD Td )
+{
+ UINT32 Count;
+ OHCI_HC_REGISTERS *HcReg =
+ (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress;
+ HC_INTERRUPT_STATUS *HcIntStatus = &HcReg->HcInterruptStatus;
+ UINT32 DoneHead = 0;
+
+ // Poll (up to 4 seconds) or until the
+ // WriteBackDoneHead status bit is set in
+ // the HcInterruptStatus operational register.
+
+ // if the WriteBackDoneHead is set, then clear
+ // HccaDoneHead in the HCCA and WriteBackDoneHead
+ // and then return EFI_SUCCESS to continue execution.
+
+ for (Count = 0; Count < 1000; Count++) {
+ if (HcIntStatus->Field.WriteBackDoneHead == HCINT_WB_DONE ) {
+ DoneHead = HcReg->HcHcca->HccaDoneHead;
+ HcReg->HcHcca->HccaDoneHead = 0;
+ HcIntStatus->Field.WriteBackDoneHead = HCINT_STATUS_CLEAR;
+ if (DoneHead == (UINT32)Td) {
+ return EFI_SUCCESS;
+ }
+ }
+ OHCI_FIXED_DELAY_MS( OhciDevPtr, 4 ); // 4 ms
+
+ }
+
+ PEI_TRACE ((EFI_D_ERROR, PeiServices, "OHCI Time-Out:\n"));
+ return EFI_NOT_FOUND;
+
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/OhciPEI/OhciPei.cif b/Core/EM/UsbRecovery/OhciPEI/OhciPei.cif
new file mode 100644
index 0000000..49ec85b
--- /dev/null
+++ b/Core/EM/UsbRecovery/OhciPEI/OhciPei.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "OhciPei"
+ category = ModulePart
+ LocalRoot = "core\em\UsbRecovery\OhciPEI\"
+ RefName = "OhciPei"
+[files]
+"OhciPei.c"
+"OhciPei.h"
+"OhciPeiBoard.c"
+[parts]
+"OHCI PPI"
+<endComponent>
diff --git a/Core/EM/UsbRecovery/OhciPEI/OhciPei.h b/Core/EM/UsbRecovery/OhciPEI/OhciPei.h
new file mode 100644
index 0000000..d743f61
--- /dev/null
+++ b/Core/EM/UsbRecovery/OhciPEI/OhciPei.h
@@ -0,0 +1,909 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/OhciPei.h 9 11/24/12 5:44a Ryanchou $
+//
+// $Revision: 9 $
+//
+// $Date: 11/24/12 5:44a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/OhciPei.h $
+//
+// 9 11/24/12 5:44a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 8 8/23/12 9:59p Wilsonlee
+// [TAG] EIP97069
+// [Category] Improvement
+// [Description] Reset root port algorythm update.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// UhcPeim.h, UsbPeim.c, usb.h
+//
+// 7 1/18/11 1:00a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 6 3/17/09 5:09p Olegi
+//
+// 5 3/03/09 7:26p Olegi
+// MaximumPacketLength changed from UINT8 to UINT16.
+//
+// 4 7/18/08 5:04p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 3 7/10/08 6:36p Michaela
+// Updated to support OHCI controllers
+//
+// 2 9/22/06 12:23p Sivagarn
+// - Included appropriate headers for flies and functions
+// - Updated copyright messages
+// - Merged multiple MAK and SDL files into one MAK and SDL file
+// - Removed unnecessary files
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: OhciPei.h
+//
+// Description: This file is the main header file for the OHCI PEI USB
+// recovery module. It contains generic constant and type
+// declarations/definitions.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef _OHCIPEI_H
+#define _OHCIPEI_H
+
+#include "Efi.h"
+#include "Pei.h"
+#include "Ppi\UsbHostController.h"
+
+
+
+//----------------------------------------------------------------------------
+// Macros
+//----------------------------------------------------------------------------
+
+
+
+//----------------------------------------------------------------------------
+// OHCI_FIXED_DELAY_MS( OhciDevPtr, milliseconds )
+//
+// invokes a delay specified in milliseconds using the PEI_OHCI_DEV.StallPpi
+// member interface pointer, which is initialized from a EFI_PEI_STALL_PPI
+// interface.
+#define OHCI_FIXED_DELAY_MS( OhciDevPtr, milliseconds ) \
+ OhciDevPtr->StallPpi->Stall( OhciDevPtr->PeiServices, \
+ OhciDevPtr->StallPpi, milliseconds * 1000 );
+
+
+//----------------------------------------------------------------------------
+// MASK(high,low)
+//
+// defines a bit mask value with bits set in the bit
+// range specified from high down to low (zero-based)
+//
+// Notes:
+// 1) this is expected to be used only in 32-bit compiled code
+#ifndef MASK
+#define MAX_VAL 0xffffffff // maximum value supported by CPU
+#define MAX_BIT 31 // highest bit position in MAX_VAL
+#define MASK( high, low ) (\
+ ( MAX_VAL >> ( MAX_BIT - ( (high) - (low) ) ) ) \
+ << (low) \
+)
+#endif
+
+
+//----------------------------------------------------------------------------
+// READ_BITS(src,high,low)
+//
+// extracts a bit field shifted down to bit position 0 from src, where high
+// and low define the bit range (zero-based).
+//
+// Notes:
+// 1) this is expected to be used only in 32-bit compiled code
+#ifndef READ_BITS
+#define READ_BITS( src, high, low ) (\
+ ( (src) & MASK( (high), (low) ) ) \
+ >> (low) \
+)
+#endif
+
+
+//----------------------------------------------------------------------------
+// WRITE_BITS( src, val, high, low )
+//
+// returns the modified src after writing a bit field with val, where the bit
+// field's range is specified by high down to low.
+//
+// Notes:
+// 1) the user must ensure that the val fits in the bit range
+// 2) the bits in the range high:low are the only bits touched and
+// they are cleared and replaced with val
+// 3) this is expected to be used only in 32-bit compiled code
+#ifndef WRITE_BITS
+#define WRITE_BITS( src, val, high, low ) (\
+ ( (src) & ~MASK( (high), (low) ) ) \
+ | ( (val) << (low) ) \
+)
+#endif
+
+
+//----------------------------------------------------------------------------
+// ABORT_ON_ERROR( call )
+//
+// simplifies the task of returning EFI_STATUS value after an unsuccessful
+// function execution.
+#define ABORT_ON_ERROR( call ) {\
+ EFI_STATUS status = call; \
+ if ( EFI_ERROR( status ) ) {\
+ return status;}}
+
+
+//----------------------------------------------------------------------------
+// OHCI_PCI_ADDRESS( ControllerIndex, Register )
+//
+// allows easy generation of a valid PCI address using an index into the
+// gOhciControllerPciTable and a register number
+#define OHCI_PCI_ADDRESS( ControllerIndex, Register ) PEI_PCI_CFG_ADDRESS( \
+ gOhciControllerPciTable[ControllerIndex].Bus, \
+ gOhciControllerPciTable[ControllerIndex].Device, \
+ gOhciControllerPciTable[ControllerIndex].Function, \
+ Register )
+
+
+//----------------------------------------------------------------------------
+// EFI_SIGNATURE_32( A, B, C, D)
+//
+// defines a signature that can be used with the PEI_CR macro to return a
+// pointer to the data structure that contains the specified field and
+// signature
+#define EFI_SIGNATURE_16(A,B) ((A) | ((B)<<8))
+#define EFI_SIGNATURE_32(A,B,C,D) \
+ (EFI_SIGNATURE_16((A),(B)) | (EFI_SIGNATURE_16((C),(D)) << 16))
+
+
+//----------------------------------------------------------------------------
+// PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( a )
+//
+// uses the _CR macro to obtain a pointer to a PEI_OHCI_DEV structure from
+// a PEI_USB_HOST_CONTROLLER_PPI interface pointer
+#define _CR( Record, TYPE, Field ) \
+ ( (TYPE *) ( (CHAR8 *) (Record) - (CHAR8 *) &( ( (TYPE *) 0 )->Field ) ) )
+#define PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( a ) \
+ _CR( a, PEI_OHCI_DEV, UsbHostControllerPpi )
+
+
+//----------------------------------------------------------------------------
+// GET_PORT_STATUS_REG_OFFSET( x )
+//
+//Macro to get the RhPortStatus register offset
+#define GET_PORT_STATUS_REG_OFFSET( x ) ( (x) + 21 ) // 0x54 / 4 = 21
+
+
+
+//----------------------------------------------------------------------------
+// Constants
+//
+// Notes:
+// 1) These constants are not associated with a particular structure
+// and are used globally withing OHCI-specific code
+//----------------------------------------------------------------------------
+
+
+
+// Standard OHCI PCI configuration space registers
+#define OHCI_BASE_ADDR_REG 0x10 // OHCI BAR register
+#define OHCI_CMD_REGISTER 0x04 // OHCI command register
+
+// Stantdard ED and TD list structure constants
+#define OHCI_TERMINATE 0x00000000
+
+
+
+//----------------------------------------------------------------------------
+// Structure types
+//
+// Notes:
+// 1) Constants that are associated with a particular structure
+// are defined locally within the structure to facilitate easier
+// maintenance.
+//----------------------------------------------------------------------------
+
+
+
+#pragma pack(push,1)
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: PCI_BUS_DEV_FUNCTION
+//
+// Description:
+// This structure type defines the bus, device and function number
+// that compose a PCI address.
+//
+// Fields: Type Name Description
+// ----------------------------------
+// UINT8 Bus PCI Bus on which a particular OHCI controller resides
+// UINT8 Device PCI Device number for a particular OHCI controller
+// UINT8 Function PCI Function number for a particular OHCI controller
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct
+{
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+} PCI_BUS_DEV_FUNCTION;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: OHCI_PCI_PROGRAMMING_TABLE
+//
+// Description:
+// This structure type defines the parameters to be used in a call
+// to EFI_PEI_PCI_CFG_PPI.Modify(), when programming the PCI
+// configuration space for a particular OHCI controller.
+//
+// Fields: Type Name Description
+// ----------------------------------
+// EFI_PEI_PCI_CFG_PPI_WIDTH Size Size of the access
+// UINT32 Register Register/offset within the PCI configuration space
+// UINT32 SetBits Bits to set
+// UINT32 ClearBits Bits to clear
+//
+// Notes:
+// See also
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct
+{
+ EFI_PEI_PCI_CFG_PPI_WIDTH Size;
+ UINT32 Register;
+ UINT32 SetBits;
+ UINT32 ClearBits;
+} OHCI_PCI_PROGRAMMING_TABLE;
+
+
+typedef struct _HC_CONTROL
+{
+ union {
+ UINT32 AllBits;
+ // Set bits using the following
+ #define CONTROL_LIST_ENABLE BIT4
+ #define BULK_LIST_ENABLE BIT5
+ #define USB_RESET 0 << 6
+ #define USB_RESUME 1 << 6
+ #define USB_OPERATIONAL 2 << 6
+ #define USB_SUSPEND 3 << 6
+
+ struct
+ {
+ UINT32 ControlBulkServiceRatio : 2; // [1:0] CBSR
+ UINT32 PeriodicListEnable : 1; // [2] PLE
+ UINT32 IsochronousEnable : 1; // [3] IE
+ UINT32 ControlListEnable : 1; // [4] CLE
+ // Read: TRUE or FALSE
+
+ UINT32 BulkListEnable : 1; // [5] BLE
+ // Read: TRUE or FALSE
+
+ UINT32 HostControllerFunctionalState : 2; // [7:6] HCFS
+ // Write:
+ #define SET_USB_RESET 0
+ #define SET_USB_RESUME 1
+ #define SET_USB_OPERATIONAL 2
+ #define SET_USB_SUSPEND 3
+
+ UINT32 InterruptRouting : 1; // [8] IR
+ UINT32 RemoteWakeupConnected : 1; // [9] RWC
+ UINT32 RemoteWakeupEnable : 1; // [10] RWE
+ UINT32 Reserved : 21; // [31:11]
+ } Field;
+ };
+} HC_CONTROL;
+
+//
+// Notes:
+// To ensure proper updating, follow these guidelines:
+//
+// 1) Write all bits using the AllBits union element
+// (OR bit-constants if modifying multiple fields).
+//
+// * Writing individual bits may have adverse
+// effects.
+//
+// 2) Typically you will read individual bits using the
+// Field union element.
+//
+// 3) Writing a zero to any field in this register has
+// no effect.
+//
+typedef struct _HC_RH_PORT_STATUS
+{
+ union {
+ UINT32 AllBits;
+ #define SET_PORT_ENABLE BIT1
+ #define SET_PORT_SUSPEND BIT2
+ #define SET_PORT_RESET BIT4
+ #define SET_PORT_POWER BIT8
+
+ #define CLEAR_PORT_ENABLE BIT0
+ #define CLEAR_SUSPEND_STATUS BIT3
+ #define CLEAR_PORT_POWER BIT9
+ #define CLEAR_CONNECT_STATUS_CHANGE BIT16
+ #define CLEAR_PORT_ENABLE_STATUS_CHANGE BIT17
+ #define CLEAR_PORT_SUSPEND_STATUS_CHANGE BIT18
+ #define CLEAR_PORT_OVERCURRENT_INDICATOR_CHANGE BIT19
+ #define CLEAR_PORT_RESET_STATUS_CHANGE BIT20
+
+ struct
+ {
+ UINT32 CurrentConnectStatus : 1; // [0] CCS
+ #define RH_PORT_CLEAR_ENABLE 1
+ UINT32 PortEnableStatus : 1; // [1] PES
+ #define RH_PORT_SET_ENABLE 1
+ UINT32 PortSuspendStatus : 1; // [2] PSS
+ #define RH_PORT_SET_SUSPEND 1
+ UINT32 PortOverCurrentIndicator : 1; // [3] POCI
+ #define RH_PORT_CLEAR_SUSPEND 1
+ UINT32 PortResetStatus : 1; // [4] PRS
+ #define RH_SET_PORT_RESET 1 // write to initiate reset
+ #define RH_RESET_ACTIVE 1 // read set if reset active
+ UINT32 Reserved1 : 3; // [7:5]
+ UINT32 PortPowerStatus : 1; // [8] PPS
+ #define RH_PORT_POWER_ON 1
+
+ UINT32 LowSpeedDeviceAttached : 1; // [9] LSDA
+ UINT32 Reserved2 : 6; // [15:10]
+ UINT32 ConnectStatusChange : 1; // [16] CSC
+ #define RH_PORT_CLEAR_CONNECT_CHANGE 1
+ UINT32 PortEnableStatusChange : 1; // [17] PESC
+ #define RH_PORT_CLEAR_ENABLE_CHANGE 1
+ UINT32 PortSuspendStatusChange : 1; // [18] PSSC
+ UINT32 PortOverCurrentIndicatorChange : 1; // [19] OCIC
+ UINT32 PortResetStatusChange : 1; // [20] PRSC
+ #define RH_PORT_CLEAR_RESET_CHANGE 1
+ #define PORT_RESET_NOT_COMPLETE 0
+ #define PORT_RESET_COMPLETE 1
+ UINT32 Reserved3 : 11; // [31:21]
+ } Field;
+ };
+} HC_RH_PORT_STATUS;
+
+
+typedef struct _HC_INTERRUPT_STATUS
+{
+ union {
+ UINT32 AllBits;
+ struct
+ {
+ #define HCINT_STATUS_CLEAR 1 // write 1 to clear a status bit
+
+ UINT32 SchedulingOverrun : 1; // [0] SO
+ UINT32 WriteBackDoneHead : 1; // [1] WDH
+ #define HCINT_WB_DONE 1
+
+ UINT32 StartofFrame : 1; // [2] SF
+ UINT32 ResumeDetected : 1; // [3] RD
+ UINT32 UnrecoverableError : 1; // [4] UE
+ UINT32 FrameNumberOverflow : 1; // [5] FNO
+ UINT32 RootHubStatusChange : 1; // [6] RHSC
+ UINT32 Reserved1 : 23; // [29:7]
+ UINT32 OwnershipChange : 1; // [30] OC
+ UINT32 Reserved2 : 1; // [31]
+ } Field;
+ };
+} HC_INTERRUPT_STATUS;
+
+
+typedef struct _HC_RH_DESCRIPTORA
+{
+ union {
+ UINT32 AllBits;
+ #define POWERED_SAME (0 << 8)
+ #define POWERED_INDIVIDUALLY (1 << 8)
+ #define POWER_SWITCHED (0 << 9)
+ #define ALWAYS_POWERED (1 << 9)
+ #define OVERCURRENT_REPORTED_COLLECTIVELY (0 << 11)
+ #define OVERCURRENT_REPORTED_PER_PORT (1 << 11)
+ #define OVERCURRENT_COLLECTIVE_PROTECTION (0 << 12)
+ #define NO_OVERCURRENT_PROTECTION (1 << 12)
+
+ struct
+ {
+ UINT32 NumberDownstreamPorts : 8; // [7:0] NDP
+ UINT32 PowerSwitchingMode : 1; // [8] PSM
+ #define PSM_COLLECTIVE 0 // all ports powered same
+ #define PSM_PER_PORT 1 // ports powered individually
+
+ UINT32 NoPowerSwitching : 1; // [9] NPS
+ #define NPS_SWITCHED 0 // ports are individually
+ // power switched
+ #define NPS_NOT_SWITCHED 1 // ports are always on when
+ // HC is powered
+
+ UINT32 DeviceType : 1; // [10] DT (always 0)
+ UINT32 OverCurrentProtectionMode : 1; // [11] OCPM
+ #define OCPM_COLLECTIVE 0 // reported collectively
+ #define OCPM_PER_PORT 1 // reported per-port
+
+ UINT32 NoOverCurrentProtection : 1; // [12] NOCP
+ #define NOCP_PROTECTED 0 // reported collectively
+ #define NOCP_NOT_PROTECTED 1 // no support
+
+ UINT32 Reservered : 11; // [23:13]
+ UINT32 PowerOnToPowerGoodTime : 8; // [31:24] POTPGT
+ // (in units of 2ms)
+ } Field;
+ };
+} HC_RH_DESCRIPTORA;
+
+
+typedef struct _HC_RH_DESCRIPTORB
+{
+ union {
+ UINT32 AllBits;
+ #define ALL_REMOVEABLE (0x0000 << 0)
+ #define ALL_PER_PORT_POWER_SWITCHED (0xfffe << 15)
+ struct
+ {
+ UINT32 DeviceRemovable : 16; // [15:0] DR
+ // Each bit represents a port
+ // 0 = removable
+ // 1 = not removable
+ UINT32 PortPowerControlMask : 16; // [31:16] PPCM
+ // Each bit represents a port
+ // 0 = controlled by global
+ // power switch
+ // 1 = per-port power control
+ } Field;
+ };
+} HC_RH_DESCRIPTORB;
+
+typedef struct _HC_RH_STATUS
+{
+ union {
+ UINT32 AllBits;
+ struct
+ {
+ UINT32 LocalPowerStatus : 1; // [0] LPS
+ UINT32 OverCurrentIndicator : 1; // [1] OCI
+ UINT32 Reserved1 : 13; // [14:2]
+ UINT32 DeviceRemoteWakeupEnable : 1; // [15] DRWE
+ UINT32 LocalPowerStatusChange : 1; // [16] LPSC
+ // Write 1 to turn on power to all ports or to ports
+ // specified by PortPowerControlMask, depending on
+ // PowerSwitchingMode.
+ #define SET_GLOBAL_POWER 1
+
+ UINT32 OverCurrentIndicatorChange : 1; // [17] OCIC
+ UINT32 Reserved2 : 13; // [30:18]
+ UINT32 ClearRemoteWakeupEnable : 1; // [31] CRWE
+ } Field;
+ };
+} HC_RH_STATUS;
+
+typedef struct _HC_FM_INTERVAL
+{
+ union {
+ UINT32 AllBits;
+ struct
+ {
+ UINT32 FrameInterval : 14; // [13:0] FI
+ #define FM_INTERVAL_DEFAULT 0x2edf
+
+ UINT32 Reserved : 2; // [15:14]
+ UINT32 FsLargestDataPacket : 15; // [30:16] FSMPS
+ // (FrameInterval-210) * 6/7 ==> 0x2778
+ // (See OHCI specification)
+ #define FS_LARGEST_PACKET_DEFAULT 0x2778
+
+ UINT32 FrameIntervalToggle : 1; // [31] FIT
+ } Field;
+ };
+} HC_FM_INTERVAL;
+
+typedef struct _HC_HCCA
+{
+ #define OHCI_FRAME_LIST_SIZE 32
+ UINT32 HccaInterrruptTable[OHCI_FRAME_LIST_SIZE]; // Offset 0x00
+ UINT16 HccaFrameNumber; // Offset 0x80
+ UINT16 HccaPad1; // Offset 0x82
+ UINT32 HccaDoneHead; // Offset 0x84
+ UINT8 HccaReserved[120]; // Offset 0x88
+} HC_HCCA;
+
+typedef struct _HC_COMMAND_STATUS
+{
+ union {
+ UINT32 AllBits;
+ // Typically write to this entire register
+ #define SET_CONTROLLER_RESET (1 << 0)
+ #define SET_CONTROL_LIST_FILLED (1 << 1)
+ #define SET_BULK_LIST_FILLED (1 << 2)
+
+ struct
+ {
+ UINT32 HostControllerReset : 1; // [0] HCR
+ UINT32 ControlListFilled : 1; // [1] CLF
+ UINT32 BulkListFilled : 1; // [2] BLF
+ UINT32 OwnershipChangeRequest : 1; // [3] OCR
+ UINT32 Reserved1 : 12; // [15:4]
+ UINT32 SchedulingOverrunCount : 2; // [17:16] SOC
+ UINT32 Reserved2 : 14; // [31:18]
+ } Field;
+ };
+} HC_COMMAND_STATUS;
+
+typedef struct _OHCI_HC_REGISTERS_
+{
+ UINT32 HcRevision; // [31:0] (Offset 00)
+ HC_CONTROL HcControl; // [63:32] (Offset 04)
+ HC_COMMAND_STATUS HcCommandStatus; // [95:64] (Offset 08)
+ HC_INTERRUPT_STATUS HcInterruptStatus; // [127:96] (Offset 0C)
+ UINT32 HcInterruptEnable; // [159:128] (Offset 10)
+ UINT32 HcInterruptDisable; // [191:160] (Offset 14)
+ HC_HCCA *HcHcca; // [223:192] (Offset 18)
+ UINT32 HcPeriodCurrentEd; // [255:224] (Offset 1C)
+ UINT32 HcControlHeadEd; // [287:256] (Offset 20)
+ UINT32 HcControlCurrentEd; // [319:288] (Offset 24)
+ UINT32 HcBulkHeadEd; // [351:320] (Offset 28)
+ UINT32 HcBulkCurrentEd; // [383:352] (Offset 2C)
+ UINT32 HcDoneHead; // [415:384] (Offset 30)
+ HC_FM_INTERVAL HcFmInterval; // [447:416] (Offset 34)
+ UINT32 HcFmRemaining; // [479:448] (Offset 38)
+ HC_FM_INTERVAL HcFmNumber; // [511:480] (Offset 3C)
+ UINT32 HcPeriodicStart; // [543:512] (Offset 40)
+ UINT32 HcLsThreshold; // [575:544] (Offset 44)
+ HC_RH_DESCRIPTORA HcRhDescriptorA; // [607:576] (Offset 48)
+ HC_RH_DESCRIPTORB HcRhDescriptorB; // [639:608] (Offset 4C)
+ HC_RH_STATUS HcRhStatus; // [671:640] (Offset 50)
+ HC_RH_PORT_STATUS HcRhPortStatus[3]; // [767:672] (Offset 54)
+ UINT32 Reserved[40]; // [2047:768] (Offset 60)
+ UINT32 HceControl; // [2079:2048] (Offset 100)
+ UINT32 HceInput; // [2111:2080] (Offset 104)
+ UINT32 HceOutput; // [2143:2112] (Offset 108)
+ UINT32 HceStatus; // [2175:2144] (Offset 10C)
+} OHCI_HC_REGISTERS;
+
+
+typedef struct _OHCI_TD_
+{
+ UINT32 dControlStatus; // Control and status fields
+ #define GTD_BUFFER_ROUNDING (1 << 18) // [18] BufferRounding
+ #define GTD_SETUP_PACKET (0 << 19) // [20:19] Direction/PID
+ #define GTD_OUT_PACKET (1 << 19)
+ #define GTD_IN_PACKET (2 << 19)
+ #define GTD_INTD (0 << 21) // [23:21] DelayInterrupt
+ // depends on device
+ #define GTD_DATA_TOGGLE (3 << 24) // [25:24] DataToggle
+ #define GTD_SETUP_TOGGLE (2 << 24) // (see MSB of data toggle)
+ #define GTD_DATA1_TOGGLE (3 << 24)
+ #define GTD_NO_ERRORS (0 << 26) // [27:26] ErrorCount
+ #define GTD_STALL 0x04 // [31:28] ConditionCode
+ #define GTD_DEVICE_NOT_RESPOND 0x05
+ #define GTD_NOT_ACCESSED 0x0f
+
+ UINT8 *fpCurrentBufferPointer; // Current buffer pointer
+ UINT8 *fpLinkPointer; // Pointer to the next TD
+ UINT8 *fpBufferEnd; // End pointer of data buffer
+ #define MAX_CONTROL_DATA_SIZE 0x200
+
+ UINT32 dCSReloadValue; // Control status reload value
+ UINT8 bCallBackIndex; // Index of the routine to
+ // call
+ // on completion
+ UINT8 bActiveFlag; // Routine to call on
+ // completion
+ UINT8 bDeviceAddr; // Device Address
+ UINT8 bResvd;
+ UINT8 aSetupData[8]; // Used for setup packet
+} OHCI_TD, *POHCI_TD;
+
+typedef struct _OHCI_TD_DESCRIPTOR OHCI_TD_DESCRIPTOR;
+typedef struct _OHCI_TD_DESCRIPTOR
+{
+ union {
+ UINT32 AllBits;
+ struct
+ {
+ UINT32 Reserved : 18; // [17:0]
+ UINT32 BufferRounding : 1; // [18] R
+ UINT32 DirectionPid : 2; // [20:19] DP
+ UINT32 DelayInterrupt : 3; // [23:21] DI
+ UINT32 DataToggle : 2; // [25:24] T
+ UINT32 ErrorCount : 2; // [27:26] EC
+ UINT32 ConditionCode : 4; // [31:28] CC
+ // 0000 NOERROR
+ // 0001 CRC
+ // 0010 BITSTUFFING
+ // 0011 DATATOGGLEMISMATCH
+ // 0100 STALL
+ // 0101 DEVICENOTRESPONDING
+ // 0110 PIDCHECKFAILURE
+ // 0111 UNEXPECTEDPID
+ // 1000 DATAOVERRUN
+ // 1001 DATAUNDERRUN
+ // 1010 reserved
+ // 1011 reserved
+ // 1100 BUFFEROVERRUN
+ // 1101 BUFFERUNDERRUN
+ // 111x NOT ACCESSED
+ } Field;
+ } Controlfield;
+ UINT32 CurrentBufferPointer;
+ UINT32 NextTd;
+ UINT32 BufferEnd;
+} OHCI_TD_DESCRIPTOR;
+
+
+typedef struct _OHCI_ED_
+{
+ UINT32 dControl; // ED control fields
+ #define ED_OUT_PACKET 0x00000800
+ #define ED_IN_PACKET 0x00001000
+ #define ED_SKIP_TDQ BIT14
+ POHCI_TD fpTailPointer; // TD queue tail pointer
+ POHCI_TD fpHeadPointer; // TD queue head pointer
+ struct _OHCI_ED_ *fpEDLinkPointer; // Pointer to next ED
+ UINT8 aReserved[16];
+} OHCI_ED, *POHCI_ED;
+
+typedef struct _OHCI_EP_DESCRIPTOR OHCI_EP_DESCRIPTOR;
+typedef struct _OHCI_EP_DESCRIPTOR
+{
+ union {
+ UINT32 AllBits;
+ struct
+ {
+ UINT32 FunctionAddress : 7; // [6:0] FA
+ UINT32 EndpointNumber : 4; // [10:7] EN
+ UINT32 Direction : 2; // [12:11] D
+ UINT32 Speed : 1; // [13] S
+ UINT32 Skip : 1; // [14] K
+ UINT32 Format : 1; // [15] F
+ UINT32 MaximumPacketSize : 11; // [26:16] MPS
+ UINT32 Reserved : 5; // [31:27] Reserved
+ } Field;
+ } Controlfield;
+ UINT32 TailPointer;
+ union {
+ UINT32 AllBits;
+ struct
+ {
+ UINT32 Halted : 1; // [0] H
+ UINT32 ToggleCarry : 1; // [1] C
+ UINT32 Reserved : 29; // [31:2] Reserved
+ } Field;
+ } HeadPointer;
+ OHCI_EP_DESCRIPTOR *NextEndpointDescriptor;
+} OHCI_EP_DESCRIPTOR;
+
+
+typedef struct _OHCI_DESC_PTRS_
+{
+ POHCI_ED pstED1ms;
+ POHCI_ED pstED2ms;
+ POHCI_ED pstED8ms;
+ // Do not change the following order of ED32ms and TD32ms
+ POHCI_ED pstED32ms;
+ POHCI_TD pstTD32ms;
+ // Do not change the following order of EDRepeat and TDRepeat
+ POHCI_ED pstEDRepeat;
+ POHCI_TD pstTDRepeat;
+
+ POHCI_ED pstEDControl;
+ POHCI_TD pstTDControlSetup;
+ POHCI_TD pstTDControlData;
+ POHCI_TD pstTDControlStatus;
+
+ POHCI_ED pstEDInterrupt;
+ POHCI_TD pstTDInterruptData;
+
+ POHCI_ED pstEDBulk;
+ POHCI_TD pstTDBulkData;
+
+} OHCI_DESC_PTRS, *POHCI_DESC_PTRS;
+
+typedef struct _USB_HC_INFO_
+{
+ UINT32 dStateFlag;
+ UINT8 bHCNum;
+ UINT8 bHCType;
+ UINTN *HCCommArea;
+ UINTN BaseAddr;
+ UINT8 bPortNum;
+ UINT16 wBusDevFuncNum;
+ // FPIRQ_INFO
+ UINT16 wAsyncListSize;
+ UINT8 bOpRegOffset;
+ UINT32 dMaxBulkDataSize;
+ UINT8 bHCFlag;
+ // UINT8 bExtCapPtr; //EHCI
+ // UINT8 bRegOff;
+ VOID *usb_bus_data;
+ // EFI_HANDLE Controller;
+ // EFI_DEVICE_PATH_PROTOCOL *pHCdp;
+
+} USB_HC_INFO, *PUSB_HC_INFO;
+
+
+typedef struct _PEI_OHCI_DEV
+{
+ UINTN Signature;
+ #define PEI_OHCI_DEV_SIGNATURE EFI_SIGNATURE_32( 'p', 'u', 'h', 'c' )
+ EFI_PEI_SERVICES **PeiServices;
+ PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi;
+ EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
+ EFI_PEI_CPU_IO_PPI *CpuIoPpi;
+ EFI_PEI_STALL_PPI *StallPpi;
+ EFI_PEI_PCI_CFG_PPI *PciCfgPpi;
+ UINT32 UsbHostControllerBaseAddress;
+
+ UINT8 bNumPorts;
+ OHCI_DESC_PTRS stOHCIDescPtrs;
+ UINT16 wAsyncListSize;
+ UINT32 dMaxBulkDataSize;
+ #define MAX_OHCI_BULK_DATA_SIZE 4096
+
+ UINT32 *pFrameList; // HC Communication Area base
+ // & HccaInterruptTable base
+} PEI_OHCI_DEV, *PPEI_OHCI_DEV;
+
+#pragma pack(pop)
+
+
+
+//----------------------------------------------------------------------------
+// Function prototypes
+//----------------------------------------------------------------------------
+
+
+
+EFI_STATUS InitializeUsbHC (
+ PEI_OHCI_DEV *UhcDev );
+
+VOID OhciInitHC (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_OHCI_DEV *pUhcDev,
+ UINT8 Index );
+
+VOID OhciHcReset (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_OHCI_DEV *pUhcDev );
+
+
+VOID OhciHcEnableRootHub (
+ PEI_OHCI_DEV *OhciDevPtr,
+ UINT8 PortNumber );
+
+EFI_STATUS OhciHcWaitForTransferComplete (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_OHCI_DEV *OhciDevPtr,
+ POHCI_TD Td );
+
+EFI_STATUS OhciHcControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult );
+
+EFI_STATUS OhciHcBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT16 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult );
+
+EFI_STATUS OhciHcGetRootHubPortNumber (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *PortNumber );
+
+EFI_STATUS OhciHcGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus );
+
+EFI_STATUS OhciHcSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature );
+
+EFI_STATUS OhciHcClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature );
+
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c b/Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c
new file mode 100644
index 0000000..4256cdf
--- /dev/null
+++ b/Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c
@@ -0,0 +1,508 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/OhciPeiBoard.c 6 4/11/11 11:59p Rameshr $
+//
+// $Revision: 6 $
+//
+// $Date: 4/11/11 11:59p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/OhciPeiBoard.c $
+//
+// 6 4/11/11 11:59p Rameshr
+// [TAG]- EIP 57444
+// [Category]-IMPROVEMENT
+// [Description]- PI1.1 Support.
+// [Files]- OhciPeiboard.c,Xhcipei.c, Peiusblib.c
+//
+// 5 10/21/08 5:57p Michaela
+// Added EHCI-related fixes for issues
+// that may occur if EHCI is used before
+// USB Recovery is invoked:
+// Added SDL Tokens:
+// PEI_EHCI_PCI_BDFS and
+// PEI_EHCI_MEM_BASE_ADDRESSES.
+//
+// Removed/modified some debugging
+// development code:
+// Removed SDL Tokens:
+// USBR_DEBUG_SUPPORT and
+// USBR_SERIAL_PORT_AVAILABLE
+// Removed Elinks:
+// UsbRecoveryDebug_DIR and
+// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+// Modified SDL Token:
+// FORCE_RECOVERY to default value of 0.
+//
+// (See this module's Help documentation
+// for more information.)
+//
+// 4 7/29/08 7:50p Michaela
+// cleaned-up SB700-specific code
+//
+// 3 7/29/08 5:50p Michaela
+// 1) Updated code to move most porting tasks to SDL
+// 2) Added more debug break points and improved interactive
+// debugging capability for when a serial port is not available.
+// 3) Updated help files
+//
+// 2 7/18/08 5:04p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 1 7/10/08 6:35p Michaela
+// Updated to support OHCI controllers
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: OhciPeiBoard.c
+//
+// Description: This file contains routines that are board specific for
+// initializing the OHCI controller in the USB Recovery module.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <PEI.h>
+#include <AmiPeiLib.h>
+#include <token.h>
+#include <PPI/PeiGetUCtrl.h>
+#include <PPI/OhciPPI.h>
+#include <PPI/stall.h>
+#include "OhciPei.h"
+
+#ifndef PI_SPECIFICATION_VERSION //old Core
+extern EFI_STATUS PciCfgModify(
+IN CONST EFI_PEI_SERVICES **PeiServices,
+IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
+IN UINT64 Address,
+IN UINTN SetBits,
+IN UINTN ClearBits
+);
+#endif
+
+//----------------------------------------------------------------------------
+// Porting Steps:
+//
+// 1) define/undefine the appropriate southbridge type
+// 2) define the OHCI_BASE register
+// 3) define registers and their set/clear bits for each register to be
+// modified in each controller's PCI configuration space
+//
+//----------------------------------------------------------------------------
+
+
+// #define AMD_8111 // define to initialize AMD 8111 SB
+
+// #define AMD_SB700 // define to initialize AMD SB700 SB
+
+#define OHCI_BASE PEI_OHCI_IOBASE // first OHCI device is defined
+ // by SDL token and others
+ // are programmatically
+ // determined
+
+#define OHCI_MMIO_SIZE 0x1000 // size of each MMIO region
+
+// For the SB700, the SMBUS PCI configuration space is used
+// to enable USB hardware in the Southbridge
+#define SMBUS_PCI_USB_ENABLE_CFG PEI_PCI_CFG_ADDRESS( 0, 0x14, 0, 0x68 )
+#define SMBUS_PCI_EHCI_BITS BIT2 | BIT6
+#define SMBUS_PCI_OHCI_BITS BIT0 | BIT1 | BIT4 | BIT5 | BIT7
+
+
+
+//<AMI_THDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: gOhciControllerPciTable
+//
+// Description:
+// This is an array of type: PCI_BUS_DEV_FUNCTION
+//
+// This array is initialized from the PEI_OHCI_PCI_DEVICES SDL
+// token, which specifies a {bus,device,function} entry for each OHCI
+// controller. If no OHCI controllers exist, there will be only one
+// NULL entry.
+//
+// This array is used for PCI initialization of OHCI controllers,
+// as well as access to PCI configuration registers.
+//
+// Notes:
+// gOhciControllerPciTable and gOhciControllerCount are accessed via
+// extern declarations by OHCI generic code to access PCI configuration
+// space registers.
+//
+//---------------------------------------------------------------------------
+//<AMI_THDR_END>
+
+PCI_BUS_DEV_FUNCTION gOhciControllerPciTable[] = {USBR_OHCI_CONTROLLER_PCI_ADDRESS};
+UINT16 gOhciControllerCount = \
+ sizeof(gOhciControllerPciTable) / sizeof(PCI_BUS_DEV_FUNCTION);
+
+
+//<AMI_THDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: gOhciPciRegisterTable
+//
+// Description:
+// This is an array of type: OHCI_PCI_PROGRAMMING_TABLE
+//
+// This array is initialized from the OHCI_CONTROLLER_PCI_REGISTER_VALUE
+// SDL eLink, which specifies a { RegisterSize, Register, BitsToSet,
+// BitsToClear } entry for each register in the PCI configuration space
+// that needs to be modified.
+//
+// This array is used for PCI initialization of OHCI controllers.
+//
+// Notes:
+// If no OHCI controllers exist, there will be only one
+// NULL entry.
+//
+// When this table is used, it is assumed that all OHCI controllers
+// are identically programmed for the platform.
+//
+// Other important notes are:
+//
+// 1) do not include the BAR register (the first BAR is
+// PEI_OHCI_IOBASE and subsequent BAR values are
+// calculated from there),
+// 2) the command register should be last, as it enables
+// the devices MMIO access space.
+//
+//---------------------------------------------------------------------------
+//<AMI_THDR_END>
+
+OHCI_PCI_PROGRAMMING_TABLE gOhciPciRegisterTable[] = {USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE};
+#define OHCI_PCI_REGISTER_TABLE_SIZE \
+ sizeof(gOhciPciRegisterTable) / sizeof(OHCI_PCI_PROGRAMMING_TABLE)
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DefaultInit
+//
+// Description:
+// This function generically initializes the PCI configuration space
+// registers for all the OHCI controllers whose PCI addresses are
+// specified by the global PCI_BUS_DEV_FUNCTION array and whose PCI
+// register programming details are specified by the global
+// OHCI_PCI_PROGRAMMING_TABLE array.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN EFI_PEI_PCI_CFG_PPI *Pci
+// -- EFI_PEI_PCI_CFG_PPI pointer
+// IN EFI_PEI_STALL_PPI *StallPpi
+// -- EFI_PEI_STALL_PPI pointer
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+// Notes:
+// This function should not need porting. All porting is accomplished
+// in the global PCI_BUS_DEV_FUNCTION and OHCI_PCI_PROGRAMMING_TABLE
+// arrays, where the former is defined by the
+// USBR_OHCI_CONTROLLER_PCI_ADDRESS SDL eLink and the latter is defined
+// by the USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE SDL eLink.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS DefaultInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PCI_CFG_PPI *Pci,
+ IN EFI_PEI_STALL_PPI *StallPpi )
+{
+ EFI_STATUS Status;
+ UINT32 OhciBaseAddress = OHCI_BASE;
+ UINT16 ControllerIndex;
+ UINT16 RegisterIndex;
+
+
+ //------------------------------------------------------------------------
+ // PCI configuration space programming for all OHCI controllers
+ //------------------------------------------------------------------------
+ for (ControllerIndex = 0;
+ ControllerIndex < gOhciControllerCount;
+ ControllerIndex++, OhciBaseAddress += OHCI_MMIO_SIZE)
+ {
+
+ // Program the BAR
+ //~~~~~~~~~~~~~~~~
+ ABORT_ON_ERROR(
+ Pci->Write( PeiServices, Pci,
+ EfiPeiPciCfgWidthUint32,
+ OHCI_PCI_ADDRESS( ControllerIndex, OHCI_BASE_ADDR_REG ),
+ &OhciBaseAddress );
+ )
+
+ // Program all other registers using gOhciPciRegisterTable[]
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ for (RegisterIndex = 0;
+ RegisterIndex < OHCI_PCI_REGISTER_TABLE_SIZE;
+ RegisterIndex++)
+ {
+ EFI_PEI_PCI_CFG_PPI_WIDTH Width;
+
+ switch (gOhciPciRegisterTable[RegisterIndex].Size)
+ {
+ case 8:
+ Width = EfiPeiPciCfgWidthUint8;
+ break;
+ case 16:
+ Width = EfiPeiPciCfgWidthUint16;
+ break;
+ case 32:
+ Width = EfiPeiPciCfgWidthUint32;
+ break;
+ case 64:
+ Width = EfiPeiPciCfgWidthUint64;
+ break;
+ default:
+ continue;
+ }
+
+ ABORT_ON_ERROR(
+ PciCfgModify(
+ PeiServices,
+ Width,
+ OHCI_PCI_ADDRESS( ControllerIndex,
+ gOhciPciRegisterTable[RegisterIndex].Register ),
+ gOhciPciRegisterTable[RegisterIndex].SetBits,
+ gOhciPciRegisterTable[RegisterIndex].ClearBits );
+ )
+ }
+ }
+
+ return Status = EFI_SUCCESS;
+}
+
+
+#ifdef AMD_8111
+//-----------------------------------------------------
+// This code is not tested, it is simply preserved here
+//-----------------------------------------------------
+
+#define REG_PRI_MEMBASE 0x20
+#define REG_PRI_MEMLIM 0x22
+
+EFI_STATUS Amd8111Init (
+ IN EFI_PEI_SERVICES **PeiServices,
+ EFI_PEI_PCI_CFG_PPI *Pci,
+ EFI_PEI_STALL_PPI *StallPpi )
+{
+ EFI_STATUS Status;
+ UINT32 Buffer32;
+ UINT16 Buffer16;
+ UINT16 CmdReg;
+ volatile UINT32 BaseAddress;
+
+ //
+ // OHCI is sits behind the PCI brige. So program the PCI bridge
+ // First program bus numbers so that PCI slots are available
+ //
+ Buffer32 = 0x080800;
+ Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint32,
+ PEI_PCI_CFG_ADDRESS( 0, 30, 0, REG_PRI_BNUM ),
+ &Buffer32
+ );
+
+
+ // Defines the base of memory range for PCI. 15:4 this 12 bits corresponds
+ // to 31:20 of mem addr 1MB boundary
+ BaseAddress = 0xc0c00000;
+ BaseAddress >>= 16;
+ BaseAddress &= 0xfffffff0;
+ Buffer16 = (UINT16) BaseAddress;
+ Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint16,
+ PEI_PCI_CFG_ADDRESS( 0, 30, 0, REG_PRI_MEMBASE ),
+ &Buffer16
+ );
+
+ //Defines the top of the memory range
+ // BaseAddress = 0xc0c00000;
+ // BaseAddress += 0x00100000;
+ // BaseAddress >>= 16;
+ // BaseAddress &= 0xfffffff0;
+ // Buffer16 = (UINT16)BaseAddress;
+ Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint16,
+ PEI_PCI_CFG_ADDRESS( 0, 30, 0, REG_PRI_MEMLIM ),
+ &Buffer16
+ );
+
+ //Program the prefectable memory space also.
+ BaseAddress = 0xc0c00000;
+ BaseAddress += 0x00100000;
+ BaseAddress >>= 16;
+ BaseAddress &= 0xfffffff0;
+ Buffer16 = (UINT16) BaseAddress;
+ Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint16,
+ PEI_PCI_CFG_ADDRESS( 0, 30, 0, 0x24 ),
+ &Buffer16
+ );
+
+ Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint16,
+ PEI_PCI_CFG_ADDRESS( 0, 30, 0, 0x26 ),
+ &Buffer16
+ );
+
+
+ //Enable memory space, bus mastering of the root bridge
+ Pci->Read(
+ PeiServices,
+ Pci,
+ EfiPeiPciCfgWidthUint16,
+ PEI_PCI_CFG_ADDRESS( 0, 30, 0, 0x04 ),
+ &CmdReg
+ );
+ CmdReg = (UINT16) (CmdReg | 0x06);
+ Pci->Write(
+ PeiServices,
+ Pci,
+ EfiPeiPciCfgWidthUint16,
+ PEI_PCI_CFG_ADDRESS( 0, 30, 0, 0x04 ),
+ &CmdReg
+ );
+}
+#endif // #ifdef AMD_8111
+
+
+#ifdef AMD_SB700
+EFI_STATUS AmdSb700Init (
+ IN EFI_PEI_SERVICES **PeiServices,
+ EFI_PEI_PCI_CFG_PPI *Pci,
+ EFI_PEI_STALL_PPI *StallPpi )
+{
+
+ //-----------------------------------------------------------------------
+ // Enable OHCI controllers from the SMBUS PCI configuration space
+ // using the SMBUS PCI space USB enable register
+ //
+ // By default, the companion controller (OHCI) should be the owner
+ // of the root hub port, so the EHCI controller hardware block
+ // does not need to be disabled.
+ //-----------------------------------------------------------------------
+ ABORT_ON_ERROR(
+ PciCfgModify( PeiServices,
+ EfiPeiPciCfgWidthUint8,
+ SMBUS_PCI_USB_ENABLE_CFG,
+ SMBUS_PCI_OHCI_BITS + SMBUS_PCI_EHCI_BITS,
+ 0
+ )
+ )
+
+ return EFI_SUCCESS;
+}
+#endif // #ifdef AMD_SB700
+
+
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: OhciPeiBoardInit
+//
+// Description:
+// This is a porting hook for board-specific OHCI controller
+// initialization
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices -
+// IN EFI_PEI_PCI_CFG_PPI *Pci -
+// IN EFI_PEI_STALL_PPI *StallPpi -
+//
+// Output:
+// VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS OhciPeiBoardInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PCI_CFG_PPI *Pci,
+ IN EFI_PEI_STALL_PPI *StallPpi )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ // SB-specific programming
+ #if defined (AMD_8111)
+ Status = Amd8111Init( PeiServices, Pci, StallPpi );
+ #elif defined (AMD_SB700)
+ Status = AmdSb700Init( PeiServices, Pci, StallPpi );
+ #endif
+
+ // Generic programming for all OHCI SB, should be called
+ // for all types of southbridges after platform-specific
+ // programming has been done.
+ if (!EFI_ERROR(Status)){
+ Status = DefaultInit( PeiServices, Pci, StallPpi );
+ }
+
+ // PCI root bridge programming is done.
+ // At this stage the OHCI controller should be visible and
+ // Memory mapped IO space should be visible
+
+ return Status;
+
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/PeiUsbLib.c b/Core/EM/UsbRecovery/PeiUsbLib.c
new file mode 100644
index 0000000..2348910
--- /dev/null
+++ b/Core/EM/UsbRecovery/PeiUsbLib.c
@@ -0,0 +1,825 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/PeiUsbLib.c 10 11/24/12 5:43a Ryanchou $
+//
+// $Revision: 10 $
+//
+// $Date: 11/24/12 5:43a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/PeiUsbLib.c $
+//
+// 10 11/24/12 5:43a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 9 4/12/11 12:00a Rameshr
+// [TAG]- EIP 57444
+// [Category]-IMPROVEMENT
+// [Description]- PI1.1 Support.
+// [Files]- OhciPeiboard.c,Xhcipei.c, Peiusblib.c
+//
+// 8 10/11/10 4:51p Olegi
+// XHCI support added.
+//
+// 7 4/06/10 3:37p Fasihm
+// EIP#31987 - Added the generic USBRecovery Fix in the module.
+//
+// 6 3/17/09 5:10p Olegi
+// Added IsPortHighSpeedDeviceAttached function.
+//
+// 5 7/18/08 5:03p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 4 7/10/08 6:33p Michaela
+// Updated to support OHCI controllers
+//
+// 3 4/16/07 1:02p Sivagarn
+// - Updated as per coding standard review
+// - In previous check-in, TIANO.H file is removed and AMIMAPPING.H file
+// is included
+//
+// 2 3/28/07 3:07a Meenakshim
+// Removed dependency on core source files..Added amimapping file.
+//
+// 1 9/22/06 4:07p Sivagarn
+// - Initial Check-in
+// - Included Recovery code in Source
+// - Included appropriate headers for flies and functions
+// - Updated copyright messages
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: PeiUsbLib.C
+//
+// Description:
+// This file belongs to "Framework" and included here for
+// compatibility purposes. This file is modified by AMI to include
+// copyright message, appropriate header and integration code.
+// This file contains generic routines needed for USB recover
+// PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+/*++
+ This file contains 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+ --*/
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ PeiUsbLib.c
+
+ Abstract:
+
+ Common Libarary for PEI USB
+
+ Revision History
+
+ --*/
+
+#include "Efi.h"
+#include "Pei.h"
+#include "usb.h"
+#include "UsbPeim.h"
+#include "PeiUsbLib.h"
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ZeroMem
+//
+// Description: This library function initializes provided buffer with Zero
+//
+// Input: *Buffer Pointer to the buffer whose content to be inited
+// Size Number of bytes to be filled in
+//
+// Output: Returns None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID ZeroMem (
+ OUT VOID *Buffer,
+ IN UINTN Size )
+{
+ UINT8 *Ptr;
+
+ Ptr = Buffer;
+ while (Size--) {
+ *(Ptr++) = 0;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PeiCopyMem
+//
+// Description:
+// This library function copies bytes specified by Length from the memory
+// location specified by Source to the memory location specified by
+// Destination.
+//
+// Input:
+// OUT VOID *Destination
+// -- Target memory location of copy
+// IN VOID *Source
+// -- Source memory location
+// IN UINTN Length
+// -- Number of bytes to copy
+//
+// Output:
+// VOID (No Return Value)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID PeiCopyMem (
+ OUT VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length )
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+
+ Destination8 = Destination;
+ Source8 = Source;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PeiUsbGetDescriptor
+//
+// Description:
+// This function uses a device's PEI_USB_IO_PPI interface to execute a
+// control transfer on the default control pipe to obtain a device
+// descriptor.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- PEI Sevices table pointer
+// IN PEI_USB_IO_PPI *UsbIoPpi
+// -- PEI_USB_IO_PPI interface pointer for the device
+// that is being accessed
+// IN UINT16 Value
+// -- The upper byte of Value specifies the type of
+// descriptor and the lower byte of Value specifies
+// the index (for configuration and string descriptors)
+// IN UINT16 Index
+// -- Specifies the Language ID for string descriptors
+// or zero for all other descriptors
+// IN UINT16 DescriptorLength
+// -- Specifies the length of the descriptor to be
+// retrieved
+// IN VOID *Descriptor
+// -- Allocated buffer in which the descriptor will be
+// returned
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+// Notes:
+// The lower byte of Value is typically zero and the upper byte of
+// Value specifies the type of descriptor:
+//
+// READ_BITS(Value,15,8) Descriptor
+// -------------------------------------------------
+// 1 DEVICE
+// 2 CONFIGURATION
+// 3 STRING
+// 4 INTERFACE
+// 5 ENDPOINT
+// 6 DEVICE_QUALIFIER
+// 7 OTHER_SPEED_CONFIGURATION
+// 8 INTERFACE_POWER
+//
+// For additional reference, read the USB Device Framework chapter in
+// the USB Specification (Revision 2.0)
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbGetDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 Value,
+ IN UINT16 Index,
+ IN UINT16 DescriptorLength,
+ IN VOID *Descriptor )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ UINT32 Timeout;
+
+ if (UsbIoPpi == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DevReq.RequestType = USB_DEV_GET_DESCRIPTOR_REQ_TYPE;
+ DevReq.Request = USB_DEV_GET_DESCRIPTOR;
+ DevReq.Value = Value;
+ DevReq.Index = Index;
+ DevReq.Length = DescriptorLength;
+
+ Timeout = 3000;
+
+ return UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbDataIn,
+ Timeout,
+ Descriptor,
+ DescriptorLength
+ );
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PeiUsbSetDeviceAddress
+//
+// Description:
+// This function uses a device's PEI_USB_IO_PPI interface to execute a
+// control transfer on the default control pipe to set the device's
+// address on the USB bus for all future accesses.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- PEI Sevices table pointer
+// IN PEI_USB_IO_PPI *UsbIoPpi
+// -- PEI_USB_IO_PPI interface pointer for the device
+// that is being accessed
+// IN UINT16 AddressValue
+// -- The device address to be set
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbSetDeviceAddress (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 AddressValue )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ UINT32 Timeout;
+
+ if (UsbIoPpi == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DevReq.RequestType = USB_DEV_SET_ADDRESS_REQ_TYPE;
+ DevReq.Request = USB_DEV_SET_ADDRESS;
+ DevReq.Value = AddressValue;
+ DevReq.Index = 0;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+
+ return UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0
+ );
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PeiUsbClearDeviceFeature
+//
+// Description:
+// This function uses a device's PEI_USB_IO_PPI interface to execute a
+// control transfer on the default control pipe to clear or disable a
+// specific feature.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- PEI Sevices table pointer
+// IN PEI_USB_IO_PPI *UsbIoPpi
+// -- PEI_USB_IO_PPI interface pointer for the device
+// that is being accessed
+// IN EFI_USB_RECIPIENT Recipient
+// -- The recipient of the request can be a device,
+// an interface or an endpoint respectively specified
+// by EfiUsbDevice, EfiUsbInterface or EfiUsbEndpoint.
+// IN UINT16 Value
+// -- The feature selector to be cleared or disabled
+// IN UINT16 Target
+// -- This value specifies an index for a specific
+// interface/endpoint or zero for device recipients.
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbClearDeviceFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN EFI_USB_RECIPIENT Recipient,
+ IN UINT16 Value,
+ IN UINT16 Target )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ UINT32 Timeout;
+
+ if (UsbIoPpi == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (Recipient)
+ {
+ case EfiUsbDevice:
+ DevReq.RequestType = 0x00;
+ break;
+
+ case EfiUsbInterface:
+ DevReq.RequestType = 0x01;
+ break;
+
+ case EfiUsbEndpoint:
+ DevReq.RequestType = 0x02;
+ break;
+ }
+
+ DevReq.Request = USB_DEV_CLEAR_FEATURE;
+ DevReq.Value = Value;
+ DevReq.Index = Target;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+
+ return UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0
+ );
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PeiUsbSetConfiguration
+//
+// Description:
+// This function uses a device's PEI_USB_IO_PPI interface to execute a
+// control transfer on the default control pipe to set the device's
+// default configuration index of 1.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- PEI Sevices table pointer
+// IN PEI_USB_IO_PPI *UsbIoPpi
+// -- PEI_USB_IO_PPI interface pointer for the device
+// that is being accessed
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbSetConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ UINT32 Timeout;
+
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ DevReq.RequestType = USB_DEV_SET_CONFIGURATION_REQ_TYPE;
+ DevReq.Request = USB_DEV_SET_CONFIGURATION;
+ DevReq.Value = 1; // default
+ DevReq.Index = 0;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+
+ return UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0
+ );
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PeiUsbClearEndpointHalt
+//
+// Description:
+// This function uses a device's PEI_USB_IO_PPI interface to execute a
+// control transfer on the default control pipe to clear a bulk Endpoint
+// halt condition (and resetting the Halt status bit) for a specified
+// Endpoint.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- PEI Sevices table pointer
+// IN PEI_USB_IO_PPI *UsbIoPpi
+// -- PEI_USB_IO_PPI interface pointer for the device
+// that is being accessed
+// IN UINT8 EndpointAddress
+// -- The endpoint for which the Halt condition is to be
+// cleared
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbClearEndpointHalt (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 EndpointAddress )
+{
+ EFI_STATUS Status;
+ PEI_USB_DEVICE *PeiUsbDev;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
+ UINT8 EndpointIndex = 0;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS( UsbIoPpi );
+
+ while (EndpointIndex < MAX_ENDPOINT) {
+ Status = UsbIoPpi->UsbGetEndpointDescriptor( PeiServices, UsbIoPpi,
+ EndpointIndex, &EndpointDescriptor );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EndpointDescriptor->EndpointAddress == EndpointAddress) {
+ break;
+ }
+
+ EndpointIndex++;
+ }
+
+ if (EndpointIndex == MAX_ENDPOINT) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PeiUsbClearDeviceFeature(
+ PeiServices,
+ UsbIoPpi,
+ EfiUsbEndpoint,
+ EfiUsbEndpointHalt,
+ EndpointAddress
+ );
+
+ //
+ // set data toggle to zero.
+ //
+ if ( ( PeiUsbDev->DataToggle & (1 << EndpointIndex) ) != 0 ) {
+ PeiUsbDev->DataToggle =
+ (UINT8) ( PeiUsbDev->DataToggle ^ (1 << EndpointIndex) );
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IsPortConnect
+//
+// Description:
+// This function returns true if the Hub Class device's Current Connect
+// Status bit is set in the port status value specified by PortStatus.
+//
+// Input:
+// IN UINT16 PortStatus
+// -- This value is the USB Specification (Revision 2.0)
+// Hub Port Status Field value as returned by the Get
+// Port Status Hub Class device standard request.
+//
+// Output:
+// BOOLEAN (Return Value)
+// = TRUE if a device is present or FALSE if a device is not
+// present
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsPortConnect (
+ IN UINT16 PortStatus )
+{
+ //
+ // return the bit 0 value of PortStatus
+ //
+ if ( (PortStatus & USB_PORT_STAT_CONNECTION) != 0 ) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IsPortEnable
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsPortEnable (
+ IN UINT16 PortStatus )
+{
+ //
+ // return the bit 0 value of PortStatus
+ //
+ if ( (PortStatus & USB_PORT_STAT_ENABLE) != 0 ) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IsPortLowSpeedDeviceAttached
+//
+// Description:
+// This function returns true if the Hub Class device's Low-Speed
+// Device Attached bit is set in the port status value specified by
+// PortStatus.
+//
+// Input:
+// IN UINT16 PortStatus
+// -- This value is the USB Specification (Revision 2.0)
+// Hub Port Status Field value as returned by the Get
+// Port Status Hub Class device standard request.
+//
+// Output:
+// BOOLEAN (Return Value)
+// = TRUE if a low-speed device is present or FALSE otherwise
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsPortLowSpeedDeviceAttached (
+ UINT16 PortStatus )
+{
+ //
+ // return the bit 9 value of PortStatus
+ //
+ if ( (PortStatus & USB_PORT_STAT_LOW_SPEED) != 0 ) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IsPortHighSpeedDeviceAttached
+//
+// Description:
+// This function returns true if the Hub Class device's High-Speed
+// Device Attached bit is set in the port status value specified by
+// PortStatus.
+//
+// Input:
+// IN UINT16 PortStatus
+// -- This value is the USB Specification (Revision 2.0)
+// Hub Port Status Field value as returned by the Get
+// Port Status Hub Class device standard request.
+//
+// Output:
+// BOOLEAN (Return Value)
+// = TRUE if a high-speed device is present or FALSE otherwise
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsPortHighSpeedDeviceAttached (
+ UINT16 PortStatus )
+{
+ //
+ // return the bit 10 value of PortStatus
+ //
+ if ( (PortStatus & USB_PORT_STAT_HIGH_SPEED) != 0 ) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IsPortSuperSpeedDeviceAttached
+//
+// Description:
+// This function returns true if connect status indicates the SuperSpeed
+// device.
+//
+// Output:
+// BOOLEAN (Return Value)
+// = TRUE if a super-speed device is present or FALSE otherwise
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsPortSuperSpeedDeviceAttached (
+ UINT16 PortStatus )
+{
+ //
+ // return the bit 10 value of PortStatus
+ //
+ if ( (PortStatus & USB_PORT_STAT_SUPER_SPEED) != 0 ) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IsPortConnectChange
+//
+// Description:
+// This function returns true if the Hub Class device's Connect Status
+// Change bit is set in the port change status value specified
+// by PortChangeStatus.
+//
+// Input:
+// IN UINT16 PortStatus
+// -- This value is the USB Specification (Revision 2.0)
+// Hub Port Change Field value as returned by the Get
+// Port Status Hub Class device standard request.
+//
+// Output:
+// BOOLEAN (Return Value)
+// = TRUE if Current Connect status has changed or FALSE
+// if no change has occurred to Current Connect status
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsPortConnectChange (
+ UINT16 PortChangeStatus )
+{
+ //
+ // return the bit 0 value of PortChangeStatus
+ //
+ if ( (PortChangeStatus & USB_PORT_STAT_C_CONNECTION) != 0 ) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+
+#ifndef PI_SPECIFICATION_VERSION //old Core
+
+EFI_STATUS PciCfgModify(
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN SetBits,
+ IN UINTN ClearBits)
+{
+ if((*PeiServices)->PciCfg==NULL)
+ return EFI_NOT_AVAILABLE_YET;
+
+ return (*PeiServices)->PciCfg->Modify(
+ (EFI_PEI_SERVICES**)PeiServices,
+ (*PeiServices)->PciCfg,
+ Width, Address,
+ SetBits, ClearBits);
+}
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/UsbRecovery/PeiUsbLib.h b/Core/EM/UsbRecovery/PeiUsbLib.h
new file mode 100644
index 0000000..d6c14dd
--- /dev/null
+++ b/Core/EM/UsbRecovery/PeiUsbLib.h
@@ -0,0 +1,171 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/PeiUsbLib.h 5 11/24/12 5:43a Ryanchou $
+//
+// $Revision: 5 $
+//
+// $Date: 11/24/12 5:43a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/PeiUsbLib.h $
+//
+// 5 11/24/12 5:43a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 4 10/11/10 4:51p Olegi
+// XHCI support added.
+//
+// 3 3/17/09 5:10p Olegi
+//
+// 2 7/10/08 6:33p Michaela
+// Updated to support OHCI controllers
+//
+// 1 9/22/06 4:07p Sivagarn
+// - Initial Check-in
+// - Included Recovery code in Source
+// - Included appropriate headers for flies and functions
+// - Updated copyright messages
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: PeiUsbLib.H
+//
+// Description: This file belongs to "Framework" and included here for
+// compatibility purposes. This file is modified by AMI to include
+// copyright message, appropriate header and integration code.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//
+// This file contains 'Framework Code' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may not be modified, except as allowed by
+// additional terms of your license agreement.
+//
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ PeiUsbLib.h
+
+ Abstract:
+
+ Common Libarary for PEI USB
+
+ Revision History
+
+ --*/
+
+#ifndef _PEI_USB_LIB_H
+#define _PEI_USB_LIB_H
+
+EFI_STATUS
+PeiUsbGetDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 Value,
+ IN UINT16 Index,
+ IN UINT16 DescriptorLength,
+ IN VOID *Descriptor );
+
+EFI_STATUS
+PeiUsbSetDeviceAddress (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 AddressValue );
+
+EFI_STATUS
+PeiUsbClearDeviceFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN EFI_USB_RECIPIENT Recipient,
+ IN UINT16 Value,
+ IN UINT16 Target );
+
+EFI_STATUS
+PeiUsbSetConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi );
+
+EFI_STATUS
+PeiUsbClearEndpointHalt (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 EndpointAddress );
+
+BOOLEAN
+IsPortConnect (
+ UINT16 PortStatus );
+
+BOOLEAN
+IsPortEnable (
+ UINT16 PortStatus );
+
+BOOLEAN
+IsPortLowSpeedDeviceAttached (
+ UINT16 PortStatus );
+
+BOOLEAN
+IsPortHighSpeedDeviceAttached (
+ UINT16 PortStatus );
+
+BOOLEAN
+IsPortSuperSpeedDeviceAttached (
+ UINT16 PortStatus );
+
+BOOLEAN
+IsPortConnectChange (
+ UINT16 PortChangeStatus );
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/USBRecoverySrc.chm b/Core/EM/UsbRecovery/USBRecoverySrc.chm
new file mode 100644
index 0000000..fdee69a
--- /dev/null
+++ b/Core/EM/UsbRecovery/USBRecoverySrc.chm
Binary files differ
diff --git a/Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.c b/Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.c
new file mode 100644
index 0000000..ee535dd
--- /dev/null
+++ b/Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.c
@@ -0,0 +1,3575 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UhcPeimSrc/UhcPeim.c 17 11/24/12 5:45a Ryanchou $
+//
+// $Revision: 17 $
+//
+// $Date: 11/24/12 5:45a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UhcPeimSrc/UhcPeim.c $
+//
+// 17 11/24/12 5:45a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 16 8/23/12 10:00p Wilsonlee
+// [TAG] EIP97069
+// [Category] Improvement
+// [Description] Reset root port algorythm update.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// UhcPeim.h, UsbPeim.c, usb.h
+//
+// 15 1/18/11 1:01a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 14 10/22/10 2:53a Rameshr
+// [TAG]- EIP 43687
+// [Category]-IMPROVEMENT
+// [Description]- Build warning from UsbRecovery driver -
+// UsbHostController.obj : warning LNK4221: no public symbols found;
+// archive member will be inaccessible.
+// [Files]- uhcpeim.c, usbpeim.c, UsbHostcontroller.h
+//
+// 13 10/12/10 11:19a Olegi
+// XHCI support added.
+//
+// 12 4/06/10 3:32p Fasihm
+// EIP#31987 - Added the generic USBRecovery Fix in the module.
+//
+// 11 4/29/09 2:13p Olegi
+// Added TreansactionTranslator to UHCI Bulk transfer.
+//
+// 10 3/17/09 5:06p Olegi
+// Added TransactionTranslator for slow/full speed devices behind USB2
+// hub.
+//
+// 9 3/03/09 7:20p Olegi
+// Changed the type of MaxPktSize from UINT8 to UINT16.
+//
+// 8 11/19/08 12:03p Rameshraju
+// Continue to initilize other UCHI controllers on the system when Uchi
+// controller initilization is failed.
+//
+// 7 10/23/08 2:00p Michaela
+// Removed UsbDebug.h include
+//
+// 6 10/21/08 5:57p Michaela
+// Added EHCI-related fixes for issues
+// that may occur if EHCI is used before
+// USB Recovery is invoked:
+// Added SDL Tokens:
+// PEI_EHCI_PCI_BDFS and
+// PEI_EHCI_MEM_BASE_ADDRESSES.
+//
+// Removed/modified some debugging
+// development code:
+// Removed SDL Tokens:
+// USBR_DEBUG_SUPPORT and
+// USBR_SERIAL_PORT_AVAILABLE
+// Removed Elinks:
+// UsbRecoveryDebug_DIR and
+// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+// Modified SDL Token:
+// FORCE_RECOVERY to default value of 0.
+//
+// (See this module's Help documentation
+// for more information.)
+//
+// 5 7/18/08 5:05p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 4 7/10/08 6:37p Michaela
+// Updated to support OHCI controllers
+//
+// 3 10/23/07 5:40p Ambikas
+//
+// 2 8/17/07 4:06p Ambikas
+//
+// 1 9/22/06 12:21p Sivagarn
+// - Initial Check-in
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UhcPeim.C
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+// This file contains generic routines needed for USB recovery
+// PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+/*++
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+ --*/
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ UhcPeim.c
+
+ Abstract:
+
+ Usb Host Controller PEIM
+
+ --*/
+
+#include "UhcPeim.h"
+
+#include EFI_PPI_DEFINITION( LoadFile )
+//#include "PeiUsbLib.h"
+
+EFI_GUID guidGetUhciController = EFI_PEI_GET_UHCI_CTRLER_GUID;
+static EFI_GUID gPeiStallPpiGuid = EFI_PEI_STALL_PPI_GUID;
+EFI_GUID gPeiCpuIoPpiInServiceTableGuid =
+ EFI_PEI_CPU_IO_PPI_INSTALLED_GUID;
+
+#define PAGESIZE 4096
+#include EFI_PPI_DEFINITION( LoadFile )
+
+
+//
+// PEIM Entry Ppint
+//
+EFI_STATUS
+UhcPeimEntry (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+
+
+UINT32
+USBReadPortDW (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 Port );
+void
+PrintTD (
+ TD_STRUCT *ptrTD,
+ USB_UHC_DEV *UhcDev );
+void
+PrintQH (
+ QH_STRUCT *ptrQH,
+ USB_UHC_DEV *UhcDev );
+
+extern VOID ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size );
+
+
+EFI_STATUS UhcPeimEntry (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ PEI_CPU_IO_PPI *CpuIoPpi;
+ PEI_STALL_PPI *StallPpi;
+ EFI_PEI_USB_CONTROLLER_PPI *ChipSetUsbControllerPpi;
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINTN ControllerType;
+ UINTN BaseAddress;
+ USB_UHC_DEV *UhcDev;
+
+ // Locate the PEI_CPU_IO_PPI interface
+ if ( EFI_ERROR( (**PeiServices).LocatePpi(
+ PeiServices, &gPeiCpuIoPpiInServiceTableGuid, 0, NULL,
+ &CpuIoPpi ) ) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ // Locate the PEI_STALL_PPI interface
+ if ( EFI_ERROR( (**PeiServices).LocatePpi(
+ PeiServices, &gPeiStallPpiGuid, 0, NULL, &StallPpi ) ) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ // Locate the EFI_PEI_USB_CONTROLLER_PPI interface
+ if ( EFI_ERROR( (**PeiServices).LocatePpi(
+ PeiServices, &guidGetUhciController, 0, NULL,
+ &ChipSetUsbControllerPpi ) ) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //--------------------------------------------------
+ // For each UHCI controller found:
+ //
+ // 1) Verify it is a UHCI controller
+ // 2) Allocate and initialize a USB_UHC_DEV structure
+ // to manage the controller.
+ // 3) Initialize the controller.
+ // 4) Install the PEI_USB_HOST_CONTROLLER_PPI interface.
+ //
+ //--------------------------------------------------
+ Index = 0;
+ while (TRUE) {
+
+ // GetUhciControllerPpi() returns error if no more controllers
+ if ( EFI_ERROR( ChipSetUsbControllerPpi->GetUhciControllerPpi(
+ PeiServices, ChipSetUsbControllerPpi, Index,
+ &ControllerType,
+ &BaseAddress ) ) ) {
+ break;
+ }
+
+ // This PEIM is for UHC type controller.
+ if (ControllerType != PEI_UHCI_CONTROLLER) {
+ Index++;
+ continue;
+ }
+
+ // Allocate and initialize USB_UHC_DEV members
+ if ( EFI_ERROR( (**PeiServices).AllocatePages(
+ PeiServices, EfiConventionalMemory,
+ sizeof(USB_UHC_DEV) / PAGESIZE + 1,
+ (EFI_PHYSICAL_ADDRESS *) &UhcDev ) ) ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ UhcDev->Signature = USB_UHC_DEV_SIGNATURE;
+ UhcDev->PeiServices = PeiServices;
+ UhcDev->CpuIoPpi = (*PeiServices)->CpuIo;
+ UhcDev->StallPpi = StallPpi;
+ UhcDev->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
+
+ // Initialize Uhc's hardware
+ Status = InitializeUsbHC( UhcDev );
+ if ( EFI_ERROR( Status ) ) {
+ PEI_TRACE( (EFI_D_ERROR, PeiServices,
+ "UHCPEIM: BaseAddress %x\n", BaseAddress) );
+ PEI_TRACE( (EFI_D_ERROR, PeiServices,
+ "UHCPEIM: InitializeUSbHC Status %r\n", Status) );
+ // error in initilizing the controller , so try for next controller
+ Index++;
+ continue;
+ }
+
+ // Init local memory management service
+ Status = InitializeMemoryManagement( UhcDev );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ // Update PEI_USB_HOST_CONTROLLER_PPI members
+ UhcDev->UsbHostControllerPpi.ControlTransfer = UhcControlTransfer;
+ UhcDev->UsbHostControllerPpi.BulkTransfer = UhcBulkTransfer;
+ UhcDev->UsbHostControllerPpi.GetRootHubPortNumber =
+ UhcGetRootHubPortNumber;
+ UhcDev->UsbHostControllerPpi.GetRootHubPortStatus =
+ UhcGetRootHubPortStatus;
+ UhcDev->UsbHostControllerPpi.SetRootHubPortFeature =
+ UhcSetRootHubPortFeature;
+ UhcDev->UsbHostControllerPpi.ClearRootHubPortFeature =
+ UhcClearRootHubPortFeature;
+ UhcDev->UsbHostControllerPpi.PreConfigureDevice = NULL;
+ UhcDev->UsbHostControllerPpi.EnableEndpoints = NULL;
+
+ // Install the PEI_USB_HOST_CONTROLLER_PPI interface
+ // for this controller
+ UhcDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI
+ |
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ UhcDev->PpiDescriptor.Guid = &gPeiUsbHostControllerPpiGuid;
+ UhcDev->PpiDescriptor.Ppi = &UhcDev->UsbHostControllerPpi;
+ if ( EFI_ERROR( (**PeiServices).InstallPpi(
+ PeiServices, &UhcDev->PpiDescriptor ) ) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Index++;
+ }
+
+ PEI_TRACE( (EFI_D_ERROR, PeiServices, "UHCPEIM: Exit() \n") );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS UhcControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult )
+{
+ USB_UHC_DEV *UhcDev;
+ UINT32 StatusReg;
+ UINT32 FrameNumReg;
+ UINT8 PktID;
+ QH_STRUCT *ptrQH;
+ TD_STRUCT *ptrTD;
+ TD_STRUCT *ptrPreTD;
+ TD_STRUCT *ptrSetupTD;
+ TD_STRUCT *ptrStatusTD;
+ EFI_STATUS Status;
+ UINTN i;
+ UINT32 DataLen;
+ UINT8 *ptrDataSource;
+ UINT8 *ptr;
+ UINT8 DataToggle;
+ UINT16 LoadFrameListIndex;
+
+ UhcDev = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS( This );
+
+ StatusReg = UhcDev->UsbHostControllerBaseAddress + USBSTS;
+ FrameNumReg = UhcDev->UsbHostControllerBaseAddress + USBFRNUM;
+
+ PktID = INPUT_PACKET_ID;
+ // PEI_TRACE ((EFI_D_ERROR, PeiServices, "Enter UhcControlTransfer\n"));
+
+ if (Request == NULL || TransferResult == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if errors exist that cause host controller halt,
+ // then return EFI_DEVICE_ERROR.
+ //
+ if ( IsHCHalted( UhcDev, StatusReg ) ||
+ IsHCProcessErr( UhcDev, StatusReg ) ||
+ IsHostSysErr( UhcDev, StatusReg ) ) {
+
+ ClearStatusReg( UhcDev, StatusReg );
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ PEI_TRACE( (EFI_D_ERROR, PeiServices, "UHCIPEIM: Ctrler halted\n") );
+ return EFI_DEVICE_ERROR;
+ }
+
+ ClearStatusReg( UhcDev, StatusReg );
+
+ //
+ // Setup Stage of Control Transfer
+ //
+
+ //
+ // create QH structure and init
+ //
+ Status = CreateQH( UhcDev, &ptrQH );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ //
+ // generate Setup Stage TD
+ //
+
+ GenSetupStageTD( UhcDev, DeviceAddress, 0,
+ DeviceSpeed, (UINT8 *) Request,
+ sizeof(EFI_USB_DEVICE_REQUEST), &ptrSetupTD );
+
+ //
+ // link setup TD structures to QH structure
+ //
+ LinkTDToQH( ptrQH, ptrSetupTD );
+
+ ptrPreTD = ptrSetupTD;
+
+ //
+ // Data Stage of Control Transfer
+ //
+ switch (TransferDirection)
+ {
+
+ case EfiUsbDataIn:
+ PktID = INPUT_PACKET_ID;
+ ptrDataSource = Data;
+ DataLen = (UINT32) *DataLength;
+ ptr = ptrDataSource;
+ break;
+
+ case EfiUsbDataOut:
+ PktID = OUTPUT_PACKET_ID;
+ ptrDataSource = Data;
+ DataLen = (UINT32) *DataLength;
+ ptr = ptrDataSource;
+ break;
+
+ //
+ // no data stage
+ //
+ case EfiUsbNoData:
+ if (*DataLength != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PktID = OUTPUT_PACKET_ID;
+ ptrDataSource = NULL;
+ DataLen = 0;
+ ptr = NULL;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DataToggle = 1;
+
+ ptrTD = ptrSetupTD;
+ while (DataLen > 0) {
+
+ //
+ // create TD structures and link together
+ //
+
+ UINT8 pktsize;
+
+ //
+ // pktsize is the data load size of each TD carries.
+ //
+ pktsize = (UINT8) DataLen;
+ if (DataLen > MaximumPacketLength) {
+ pktsize = MaximumPacketLength;
+ }
+ GenDataTD( UhcDev, DeviceAddress, 0, ptr, pktsize, PktID, DataToggle,
+ DeviceSpeed, &ptrTD );
+
+ //
+ // Link two TDs in vertical depth
+ //
+ LinkTDToTD( ptrPreTD, ptrTD );
+ ptrPreTD = ptrTD;
+
+ DataToggle ^= 1;
+ ptr += pktsize;
+ DataLen -= pktsize;
+ }
+
+ //
+ // ptrPreTD points to the last TD before the Setup-Stage TD.
+ //
+ ptrPreTD = ptrTD;
+
+ //
+ // Status Stage of Control Transfer
+ //
+ if (PktID == OUTPUT_PACKET_ID) {
+ PktID = INPUT_PACKET_ID;
+ }
+ else {
+ PktID = OUTPUT_PACKET_ID;
+ }
+ //
+ // create Status Stage TD structure
+ //
+ CreateStatusTD( UhcDev,
+ DeviceAddress,
+ 0,
+ PktID,
+ DeviceSpeed,
+ &ptrStatusTD );
+
+ LinkTDToTD( ptrPreTD, ptrStatusTD );
+
+ //
+ // get the frame list index that the QH-TDs will be linked to.
+ //
+ LoadFrameListIndex = (UINT16) ( ( GetCurrentFrameNumber
+ ( UhcDev, FrameNumReg ) ) % 1024 );
+
+ //
+ // link QH-TDs to total 500 frame list entry to speed up the execution.
+ //
+ for (i = 0; i < 500; i++) {
+
+ //
+ // put the QH-TDs directly or indirectly into the proper place in
+ // the Frame List
+ //
+ LinkQHToFrameList( UhcDev->FrameListEntry,
+ (UINT16) ( (LoadFrameListIndex + i) % 1024 ), ptrQH );
+ }
+
+ //
+ // Poll QH-TDs execution and get result.
+ // detail status is returned
+ //
+ //TimeOut = 1000; //bala
+
+ Status = ExecuteControlTransfer( UhcDev, ptrSetupTD,
+ LoadFrameListIndex, DataLength,
+ TimeOut, TransferResult );
+ //
+ // TRUE means must search other framelistindex
+ //
+ DeleteSingleQH( UhcDev, ptrQH, LoadFrameListIndex, TRUE );
+ DeleteQueuedTDs( UhcDev, ptrSetupTD );
+
+ //
+ // if has errors that cause host controller halt, then return
+ // EFI_DEVICE_ERROR directly.
+ //
+ if ( IsHCHalted( UhcDev, StatusReg ) ||
+ IsHCProcessErr( UhcDev, StatusReg ) ||
+ IsHostSysErr( UhcDev, StatusReg ) ) {
+
+ ClearStatusReg( UhcDev, StatusReg );
+ *TransferResult |= EFI_USB_ERR_SYSTEM;
+ PEI_TRACE( (EFI_D_ERROR, PeiServices,
+ "UHCIPEIM: Ctrl transfer failed\n") );
+ return EFI_DEVICE_ERROR;
+ }
+
+ ClearStatusReg( UhcDev, StatusReg );
+
+ // PEI_TRACE ((EFI_D_ERROR, PeiServices, "Exit UhcControlTransfer\n"));
+ return Status;
+}
+
+
+void PrintTD (
+ TD_STRUCT *ptrTD,
+ USB_UHC_DEV *UhcDev )
+{
+ EFI_PEI_SERVICES **PeiServices;
+ UINT8 i;
+ UINT32 *Tmp;
+
+ PeiServices = UhcDev->PeiServices;
+ PEI_TRACE( (EFI_D_ERROR, PeiServices, "UHCPIM: TD ... \n") );
+
+ Tmp = (UINT32 *) ptrTD;
+ for (i = 0; i < 4; i++)
+ {
+ PEI_TRACE( (EFI_D_ERROR, PeiServices, " %x", Tmp[i]) );
+
+ }
+ PEI_TRACE( (EFI_D_ERROR, PeiServices, "\n") );
+
+}
+
+
+void PrintQH (
+ QH_STRUCT *ptrQH,
+ USB_UHC_DEV *UhcDev )
+{
+ EFI_PEI_SERVICES **PeiServices;
+ UINT8 i;
+ UINT32 *Tmp;
+
+ PeiServices = UhcDev->PeiServices;
+ PEI_TRACE( (EFI_D_ERROR, PeiServices, "UHCPIM: QH ... \n") );
+
+ Tmp = (UINT32 *) ptrQH;
+ for (i = 0; i < 2; i++)
+ {
+ PEI_TRACE( (EFI_D_ERROR, PeiServices, " %x", Tmp[i]) );
+
+ }
+ PEI_TRACE( (EFI_D_ERROR, PeiServices, "\n") );
+
+}
+
+
+EFI_STATUS UhcBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT16 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult )
+{
+ USB_UHC_DEV *UhcDev;
+ UINT32 StatusReg;
+ UINT32 FrameNumReg;
+
+ UINT32 DataLen;
+
+ QH_STRUCT *ptrQH;
+ TD_STRUCT *ptrFirstTD;
+ TD_STRUCT *ptrTD;
+ TD_STRUCT *ptrPreTD;
+
+ UINT16 LoadFrameListIndex;
+ UINT16 SavedFrameListIndex;
+
+ UINT8 PktID;
+ UINT8 *ptrDataSource;
+ UINT8 *ptr;
+
+ BOOLEAN IsFirstTD;
+
+ EFI_STATUS Status;
+ UINT32 i;
+
+ EFI_USB_DATA_DIRECTION TransferDirection;
+ //
+ // Used to calculate how many entries are linked to the specified bulk
+ // transfer QH-TDs
+ //
+ UINT32 LinkTimes;
+
+ BOOLEAN ShortPacketEnable;
+
+ UINT16 CommandContent;
+
+ UhcDev = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS( This );
+
+ //
+ // Enable the maximum packet size (64bytes)
+ // that can be used for full speed bandwidth reclamation
+ // at the end of a frame.
+ //
+ CommandContent = USBReadPortW( UhcDev,
+ UhcDev->UsbHostControllerBaseAddress + USBCMD );
+
+ if ( (CommandContent & USBCMD_MAXP) != USBCMD_MAXP ) {
+ CommandContent |= USBCMD_MAXP;
+ USBWritePortW( UhcDev, UhcDev->UsbHostControllerBaseAddress + USBCMD,
+ CommandContent );
+
+ }
+
+ StatusReg = UhcDev->UsbHostControllerBaseAddress + USBSTS;
+ FrameNumReg = UhcDev->UsbHostControllerBaseAddress + USBFRNUM;
+
+ //
+ // these code lines are added here per complier's strict demand
+ //
+ PktID = INPUT_PACKET_ID;
+ ptrTD = NULL;
+ ptrFirstTD = NULL;
+ ptrPreTD = NULL;
+ LinkTimes = 1;
+ DataLen = 0;
+ ptr = NULL;
+
+ ShortPacketEnable = FALSE;
+
+ if ( (DataLength == 0) || (Data == NULL)
+ || (TransferResult == NULL) ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( (*DataToggle != 1) && (*DataToggle != 0) ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MaximumPacketLength != 8 && MaximumPacketLength != 16
+ && MaximumPacketLength != 32 && MaximumPacketLength != 64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if has errors that cause host controller halt, then return
+ // EFI_DEVICE_ERROR directly.
+ //
+ if ( IsHCHalted( UhcDev, StatusReg ) ||
+ IsHCProcessErr( UhcDev, StatusReg ) ||
+ IsHostSysErr( UhcDev, StatusReg ) ) {
+
+ ClearStatusReg( UhcDev, StatusReg );
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+
+ ClearStatusReg( UhcDev, StatusReg );
+
+ //
+ // construct QH and TD data structures,
+ // and link them together
+ //
+ if (EndPointAddress & 0x80) {
+ TransferDirection = EfiUsbDataIn;
+ }
+ else {
+ TransferDirection = EfiUsbDataOut;
+ }
+
+ switch (TransferDirection)
+ {
+
+ case EfiUsbDataIn:
+ ShortPacketEnable = TRUE;
+ PktID = INPUT_PACKET_ID;
+ ptrDataSource = Data;
+ DataLen = (UINT32) *DataLength;
+ ptr = ptrDataSource;
+ break;
+
+ case EfiUsbDataOut:
+ PktID = OUTPUT_PACKET_ID;
+ ptrDataSource = Data;
+ DataLen = (UINT32) *DataLength;
+ ptr = ptrDataSource;
+ break;
+ }
+
+ //
+ // create QH structure and init
+ //
+ Status = CreateQH( UhcDev, &ptrQH );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ //
+ // Self link the QH, to make NAK TD retried in one frame.
+ //
+ //SelfLinkBulkTransferQH (ptrQH);
+
+ //
+ // i is used to calculate the total number of TDs.
+ //
+ i = 0;
+
+ IsFirstTD = TRUE;
+ while (DataLen > 0) {
+
+ //
+ // create TD structures and link together
+ //
+ UINT16 pktsize;
+
+ pktsize = (UINT16) DataLen;
+ if (DataLen > MaximumPacketLength) {
+ pktsize = MaximumPacketLength;
+ }
+ GenDataTD( UhcDev, DeviceAddress, EndPointAddress, ptr,
+ pktsize, PktID, *DataToggle, USB_FULL_SPEED_DEVICE, &ptrTD );
+
+ //
+ // Enable short packet detection.
+ // (default action is disabling short packet detection)
+ //
+ if (ShortPacketEnable) {
+ EnableorDisableTDShortPacket( ptrTD, TRUE );
+ }
+
+ if (IsFirstTD) {
+ ptrFirstTD = ptrTD;
+ ptrFirstTD->ptrNextTD = NULL;
+ IsFirstTD = FALSE;
+ }
+ else {
+ //
+ // Link two TDs in vertical depth
+ //
+ LinkTDToTD( ptrPreTD, ptrTD );
+ }
+
+ i++;
+
+ ptrPreTD = ptrTD;
+
+ *DataToggle ^= 1;
+ ptr += pktsize;
+ DataLen -= pktsize;
+ }
+
+ //
+ // link TD structures to QH structure
+ //
+ LinkTDToQH( ptrQH, ptrFirstTD );
+
+ //
+ // calculate how many entries are linked to the specified bulk
+ // transfer QH-TDs the below values are referred to the USB spec
+ // revision1.1.
+ //
+ switch (MaximumPacketLength)
+ {
+ case 8:
+ LinkTimes = i / 71 + 1;
+ break;
+
+ case 16:
+ LinkTimes = i / 51 + 1;
+ break;
+
+ case 32:
+ LinkTimes = i / 33 + 1;
+ break;
+
+ case 64:
+ LinkTimes = i / 19 + 1;
+ break;
+ }
+ LinkTimes += 200; // redundant
+
+ //
+ // put QH-TDs into Frame list
+ //
+
+ LoadFrameListIndex = (UINT16)
+ ( ( GetCurrentFrameNumber( UhcDev,
+ FrameNumReg ) ) % 1024 );
+ SavedFrameListIndex = LoadFrameListIndex;
+
+ for (i = 0; i <= LinkTimes; i++) {
+
+ //
+ // put the QH-TD directly or indirectly into the proper
+ // place in the Frame List
+ //
+ LinkQHToFrameList( UhcDev->FrameListEntry, LoadFrameListIndex, ptrQH );
+
+ LoadFrameListIndex += 1;
+ LoadFrameListIndex %= 1024;
+ }
+
+ LoadFrameListIndex = SavedFrameListIndex;
+
+ //
+ // Execute QH-TD and get result
+ //
+ //
+ // detail status is put into the Result field in the pIRP
+ // the Data Toggle value is also re-updated to the value
+ // of the last successful TD
+ //
+ Status = ExecBulkTransfer( UhcDev, ptrFirstTD,
+ LoadFrameListIndex, DataLength,
+ DataToggle, TimeOut, TransferResult );
+
+ //
+ // Delete Bulk transfer QH-TD structure
+ // and maitain the pointers in the Frame List
+ // and other pointers in related QH structure
+ //
+
+
+ // TRUE means must search other framelistindex
+ DeleteSingleQH( UhcDev, ptrQH, LoadFrameListIndex, TRUE );
+ DeleteQueuedTDs( UhcDev, ptrFirstTD );
+
+ //
+ // if has errors that cause host controller halt, then
+ // return EFI_DEVICE_ERROR directly.
+ //
+ if ( IsHCHalted( UhcDev, StatusReg ) ||
+ IsHCProcessErr( UhcDev, StatusReg ) ||
+ IsHostSysErr( UhcDev, StatusReg ) ) {
+
+ ClearStatusReg( UhcDev, StatusReg );
+ *TransferResult |= EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+
+ ClearStatusReg( UhcDev, StatusReg );
+
+ return Status;
+}
+
+
+EFI_STATUS UhcGetRootHubPortNumber (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *PortNumber )
+{
+ USB_UHC_DEV *UhcDev;
+ UINT32 PSAddr;
+ UINT16 RHPortControl;
+ UINT32 i;
+
+ UhcDev = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS( This );
+
+ if (PortNumber == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *PortNumber = 0;
+
+ for (i = 0; i < 2; i++) {
+ PSAddr = UhcDev->UsbHostControllerBaseAddress + USBPORTSC1 + i * 2;
+ //RHPortControl = ReadRootPortReg(UhcDev->CpuIoPpi,PSAddr);
+ RHPortControl = USBReadPortW( UhcDev, PSAddr );
+ //
+ // Port Register content is valid
+ //
+ if (RHPortControl != 0xff) {
+ (*PortNumber)++;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS UhcGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus )
+{
+ USB_UHC_DEV *UhcDev;
+ UINT32 PSAddr;
+ UINT16 RHPortStatus; // root hub port status
+ UINT8 TotalPortNumber;
+
+ if (PortStatus == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UhcGetRootHubPortNumber( PeiServices, This, &TotalPortNumber );
+ if (PortNumber > TotalPortNumber) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UhcDev = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS( This );
+ PSAddr = UhcDev->UsbHostControllerBaseAddress +
+ USBPORTSC1 + (PortNumber - 1) * 2;
+
+ PortStatus->PortStatus = 0;
+ PortStatus->PortChangeStatus = 0;
+
+ //RHPortStatus = ReadRootPortReg (UhcDev->CpuIoPpi,PSAddr) ;
+ RHPortStatus = USBReadPortW( UhcDev, PSAddr );
+
+ //
+ // Fill Port Status bits
+ //
+
+ //
+ // Current Connect Status
+ //
+ if (RHPortStatus & USBPORTSC_CCS) {
+ PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+
+ //
+ // Port Enabled/Disabled
+ //
+ if (RHPortStatus & USBPORTSC_PED) {
+ PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
+ }
+
+ //
+ // Port Suspend
+ //
+ if (RHPortStatus & USBPORTSC_SUSP) {
+ PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+
+ //
+ // Port Reset
+ //
+ if (RHPortStatus & USBPORTSC_PR) {
+ PortStatus->PortStatus |= USB_PORT_STAT_RESET;
+ }
+
+ //
+ // Low Speed Device Attached
+ //
+ if (RHPortStatus & USBPORTSC_LSDA) {
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+ }
+
+ //
+ // Fill Port Status Change bits
+ //
+
+ //
+ // Connect Status Change
+ //
+ if (RHPortStatus & USBPORTSC_CSC) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+
+ //
+ // Port Enabled/Disabled Change
+ //
+ if (RHPortStatus & USBPORTSC_PEDC) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
+ }
+ if (UhcDev->PortResetStatusChangeMap & (1 << (PortNumber - 1))) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
+ }
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS UhcSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature )
+{
+ USB_UHC_DEV *UhcDev;
+ UINT32 PSAddr;
+ UINT32 CommandRegAddr;
+ UINT16 RHPortControl; // root hub port status
+ UINT8 TotalPortNumber;
+
+ UhcGetRootHubPortNumber( PeiServices, This, &TotalPortNumber );
+ if (PortNumber > TotalPortNumber) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UhcDev = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS( This );
+ PSAddr = UhcDev->UsbHostControllerBaseAddress +
+ USBPORTSC1 + (PortNumber - 1) * 2;
+ CommandRegAddr = UhcDev->UsbHostControllerBaseAddress + USBCMD;
+
+ RHPortControl = USBReadPortW( UhcDev, PSAddr );
+
+ switch (PortFeature)
+ {
+
+ case EfiUsbPortSuspend:
+ if ( !(USBReadPortW( UhcDev, CommandRegAddr ) & USBCMD_EGSM) ) {
+ //
+ // if global suspend is not active, can set port suspend
+ //
+ RHPortControl &= 0xfff5;
+ RHPortControl |= USBPORTSC_SUSP;
+ }
+ break;
+
+ case EfiUsbPortReset:
+ RHPortControl &= 0xfff5;
+ RHPortControl |= USBPORTSC_PR; // Set the reset bit
+ USBWritePortW( UhcDev, PSAddr, RHPortControl );
+ UhcDev->StallPpi->Stall (UhcDev->PeiServices,UhcDev->StallPpi,10 * 1000);
+ RHPortControl = USBReadPortW( UhcDev, PSAddr );
+ RHPortControl &= 0xfff5;
+ RHPortControl &= ~USBPORTSC_PR;
+ USBWritePortW( UhcDev, PSAddr, RHPortControl );
+ UhcDev->PortResetStatusChangeMap |= (1 << (PortNumber - 1));
+ return EFI_SUCCESS;
+
+ case EfiUsbPortPower:
+ break;
+
+ case EfiUsbPortEnable:
+ RHPortControl &= 0xfff5;
+ RHPortControl |= USBPORTSC_PED;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //WriteRootPortReg(UhcDev->CpuIoPpi,PSAddr,RHPortControl) ;
+ USBWritePortW( UhcDev, PSAddr, RHPortControl );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS UhcClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature )
+{
+ USB_UHC_DEV *UhcDev;
+ UINT32 PSAddr;
+ UINT16 RHPortControl;
+ UINT8 TotalPortNumber;
+
+ UhcGetRootHubPortNumber( PeiServices, This, &TotalPortNumber );
+
+ if (PortNumber > TotalPortNumber) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UhcDev = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS( This );
+ PSAddr = UhcDev->UsbHostControllerBaseAddress +
+ USBPORTSC1 + (PortNumber - 1) * 2;
+
+ //RHPortControl = ReadRootPortReg (UhcDev->CpuIoPpi,PSAddr) ;
+ RHPortControl = USBReadPortW( UhcDev, PSAddr );
+
+ switch (PortFeature)
+ {
+
+ //
+ // clear PORT_ENABLE feature means disable port.
+ //
+ case EfiUsbPortEnable:
+ RHPortControl &= 0xfff5;
+ RHPortControl &= ~USBPORTSC_PED;
+ break;
+
+ //
+ // clear PORT_SUSPEND feature means resume the port.
+ // (cause a resume on the specified port if in suspend mode)
+ //
+ case EfiUsbPortSuspend:
+ RHPortControl &= 0xfff5;
+ RHPortControl &= ~USBPORTSC_SUSP;
+ break;
+
+ //
+ // no operation
+ //
+ case EfiUsbPortPower:
+ break;
+
+ //
+ // clear PORT_RESET means clear the reset signal.
+ //
+ case EfiUsbPortReset:
+ RHPortControl &= 0xfff5;
+ RHPortControl &= ~USBPORTSC_PR;
+ break;
+
+ //
+ // clear connect status change
+ //
+ case EfiUsbPortConnectChange:
+ RHPortControl &= 0xfff5;
+ RHPortControl |= USBPORTSC_CSC;
+ break;
+
+ //
+ // clear enable/disable status change
+ //
+ case EfiUsbPortEnableChange:
+ RHPortControl &= 0xfff5;
+ RHPortControl |= USBPORTSC_PEDC;
+ break;
+
+ //
+ // root hub does not support this request
+ //
+ case EfiUsbPortSuspendChange:
+ break;
+
+ //
+ // root hub does not support this request
+ //
+ case EfiUsbPortOverCurrentChange:
+ break;
+
+ //
+ // root hub does not support this request
+ //
+ case EfiUsbPortResetChange:
+ UhcDev->PortResetStatusChangeMap &= ~(1 << (PortNumber - 1));
+ return EFI_SUCCESS;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //WriteRootPortReg(UhcDev->CpuIoPpi,PSAddr,RHPortControl) ;
+ USBWritePortW( UhcDev, PSAddr, RHPortControl );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS InitializeUsbHC (
+ USB_UHC_DEV *UhcDev )
+{
+ EFI_STATUS Status;
+ UINT32 FrameListBaseAddrReg;
+ UINT32 StatusReg;
+ UINT32 CommandReg;
+ UINT16 Command;
+ UINTN Delay;
+
+ // Create and Initialize Frame List For the Host Controller.
+ Status = CreateFrameList( UhcDev );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ FrameListBaseAddrReg = UhcDev->UsbHostControllerBaseAddress +
+ USBFLBASEADD;
+ StatusReg = UhcDev->UsbHostControllerBaseAddress + USBSTS;
+ CommandReg = UhcDev->UsbHostControllerBaseAddress + USBCMD;
+
+ //Issue a Global reset
+ Command = USBReadPortW (UhcDev,CommandReg);
+ Command |= USBCMD_GRESET ;
+ USBWritePortW (UhcDev,CommandReg,Command);
+
+ Delay = (100 * STALL_1_MILLI_SECOND / 50) + 1;
+
+ do {
+ UhcDev->StallPpi->Stall (UhcDev->PeiServices,UhcDev->StallPpi,50);
+ } while(Delay--);
+
+ Command = USBReadPortW (UhcDev,CommandReg);
+ Command &= !USBCMD_GRESET ;
+ USBWritePortW (UhcDev,CommandReg,Command);
+
+ Delay = (100 * STALL_1_MILLI_SECOND / 50) + 1;
+
+ do {
+ UhcDev->StallPpi->Stall (UhcDev->PeiServices,UhcDev->StallPpi,50);
+ } while(Delay--);
+
+ // Set Frame List Base Address to the specific register to
+ // inform the hardware.
+ SetFrameListBaseAddress( UhcDev, FrameListBaseAddrReg,
+ (UINT32) (UINTN) (UhcDev->FrameListEntry) );
+
+ // Make the Host Controller in Run state.
+ if ( IsHostSysErr( UhcDev, StatusReg )
+ || IsHCProcessErr( UhcDev, StatusReg ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Command = USBReadPortW( UhcDev, CommandReg );
+ Command |= USBCMD_RS;
+
+ USBWritePortW( UhcDev, CommandReg, Command );
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS CreateFrameList (
+ USB_UHC_DEV *UhcDev )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS FrameListBaseAddr;
+
+ //
+ // The Frame List ocupies 4K bytes,
+ // and must be aligned on 4-Kbyte boundaries.
+ //
+ Status = ( **(UhcDev->PeiServices) ).AllocatePages(
+ UhcDev->PeiServices,
+ EfiConventionalMemory,
+ 1,
+ &FrameListBaseAddr );
+
+ if (Status != EFI_SUCCESS) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UhcDev->FrameListEntry = (FRAMELIST_ENTRY *) ( (UINTN) FrameListBaseAddr );
+
+ InitFrameList( UhcDev );
+
+ return EFI_SUCCESS;
+}
+
+
+VOID InitFrameList (
+ USB_UHC_DEV *UhcDev )
+{
+ FRAMELIST_ENTRY *FrameListPtr;
+ UINTN i;
+
+ //
+ // Validate each Frame List Entry
+ //
+ FrameListPtr = UhcDev->FrameListEntry;
+ for (i = 0; i < 1024; i++) {
+ FrameListPtr->FrameListPtrTerminate = 1;
+ FrameListPtr->FrameListPtr = 0;
+ FrameListPtr->FrameListPtrQSelect = 0;
+ FrameListPtr->FrameListRsvd = 0;
+ FrameListPtr++;
+ }
+}
+
+
+UINT16 USBReadPortW (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 Port )
+{
+ UINT16 Data;
+
+ //
+ // Perform 16bit Read
+ //
+ UhcDev->CpuIoPpi->Io.Read(
+ UhcDev->PeiServices,
+ UhcDev->CpuIoPpi,
+ EfiPeiCpuIoWidthUint16,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+
+ return Data;
+}
+
+
+VOID USBWritePortW (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 Port,
+ IN UINT16 Data )
+{
+ //
+ // Perform 16bit Write
+ //
+ UhcDev->CpuIoPpi->Io.Write(
+ UhcDev->PeiServices,
+ UhcDev->CpuIoPpi,
+ EfiPeiCpuIoWidthUint16,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+}
+
+
+VOID USBWritePortDW (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 Port,
+ IN UINT32 Data )
+{
+ //
+ // Perform 32bit Write
+ //
+
+ UhcDev->CpuIoPpi->Io.Write(
+ UhcDev->PeiServices,
+ UhcDev->CpuIoPpi,
+ EfiPeiCpuIoWidthUint32,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+}
+
+
+UINT32 USBReadPortDW (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 Port )
+{
+ UINT32 Data;
+
+ //
+ // Perform 16bit Read
+ //
+ UhcDev->CpuIoPpi->Io.Read(
+ UhcDev->PeiServices,
+ UhcDev->CpuIoPpi,
+ EfiPeiCpuIoWidthUint32,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+ return Data;
+}
+
+
+//
+// USB register-base helper functions
+//
+
+VOID ClearStatusReg (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 STSAddr )
+{
+ UINT16 UsbSts;
+
+ //
+ // Clear the content of UHC's Status Register
+ //
+ UsbSts = 0x003f;
+ USBWritePortW( UhcDev, STSAddr, UsbSts );
+ //WriteUHCStatusReg (PciIo,STSAddr,UsbSts);
+}
+
+
+BOOLEAN IsHostSysErr (
+ USB_UHC_DEV *UhcDev,
+ UINT32 StatusRegAddr )
+{
+ UINT16 StatusValue;
+
+ //
+ // Detect whether the interrupt is caused by serious error.
+ // see "UHCI Design Guid".
+ //
+ StatusValue = USBReadPortW( UhcDev, StatusRegAddr );
+
+ if (StatusValue & USBSTS_HSE) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+
+BOOLEAN IsHCProcessErr (
+ USB_UHC_DEV *UhcDev,
+ UINT32 StatusRegAddr )
+{
+ UINT16 StatusValue;
+
+ //
+ // Detect whether the interrupt is caused by fatal error.
+ // see "UHCI Design Guid".
+ //
+ StatusValue = USBReadPortW( UhcDev, StatusRegAddr );
+
+ if (StatusValue & USBSTS_HCPE) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+
+BOOLEAN IsHCHalted (
+ USB_UHC_DEV *UhcDev,
+ UINT32 StatusRegAddr )
+{
+ UINT16 StatusValue;
+
+ //
+ // Detect whether the the Host Controller is halted.
+ //
+ StatusValue = USBReadPortW( UhcDev, StatusRegAddr );
+
+ if (StatusValue & USBSTS_HCH) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+
+UINT16 GetCurrentFrameNumber (
+ USB_UHC_DEV *UhcDev,
+ UINT32 FRNUMAddr )
+{
+ //
+ // Gets value in the USB frame number register.
+ //
+
+ return (UINT16) (USBReadPortW( UhcDev, FRNUMAddr ) & 0x03ff);
+}
+
+
+VOID SetFrameListBaseAddress (
+ USB_UHC_DEV *UhcDev,
+ UINT32 FLBASEADDRReg,
+ UINT32 Addr )
+{
+ //
+ // Sets value in the USB Frame List Base Address register.
+ //
+ USBWritePortDW( UhcDev, FLBASEADDRReg, (UINT32) (Addr & 0xfffff000) );
+}
+
+
+////////////////////////////////////////////////////////////////
+//
+// QH TD related Helper Functions
+//
+////////////////////////////////////////////////////////////////
+
+//
+// functions for QH
+//
+EFI_STATUS AllocateQHStruct (
+ USB_UHC_DEV *UhcDev,
+ QH_STRUCT **ppQHStruct )
+{
+ EFI_STATUS Status;
+
+ *ppQHStruct = NULL;
+
+ Status = UhcAllocatePool( UhcDev, MEM_QH_TD_TYPE,
+ (UINT8 **) ppQHStruct, sizeof(QH_STRUCT) );
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ ZeroMem( *ppQHStruct, sizeof(QH_STRUCT) );
+
+ return EFI_SUCCESS;
+}
+
+
+VOID InitQH (
+ IN QH_STRUCT *ptrQH )
+{
+ //
+ // Make QH ready
+ //
+ SetQHHorizontalValidorInvalid( ptrQH, FALSE );
+ SetQHVerticalValidorInvalid( ptrQH, FALSE );
+}
+
+
+EFI_STATUS CreateQH (
+ USB_UHC_DEV *UhcDev,
+ QH_STRUCT **pptrQH )
+{
+ EFI_STATUS Status;
+
+ //
+ // allocate align memory for QH_STRUCT
+ //
+ Status = AllocateQHStruct( UhcDev, pptrQH );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // init each field of the QH_STRUCT
+ //
+ InitQH( *pptrQH );
+
+ return EFI_SUCCESS;
+}
+
+
+VOID SetQHHorizontalLinkPtr (
+ IN QH_STRUCT *ptrQH,
+ IN VOID *ptrNext )
+{
+ //
+ // Since the QH_STRUCT is aligned on 16-byte boundaries,
+ // Only the highest 28bit of the address is valid
+ // (take 32bit address as an example).
+ //
+ ptrQH->QH.QHHorizontalPtr = (UINT32) (UINTN) ptrNext >> 4;
+}
+
+
+VOID *GetQHHorizontalLinkPtr (
+ IN QH_STRUCT *ptrQH )
+{
+ //
+ // Restore the 28bit address to 32bit address
+ //(take 32bit address as an example)
+ //
+ return ( (VOID *) (UINTN) ( (ptrQH->QH.QHHorizontalPtr) << 4 ) );
+}
+
+
+VOID SetQHHorizontalQHorTDSelect (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bQH )
+{
+ //
+ // if QH is connected, the specified bit is set,
+ // if TD is connected, the specified bit is cleared.
+ //
+ ptrQH->QH.QHHorizontalQSelect = bQH ? 1 : 0;
+}
+
+
+VOID SetQHHorizontalValidorInvalid (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bValid )
+{
+ //
+ // Valid means the horizontal link pointer is valid,
+ // else, it's invalid.
+ //
+ ptrQH->QH.QHHorizontalTerminate = bValid ? 0 : 1;
+}
+
+
+VOID SetQHVerticalLinkPtr (
+ IN QH_STRUCT *ptrQH,
+ IN VOID *ptrNext )
+{
+ //
+ // Since the QH_STRUCT is aligned on 16-byte boundaries,
+ // Only the highest 28bit of the address is valid
+ // (take 32bit address as an example).
+ //
+ ptrQH->QH.QHVerticalPtr = (UINT32) (UINTN) ptrNext >> 4;
+}
+
+
+VOID SetQHVerticalQHorTDSelect (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bQH )
+{
+ //
+ // Set the specified bit if the Vertical Link Pointer pointing to a QH,
+ // Clear the specified bit if the Vertical Link Pointer pointing to a TD.
+ //
+ ptrQH->QH.QHVerticalQSelect = bQH ? 1 : 0;
+}
+
+
+VOID SetQHVerticalValidorInvalid (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bValid )
+{
+ //
+ // If TRUE, meaning the Vertical Link Pointer field is valid,
+ // else, the field is invalid.
+ //
+ ptrQH->QH.QHVerticalTerminate = bValid ? 0 : 1;
+}
+
+
+BOOLEAN GetQHHorizontalValidorInvalid (
+ IN QH_STRUCT *ptrQH )
+{
+ //
+ // If TRUE, meaning the Horizontal Link Pointer field is valid,
+ // else, the field is invalid.
+ //
+ return (BOOLEAN) ( !(ptrQH->QH.QHHorizontalTerminate) );
+}
+
+
+//
+// functions for TD
+//
+
+EFI_STATUS AllocateTDStruct (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT **ppTDStruct )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ *ppTDStruct = NULL;
+
+ Status = UhcAllocatePool( UhcDev, MEM_QH_TD_TYPE,
+ (UINT8 **) ppTDStruct, sizeof(TD_STRUCT) );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ ZeroMem( *ppTDStruct, sizeof (TD_STRUCT) );
+
+ return Status;
+}
+
+
+VOID InitTD (
+ IN TD_STRUCT *ptrTD )
+{
+ //
+ // Make TD ready.
+ //
+ SetTDLinkPtrValidorInvalid( ptrTD, FALSE );
+}
+
+
+EFI_STATUS CreateTD (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT **pptrTD )
+{
+ EFI_STATUS Status;
+
+ //
+ // create memory for TD_STRUCT, and align the memory.
+ //
+ Status = AllocateTDStruct( UhcDev, pptrTD );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ InitTD( *pptrTD );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS GenSetupStageTD (
+ USB_UHC_DEV *UhcDev,
+ UINT8 DevAddr,
+ UINT8 Endpoint,
+ UINT8 DeviceSpeed,
+ UINT8 *pDevReq,
+ UINT8 RequestLen,
+ TD_STRUCT **ppTD )
+{
+ TD_STRUCT *pTDStruct;
+ EFI_STATUS Status;
+
+ Status = CreateTD( UhcDev, &pTDStruct );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ SetTDLinkPtr( pTDStruct, NULL );
+
+ //
+ // Depth first fashion
+ //
+ SetTDLinkPtrDepthorBreadth( pTDStruct, TRUE );
+
+ //SetTDLinkPtrQHorTDSelect(pTDStruct,FALSE) ;
+
+ //
+ // initialize as the last TD in the QH context,
+ // this field will be updated in the TD linkage process.
+ //
+ SetTDLinkPtrValidorInvalid( pTDStruct, FALSE );
+
+ //
+ // Disable Short Packet Detection by default
+ //
+ EnableorDisableTDShortPacket( pTDStruct, FALSE );
+
+ //
+ // Max error counter is 3, retry 3 times when error encountered.
+ //
+ SetTDControlErrorCounter( pTDStruct, 3 );
+
+ //
+ // set device speed attribute
+ // (TRUE - Slow Device; FALSE - Full Speed Device)
+ //
+ switch (DeviceSpeed)
+ {
+ case USB_SLOW_SPEED_DEVICE:
+ SetTDLoworFullSpeedDevice( pTDStruct, TRUE );
+ break;
+
+ case USB_FULL_SPEED_DEVICE:
+ SetTDLoworFullSpeedDevice( pTDStruct, FALSE );
+ break;
+ }
+
+ //
+ // Non isochronous transfer TD
+ //
+ SetTDControlIsochronousorNot( pTDStruct, FALSE );
+
+ //
+ // Interrupt On Complete bit be set to zero,
+ // Disable IOC interrupt.
+ //
+ SetorClearTDControlIOC( pTDStruct, FALSE );
+
+ //
+ // Set TD Active bit
+ //
+ SetTDStatusActiveorInactive( pTDStruct, TRUE );
+
+ SetTDTokenMaxLength( pTDStruct, RequestLen );
+
+ SetTDTokenDataToggle0( pTDStruct );
+
+ SetTDTokenEndPoint( pTDStruct, Endpoint );
+
+ SetTDTokenDeviceAddress( pTDStruct, DevAddr );
+
+ SetTDTokenPacketID( pTDStruct, SETUP_PACKET_ID );
+
+ pTDStruct->pTDBuffer = (UINT8 *) pDevReq;
+ pTDStruct->TDBufferLength = RequestLen;
+ SetTDDataBuffer( pTDStruct );
+
+ *ppTD = pTDStruct;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS GenDataTD (
+ USB_UHC_DEV *UhcDev,
+ UINT8 DevAddr,
+ UINT8 Endpoint,
+ UINT8 *pData,
+ UINT16 Len,
+ UINT8 PktID,
+ UINT8 Toggle,
+ UINT8 DeviceSpeed,
+ TD_STRUCT **ppTD )
+{
+ TD_STRUCT *pTDStruct;
+ EFI_STATUS Status;
+
+ Status = CreateTD( UhcDev, &pTDStruct );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ SetTDLinkPtr( pTDStruct, NULL );
+
+ //
+ // Depth first fashion
+ //
+ SetTDLinkPtrDepthorBreadth( pTDStruct, TRUE );
+
+ //
+ // Link pointer pointing to TD struct
+ //
+ SetTDLinkPtrQHorTDSelect( pTDStruct, FALSE );
+
+ //
+ // initialize as the last TD in the QH context,
+ // this field will be updated in the TD linkage process.
+ //
+ SetTDLinkPtrValidorInvalid( pTDStruct, FALSE );
+
+ //
+ // Disable short packet detect
+ //
+ EnableorDisableTDShortPacket( pTDStruct, FALSE );
+ //
+ // Max error counter is 3
+ //
+ SetTDControlErrorCounter( pTDStruct, 3 );
+
+ //
+ // set device speed attribute
+ // (TRUE - Slow Device; FALSE - Full Speed Device)
+ //
+ switch (DeviceSpeed)
+ {
+ case USB_SLOW_SPEED_DEVICE:
+ SetTDLoworFullSpeedDevice( pTDStruct, TRUE );
+ break;
+
+ case USB_FULL_SPEED_DEVICE:
+ SetTDLoworFullSpeedDevice( pTDStruct, FALSE );
+ break;
+ }
+ //
+ // Non isochronous transfer TD
+ //
+ SetTDControlIsochronousorNot( pTDStruct, FALSE );
+
+ //
+ // Disable Interrupt On Complete
+ // Disable IOC interrupt.
+ //
+ SetorClearTDControlIOC( pTDStruct, FALSE );
+
+ //
+ // Set Active bit
+ //
+ SetTDStatusActiveorInactive( pTDStruct, TRUE );
+
+ SetTDTokenMaxLength( pTDStruct, Len );
+
+ if (Toggle) {
+ SetTDTokenDataToggle1( pTDStruct );
+ }
+ else {
+ SetTDTokenDataToggle0( pTDStruct );
+ }
+
+ SetTDTokenEndPoint( pTDStruct, Endpoint );
+
+ SetTDTokenDeviceAddress( pTDStruct, DevAddr );
+
+ SetTDTokenPacketID( pTDStruct, PktID );
+
+ pTDStruct->pTDBuffer = (UINT8 *) pData;
+ pTDStruct->TDBufferLength = Len;
+ SetTDDataBuffer( pTDStruct );
+
+ *ppTD = pTDStruct;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS CreateStatusTD (
+ USB_UHC_DEV *UhcDev,
+ UINT8 DevAddr,
+ UINT8 Endpoint,
+ UINT8 PktID,
+ UINT8 DeviceSpeed,
+ TD_STRUCT **ppTD )
+{
+ TD_STRUCT *ptrTDStruct;
+ EFI_STATUS Status;
+
+ Status = CreateTD( UhcDev, &ptrTDStruct );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ SetTDLinkPtr( ptrTDStruct, NULL );
+
+ // Depth first fashion
+ SetTDLinkPtrDepthorBreadth( ptrTDStruct, TRUE );
+
+ //SetTDLinkPtrQHorTDSelect(pTDStruct,FALSE) ;
+
+ //
+ // initialize as the last TD in the QH context,
+ // this field will be updated in the TD linkage process.
+ //
+ SetTDLinkPtrValidorInvalid( ptrTDStruct, FALSE );
+
+ //
+ // Disable short packet detect
+ //
+ EnableorDisableTDShortPacket( ptrTDStruct, FALSE );
+
+ //
+ // Max error counter is 3
+ //
+ SetTDControlErrorCounter( ptrTDStruct, 3 );
+
+ //
+ // set device speed attribute
+ // (TRUE - Slow Device; FALSE - Full Speed Device)
+ //
+ switch (DeviceSpeed)
+ {
+ case USB_SLOW_SPEED_DEVICE:
+ SetTDLoworFullSpeedDevice( ptrTDStruct, TRUE );
+ break;
+
+ case USB_FULL_SPEED_DEVICE:
+ SetTDLoworFullSpeedDevice( ptrTDStruct, FALSE );
+ break;
+ }
+
+ //
+ // Non isochronous transfer TD
+ //
+ SetTDControlIsochronousorNot( ptrTDStruct, FALSE );
+
+ //
+ // Disable Interrupt On Complete
+ // Disable IOC interrupt.
+ //
+ SetorClearTDControlIOC( ptrTDStruct, FALSE );
+
+ //
+ // Set TD Active bit
+ //
+ SetTDStatusActiveorInactive( ptrTDStruct, TRUE );
+
+ SetTDTokenMaxLength( ptrTDStruct, 0 );
+
+ SetTDTokenDataToggle1( ptrTDStruct );
+
+ SetTDTokenEndPoint( ptrTDStruct, Endpoint );
+
+ SetTDTokenDeviceAddress( ptrTDStruct, DevAddr );
+
+ SetTDTokenPacketID( ptrTDStruct, PktID );
+
+ ptrTDStruct->pTDBuffer = NULL;
+ ptrTDStruct->TDBufferLength = 0;
+ SetTDDataBuffer( ptrTDStruct );
+
+ *ppTD = ptrTDStruct;
+
+ return EFI_SUCCESS;
+}
+
+
+VOID SetTDLinkPtrValidorInvalid (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bValid )
+{
+ //
+ // Valid means the link pointer is valid,
+ // else, it's invalid.
+ //
+ ptrTDStruct->TDData.TDLinkPtrTerminate = (bValid ? 0 : 1);
+}
+
+
+VOID SetTDLinkPtrQHorTDSelect (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bQH )
+{
+ //
+ // Indicate whether the Link Pointer pointing to a QH or TD
+ //
+ ptrTDStruct->TDData.TDLinkPtrQSelect = (bQH ? 1 : 0);
+}
+
+
+VOID SetTDLinkPtrDepthorBreadth (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bDepth )
+{
+ //
+ // If TRUE, indicating the host controller should process in
+ // depth first fashion, else, the host controller should process
+ // in breadth first fashion
+ //
+ ptrTDStruct->TDData.TDLinkPtrDepthSelect = (bDepth ? 1 : 0);
+}
+
+
+VOID SetTDLinkPtr (
+ IN TD_STRUCT *ptrTDStruct,
+ IN VOID *ptrNext )
+{
+ //
+ // Set TD Link Pointer. Since QH,TD align on 16-byte boundaries,
+ // only the highest 28 bits are valid. (if take 32bit address as an example)
+ //
+ ptrTDStruct->TDData.TDLinkPtr = (UINT32) (UINTN) ptrNext >> 4;
+}
+
+
+VOID *GetTDLinkPtr (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ //
+ // Get TD Link Pointer. Restore it back to 32bit
+ // (if take 32bit address as an example)
+ //
+ return ( (VOID *) (UINTN) ( (ptrTDStruct->TDData.TDLinkPtr) << 4 ) );
+}
+
+
+BOOLEAN IsTDLinkPtrQHOrTD (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ //
+ // Get the information about whether the Link Pointer field pointing to
+ // a QH or a TD.
+ //
+ return (BOOLEAN) (ptrTDStruct->TDData.TDLinkPtrQSelect);
+}
+
+
+VOID EnableorDisableTDShortPacket (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bEnable )
+{
+ //
+ // TRUE means enable short packet detection mechanism.
+ //
+ ptrTDStruct->TDData.TDStatusSPD = (bEnable ? 1 : 0);
+}
+
+
+VOID SetTDControlErrorCounter (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT8 nMaxErrors )
+{
+ //
+ // valid value of nMaxErrors is 0,1,2,3
+ //
+ if (nMaxErrors > 3) {
+ nMaxErrors = 3;
+ }
+ ptrTDStruct->TDData.TDStatusErr = nMaxErrors;
+}
+
+
+VOID SetTDLoworFullSpeedDevice (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bLowSpeedDevice )
+{
+ //
+ // TRUE means the TD is targeting at a Low-speed device
+ //
+ ptrTDStruct->TDData.TDStatusLS = (bLowSpeedDevice ? 1 : 0);
+}
+
+
+VOID SetTDControlIsochronousorNot (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bIsochronous )
+{
+ //
+ // TRUE means the TD belongs to Isochronous transfer type.
+ //
+ ptrTDStruct->TDData.TDStatusIOS = (bIsochronous ? 1 : 0);
+}
+
+
+VOID SetorClearTDControlIOC (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bSet )
+{
+ //
+ // If this bit is set, it indicates that the host controller should issue
+ // an interrupt on completion of the frame in which this TD is executed.
+ //
+ ptrTDStruct->TDData.TDStatusIOC = bSet ? 1 : 0;
+}
+
+
+VOID SetTDStatusActiveorInactive (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bActive )
+{
+ //
+ // If this bit is set, it indicates that the TD is active and can be
+ // executed.
+ //
+ if (bActive) {
+ ptrTDStruct->TDData.TDStatus |= 0x80;
+ }
+ else {
+ ptrTDStruct->TDData.TDStatus &= 0x7f;
+ }
+}
+
+
+UINT16 SetTDTokenMaxLength (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT16 nMaxLen )
+{
+ //
+ // Specifies the maximum number of data bytes allowed for the transfer.
+ // the legal value extent is 0 ~ 0x500.
+ //
+ if (nMaxLen > 0x500) {
+ nMaxLen = 0x500;
+ }
+ ptrTDStruct->TDData.TDTokenMaxLen = nMaxLen - 1;
+
+ return nMaxLen;
+}
+
+
+VOID SetTDTokenDataToggle1 (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ //
+ // Set the data toggle bit to DATA1
+ //
+ ptrTDStruct->TDData.TDTokenDataToggle = 1;
+}
+
+
+VOID SetTDTokenDataToggle0 (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ //
+ // Set the data toggle bit to DATA0
+ //
+ ptrTDStruct->TDData.TDTokenDataToggle = 0;
+}
+
+
+VOID SetTDTokenEndPoint (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINTN nEndPoint )
+{
+ //
+ // Set EndPoint Number the TD is targeting at.
+ //
+ ptrTDStruct->TDData.TDTokenEndPt = (UINT8) nEndPoint;
+}
+
+
+VOID SetTDTokenDeviceAddress (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINTN nDevAddr )
+{
+ //
+ // Set Device Address the TD is targeting at.
+ //
+ ptrTDStruct->TDData.TDTokenDevAddr = (UINT8) nDevAddr;
+}
+
+
+VOID SetTDTokenPacketID (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT8 nPID )
+{
+ //
+ // Set the Packet Identification to be used for this transaction.
+ //
+ ptrTDStruct->TDData.TDTokenPID = nPID;
+}
+
+
+VOID SetTDDataBuffer (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ //
+ // Set the beginning address of the data buffer that will be used
+ // during the transaction.
+ //
+ ptrTDStruct->TDData.TDBufferPtr = (UINT32) (UINTN) (ptrTDStruct->
+ pTDBuffer);
+}
+
+
+BOOLEAN IsTDStatusActive (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether the TD is active.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x80);
+}
+
+
+BOOLEAN IsTDStatusStalled (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether the device/endpoint addressed by this TD is stalled.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x40);
+}
+
+
+BOOLEAN IsTDStatusBufferError (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether Data Buffer Error is happened.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x20);
+}
+
+
+BOOLEAN IsTDStatusBabbleError (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether Babble Error is happened.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x10);
+}
+
+
+BOOLEAN IsTDStatusNAKReceived (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether NAK is received.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x08);
+}
+
+
+BOOLEAN IsTDStatusCRCTimeOutError (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether CRC/Time Out Error is encountered.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x04);
+}
+
+
+BOOLEAN IsTDStatusBitStuffError (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether Bitstuff Error is received.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x02);
+}
+
+
+UINT16 GetTDStatusActualLength (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ //
+ // Retrieve the actual number of bytes that were tansferred.
+ // the value is encoded as n-1. so return the decoded value.
+ //
+ return (UINT16) ( (ptrTDStruct->TDData.TDStatusActualLength) + 1 );
+}
+
+
+BOOLEAN GetTDLinkPtrValidorInvalid (
+ IN TD_STRUCT *ptrTDStruct )
+{
+ //
+ // Retrieve the information of whether the Link Pointer field
+ // is valid or not.
+ //
+ if (ptrTDStruct->TDData.TDLinkPtrTerminate) {
+ return FALSE;
+ }
+ else {
+ return TRUE;
+ }
+
+}
+
+
+UINTN CountTDsNumber (
+ IN TD_STRUCT *ptrFirstTD )
+{
+ UINTN Number;
+ TD_STRUCT *ptr;
+
+ //
+ // Count the queued TDs number.
+ //
+ Number = 0;
+ ptr = ptrFirstTD;
+ while (ptr) {
+ ptr = (TD_STRUCT *) ptr->ptrNextTD;
+ Number++;
+ }
+
+ return Number;
+}
+
+
+VOID LinkTDToQH (
+ IN QH_STRUCT *ptrQH,
+ IN TD_STRUCT *ptrTD )
+{
+ if (ptrQH == NULL || ptrTD == NULL) {
+ return;
+ }
+ //
+ // Validate QH Vertical Ptr field
+ //
+ SetQHVerticalValidorInvalid( ptrQH, TRUE );
+
+ //
+ // Vertical Ptr pointing to TD structure
+ //
+ SetQHVerticalQHorTDSelect( ptrQH, FALSE );
+
+ SetQHVerticalLinkPtr( ptrQH, (VOID *) ptrTD );
+
+ ptrQH->ptrDown = (VOID *) ptrTD;
+}
+
+
+VOID LinkTDToTD (
+ IN TD_STRUCT *ptrPreTD,
+ IN TD_STRUCT *ptrTD )
+{
+ if (ptrPreTD == NULL || ptrTD == NULL) {
+ return;
+ }
+ //
+ // Depth first fashion
+ //
+ SetTDLinkPtrDepthorBreadth( ptrPreTD, TRUE );
+
+ //
+ // Link pointer pointing to TD struct
+ //
+ SetTDLinkPtrQHorTDSelect( ptrPreTD, FALSE );
+
+ //
+ // Validate the link pointer valid bit
+ //
+ SetTDLinkPtrValidorInvalid( ptrPreTD, TRUE );
+
+ SetTDLinkPtr( ptrPreTD, ptrTD );
+
+ ptrPreTD->ptrNextTD = (VOID *) ptrTD;
+
+ ptrTD->ptrNextTD = NULL;
+}
+
+
+//
+// Transfer Schedule related Helper Functions
+//
+VOID SetorClearCurFrameListTerminate (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN BOOLEAN bSet )
+{
+ //
+ // If TRUE, empty the frame. If FALSE, indicate the Pointer field is valid.
+ //
+ pCurEntry->FrameListPtrTerminate = (bSet ? 1 : 0);
+}
+
+
+VOID SetCurFrameListQHorTD (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN BOOLEAN bQH )
+{
+ //
+ // This bit indicates to the hardware whether the item referenced by the
+ // link pointer is a TD or a QH.
+ //
+ pCurEntry->FrameListPtrQSelect = (bQH ? 1 : 0);
+}
+
+
+BOOLEAN IsCurFrameListQHorTD (
+ IN FRAMELIST_ENTRY *pCurEntry )
+{
+ //
+ //TRUE is QH
+ //FALSE is TD
+ //
+ return (BOOLEAN) (pCurEntry->FrameListPtrQSelect);
+}
+
+
+BOOLEAN GetCurFrameListTerminate (
+ IN FRAMELIST_ENTRY *pCurEntry )
+{
+ //
+ // TRUE means the frame is empty,
+ // FALSE means the link pointer field is valid.
+ //
+ return (BOOLEAN) (pCurEntry->FrameListPtrTerminate);
+}
+
+
+VOID SetCurFrameListPointer (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN UINT8 *ptr )
+{
+ //
+ // Set the pointer field of the frame.
+ //
+ pCurEntry->FrameListPtr = (UINT32) (UINTN) ptr >> 4;
+}
+
+
+VOID *GetCurFrameListPointer (
+ IN FRAMELIST_ENTRY *pCurEntry )
+{
+ VOID *ptr;
+
+ //
+ // Get the link pointer of the frame.
+ //
+ ptr = (VOID *) (UINTN) ( (pCurEntry->FrameListPtr) << 4 );
+ return ptr;
+}
+
+
+VOID LinkQHToFrameList (
+ IN FRAMELIST_ENTRY *pEntry,
+ IN UINT16 FrameListIndex,
+ IN QH_STRUCT *ptrQH )
+{
+ FRAMELIST_ENTRY *pCurFrame;
+ QH_STRUCT *TempQH, *NextTempQH;
+ TD_STRUCT *TempTD;
+ BOOLEAN LINK;
+
+ //
+ // Get frame list entry that the link process will begin from.
+ //
+ pCurFrame = pEntry + FrameListIndex;
+
+ //
+ // if current frame is empty
+ // then link the specified QH directly to the Frame List.
+ //
+ if ( GetCurFrameListTerminate( pCurFrame ) ) {
+
+ //
+ // Link new QH to the frame list entry.
+ //
+ SetCurFrameListQHorTD( pCurFrame, TRUE );
+
+ SetCurFrameListPointer( pCurFrame, (UINT8 *) ptrQH );
+
+ //
+ // clear T bit in the Frame List, means that the frame list
+ // entry is no longer empty.
+ //
+ SetorClearCurFrameListTerminate( pCurFrame, FALSE );
+
+ return;
+
+ }
+ else {
+ //
+ // current frame list has link pointer
+ //
+ if ( !IsCurFrameListQHorTD( pCurFrame ) ) {
+ //
+ // a TD is linked to the framelist entry
+ //
+ TempTD = (TD_STRUCT *) GetCurFrameListPointer( pCurFrame );
+
+ while ( GetTDLinkPtrValidorInvalid( TempTD ) ) {
+
+ if ( IsTDLinkPtrQHOrTD( TempTD ) ) { // QH linked next to the TD
+ break;
+ }
+
+ TempTD = (TD_STRUCT *) GetTDLinkPtr( TempTD );
+ }
+
+ //
+ // either no ptr linked next to the TD or QH is linked next to the TD
+ //
+ if ( !GetTDLinkPtrValidorInvalid( TempTD ) ) {
+
+ //
+ // no ptr linked next to the TD
+ //
+ TempTD->ptrNextQH = ptrQH;
+ SetTDLinkPtrQHorTDSelect( TempTD, TRUE );
+ SetTDLinkPtr( TempTD, ptrQH );
+ SetTDLinkPtrValidorInvalid( TempTD, TRUE );
+ //ptrQH->ptrNext = NULL;
+
+ return;
+
+ }
+ else {
+ //
+ // QH is linked next to the TD
+ //
+ TempQH = (QH_STRUCT *) GetTDLinkPtr( TempTD );
+ }
+
+ }
+ else {
+ //
+ // a QH is linked to the framelist entry
+ //
+ TempQH = (QH_STRUCT *) GetCurFrameListPointer( pCurFrame );
+ }
+
+ //
+ // Set up Flag
+ //
+ LINK = TRUE;
+
+ //
+ // aVOID the same qh repeated linking in one frame entry
+ //
+ if (TempQH == ptrQH) {
+ LINK = FALSE;
+ }
+ //
+ // if current QH has next QH connected
+ //
+ while ( GetQHHorizontalValidorInvalid( TempQH ) ) {
+
+ //
+ // Get next QH pointer
+ //
+ NextTempQH = (QH_STRUCT *) GetQHHorizontalLinkPtr( TempQH );
+
+ //
+ // Bulk transfer qh may be self-linked,
+ // so, the code below is to aVOID dead-loop when meeting self-linked qh
+ //
+ if (NextTempQH == TempQH) {
+ LINK = FALSE;
+ break;
+ }
+
+ TempQH = NextTempQH;
+
+ //
+ // aVOID the same qh repeated linking in one frame entry
+ //
+ if (TempQH == ptrQH) {
+ LINK = FALSE;
+ }
+ }
+
+ if (LINK) {
+ // Link
+ TempQH->ptrNext = ptrQH;
+ SetQHHorizontalQHorTDSelect( TempQH, TRUE );
+ SetQHHorizontalLinkPtr( TempQH, ptrQH );
+ SetQHHorizontalValidorInvalid( TempQH, TRUE );
+ //ptrQH->ptrNext = NULL;
+ }
+
+ return;
+
+ }
+
+}
+
+
+EFI_STATUS ExecuteControlTransfer (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT *ptrTD,
+ UINT32 wIndex,
+ UINTN *ActualLen,
+ UINTN TimeOut,
+ UINT32 *TransferResult )
+{
+ UINT32 StatusAddr;
+ UINT32 FrameListBaseReg;
+ UINTN ErrTDPos;
+ UINTN Delay;
+ CHAR8 *ErrorStr;
+
+ //
+ // Retrieve the Registers' address
+ //
+ StatusAddr = UhcDev->UsbHostControllerBaseAddress + USBSTS;
+ FrameListBaseReg = UhcDev->UsbHostControllerBaseAddress + USBFLBASEADD;
+
+ ErrTDPos = 0;
+ *TransferResult = EFI_USB_NOERROR;
+ *ActualLen = 0;
+ Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;
+
+ do {
+
+ CheckTDsResults( ptrTD, TransferResult, &ErrTDPos, ActualLen );
+
+ //
+ // TD is inactive, means the control transfer is end.
+ //
+ if ( (*TransferResult & EFI_USB_ERR_NOTEXECUTE) !=
+ EFI_USB_ERR_NOTEXECUTE ) {
+ break;
+ }
+ UhcDev->StallPpi->Stall( UhcDev->PeiServices, UhcDev->StallPpi, 50 );
+
+ } while (Delay--);
+
+
+ if (*TransferResult != EFI_USB_NOERROR) {
+ switch (*TransferResult)
+ {
+ case EFI_USB_ERR_NOTEXECUTE: ErrorStr = gUsbErrorStrings[0];
+ break;
+
+ case EFI_USB_ERR_STALL: ErrorStr = gUsbErrorStrings[1];
+ break;
+
+ case EFI_USB_ERR_BUFFER: ErrorStr = gUsbErrorStrings[2];
+ break;
+
+ case EFI_USB_ERR_BABBLE: ErrorStr = gUsbErrorStrings[3];
+ break;
+
+ case EFI_USB_ERR_NAK: ErrorStr = gUsbErrorStrings[4];
+ break;
+
+ case EFI_USB_ERR_CRC: ErrorStr = gUsbErrorStrings[5];
+ break;
+
+ case EFI_USB_ERR_TIMEOUT: ErrorStr = gUsbErrorStrings[6];
+ break;
+
+ case EFI_USB_ERR_BITSTUFF: ErrorStr = gUsbErrorStrings[7];
+ break;
+
+ case EFI_USB_ERR_SYSTEM: ErrorStr = gUsbErrorStrings[8];
+ break;
+ }
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS ExecBulkTransfer (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT *ptrTD,
+ UINT32 wIndex,
+ UINTN *ActualLen,
+ UINT8 *DataToggle,
+ UINTN TimeOut,
+ UINT32 *TransferResult )
+{
+ UINT32 StatusAddr;
+ UINT32 FrameListBaseReg;
+ UINTN ErrTDPos;
+ UINTN ScrollNum;
+ UINTN Delay;
+
+ StatusAddr = UhcDev->UsbHostControllerBaseAddress + USBSTS;
+ FrameListBaseReg = UhcDev->UsbHostControllerBaseAddress + USBFLBASEADD;
+
+ ErrTDPos = 0;
+ *TransferResult = EFI_USB_NOERROR;
+ *ActualLen = 0;
+
+ Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;
+
+ do {
+
+ CheckTDsResults( ptrTD, TransferResult, &ErrTDPos, ActualLen );
+ //
+ // TD is inactive, thus meaning bulk transfer's end.
+ //
+ if ( (*TransferResult & EFI_USB_ERR_NOTEXECUTE) !=
+ EFI_USB_ERR_NOTEXECUTE ) {
+ break;
+ }
+ UhcDev->StallPpi->Stall( UhcDev->PeiServices, UhcDev->StallPpi, 50 );
+
+ } while (Delay--);
+
+ //
+ // has error
+ //
+ if (*TransferResult != EFI_USB_NOERROR) {
+
+ //
+ // scroll the Data Toggle back to the last success TD
+ //
+ ScrollNum = CountTDsNumber( ptrTD ) - ErrTDPos;
+ if (ScrollNum % 2) {
+ *DataToggle ^= 1;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID DeleteSingleQH (
+ USB_UHC_DEV *UhcDev,
+ QH_STRUCT *ptrQH,
+ UINT16 FrameListIndex,
+ BOOLEAN SearchOther )
+{
+ FRAMELIST_ENTRY *pCurFrame;
+ UINTN i;
+ UINTN BeginFrame;
+ UINTN EndFrame;
+ QH_STRUCT *TempQH;
+ TD_STRUCT *TempTD;
+ VOID *PtrPreQH = NULL;
+ BOOLEAN Found = FALSE;
+
+ if (ptrQH == NULL) {
+ return;
+ }
+
+ if (SearchOther) {
+ BeginFrame = 0;
+ EndFrame = 1024;
+ }
+ else {
+ BeginFrame = FrameListIndex % 1024;
+ EndFrame = (FrameListIndex + 1) % 1024;
+ }
+
+ for (i = BeginFrame; i < EndFrame; i++) {
+
+ pCurFrame = UhcDev->FrameListEntry + i;
+
+ if ( GetCurFrameListTerminate( pCurFrame ) ) {
+ //
+ // current frame list is empty,search next frame list entry
+ //
+ continue;
+ }
+
+ if ( !IsCurFrameListQHorTD( pCurFrame ) ) {
+ //
+ // TD linked to current framelist
+ //
+ TempTD = (TD_STRUCT *) GetCurFrameListPointer( pCurFrame );
+
+ while ( GetTDLinkPtrValidorInvalid( TempTD ) ) {
+
+ if ( IsTDLinkPtrQHOrTD( TempTD ) ) {
+ //
+ // QH linked next to the TD,break while()
+ //
+ break;
+ }
+
+ TempTD = (TD_STRUCT *) GetTDLinkPtr( TempTD );
+ }
+
+ if ( !GetTDLinkPtrValidorInvalid( TempTD ) ) {
+ //
+ // no QH linked next to the last TD,
+ // search next frame list
+ //
+ continue;
+ }
+
+ //
+ // a QH linked next to the last TD
+ //
+ TempQH = (QH_STRUCT *) GetTDLinkPtr( TempTD );
+
+ PtrPreQH = TempTD;
+
+ }
+ else {
+ //
+ // a QH linked to current framelist
+ //
+ TempQH = (QH_STRUCT *) GetCurFrameListPointer( pCurFrame );
+
+ PtrPreQH = NULL;
+ }
+
+ if (TempQH == ptrQH) {
+
+ if (PtrPreQH) { // QH linked to a TD struct
+
+ TempTD = (TD_STRUCT *) PtrPreQH;
+ SetTDLinkPtrValidorInvalid( TempTD, FALSE );
+ SetTDLinkPtr( TempTD, NULL );
+ TempTD->ptrNextQH = NULL;
+
+ }
+ else { // QH linked directly to current framelist entry
+
+ SetorClearCurFrameListTerminate( pCurFrame, TRUE );
+ SetCurFrameListPointer( pCurFrame, NULL );
+ }
+
+ Found = TRUE;
+ //
+ // search next framelist entry
+ //
+ continue;
+ }
+
+ while (TempQH != ptrQH) {
+
+ PtrPreQH = TempQH;
+
+ //
+ // Get next horizontal linked QH
+ //
+ TempQH = (QH_STRUCT *) GetQHHorizontalLinkPtr( TempQH );
+
+ //
+ // if has no valid QH linked,break the while()
+ //
+ if (TempQH == NULL) {
+ break;
+ }
+
+ //
+ // detect self-linked QH, then break the loop
+ //
+ if (TempQH == PtrPreQH) {
+ break;
+ }
+ }
+
+ if (TempQH != ptrQH) {
+ //
+ // search next frame list entry
+ //
+ continue;
+ }
+
+ //
+ // TempQH == ptrQH,
+ // Update the related QHs
+ //
+ if ( GetQHHorizontalValidorInvalid( ptrQH ) ) {
+ //
+ // if has QH connected after the deleted QH
+ //
+ //
+ // get next QH of the deleted QH
+ //
+ TempQH = GetQHHorizontalLinkPtr( ptrQH );
+
+ //----------------------------------------------
+ //
+ // Bulk transfer qh may be self link to itself to enhance performance
+ // so, only if the qh is not self linked, can we link the next qh to
+ // the previous qh
+ //
+ if (TempQH != ptrQH) {
+ //
+ // link the next QH to the previous QH
+ //
+ SetQHHorizontalLinkPtr( (QH_STRUCT *) PtrPreQH, TempQH );
+
+ ( (QH_STRUCT *) PtrPreQH )->ptrNext = TempQH;
+ }
+ //----------------------------------------------
+
+ //
+ // if the qh is self linked, also need to update the previous qh,
+ // the situation just the same as that there is no qh connected after
+ // the deleted qh
+ //
+ }
+ //
+ // has no QH connected after the deleted QH,
+ // or the deleted QH is self-linked,
+ //
+ //
+ // NULL the previous QH's link ptr and set Terminate field.
+ //
+ SetQHHorizontalValidorInvalid( (QH_STRUCT *) PtrPreQH, FALSE );
+ SetQHHorizontalLinkPtr( (QH_STRUCT *) PtrPreQH, NULL );
+ ( (QH_STRUCT *) PtrPreQH )->ptrNext = NULL;
+
+ Found = TRUE;
+ }
+
+ if (Found) {
+ //
+ // free memory once used by deleted QH
+ //
+ UhcFreePool( UhcDev, MEM_QH_TD_TYPE, (UINT8 *) ptrQH,
+ sizeof(QH_STRUCT) );
+ }
+
+ return;
+}
+
+
+VOID DeleteQueuedTDs (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT *ptrFirstTD )
+{
+ TD_STRUCT *Tptr1, *Tptr2;
+
+ Tptr1 = ptrFirstTD;
+ //
+ // Delete all the TDs in a queue.
+ //
+ while (Tptr1) {
+
+ Tptr2 = Tptr1;
+
+ if ( !GetTDLinkPtrValidorInvalid( Tptr2 ) ) {
+ Tptr1 = NULL;
+ }
+ else {
+ //
+ // has more than one TD in the queue.
+ //
+ Tptr1 = GetTDLinkPtr( Tptr2 );
+ }
+
+ UhcFreePool( UhcDev, MEM_QH_TD_TYPE, (UINT8 *) Tptr2,
+ sizeof(TD_STRUCT) );
+ }
+
+ return;
+}
+
+
+BOOLEAN CheckTDsResults (
+ IN TD_STRUCT *ptrTD,
+ OUT UINT32 *Result,
+ OUT UINTN *ErrTDPos,
+ OUT UINTN *ActualTransferSize )
+{
+ UINTN Len;
+
+ *Result = EFI_USB_NOERROR;
+ *ErrTDPos = 0;
+
+ //
+ // Init to zero.
+ //
+ *ActualTransferSize = 0;
+
+ while (ptrTD) {
+
+ if ( IsTDStatusActive( ptrTD ) ) {
+ *Result |= EFI_USB_ERR_NOTEXECUTE;
+ }
+
+ if ( IsTDStatusStalled( ptrTD ) ) {
+ *Result |= EFI_USB_ERR_STALL;
+ }
+
+
+ if ( IsTDStatusBufferError( ptrTD ) ) {
+ *Result |= EFI_USB_ERR_BUFFER;
+ }
+
+ if ( IsTDStatusBabbleError( ptrTD ) ) {
+ *Result |= EFI_USB_ERR_BABBLE;
+ }
+
+ if ( IsTDStatusNAKReceived( ptrTD ) ) {
+ *Result |= EFI_USB_ERR_NAK;
+ }
+
+ if ( IsTDStatusCRCTimeOutError( ptrTD ) ) {
+ *Result |= EFI_USB_ERR_TIMEOUT;
+ }
+
+ if ( IsTDStatusBitStuffError( ptrTD ) ) {
+ *Result |= EFI_USB_ERR_BITSTUFF;
+ }
+
+ //
+ // Accumulate actual transferred data length in each TD.
+ //
+ Len = GetTDStatusActualLength( ptrTD ) % 0x800;
+ *ActualTransferSize += Len;
+
+ //
+ // if any error encountered, stop processing the left TDs.
+ //
+ if (*Result) {
+ return FALSE;
+ }
+
+ ptrTD = (TD_STRUCT *) (ptrTD->ptrNextTD);
+ //
+ // Record the first Error TD's position in the queue,
+ // this value is zero-based.
+ //
+ (*ErrTDPos)++;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ VOID
+ SelfLinkBulkTransferQH (
+ IN QH_STRUCT *ptrQH
+ )
+ {
+ if (ptrQH == NULL) {
+ return;
+ }
+
+ //
+ // Make the QH's horizontal link pointer pointing to itself.
+ //
+ ptrQH->ptrNext = ptrQH;
+ SetQHHorizontalQHorTDSelect(ptrQH,TRUE);
+ SetQHHorizontalLinkPtr(ptrQH,ptrQH);
+ SetQHHorizontalValidorInvalid(ptrQH,TRUE);
+ }
+ */
+
+EFI_STATUS CreateMemoryBlock (
+ USB_UHC_DEV *UhcDev,
+ MEMORY_MANAGE_HEADER **MemoryHeader,
+ UINTN MemoryBlockSizeInPages )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ UINTN MemPages;
+ UINT8 *Ptr;
+
+ //
+ // Memory Block uses MemoryBlockSizeInPages pages,
+ // memory management header and bit array use 1 page
+ //
+ MemPages = MemoryBlockSizeInPages + 1;
+ Status = ( **(UhcDev->PeiServices) ).AllocatePages(
+ UhcDev->PeiServices,
+ EfiConventionalMemory,
+ MemPages,
+ &TempPtr
+ );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ Ptr = (UINT8 *) ( (UINTN) TempPtr );
+
+ ZeroMem( Ptr, MemPages * PAGESIZE );
+
+ *MemoryHeader = (MEMORY_MANAGE_HEADER *) Ptr;
+ //
+ // adjust Ptr pointer to the next empty memory
+ //
+ Ptr += sizeof(MEMORY_MANAGE_HEADER);
+ //
+ // Set Bit Array initial address
+ //
+ (*MemoryHeader)->BitArrayPtr = Ptr;
+
+ (*MemoryHeader)->Next = NULL;
+
+ //
+ // Memory block initial address
+ //
+ Ptr = (UINT8 *) ( (UINTN) TempPtr );
+ Ptr += PAGESIZE;
+ (*MemoryHeader)->MemoryBlockPtr = Ptr;
+ //
+ // set Memory block size
+ //
+ (*MemoryHeader)->MemoryBlockSizeInBytes = MemoryBlockSizeInPages *
+ PAGESIZE;
+ //
+ // each bit in Bit Array will manage 32byte memory in memory block
+ //
+ (*MemoryHeader)->BitArraySizeInBytes =
+ ( (*MemoryHeader)->MemoryBlockSizeInBytes / 32 ) / 8;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS InitializeMemoryManagement (
+ USB_UHC_DEV *UhcDev )
+{
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ EFI_STATUS Status;
+ UINTN MemPages;
+
+ MemPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;
+ Status = CreateMemoryBlock( UhcDev, &MemoryHeader, MemPages );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ UhcDev->Header1 = MemoryHeader;
+
+ Status = CreateMemoryBlock( UhcDev, &MemoryHeader, MemPages );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ UhcDev->Header2 = MemoryHeader;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS UhcAllocatePool (
+ USB_UHC_DEV *UhcDev,
+ UINT8 Type,
+ UINT8 **Pool,
+ UINTN AllocSize )
+{
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+ MEMORY_MANAGE_HEADER *NewMemoryHeader;
+ UINTN RealAllocSize;
+ UINTN MemoryBlockSizeInPages;
+ EFI_STATUS Status;
+
+ *Pool = NULL;
+
+ switch (Type)
+ {
+ case MEM_QH_TD_TYPE:
+ MemoryHeader = UhcDev->Header1;
+ break;
+
+ case MEM_DATA_BUFFER_TYPE:
+ MemoryHeader = UhcDev->Header2;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // allocate unit is 32 byte (align on 32 byte)
+ //
+ if (AllocSize % 32) {
+ RealAllocSize = (AllocSize / 32 + 1) * 32;
+ }
+ else {
+ RealAllocSize = AllocSize;
+ }
+ //RealAllocSize = (AllocSize / 32 + 1) * 32;
+
+ Status = EFI_NOT_FOUND;
+ for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL;
+ TempHeaderPtr = TempHeaderPtr->Next) {
+
+ Status = AllocMemInMemoryBlock(
+ TempHeaderPtr,
+ Pool,
+ RealAllocSize / 32
+ );
+ if ( !EFI_ERROR( Status ) ) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // There is no enough memory,
+ // Create a new Memory Block
+ //
+
+ //
+ // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,
+ // just allocate a large enough memory block.
+ //
+ if ( RealAllocSize > (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES * PAGESIZE) ) {
+ MemoryBlockSizeInPages = RealAllocSize / PAGESIZE + 1;
+ }
+ else {
+ MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;
+ }
+ Status = CreateMemoryBlock( UhcDev,
+ &NewMemoryHeader,
+ MemoryBlockSizeInPages );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ //
+ // Link the new Memory Block to the Memory Header list
+ //
+ InsertMemoryHeaderToList( MemoryHeader, NewMemoryHeader );
+
+ Status = AllocMemInMemoryBlock( NewMemoryHeader,
+ Pool,
+ RealAllocSize / 32
+ );
+ return Status;
+}
+
+
+EFI_STATUS AllocMemInMemoryBlock (
+ MEMORY_MANAGE_HEADER *MemoryHeader,
+ VOID **Pool,
+ UINTN NumberOfMemoryUnit )
+{
+ UINTN TempBytePos;
+ UINTN FoundBytePos = 0;
+ UINT8 i;
+ UINT8 FoundBitPos = 0;
+ UINT8 ByteValue;
+ UINT8 BitValue;
+ UINTN NumberOfZeros;
+ UINTN Count;
+
+ ByteValue = MemoryHeader->BitArrayPtr[0];
+ NumberOfZeros = 0;
+ i = 0;
+ for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;
+ ) {
+
+ //
+ // Pop out BitValue from a byte in TempBytePos.
+ //
+ BitValue = (UINT8) (ByteValue % 2);
+
+ if (BitValue == 0) {
+ //
+ // Found a free bit, the NumberOfZeros only record the number
+ // of those consecutive zeros
+ //
+ NumberOfZeros++;
+ //
+ // Found enough consecutive free space, break the loop
+ //
+ if (NumberOfZeros >= NumberOfMemoryUnit) {
+ break;
+ }
+ }
+ else {
+ //
+ // Encountering a '1', meant the bit is ocupied.
+ //
+ if (NumberOfZeros >= NumberOfMemoryUnit) {
+ //
+ // Found enough consecutive free space,break the loop
+ //
+ break;
+ }
+ else {
+ //
+ // the NumberOfZeros only record the number of those consecutive zeros,
+ // so reset the NumberOfZeros to 0 when encountering '1' before finding
+ // enough consecutive '0's
+ //
+ NumberOfZeros = 0;
+ //
+ // reset the (FoundBytePos,FoundBitPos) to the position of '1'
+ //
+ FoundBytePos = TempBytePos;
+ FoundBitPos = i;
+ }
+ }
+
+ //
+ // right shift the byte
+ //
+ ByteValue /= 2;
+
+ //
+ // step forward a bit
+ //
+ i++;
+ if (i == 8) {
+ //
+ // step forward a byte, getting the byte value,
+ // and reset the bit pos.
+ //
+ TempBytePos += 1;
+ ByteValue = MemoryHeader->BitArrayPtr[TempBytePos];
+ i = 0;
+ }
+ }
+
+ if (NumberOfZeros < NumberOfMemoryUnit) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Found enough free space.
+ //
+
+ //
+ // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:
+ // 1)(FoundBytePos,FoundBitPos) record the position
+ // of the last '1' before the consecutive '0's, it must
+ // be adjusted to the start position of the consecutive '0's.
+ // 2)the start address of the consecutive '0's is just the start of
+ // the bitarray. so no need to adjust the values of
+ // (FoundBytePos,FoundBitPos).
+ //
+ if ( ( MemoryHeader->BitArrayPtr[0] & bit( 0 ) ) != 0 ) {
+ FoundBitPos += 1;
+ }
+
+ //
+ // Have the (FoundBytePos,FoundBitPos) make sense.
+ //
+ if (FoundBitPos > 7) {
+ FoundBytePos += 1;
+ FoundBitPos -= 8;
+ }
+
+ //
+ // Set the memory as allocated
+ //
+ for (TempBytePos = FoundBytePos, i = FoundBitPos, Count = 0;
+ Count < NumberOfMemoryUnit; Count++) {
+
+ MemoryHeader->BitArrayPtr[TempBytePos] |= bit( i );
+ i++;
+ if (i == 8) {
+ TempBytePos += 1;
+ i = 0;
+ }
+ }
+
+ *Pool = MemoryHeader->MemoryBlockPtr +
+ (FoundBytePos * 8 + FoundBitPos) * 32;
+
+ return EFI_SUCCESS;
+}
+
+
+VOID UhcFreePool (
+ USB_UHC_DEV *UhcDev,
+ UINT8 Type,
+ UINT8 *Pool,
+ UINTN AllocSize )
+{
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+ UINTN StartBytePos;
+ UINTN i;
+ UINT8 StartBitPos;
+ UINT8 j;
+ UINTN Count;
+ UINTN RealAllocSize;
+
+ // UINTN MemPages;
+ // EFI_PHYSICAL_ADDRESS TempPtr;
+
+ switch (Type)
+ {
+ case MEM_QH_TD_TYPE:
+ MemoryHeader = UhcDev->Header1;
+ break;
+
+ case MEM_DATA_BUFFER_TYPE:
+ MemoryHeader = UhcDev->Header2;
+ break;
+
+ default:
+ return;
+ }
+
+ //
+ // allocate unit is 32 byte (align on 32 byte)
+ //
+ if (AllocSize % 32) {
+ RealAllocSize = (AllocSize / 32 + 1) * 32;
+ }
+ else {
+ RealAllocSize = AllocSize;
+ }
+ //RealAllocSize = (AllocSize / 32 + 1) * 32;
+
+ for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL;
+ TempHeaderPtr = TempHeaderPtr->Next) {
+
+ if ( (Pool >= TempHeaderPtr->MemoryBlockPtr) &&
+ ( (Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr +
+ TempHeaderPtr->
+ MemoryBlockSizeInBytes) ) ) {
+
+ //
+ // Pool is in the Memory Block area,
+ // find the start byte and bit in the bit array
+ //
+ StartBytePos = ( (Pool -
+ TempHeaderPtr->MemoryBlockPtr) / 32 ) / 8;
+ StartBitPos = (UINT8)
+ ( ( (Pool -
+ TempHeaderPtr->MemoryBlockPtr) / 32 ) % 8 );
+
+ //
+ // reset associated bits in bit arry
+ //
+ for (i = StartBytePos, j = StartBitPos, Count = 0;
+ Count < (RealAllocSize / 32); Count++) {
+
+ TempHeaderPtr->BitArrayPtr[i] ^= (UINT8) ( bit( j ) );
+ j++;
+ if (j == 8) {
+ i += 1;
+ j = 0;
+ }
+ }
+ //
+ // break the loop
+ //
+ break;
+ }
+ }
+
+}
+
+
+VOID InsertMemoryHeaderToList (
+ MEMORY_MANAGE_HEADER *MemoryHeader,
+ MEMORY_MANAGE_HEADER *NewMemoryHeader )
+{
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+
+ for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL;
+ TempHeaderPtr = TempHeaderPtr->Next) {
+ if (TempHeaderPtr->Next == NULL) {
+ TempHeaderPtr->Next = NewMemoryHeader;
+ break;
+ }
+ }
+}
+
+
+BOOLEAN IsMemoryBlockEmptied (
+ MEMORY_MANAGE_HEADER *MemoryHeaderPtr )
+{
+ UINTN i;
+
+ for (i = 0; i < MemoryHeaderPtr->BitArraySizeInBytes; i++) {
+ if (MemoryHeaderPtr->BitArrayPtr[i] != 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+VOID DelinkMemoryBlock (
+ MEMORY_MANAGE_HEADER *FirstMemoryHeader,
+ MEMORY_MANAGE_HEADER *FreeMemoryHeader )
+{
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+
+ if ( (FirstMemoryHeader == NULL) || (FreeMemoryHeader == NULL) ) {
+ return;
+ }
+ for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL;
+ TempHeaderPtr = TempHeaderPtr->Next) {
+
+ if (TempHeaderPtr->Next == FreeMemoryHeader) {
+ //
+ // Link the before and after
+ //
+ TempHeaderPtr->Next = FreeMemoryHeader->Next;
+ break;
+ }
+ }
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.h b/Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.h
new file mode 100644
index 0000000..6c167c7
--- /dev/null
+++ b/Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.h
@@ -0,0 +1,865 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UhcPeimSrc/UhcPeim.h 9 8/23/12 10:01p Wilsonlee $
+//
+// $Revision: 9 $
+//
+// $Date: 8/23/12 10:01p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UhcPeimSrc/UhcPeim.h $
+//
+// 9 8/23/12 10:01p Wilsonlee
+// [TAG] EIP97069
+// [Category] Improvement
+// [Description] Reset root port algorythm update.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// UhcPeim.h, UsbPeim.c, usb.h
+//
+// 8 1/18/11 1:01a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 7 4/29/09 2:13p Olegi
+// Added TreansactionTranslator to UHCI Bulk transfer.
+//
+// 6 3/17/09 5:06p Olegi
+// Added TransactionTranslator for slow/full speed devices behind USB2
+// hub.
+//
+// 5 3/03/09 7:21p Olegi
+// Changed the type of MaxPktSize from UINT8 to UINT16.
+//
+// 4 7/10/08 6:37p Michaela
+// Updated to support OHCI controllers
+//
+// 3 4/16/07 12:44p Sivagarn
+// - Updated as per coding standard review
+// - In previous check-in, TIANO.H file is removed and AMIMAPPING.H file
+// is included
+//
+// 2 3/28/07 3:34a Meenakshim
+//
+// 1 9/22/06 12:21p Sivagarn
+// - Initial Check-in
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UhcPeim.h
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//
+// This file contains a 'Sample Driver' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may be modified by the user, subject to
+// the additional terms of the license agreement
+//
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ UhcPeim.h
+
+ Abstract:
+
+ Header file for Usb Host Controller PEIM
+
+ --*/
+#ifndef _RECOVERY_UHC_H
+#define _RECOVERY_UHC_H
+
+#include "Efi.h"
+#include "Pei.h"
+#include "AmiPeiLib.h"
+#include "AmiMapping.h"
+//#include "PeiHob.h" // NOT NEEDED FOR APTIO
+//#include "PeiLib.h" // NOT NEEDED FOR APTIO
+
+//
+// Driver Produced PPI Prototypes
+//
+#include "Ppi\UsbHostController.h"
+//
+// Driver Consumed PPI Prototypes
+//
+#include EFI_PPI_DEFINITION( CpuIo )
+#include EFI_PPI_DEFINITION( Stall )
+#include "Ppi\PeiGetUCtrl.h"
+
+#define bit( a ) (1 << (a))
+
+#define USB_SLOW_SPEED_DEVICE 0x01
+#define USB_FULL_SPEED_DEVICE 0x02
+
+//
+// One memory block uses 16 page
+//
+#define NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES 16
+
+#define USBCMD 0 // Command Register Offset 00-01h
+#define USBCMD_RS bit( 0 ) // Run/Stop
+#define USBCMD_HCRESET bit( 1 ) // Host reset
+#define USBCMD_GRESET bit( 2 ) // Global reset
+#define USBCMD_EGSM bit( 3 ) // Global Suspend Mode
+#define USBCMD_FGR bit( 4 ) // Force Global Resume
+#define USBCMD_SWDBG bit( 5 ) // SW Debug mode
+#define USBCMD_CF bit( 6 ) // Config Flag (sw only)
+#define USBCMD_MAXP bit( 7 ) // Max Packet (0 = 32, 1 = 64)
+
+// Status register
+#define USBSTS 2 // Status Register Offset 02-03h
+#define USBSTS_USBINT bit( 0 ) // Interrupt due to IOC
+#define USBSTS_ERROR bit( 1 ) // Interrupt due to error
+#define USBSTS_RD bit( 2 ) // Resume Detect
+#define USBSTS_HSE bit( 3 ) // Host System Error
+ // - basically PCI problems
+#define USBSTS_HCPE bit( 4 ) // Host Controller Process Error
+ // - the scripts were buggy
+#define USBSTS_HCH bit( 5 ) // HC Halted
+
+// Interrupt enable register
+#define USBINTR 4 // Interrupt Enable Register 04-05h
+#define USBINTR_TIMEOUT bit( 0 ) // Timeout/CRC error enable
+#define USBINTR_RESUME bit( 1 ) // Resume interrupt enable
+#define USBINTR_IOC bit( 2 ) // Interrupt On Complete enable
+#define USBINTR_SP bit( 3 ) // Short packet interrupt enable
+
+// Frame Number Register Offset 06-08h
+#define USBFRNUM 6
+
+// Frame List Base Address Register Offset 08-0Bh
+#define USBFLBASEADD 8
+
+// Start of Frame Modify Register Offset 0Ch
+#define USBSOF 0x0c
+
+// USB port status and control registers
+#define USBPORTSC1 0x10 //Port 1 offset 10-11h
+#define USBPORTSC2 0x12 //Port 2 offset 12-13h
+
+#define USBPORTSC_CCS bit( 0 ) // Current Connect Status ("device present")
+#define USBPORTSC_CSC bit( 1 ) // Connect Status Change
+#define USBPORTSC_PED bit( 2 ) // Port Enable / Disable
+#define USBPORTSC_PEDC bit( 3 ) // Port Enable / Disable Change
+#define USBPORTSC_LSL bit( 4 ) // Line Status Low bit
+#define USBPORTSC_LSH bit( 5 ) // Line Status High bit
+#define USBPORTSC_RD bit( 6 ) // Resume Detect
+#define USBPORTSC_LSDA bit( 8 ) // Low Speed Device Attached
+#define USBPORTSC_PR bit( 9 ) // Port Reset
+#define USBPORTSC_SUSP bit( 12 ) // Suspend
+
+#define SETUP_PACKET_ID 0x2d
+#define INPUT_PACKET_ID 0x69
+#define OUTPUT_PACKET_ID 0xe1
+#define ERROR_PACKET_ID 0x55
+
+#define MEM_QH_TD_TYPE 0
+#define MEM_DATA_BUFFER_TYPE 1
+
+#define STALL_1_MILLI_SECOND 1000
+//#define STALL_1_MILLI_SECOND 10
+
+//#pragma pack(1)
+
+#pragma pack(push, 16)
+typedef struct
+{
+ UINT32 FrameListPtrTerminate : 1;
+ UINT32 FrameListPtrQSelect : 1;
+ UINT32 FrameListRsvd : 2;
+ UINT32 FrameListPtr : 28;
+} FRAMELIST_ENTRY;
+
+typedef struct
+{
+ UINT32 QHHorizontalTerminate : 1;
+ UINT32 QHHorizontalQSelect : 1;
+ UINT32 QHHorizontalRsvd : 2;
+ UINT32 QHHorizontalPtr : 28;
+ UINT32 QHVerticalTerminate : 1;
+ UINT32 QHVerticalQSelect : 1;
+ UINT32 QHVerticalRsvd : 2;
+ UINT32 QHVerticalPtr : 28;
+} QUEUE_HEAD;
+
+typedef struct
+{
+ QUEUE_HEAD QH;
+ UINT32 reserved1;
+ UINT32 reserved2;
+ VOID *ptrNext;
+ VOID *ptrDown;
+ VOID *reserved3;
+ UINT32 reserved4;
+} QH_STRUCT;
+
+typedef struct
+{
+ UINT32 TDLinkPtrTerminate : 1;
+ UINT32 TDLinkPtrQSelect : 1;
+ UINT32 TDLinkPtrDepthSelect : 1;
+ UINT32 TDLinkPtrRsvd : 1;
+ UINT32 TDLinkPtr : 28;
+ UINT32 TDStatusActualLength : 11;
+ UINT32 TDStatusRsvd : 5;
+ UINT32 TDStatus : 8;
+ UINT32 TDStatusIOC : 1;
+ UINT32 TDStatusIOS : 1;
+ UINT32 TDStatusLS : 1;
+ UINT32 TDStatusErr : 2;
+ UINT32 TDStatusSPD : 1;
+ UINT32 TDStatusRsvd2 : 2;
+ UINT32 TDTokenPID : 8;
+ UINT32 TDTokenDevAddr : 7;
+ UINT32 TDTokenEndPt : 4;
+ UINT32 TDTokenDataToggle : 1;
+ UINT32 TDTokenRsvd : 1;
+ UINT32 TDTokenMaxLen : 11;
+ UINT32 TDBufferPtr;
+} TD;
+
+typedef struct
+{
+ TD TDData;
+ UINT8 *pTDBuffer;
+ VOID *ptrNextTD;
+ VOID *ptrNextQH;
+ UINT16 TDBufferLength;
+ UINT16 reserved;
+} TD_STRUCT;
+
+//#pragma pack()
+#pragma pack(pop)
+
+typedef struct _MEMORY_MANAGE_HEADER
+{
+ UINT8 *BitArrayPtr;
+ UINTN BitArraySizeInBytes;
+ UINT8 *MemoryBlockPtr;
+ UINTN MemoryBlockSizeInBytes;
+ struct _MEMORY_MANAGE_HEADER *Next;
+} MEMORY_MANAGE_HEADER;
+
+#define USB_UHC_DEV_SIGNATURE EFI_SIGNATURE_32( 'p', 'u', 'h', 'c' )
+typedef struct
+{
+ UINTN Signature;
+
+ EFI_PEI_SERVICES **PeiServices;
+ PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi;
+ EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
+ PEI_CPU_IO_PPI *CpuIoPpi;
+ PEI_STALL_PPI *StallPpi;
+
+ UINT32 UsbHostControllerBaseAddress;
+ FRAMELIST_ENTRY *FrameListEntry;
+ //
+ // Header1 used for QH,TD memory blocks management
+ //
+ MEMORY_MANAGE_HEADER *Header1;
+ //
+ // Header2 used for Data transfer memory blocks management
+ //
+ MEMORY_MANAGE_HEADER *Header2;
+ UINT16 PortResetStatusChangeMap;
+} USB_UHC_DEV;
+
+#define PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS( a ) \
+ PEI_CR( a, USB_UHC_DEV, UsbHostControllerPpi, USB_UHC_DEV_SIGNATURE )
+
+EFI_STATUS
+UhcControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult );
+
+EFI_STATUS
+UhcBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT16 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult );
+
+EFI_STATUS
+UhcGetRootHubPortNumber (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *PortNumber );
+
+EFI_STATUS
+UhcGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus );
+
+EFI_STATUS
+UhcSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature );
+
+EFI_STATUS
+UhcClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature );
+
+EFI_STATUS
+InitializeUsbHC (
+ USB_UHC_DEV *UhcDev );
+
+EFI_STATUS
+CreateFrameList (
+ USB_UHC_DEV *UhcDev );
+
+VOID
+InitFrameList (
+ USB_UHC_DEV *UhcDev );
+
+UINT16
+USBReadPortW (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 Port );
+
+
+UINT32
+USBReadPortDW (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 Port );
+
+VOID
+USBWritePortW (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 Port,
+ IN UINT16 Data );
+
+VOID
+USBWritePortDW (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 Port,
+ IN UINT32 Data );
+
+
+VOID
+ClearStatusReg (
+ IN USB_UHC_DEV *UhcDev,
+ IN UINT32 STSAddr );
+
+
+UINT32
+GetFrameListBaseAddrFromRegister (
+ USB_UHC_DEV *UhcDev,
+ UINT32 FLBAAddr );
+
+BOOLEAN
+IsHostSysErr (
+ USB_UHC_DEV *UhcDev,
+ UINT32 StatusRegAddr );
+
+BOOLEAN
+IsHCProcessErr (
+ USB_UHC_DEV *UhcDev,
+ UINT32 StatusRegAddr );
+
+BOOLEAN
+IsHCHalted (
+ USB_UHC_DEV *UhcDev,
+ UINT32 StatusRegAddr );
+
+
+UINT16
+GetCurrentFrameNumber (
+ USB_UHC_DEV *UhcDev,
+ UINT32 FRNUMAddr );
+
+VOID
+SetFrameListBaseAddress (
+ USB_UHC_DEV *UhcDev,
+ UINT32 FLBASEADDRReg,
+ UINT32 Addr );
+
+
+EFI_STATUS
+AllocateQHStruct (
+ USB_UHC_DEV *UhcDev,
+ QH_STRUCT **ppQHStruct );
+
+VOID
+InitQH (
+ IN QH_STRUCT *ptrQH );
+
+
+EFI_STATUS
+CreateQH (
+ USB_UHC_DEV *UhcDev,
+ QH_STRUCT **pptrQH );
+
+VOID
+SetQHHorizontalLinkPtr (
+ IN QH_STRUCT *ptrQH,
+ IN VOID *ptrNext );
+
+VOID *
+GetQHHorizontalLinkPtr (
+ IN QH_STRUCT *ptrQH );
+
+VOID
+SetQHHorizontalQHorTDSelect (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bQH );
+
+
+VOID
+SetQHHorizontalValidorInvalid (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bValid );
+
+VOID
+SetQHVerticalLinkPtr (
+ IN QH_STRUCT *ptrQH,
+ IN VOID *ptrNext );
+
+VOID *
+GetQHVerticalLinkPtr (
+ IN QH_STRUCT *ptrQH );
+
+VOID
+SetQHVerticalQHorTDSelect (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bQH );
+
+BOOLEAN
+IsQHHorizontalQHSelect (
+ IN QH_STRUCT *ptrQH );
+
+VOID
+SetQHVerticalValidorInvalid (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bValid );
+
+
+BOOLEAN
+GetQHVerticalValidorInvalid (
+ IN QH_STRUCT *ptrQH );
+
+BOOLEAN
+GetQHHorizontalValidorInvalid (
+ IN QH_STRUCT *ptrQH );
+
+
+EFI_STATUS
+AllocateTDStruct (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT **ppTDStruct );
+
+VOID
+InitTD (
+ IN TD_STRUCT *ptrTD );
+
+EFI_STATUS
+CreateTD (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT **pptrTD );
+
+EFI_STATUS
+GenSetupStageTD (
+ USB_UHC_DEV *UhcDev,
+ UINT8 DevAddr,
+ UINT8 Endpoint,
+ UINT8 DeviceSpeed,
+ UINT8 *pDevReq,
+ UINT8 RequestLen,
+ TD_STRUCT **ppTD );
+
+EFI_STATUS
+GenDataTD (
+ USB_UHC_DEV *UhcDev,
+ UINT8 DevAddr,
+ UINT8 Endpoint,
+ UINT8 *pData,
+ UINT16 Len,
+ UINT8 PktID,
+ UINT8 Toggle,
+ UINT8 DeviceSpeed,
+ TD_STRUCT **ppTD );
+
+EFI_STATUS
+CreateStatusTD (
+ USB_UHC_DEV *UhcDev,
+ UINT8 DevAddr,
+ UINT8 Endpoint,
+ UINT8 PktID,
+ UINT8 DeviceSpeed,
+ TD_STRUCT **ppTD );
+
+
+VOID
+SetTDLinkPtrValidorInvalid (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bValid );
+
+VOID
+SetTDLinkPtrQHorTDSelect (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bQH );
+
+VOID
+SetTDLinkPtrDepthorBreadth (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bDepth );
+
+VOID
+SetTDLinkPtr (
+ IN TD_STRUCT *ptrTDStruct,
+ IN VOID *ptrNext );
+
+VOID *
+GetTDLinkPtr (
+ IN TD_STRUCT *ptrTDStruct );
+
+BOOLEAN
+IsTDLinkPtrQHOrTD (
+ IN TD_STRUCT *ptrTDStruct );
+
+VOID
+EnableorDisableTDShortPacket (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bEnable );
+
+VOID
+SetTDControlErrorCounter (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT8 nMaxErrors );
+
+
+VOID
+SetTDLoworFullSpeedDevice (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bLowSpeedDevice );
+
+VOID
+SetTDControlIsochronousorNot (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bIsochronous );
+
+VOID
+SetorClearTDControlIOC (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bSet );
+
+VOID
+SetTDStatusActiveorInactive (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bActive );
+
+UINT16
+SetTDTokenMaxLength (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT16 nMaxLen );
+
+VOID
+SetTDTokenDataToggle1 (
+ IN TD_STRUCT *ptrTDStruct );
+
+VOID
+SetTDTokenDataToggle0 (
+ IN TD_STRUCT *ptrTDStruct );
+
+UINT8
+GetTDTokenDataToggle (
+ IN TD_STRUCT *ptrTDStruct );
+
+VOID
+SetTDTokenEndPoint (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINTN nEndPoint );
+
+VOID
+SetTDTokenDeviceAddress (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINTN nDevAddr );
+
+VOID
+SetTDTokenPacketID (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT8 nPID );
+
+VOID
+SetTDDataBuffer (
+ IN TD_STRUCT *ptrTDStruct );
+
+BOOLEAN
+IsTDStatusActive (
+ IN TD_STRUCT *ptrTDStruct );
+
+BOOLEAN
+IsTDStatusStalled (
+ IN TD_STRUCT *ptrTDStruct );
+
+BOOLEAN
+IsTDStatusBufferError (
+ IN TD_STRUCT *ptrTDStruct );
+
+BOOLEAN
+IsTDStatusBabbleError (
+ IN TD_STRUCT *ptrTDStruct );
+
+BOOLEAN
+IsTDStatusNAKReceived (
+ IN TD_STRUCT *ptrTDStruct );
+
+BOOLEAN
+IsTDStatusCRCTimeOutError (
+ IN TD_STRUCT *ptrTDStruct );
+
+BOOLEAN
+IsTDStatusBitStuffError (
+ IN TD_STRUCT *ptrTDStruct );
+
+UINT16
+GetTDStatusActualLength (
+ IN TD_STRUCT *ptrTDStruct );
+
+UINT16
+GetTDTokenMaxLength (
+ IN TD_STRUCT *ptrTDStruct );
+
+UINT8
+GetTDTokenEndPoint (
+ IN TD_STRUCT *ptrTDStruct );
+
+UINT8
+GetTDTokenDeviceAddress (
+ IN TD_STRUCT *ptrTDStruct );
+
+UINT8
+GetTDTokenPacketID (
+ IN TD_STRUCT *ptrTDStruct );
+
+UINT8 *
+GetTDDataBuffer (
+ IN TD_STRUCT *ptrTDStruct );
+
+BOOLEAN
+GetTDLinkPtrValidorInvalid (
+ IN TD_STRUCT *ptrTDStruct );
+
+UINTN
+CountTDsNumber (
+ IN TD_STRUCT *ptrFirstTD );
+
+VOID
+LinkTDToQH (
+ IN QH_STRUCT *ptrQH,
+ IN TD_STRUCT *ptrTD );
+
+VOID
+LinkTDToTD (
+ IN TD_STRUCT *ptrPreTD,
+ IN TD_STRUCT *ptrTD );
+
+
+//
+// Transfer Schedule related Helper Functions
+//
+VOID
+SetorClearCurFrameListTerminate (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN BOOLEAN bSet );
+
+VOID
+SetCurFrameListQHorTD (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN BOOLEAN bQH );
+
+BOOLEAN
+IsCurFrameListQHorTD (
+ IN FRAMELIST_ENTRY *pCurEntry );
+
+BOOLEAN
+GetCurFrameListTerminate (
+ IN FRAMELIST_ENTRY *pCurEntry );
+
+VOID
+SetCurFrameListPointer (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN UINT8 *ptr );
+
+VOID *
+GetCurFrameListPointer (
+ IN FRAMELIST_ENTRY *pCurEntry );
+
+VOID
+LinkQHToFrameList (
+ IN FRAMELIST_ENTRY *pEntry,
+ IN UINT16 FrameListIndex,
+ IN QH_STRUCT *ptrQH );
+
+EFI_STATUS
+ExecuteControlTransfer (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT *ptrTD,
+ UINT32 wIndex,
+ UINTN *ActualLen,
+ UINTN TimeOut,
+ UINT32 *TransferResult );
+
+EFI_STATUS
+ExecBulkTransfer (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT *ptrTD,
+ UINT32 wIndex,
+ UINTN *ActualLen,
+ UINT8 *DataToggle,
+ UINTN TimeOut,
+ UINT32 *TransferResult );
+
+VOID
+DeleteSingleQH (
+ USB_UHC_DEV *UhcDev,
+ QH_STRUCT *ptrQH,
+ UINT16 FrameListIndex,
+ BOOLEAN SearchOther );
+
+VOID
+DeleteQueuedTDs (
+ USB_UHC_DEV *UhcDev,
+ TD_STRUCT *ptrFirstTD );
+
+
+BOOLEAN
+CheckTDsResults (
+ IN TD_STRUCT *ptrTD,
+ OUT UINT32 *Result,
+ OUT UINTN *ErrTDPos,
+ OUT UINTN *ActualTransferSize );
+
+VOID
+ClearTDStatus (
+ IN TD_STRUCT *ptrTD );
+
+VOID
+SelfLinkBulkTransferQH (
+ IN QH_STRUCT *ptrQH );
+
+EFI_STATUS
+CreateMemoryBlock (
+ USB_UHC_DEV *UhcDev,
+ MEMORY_MANAGE_HEADER **MemoryHeader,
+ UINTN MemoryBlockSizeInPages );
+
+EFI_STATUS
+InitializeMemoryManagement (
+ USB_UHC_DEV *UhcDev );
+
+EFI_STATUS
+UhcAllocatePool (
+ USB_UHC_DEV *UhcDev,
+ UINT8 Type,
+ UINT8 **Pool,
+ UINTN AllocSize );
+
+EFI_STATUS
+AllocMemInMemoryBlock (
+ MEMORY_MANAGE_HEADER *MemoryHeader,
+ VOID **Pool,
+ UINTN NumberOfMemoryUnit );
+
+
+VOID
+UhcFreePool (
+ USB_UHC_DEV *UhcDev,
+ UINT8 Type,
+ UINT8 *Pool,
+ UINTN AllocSize );
+
+VOID
+InsertMemoryHeaderToList (
+ MEMORY_MANAGE_HEADER *MemoryHeader,
+ MEMORY_MANAGE_HEADER *NewMemoryHeader );
+
+BOOLEAN
+IsMemoryBlockEmptied (
+ MEMORY_MANAGE_HEADER *MemoryHeaderPtr );
+
+VOID
+DelinkMemoryBlock (
+ MEMORY_MANAGE_HEADER *FirstMemoryHeader,
+ MEMORY_MANAGE_HEADER *FreeMemoryHeader );
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UhcPeimSrc/UhcPeimSrc.cif b/Core/EM/UsbRecovery/UhcPeimSrc/UhcPeimSrc.cif
new file mode 100644
index 0000000..582376f
--- /dev/null
+++ b/Core/EM/UsbRecovery/UhcPeimSrc/UhcPeimSrc.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "UhcPeimSrc"
+ category = ModulePart
+ LocalRoot = "Core\em\UsbRecovery\UhcPeimSrc"
+ RefName = "UhcPeimSrc"
+[files]
+"UhcPeim.c"
+"UhcPeim.h"
+[parts]
+"UsbHCPpi"
+<endComponent>
diff --git a/Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.c b/Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.c
new file mode 100644
index 0000000..953d37c
--- /dev/null
+++ b/Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.c
@@ -0,0 +1,376 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UhciPeiUsb.c 10 10/23/08 1:59p Michaela $
+//
+// $Revision: 10 $
+//
+// $Date: 10/23/08 1:59p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UhciPeiUsb.c $
+//
+// 10 10/23/08 1:59p Michaela
+// Removed UsbDebug.h include
+//
+// 9 10/21/08 5:56p Michaela
+// Added EHCI-related fixes for issues
+// that may occur if EHCI is used before
+// USB Recovery is invoked:
+// Added SDL Tokens:
+// PEI_EHCI_PCI_BDFS and
+// PEI_EHCI_MEM_BASE_ADDRESSES.
+//
+// Removed/modified some debugging
+// development code:
+// Removed SDL Tokens:
+// USBR_DEBUG_SUPPORT and
+// USBR_SERIAL_PORT_AVAILABLE
+// Removed Elinks:
+// UsbRecoveryDebug_DIR and
+// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+// Modified SDL Token:
+// FORCE_RECOVERY to default value of 0.
+//
+// (See this module's Help documentation
+// for more information.)
+//
+// 8 7/10/08 6:34p Michaela
+// Updated to support OHCI controllers
+//
+// 7 10/23/07 5:56p Ambikas
+//
+// 6 10/23/07 5:39p Ambikas
+//
+// 5 8/17/07 4:05p Ambikas
+//
+// 4 9/22/06 4:03p Sivagarn
+// - Included appropriate headers for flies and functions
+// - Updated copyright messages
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UhciPeiUsb.C
+//
+// Description: This file is the main source file for the UHCI PEI USB
+// recovery module
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <PEI.h>
+#include <AmiPeiLib.h>
+#include <PPI/PeiGetUCtrl.h>
+#include <token.h>
+
+
+//----------------------------------------------------------------------------
+// Global Constants
+//----------------------------------------------------------------------------
+
+#define PCI_REG_UHCI_COMMAND_REGISTER 0x04
+#define PCI_REG_UHCI_BASE_ADDRESS_REGISTER 0x20
+#define PCI_REG_UHCI_LEGACY_CONTROL_REGISTER 0xc0
+#define PCI_REG_UHCI_RESUME_ENABLE_REGISTER 0xc4
+
+#define PEI_UHCI_CONTROLLER 0x01
+
+#define PCI_REG_EHCI_MEMORY_BAR 0x10
+
+#define EHCI_HC_OPERATIONAL_CONFIG_FLAG_REG 0x40
+
+UINTN gUhciPciReg[] = PEI_UHCI_PCI_DEVICES;
+#define MAX_USB_CTRLERS sizeof(gUhciPciReg) / sizeof(UINTN)
+
+
+//----------------------------------------------------------------------------
+// Type definitions
+//----------------------------------------------------------------------------
+
+typedef struct
+{
+ // UINTN Signature;
+ // PEI_USB_CONTROLLER_PPI UsbControllerPpi;
+ // EFI_PEI_PPI_DESCRIPTOR PpiList;
+ // PEI_PCI_CFG_PPI *PciCfgPpi;
+ // UINTN TotalUsbControllers;
+ UINTN IoBase[MAX_USB_CTRLERS];
+} PCI_UHCI_DEVICE;
+
+//----------------------------------------------------------------------------
+// Function Prototypes
+//----------------------------------------------------------------------------
+
+EFI_STATUS GetUhciController (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_USB_CONTROLLER_PPI *This,
+ IN UINT8 UsbControllerId,
+ IN UINTN *ControllerType,
+ IN UINTN *IoBaseAddress );
+
+EFI_STATUS
+EnableUhciController (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PCI_CFG_PPI *PciCfgPpi,
+ IN UINTN BaseAddress,
+ IN UINT8 UsbControllerId );
+
+VOID
+ClearEhciConfigFlagReg (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PCI_CFG_PPI *PciCfgPpi );
+
+//----------------------------------------------------------------------------
+// Global Variables
+//----------------------------------------------------------------------------
+
+#ifdef PEI_EHCI_MEM_BASE_ADDRESSES
+UINTN mEhciPciBDFs[USB_EHCI] = PEI_EHCI_PCI_BDFS;
+UINT32 mEhciMemBaseAddresses[USB_EHCI] = PEI_EHCI_MEM_BASE_ADDRESSES;
+#endif
+
+static EFI_GUID guidGetUhciController = EFI_PEI_GET_UHCI_CTRLER_GUID;
+PCI_UHCI_DEVICE gPeiUhciDev;
+EFI_PEI_USB_CONTROLLER_PPI GetUhciControllerPpi = {
+ GetUhciController
+};
+
+// PPI to be installed
+static
+EFI_PEI_PPI_DESCRIPTOR PpiList[] = {
+ {EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &guidGetUhciController, &GetUhciControllerPpi}
+};
+
+//----------------------------------------------------------------------------
+// Function Definitions
+//----------------------------------------------------------------------------
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UhciPeiUsbEntryPoint
+//
+// Description: This function is the entry point for this PEI. This function
+// initializes the UHCI Controller
+//
+// Input: FfsHeader Pointer to the FFS file header
+// PeiServices Pointer to the PEI services table
+//
+// Output: Return Status based on errors that occurred while waiting for
+// time to expire.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS UhciPeiUsbEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+
+ UINTN i;
+ EFI_STATUS Status;
+ EFI_PEI_PCI_CFG_PPI *PciCfgPpi;
+
+ // Set PCI Config pointer
+ PciCfgPpi = (*PeiServices)->PciCfg;
+
+ #ifdef PEI_EHCI_MEM_BASE_ADDRESSES
+ ClearEhciConfigFlagReg( PeiServices, PciCfgPpi );
+ #endif
+
+ // Assign resources and enable UHCI controllers
+ for (i = 0; i < MAX_USB_CTRLERS; i++) {
+ // PEI_UHCI_IOBASE = 0x4000
+ gPeiUhciDev.IoBase[i] = PEI_UHCI_IOBASE + 0x40 * i;
+ Status = EnableUhciController( PeiServices, PciCfgPpi,
+ gPeiUhciDev.IoBase[i], (UINT8) i );
+ }
+
+ // Install USB Controller PPI
+ return (*PeiServices)->InstallPpi( PeiServices, PpiList );
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EnableUhciController
+//
+// Description: This function enables the UHCI controller
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *PciCfgPpi Pointer to the PCI Configuration PPI
+// BaseAddress I/O base Address to be programmed for the
+// UHCI controller
+// UsbControllerId USB Controller ID
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EnableUhciController (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PCI_CFG_PPI *PciCfgPpi,
+ IN UINTN BaseAddress,
+ IN UINT8 UsbControllerId )
+{
+ UINT16 CmdReg;
+
+
+ // Validate USB Controller ID
+ if (UsbControllerId >= MAX_USB_CTRLERS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Assign base address register
+ PciCfgPpi->Write( PeiServices, PciCfgPpi, EfiPeiPciCfgWidthUint32,
+ gUhciPciReg[UsbControllerId] |
+ PCI_REG_UHCI_BASE_ADDRESS_REGISTER, &BaseAddress );
+
+ // Enable UHCI PCI Command register
+ PciCfgPpi->Read( PeiServices, PciCfgPpi, EfiPeiPciCfgWidthUint16,
+ gUhciPciReg[UsbControllerId] |
+ PCI_REG_UHCI_COMMAND_REGISTER, &CmdReg );
+
+ CmdReg = (UINT16) (CmdReg | 0x05);
+
+ PciCfgPpi->Write( PeiServices, PciCfgPpi, EfiPeiPciCfgWidthUint16,
+ gUhciPciReg[UsbControllerId] |
+ PCI_REG_UHCI_COMMAND_REGISTER, &CmdReg );
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ClearEhciConfigFlagReg
+//
+// Description:
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *PciCfgPpi Pointer to the PCI Configuration PPI
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+#ifdef PEI_EHCI_MEM_BASE_ADDRESSES
+VOID ClearEhciConfigFlagReg (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_PCI_CFG_PPI *PciCfgPpi )
+{
+ UINT32 i;
+ UINT16 CmdReg;
+ UINT32 ConfigureFlagAddress;
+
+
+ for (i = 0; i < USB_EHCI; i++) {
+ // Assign Memory Base Address
+ PciCfgPpi->Write( PeiServices, PciCfgPpi, EfiPeiPciCfgWidthUint32,
+ mEhciPciBDFs[i] |
+ PCI_REG_EHCI_MEMORY_BAR,
+ &mEhciMemBaseAddresses[i] );
+
+ // Set the Memory Space Enable and Bus Master Enable bits in the
+ // PCI Command register.
+ PciCfgPpi->Read( PeiServices, PciCfgPpi, EfiPeiPciCfgWidthUint16,
+ mEhciPciBDFs[i] |
+ PCI_REG_UHCI_COMMAND_REGISTER, &CmdReg );
+
+ CmdReg = (UINT16) (CmdReg | 0x06);
+
+ PciCfgPpi->Write( PeiServices, PciCfgPpi, EfiPeiPciCfgWidthUint16,
+ mEhciPciBDFs[i] |
+ PCI_REG_UHCI_COMMAND_REGISTER, &CmdReg );
+
+ //Clear Config Flag Register
+ ConfigureFlagAddress=mEhciMemBaseAddresses[i]+(UINT32)MMIO_READ8(mEhciMemBaseAddresses[i])+EHCI_HC_OPERATIONAL_CONFIG_FLAG_REG;
+ MMIO_WRITE32(ConfigureFlagAddress, 0);
+
+ // Clear the Memory Space Enable and Bus Master Enable bits in the
+ // PCI Command register.
+ PciCfgPpi->Read( PeiServices, PciCfgPpi, EfiPeiPciCfgWidthUint16,
+ mEhciPciBDFs[i] |
+ PCI_REG_UHCI_COMMAND_REGISTER, &CmdReg );
+
+ CmdReg = (UINT16) ( CmdReg &= ~(0x6) );
+
+ PciCfgPpi->Write( PeiServices, PciCfgPpi, EfiPeiPciCfgWidthUint16,
+ mEhciPciBDFs[i] |
+ PCI_REG_UHCI_COMMAND_REGISTER, &CmdReg );
+ }
+}
+
+
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetUhciController
+//
+// Description: This function returns controller type and I/O base address
+// value for the controller specified
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *PciCfgPpi Pointer to the PCI Configuration PPI
+// UsbControllerId USB Controller ID
+//
+// Output: EFI_STATUS
+// *ControllerType Type of the USB controller
+// *IoBaseAddress I/O base Address programmed for this
+// controller
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GetUhciController (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_USB_CONTROLLER_PPI *This,
+ IN UINT8 UsbControllerId,
+ OUT UINTN *ControllerType,
+ OUT UINTN *IoBaseAddress )
+{
+
+ if (UsbControllerId >= MAX_USB_CTRLERS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ControllerType = PEI_UHCI_CONTROLLER;
+ *IoBaseAddress = gPeiUhciDev.IoBase[UsbControllerId];
+
+ return EFI_SUCCESS;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.cif b/Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.cif
new file mode 100644
index 0000000..9dd2315
--- /dev/null
+++ b/Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.cif
@@ -0,0 +1,10 @@
+<component>
+ name = "UhciPeiUsb"
+ category = ModulePart
+ LocalRoot = "core\em\UsbRecovery\UhciPeiUsb\"
+ RefName = "UhciPeiUsb"
+[files]
+"UhciPeiUsb.c"
+[parts]
+"UHCI PPI"
+<endComponent>
diff --git a/Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.c b/Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.c
new file mode 100644
index 0000000..7ebdb88
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.c
@@ -0,0 +1,482 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/BotPeim.c 7 11/24/12 5:47a Ryanchou $
+//
+// $Revision: 7 $
+//
+// $Date: 11/24/12 5:47a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/BotPeim.c $
+//
+// 7 11/24/12 5:47a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 6 4/16/11 3:41a Ryanchou
+// [TAG] EIP50311
+// [Category] New Feature
+// [Description] Multiple LUN device support added.
+// [Files] BotPeim.c, UsbBotPeim.c, UsbBotPeim.h
+//
+// 5 2/18/11 2:13a Ryanchou
+// [TAG] EIP52191
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Recovery from card reader causes "EHCI Time-Out".
+// [RootCause] The card reader returns zero length during BOT data
+// transport, BIOS will do data transport again if the remain data length
+// isn't zero, then CSW will be received in data transport phase.
+// [Solution] Added the code that check if the transfered length is less
+// than expect length, break the loop.
+// [Files] BotPeim.c
+//
+// 4 4/06/10 3:27p Fasihm
+// EIP#31987 - Added the generic USBRecovery Fix in the module.
+//
+// 3 7/10/08 6:38p Michaela
+// Updated to support OHCI controllers
+//
+// 2 8/17/07 4:12p Ambikas
+//
+// 1 9/22/06 12:17p Sivagarn
+// - Included Recovery code in Source
+//
+// 1 9/22/06 12:14p Sivagarn
+// - Initial checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: BotPeim.C
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+// This file contains generic routines needed for USB recovery
+// Mass Storage BOT PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+/*++
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+ --*/
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ BotPeim.c
+
+ Abstract:
+
+ BOT Transportation implementation
+
+ --*/
+
+#include "UsbBotPeim.h"
+#include "BotPeim.h"
+#include "PeiUsbLib.h"
+
+extern VOID ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size );
+extern VOID PeiCopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length );
+
+
+STATIC
+EFI_STATUS BotRecoveryReset (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDev )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ UINT32 Timeout;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ UINT8 EndpointAddr;
+ EFI_STATUS Status;
+
+ UsbIoPpi = PeiBotDev->UsbIoPpi;
+
+ if (UsbIoPpi == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ DevReq.RequestType = 0x21;
+ DevReq.Request = 0xff;
+ DevReq.Value = 0;
+ DevReq.Index = 0;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+
+ Status = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0
+ );
+
+ //
+ // clear bulk in endpoint stall feature
+ //
+ EndpointAddr = (PeiBotDev->BulkInEndpoint)->EndpointAddress;
+ PeiUsbClearEndpointHalt( PeiServices, UsbIoPpi, EndpointAddr );
+
+ //
+ // clear bulk out endpoint stall feature
+ //
+ EndpointAddr = (PeiBotDev->BulkOutEndpoint)->EndpointAddress;
+ PeiUsbClearEndpointHalt( PeiServices, UsbIoPpi, EndpointAddr );
+
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS BotCommandPhase (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDev,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN UINT32 DataTransferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout )
+{
+ CBW cbw;
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ UINTN DataSize;
+
+ UsbIoPpi = PeiBotDev->UsbIoPpi;
+
+ ZeroMem( &cbw, sizeof(CBW) );
+
+ //
+ // Fill the command block, detailed see BOT spec
+ //
+ cbw.dCBWSignature = CBWSIG;
+ cbw.dCBWTag = 0x01;
+ cbw.dCBWDataTransferLength = DataTransferLength;
+ cbw.bmCBWFlags = (Direction == EfiUsbDataIn)? 0x80 : 0;
+ cbw.bCBWLUN = PeiBotDev->Lun;
+ cbw.bCBWCBLength = CommandSize;
+
+ PeiCopyMem( cbw.CBWCB, Command, CommandSize );
+
+ DataSize = sizeof(CBW);
+
+ Status = UsbIoPpi->UsbBulkTransfer(
+ PeiServices,
+ UsbIoPpi,
+ (PeiBotDev->BulkOutEndpoint)->EndpointAddress,
+ (UINT8 *) &cbw,
+ &DataSize,
+ Timeout
+ );
+ if ( EFI_ERROR( Status ) ) {
+ //
+ // Command phase fail, we need to recovery reset this device
+ //
+ BotRecoveryReset( PeiServices, PeiBotDev );
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS BotDataPhase (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDev,
+ IN UINT32 *DataSize,
+ IN OUT VOID *DataBuffer,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout )
+{
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ UINT8 EndpointAddr;
+ UINTN Remain;
+ UINTN Increment;
+ UINT32 MaxPacketLen;
+ UINT8 *BufferPtr;
+ UINTN TransferredSize;
+ UINTN TransferSize;
+
+ UsbIoPpi = PeiBotDev->UsbIoPpi;
+
+ Remain = *DataSize;
+ BufferPtr = (UINT8 *) DataBuffer;
+ TransferredSize = 0;
+
+ //
+ // retrieve the the max packet length of the given endpoint
+ //
+ if (Direction == EfiUsbDataIn) {
+ MaxPacketLen = (PeiBotDev->BulkInEndpoint)->MaxPacketSize;
+ EndpointAddr = (PeiBotDev->BulkInEndpoint)->EndpointAddress;
+ }
+ else {
+ MaxPacketLen = (PeiBotDev->BulkOutEndpoint)->MaxPacketSize;
+ EndpointAddr = (PeiBotDev->BulkOutEndpoint)->EndpointAddress;
+ }
+
+ while (Remain > 0) {
+ //
+ // Using 15 packets to avoid Bitstuff error
+ //
+ if (Remain > 16 * MaxPacketLen) {
+ TransferSize = 16 * MaxPacketLen;
+ }
+ else {
+ TransferSize = Remain;
+ }
+
+ Increment = TransferSize;
+
+ Status = UsbIoPpi->UsbBulkTransfer(
+ PeiServices,
+ UsbIoPpi,
+ EndpointAddr,
+ BufferPtr,
+ &Increment,
+ Timeout
+ );
+
+ TransferredSize += Increment;
+
+ if ( EFI_ERROR( Status ) ) {
+ PeiUsbClearEndpointHalt( PeiServices, UsbIoPpi, EndpointAddr );
+ return Status;
+ }
+
+ if (Increment < TransferSize) {
+ break;
+ }
+
+ BufferPtr += Increment;
+ Remain -= Increment;
+ }
+
+ *DataSize = (UINT32) TransferredSize;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS BotStatusPhase (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDev,
+ OUT UINT8 *TransferStatus,
+ IN UINT16 Timeout )
+{
+ CSW csw;
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ UINT8 EndpointAddr;
+ UINTN DataSize;
+
+ //UINT32 Temp;
+
+ UsbIoPpi = PeiBotDev->UsbIoPpi;
+
+ ZeroMem( &csw, sizeof(CSW) );
+
+ EndpointAddr = (PeiBotDev->BulkInEndpoint)->EndpointAddress;
+
+ // DataSize = sizeof(CSW);
+ DataSize = 0x0d; //bala changed
+
+ //
+ // Get the status field from bulk transfer
+ //
+ Status = UsbIoPpi->UsbBulkTransfer(
+ PeiServices,
+ UsbIoPpi,
+ EndpointAddr,
+ &csw,
+ &DataSize,
+ Timeout
+ );
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ if (csw.dCSWSignature == CSWSIG)
+ {
+ *TransferStatus = csw.bCSWStatus;
+ }
+ else {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS PeiAtapiCommand (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDev,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN VOID *DataBuffer,
+ IN UINT32 BufferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 TimeOutInMilliSeconds )
+
+/*++
+
+ Routine Description:
+ Send ATAPI command using BOT protocol.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Command - Command buffer
+ CommandSize - Size of Command Buffer
+ DataBuffer - Data buffer
+ BufferLength - Length of Data buffer
+ Direction - Data direction of this command
+ TimeoutInMilliseconds - Timeout value in ms
+
+ Returns:
+ EFI_SUCCES - Commond succeeded.
+ EFI_DEVICE_ERROR - Command failed.
+
+ --*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS BotDataStatus = EFI_SUCCESS;
+ UINT8 TransferStatus;
+ UINT32 BufferSize;
+ UINT8 *Tmp;
+ UINT32 Temp;
+
+ Tmp = (UINT8 *) Command;
+ Temp = Tmp[0];
+ PEI_TRACE( (EFI_D_ERROR, PeiServices, "Executing ScsiCmd(%x)\n", Temp) );
+ //
+ // First send ATAPI command through Bot
+ //
+ Status = BotCommandPhase(
+ PeiServices,
+ PeiBotDev,
+ Command,
+ CommandSize,
+ BufferLength,
+ Direction,
+ TimeOutInMilliSeconds
+ );
+
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Send/Get Data if there is a Data Stage
+ //
+ switch (Direction)
+ {
+ case EfiUsbDataIn:
+ case EfiUsbDataOut:
+ BufferSize = BufferLength;
+
+ BotDataStatus = BotDataPhase(
+ PeiServices,
+ PeiBotDev,
+ &BufferSize,
+ DataBuffer,
+ Direction,
+ TimeOutInMilliSeconds
+ );
+
+ break;
+
+ case EfiUsbNoData:
+ break;
+ }
+
+ //
+ // Status Phase
+ //
+
+ Status = BotStatusPhase(
+ PeiServices,
+ PeiBotDev,
+ &TransferStatus,
+ TimeOutInMilliSeconds
+ );
+ if ( EFI_ERROR( Status ) ) {
+ BotRecoveryReset( PeiServices, PeiBotDev );
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (TransferStatus == 0x01) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return BotDataStatus;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.h b/Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.h
new file mode 100644
index 0000000..25c3e56
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.h
@@ -0,0 +1,201 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/BotPeim.h 5 11/24/12 5:47a Ryanchou $
+//
+// $Revision: 5 $
+//
+// $Date: 11/24/12 5:47a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/BotPeim.h $
+//
+// 5 11/24/12 5:47a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 4 7/10/08 6:38p Michaela
+// Updated to support OHCI controllers
+//
+// 3 4/16/07 12:46p Sivagarn
+// - Updated as per coding standard review
+// - In previous check-in, TIANO.H file is removed and AMIMAPPING.H file
+// is included
+//
+// 2 3/28/07 3:40a Meenakshim
+//
+// 1 9/22/06 12:17p Sivagarn
+// - Included Recovery code in Source
+//
+// 1 9/22/06 12:14p Sivagarn
+// - Initial checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: BotPeim.h
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//
+// This file contains a 'Sample Driver' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may be modified by the user, subject to
+// the additional terms of the license agreement
+//
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ BotPeim.h
+
+ Abstract:
+
+ BOT Transportation implementation
+
+ --*/
+
+#ifndef _PEI_BOT_PEIM_H
+#define _PEI_BOT_PEIM_H
+
+#define STATIC static
+
+#include "Atapi.h"
+#include "AmiPeiLib.h"
+
+#pragma pack(1)
+
+//
+//Bulk Only device protocol
+//
+typedef struct
+{
+ UINT32 dCBWSignature;
+ UINT32 dCBWTag;
+ UINT32 dCBWDataTransferLength;
+ UINT8 bmCBWFlags;
+ UINT8 bCBWLUN;
+ UINT8 bCBWCBLength;
+ UINT8 CBWCB[16];
+} CBW;
+
+typedef struct
+{
+ UINT32 dCSWSignature;
+ UINT32 dCSWTag;
+ UINT32 dCSWDataResidue;
+ UINT8 bCSWStatus;
+ UINT8 Filler[18];
+} CSW;
+
+#pragma pack()
+
+//
+// Status code, see Usb Bot device spec
+//
+#define CSWSIG 0x53425355
+#define CBWSIG 0x43425355
+
+EFI_STATUS
+PeiUsbInquiry (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice );
+
+EFI_STATUS
+PeiUsbTestUnitReady (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice );
+
+EFI_STATUS
+PeiUsbRequestSense (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice,
+ IN UINT8 *SenseKeyBuffer );
+
+EFI_STATUS
+PeiUsbReadCapacity (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice );
+
+EFI_STATUS
+PeiUsbReadFormattedCapacity (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice );
+
+EFI_STATUS
+PeiUsbRead10 (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice,
+ IN VOID *Buffer,
+ IN EFI_PEI_LBA Lba,
+ IN UINTN NumberOfBlocks );
+
+BOOLEAN
+IsNoMedia (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts );
+
+BOOLEAN
+IsMediaError (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts );
+
+BOOLEAN
+IsMediaChange (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts );
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UsbBotPeimSrc/PeiAtapi.c b/Core/EM/UsbRecovery/UsbBotPeimSrc/PeiAtapi.c
new file mode 100644
index 0000000..24917af
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbBotPeimSrc/PeiAtapi.c
@@ -0,0 +1,832 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/PeiAtapi.c 11 11/24/12 5:47a Ryanchou $
+//
+// $Revision: 11 $
+//
+// $Date: 11/24/12 5:47a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/PeiAtapi.c $
+//
+// 11 11/24/12 5:47a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 10 10/24/11 5:59a Ryanchou
+// [TAG] EIP69936
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB ODD recovery fail
+// [RootCause] The device needs 4 sec to respond to Inquiry command, the
+// current timeout value is 2 sec
+// [Solution] Increase the timeout value to 4 sec.
+// [Files] PeiAtapi.c
+//
+// 9 8/18/10 4:19p Olegi
+// Klockwork related fixes; EIP37978
+//
+// 8 4/06/10 3:27p Fasihm
+// EIP#31987 - Added the generic USBRecovery Fix in the module.
+//
+// 7 10/21/08 5:58p Michaela
+// Added EHCI-related fixes for issues
+// that may occur if EHCI is used before
+// USB Recovery is invoked:
+// Added SDL Tokens:
+// PEI_EHCI_PCI_BDFS and
+// PEI_EHCI_MEM_BASE_ADDRESSES.
+//
+// Removed/modified some debugging
+// development code:
+// Removed SDL Tokens:
+// USBR_DEBUG_SUPPORT and
+// USBR_SERIAL_PORT_AVAILABLE
+// Removed Elinks:
+// UsbRecoveryDebug_DIR and
+// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+// Modified SDL Token:
+// FORCE_RECOVERY to default value of 0.
+//
+// (See this module's Help documentation
+// for more information.)
+//
+// 6 7/29/08 5:51p Michaela
+// 1) Updated code to move most porting tasks to SDL
+// 2) Added more debug break points and improved interactive
+// debugging capability for when a serial port is not available.
+// 3) Updated help files
+//
+// 5 7/18/08 5:05p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 4 7/10/08 6:38p Michaela
+// Updated to support OHCI controllers
+//
+// 3 8/17/07 4:35p Ambikas
+//
+// 2 10/02/06 7:24p Sivagarn
+// - Fixed the bug in identifying partition table entries
+// - Updated function headers and converted to AMI coding standard
+//
+// 1 9/22/06 12:17p Sivagarn
+// - Included Recovery code in Source
+//
+// 1 9/22/06 12:14p Sivagarn
+// - Initial checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: PeiAtapi.C
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+// This file contains generic routines needed for USB recovery
+// PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+/*++
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+ --*/
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ PeiAtapi.c
+
+ Abstract:
+
+ Pei USB ATATPI command implementations
+
+ --*/
+
+#include "UsbBotPeim.h"
+#include "BotPeim.h"
+#include "Atapi.h"
+
+#define MAXSENSEKEY 5
+
+// External function declaration
+
+extern VOID ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size );
+
+// Function prototype
+
+VOID PeiUsbValidatePartitionTable (
+ EFI_PEI_SERVICES **PeiServices,
+ UINT8 *Buffer,
+ UINTN LastBlock,
+ UINT32 *FdEmulOffset );
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PeiUsbInquiry
+//
+// Description: This function issues the ATA Inquiry command to the USB
+// mass storage device
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *PeiBotDevice Pointer to the PEI_BOT_DEVICE structure
+//
+// Output: Return Status based on the command
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbInquiry (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice )
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+ USB_INQUIRY_DATA Idata;
+
+ // Fill command packet
+ ZeroMem( &Packet, sizeof(ATAPI_PACKET_COMMAND) );
+ ZeroMem( &Idata, sizeof(USB_INQUIRY_DATA) );
+
+ Packet.Inquiry.opcode = INQUIRY;
+ Packet.Inquiry.page_code = 0;
+ Packet.Inquiry.allocation_length = sizeof(USB_INQUIRY_DATA);
+
+ // Send command packet
+ Status = PeiAtapiCommand( PeiServices, PeiBotDevice, &Packet,
+ sizeof(ATAPI_PACKET_COMMAND), &Idata,
+ sizeof(USB_INQUIRY_DATA), EfiUsbDataIn, 4000 ); //(EIP69936)
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ( (Idata.peripheral_type & 0x1f) == 0x05 ) {
+ PeiBotDevice->DeviceType = USBCDROM;
+ PeiBotDevice->Media.BlockSize = 0x800;
+ }
+ else {
+ PeiBotDevice->DeviceType = USBFLOPPY;
+ PeiBotDevice->Media.BlockSize = 0x200;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PeiUsbTestUnitReady
+//
+// Description: This function issues the ATA Test Unit Ready command to the USB
+// mass storage device
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *PeiBotDevice Pointer to the PEI_BOT_DEVICE structure
+//
+// Output: Return Status based on the command
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbTestUnitReady (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice )
+{
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+
+ // Fill command packet
+ ZeroMem( &Packet, sizeof(ATAPI_PACKET_COMMAND) );
+ Packet.TestUnitReady.opcode = TEST_UNIT_READY;
+
+ // Send command packet
+ Status = PeiAtapiCommand( PeiServices, PeiBotDevice, &Packet,
+ sizeof(ATAPI_PACKET_COMMAND), NULL, 0, EfiUsbNoData,
+ 2000 );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PeiUsbRequestSense
+//
+// Description: This function issues the ATA Request Sense command to the USB
+// mass storage device
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *PeiBotDevice Pointer to the PEI_BOT_DEVICE structure
+// *SenseCounts Buffer to return sense key data
+// *SenseKeyBuffer Buffer used for internal use
+//
+// Output: Return Status based on the command
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbRequestSense (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice,
+ IN UINT8 *SenseKeyBuffer )
+{
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+
+ // Fill command packet for Request Sense Packet Command
+ ZeroMem( &Packet, sizeof(ATAPI_PACKET_COMMAND) );
+ Packet.RequestSence.opcode = REQUEST_SENSE;
+ Packet.RequestSence.allocation_length = sizeof(REQUEST_SENSE_DATA);
+
+
+ // Send out Request Sense Packet Command and get one Sense
+ // data form device.
+ Status = PeiAtapiCommand( PeiServices, PeiBotDevice, &Packet,
+ sizeof(ATAPI_PACKET_COMMAND),
+ (VOID *) SenseKeyBuffer,
+ sizeof(REQUEST_SENSE_DATA),
+ EfiUsbDataIn,
+ 2000 );
+
+ // Failed to get Sense data
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PeiUsbReadCapacity
+//
+// Description: This function issues the ATA Read Capacity command to the USB
+// mass storage device
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *PeiBotDevice Pointer to the PEI_BOT_DEVICE structure
+//
+// Output: Return Status based on the command
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbReadCapacity (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice )
+{
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ READ_CAPACITY_DATA Data;
+ UINT8 Buffer[512];
+
+
+ ZeroMem( &Data, sizeof(READ_CAPACITY_DATA) );
+ ZeroMem( &Packet, sizeof(ATAPI_PACKET_COMMAND) );
+
+ Packet.Inquiry.opcode = READ_CAPACITY;
+
+ // Send command packet
+ Status = PeiAtapiCommand( PeiServices, PeiBotDevice, &Packet,
+ sizeof(ATAPI_PACKET_COMMAND),
+ (VOID *) &Data,
+ sizeof(READ_CAPACITY_DATA),
+ EfiUsbDataIn,
+ 2000 );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ PeiBotDevice->Media.LastBlock = (Data.LastLba3 << 24) |
+ (Data.LastLba2 << 16) |
+ (Data.LastLba1 << 8) |
+ Data.LastLba0;
+
+ // AMI Changes ->>
+ //This is the right place to set Medium BlockSize.
+ PeiBotDevice->Media.BlockSize = (Data.BlockSize3 << 24) |
+ (Data.BlockSize2 << 16) |
+ (Data.BlockSize1 << 8) |
+ Data.BlockSize0;
+ // <-- AMI Changes
+
+ PeiBotDevice->Media.MediaPresent = TRUE;
+
+ // BIOS Forced FDD option to emulate USB Key Hard Drive as Floppy
+ // Do Floppy emulation only for Harddrive/Direct Access Device
+ if (PeiBotDevice->DeviceType == USBFLOPPY) {
+ Status = PeiUsbRead10( PeiServices, PeiBotDevice, Buffer,
+ 0, /*StartLBA*/ 1 /*NumberOfBlocks*/ );
+ if ( EFI_ERROR( Status ) ) {
+ // Don't return error, as this shouldn't
+ // messup with ReadCapacity
+ return EFI_SUCCESS;
+ }
+ PeiUsbValidatePartitionTable( PeiServices, Buffer,
+ PeiBotDevice->Media.LastBlock, &(PeiBotDevice->FdEmulOffset) );
+ }
+ return EFI_SUCCESS;
+}
+
+
+// AMI Changes ->>
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PeiUsbValidatePartitionTable
+//
+// Description: This function validates the existence of the partition table
+// from the LBA 0 data provided and return FdEmulOffset value
+// (hidden sector) from the partition table
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *Buffer Pointer to the buffer containing LBA 0
+// data
+// LastBlock Last LBA address
+//
+// *FdEmulOffset Returned FD emulation hidden sector value
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID PeiUsbValidatePartitionTable (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT8 *Buffer,
+ IN UINTN LastBlock,
+ OUT UINT32 *FdEmulOffset )
+{
+ UINT8 i;
+ UINT8 *pTable = Buffer + 0x1be; // Start offset of partition
+ // table
+ UINT8 *active_partition_addr = NULL;
+ UINT8 PartitionFound = 0; // Total number of valid
+ // partitions
+ UINT8 *PartitionTableEntries[4];
+
+ for (i = 0; i < 4; i++) {
+ PartitionTableEntries[i] = 0;
+
+ // Boot flag check added to ensure that boot sector will not be
+ // treated as a valid partation table.
+ if (*pTable & 0x7f) {
+ return; // BootFlag should be 0x0 or 0x80
+
+ }
+ // Check whether beginning LBA is reasonable
+ if (*(UINT32 *) (pTable + 8) > LastBlock) {
+ return;
+ }
+
+ // Check whether the size is reasonable
+
+ /** This check has to be refined
+ #if HDD_PART_SIZE_CHECK
+ if (*(UINT32*)(pTable + 0xc) > LastBlock)
+ return;
+ #endif
+ **/
+ PartitionFound++;
+ PartitionTableEntries[i] = pTable;
+ // Update active entry offset
+ if (*pTable & 0x80) {
+ active_partition_addr = pTable;
+ }
+
+ pTable += 0x10; //Get next Partition
+ }
+
+ if (PartitionFound == 0) {
+ return;
+ }
+
+ // If no active partition table entry found use first entry
+ if (active_partition_addr == NULL) {
+ for (i = 0; (i < 4) && !PartitionTableEntries[i]; i++) {
+ ;
+ }
+ if (i == 4) return;
+ active_partition_addr = PartitionTableEntries[i];
+ }
+
+ *FdEmulOffset = *( (UINT32 *) (active_partition_addr + 8) );
+ PEI_TRACE( (EFI_D_ERROR, PeiServices,
+ "USBPEIM: PeiUsbValidatePartitionTable() FdEmulOffset %x\n",
+ *FdEmulOffset) );
+}
+
+
+// <-- AMI Changes
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PeiUsbReadFormattedCapacity
+//
+// Description: This function issues the ATA Read Formatted Capacity command
+// to the USB mass storage device
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *PeiBotDevice Pointer to the PEI_BOT_DEVICE structure
+//
+// Output: Return Status based on the command
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbReadFormattedCapacity (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice )
+{
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ READ_FORMAT_CAPACITY_DATA FormatData;
+
+ ZeroMem( &FormatData, sizeof(READ_FORMAT_CAPACITY_DATA) );
+ ZeroMem( &Packet, sizeof(ATAPI_PACKET_COMMAND) );
+
+ Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY;
+ Packet.ReadFormatCapacity.allocation_length_lo = 12;
+
+ // Send command packet
+ Status = PeiAtapiCommand( PeiServices, PeiBotDevice, &Packet,
+ sizeof(ATAPI_PACKET_COMMAND), (VOID *) &FormatData,
+ sizeof(READ_FORMAT_CAPACITY_DATA), EfiUsbDataIn, 2000 );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (FormatData.DesCode == 3) {
+ // Media is not present
+ PeiBotDevice->Media.MediaPresent = FALSE;
+ PeiBotDevice->Media.LastBlock = 0;
+ }
+ else {
+ PeiBotDevice->Media.LastBlock = (FormatData.LastLba3 << 24) |
+ (FormatData.LastLba2 << 16) |
+ (FormatData.LastLba1 << 8) |
+ FormatData.LastLba0;
+
+ PeiBotDevice->Media.LastBlock--;
+ PeiBotDevice->Media.MediaPresent = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PeiUsbRead10
+//
+// Description: This function issues the ATA Read (10) command to the USB
+// mass storage device
+//
+// Input: **PeiServices Pointer to the PEI services table
+// *PeiBotDevice Pointer to the PEI_BOT_DEVICE structure
+// *Buffer Buffer to read the data into
+// Lba Start LBA Number
+// NumberOfBlocks Number of blocks to read
+//
+// Output: Return Status based on the command
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiUsbRead10 (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDevice,
+ IN VOID *Buffer,
+ IN EFI_PEI_LBA Lba,
+ IN UINTN NumberOfBlocks )
+{
+ VOID *ptrBuffer;
+ UINT16 MaxBlock;
+ UINT16 BlocksRemaining;
+ UINT16 SectorCount;
+ UINT16 TimeOut;
+ // UINT32 BufferSize;
+ UINT32 Lba32;
+ UINT32 BlockSize;
+ UINT32 ByteCount;
+ EFI_STATUS Status;
+ READ10_CMD *Read10Packet;
+ ATAPI_PACKET_COMMAND Packet;
+
+ // Prepare command packet for the Inquiry Packet Command.
+ ZeroMem( &Packet, sizeof(ATAPI_PACKET_COMMAND) );
+ Read10Packet = &Packet.Read10;
+ Lba32 = (UINT32) Lba;
+ ptrBuffer = Buffer;
+
+ BlockSize = (UINT32) PeiBotDevice->Media.BlockSize;
+ // AMI Changes -->
+ MaxBlock = (UINT16) (65536 / BlockSize);
+ // BufferSize = NumberOfBlocks * BlockSize;
+ // MaxBlock = (UINT16)(BufferSize /BlockSize);
+ // <-- AMI Changes
+ BlocksRemaining = (UINT16) NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while (BlocksRemaining > 0) {
+ if (BlocksRemaining <= MaxBlock) {
+ SectorCount = BlocksRemaining;
+ }
+ else {
+ SectorCount = MaxBlock;
+ }
+
+ // Fill the Packet data structure
+ Read10Packet->opcode = READ_10;
+
+ // Lba0 ~ Lba3 specify the start logical block
+ // address of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
+ Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
+ Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
+ Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
+
+ // TranLen0 ~ TranLen1 specify the transfer length in block unit.
+ // TranLen0 is MSB, TranLen is LSB
+ Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
+ Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
+
+ ByteCount = SectorCount * BlockSize;
+
+ TimeOut = (UINT16) (SectorCount * 2000);
+
+ // Send command packet
+ Status = PeiAtapiCommand( PeiServices, PeiBotDevice, &Packet,
+ sizeof(ATAPI_PACKET_COMMAND), (VOID *) ptrBuffer, ByteCount,
+ EfiUsbDataIn, TimeOut );
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
+ BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsNoMedia
+//
+// Description: This function verifies whether Media is present in the drive
+// or not by checking the Sense Data obtained from the drive
+//
+// Input: *SenseData Sense data obtained from the drive
+// SenseCounts Sense count value
+//
+// Output: Returns TRUE if media is present
+// FALSE otherwise
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsNoMedia (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts )
+{
+ UINTN i;
+ BOOLEAN NoMedia;
+ REQUEST_SENSE_DATA *SensePtr;
+
+ NoMedia = FALSE;
+ SensePtr = SenseData;
+
+ for (i = 0; i < SenseCounts; i++) {
+ switch (SensePtr->sense_key)
+ {
+ case SK_NOT_READY:
+ switch (SensePtr->addnl_sense_code)
+ {
+ // If no media, fill IdeDev parameter with specific info.
+ case ASC_NO_MEDIA:
+ NoMedia = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ SensePtr++;
+ }
+
+ return NoMedia;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsMediaError
+//
+// Description: This function verifies whether Media access is having problem
+// or not by checking the Sense Data obtained from the drive
+//
+// Input: *SenseData Sense data obtained from the drive
+// SenseCounts Sense count value
+//
+// Output: Returns TRUE if media has error
+// FALSE otherwise
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsMediaError (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts )
+{
+ UINTN i;
+ BOOLEAN Error;
+ REQUEST_SENSE_DATA *SensePtr;
+
+ SensePtr = SenseData;
+ Error = FALSE;
+
+ for (i = 0; i < SenseCounts; i++) {
+ switch (SensePtr->sense_key)
+ {
+ // Medium error case
+ case SK_MEDIUM_ERROR:
+ switch (SensePtr->addnl_sense_code)
+ {
+ case ASC_MEDIA_ERR1: // fall through
+ case ASC_MEDIA_ERR2: // fall through
+ case ASC_MEDIA_ERR3: // fall through
+ case ASC_MEDIA_ERR4:
+ Error = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ // Medium upside-down case
+ case SK_NOT_READY:
+ switch (SensePtr->addnl_sense_code)
+ {
+ case ASC_MEDIA_UPSIDE_DOWN:
+ Error = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ SensePtr++;
+ }
+
+ return Error;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsMediaChange
+//
+// Description: This function verifies whether Media change had happened
+// or not by checking the Sense Data obtained from the drive
+//
+// Input: *SenseData Sense data obtained from the drive
+// SenseCounts Sense count value
+//
+// Output: Returns TRUE if media has changed
+// FALSE otherwise
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN IsMediaChange (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts )
+{
+ UINTN i;
+ BOOLEAN MediaChange;
+ REQUEST_SENSE_DATA *SensePtr;
+
+ MediaChange = FALSE;
+ SensePtr = SenseData;
+ for (i = 0; i < SenseCounts; i++) {
+ // Catch media change sense key and addition sense data
+ switch (SensePtr->sense_key)
+ {
+ case SK_UNIT_ATTENTION:
+ switch (SensePtr->addnl_sense_code)
+ {
+ case ASC_MEDIA_CHANGE:
+ MediaChange = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ SensePtr++;
+ }
+
+ return MediaChange;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.c b/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.c
new file mode 100644
index 0000000..6a0ce90
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.c
@@ -0,0 +1,726 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/UsbBotPeim.c 13 11/24/12 5:47a Ryanchou $
+//
+// $Revision: 13 $
+//
+// $Date: 11/24/12 5:47a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/UsbBotPeim.c $
+//
+// 13 11/24/12 5:47a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 12 4/16/11 3:42a Ryanchou
+// [TAG] EIP50311
+// [Category] New Feature
+// [Description] Multiple LUN device support added.
+// [Files] BotPeim.c, UsbBotPeim.c, UsbBotPeim.h
+//
+// 11 10/12/10 11:20a Olegi
+// XHCI support added.
+//
+// 10 2/23/10 3:36p Olegi
+// Bugfixes found by Coverity tests: EIP34507.
+//
+// 9 3/03/09 7:22p Olegi
+// Added EHCI support.
+//
+// 8 10/21/08 5:58p Michaela
+// Added EHCI-related fixes for issues
+// that may occur if EHCI is used before
+// USB Recovery is invoked:
+// Added SDL Tokens:
+// PEI_EHCI_PCI_BDFS and
+// PEI_EHCI_MEM_BASE_ADDRESSES.
+//
+// Removed/modified some debugging
+// development code:
+// Removed SDL Tokens:
+// USBR_DEBUG_SUPPORT and
+// USBR_SERIAL_PORT_AVAILABLE
+// Removed Elinks:
+// UsbRecoveryDebug_DIR and
+// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+// Modified SDL Token:
+// FORCE_RECOVERY to default value of 0.
+//
+// (See this module's Help documentation
+// for more information.)
+//
+// 7 7/29/08 5:51p Michaela
+// 1) Updated code to move most porting tasks to SDL
+// 2) Added more debug break points and improved interactive
+// debugging capability for when a serial port is not available.
+// 3) Updated help files
+//
+// 6 7/18/08 5:05p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 5 7/10/08 6:38p Michaela
+// Updated to support OHCI controllers
+//
+// 4 10/23/07 5:42p Ambikas
+//
+// 3 8/17/07 4:35p Ambikas
+//
+// 2 8/17/07 4:11p Ambikas
+//
+// 1 9/22/06 12:17p Sivagarn
+// - Included Recovery code in Source
+//
+// 1 9/22/06 12:14p Sivagarn
+// - Initial checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbbotPeim.C
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+// This file contains generic routines needed for USB recovery
+// PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+/*++
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+ --*/
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ UsbBotPeim.c
+
+ Abstract:
+
+ Usb Bus PPI
+
+ --*/
+
+#include "UsbBotPeim.h"
+#include "BotPeim.h"
+#define PAGESIZE 4096
+#include EFI_PPI_DEFINITION( Stall )
+#include EFI_PPI_DEFINITION( LoadFile )
+
+static EFI_GUID gPeiStallPpiGuid = PEI_STALL_PPI_GUID;
+static EFI_GUID gPeiBlockIoPpiGuid = EFI_PEI_VIRTUAL_BLOCK_IO_PPI;
+static EFI_GUID gPeiUsbIoPpiGuid = PEI_USB_IO_PPI_GUID;
+
+//
+// Global function
+//
+STATIC
+EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH |
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gPeiUsbIoPpiGuid,
+ NotifyOnUsbIoPpi
+};
+
+STATIC
+EFI_PEI_RECOVERY_BLOCK_IO_PPI mRecoveryBlkIoPpi = {
+ BotGetNumberOfBlockDevices,
+ BotGetMediaInfo,
+ BotReadBlocks
+};
+
+STATIC
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gPeiBlockIoPpiGuid,
+ NULL
+};
+
+//
+// Driver Entry Point
+//
+EFI_STATUS
+PeimInitializeUsbBot (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+
+STATIC
+EFI_STATUS
+PeiBotDetectMedia (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDev );
+
+EFI_STATUS PeimInitializeUsbBot (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ EFI_STATUS Status;
+ UINTN UsbIoPpiInstance;
+ EFI_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ UINTN PpiInstance;
+
+ for (PpiInstance = 0; PpiInstance < PEI_MAX_USB_RECOVERY_INIT_PPI; PpiInstance++)
+ {
+ PEI_USB_CHIP_INIT_PPI *UsbChipsetRecoveryInitPpi;
+ static EFI_GUID gPeiChipUsbRecoveryInitPpiGuid = PEI_USB_CHIP_INIT_PPI_GUID;
+
+ Status = (**PeiServices).LocatePpi( PeiServices, &gPeiChipUsbRecoveryInitPpiGuid,
+ PpiInstance, NULL, &UsbChipsetRecoveryInitPpi );
+ if (EFI_ERROR( Status ) ) break;
+
+ UsbChipsetRecoveryInitPpi->EnableChipUsbRecovery(PeiServices);
+ }
+
+ #if (PEI_EHCI_SUPPORT == 1)
+ EhciPeiUsbEntryPoint( FfsHeader, PeiServices );
+ #endif
+ #if (PEI_UHCI_SUPPORT == 1)
+ UhciPeiUsbEntryPoint( FfsHeader, PeiServices );
+ UhcPeimEntry( FfsHeader, PeiServices );
+ #endif
+ #if (PEI_OHCI_SUPPORT == 1)
+ OhciPeiUsbEntryPoint( FfsHeader, PeiServices ); // 0xff02
+ #endif
+ #if (PEI_XHCI_SUPPORT == 1)
+ XhciPeiUsbEntryPoint( FfsHeader, PeiServices ); // 0xff02
+ #endif
+ PeimInitializeUsb( FfsHeader, PeiServices ); // 0xff05
+
+
+ //
+ // locate all usb io PPIs
+ //
+ for (UsbIoPpiInstance = 0;
+ UsbIoPpiInstance < PEI_FAT_MAX_USB_IO_PPI;
+ UsbIoPpiInstance++)
+ {
+ Status = (**PeiServices).LocatePpi( PeiServices,
+ &gPeiUsbIoPpiGuid,
+ UsbIoPpiInstance,
+ &TempPpiDescriptor,
+ &UsbIoPpi
+ );
+ if ( EFI_ERROR( Status ) ) {
+ break;
+ }
+
+ InitUsbBot( PeiServices, UsbIoPpi );
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS NotifyOnUsbIoPpi (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *InvokePpi )
+{
+ PEI_USB_IO_PPI *UsbIoPpi;
+
+ UsbIoPpi = (PEI_USB_IO_PPI *) InvokePpi;
+
+ InitUsbBot( PeiServices, UsbIoPpi );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS GetMaxLun (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ OUT UINT8 *MaxLun )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 Timeout;
+
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = 0xA1;
+ DevReq.Request = 0x0FE;
+ DevReq.Value = 0;
+ DevReq.Index = Port;
+ DevReq.Length = sizeof(UINT8);
+
+ Timeout = 3000;
+
+ EfiStatus = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ UsbDataIn,
+ Timeout,
+ MaxLun,
+ sizeof(UINT8)
+ );
+
+ return EfiStatus;
+}
+
+
+EFI_STATUS InitUsbBot (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi )
+{
+ STATIC UINTN UsbIoPpiIndex = 0;
+
+ PEI_BOT_DEVICE *PeiBotDevice;
+ EFI_STATUS Status;
+ EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDesc;
+ UINT8 *AllocateAddress;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc;
+ UINT8 i;
+ UINT8 MaxLun = 0;
+ UINT8 CurrentLun;
+
+ //
+ // Check its interface
+ //
+ Status = UsbIoPpi->UsbGetInterfaceDescriptor( PeiServices,
+ UsbIoPpi, &InterfaceDesc );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ //
+ // Check if it is the BOT device we support
+ //
+
+ if ( (InterfaceDesc->InterfaceClass != BASE_CLASS_MASS_STORAGE)
+ || (InterfaceDesc->InterfaceProtocol != PROTOCOL_BOT) ) {
+
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetMaxLun(PeiServices,UsbIoPpi,InterfaceDesc->InterfaceNumber,&MaxLun);
+
+ for(CurrentLun = 0; CurrentLun <= MaxLun; CurrentLun++) {
+
+ Status = (*PeiServices)->AllocatePool( PeiServices,
+ sizeof(PEI_BOT_DEVICE), &AllocateAddress );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ PeiBotDevice = (PEI_BOT_DEVICE *) ( (UINTN) AllocateAddress );
+ (**PeiServices).SetMem(PeiBotDevice, sizeof(PEI_BOT_DEVICE), 0);
+
+ PeiBotDevice->Signature = PEI_BOT_DEVICE_SIGNATURE;
+ PeiBotDevice->UsbIoPpi = UsbIoPpi;
+ PeiBotDevice->BotInterface = InterfaceDesc;
+ PeiBotDevice->FdEmulOffset = 0; //bala
+ //
+ // Default value
+ //
+ PeiBotDevice->Media.DeviceType = UsbMassStorage;
+ PeiBotDevice->Media.BlockSize = 0x200;
+ PeiBotDevice->Lun = CurrentLun;
+
+ //
+ // Check its Bulk-in/Bulk-out endpoint
+ //
+ for (i = 0; i < 2; i++) {
+ Status = UsbIoPpi->UsbGetEndpointDescriptor( PeiServices,
+ UsbIoPpi, i, &EndpointDesc );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ if (EndpointDesc->Attributes != 2) {
+ continue;
+ }
+
+ if ( (EndpointDesc->EndpointAddress & 0x80) != 0 ) {
+ PeiBotDevice->BulkInEndpoint = EndpointDesc;
+ }
+ else {
+ PeiBotDevice->BulkOutEndpoint = EndpointDesc;
+ }
+
+ }
+
+ PeiBotDevice->BlkIoPpi = mRecoveryBlkIoPpi;
+ PeiBotDevice->BlkIoPpiList = mPpiList;
+ PeiBotDevice->BlkIoPpiList.Ppi = &PeiBotDevice->BlkIoPpi;
+
+ Status = PeiUsbInquiry( PeiServices, PeiBotDevice );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ Status = (**PeiServices).InstallPpi( PeiServices,
+ &PeiBotDevice->BlkIoPpiList );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS BotGetNumberOfBlockDevices (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ OUT UINTN *NumberBlockDevices )
+{
+ //
+ // For Usb devices, this value should be always 1
+ //
+
+ *NumberBlockDevices = 1;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS BotGetMediaInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo )
+{
+ PEI_BOT_DEVICE *PeiBotDev;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ PeiBotDev = PEI_BOT_DEVICE_FROM_THIS( This );
+
+ Status = PeiBotDetectMedia(
+ PeiServices,
+ PeiBotDev
+ );
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ *MediaInfo = PeiBotDev->Media;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS PeiBotDetectMedia (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDev )
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 *AllocateAddress;
+ REQUEST_SENSE_DATA *SensePtr;
+ UINT8 SenseKey, ASC, ASCQ;
+ UINT8 RetryCount, RetryReq = 0;
+ PEI_STALL_PPI *StallPpi;
+ UINT32 Temp;
+ UINT32 Temp1, Temp2, Temp3;
+
+ //PeiUsbReadCapacity fills PeiBotDev structure for
+ //BlockSize, LastBlock, Media Present
+ for (RetryCount = 0; RetryCount < 25; RetryCount++)
+ {
+ Status = PeiUsbReadCapacity(
+ PeiServices,
+ PeiBotDev
+ );
+
+ if ( EFI_ERROR( Status ) )
+ {
+ Temp = RetryCount;
+
+ //If ReadCapcity fails, then find out type of error
+ if (RetryCount == 0)
+ {
+ if (PeiBotDev->SensePtr == NULL) {
+ //During the first retry allocate the memory
+ Status = (**PeiServices).AllocatePool(
+ PeiServices,
+ sizeof(REQUEST_SENSE_DATA),
+ &AllocateAddress
+ );
+ if ( EFI_ERROR( Status ) )
+ {
+ return Status;
+ }
+ PeiBotDev->SensePtr = (REQUEST_SENSE_DATA *)AllocateAddress;
+ }
+ SensePtr = PeiBotDev->SensePtr;
+ (**PeiServices).SetMem((VOID*)SensePtr, sizeof(REQUEST_SENSE_DATA), 0);
+ Status = (**PeiServices).LocatePpi( PeiServices,
+ &gPeiStallPpiGuid, 0, NULL, &StallPpi );
+ }
+
+ Status = PeiUsbRequestSense(
+ PeiServices,
+ PeiBotDev,
+ (UINT8 *) SensePtr
+ );
+ if ( EFI_ERROR( Status ) )
+ {
+ //If RequestSense also fails, then there is an serious error
+ //Return to the caller with appropriate error code
+ // PeiBotDev->Media.MediaPresent = FALSE;
+ // PeiBotDev->Media.BlockSize = 0;
+ // Status = EFI_DEVICE_ERROR;
+ // return EFI_DEVICE_ERROR;
+ }
+ //TODO:Parse the sense buffer for the error
+ //If media getting ready, then wait for few mSec, then
+ //retry ReadCapacity
+ //For all other errors, return with error condition
+
+ SenseKey = SensePtr->sense_key;
+ ASC = SensePtr->addnl_sense_code;
+ ASCQ = SensePtr->addnl_sense_code_qualifier;
+ Temp1 = SenseKey;
+ Temp2 = ASC;
+ Temp3 = ASCQ;
+
+ if ( (SenseKey == 0x02) && (ASC == 0x3a) && (ASCQ == 00) )
+ {
+ //medium Not Present.
+ //Don't retry.
+ return EFI_DEVICE_ERROR;
+
+ }
+ // The following retry logic is broken, assigning RetryReq 1 does
+ // not make sense and leads to a dead code later: "if (!RetryReq)"
+ // Remove this assignment. EIP34507
+ //For all error retry ReadCapacity 25 times
+ //RetryReq = 1; //Do retry
+ if (SenseKey == 0x02)
+ {
+ //Logical Unit Problem
+ if (ASC == 0x04)
+ {
+ //Becoming Ready/Init Required/ Busy/ Format in Progress.
+ RetryReq = 1; //Do retry
+
+ }
+ if ( (ASC == 0x06) || (ASC == 0x08) )
+ {
+ //No ref. found/ Comm failure
+ RetryReq = 1; //Do retry
+ }
+ }
+
+
+ PeiBotDev->Media.MediaPresent = FALSE;
+ PeiBotDev->Media.BlockSize = 0;
+ Status = EFI_DEVICE_ERROR;
+ if (!RetryReq) {
+ return Status;
+ }
+ }
+ else {
+ Status = EFI_SUCCESS;
+ return Status; //Command Passed so return to caller
+ }
+
+ //Wait for 100 msec
+ StallPpi->Stall( PeiServices, StallPpi, 100 * 1000 );
+ }
+ return Status;
+}
+
+
+EFI_STATUS BotReadBlocks (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ IN EFI_PEI_LBA StartLBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer )
+{
+ PEI_BOT_DEVICE *PeiBotDev;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINT8 *AllocateAddress;
+ REQUEST_SENSE_DATA *SensePtr;
+ UINT8 SenseKey, ASC, ASCQ;
+ UINT8 RetryCount;
+ PEI_STALL_PPI *StallPpi;
+ UINT32 Temp1, Temp2, Temp3;
+
+ PeiBotDev = PEI_BOT_DEVICE_FROM_THIS( This );
+
+ Temp1 = (UINT32) StartLBA;
+
+ StartLBA += PeiBotDev->FdEmulOffset;
+
+ //
+ // Check parameters
+ //
+ if (Buffer == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0)
+ {
+ return EFI_SUCCESS;
+ }
+
+ BlockSize = PeiBotDev->Media.BlockSize;
+
+ if (BufferSize % BlockSize != 0)
+ {
+ Status = EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (!PeiBotDev->Media.MediaPresent)
+ {
+ return EFI_NO_MEDIA;
+ }
+
+ if (StartLBA > PeiBotDev->Media.LastBlock)
+ {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ NumberOfBlocks = BufferSize / (PeiBotDev->Media.BlockSize);
+
+ for (RetryCount = 0; RetryCount < 3; RetryCount++)
+ {
+ Status = PeiUsbRead10(
+ PeiServices,
+ PeiBotDev,
+ Buffer,
+ StartLBA,
+ NumberOfBlocks
+ );
+ if ( EFI_ERROR( Status ) )
+ {
+
+ if (RetryCount == 0)
+ {
+ if (PeiBotDev->SensePtr == NULL) {
+ Status = (**PeiServices).AllocatePool(
+ PeiServices,
+ sizeof(REQUEST_SENSE_DATA),
+ &AllocateAddress
+ );
+ if ( EFI_ERROR( Status ) )
+ {
+ return Status;
+ }
+ PeiBotDev->SensePtr = (REQUEST_SENSE_DATA *) AllocateAddress;
+ }
+ SensePtr = PeiBotDev->SensePtr;
+ (**PeiServices).SetMem((VOID*)SensePtr, sizeof(REQUEST_SENSE_DATA), 0);
+ Status = (**PeiServices).LocatePpi( PeiServices,
+ &gPeiStallPpiGuid, 0, NULL, &StallPpi );
+ }
+
+ Status = PeiUsbRequestSense(
+ PeiServices,
+ PeiBotDev,
+ (UINT8 *) SensePtr
+ );
+ if ( EFI_ERROR( Status ) )
+ {
+ //If RequestSense also fails, then there is an serious error
+ //Return to the caller with appropriate error code
+ return EFI_DEVICE_ERROR;
+ }
+ //TODO:Parse the sense buffer for the error
+ //If media getting ready, then wait for few mSec, then
+ //retry ReadCapacity
+ //For all other errors, return with error condition
+
+ SenseKey = SensePtr->sense_key;
+ ASC = SensePtr->addnl_sense_code;
+ ASCQ = SensePtr->addnl_sense_code_qualifier;
+ Temp1 = SenseKey;
+ Temp2 = ASC;
+ Temp3 = ASCQ;
+ StallPpi->Stall( PeiServices, StallPpi, 9000 );
+
+ }
+ break; //break the for loop
+ }
+ return EFI_SUCCESS;
+
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.cif b/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.cif
new file mode 100644
index 0000000..ec62a8d
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.cif
@@ -0,0 +1,14 @@
+<component>
+ name = "UsbBotPeimSrc"
+ category = ModulePart
+ LocalRoot = "Core\em\UsbRecovery\UsbBotPeimSrc"
+ RefName = "UsbBotPeimSrc"
+[files]
+"UsbBotPeim.dxs" = "dxs"
+"BotPeim.c"
+"BotPeim.h"
+"PeiAtapi.c"
+"UsbBotPeim.c"
+"UsbBotPeim.h"
+"atapi.h"
+<endComponent>
diff --git a/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.dxs b/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.dxs
new file mode 100644
index 0000000..baa6bb6
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.dxs
@@ -0,0 +1,106 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/UsbBotPeim.dxs 4 7/10/08 6:38p Michaela $
+//
+// $Revision: 4 $
+//
+// $Date: 7/10/08 6:38p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/UsbBotPeim.dxs $
+//
+// 4 7/10/08 6:38p Michaela
+// Updated to support OHCI controllers
+//
+// 3 10/23/07 5:41p Ambikas
+//
+// 2 8/17/07 4:12p Ambikas
+//
+// 1 9/22/06 12:17p Sivagarn
+// - Included Recovery code in Source
+//
+// 1 9/22/06 12:14p Sivagarn
+// - Initial checkin
+// - Included Recovery code in Source
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbBotPeim.DXS
+//
+// Description: This file is the dependency file for the USB BOT protocol PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+/*++
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+--*/
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ UsbBotPeim.dxs
+
+Abstract:
+
+ Dependency expression file for Usb Bot PEIM.
+ PEI_USB_IO_PPI_GUID AND
+--*/
+
+#include "pei.h"
+#include "ppi\LoadFile.h"
+#include "ppi\UsbIo.h"
+
+DEPENDENCY_START
+ EFI_PEI_FV_FILE_LOADER_GUID AND
+ EFI_PEI_BOOT_IN_RECOVERY_MODE_PEIM_PPI AND
+ EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI
+DEPENDENCY_END
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.h b/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.h
new file mode 100644
index 0000000..92a8668
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.h
@@ -0,0 +1,362 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/UsbBotPeim.h 12 11/24/12 5:47a Ryanchou $
+//
+// $Revision: 12 $
+//
+// $Date: 11/24/12 5:47a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/UsbBotPeim.h $
+//
+// 12 11/24/12 5:47a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 11 4/16/11 3:42a Ryanchou
+// [TAG] EIP50311
+// [Category] New Feature
+// [Description] Multiple LUN device support added.
+// [Files] BotPeim.c, UsbBotPeim.c, UsbBotPeim.h
+//
+// 10 10/12/10 11:20a Olegi
+// XHCI support added.
+//
+// 9 3/03/09 7:23p Olegi
+// Added EHCI support.
+//
+// 8 10/21/08 5:58p Michaela
+// Added EHCI-related fixes for issues
+// that may occur if EHCI is used before
+// USB Recovery is invoked:
+// Added SDL Tokens:
+// PEI_EHCI_PCI_BDFS and
+// PEI_EHCI_MEM_BASE_ADDRESSES.
+//
+// Removed/modified some debugging
+// development code:
+// Removed SDL Tokens:
+// USBR_DEBUG_SUPPORT and
+// USBR_SERIAL_PORT_AVAILABLE
+// Removed Elinks:
+// UsbRecoveryDebug_DIR and
+// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+// Modified SDL Token:
+// FORCE_RECOVERY to default value of 0.
+//
+// (See this module's Help documentation
+// for more information.)
+//
+// 7 7/29/08 5:51p Michaela
+// 1) Updated code to move most porting tasks to SDL
+// 2) Added more debug break points and improved interactive
+// debugging capability for when a serial port is not available.
+// 3) Updated help files
+//
+// 6 7/18/08 5:05p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 5 7/10/08 6:38p Michaela
+// Updated to support OHCI controllers
+//
+// 4 8/17/07 4:11p Ambikas
+//
+// 3 4/16/07 12:49p Sivagarn
+// - Updated as per coding standard review
+// - In previous check-in, TIANO.H file is removed and AMIMAPPING.H file
+// is included
+//
+// 2 3/28/07 3:52a Meenakshim
+//
+// 1 9/22/06 12:17p Sivagarn
+// - Included Recovery code in Source
+//
+// 1 9/22/06 12:14p Sivagarn
+// - Initial checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbBotPeim.h
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+//
+// This file contains a 'Sample Driver' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may be modified by the user, subject to
+// the additional terms of the license agreement
+//
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ UsbBotPeim.h
+
+ Abstract:
+
+ Usb BOT Peim definition
+
+ --*/
+
+#ifndef _PEI_USB_BOT_PEIM_H
+#define _PEI_USB_BOT_PEIM_H
+
+#include "Efi.h"
+#include "Pei.h"
+// #include "PeiLib.h"
+#include "usb.h"
+#include "Atapi.h"
+#include "AmiMapping.h"
+
+//
+// Driver consumed PPI Prototypes
+//
+#include "Include\Ppi\UsbIo.h"
+
+//
+// Driver produces PPI Prototypes
+//
+#include "Include\Ppi\DeviceRecoveryBlockIo.h"
+#include <Token.h>
+
+#define PEI_FAT_MAX_USB_IO_PPI 127
+
+//---------------------------------------------------------------------------
+// Values for InterfaceDescriptor.BaseClass
+//---------------------------------------------------------------------------
+#define BASE_CLASS_HID 0x03
+#define BASE_CLASS_MASS_STORAGE 0x08
+#define BASE_CLASS_HUB 0x09
+//----------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Values for InterfaceDescriptor.Protocol
+//---------------------------------------------------------------------------
+#define PROTOCOL_KEYBOARD 0x01 // Keyboard device protocol
+#define PROTOCOL_MOUSE 0x02 // Mouse device protocol?
+
+// Mass storage related protocol equates
+#define PROTOCOL_CBI 0x00 // Mass Storage Control/Bulk/Interrupt
+ // with command completion interrupt
+#define PROTOCOL_CBI_NO_INT 0x01 // MASS STORAGE Control/Bulk/Interrupt
+ // with NO command completion interrupt
+#define PROTOCOL_BOT 0x50 // Mass Storage Bulk-Only Transport
+#define PROTOCOL_VENDOR 0xff // Vendor specific mass protocol
+//---------------------------------------------------------------------------
+
+//
+// BlockIo PPI prototype
+//
+EFI_STATUS
+BotGetNumberOfBlockDevices (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ OUT UINTN *NumberBlockDevices );
+
+EFI_STATUS
+BotGetMediaInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo );
+
+EFI_STATUS
+BotReadBlocks (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ IN EFI_PEI_LBA StartLBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer );
+
+//
+// UsbIo PPI Notification
+//
+EFI_STATUS
+NotifyOnUsbIoPpi (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *InvokePpi );
+
+EFI_STATUS
+InitUsbBot (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi );
+
+#define USBFLOPPY 1
+#define USBFLOPPY2 2 // for those that use ReadCapacity(0x25)
+ // command to retrieve media capacity
+#define USBCDROM 3
+//
+// Bot device structure
+//
+#define PEI_BOT_DEVICE_SIGNATURE EFI_SIGNATURE_32( 'U', 'B', 'O', 'T' )
+typedef struct
+{
+ UINTN Signature;
+ EFI_PEI_RECOVERY_BLOCK_IO_PPI BlkIoPpi;
+ EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList;
+ EFI_PEI_BLOCK_IO_MEDIA Media;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ EFI_USB_INTERFACE_DESCRIPTOR *BotInterface;
+ EFI_USB_ENDPOINT_DESCRIPTOR *BulkInEndpoint;
+ EFI_USB_ENDPOINT_DESCRIPTOR *BulkOutEndpoint;
+ UINTN DeviceType;
+ REQUEST_SENSE_DATA *SensePtr;
+ UINT32 FdEmulOffset;
+ UINT8 Lun;
+} PEI_BOT_DEVICE;
+
+#define PEI_BOT_DEVICE_FROM_THIS( a ) \
+ PEI_CR( a, PEI_BOT_DEVICE, BlkIoPpi, PEI_BOT_DEVICE_SIGNATURE )
+
+//
+// USB ATATPI command
+//
+EFI_STATUS
+PeiAtapiCommand (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_BOT_DEVICE *PeiBotDev,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN VOID *DataBuffer,
+ IN UINT32 BufferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 TimeOutInMilliSeconds );
+
+
+extern VOID ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size );
+
+#define ONE_SECOND_DELAY 1000000 // 1 second = 1000000 microseconds
+
+// Controller-specific externs
+#if (PEI_UHCI_SUPPORT == 1)
+EFI_STATUS UhciPeiUsbEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+
+extern EFI_STATUS UhcPeimEntry (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+#endif
+
+#if (PEI_OHCI_SUPPORT == 1)
+EFI_STATUS OhciPeiUsbEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+#endif
+
+#if (PEI_EHCI_SUPPORT == 1)
+EFI_STATUS EhciPeiUsbEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+#endif
+
+#if (PEI_XHCI_SUPPORT == 1)
+EFI_STATUS XhciPeiUsbEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+#endif
+
+extern EFI_STATUS PeimInitializeUsb (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+
+#define PEI_MAX_USB_RECOVERY_INIT_PPI 16
+
+// The following section should eventually go to SBPPI.H.
+#ifndef PEI_USB_CHIP_INIT_PPI_GUID
+#define PEI_USB_CHIP_INIT_PPI_GUID \
+ { 0xdb75358d, 0xfef0, 0x4471, 0xa8, 0xd, 0x2e, 0xeb, 0x13, 0x8, 0x2d, 0x2d }
+
+typedef EFI_STATUS (EFIAPI *PEI_ENABLE_CHIP_USB_RECOVERY) (
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+typedef struct _PEI_USB_CHIP_INIT_PPI PEI_USB_CHIP_INIT_PPI;
+
+typedef struct _PEI_USB_CHIP_INIT_PPI {
+ PEI_ENABLE_CHIP_USB_RECOVERY EnableChipUsbRecovery;
+} PEI_USB_CHIP_INIT_PPI;
+#endif
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/UsbRecovery/UsbBotPeimSrc/atapi.h b/Core/EM/UsbRecovery/UsbBotPeimSrc/atapi.h
new file mode 100644
index 0000000..2d6d376
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbBotPeimSrc/atapi.h
@@ -0,0 +1,418 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/atapi.h 2 7/10/08 6:38p Michaela $
+//
+// $Revision: 2 $
+//
+// $Date: 7/10/08 6:38p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbBotPeimSrc/atapi.h $
+//
+// 2 7/10/08 6:38p Michaela
+// Updated to support OHCI controllers
+//
+// 1 9/22/06 12:17p Sivagarn
+// - Included Recovery code in Source
+//
+// 1 9/22/06 12:14p Sivagarn
+// - Initial checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: Atapi.h
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//
+// This file contains 'Framework Code' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may not be modified, except as allowed by
+// additional terms of your license agreement.
+//
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ Atapi.h
+
+ Abstract:
+
+
+ Revision History
+ --*/
+
+#ifndef _PEI_RECOVERY_ATAPI_H
+#define _PEI_RECOVERY_ATAPI_H
+
+#include "Efi.h"
+
+#pragma pack(1)
+
+typedef struct
+{
+ UINT16 config; // General Configuration
+ UINT16 cylinders; // Number of Cylinders
+ UINT16 reserved_2;
+ UINT16 heads; // Number of logical heads
+ UINT16 vendor_data1;
+ UINT16 vendoe_data2;
+ UINT16 sectors_per_track;
+ UINT16 vendor_specific_7_9[3];
+ CHAR8 SerialNo[20]; // ASCII
+ UINT16 vendor_specific_20_21[2];
+ UINT16 ecc_bytes_available;
+ CHAR8 FirmwareVer[8]; // ASCII
+ CHAR8 ModelName[40]; // ASCII
+ UINT16 multi_sector_cmd_max_sct_cnt;
+ UINT16 reserved_48;
+ UINT16 capabilities;
+ UINT16 reserved_50;
+ UINT16 pio_cycle_timing;
+ UINT16 reserved_52;
+ UINT16 field_validity;
+ UINT16 current_cylinders;
+ UINT16 current_heads;
+ UINT16 current_sectors;
+ UINT16 CurrentCapacityLsb;
+ UINT16 CurrentCapacityMsb;
+ UINT16 reserved_59;
+ UINT16 user_addressable_sectors_lo;
+ UINT16 user_addressable_sectors_hi;
+ UINT16 reserved_62;
+ UINT16 multi_word_dma_mode;
+ UINT16 advanced_pio_modes;
+ UINT16 min_multi_word_dma_cycle_time;
+ UINT16 rec_multi_word_dma_cycle_time;
+ UINT16 min_pio_cycle_time_without_flow_control;
+ UINT16 min_pio_cycle_time_with_flow_control;
+ UINT16 reserved_69_79[11];
+ UINT16 major_version_no;
+ UINT16 minor_version_no;
+ UINT16 reserved_82_127[46];
+ UINT16 security_status;
+ UINT16 vendor_data_129_159[31];
+ UINT16 reserved_160_255[96];
+} IDENTIFY;
+
+typedef struct
+{
+ UINT8 peripheral_type;
+ UINT8 RMB;
+ UINT8 version;
+ UINT8 response_data_format;
+ UINT8 addnl_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 vendor_info[8];
+ UINT8 product_id[12];
+ UINT8 eeprom_product_code[4];
+ UINT8 firmware_rev_level[4];
+ UINT8 firmware_sub_rev_level[1];
+ UINT8 reserved_37;
+ UINT8 reserved_38;
+ UINT8 reserved_39;
+ UINT8 max_capacity_hi;
+ UINT8 max_capacity_mid;
+ UINT8 max_capacity_lo;
+ UINT8 reserved_43_95[95 - 43 + 1];
+ UINT8 vendor_id[20];
+ UINT8 eeprom_drive_sno[12];
+} INQUIRY_DATA;
+
+typedef struct
+{
+ UINT8 error_code : 7;
+ UINT8 valid : 1;
+ UINT8 reserved_1;
+ UINT8 sense_key : 4;
+ UINT8 reserved_21 : 1;
+ UINT8 ILI : 1;
+ UINT8 reserved_22 : 2;
+ UINT8 vendor_specific_3;
+ UINT8 vendor_specific_4;
+ UINT8 vendor_specific_5;
+ UINT8 vendor_specific_6;
+ UINT8 addnl_sense_length; // n - 7
+ UINT8 vendor_specific_8;
+ UINT8 vendor_specific_9;
+ UINT8 vendor_specific_10;
+ UINT8 vendor_specific_11;
+ UINT8 addnl_sense_code; // mandatory
+ UINT8 addnl_sense_code_qualifier; // mandatory
+ UINT8 field_replaceable_unit_code; // optional
+ UINT8 reserved_15;
+ UINT8 reserved_16;
+ UINT8 reserved_17;
+ // Followed by additional sense bytes : FIXME
+} REQUEST_SENSE_DATA;
+
+typedef struct
+{
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 BlockSize3;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_CAPACITY_DATA;
+
+typedef struct
+{
+ UINT8 reserved_0;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 Capacity_Length;
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 DesCode : 2;
+ UINT8 reserved_9 : 6;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_FORMAT_CAPACITY_DATA;
+
+#pragma pack()
+
+//
+// ATAPI Command
+//
+#define ATAPI_SOFT_RESET_CMD 0x08
+#define PACKET_CMD 0xa0
+#define ATAPI_IDENTIFY_DEVICE_CMD 0xa1
+#define ATAPI_SERVICE_CMD 0xa2
+
+//
+// ATAPI Packet Command
+//
+#pragma pack(1)
+
+typedef struct
+{
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} TEST_UNIT_READY_CMD;
+
+typedef struct
+{
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 page_code;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} INQUIRY_CMD;
+
+
+typedef struct
+{
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} REQUEST_SENSE_CMD;
+
+typedef struct
+{
+ UINT8 opcode;
+ UINT8 reserved_1 : 5;
+ UINT8 lun : 3;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 reserved_6;
+ UINT8 TranLen0;
+ UINT8 TranLen1;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ10_CMD;
+
+typedef struct
+{
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 allocation_length_hi;
+ UINT8 allocation_length_lo;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ_FORMAT_CAP_CMD;
+
+typedef struct
+{
+ UINT8 peripheral_type;
+ UINT8 RMB;
+ UINT8 version;
+ UINT8 response_data_format;
+ UINT8 addnl_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 vendor_info[8];
+ UINT8 product_id[12];
+ UINT8 eeprom_product_code[4];
+ UINT8 firmware_rev_level[4];
+} USB_INQUIRY_DATA;
+
+typedef union {
+ UINT16 Data16[6];
+ TEST_UNIT_READY_CMD TestUnitReady;
+ READ10_CMD Read10;
+ REQUEST_SENSE_CMD RequestSence;
+ INQUIRY_CMD Inquiry;
+ READ_FORMAT_CAP_CMD ReadFormatCapacity;
+} ATAPI_PACKET_COMMAND;
+
+#pragma pack()
+
+//
+// Packet Command Code
+//
+#define TEST_UNIT_READY 0x00
+#define REQUEST_SENSE 0x03
+#define INQUIRY 0x12
+#define READ_FORMAT_CAPACITY 0x23
+#define READ_CAPACITY 0x25
+#define READ_10 0x28
+
+#define DEFAULT_CTL (0x0a) // default content of device
+ // control register,
+ // disable INT
+#define DEFAULT_CMD (0xa0)
+
+#define MAX_ATAPI_BYTE_COUNT (0xfffe)
+
+//
+// Sense Key
+//
+#define REQUEST_SENSE_ERROR (0x70)
+#define SK_NO_SENSE (0x0)
+#define SK_RECOVERY_ERROR (0x1)
+#define SK_NOT_READY (0x2)
+#define SK_MEDIUM_ERROR (0x3)
+#define SK_HARDWARE_ERROR (0x4)
+#define SK_ILLEGAL_REQUEST (0x5)
+#define SK_UNIT_ATTENTION (0x6)
+#define SK_DATA_PROTECT (0x7)
+#define SK_BLANK_CHECK (0x8)
+#define SK_VENDOR_SPECIFIC (0x9)
+#define SK_RESERVED_A (0xa)
+#define SK_ABORT (0xb)
+#define SK_RESERVED_C (0xc)
+#define SK_OVERFLOW (0xd)
+#define SK_MISCOMPARE (0xe)
+#define SK_RESERVED_F (0xf)
+
+//
+// Additional Sense Codes
+//
+#define ASC_NOT_READY (0x04)
+#define ASC_MEDIA_ERR1 (0x10)
+#define ASC_MEDIA_ERR2 (0x11)
+#define ASC_MEDIA_ERR3 (0x14)
+#define ASC_MEDIA_ERR4 (0x30)
+#define ASC_MEDIA_UPSIDE_DOWN (0x06)
+#define ASC_INVALID_CMD (0x20)
+#define ASC_LBA_OUT_OF_RANGE (0x21)
+#define ASC_INVALID_FIELD (0x24)
+#define ASC_WRITE_PROTECTED (0x27)
+#define ASC_MEDIA_CHANGE (0x28)
+#define ASC_RESET (0x29) // Power On Reset or Bus Reset occurred
+#define ASC_ILLEGAL_FIELD (0x26)
+#define ASC_NO_MEDIA (0x3a)
+#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64)
+
+//
+// Additional Sense Code Qualifier
+//
+#define ASCQ_IN_PROGRESS (0x01)
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UsbPeim.h b/Core/EM/UsbRecovery/UsbPeim.h
new file mode 100644
index 0000000..b87ded6
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbPeim.h
@@ -0,0 +1,244 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbPeim.h 8 11/24/12 5:43a Ryanchou $
+//
+// $Revision: 8 $
+//
+// $Date: 11/24/12 5:43a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbPeim.h $
+//
+// 8 11/24/12 5:43a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 7 1/18/11 12:50a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 6 10/11/10 4:51p Olegi
+// XHCI support added.
+//
+// 5 3/17/09 5:11p Olegi
+//
+// 4 7/10/08 6:33p Michaela
+// Updated to support OHCI controllers
+//
+// 3 4/16/07 1:03p Sivagarn
+// - Updated as per coding standard review
+// - In previous check-in, TIANO.H file is removed and AMIMAPPING.H file
+// is included
+//
+// 2 3/28/07 3:07a Meenakshim
+// Removed dependency on core source files..Added amimapping file.
+//
+// 1 9/22/06 4:06p Sivagarn
+// - Initial Check-in
+// - Included Recovery code in Source
+// - Included appropriate headers for flies and functions
+// - Updated copyright messages
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbPeim.H
+//
+// Description: This file belongs to "Framework" and included here for
+// compatibility purposes. This file is modified by AMI to include
+// copyright message, appropriate header and integration code
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//
+// This file contains 'Framework Code' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may not be modified, except as allowed by
+// additional terms of your license agreement.
+//
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ UsbPeim.h
+
+ Abstract:
+
+ Usb Peim definition
+
+ --*/
+
+#ifndef _PEI_USB_PEIM_H
+#define _PEI_USB_PEIM_H
+
+#include "Efi.h"
+#include "Pei.h"
+#include "AmiMapping.h"
+#include "AmiPeiLib.h"
+
+#include "usb.h"
+
+//
+// Driver Produced PPI Prototypes
+//
+#include "Ppi\UsbIo.h"
+
+//
+// Driver Consumed PPI Prototypes
+//
+#include "Ppi\UsbHostController.h"
+
+#define MAX_ROOT_PORT 2
+#define MAX_ENDPOINT 16
+#define HUB_TIME_OUT 3000
+#define STALL_1_MILLI_SECOND 1000 // stall 1 ms
+
+
+#define USB_SLOW_SPEED_DEVICE 0x01
+#define USB_FULL_SPEED_DEVICE 0x02
+#define USB_HIGH_SPEED_DEVICE 0x03
+#define USB_SUPER_SPEED_DEVICE 0x04
+
+//---------------------------------------------------------------------------
+// Values for InterfaceDescriptor.BaseClass
+//---------------------------------------------------------------------------
+#define BASE_CLASS_HID 0x03
+#define BASE_CLASS_MASS_STORAGE 0x08
+#define BASE_CLASS_HUB 0x09
+//----------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Values for InterfaceDescriptor.Protocol
+//---------------------------------------------------------------------------
+#define PROTOCOL_KEYBOARD 0x01 // Keyboard device protocol
+#define PROTOCOL_MOUSE 0x02 // Mouse device protocol?
+
+// Mass storage related protocol equates
+#define PROTOCOL_CBI 0x00 // Mass Storage Control/Bulk/Interrupt
+ // with command completion interrupt
+#define PROTOCOL_CBI_NO_INT 0x01 // MASS STORAGE Control/Bulk/Interrupt
+ // with NO command completion interrupt
+#define PROTOCOL_BOT 0x50 // Mass Storage Bulk-Only Transport
+#define PROTOCOL_VENDOR 0xff // Vendor specific mass protocol
+//---------------------------------------------------------------------------
+
+#define PEI_USB_DEVICE_SIGNATURE EFI_SIGNATURE_32( 'U', 's', 'b', 'D' )
+typedef struct
+{
+ UINTN Signature;
+ PEI_USB_IO_PPI UsbIoPpi;
+ EFI_PEI_PPI_DESCRIPTOR UsbIoPpiList;
+ UINT8 DeviceAddress;
+ UINT8 MaxPacketSize0;
+ UINT8 DeviceSpeed;
+ UINT8 DataToggle;
+ UINT8 IsHub;
+ UINT8 DownStreamPortNo;
+ UINT8 Reserved[2]; // Padding for IPF
+ PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
+ UINT8 *ConfigurationData;
+ EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
+ EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDesc;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc[MAX_ENDPOINT];
+ UINT16 TransactionTranslator;
+ UINT8 HubDepth;
+} PEI_USB_DEVICE;
+
+#define PEI_USB_DEVICE_FROM_THIS( a ) \
+ PEI_CR( a, PEI_USB_DEVICE, UsbIoPpi, PEI_USB_DEVICE_SIGNATURE )
+
+//
+// Peim UsbIo prototype
+//
+
+EFI_STATUS
+PeiUsbControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT32 Timeout,
+ IN OUT VOID *Data OPTIONAL,
+ IN UINTN DataLength OPTIONAL );
+
+EFI_STATUS
+PeiUsbBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout );
+
+EFI_STATUS
+PeiUsbGetInterfaceDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor );
+
+EFI_STATUS
+PeiUsbGetEndpointDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN UINT8 EndpointIndex,
+ IN EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor );
+
+EFI_STATUS
+PeiUsbPortReset (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This );
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UsbPeimSrc/HubPeim.c b/Core/EM/UsbRecovery/UsbPeimSrc/HubPeim.c
new file mode 100644
index 0000000..a2a2246
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbPeimSrc/HubPeim.c
@@ -0,0 +1,889 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbPeimSrc/HubPeim.c 12 11/24/12 5:46a Ryanchou $
+//
+// $Revision: 12 $
+//
+// $Date: 11/24/12 5:46a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbPeimSrc/HubPeim.c $
+//
+// 12 11/24/12 5:46a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 11 8/24/11 4:24a Roberthsu
+// [TAG] EIP67320
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB recovery will fail when plug-in USB touch panel on
+// Oaktrail platform
+// [RootCause] Usbrecovery will exit when get portchanged.Touch panel
+// port status is early than usbkey.So usbrecovery fail.
+// [Solution] Add delay after hub set port power.
+// [Files] HubPeim.c
+//
+// 10 1/18/11 12:54a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 9 4/26/10 4:17p Krishnakumarg
+// DebugRx causes the system to hang in Recovery mode EIP#34401
+//
+// 8 4/06/10 3:31p Fasihm
+// EIP#31987 - Added the generic USBRecovery Fix in the module.
+//
+// 7 3/17/09 5:03p Olegi
+// Removed unnecessary CLEAR_FEATURE (Reset) and SET_FEATURE (Enable) in
+// the hub enumeration routine.
+//
+// 6 7/18/08 5:05p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 5 7/10/08 6:37p Michaela
+// Updated to support OHCI controllers
+//
+// 4 8/17/07 4:14p Ambikas
+//
+// 3 4/16/07 12:54p Sivagarn
+// - Updated as per coding standard review
+// - In previous check-in, TIANO.H file is removed and AMIMAPPING.H file
+// is included
+//
+// 2 3/28/07 3:38a Meenakshim
+//
+// 1 9/22/06 12:19p Sivagarn
+// - Initial Checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: HubPeim.C
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+// This file contains generic routines needed for USB recovery
+// PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+/*++
+ This file contains 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+ --*/
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ HubPeim.c
+
+ Abstract:
+
+ Usb Hub Request Support In PEI Phase
+
+ Revision History
+
+ --*/
+//NOT NEEDED FOR APTIO
+//#include "Efi.h"
+//#include "EfiDriverLib.h"
+//#include "usb.h"
+
+#include "HubPeim.h"
+#include "UsbPeim.h"
+#include "PeiUsbLib.h"
+
+#include EFI_PPI_DEFINITION( Stall )
+static EFI_GUID gPeiStallPpiGuid = EFI_PEI_STALL_PPI_GUID;
+
+//NOT NEEDED FOR APTIO
+//#include "usbbus.h"
+//#include "usblib.h"
+//#include "hub.h"
+
+extern VOID ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size );
+
+typedef struct {
+ UINT32 HubPortStatus;
+ UINT32 EfiPortStatus;
+} EFI_USB_PORT_STATUS_MAP;
+
+EFI_USB_PORT_STATUS_MAP HubPortStatusMap[] = {
+ // Port status bits
+ {HUB_PORT_CONNECTION, USB_PORT_STAT_CONNECTION},
+ {HUB_PORT_ENABLE, USB_PORT_STAT_ENABLE},
+ {HUB_PORT_SUSPEND, USB_PORT_STAT_SUSPEND},
+ {HUB_PORT_OVER_CURRENT, USB_PORT_STAT_OVERCURRENT},
+ {HUB_PORT_RESET, USB_PORT_STAT_RESET},
+ {HUB_PORT_POWER, USB_PORT_STAT_POWER},
+ {HUB_PORT_LOW_SPEED, USB_PORT_STAT_LOW_SPEED},
+ {HUB_PORT_HIGH_SPEED, USB_PORT_STAT_HIGH_SPEED},
+ // Port status change bits
+ {HUB_C_PORT_CONNECTION << 16, USB_PORT_STAT_C_CONNECTION << 16},
+ {HUB_C_PORT_ENABLE << 16, USB_PORT_STAT_C_ENABLE << 16},
+ {HUB_C_PORT_SUSPEND << 16, USB_PORT_STAT_C_SUSPEND << 16},
+ {HUB_C_PORT_OVER_CURRENT << 16, USB_PORT_STAT_C_OVERCURRENT << 16},
+ {HUB_C_PORT_RESET << 16, USB_PORT_STAT_C_RESET << 16}
+};
+
+EFI_USB_PORT_STATUS_MAP SsHubPortStatusMap[] = {
+ // Port status bits
+ {SS_HUB_PORT_CONNECTION, USB_PORT_STAT_CONNECTION | USB_PORT_STAT_SUPER_SPEED},
+ {SS_HUB_PORT_ENABLE, USB_PORT_STAT_ENABLE},
+ {SS_HUB_PORT_OVER_CURRENT, USB_PORT_STAT_OVERCURRENT},
+ {SS_HUB_PORT_RESET, USB_PORT_STAT_RESET},
+ {SS_HUB_PORT_POWER, USB_PORT_STAT_POWER},
+ // Port status change bits
+ {SS_HUB_C_PORT_CONNECTION << 16, USB_PORT_STAT_C_CONNECTION << 16},
+ {SS_HUB_C_PORT_ENABLE << 16, USB_PORT_STAT_C_ENABLE << 16},
+ {SS_HUB_C_PORT_SUSPEND << 16, USB_PORT_STAT_C_SUSPEND << 16},
+ {SS_HUB_C_PORT_OVER_CURRENT << 16, USB_PORT_STAT_C_OVERCURRENT << 16},
+ {SS_HUB_C_PORT_RESET << 16, USB_PORT_STAT_C_RESET << 16}
+};
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PeiHubGetPortStatus
+//
+// Description:
+// This function uses a device's PEI_USB_IO_PPI interface to execute a
+// control transfer on the default control pipe to issue a Hub
+// Class-specific request to obtain the port status and port status
+// change bits.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- PEI Sevices table pointer
+// IN PEI_USB_IO_PPI *UsbIoPpi
+// -- PEI_USB_IO_PPI interface pointer for the device
+// that is being accessed
+// IN UINT8 Port
+// -- This value is the hub port number for which the
+// status is to be returned.
+// OUT UINT32 *PortStatus
+// -- This output value is the USB Specification
+// (Revision 2.0) Hub Port Status field (upper word)
+// and Change Status field (lower word) values as
+// returned by the Get Port Status Hub Class device
+// standard request.
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS PeiHubGetPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ OUT UINT32 *PortStatus )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ PEI_USB_DEVICE *PeiUsbDev;
+ EFI_STATUS EfiStatus;
+ UINT32 HubPortStatus = 0;
+ UINT32 Timeout;
+ EFI_USB_PORT_STATUS_MAP *PortStatusMap;
+ UINT8 Index;
+ UINT8 Count;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS( UsbIoPpi );
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_GET_PORT_STATUS_REQ_TYPE;
+ DevReq.Request = HUB_GET_PORT_STATUS;
+ DevReq.Value = 0;
+ DevReq.Index = Port;
+ DevReq.Length = sizeof(UINT32);
+
+ Timeout = 3000;
+
+ EfiStatus = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbDataIn,
+ Timeout,
+ &HubPortStatus,
+ sizeof(UINT32)
+ );
+
+ if (PeiUsbDev->DeviceSpeed != USB_SUPER_SPEED_DEVICE) {
+ PortStatusMap = HubPortStatusMap;
+ Count = sizeof(HubPortStatusMap) / sizeof(EFI_USB_PORT_STATUS_MAP);
+ } else {
+ PortStatusMap = SsHubPortStatusMap;
+ Count = sizeof(SsHubPortStatusMap) / sizeof(EFI_USB_PORT_STATUS_MAP);
+ }
+
+ for (*PortStatus = 0, Index = 0; Index < Count; Index++) {
+ if (HubPortStatus & PortStatusMap[Index].HubPortStatus) {
+ *PortStatus |= PortStatusMap[Index].EfiPortStatus;
+ }
+ }
+
+ return EfiStatus;
+}
+
+
+EFI_STATUS PeiHubSetPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ IN UINT8 Value )
+
+/*++
+
+ Routine Description:
+ Set specified feature to a give hub port
+
+ Arguments:
+ UsbIoPpi - EFI_USB_IO_PROTOCOL instance
+ Port - Usb hub port number (starting from 1).
+ Value - New feature value.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+ EFI_INVALID_PARAMETER
+
+ --*/
+
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 Timeout;
+
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_SET_PORT_FEATURE_REQ_TYPE;
+ DevReq.Request = HUB_SET_PORT_FEATURE;
+ DevReq.Value = Value;
+ DevReq.Index = Port;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+ EfiStatus = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0
+ );
+
+ return EfiStatus;
+}
+
+
+EFI_STATUS PeiHubClearPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ IN UINT8 Value )
+
+/*++
+
+ Routine Description:
+ Clear a specified feature of a given hub port
+
+ Arguments:
+ UsbIoPpi - EFI_USB_IO_PROTOCOL instance
+ Port - Usb hub port number (starting from 1).
+ Value - Feature value that will be cleared from
+ that hub port.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+ EFI_INVALID_PARAMETER
+
+ --*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 Timeout;
+
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
+ DevReq.Request = HUB_CLEAR_FEATURE_PORT;
+ DevReq.Value = Value;
+ DevReq.Index = Port;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+ EfiStatus = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0
+ );
+
+ return EfiStatus;
+}
+
+
+EFI_STATUS PeiHubGetHubStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ OUT UINT32 *HubStatus )
+
+/*++
+
+ Routine Description:
+ Get Hub Status
+
+ Arguments:
+ UsbIoPpi - EFI_USB_IO_PROTOCOL instance
+ HubStatus - Current Hub status and change status.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+
+ --*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 Timeout;
+
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_GET_HUB_STATUS_REQ_TYPE;
+ DevReq.Request = HUB_GET_HUB_STATUS;
+ DevReq.Value = 0;
+ DevReq.Index = 0;
+ DevReq.Length = sizeof(UINT32);
+
+ Timeout = 3000;
+ EfiStatus = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbDataIn,
+ Timeout,
+ HubStatus,
+ sizeof(UINT32)
+ );
+
+ return EfiStatus;
+}
+
+
+EFI_STATUS PeiHubSetHubFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Value )
+
+/*++
+
+ Routine Description:
+ Set a specified feature to the hub
+
+ Arguments:
+ UsbIoPpi - EFI_USB_IO_PROTOCOL instance
+ Value - Feature value that will be set to the hub.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+
+ --*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 Timeout;
+
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_SET_HUB_FEATURE_REQ_TYPE;
+ DevReq.Request = HUB_SET_HUB_FEATURE;
+ DevReq.Value = Value;
+ DevReq.Index = 0;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+ EfiStatus = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0
+ );
+
+ return EfiStatus;
+}
+
+
+EFI_STATUS PeiHubClearHubFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Value )
+
+/*++
+
+ Routine Description:
+ Set a specified feature to the hub
+
+ Arguments:
+ UsbIoPpi - EFI_USB_IO_PROTOCOL instance
+ Value - Feature value that will be cleared from the hub.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+
+ --*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 Timeout;
+
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_CLEAR_FEATURE_REQ_TYPE;
+ DevReq.Request = HUB_CLEAR_FEATURE;
+ DevReq.Value = Value;
+ DevReq.Index = 0;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+ EfiStatus = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0
+ );
+
+ return EfiStatus;
+
+}
+
+EFI_STATUS PeiSetHubDepth (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 HubDepth)
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ PEI_USB_DEVICE *PeiUsbDev;
+ EFI_STATUS EfiStatus;
+ UINT32 Timeout;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS( UsbIoPpi );
+ if (PeiUsbDev->DeviceSpeed != USB_SUPER_SPEED_DEVICE) {
+ return EFI_SUCCESS;
+ }
+
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_SET_HUB_DEPTH_REQ_TYPE;
+ DevReq.Request = HUB_SET_HUB_DEPTH;
+ DevReq.Value = HubDepth;
+ DevReq.Index = 0;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+ EfiStatus = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0
+ );
+
+ return EfiStatus;
+}
+
+EFI_STATUS PeiGetHubDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINTN DescriptorSize,
+ OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor )
+
+/*++
+
+ Routine Description:
+ Get the hub descriptor
+
+ Arguments:
+ UsbIoPpi - EFI_USB_IO_PROTOCOL instance
+ DescriptorSize - The length of Hub Descriptor buffer.
+ HubDescriptor - Caller allocated buffer to store the hub descriptor
+ if successfully returned.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+
+ --*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ PEI_USB_DEVICE *PeiUsbDev;
+ EFI_STATUS EfiStatus;
+ UINT32 Timeout;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS( UsbIoPpi );
+ ZeroMem( &DevReq, sizeof(EFI_USB_DEVICE_REQUEST) );
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = USB_RT_HUB | 0x80;
+ DevReq.Request = HUB_GET_DESCRIPTOR;
+ DevReq.Value = PeiUsbDev->DeviceSpeed == USB_SUPER_SPEED_DEVICE ?
+ USB_DT_SS_HUB << 8: USB_DT_HUB << 8;
+ DevReq.Index = 0;
+ DevReq.Length = (UINT16) DescriptorSize;
+
+ Timeout = 3000;
+ EfiStatus = UsbIoPpi->UsbControlTransfer(
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbDataIn,
+ Timeout,
+ HubDescriptor,
+ (UINT16) DescriptorSize
+ );
+
+ return EfiStatus;
+
+}
+
+
+EFI_STATUS PeiDoHubConfig (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice )
+
+/*++
+
+ Routine Description:
+ Configure the hub
+
+ Arguments:
+ PeiUsbDevice - Indicating the hub controller device that
+ will be configured
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+ --*/
+{
+ EFI_USB_HUB_DESCRIPTOR HubDescriptor;
+ EFI_STATUS Status;
+ EFI_USB_HUB_STATUS HubStatus;
+ UINTN i;
+ UINT32 PortStatus;
+ PEI_USB_IO_PPI *UsbIoPpi;
+
+ BOOLEAN SkipDebugPort = PeiUsbDevice->UsbHcPpi->DebugPortUsed;
+//(EIP67320+)>
+ PEI_STALL_PPI *PeiStall;
+ (**PeiServices).LocatePpi(
+ PeiServices,
+ &gPeiStallPpiGuid,
+ 0,
+ NULL,
+ &PeiStall
+ );
+//<(EIP67320+)
+ ZeroMem( &HubDescriptor, sizeof(HubDescriptor) );
+ UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+
+ Status = PeiSetHubDepth(PeiServices,
+ UsbIoPpi,
+ PeiUsbDevice->HubDepth);
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // First get the whole descriptor, then
+ // get the number of hub ports
+ //
+ Status = PeiGetHubDescriptor(
+ PeiServices,
+ UsbIoPpi,
+ sizeof(EFI_USB_HUB_DESCRIPTOR),
+ &HubDescriptor
+ );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ PeiUsbDevice->DownStreamPortNo = HubDescriptor.NbrPorts;
+
+ Status = PeiHubGetHubStatus( PeiServices,
+ UsbIoPpi,
+ (UINT32 *) &HubStatus
+ );
+
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get all hub ports status
+ //
+ for (i = 0; i < PeiUsbDevice->DownStreamPortNo; i++) {
+
+// Intel Debug port - Second port of the controller
+ if(SkipDebugPort && (i == 1) )
+ continue;
+
+ Status = PeiHubGetPortStatus( PeiServices,
+ UsbIoPpi,
+ (UINT8) (i + 1),
+ &PortStatus
+ );
+ if ( EFI_ERROR( Status ) ) {
+ continue;
+ }
+ }
+
+ //
+ // Power all the hub ports
+ //
+ for (i = 0; i < PeiUsbDevice->DownStreamPortNo; i++) {
+// Intel Debug port - Second port of the controller
+ if( SkipDebugPort && (i == 1) )
+ continue;
+
+ Status = PeiHubSetPortFeature( PeiServices,
+ UsbIoPpi,
+ (UINT8) (i + 1),
+ EfiUsbPortPower
+ );
+ if ( EFI_ERROR( Status ) ) {
+ continue;
+ }
+ }
+
+ //
+ // Clear Hub Status Change
+ //
+ Status = PeiHubGetHubStatus( PeiServices,
+ UsbIoPpi,
+ (UINT32 *) &HubStatus
+ );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_DEVICE_ERROR;
+ }
+ else {
+ //
+ // Hub power supply change happens
+ //
+ if (HubStatus.HubChange & HUB_CHANGE_LOCAL_POWER) {
+ PeiHubClearHubFeature( PeiServices,
+ UsbIoPpi,
+ C_HUB_LOCAL_POWER
+ );
+ }
+
+ //
+ // Hub change overcurrent happens
+ //
+ if (HubStatus.HubChange & HUB_CHANGE_OVERCURRENT) {
+ PeiHubClearHubFeature( PeiServices,
+ UsbIoPpi,
+ C_HUB_OVER_CURRENT
+ );
+ }
+ }
+ PeiStall->Stall( PeiServices, PeiStall, (HubDescriptor.PwrOn2PwrGood << 1) *1000); //(EIP67320)
+ return EFI_SUCCESS;
+
+}
+
+
+//
+// Send reset signal over the given root hub port
+//
+VOID PeiResetHubPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ UINT8 PortNum )
+{
+ PEI_STALL_PPI *PeiStall;
+ UINT8 n;
+ EFI_USB_PORT_STATUS HubPortStatus;
+
+
+ (**PeiServices).LocatePpi(
+ PeiServices,
+ &gPeiStallPpiGuid,
+ 0,
+ NULL,
+ &PeiStall
+ );
+
+ //
+ // reset root port
+ //
+ PeiHubSetPortFeature(
+ PeiServices,
+ UsbIoPpi,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ n = 20;
+ do {
+ PeiHubGetPortStatus(
+ PeiServices,
+ UsbIoPpi,
+ PortNum,
+ (UINT32 *) &HubPortStatus
+ );
+ PeiStall->Stall(
+ PeiServices,
+ PeiStall,
+ 1000
+ );
+ n -= 1;
+ } while ( (HubPortStatus.PortChangeStatus &
+ USB_PORT_STAT_C_RESET) == 0 && n > 0 );
+
+ PeiStall->Stall(
+ PeiServices,
+ PeiStall,
+ 500
+ );
+ //
+ // Clear any change status
+ //
+ PeiHubClearPortFeature(
+ PeiServices,
+ UsbIoPpi,
+ PortNum,
+ EfiUsbPortResetChange
+ );
+
+ return;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UsbPeimSrc/UsbIoPeim.c b/Core/EM/UsbRecovery/UsbPeimSrc/UsbIoPeim.c
new file mode 100644
index 0000000..157cb9b
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbPeimSrc/UsbIoPeim.c
@@ -0,0 +1,334 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbPeimSrc/UsbIoPeim.c 6 1/18/11 1:05a Ryanchou $
+//
+// $Revision: 6 $
+//
+// $Date: 1/18/11 1:05a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbPeimSrc/UsbIoPeim.c $
+//
+// 6 1/18/11 1:05a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 5 3/17/09 5:04p Olegi
+// Added TransactionTranslator for slow/full speed devices behind USB2
+// hub.
+//
+// 4 3/03/09 7:21p Olegi
+// Changed the type of MaxPktSize from UINT8 to UINT16.
+//
+// 3 7/18/08 5:05p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 2 7/10/08 6:37p Michaela
+// Updated to support OHCI controllers
+//
+// 1 9/22/06 12:19p Sivagarn
+// - Initial Checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbIoPeim.C
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+// This file contains generic routines needed for USB recovery
+// PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+/*++
+ This file contains 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+ --*/
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ UsbIoPeim.c
+
+ Abstract:
+
+ Usb Io PPI
+
+ --*/
+
+#include "UsbPeim.h"
+#include "PeiUsbLib.h"
+
+#define PAGESIZE 4096
+
+VOID
+ResetRootPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
+ UINT8 PortNum );
+
+EFI_STATUS PeiUsbControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT32 Timeout,
+ IN OUT VOID *Data OPTIONAL,
+ IN UINTN DataLength OPTIONAL )
+{
+ EFI_STATUS Status;
+ PEI_USB_DEVICE *PeiUsbDev;
+ PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
+ UINT32 TransferResult;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS( This );
+ UsbHcPpi = PeiUsbDev->UsbHcPpi;
+
+ Status = UsbHcPpi->ControlTransfer(
+ PeiServices,
+ UsbHcPpi,
+ PeiUsbDev->DeviceAddress,
+ PeiUsbDev->DeviceSpeed,
+ PeiUsbDev->MaxPacketSize0,
+ PeiUsbDev->TransactionTranslator,
+ Request,
+ Direction,
+ Data,
+ &DataLength,
+ Timeout,
+ &TransferResult
+ );
+
+ return Status;
+}
+
+
+EFI_STATUS PeiUsbBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout )
+{
+ EFI_STATUS Status;
+ PEI_USB_DEVICE *PeiUsbDev;
+ PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
+ UINT32 TransferResult;
+ UINT16 MaxPacketLength;
+ UINT8 DataToggle;
+ UINT8 OldToggle;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
+ UINT8 EndpointIndex;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS( This );
+ UsbHcPpi = PeiUsbDev->UsbHcPpi;
+
+ EndpointIndex = 0;
+
+ while (EndpointIndex < MAX_ENDPOINT) {
+ Status = PeiUsbGetEndpointDescriptor( PeiServices,
+ This, EndpointIndex, &EndpointDescriptor );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
+ break;
+ }
+
+ EndpointIndex++;
+ }
+
+ if (EndpointIndex == MAX_ENDPOINT) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MaxPacketLength = (PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize);
+ if ( ( PeiUsbDev->DataToggle & (1 << EndpointIndex) ) != 0 ) {
+ DataToggle = 1;
+ }
+ else {
+ DataToggle = 0;
+ }
+
+ OldToggle = DataToggle;
+
+ Status = UsbHcPpi->BulkTransfer(
+ PeiServices,
+ UsbHcPpi,
+ PeiUsbDev->DeviceAddress,
+ DeviceEndpoint,
+ PeiUsbDev->DeviceSpeed,
+ MaxPacketLength,
+ PeiUsbDev->TransactionTranslator,
+ Data,
+ DataLength,
+ &DataToggle,
+ Timeout,
+ &TransferResult
+ );
+
+ if (OldToggle != DataToggle) {
+ PeiUsbDev->DataToggle =
+ (UINT8) ( PeiUsbDev->DataToggle ^ (1 << EndpointIndex) );
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS PeiUsbGetInterfaceDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor )
+{
+ PEI_USB_DEVICE *PeiUsbDev;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS( This );
+
+ *InterfaceDescriptor = PeiUsbDev->InterfaceDesc;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS PeiUsbGetEndpointDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN UINT8 EndpointIndex,
+ IN EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor )
+{
+ PEI_USB_DEVICE *PeiUsbDev;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS( This );
+
+ if (EndpointIndex >= PeiUsbDev->InterfaceDesc->NumEndpoints) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *EndpointDescriptor = PeiUsbDev->EndpointDesc[EndpointIndex];
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS PeiUsbPortReset (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This )
+{
+ PEI_USB_DEVICE *PeiUsbDev;
+ EFI_STATUS Status;
+ UINT8 Address;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS( This );
+
+ ResetRootPort(
+ PeiServices,
+ PeiUsbDev->UsbHcPpi,
+ PeiUsbDev->DeviceAddress
+ );
+
+ //
+ // Set address
+ //
+ Address = PeiUsbDev->DeviceAddress;
+ PeiUsbDev->DeviceAddress = 0;
+
+ Status = PeiUsbSetDeviceAddress(
+ PeiServices,
+ This,
+ Address
+ );
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ PeiUsbDev->DeviceAddress = Address;
+
+ //
+ // Set default configuration
+ //
+ Status = PeiUsbSetConfiguration(
+ PeiServices,
+ This
+ );
+
+ return Status;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c b/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c
new file mode 100644
index 0000000..87afc78
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c
@@ -0,0 +1,1006 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbPeimSrc/UsbPeim.c 17 11/24/12 5:46a Ryanchou $
+//
+// $Revision: 17 $
+//
+// $Date: 11/24/12 5:46a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbPeimSrc/UsbPeim.c $
+//
+// 17 11/24/12 5:46a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 16 8/23/12 10:01p Wilsonlee
+// [TAG] EIP97069
+// [Category] Improvement
+// [Description] Reset root port algorythm update.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// UhcPeim.h, UsbPeim.c, usb.h
+//
+// 15 1/18/11 1:06a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 14 10/22/10 2:55a Rameshr
+// [TAG]- EIP 43687
+// [Category]-IMPROVEMENT
+// [Description]- Build warning from UsbRecovery driver -
+// UsbHostController.obj : warning LNK4221: no public symbols found;
+// archive member will be inaccessible.
+// [Files]- uhcpeim.c, usbpeim.c, UsbHostcontroller.h
+//
+// 13 10/12/10 11:20a Olegi
+// XHCI support added.
+//
+// 12 1/06/10 11:23a Olegi
+// Fix for EIP32503: The Interface descriptor of some devices is not
+// directly after the configuration descriptor, and the first Endpoint
+// descriptor is not directly after the Interface either. Changed the
+// descriptior data parser.
+//
+// 11 10/20/09 9:17a Olegi
+// EIP#28255: Set proper TransactionTranslator field for a non-hispeed USB
+// device.
+//
+// 10 3/17/09 5:07p Olegi
+// Added TransactionTranslator for slow/full speed devices behind USB2
+// hub.
+//
+// 9 10/21/08 5:57p Michaela
+// Added EHCI-related fixes for issues
+// that may occur if EHCI is used before
+// USB Recovery is invoked:
+// Added SDL Tokens:
+// PEI_EHCI_PCI_BDFS and
+// PEI_EHCI_MEM_BASE_ADDRESSES.
+//
+// Removed/modified some debugging
+// development code:
+// Removed SDL Tokens:
+// USBR_DEBUG_SUPPORT and
+// USBR_SERIAL_PORT_AVAILABLE
+// Removed Elinks:
+// UsbRecoveryDebug_DIR and
+// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+// Modified SDL Token:
+// FORCE_RECOVERY to default value of 0.
+//
+// (See this module's Help documentation
+// for more information.)
+//
+// 8 7/29/08 5:52p Michaela
+// 1) Updated code to move most porting tasks to SDL
+// 2) Added more debug break points and improved interactive
+// debugging capability for when a serial port is not available.
+// 3) Updated help files
+//
+// 7 7/18/08 5:05p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 6 7/10/08 6:37p Michaela
+// Updated to support OHCI controllers
+//
+// 5 10/23/07 5:41p Ambikas
+//
+// 4 8/17/07 4:13p Ambikas
+//
+// 3 4/16/07 12:55p Sivagarn
+// - Updated as per coding standard review
+// - In previous check-in, TIANO.H file is removed and AMIMAPPING.H file
+// is included
+//
+// 2 3/28/07 3:36a Meenakshim
+//
+// 1 9/22/06 12:19p Sivagarn
+// - Initial Checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbPeim.C
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+// This file contains generic routines needed for USB recovery
+// PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+/*++
+ This file contains 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+ --*/
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ UsbPeim.c
+
+ Abstract:
+
+ Usb Bus PPI
+
+ --*/
+
+#include "UsbPeim.h"
+#include "HubPeim.h"
+#include "PeiUsbLib.h"
+
+
+#include EFI_PPI_DEFINITION (Stall)
+#include EFI_PPI_DEFINITION (LoadFile)
+
+EFI_GUID gPeiUsbIoPpiGuid = PEI_USB_IO_PPI_GUID;
+
+extern EFI_GUID gPeiStallPpiGuid;
+
+
+#define PAGESIZE 4096
+
+//static BOOLEAN mImageInMemory = FALSE;
+
+
+//
+// Driver Entry Point
+//
+
+
+EFI_STATUS
+PeimInitializeUsb (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+
+//
+// UsbIo PPI interface function
+//
+STATIC PEI_USB_IO_PPI mUsbIoPpi = {
+ PeiUsbControlTransfer,
+ PeiUsbBulkTransfer,
+ PeiUsbGetInterfaceDescriptor,
+ PeiUsbGetEndpointDescriptor,
+ PeiUsbPortReset
+};
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiUsbIoPpiGuid,
+ NULL
+};
+
+//
+// Helper functions
+//
+STATIC
+EFI_STATUS
+PeiUsbEnumeration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi );
+
+STATIC
+EFI_STATUS
+PeiConfigureUsbDevice (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice,
+ IN UINT8 Port,
+ IN OUT UINT8 *DeviceAddress );
+
+STATIC
+EFI_STATUS
+PeiUsbGetAllConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice );
+
+
+VOID
+ResetRootPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
+ UINT8 PortNum );
+
+extern VOID ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size );
+
+
+
+//
+// PEIM Entry Point
+//
+// EFI_PEIM_ENTRY_POINT (PeimInitializeUsb);
+
+EFI_STATUS PeimInitializeUsb (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ EFI_STATUS Status;
+ UINTN i;
+ PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
+
+ // Assign resources and enable UHCI controllers
+ //
+ // when the image is in flash, the global variable
+ // mImageInMemory could not be modified;
+ // when the image is successfully loaded into memory,
+ // mImageInMemory could be modified to TRUE.
+ //
+
+ i = 0;
+ while (TRUE) {
+ //
+ // Get UsbHcPpi at first.
+ //
+ Status = (**PeiServices).LocatePpi( PeiServices,
+ &gPeiUsbHostControllerPpiGuid, i, NULL, &UsbHcPpi );
+
+ if ( EFI_ERROR( Status ) ) {
+ break;
+ }
+
+ PeiUsbEnumeration( PeiServices, UsbHcPpi ); // 0xff06
+ i++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS PeiHubEnumeration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice,
+ IN UINT8 *CurrentAddress )
+//
+// Since we are not going to support hot-plug, we will do a
+// dedicated polling process to get all ports change event
+// discovered. This can help to avoid introduce interrupt
+// transfer into the system, for each hub, we will wait for
+// 3s and if one port is enabled we will not wait for others
+// We will start parsing each of them in sequence.
+//
+{
+ UINTN Delay;
+ UINT8 Port;
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ EFI_USB_PORT_STATUS PortStatus;
+ BOOLEAN PortChanged;
+ UINT8 *AllocateAddress;
+ PEI_USB_DEVICE *NewPeiUsbDevice;
+ PEI_STALL_PPI *StallPpi;
+
+
+ PortChanged = FALSE;
+
+ UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+ Status = (**PeiServices).LocatePpi( PeiServices, &gPeiStallPpiGuid,
+ 0, NULL, &StallPpi );
+
+ Delay = (HUB_TIME_OUT * STALL_1_MILLI_SECOND / 50000) + 1;
+
+ //
+ // Do while will do a 3s scan for the USB HUB for a connected
+ // device. If we have found one, the waiting process will be
+ // breaked since we assue other ports will be discovered at
+ // the same time.
+ //
+ do {
+ for (Port = 1; Port <= PeiUsbDevice->DownStreamPortNo; Port++) {
+
+ Status = PeiHubGetPortStatus( PeiServices, UsbIoPpi,
+ Port, (UINT32 *) &PortStatus );
+
+ if ( EFI_ERROR( Status ) ) {
+ continue;
+ }
+
+ if ( IsPortConnectChange( PortStatus.PortChangeStatus ) ) {
+ PortChanged = TRUE;
+ PeiHubClearPortFeature( PeiServices, UsbIoPpi,
+ Port, EfiUsbPortConnectChange );
+
+ if ( IsPortConnect( PortStatus.PortStatus ) ) {
+
+ if (IsPortEnable(PortStatus.PortStatus) == FALSE) {
+ //
+ // First reset and enable this port
+ //
+ PeiResetHubPort( PeiServices, UsbIoPpi, Port );
+
+ PeiHubGetPortStatus( PeiServices, UsbIoPpi,
+ Port, (UINT32 *) &PortStatus );
+ }
+
+ //
+ // Begin to deal with the new device
+ //
+ Status = (*PeiServices)->AllocatePool( PeiServices,
+ sizeof(PEI_USB_DEVICE), &AllocateAddress );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewPeiUsbDevice = (PEI_USB_DEVICE *)AllocateAddress;
+
+ ZeroMem( NewPeiUsbDevice, sizeof(PEI_USB_DEVICE) );
+
+ NewPeiUsbDevice->Signature =
+ PEI_USB_DEVICE_SIGNATURE;
+ NewPeiUsbDevice->DeviceAddress = 0;
+ NewPeiUsbDevice->MaxPacketSize0 = 8;
+ NewPeiUsbDevice->DataToggle = 0;
+ NewPeiUsbDevice->UsbIoPpi = mUsbIoPpi;
+ NewPeiUsbDevice->UsbIoPpiList = mUsbIoPpiList;
+ NewPeiUsbDevice->UsbIoPpiList.Ppi =
+ &NewPeiUsbDevice->UsbIoPpi;
+ NewPeiUsbDevice->UsbHcPpi =
+ PeiUsbDevice->UsbHcPpi;
+ NewPeiUsbDevice->DeviceSpeed =
+ USB_FULL_SPEED_DEVICE;
+ NewPeiUsbDevice->IsHub = 0x0;
+ NewPeiUsbDevice->DownStreamPortNo = 0x0;
+ NewPeiUsbDevice->TransactionTranslator =
+ (UINT16)(Port << 7) + PeiUsbDevice->DeviceAddress;
+ NewPeiUsbDevice->HubDepth = 0x0;
+ //(EIP28255+)>
+ if ( (PeiUsbDevice->DeviceSpeed == USB_SLOW_SPEED_DEVICE) ||
+ (PeiUsbDevice->DeviceSpeed == USB_FULL_SPEED_DEVICE) )
+ {
+ NewPeiUsbDevice->TransactionTranslator = PeiUsbDevice->TransactionTranslator;
+ }
+ //<(EIP28255+)
+ if ( IsPortLowSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ NewPeiUsbDevice->DeviceSpeed = USB_SLOW_SPEED_DEVICE;
+ }
+
+ if ( IsPortHighSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ NewPeiUsbDevice->DeviceSpeed = USB_HIGH_SPEED_DEVICE;
+ }
+
+ if ( IsPortSuperSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ NewPeiUsbDevice->DeviceSpeed = USB_SUPER_SPEED_DEVICE;
+ }
+
+ //
+ // Configure that Usb Device
+ //
+ Status = PeiConfigureUsbDevice( PeiServices,
+ NewPeiUsbDevice, Port, CurrentAddress );
+
+ if ( EFI_ERROR( Status ) ) {
+ PeiHubClearPortFeature( PeiServices, UsbIoPpi,
+ Port, EfiUsbPortEnable );
+ continue;
+ }
+
+ Status = (**PeiServices).InstallPpi( PeiServices,
+ &NewPeiUsbDevice->UsbIoPpiList );
+
+ if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass
+ == BASE_CLASS_HUB)
+ {
+ NewPeiUsbDevice->IsHub = 0x1;
+ NewPeiUsbDevice->HubDepth = PeiUsbDevice->HubDepth + 1;
+
+ Status = PeiDoHubConfig( PeiServices,
+ NewPeiUsbDevice );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ PeiHubEnumeration( PeiServices, NewPeiUsbDevice,
+ CurrentAddress );
+ }
+ }
+
+ }
+ }
+
+ if (PortChanged) {
+ break;
+ }
+ StallPpi->Stall( PeiServices, StallPpi, 50000 );
+
+ } while (Delay--);
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS PeiUsbEnumeration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi )
+{
+ UINT8 NumOfRootPort;
+ EFI_STATUS Status;
+ UINT8 Port;
+ EFI_USB_PORT_STATUS PortStatus;
+ PEI_USB_DEVICE *PeiUsbDevice;
+ UINT8 *AllocateAddress;
+ UINT8 CurrentAddress;
+ PEI_STALL_PPI *PeiStall;
+
+ (**PeiServices).LocatePpi(
+ PeiServices,
+ &gPeiStallPpiGuid,
+ 0,
+ NULL,
+ &PeiStall
+ );
+
+ CurrentAddress = 0;
+ UsbHcPpi->GetRootHubPortNumber(
+ PeiServices,
+ UsbHcPpi,
+ (UINT8 *) &NumOfRootPort
+ );
+
+
+ for (Port = 1; Port <= NumOfRootPort; Port++) {
+ //
+ // First get root port status to detect changes happen
+ //
+ UsbHcPpi->GetRootHubPortStatus(
+ PeiServices,
+ UsbHcPpi,
+ Port,
+ &PortStatus
+ );
+
+ if ( IsPortConnectChange( PortStatus.PortChangeStatus ) ) {
+
+ //
+ // Changes happen, first clear this change status
+ //
+ UsbHcPpi->ClearRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ Port,
+ EfiUsbPortConnectChange
+ );
+
+ if ( IsPortConnect( PortStatus.PortStatus ) ) {
+
+ if (IsPortEnable(PortStatus.PortStatus) == FALSE) {
+ //
+ // First reset and enable this port
+ //
+ ResetRootPort( PeiServices, UsbHcPpi, Port );
+
+ UsbHcPpi->GetRootHubPortStatus(
+ PeiServices,
+ UsbHcPpi,
+ Port,
+ &PortStatus
+ );
+ }
+
+ //
+ // Connect change happen
+ //
+ Status = (*PeiServices)->AllocatePool(
+ PeiServices,
+ sizeof(PEI_USB_DEVICE),
+ &AllocateAddress
+ );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PeiUsbDevice = (PEI_USB_DEVICE *) ( (UINTN) AllocateAddress );
+ ZeroMem( PeiUsbDevice, sizeof(PEI_USB_DEVICE) );
+
+ PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
+ PeiUsbDevice->DeviceAddress = 0;
+ PeiUsbDevice->MaxPacketSize0 = 8;
+ PeiUsbDevice->DataToggle = 0;
+ PeiUsbDevice->UsbIoPpi = mUsbIoPpi;
+ PeiUsbDevice->UsbIoPpiList = mUsbIoPpiList;
+ PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
+ PeiUsbDevice->UsbHcPpi = UsbHcPpi;
+ PeiUsbDevice->DeviceSpeed = USB_FULL_SPEED_DEVICE;
+ PeiUsbDevice->IsHub = 0x0;
+ PeiUsbDevice->DownStreamPortNo = 0x0;
+ PeiUsbDevice->TransactionTranslator = 0x0;
+ PeiUsbDevice->HubDepth = 0x0;
+
+ if ( IsPortLowSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ PeiUsbDevice->DeviceSpeed = USB_SLOW_SPEED_DEVICE;
+ }
+
+ if ( IsPortHighSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ PeiUsbDevice->DeviceSpeed = USB_HIGH_SPEED_DEVICE;
+ }
+
+ if ( IsPortSuperSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ PeiUsbDevice->DeviceSpeed = USB_SUPER_SPEED_DEVICE;
+ }
+
+ //
+ // Delay some times to enable usb devices to initiate.
+ //
+ PeiStall->Stall(
+ PeiServices,
+ PeiStall,
+ 5000
+ );
+
+ //
+ // Configure that Usb Device
+ //
+ Status = PeiConfigureUsbDevice(
+ PeiServices,
+ PeiUsbDevice,
+ Port,
+ &CurrentAddress
+ );
+
+ if ( EFI_ERROR( Status ) ) {
+ UsbHcPpi->ClearRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ Port,
+ EfiUsbPortEnable
+ );
+ continue;
+ }
+
+ Status = (**PeiServices).InstallPpi(
+ PeiServices,
+ &PeiUsbDevice->UsbIoPpiList
+ );
+
+ if (PeiUsbDevice->InterfaceDesc->InterfaceClass
+ == BASE_CLASS_HUB)
+ {
+ PeiUsbDevice->IsHub = 0x1;
+
+ Status = PeiDoHubConfig( PeiServices, PeiUsbDevice );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ PeiHubEnumeration( PeiServices, PeiUsbDevice,
+ &CurrentAddress );
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC EFI_STATUS PeiConfigureUsbDevice (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice,
+ IN UINT8 Port,
+ IN OUT UINT8 *DeviceAddress )
+{
+ EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ UINT8 i;
+ PEI_STALL_PPI *StallPpi = NULL;
+ UINT8 Retry = 2;
+
+ ( **PeiServices ).LocatePpi( PeiServices, &gPeiStallPpiGuid,
+ 0, NULL, &StallPpi );
+
+ if (PeiUsbDevice->UsbHcPpi->PreConfigureDevice != NULL) {
+ Status = PeiUsbDevice->UsbHcPpi->PreConfigureDevice( PeiServices,
+ PeiUsbDevice->UsbHcPpi, Port, PeiUsbDevice->DeviceSpeed,
+ PeiUsbDevice->TransactionTranslator);
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ }
+
+ UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+
+ //-----------------------------------------------------------------------
+ // Try 5 times to read the first 8 bytes to determine the size
+ for (i = 0; i < 5; i++) {
+ Status = PeiUsbGetDescriptor( PeiServices,
+ UsbIoPpi,
+ SET_DESCRIPTOR_TYPE( USB_DT_DEVICE ), // Value = Type << 8 | Index
+ 0, // Index
+ 8, // DescriptorLength
+ &DeviceDescriptor );
+ if ( !EFI_ERROR( Status ) ) {
+ break;
+ }
+ StallPpi->Stall( PeiServices, StallPpi, 100 * 1000 ); // 100msec delay
+ }
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ //-----------------------------------------------------------------------
+ // Set MaxPacketSize0 = 0x40 if packet size is not specified
+ PeiUsbDevice->MaxPacketSize0 = (DeviceDescriptor.MaxPacketSize0)
+ ? DeviceDescriptor.MaxPacketSize0
+ : 0x40;
+
+
+ //-----------------------------------------------------------------------
+ // Get the entire USB device descriptor
+ StallPpi->Stall( PeiServices, StallPpi, 10 * 1000 ); // 10msec delay
+ Status = PeiUsbGetDescriptor(
+ PeiServices,
+ UsbIoPpi,
+ SET_DESCRIPTOR_TYPE( USB_DT_DEVICE ), // Value = Type << 8 | Index
+ 0, // Index
+ sizeof(EFI_USB_DEVICE_DESCRIPTOR), // DescriptorLength
+ &DeviceDescriptor );
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ //-----------------------------------------------------------------------
+ // Get its default configuration and its first interface
+ StallPpi->Stall( PeiServices, StallPpi, 10 * 1000 ); // 10msec delay
+ Status = PeiUsbGetAllConfiguration(
+ PeiServices,
+ PeiUsbDevice );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ //-----------------------------------------------------------------------
+ // Set the device's address
+ StallPpi->Stall( PeiServices, StallPpi, 10 * 1000 ); // 10msec delay
+ (*DeviceAddress)++;
+ Status = PeiUsbSetDeviceAddress(
+ PeiServices,
+ UsbIoPpi,
+ *DeviceAddress );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ PeiUsbDevice->DeviceAddress = *DeviceAddress;
+
+
+ StallPpi->Stall( PeiServices, StallPpi, 200 * 1000 ); // 200msec delay
+
+ Status = PeiUsbSetConfiguration(
+ PeiServices,
+ UsbIoPpi );
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC EFI_STATUS PeiUsbGetAllConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *Device )
+{
+ EFI_USB_CONFIG_DESCRIPTOR ConfigDesc = {0};
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndPointDesc = NULL; //(EIP32503+)
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi = &Device->UsbIoPpi;
+ UINTN i;
+ UINT8 *LastAddress = 0;
+
+
+ // Here we are parsing the descriptors for the device
+ // configurations where the hierarchy of descriptors
+ // is as follows:
+ //
+ // +----------------+
+ // | Configuration1 |
+ // +----------------+
+ // | +------------+
+ // +---------| Interface1 |----+------------------+
+ // | +------------+ | |
+ // | +-----------+ +-------------+
+ // | | Endpoint1 | ... | EndpointMax |
+ // | +-----------+ +-------------+
+ // | :
+ // | :
+ // | :
+ // |
+ // | +--------------+
+ // +---------| InterfaceMax |----+------------------+
+ // +--------------+ | |
+ // : +-----------+ +-------------+
+ // : | Endpoint1 | ... | EndpointMax |
+ // +-----------+ +-------------+
+ // +------------------+
+ // | ConfigurationMax |
+ // +------------------+
+ // | +------------+
+ // +---------| Interface1 |----+------------------+
+ // | +------------+ | |
+ // | +-----------+ +-------------+
+ // | | Endpoint1 | ... | EndpointMax |
+ // | +-----------+ +-------------+
+ // | :
+ // | :
+ // | :
+ // | +--------------+
+ // +---------| InterfaceMax |----+------------------+
+ // +--------------+ | |
+ // +-----------+ +-------------+
+ // | Endpoint1 | ... | EndpointMax |
+ // +-----------+ +-------------+
+
+
+ //-------------------------------------------------------------
+ // Fortunately, we are only interested in the first/default
+ // configuration and its first/default interface, so life is
+ // simple!
+ //-------------------------------------------------------------
+
+ //-------------------------------------------------------------
+ // First get the device's 9-byte configuration descriptor to
+ // determine the length of all descriptors
+ Status = PeiUsbGetDescriptor(
+ PeiServices,
+ UsbIoPpi,
+ USB_DT_CONFIG << 8,
+ 0,
+ 9,
+ &ConfigDesc );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ Status = (*PeiServices)->AllocatePool( PeiServices,
+ ConfigDesc.TotalLength, &Device->ConfigurationData );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ //-------------------------------------------------------------
+ // Get all the descriptors for this configuration using
+ // TotalLength from the first 9 bytes previously read.
+ // Then, save the Configuration descriptor into the
+ // device management structure.
+ Status = PeiUsbGetDescriptor(
+ PeiServices,
+ UsbIoPpi,
+ USB_DT_CONFIG << 8,
+ 0,
+ ConfigDesc.TotalLength,
+ (VOID *) Device->ConfigurationData );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ Device->ConfigDesc =
+ (EFI_USB_CONFIG_DESCRIPTOR *) Device->ConfigurationData;
+
+ LastAddress = Device->ConfigurationData +
+ Device->ConfigDesc->TotalLength - 1;
+
+ if (Device->UsbHcPpi->EnableEndpoints != NULL) {
+ Status = Device->UsbHcPpi->EnableEndpoints(PeiServices,
+ Device->UsbHcPpi, Device->ConfigurationData);
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ }
+
+ //--------------------------------------------------------------
+ // Assume the Interface descriptor is directly after the
+ // configuration descriptor.
+ //--------------------------------------------------------------
+ Device->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *)
+ ( (UINT8 *) Device->ConfigDesc +
+ Device->ConfigDesc->Length );
+ //(EIP32503+)>
+ while ((UINT8 *)Device->InterfaceDesc < LastAddress &&
+ Device->InterfaceDesc->DescriptorType != USB_DT_INTERFACE)
+ {
+ Device->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *)
+ ( (UINT8 *) Device->InterfaceDesc +
+ Device->InterfaceDesc->Length );
+ }
+ //<(EIP32503+)
+ //--------------------------------------------------------------
+ // Assume the first Endpoint descriptor is directly after the
+ // Interface descriptor.
+ //--------------------------------------------------------------
+ //(EIP32503)>
+ EndPointDesc = (EFI_USB_ENDPOINT_DESCRIPTOR *)
+ ( (UINT8 *) Device->InterfaceDesc +
+ Device->InterfaceDesc->Length );
+
+ for (i = 0; i < Device->InterfaceDesc->NumEndpoints &&
+ (UINT8 *)EndPointDesc < LastAddress; )
+ {
+ if(EndPointDesc->DescriptorType == USB_DT_ENDPOINT)
+ {
+ Device->EndpointDesc[i++] = EndPointDesc;
+ }
+ EndPointDesc = (EFI_USB_ENDPOINT_DESCRIPTOR *)
+ ( (UINT8 *) EndPointDesc +
+ EndPointDesc->Length );
+ }
+ //<(EIP32503)
+ return EFI_SUCCESS;
+}
+
+
+//
+// Send reset signal over the given root hub port
+//
+VOID ResetRootPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
+ UINT8 PortNum )
+{
+ EFI_PEI_STALL_PPI *PeiStall;
+ EFI_USB_PORT_STATUS PortStatus;
+ UINT8 i;
+
+ ( **PeiServices ).LocatePpi(
+ PeiServices,
+ &gPeiStallPpiGuid,
+ 0,
+ NULL,
+ &PeiStall
+ );
+
+
+ //
+ // reset root port
+ //
+ UsbHcPpi->SetRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ for (i = 0; i < 100; i++) {
+ UsbHcPpi->GetRootHubPortStatus(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ &PortStatus
+ );
+
+ if ((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) != 0) {
+ break;
+ }
+
+ PeiStall->Stall(
+ PeiServices,
+ PeiStall,
+ 1 * 1000 // NVS - Changed to 10 msec (as per AMI USB Code)
+ );
+ }
+
+ if ((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) {
+ return;
+ }
+
+ //
+ // clear reset root port
+ //
+ UsbHcPpi->ClearRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortResetChange
+ );
+
+
+ UsbHcPpi->GetRootHubPortStatus(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ &PortStatus
+ );
+
+ if ((PortStatus.PortChangeStatus & USB_PORT_STAT_ENABLE) == 0) {
+ //
+ // Set port enable
+ //
+ UsbHcPpi->SetRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortEnable
+ );
+ PeiStall->Stall(
+ PeiServices,
+ PeiStall,
+ 100 * 1000 // NVS - Changed to 100msec as per AMI USB code
+ );
+ }
+
+ return;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeimSrc.cif b/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeimSrc.cif
new file mode 100644
index 0000000..4eca72e
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeimSrc.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "UsbPeimSrc"
+ category = ModulePart
+ LocalRoot = "Core\EM\UsbRecovery\UsbPeimSrc\"
+ RefName = "UsbPeimSrc"
+[files]
+"HubPeim.c"
+"UsbIoPeim.c"
+"UsbPeim.c"
+[parts]
+"UsbIoPpi"
+<endComponent>
diff --git a/Core/EM/UsbRecovery/UsbRecov.mak b/Core/EM/UsbRecovery/UsbRecov.mak
new file mode 100644
index 0000000..5cb7fea
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbRecov.mak
@@ -0,0 +1,457 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+#
+# $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbRecov.mak 12 10/17/12 5:06a Roberthsu $
+#
+# $Revision: 12 $
+#
+# $Date: 10/17/12 5:06a $
+#
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbRecov.mak $
+#
+# 12 10/17/12 5:06a Roberthsu
+# [TAG] EIP77332
+# [Category] Improvement
+# [Description] Implement pei loadfirmware.
+# [Files] LoadFirmware.cif,LoadFirmware.sdl,LoadFirmware.mak,PeiRenesa
+# s.c,PeiRenesas.h,DxeRenesas.c,DxeRenesas.h,UsbRecov.mak
+#
+# 11 10/14/10 2:42p Olegi
+#
+# 10 10/11/10 4:51p Olegi
+# XHCI support added.
+#
+# 9 3/03/09 7:24p Olegi
+# Added EHCI support.
+#
+# 8 10/21/08 5:56p Michaela
+# Added EHCI-related fixes for issues
+# that may occur if EHCI is used before
+# USB Recovery is invoked:
+# Added SDL Tokens:
+# PEI_EHCI_PCI_BDFS and
+# PEI_EHCI_MEM_BASE_ADDRESSES.
+#
+# Removed/modified some debugging
+# development code:
+# Removed SDL Tokens:
+# USBR_DEBUG_SUPPORT and
+# USBR_SERIAL_PORT_AVAILABLE
+# Removed Elinks:
+# UsbRecoveryDebug_DIR and
+# $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+# Modified SDL Token:
+# FORCE_RECOVERY to default value of 0.
+#
+# (See this module's Help documentation
+# for more information.)
+#
+# 7 7/29/08 5:50p Michaela
+# 1) Updated code to move most porting tasks to SDL
+# 2) Added more debug break points and improved interactive
+# debugging capability for when a serial port is not available.
+# 3) Updated help files
+#
+# 6 7/18/08 5:03p Michaela
+# 1 File-level debugging is now available
+# 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+# the keypress so that conditional debugging can
+# be dynamic (alphanumeric keys only)
+# 3 Added more function headers.
+# 4 Removed code that will never be used (I.e., Bala?).
+# 5 Moved typedef, contants and extern declarations
+# into header files.
+# 6 Now all controller blocks are enabled for SB700
+# (EHCI controllers route to companion controller
+# by default)
+# 7 Removed unused constants and typedefs n OhciPei.h
+# (also reorganized the file to make it more
+# readable.)
+# 8 Renamed many functions/variables according to
+# coding standard.
+# 9 Removed code initializing data structures for
+# periodic lists, as this is not needed.
+# 10 Removed the CONTROLLER_TYPE SDL token to
+# allow UHCI and OHCI controllers to supported
+# simultaneously. (modified MAKE files
+# accordingly)
+#
+# 5 7/10/08 6:33p Michaela
+# Updated to support OHCI controllers
+#
+# 4 8/17/07 4:29p Ambikas
+#
+# 3 3/28/07 3:06a Meenakshim
+# Removed dependency on core source files..Added amimapping file.
+#
+# 2 9/22/06 4:07p Sivagarn
+# - Initial Check-in
+# - Included Recovery code in Source
+# - Included appropriate headers for flies and functions
+# - Updated copyright messages
+# - Merged multiple MAK and SDL files into one MAK and SDL file
+# - Removed unnecessary files
+#
+#**********************************************************************
+
+
+#<AMI_FHDR_START>
+#-----------------------------------------------------------------------
+#
+# Name: UsbRecov.mak
+#
+# Description: Contains make script to build USB Recovery related
+# PEIM. This script file generates UhciPeiUsb, OhciPei,
+# UhcPeim, UsbPeim and UsbBotPeim
+#
+#-----------------------------------------------------------------------
+#<AMI_FHDR_END>
+
+# Define the target list based the RECOVERY_DEBUG_SUPPORT SDL token
+# which enables/disables generic USB console debugging routines.
+
+USB_RECOVERY_TARGETS = \
+ UsbBotPeimSrc
+
+all : $(USB_RECOVERY_TARGETS)
+
+
+#-----------------------------------------------------------------------
+# Build script for UhciPeiUsb.lib
+#-----------------------------------------------------------------------
+UhciPeiUsb : $(BUILD_DIR)\UhcipeiUsb.mak UhcipeiUsbBin
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate UhcipeiUsb.mak
+
+UHCI_PEI_USB_MAK_DEPS = \
+ $(UhcipeiUsb_DIR)\UhcipeiUsb.cif \
+ $(UsbRecovery_DIR)\UsbRecov.mak \
+ $(BUILD_RULES)
+
+UHCI_PEI_USB_CIF2MAK_ARGS = \
+ $(UhcipeiUsb_DIR)\UhcipeiUsb.cif \
+ $(CIF2MAK_DEFAULTS) \
+ $(UsbRecovery_DIR)\UsbRecovery.cif
+
+$(BUILD_DIR)\UhcipeiUsb.mak : $(UHCI_PEI_USB_MAK_DEPS)
+ $(CIF2MAK) $(UHCI_PEI_USB_CIF2MAK_ARGS)
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate UhciPeiUsb.lib
+
+UHCI_PEI_USB_LIB_CFLAGS = $(CFLAGS) \
+ /I $(UhcipeiUsb_DIR) \
+ /I $(UsbRecovery_DIR)
+
+UHCI_PEI_USB_LIB_DEPS = \
+ $(AMIPEILIB)
+
+UhcipeiUsbBin : $(UHCI_PEI_USB_LIB_DEPS)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\UhciPeiUsb.mak all\
+ GUID=6895F6F0-8879-45B8-A9D9-9639E532319E\
+ "CFLAGS=$(UHCI_PEI_USB_LIB_CFLAGS)"\
+ TYPE=PEI_LIBRARY
+
+
+#-----------------------------------------------------------------------
+# Build script for UhcPeim.lib
+#-----------------------------------------------------------------------
+UhcPeim : $(BUILD_DIR)\UhcPeim.mak UhcPeimBin
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate UhcPeim.mak
+
+UHC_PEIM_MAK_DEPS = \
+ $(UhcPeimSrc_DIR)\UhcPeimSrc.cif \
+ $(UsbRecovery_DIR)\UsbRecovery.cif \
+ $(UsbRecovery_DIR)\UsbRecov.mak \
+ $(BUILD_RULES)
+
+UHC_PEIM_CIF2MAK_ARGS = \
+ $(UhcPeimSrc_DIR)\UhcPeimSrc.cif \
+ $(CIF2MAK_DEFAULTS) \
+ $(UsbRecovery_DIR)\UsbRecovery.cif \
+
+$(BUILD_DIR)\UhcPeim.mak : $(UHC_PEIM_MAK_DEPS)
+ $(CIF2MAK) $(UHC_PEIM_CIF2MAK_ARGS)
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate UhcPeim.lib
+
+UHC_PEIM_LIB_CFLAGS= $(CFLAGS) \
+ /I $(UhcPeimSrc_DIR) \
+ /I $(UsbRecovery_DIR)
+
+UHC_PEIM_LIB_DEPS = \
+ $(AMIPEILIB)
+
+UhcPeimBin : $(UHC_PEIM_LIB_DEPS)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\UhcPeim.mak all \
+ NAME=UhcPeim\
+ MAKEFILE=$(BUILD_DIR)\UhcPeim.mak \
+ "CFLAGS=$(UHC_PEIM_LIB_CFLAGS)" \
+ GUID=C463CEAC-FC57-4f36-88B7-356C750C3BCA \
+ TYPE=PEI_LIBRARY
+
+
+#-----------------------------------------------------------------------
+# Build script for OhciPei.lib
+#-----------------------------------------------------------------------
+OhciPei : $(BUILD_DIR)\OhciPei.mak OhcipeiBin
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate OhciPei.mak
+
+OHCI_PEI_MAK_DEPS = \
+ $(OhciPei_DIR)\OhciPei.cif \
+ $(UsbRecovery_DIR)\UsbRecovery.cif \
+ $(UsbRecovery_DIR)\UsbRecov.mak \
+ $(BUILD_RULES)
+
+OHCI_PEI_CIF2MAK_ARGS = \
+ $(OhciPei_DIR)\OhciPei.cif \
+ $(CIF2MAK_DEFAULTS) \
+ $(UsbRecovery_DIR)\UsbRecovery.cif
+
+$(BUILD_DIR)\OhciPei.mak : $(OHCI_PEI_MAK_DEPS)
+ $(CIF2MAK) $(OHCI_PEI_CIF2MAK_ARGS)
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate OhciPei.lib
+
+OHCI_PEI_LIB_CFLAGS = \
+ $(CFLAGS) \
+ /I $(UsbRecovery_DIR) \
+ /D\"USBR_OHCI_CONTROLLER_PCI_ADDRESS=$(USBR_OHCI_CONTROLLER_PCI_ADDRESS)\" \
+ /D\"USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE=$(USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE)\"
+
+OHCI_PEI_LIB_DEPS = \
+ $(AMIPEILIB)
+
+OhciPeiBin : $(OHCI_PEI_LIB_DEPS)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS) \
+ /f $(BUILD_DIR)\OhciPei.mak all \
+ NAME=OhciPei \
+ MAKEFILE=$(BUILD_DIR)\OhciPei.mak \
+ GUID=52DAA304-DEB3-449b-AFB8-A88A54F28F95 \
+ "CFLAGS=$(OHCI_PEI_LIB_CFLAGS)" \
+ TYPE=PEI_LIBRARY
+
+
+#-----------------------------------------------------------------------
+# Build script for XhciPei.lib
+#-----------------------------------------------------------------------
+XhciPei : $(BUILD_DIR)\XhciPei.mak XhciPeiBin
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate XhciPei.mak
+
+XHCI_PEI_MAK_DEPS = \
+ $(XHCIPEI_DIR)\XhciPei.cif \
+ $(UsbRecovery_DIR)\UsbRecovery.cif \
+ $(UsbRecovery_DIR)\UsbRecov.mak \
+ $(BUILD_RULES)
+
+XHCI_PEI_CIF2MAK_ARGS = \
+ $(XHCIPEI_DIR)\XhciPei.cif \
+ $(CIF2MAK_DEFAULTS) \
+ $(UsbRecovery_DIR)\UsbRecovery.cif
+
+$(BUILD_DIR)\XhciPei.mak : $(XHCI_PEI_MAK_DEPS)
+ $(CIF2MAK) $(XHCI_PEI_CIF2MAK_ARGS)
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate XhciPei.lib
+
+XHCI_PEI_LIB_CFLAGS = \
+ $(CFLAGS) \
+ /I $(UsbRecovery_DIR) \
+
+XHCI_PEI_LIB_DEPS = \
+ $(AMIPEILIB)
+
+XhciPeiBin : $(XHCI_PEI_LIB_DEPS)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS) \
+ /f $(BUILD_DIR)\XhciPei.mak all \
+ NAME=XhciPei \
+ MAKEFILE=$(BUILD_DIR)\XhciPei.mak \
+ GUID=45D68DB9-8B4E-48c0-99E9-F21F262DB653 \
+ "CFLAGS=$(XHCI_PEI_LIB_CFLAGS)" \
+ TYPE=PEI_LIBRARY
+
+#// {45D68DB9-8B4E-48c0-99E9-F21F262DB653}
+#0x45d68db9, 0x8b4e, 0x48c0, 0x99, 0xe9, 0xf2, 0x1f, 0x26, 0x2d, 0xb6, 0x53);
+
+#-----------------------------------------------------------------------
+# Build script for EhciPei.lib
+#-----------------------------------------------------------------------
+EhciPei : $(BUILD_DIR)\EhciPei.mak EhcipeiBin
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate EhciPei.mak
+
+EHCI_PEI_MAK_DEPS = \
+ $(EHCIPEI_DIR)\EhciPei.cif \
+ $(UsbRecovery_DIR)\UsbRecovery.cif \
+ $(UsbRecovery_DIR)\UsbRecov.mak \
+ $(BUILD_RULES)
+
+EHCI_PEI_CIF2MAK_ARGS = \
+ $(EHCIPEI_DIR)\EhciPei.cif \
+ $(CIF2MAK_DEFAULTS) \
+ $(UsbRecovery_DIR)\UsbRecovery.cif
+
+$(BUILD_DIR)\EhciPei.mak : $(EHCI_PEI_MAK_DEPS)
+ $(CIF2MAK) $(EHCI_PEI_CIF2MAK_ARGS)
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate EhciPei.lib
+
+EHCI_PEI_LIB_CFLAGS = \
+ $(CFLAGS) \
+ /I $(UsbRecovery_DIR)
+
+EHCI_PEI_LIB_DEPS = \
+ $(AMIPEILIB)
+
+EhciPeiBin : $(EHCI_PEI_LIB_DEPS)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS) \
+ /f $(BUILD_DIR)\EhciPei.mak all \
+ NAME=EhciPei \
+ MAKEFILE=$(BUILD_DIR)\EhciPei.mak \
+ GUID=D56A4094-570F-4D3D-8F5F-8D8AA0B396CB \
+ "CFLAGS=$(EHCI_PEI_LIB_CFLAGS)" \
+ TYPE=PEI_LIBRARY
+
+#-----------------------------------------------------------------------
+# Build script for UsbPeim.lib
+#-----------------------------------------------------------------------
+UsbPeimSrc : $(BUILD_DIR)\UsbPeimSrc.mak UsbPeimSrcBin
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate UsbPeimSrc.mak
+
+USB_PEIM_MAK_DEPS = \
+ $(UsbPeimSrc_DIR)\UsbPeimSrc.cif \
+ $(UsbRecovery_DIR)\UsbRecovery.cif \
+ $(UsbRecovery_DIR)\UsbRecov.mak \
+ $(BUILD_RULES)
+
+USB_PEIM_CIF2MAK_ARGS = \
+ $(UsbPeimSrc_DIR)\UsbPeimSrc.cif \
+ $(CIF2MAK_DEFAULTS) \
+ $(UsbRecovery_DIR)\UsbRecovery.cif
+
+$(BUILD_DIR)\UsbPeimSrc.mak : $(USB_PEIM_MAK_DEPS)
+ $(CIF2MAK) $(USB_PEIM_CIF2MAK_ARGS)
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate UsbPeim.lib
+
+USB_PEIM_LIB_CFLAGS = \
+ $(CFLAGS) \
+ /I $(UsbRecovery_DIR)
+
+USB_PEIM_LIB_DEPS = \
+ $(AMIPEILIB)
+
+UsbPeimSrcBin : $(USB_PEIM_LIB_DEPS)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\UsbPeimSrc.mak all \
+ NAME=UsbPeim \
+ MAKEFILE=$(BUILD_DIR)\UsbPeimSrc.mak \
+ "CFLAGS=$(USB_PEIM_LIB_CFLAGS)" \
+ TYPE=PEI_LIBRARY
+
+
+#-----------------------------------------------------------------------
+# Build script for UsbBotPeim.ffs
+#-----------------------------------------------------------------------
+UsbBotPeimSrc: $(BUILD_DIR)\UsbBotPeimSrc.mak UsbBotPeimSrcBin
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate UsbPeimSrc.mak using Cif2Mak.exe
+
+USB_BOT_PEIM_MAK_DEPS = \
+ $(UsbBotPeimSrc_DIR)\UsbBotPeim.cif \
+ $(UsbRecovery_DIR)\UsbRecovery.cif \
+ $(UsbRecovery_DIR)\UsbRecov.mak \
+ $(BUILD_RULES)
+
+USB_BOT_PEIM_CIF2MAK_ARGS = \
+ $(UsbBotPeimSrc_DIR)\UsbBotPeim.cif \
+ $(CIF2MAK_DEFAULTS)
+
+$(BUILD_DIR)\UsbBotPeimSrc.mak : $(USB_BOT_PEIM_MAK_DEPS)
+ $(CIF2MAK) $(USB_BOT_PEIM_CIF2MAK_ARGS)
+
+#~~~~~~~~~~~~~~~~~~~~~~~ Generate UsbBotPeim.ffs
+
+USB_BOT_PEIM_FFS_CFLAGS= \
+ $(CFLAGS) \
+ /I $(UsbBotPeimSrc_DIR) \
+ /I $(UsbRecovery_DIR) \
+ /I $(UhcPeimSrc_DIR) \
+ /I $(UhcipeiUsb_DIR) \
+ /I $(UsbPeimSrc_DIR) \
+ /I $(OhciPei_DIR) \
+ /I $(EHCIPEI_DIR) \
+ /I $(XHCIPEI_DIR)
+
+$(BUILD_DIR)\UhcPeim.lib : UhcPeim
+$(BUILD_DIR)\UsbPeim.lib : UsbPeimSrc
+$(BUILD_DIR)\UhcipeiUsb.lib : UhcipeiUsb
+$(BUILD_DIR)\OhciPei.lib : OhciPei
+$(BUILD_DIR)\EhciPei.lib : EhciPei
+$(BUILD_DIR)\XhciPei.lib : XhciPei
+
+USB_BOT_PEIM_FFS_DEPS = \
+ $(AMIPEILIB) \
+ $(BUILD_DIR)\UsbPeim.lib \
+!if $(PEI_UHCI_SUPPORT)
+ $(BUILD_DIR)\UhcPeim.lib \
+ $(BUILD_DIR)\UhcipeiUsb.lib \
+!endif
+!if $(PEI_OHCI_SUPPORT)
+ $(BUILD_DIR)\OhciPei.lib \
+!endif
+!if $(PEI_EHCI_SUPPORT)
+ $(BUILD_DIR)\EhciPei.lib \
+!endif
+!if $(PEI_XHCI_SUPPORT)
+ $(BUILD_DIR)\XhciPei.lib \
+!endif
+
+UsbBotPeimSrcBin : $(USB_BOT_PEIM_FFS_DEPS)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS) \
+ /f $(BUILD_DIR)\UsbBotPeimSrc.mak all \
+ NAME=UsbBotPeim \
+ MAKEFILE=$(BUILD_DIR)\UsbBotPeimSrc.mak \
+ GUID=8401A046-6F70-4505-8471-7015B40355E3 \
+ ENTRY_POINT=PeimInitializeUsbBot \
+ "CFLAGS=$(USB_BOT_PEIM_FFS_CFLAGS)" \
+ DEPEX1=$(UsbBotPeimSrc_DIR)\UsbBotPeim.dxs DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \
+ TYPE=PEIM \
+ COMPRESS=1\
+ "INIT_LIST=$(BeforeUsbRecovery)"
+
+
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
diff --git a/Core/EM/UsbRecovery/UsbRecov.sdl b/Core/EM/UsbRecovery/UsbRecov.sdl
new file mode 100644
index 0000000..681c70d
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbRecov.sdl
@@ -0,0 +1,237 @@
+TOKEN
+ Name = "UsbRecov_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable UsbRecovery support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "PEI_UHCI_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable UHCI Controller support for USB recovery"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_OHCI_SUPPORT"
+ Value = "0"
+ Help = "Main switch to enable OhciPei support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_EHCI_SUPPORT"
+ Value = "0"
+ Help = "Main switch to enable EhciPei support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_XHCI_SUPPORT"
+ Value = "0"
+ Help = "Main switch to enable XhciPei support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_UHCI_IOBASE"
+ Value = "0x4000"
+ Help = "IO Base Address for UHCI Controller during PEI phase"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_UHCI_PCI_DEVICES"
+ Value = "{0x1D0000, 0x1D0100, 0x1D0200, 0x1D0300, 0x1A0000, 0x1A0100}"
+ Help = "List of supported UHCI controllers in the following format: {devfunc1, devfunc2,...,devfuncN}\devfunc represents the location of UHCI controller on PCI bus: dev = Bus << 24 + Dev << 16 + Func << 8. Value followed by dev is the PCI device interface, for UHCI it must be 0.\Note: number of entries {devfunc} must not be less than a number of supported UHCI controllers specified in USB_UHCI token."
+ TokenType = Expression
+ TargetH = Yes
+ Token = "PEI_UHCI_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "PEI_UHCI_PCI_DEVICES"
+ Value = "{0}"
+ Help = "Default value if not using UHCI controller"
+ TokenType = Expression
+ TargetH = Yes
+ Token = "PEI_UHCI_SUPPORT" "=" "0"
+End
+
+TOKEN
+ Name = "PEI_EHCI_PCI_BDFS"
+ Value = "{0x1A0700, 0x1D0700}"
+ Help = "List of supported EHCI controllers in the following format: {devfunc1, devfunc2,...,devfuncN}\devfunc represents the location of EHCI controller on PCI bus: dev = Bus << 24 + Dev << 16 + Func << 8. Value followed by dev is the PCI device interface, for EHCI it must be 0.\Note: number of entries {devfunc} must not be less than a number of supported EHCI controllers specified in PEI_NUM_EHCI token."
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_EHCI_MEM_BASE_ADDRESSES"
+ Value = "{0xDFFFF000, 0xDFFFFC00}"
+ Help = "List of base addresses for the respective EHCI controllers specified by PEI_EHCI_PCI_BDFS"
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_OHCI_IOBASE"
+ Value = "0xFC087000"
+ Help = "Memory Mapped IO Base Address for first Recovery module OHCI Controller during PEI phase"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_XHCI_MMIOBASE"
+ Value = "0xFE400000"
+ Help = "MMIO Base Address for first XHCI Controller during PEI phase"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_XHCI_CONTROLLER_PCI_ADDRESS"
+ Value = "{0x1, 0x0, 0x0},"
+ Help = "Default value if XHCI controllers are not supported"
+ Token = "PEI_XHCI_SUPPORT" "=" "1"
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PEI_XHCI_CONTROLLER_PCI_REGISTER_VALUES"
+ Value = "{0,0x1c,0,0x19,8,1,0},{0,0x1c,0,0x1a,8,1,0},{0,0x1c,0,0x20,16,0xfe40,0},{0,0x1c,0,0x22,16,0xfe40,0},{0,0x1c,0,4,8,6,0},"
+ Help = "Enable PCIe slot by programming bridge with the secondary/subordinate bus number and memory window.\Information format (AccessWidth is decimal), with a comma at the end:\ {Bus, Device, Function, Register, AccessWidth, BitsToSet, BitsToClear},"
+ Token = "PEI_XHCI_SUPPORT" "=" "1"
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FORCE_RECOVERY"
+ Value = "0"
+ Help = "Force recovery execution by forcing BootMode = BOOT_IN_RECOVERY_MODE in SbPei.c"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+ELINK
+ Name = "USBR_OHCI_CONTROLLER_PCI_ADDRESS"
+ Help = "Specifies the location of supported OHCI controllers on the PCI bus. Use the following format with hexadecimal values, with a comma at the end: \ {bus, device, function},"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "{0x0, 0x0, 0x0},"
+ Parent = "USBR_OHCI_CONTROLLER_PCI_ADDRESS"
+ InvokeOrder = AfterParent
+ Help = "Default value if OHCI controllers are not supported"
+ Token = "PEI_OHCI_SUPPORT" "=" "0"
+End
+
+
+ELINK
+ Name = "USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE"
+ Help = "Specifies the PCI register values to be programmed for each of the supported OHCI controllers specified by OHCI_CONTROLLER_PCI_ADDRESS. Use the following format with hexadecimal values (AccessWidth is decimal), with a comma at the end:\ {AccessWidth, Register, BitsToSet, BitsToClear},"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "{ 0, 0, 0, 0 },"
+ Parent = "USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE"
+ InvokeOrder = AfterParent
+ Help = "Default value if OHCI controllers are not supported"
+ Token = "PEI_OHCI_SUPPORT" "=" "0"
+End
+
+ELINK
+ Name = "{ 32, 0x4, 0x6, 0x0 },"
+ Parent = "USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE"
+ Help = "Enable bus mastering and MMIO space (this register is typically programmed for all chipsets. Priority is set to a large number to ensure it gets updated last.)"
+ InvokeOrder = AfterParent
+ Priority = 255
+ Token = "PEI_OHCI_SUPPORT" "=" "1"
+End
+
+PATH
+ Name = "UsbRecovery_DIR"
+End
+
+PATH
+ Name = "UHCIPEIUSB"
+ Path = "$(UsbRecovery_DIR)\UhciPeiUsb"
+End
+
+PATH
+ Name = "UhcipeiUsb_DIR"
+ Path = "$(UsbRecovery_DIR)\UhciPeiUsb"
+End
+
+PATH
+ Name = "OHCIPEI"
+ Path = "$(UsbRecovery_DIR)\OhciPei"
+End
+
+PATH
+ Name = "OhciPei_DIR"
+ Path = "$(UsbRecovery_DIR)\OhciPei"
+End
+
+PATH
+ Name = "EHCIPEI_DIR"
+ Path = "$(UsbRecovery_DIR)\EhciPei"
+End
+
+PATH
+ Name = "XHCIPEI_DIR"
+ Path = "$(UsbRecovery_DIR)\XhciPei"
+End
+
+PATH
+ Name = "UhcPeimSrc_DIR"
+ Path = "$(UsbRecovery_DIR)\UhcPeimSrc"
+End
+
+PATH
+ Name = "UsbPeimSrc_DIR"
+ Path = "$(UsbRecovery_DIR)\UsbPeimSrc"
+End
+
+PATH
+ Name = "UsbBotPeimSrc_DIR"
+ Path = "$(UsbRecovery_DIR)\UsbBotPeimSrc"
+ Help = "UsbBotPeimSrc file source directory"
+End
+
+MODULE
+ Help = "Includes UsbRecov.mak to Project"
+ File = "UsbRecov.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\UsbBotPeim.ffs"
+ Parent = "FV_BB"
+ InvokeOrder = AfterParent
+ Token = "UsbRecov_SUPPORT" "=" "1"
+End
+
+
+
+
diff --git a/Core/EM/UsbRecovery/UsbRecovery.cif b/Core/EM/UsbRecovery/UsbRecovery.cif
new file mode 100644
index 0000000..91d1795
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbRecovery.cif
@@ -0,0 +1,24 @@
+<component>
+ name = "UsbRecovery"
+ category = eModule
+ LocalRoot = "Core\em\UsbRecovery\"
+ RefName = "UsbRecovery"
+[files]
+"UsbRecov.sdl"
+"UsbRecov.mak"
+"UsbPeim.h"
+"HubPeim.h"
+"PeiUsbLib.c"
+"PeiUsbLib.h"
+"usb.h"
+"USBRecoverySrc.chm"
+"AmiMapping.h"
+[parts]
+"UhciPeiUsb"
+"OhciPei"
+"EhciPei"
+"XhciPei"
+"UhcPeimSrc"
+"UsbPeimSrc"
+"UsbBotPeimSrc"
+<endComponent>
diff --git a/Core/EM/UsbRecovery/XhciPEI/XhciPei.c b/Core/EM/UsbRecovery/XhciPEI/XhciPei.c
new file mode 100644
index 0000000..ae926ca
--- /dev/null
+++ b/Core/EM/UsbRecovery/XhciPEI/XhciPei.c
@@ -0,0 +1,2314 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/XhciPei.c 10 11/24/12 5:45a Ryanchou $
+//
+// $Revision: 10 $
+//
+// $Date: 11/24/12 5:45a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/XhciPei.c $
+//
+// 10 11/24/12 5:45a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 9 4/24/12 10:16p Wilsonlee
+// [TAG] EIP75547
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Xhci recovery funtion failed when SS devices on USB 3.0
+// port.
+// [RootCause] The SS device connected to USB2 port.
+// [Solution] Reset the USB2 port when initial xhci controller, then the
+// SS device reconnect to USB3 port.
+// [Files] XhciPei.c, XhciPei.h
+//
+// 8 4/12/11 12:00a Rameshr
+// [TAG]- EIP 57444
+// [Category]-IMPROVEMENT
+// [Description]- PI1.1 Support.
+// [Files]- OhciPeiboard.c,Xhcipei.c, Peiusblib.c
+//
+// 7 1/18/11 1:08a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 6 1/17/11 7:08a Ryanchou
+// [TAG] EIP48013
+// [Category] Improvement
+// [Description] Use 32 or 64 byte Context data structures dynamically.
+// [Files] XhciPei.c, XhciPei.h
+//
+// 5 10/27/10 11:27a Olegi
+// [TAG] EIP46147
+// [Category] Bug Fix
+//
+// 4 10/20/10 10:44a Olegi
+// [TAG] EIP46492
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] TdSize variable should be declared as a 32bit integer
+// instead of a 8bit one.
+//
+// 3 10/14/10 3:57p Olegi
+// Added code that check for PCI device presence.
+//
+// 2 10/12/10 5:57p Olegi
+// Added (UINTN) typecast when converting pointers to UINT64. Without it
+// pointers that have BIT31 will have bits 32..63 set.
+//
+// 1 10/11/10 4:53p Olegi
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: XhciPei.c
+//
+// Description:
+// This file is the main source file for the xHCI PEI USB recovery module.
+// Its entry point at XhciPeiUsbEntryPoint will be executed from the
+// UsbRecoveryInitialize INIT_LIST.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <AmiPeiLib.h>
+#include "XhciPei.h"
+#include <PPI\stall.h>
+#include "token.h"
+#include "pci.h"
+#include "usbpeim.h"
+
+PCI_BUS_DEV_FUNCTION gXhciControllerPciTable[] = {PEI_XHCI_CONTROLLER_PCI_ADDRESS {0,0,0}};
+UINT16 gXhciControllerCount = \
+ sizeof(gXhciControllerPciTable) / sizeof(PCI_BUS_DEV_FUNCTION) - 1;
+
+PCI_DEV_REGISTER_VALUE gPeiXhciInitPciTable[] = {PEI_XHCI_CONTROLLER_PCI_REGISTER_VALUES {0,0,0,0,0,0,0}};
+UINT16 gPeiXhciInitPciTableCount = \
+ sizeof(gPeiXhciInitPciTable) / sizeof(PCI_DEV_REGISTER_VALUE) - 1;
+
+UINT8 gSlotBeingConfigured;
+
+#ifndef PI_SPECIFICATION_VERSION //old Core
+extern EFI_STATUS PciCfgModify(
+IN CONST EFI_PEI_SERVICES **PeiServices,
+IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
+IN UINT64 Address,
+IN UINTN SetBits,
+IN UINTN ClearBits
+);
+#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: XhciPeiUsbEntryPoint
+//
+// Description:
+// This is the entry point into the XHCI initialization.
+//
+// Input:
+// IN EFI_FFS_FILE_HEADER *FfsHeader
+// -- EFI_FFS_FILE_HEADER pointer
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS XhciPeiUsbEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+
+ EFI_STATUS Status;
+ EFI_PEI_STALL_PPI *StallPpi;
+ UINT32 XhciBaseAddress = PEI_XHCI_MMIOBASE;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ USB3_CONTROLLER *Usb3Hc;
+ UINTN MemPages;
+ UINT8 ControllerIndex;
+ UINT8 PciDevIndex;
+ UINT8 CmdRegisterValue = 6;
+
+ //-------------------------------------------
+ // Initialize the EFI_PEI_STALL_PPI interface
+ //-------------------------------------------
+ Status = (**PeiServices).LocatePpi( PeiServices, &gPeiStallPpiGuid,
+ 0, NULL, &StallPpi );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ // Program PCI registers of the host controller and other relevant PCI
+ // devices (e.g. bridges that enable this host).
+
+ for (PciDevIndex = 0; PciDevIndex < gPeiXhciInitPciTableCount; PciDevIndex++) {
+
+ EFI_PEI_PCI_CFG_PPI_WIDTH Width;
+
+ switch (gPeiXhciInitPciTable[PciDevIndex].Size) {
+ case 8: Width = EfiPeiPciCfgWidthUint8; break;
+ case 16: Width = EfiPeiPciCfgWidthUint16; break;
+ case 32: Width = EfiPeiPciCfgWidthUint32; break;
+ case 64: Width = EfiPeiPciCfgWidthUint64; break;
+ default: continue;
+ }
+
+ Status = PciCfgModify(
+ PeiServices,
+ Width,
+ PEI_PCI_CFG_ADDRESS(
+ gPeiXhciInitPciTable[PciDevIndex].Bus,
+ gPeiXhciInitPciTable[PciDevIndex].Device,
+ gPeiXhciInitPciTable[PciDevIndex].Function,
+ gPeiXhciInitPciTable[PciDevIndex].Register
+ ),
+ gPeiXhciInitPciTable[PciDevIndex].SetBits,
+ gPeiXhciInitPciTable[PciDevIndex].ClearBits);
+ }
+
+ for (ControllerIndex = 0; ControllerIndex < gXhciControllerCount;
+ ControllerIndex++, XhciBaseAddress+=0x10000)
+ {
+ UINT16 Vid;
+ UINT16 Did;
+
+ // Get VID/DID, see if controller is visible on PCI
+ (*PeiServices)->PciCfg->Read(PeiServices,(*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint16, XHCI_PCI_ADDRESS( ControllerIndex, PCI_VID ),&Vid);
+ if (Vid == 0xffff) continue; // Controller not present
+
+ (*PeiServices)->PciCfg->Read(PeiServices,(*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint16, XHCI_PCI_ADDRESS( ControllerIndex, PCI_DID ), &Did);
+
+ //----------------------------------------------------------
+ // Allocate USB3_CONTROLLER object that holds all necessary
+ // information for the Host Controller operational registers
+ // for each controller. Initialze the controller and setup
+ // data structures, get it ready for operation.
+ //----------------------------------------------------------
+ MemPages = sizeof(USB3_CONTROLLER) / 0x1000 + 1;
+ Status = (**PeiServices).AllocatePages(PeiServices,
+ EfiConventionalMemory,
+ MemPages,
+ &TempPtr);
+ if (EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES;
+
+ (**PeiServices).SetMem((VOID*)TempPtr, MemPages*4096, 0); // Clear allocated memory
+
+ Usb3Hc = (USB3_CONTROLLER*)(UINTN)TempPtr;
+
+ //----------------------------------------------------------
+ // USB3 controller data area is allocated, start stuff it in
+ // with the useful filling in with the useful data.
+ //----------------------------------------------------------
+
+ // Program BAR
+ (*PeiServices)->PciCfg->Write(PeiServices,(*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint32,
+ XHCI_PCI_ADDRESS( ControllerIndex, PCI_BAR0 ),
+ &XhciBaseAddress
+ );
+ Usb3Hc->CapRegs = (XHCI_HC_CAP_REGS*)(UINTN)XhciBaseAddress;
+
+ // Enable MMIO access and BM
+ (*PeiServices)->PciCfg->Write(PeiServices,(*PeiServices)->PciCfg,
+ EfiPeiPciCfgWidthUint8,
+ XHCI_PCI_ADDRESS( ControllerIndex, PCI_CMD ),
+ &CmdRegisterValue
+ );
+
+ (UINT8)(UINTN)Usb3Hc->CapRegs &= ~(0x7F); // Clear attributes
+
+ Usb3Hc->Did = Did;
+ Usb3Hc->Vid = Vid;
+ Usb3Hc->Access64 = Usb3Hc->CapRegs->HcParams.Ac64;
+ Usb3Hc->HciVersion = Usb3Hc->CapRegs->HciVersion;
+ Usb3Hc->MaxPorts = Usb3Hc->CapRegs->HcParams1.MaxPorts;
+ Usb3Hc->OpRegs = (XHCI_HC_OP_REGS*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->CapRegs->CapLength);
+ Usb3Hc->PageSize4K = Usb3Hc->OpRegs->PageSize;
+ Usb3Hc->ContextSize = 0x20 << Usb3Hc->CapRegs->HcParams.Csz;
+ Usb3Hc->MaxIntrs = Usb3Hc->CapRegs->HcParams1.MaxIntrs; // Get maximum number of interrupters
+ Usb3Hc->DbOffset = Usb3Hc->CapRegs->DbOff; // Doorbell offset
+ Usb3Hc->MaxSlots = PEI_XHCI_MAX_SLOTS;
+
+ Usb3Hc->InputContext = (VOID*)&Usb3Hc->InpCtx;
+ Usb3Hc->XfrRings = Usb3Hc->XfrRing;
+ Usb3Hc->XfrTrbs = (UINTN)Usb3Hc->XfrTrb;
+ Usb3Hc->DeviceContext = (VOID*)Usb3Hc->DevCtx;
+
+ XhciExtCapParser(PeiServices, Usb3Hc); //(EIP75547+)
+
+ PEI_TRACE ((-1, PeiServices, "USB recovery xHCI[%d] controller initialization details:\n", ControllerIndex));
+ PEI_TRACE ((-1, PeiServices, " PCI location: B%x/D%x/F%x, VID:DID = %x:%x, BAR0 = %x\n",
+ gXhciControllerPciTable[ControllerIndex].Bus,
+ gXhciControllerPciTable[ControllerIndex].Device,
+ gXhciControllerPciTable[ControllerIndex].Function,
+ Usb3Hc->Vid,
+ Usb3Hc->Did,
+ Usb3Hc->CapRegs
+ ));
+ PEI_TRACE((-1, PeiServices, " MaxSlots = %x, InputCtx %x, Device Ctx %x\n",
+ Usb3Hc->MaxSlots, (UINT8*)Usb3Hc->InputContext, (UINT8*)Usb3Hc->DeviceContext));
+
+ Usb3Hc->PeiServices = PeiServices;
+ Usb3Hc->CpuIoPpi = (*PeiServices)->CpuIo;
+ Usb3Hc->StallPpi = StallPpi;
+ Usb3Hc->PciCfgPpi = (*PeiServices)->PciCfg;
+
+ // Initialize the xHCI Controller for operation
+ Status = XhciInitHC(PeiServices, Usb3Hc, ControllerIndex);
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+ if (EFI_ERROR(Status)) return Status;
+
+ // Setup PPI entry point
+ Usb3Hc->UsbHostControllerPpi.ControlTransfer = XhciHcControlTransfer;
+ Usb3Hc->UsbHostControllerPpi.BulkTransfer = XhciHcBulkTransfer;
+ Usb3Hc->UsbHostControllerPpi.GetRootHubPortNumber = XhciHcGetRootHubPortNumber;
+ Usb3Hc->UsbHostControllerPpi.GetRootHubPortStatus = XhciHcGetRootHubPortStatus;
+ Usb3Hc->UsbHostControllerPpi.SetRootHubPortFeature = XhciHcSetRootHubPortFeature;
+ Usb3Hc->UsbHostControllerPpi.ClearRootHubPortFeature = XhciHcClearRootHubPortFeature;
+ Usb3Hc->UsbHostControllerPpi.PreConfigureDevice = XhciHcPreConfigureDevice;
+ Usb3Hc->UsbHostControllerPpi.EnableEndpoints = XhciEnableEndpoints;
+
+ Usb3Hc->PpiDescriptor.Flags =(EFI_PEI_PPI_DESCRIPTOR_PPI |EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ Usb3Hc->PpiDescriptor.Guid = &gPeiUsbHostControllerPpiGuid;
+ Usb3Hc->PpiDescriptor.Ppi = &Usb3Hc->UsbHostControllerPpi;
+
+ Status = (**PeiServices).InstallPpi(PeiServices, &Usb3Hc->PpiDescriptor);
+ if (EFI_ERROR(Status)) return EFI_NOT_FOUND;
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: XhciInitHC
+//
+// Description:
+// This function initializes xHCI controller registers and starts it.
+//
+// Input:
+// EFI_PEI_SERVICES **PeiServices
+// -- PEI_SERVICES pointer
+// USB3_CONTROLLER *Usb3Hc
+// -- XHCI controller data structure pointer
+// UINT8 ControllerIndex
+// -- 0-based index of the controller to be initialized
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful initialization completion
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciInitHC(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc,
+ UINT8 ControllerIndex
+)
+{
+ XHCI_INTERRUPTER_REGS *Interrupter;
+ XHCI_ER_SEGMENT_ENTRY *Erst0Entry;
+ BOOLEAN PpSet = FALSE;
+ UINT8 PortNumber;
+ volatile XHCI_PORTSC *PortSC;
+ UINT32 CurrentPortOffset = 0;
+ UINT32 i;
+
+ // Wait controller ready
+ for (i = 0; i < 100; i++) {
+ if (Usb3Hc->OpRegs->UsbSts.Field.Cnr == 0) break;
+ XHCI_FIXED_DELAY_MS(Usb3Hc, 1);
+ }
+ PEI_ASSERT(PeiServices, Usb3Hc->OpRegs->UsbSts.Field.Cnr == 0);
+ if (Usb3Hc->OpRegs->UsbSts.Field.Cnr) return EFI_DEVICE_ERROR;
+
+ // Check if the xHC is halted
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted == 0)
+ {
+ Usb3Hc->OpRegs->UsbCmd.RunStop = 0;
+ // The xHC should halt within 16 ms. Section 5.4.1.1
+ for (i = 0; i < 16; i++) {
+ XHCI_FIXED_DELAY_MS(Usb3Hc, 1);
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted) break;
+ }
+ PEI_ASSERT(PeiServices, Usb3Hc->OpRegs->UsbSts.Field.HcHalted);
+ if (Usb3Hc->OpRegs->UsbSts.Field.HcHalted == 0) return EFI_DEVICE_ERROR;
+ }
+
+ // Reset controller
+ Usb3Hc->OpRegs->UsbCmd.HcRst = 1;
+ for (i = 0; i < 400; i++) {
+ XHCI_FIXED_DELAY_MS(Usb3Hc, 1);
+ if (Usb3Hc->OpRegs->UsbCmd.HcRst == 0) break;
+ }
+
+ PEI_ASSERT(PeiServices, Usb3Hc->OpRegs->UsbCmd.HcRst == 0);
+ if (Usb3Hc->OpRegs->UsbCmd.HcRst) return EFI_DEVICE_ERROR; // Controller can not be reset
+
+ // Wait controller ready
+ for (i = 0; i < 100; i++) {
+ if (Usb3Hc->OpRegs->UsbSts.Field.Cnr == 0) break;
+ XHCI_FIXED_DELAY_MS(Usb3Hc, 1);
+ }
+ PEI_ASSERT(PeiServices, Usb3Hc->OpRegs->UsbSts.Field.Cnr == 0);
+ if (Usb3Hc->OpRegs->UsbSts.Field.Cnr) return EFI_DEVICE_ERROR;
+
+ Usb3Hc->RtRegs = (XHCI_HC_RT_REGS*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->CapRegs->RtsOff);
+ PEI_TRACE ((-1, PeiServices, "PEI_XHCI: RT registers are at %x\n", Usb3Hc->RtRegs));
+
+ Usb3Hc->OpRegs->Config = Usb3Hc->MaxSlots; // Max device slots enabled
+ Usb3Hc->DcbaaPtr = (XHCI_DCBAA*)Usb3Hc->Dcbaa;
+
+ XhciMmio64Write(Usb3Hc, (UINTN)&Usb3Hc->OpRegs->DcbAap, (UINT64)(UINTN)Usb3Hc->DcbaaPtr);
+
+ // Define the Command Ring Dequeue Pointer by programming the Command Ring
+ // Control Register (5.4.5) with a 64-bit address pointing to the starting
+ // address of the first TRB of the Command Ring.
+
+ // Initialize Command Ring Segment: Size TRBS_PER_SEGMENT*16, 64 Bytes aligned
+ XhciInitRing(&Usb3Hc->CmdRing, (UINTN)Usb3Hc->CommandRing, TRBS_PER_SEGMENT, TRUE);
+ PEI_TRACE ((-1, PeiServices, "CMD Ring is at %x\n", (UINTN)&Usb3Hc->CmdRing));
+
+ // Write CRCR HC register with the allocated address. Set Ring Cycle State to 1.
+ XhciMmio64Write(Usb3Hc, (UINTN)&Usb3Hc->OpRegs->Crcr,
+ (UINT64)(UINTN)Usb3Hc->CmdRing.Base + CRCR_RING_CYCLE_STATE);
+
+ // Initialize and assign Event Ring
+ XhciInitRing(&Usb3Hc->EvtRing, (UINTN)Usb3Hc->EventRing, TRBS_PER_SEGMENT, FALSE);
+ PEI_TRACE ((-1, PeiServices, "EVT Ring is at %x\n", (UINTN)&Usb3Hc->EvtRing));
+
+ // NOTE: This driver supports one Interrupter, hence it uses
+ // one Event Ring segment with TRBS_PER_SEGMENT TRBs in it.
+
+ // Initialize ERST[0]
+ Erst0Entry = &Usb3Hc->Erst;
+ Erst0Entry->RsBase = (UINT64)(UINTN)Usb3Hc->EvtRing.Base;
+ Erst0Entry->RsSize = TRBS_PER_SEGMENT;
+
+ Interrupter = Usb3Hc->RtRegs->IntRegs;
+
+ // Initialize Interrupter fields
+ Interrupter->Erstz = 1; // # of segments
+ // ER dequeue pointer
+ XhciMmio64Write(Usb3Hc, (UINTN)&Interrupter->Erdp, (UINT64)(UINTN)Usb3Hc->EvtRing.QueuePtr);
+ // Seg Table location
+ XhciMmio64Write(Usb3Hc, (UINTN)&Interrupter->Erstba, (UINT64)(UINTN)Erst0Entry);
+ Interrupter->IMod = XHCI_IMODI; // Max interrupt rate
+ Interrupter->IMan |= 2; // Enable interrupt
+
+ PEI_TRACE((-1, PeiServices, "Transfer Rings structures start at %x\n", Usb3Hc->XfrRings));
+
+ // Set PortPower unless PowerPortControl indicates otherwise
+ if (Usb3Hc->CapRegs->HcParams.Ppc != 0) {
+ for (PortNumber = 0; PortNumber<Usb3Hc->MaxPorts;
+ PortNumber++, CurrentPortOffset+=0x10) {
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + CurrentPortOffset);
+ if (PortSC->Field.Pp == 0) {
+ PortSC->Field.Pp = 1; // Set port power
+ PpSet = TRUE;
+ }
+ }
+ if (PpSet) XHCI_FIXED_DELAY_MS(Usb3Hc, 20); // Wait for 20 ms, Section 5.4.8
+ }
+
+ Usb3Hc->OpRegs->UsbCmd.Inte = 1;
+ Usb3Hc->OpRegs->UsbCmd.RunStop = 1;
+
+ XHCI_FIXED_DELAY_MS(Usb3Hc, 100);
+
+ XhciResetUsb2Port(PeiServices, Usb3Hc); //(EIP75547+)
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: XhciHcPreConfigureDevice
+//
+// Description:
+// This function does preliminary device initialization: enables slot and
+// sets the address.
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful pre-configuration completion
+// = EFI_DEVICE_ERROR on error
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciHcPreConfigureDevice(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 Port,
+ IN UINT8 DeviceSpeed,
+ IN UINT16 TransactionTranslator
+)
+{
+ USB3_CONTROLLER *Usb3Hc = PEI_RECOVERY_USB_XHCI_DEV_FROM_THIS(This);
+ UINT8 *Device;
+ UINT8 *ParentHubDevice;
+ TRB_RING *XfrRing;
+ UINT8 Speed;
+ static UINT16 aMaxPacketSize[5] = {0, 8, 8, 64, 512};
+ EFI_STATUS Status;
+ UINT8 SlotId;
+ XHCI_INPUT_CONTROL_CONTEXT *CtlCtx;
+ XHCI_SLOT_CONTEXT *SlotCtx;
+ XHCI_SLOT_CONTEXT *ParentHubSlotCtx;
+ XHCI_EP_CONTEXT *Ep0Ctx;
+ UINT8 ParentHubSlotId;
+ UINT8 i;
+
+// XHCI_FIXED_DELAY_MS(Usb3Hc, 1000);
+
+ // Obtain device slot using Enable Slot command, 4.3.2, 4.6.3
+ Status = XhciExecuteCommand(PeiServices, Usb3Hc, XhciTEnableSlotCmd, &SlotId);
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+ PEI_ASSERT(PeiServices, SlotId != 0);
+ if (Status != EFI_SUCCESS) return Status;
+
+ Device = (UINT8*)XhciGetDeviceContext(Usb3Hc, SlotId);
+
+ // Update DCBAA with the new device pointer (index = SlotId)
+ Usb3Hc->DcbaaPtr->DevCntxtAddr[SlotId-1] = (UINT64)(UINTN)Device;
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: Slot[%d] enabled, device context at %x\n", SlotId, Device));
+
+ // Initialize data structures associated with the slot 4.3.3
+
+ // Zero the InputContext and DeviceContext
+ (**PeiServices).SetMem((UINT8*)Usb3Hc->InputContext, XHCI_INPUT_CONTEXT_ENTRIES * Usb3Hc->ContextSize, 0);
+ (**PeiServices).SetMem(Device, XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize, 0);
+
+ // Initialize the Input Control Context of the Input Context
+ // by setting the A0 and A1 flags to 1
+
+ CtlCtx = (XHCI_INPUT_CONTROL_CONTEXT*)XhciGetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 0);
+ CtlCtx->AddContextFlags = BIT0 + BIT1;
+
+ // Initialize the Input Slot Context data structure
+ SlotCtx = (XHCI_SLOT_CONTEXT*)XhciGetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 1);
+ SlotCtx->RouteString = 0;
+ SlotCtx->ContextEntries = 1;
+ if (TransactionTranslator == 0) {
+ SlotCtx->RootHubPort = Port;
+ } else {
+ Status = GetSlotId(Usb3Hc->DeviceMap, &ParentHubSlotId, (UINT8)(TransactionTranslator & 0xF));
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+ ParentHubDevice = (UINT8*)XhciGetDeviceContext(Usb3Hc, ParentHubSlotId);
+ ParentHubSlotCtx = (XHCI_SLOT_CONTEXT*)XhciGetContextEntry(Usb3Hc, ParentHubDevice, 0);
+ SlotCtx->RootHubPort = ParentHubSlotCtx->RootHubPort;
+ }
+
+ switch (DeviceSpeed) {
+ case USB_HIGH_SPEED_DEVICE: Speed = XHCI_DEVSPEED_HIGH; break;
+ case USB_SLOW_SPEED_DEVICE: Speed = XHCI_DEVSPEED_LOW; break;
+ case USB_FULL_SPEED_DEVICE: Speed = XHCI_DEVSPEED_FULL; break;
+ case USB_SUPER_SPEED_DEVICE: Speed = XHCI_DEVSPEED_SUPER;
+ }
+
+ SlotCtx->Speed = Speed;
+
+ XfrRing = XhciInitXfrRing(Usb3Hc, SlotId, 0);
+
+ // Initialize the Input default control Endpoint 0 Context
+ Ep0Ctx = (XHCI_EP_CONTEXT*)XhciGetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 2);
+ Ep0Ctx->EpType = XHCI_EPTYPE_CTL;
+ Ep0Ctx->MaxPacketSize = aMaxPacketSize[Speed];
+ Ep0Ctx->TrDequeuePtr = (UINT64)(UINTN)XfrRing->Base + 1;
+ Ep0Ctx->AvgTrbLength = 8;
+ Ep0Ctx->ErrorCount = 3;
+
+ // Initialize Route String and TT fields
+ if (TransactionTranslator != 0) {
+ if (ParentHubSlotCtx->Speed == XHCI_DEVSPEED_SUPER) {
+ for (i = 0; i < 5; i++) {
+ if (((ParentHubSlotCtx->RouteString >> (i << 2)) & 0xF) == 0) {
+ break;
+ }
+ }
+ SlotCtx->RouteString = ParentHubSlotCtx->RouteString | (Port << (i << 2));
+ } else {
+ // Update TT fields in the Slot context for LS/FS device connected to HS hub
+ if (SlotCtx->Speed == XHCI_DEVSPEED_FULL || SlotCtx->Speed == XHCI_DEVSPEED_LOW) {
+ if(ParentHubSlotCtx->Speed == XHCI_DEVSPEED_HIGH) {
+ SlotCtx->TtHubSlotId = ParentHubSlotId;
+ SlotCtx->TtPortNumber = (UINT8)(TransactionTranslator >> 7);
+ SlotCtx->MultiTT = ParentHubSlotCtx->MultiTT;
+ } else {
+ SlotCtx->TtHubSlotId = ParentHubSlotCtx->TtHubSlotId;
+ SlotCtx->TtPortNumber = ParentHubSlotCtx->TtPortNumber;
+ SlotCtx->MultiTT = ParentHubSlotCtx->MultiTT;
+ }
+ }
+ }
+ }
+
+ // Assign a new address 4.3.4, 4.6.5
+ Status = XhciExecuteCommand(PeiServices, Usb3Hc, XhciTAddressDeviceCmd, &SlotId);
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+ if (Status != EFI_SUCCESS) {
+ XhciExecuteCommand(PeiServices, Usb3Hc, XhciTDisableSlotCmd, &SlotId);
+ Usb3Hc->DcbaaPtr->DevCntxtAddr[SlotId-1] = 0;
+ return Status;
+ }
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: new device address %d\n", ((XHCI_SLOT_CONTEXT*)Device)->DevAddr));
+
+ gSlotBeingConfigured = SlotId; // Valid from now til SetAddress
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: UpdateDeviceMap
+//
+// Description:
+// This function updates SlotId<->Address mapping table.
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS if update is successful
+// = EFI_NOT_FOUND if there is no room for a new entry in the map
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UpdateDeviceMap(
+ PEI_XHCI_SLOTADDR_MAP *DeviceMap,
+ UINT8 SlotId,
+ UINT8 DevAddr
+)
+{
+ UINT8 i;
+ PEI_XHCI_SLOTADDR_MAP *Map = DeviceMap;
+
+ for (i = 0; i < PEI_XHCI_MAX_SLOTS; i++, Map++) {
+ if (Map->SlotId == 0) {
+ Map->SlotId = SlotId;
+ Map->DevAddr = DevAddr;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GetSlotId
+//
+// Description:
+// This function retrieves SlotId from the Slot<->Address mapping table.
+//
+// Output:
+// SlotId variable is updated
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS if update is successful
+// = EFI_NOT_FOUND if the requested Slot is not found in the mapping table
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+GetSlotId(
+ PEI_XHCI_SLOTADDR_MAP *DeviceMap,
+ UINT8 *SlotId,
+ UINT8 DevAddr
+)
+{
+ UINT8 i;
+ PEI_XHCI_SLOTADDR_MAP *Map = DeviceMap;
+
+ for (i = 0; i < PEI_XHCI_MAX_SLOTS; i++, Map++) {
+ if (Map->DevAddr == DevAddr) {
+ *SlotId = Map->SlotId;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciClearStalledEp
+//
+// Description:
+// This function is called to restart endpoint. After Endpoint STALLs, it
+// transitions from Halted to Stopped state. It is restored back to Running
+// state by moving the endpoint ring dequeue pointer past the failed control
+// transfer with a Set TR Dequeue Pointer. Then it is restarted by ringing the
+// doorbell. Alternatively endpint is restarted using Configure Endpoint command.
+//
+// Input:
+// Stalled EP data - SlotId and DCI
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciClearStalledEp(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc,
+ UINT8 SlotId,
+ UINT8 Dci
+)
+{
+ UINT16 EpInfo;
+ TRB_RING *XfrRing;
+ EFI_STATUS Status;
+ XHCI_SET_TRPTR_CMD_TRB Trb;
+
+ // Reset stalled endpoint
+ EpInfo = (Dci << 8) + SlotId;
+ Status = XhciExecuteCommand(PeiServices, Usb3Hc, XhciTResetEndpointCmd, &EpInfo);
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+
+ XfrRing = XhciGetXfrRing(Usb3Hc, SlotId, Dci-1);
+
+ Trb.TrPointer = (UINT64)((UINTN)XfrRing->QueuePtr + XfrRing->CycleBit); // Set up DCS
+ Trb.EndpointId = Dci;
+ Trb.SlotId = SlotId;
+
+ Status = XhciExecuteCommand(PeiServices, Usb3Hc, XhciTSetTRDequeuePointerCmd, &Trb);
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciUpdateEp0MaxPacket
+//
+// Description:
+// This function verifies the MaxPacket size of the control pipe. If it does
+// not match the one received as a part of GET_DESCRIPTOR, then this function
+// updates the MaxPacket data in DeviceContext and HC is notified via
+// EvaluateContext command.
+//
+// Input:
+// Usb3Hc Pointer to the HC structure
+// Device Evaluated device context pointer
+// SlotId Device context index in DCBAA
+// Endp0MaxPacket Max packet size obtained from the device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+XhciUpdateEp0MaxPacket(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc,
+ UINT8 SlotId,
+ UINT8 Endp0MaxPacket
+)
+{
+ UINT8 Status;
+ UINT8 *DevCtx;
+ XHCI_INPUT_CONTROL_CONTEXT *CtlCtx;
+ XHCI_SLOT_CONTEXT *SlotCtx;
+ XHCI_EP_CONTEXT *EpCtx;
+
+ DevCtx = (UINT8*)XhciGetDeviceContext(Usb3Hc, SlotId);
+
+ SlotCtx = (XHCI_SLOT_CONTEXT*)XhciGetContextEntry(Usb3Hc, DevCtx, 0);
+ if (SlotCtx->Speed != XHCI_DEVSPEED_FULL) return;
+
+ EpCtx = (XHCI_EP_CONTEXT*)XhciGetContextEntry(Usb3Hc, DevCtx, 1);
+ if (EpCtx->MaxPacketSize == Endp0MaxPacket) return;
+
+ // Prepare input context for EvaluateContext comand
+ (**PeiServices).SetMem((UINT8*)Usb3Hc->InputContext, XHCI_INPUT_CONTEXT_ENTRIES * Usb3Hc->ContextSize, 0);
+
+ CtlCtx = (XHCI_INPUT_CONTROL_CONTEXT*)XhciGetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 0);
+ CtlCtx->AddContextFlags = BIT1;
+
+ EpCtx = (XHCI_EP_CONTEXT*)XhciGetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 2);
+ EpCtx->MaxPacketSize = Endp0MaxPacket;
+
+ Status = XhciExecuteCommand(PeiServices, Usb3Hc, XhciTEvaluateContextCmd, &SlotId);
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: XhciHcControlTransfer
+//
+// Description:
+// This function intiates a USB control transfer and waits on it to
+// complete.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 bDeviceAddress
+// -- USB address of the device for which the control
+// transfer is to be issued
+// IN UINT8 DeviceType
+// -- Not used
+// IN UINT8 MaximumPacketLength
+// -- Maximum number of bytes that can be sent to or
+// received from the endpoint in a single data packet
+// IN EFI_USB_DEVICE_REQUEST *Request
+// -- EFI_USB_DEVICE_REQUEST pointer
+// IN EFI_USB_DATA_DIRECTION TransferDirection
+// -- Direction of transfer
+// OPTIONAL IN OUT VOID *DataBuffer
+// -- Pointer to source or destination buffer
+// OPTIONAL IN OUT UINTN *DataLength
+// -- Length of buffer
+// IN UINTN TimeOut
+// -- Not used
+// OUT UINT32 *TransferResult
+// -- Not used
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS XhciHcControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult )
+{
+ USB3_CONTROLLER *Usb3Hc = PEI_RECOVERY_USB_XHCI_DEV_FROM_THIS(This);
+ XHCI_TRB *Trb;
+ volatile UINT32 *Doorbell;
+ UINT8 SlotId;
+ UINT8 CompletionCode;
+ UINT8 Status;
+ TRB_RING *XfrRing;
+ UINT16 Rq = ((UINT16)Request->Request << 8) + Request->RequestType;
+
+ // Skip SET_ADDRESS request
+ if (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE &&
+ Request->Request == USB_DEV_SET_ADDRESS)
+ {
+ Status = UpdateDeviceMap(Usb3Hc->DeviceMap, gSlotBeingConfigured, (UINT8)Request->Value);
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+ return EFI_SUCCESS;
+ }
+
+ if (DeviceAddress == 0) {
+ SlotId = gSlotBeingConfigured;
+ } else {
+ Status = GetSlotId(Usb3Hc->DeviceMap, &SlotId, DeviceAddress);
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+ }
+
+ // Insert Setup, Data(if needed), and Status TRBs into the transfer ring
+ XfrRing = XhciGetXfrRing(Usb3Hc, SlotId, 0);
+
+ // Setup TRB
+ Trb = XhciAdvanceEnqueuePtr(XfrRing);
+ Trb->TrbType = XhciTSetupStage;
+ ((XHCI_SETUP_XFR_TRB*)Trb)->Idt = 1;
+ *(UINT16*)&((XHCI_SETUP_XFR_TRB*)Trb)->bmRequestType = Rq;
+ ((XHCI_SETUP_XFR_TRB*)Trb)->wValue = Request->Value;
+ ((XHCI_SETUP_XFR_TRB*)Trb)->wIndex = Request->Index;
+ ((XHCI_SETUP_XFR_TRB*)Trb)->wLength = (UINT16)(*DataLength);
+ ((XHCI_SETUP_XFR_TRB*)Trb)->XferLength = 8;
+
+ if (Usb3Hc->HciVersion == 0x100) {
+ if (*DataLength != 0) {
+ if ((Rq & BIT7) != 0) {
+ ((XHCI_SETUP_XFR_TRB*)Trb)->Trt = XHCI_XFER_TYPE_DATA_IN;
+ } else {
+ ((XHCI_SETUP_XFR_TRB*)Trb)->Trt = XHCI_XFER_TYPE_DATA_OUT;
+ }
+ } else {
+ ((XHCI_SETUP_XFR_TRB*)Trb)->Trt = XHCI_XFER_TYPE_NO_DATA;
+ }
+ }
+
+ // Data TRB
+ if (*DataLength != 0) {
+ Trb = XhciAdvanceEnqueuePtr(XfrRing);
+ Trb->TrbType = XhciTDataStage;
+ ((XHCI_DATA_XFR_TRB*)Trb)->Dir = ((Rq & BIT7) != 0)? 1 : 0;
+ ((XHCI_DATA_XFR_TRB*)Trb)->XferLength = *DataLength;
+ ((XHCI_DATA_XFR_TRB*)Trb)->DataBuffer = (UINT64)(UINTN)Data;
+ }
+
+ // Status TRB
+ Trb = XhciAdvanceEnqueuePtr(XfrRing);
+ Trb->TrbType = XhciTStatusStage;
+ ((XHCI_STATUS_XFR_TRB*)Trb)->Ioc = 1;
+ if ((Rq & BIT7) == 0) {
+ ((XHCI_STATUS_XFR_TRB*)Trb)->Dir = 1; // Status is IN
+ }
+
+ // Ring the doorbell and see Event Ring update
+ Doorbell = XhciGetTheDoorbell(Usb3Hc, SlotId);
+ *Doorbell = 1; // Control EP0 Enqueue Pointer Update
+
+ Status = XhciWaitForEvent(
+ PeiServices, Usb3Hc, Trb, XhciTTransferEvt,
+ &CompletionCode, XHCI_CTL_COMPLETE_TIMEOUT_MS, NULL);
+
+
+ if (CompletionCode == XHCI_TRB_STALL_ERROR) {
+ Status = XhciClearStalledEp(PeiServices,
+ Usb3Hc, SlotId, 1); // Dci = 1 for control endpoint
+ return 0;
+ }
+
+ if (Request->Request == USB_DEV_GET_DESCRIPTOR && *DataLength == 8) {
+ // Full speed device requires the update of MaxPacket size
+ XhciUpdateEp0MaxPacket(PeiServices, Usb3Hc, SlotId,
+ ((EFI_USB_DEVICE_DESCRIPTOR*)Data)->MaxPacketSize0);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: XhciHcBulkTransfer
+//
+// Description:
+// This function intiates a USB bulk transfer and waits on it to
+// complete.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// -- EFI_PEI_SERVICES pointer
+// IN PEI_USB_HOST_CONTROLLER_PPI *This
+// -- PEI_USB_HOST_CONTROLLER_PPI pointer
+// IN UINT8 DeviceAddress
+// -- USB address of the device for which the control
+// transfer is to be issued
+// IN UINT8 EndPointAddress
+// -- Particular endpoint for the device
+// IN UINT8 MaximumPacketLength
+// -- Maximum number of bytes that can be sent to or
+// received from the endpoint in a single data packet
+// OPTIONAL IN OUT VOID *DataBuffer
+// -- Pointer to source or destination buffer
+// OPTIONAL IN OUT UINTN *DataLength
+// -- Length of buffer
+// IN OUT UINT8 *DataToggle
+// -- Used to update the control/status DataToggle field
+// of the Transfer Descriptor
+// IN UINTN TimeOut
+// -- Not used
+// OUT UINT32 *TransferResult
+// -- Not used
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS on successful completion
+// or valid EFI error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS XhciHcBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT16 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult )
+{
+ USB3_CONTROLLER *Usb3Hc = PEI_RECOVERY_USB_XHCI_DEV_FROM_THIS(This);
+ XHCI_TRB *Trb;
+ UINTN FirstTrb;
+ volatile UINT32 *Doorbell;
+ UINT8 SlotId;
+ UINT8 CompletionCode;
+ EFI_STATUS Status;
+ TRB_RING *XfrRing;
+ UINT8 Endpoint;
+ UINT8 Dci;
+ UINT64 DataPointer;
+ UINT32 ResidualData; // Transferred amount return by Transfer Event
+ UINT32 TransferredSize; // Total transfer amount
+ UINT32 RingDataSize; // One TRB ring transfer amount
+ UINT32 RemainingXfrSize;
+ UINT32 RemainingDataSize;
+ UINT32 XfrSize;
+ UINT32 XfrTdSize;
+ UINT32 TdPktCnt;
+ UINT32 TdSize;
+
+ Endpoint = EndPointAddress;
+ Dci = (Endpoint & 0xf)* 2;
+ if (Endpoint & BIT7) Dci++;
+
+ GetSlotId(Usb3Hc->DeviceMap, &SlotId, DeviceAddress);
+
+ Doorbell = XhciGetTheDoorbell(Usb3Hc, SlotId);
+
+ XfrRing = XhciGetXfrRing(Usb3Hc, SlotId, Dci-1);
+
+ // Make a chain of TDs to transfer the requested amount of data. If necessary,
+ // make multiple transfers in a loop.
+
+ DataPointer = (UINTN)Data;
+ RemainingDataSize = *DataLength;
+
+ // Two loops are executing the transfer:
+ // The inner loop creates a transfer ring of chained TDs, XHCI_BOT_TD_MAXSIZE
+ // bytes each. This makes a ring capable of transferring
+ // XHCI_BOT_TD_MAXSIZE * (TRBS_PER_SEGMENT-1) bytes.
+ // The outter loop repeats the transfer if the requested transfer size exceeds
+ // XHCI_BOT_TD_MAXSIZE * (TRBS_PER_SEGMENT-1).
+
+ for (TransferredSize = 0; TransferredSize < *DataLength;) {
+ // Calculate the amount of data to transfer in the ring
+ RingDataSize = (RemainingDataSize > XHCI_BOT_MAX_XFR_SIZE)?
+ XHCI_BOT_MAX_XFR_SIZE : RemainingDataSize;
+
+ RemainingXfrSize = RingDataSize;
+ TdPktCnt = RingDataSize / MaximumPacketLength;
+
+ for (Trb = NULL, XfrSize = 0, FirstTrb = 0; XfrSize < RingDataSize;)
+ {
+ Trb = XhciAdvanceEnqueuePtr(XfrRing);
+ if (FirstTrb == 0) FirstTrb = (UINTN)Trb;
+
+ Trb->TrbType = XhciTNormal;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Isp = 1;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->DataBuffer = DataPointer;
+
+ // See if we need a TD chain. Note that we do not need to
+ // place the chained TRB into Event Ring, since we will not be
+ // looking for it anyway. Set IOC only for the last-in-chain TRB.
+ if (RemainingXfrSize > XHCI_BOT_TD_MAXSIZE) {
+ XfrTdSize = XHCI_BOT_TD_MAXSIZE;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Chain = 1;
+ } else {
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Ioc = 1;
+ XfrTdSize = RemainingXfrSize;
+ }
+ // Data buffers referenced by Transfer TRBs shall not span 64KB boundaries.
+ // If a physical data buffer spans a 64KB boundary, software shall chain
+ // multiple TRBs to describe the buffer.
+ if (XfrTdSize > (UINT32)(0x10000 - (DataPointer & (0x10000 - 1))))
+ {
+ XfrTdSize = (UINT32)(0x10000 - (DataPointer & (0x10000 - 1)));
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Chain = 1;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->Ioc = 0;
+ }
+
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->XferLength = XfrTdSize;
+ if(Usb3Hc->HciVersion == 0x100) {
+ TdSize = TdPktCnt - ((XfrSize + XfrTdSize)/MaximumPacketLength);
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->TdSize = (TdSize > 31)? 31 : TdSize;
+ } else {
+ TdSize = RemainingXfrSize - XfrTdSize;
+ ((XHCI_NORMAL_XFR_TRB*)Trb)->TdSize = (TdSize < 32768)? (TdSize >> 10) : 31;
+ }
+
+ XfrSize += XfrTdSize;
+ DataPointer += XfrTdSize;
+ RemainingXfrSize -= XfrTdSize;
+ }
+
+ // If transfer ring crossed Link TRB, set its Chain flag
+ if ((UINTN)Trb < FirstTrb) {
+ ((XHCI_NORMAL_XFR_TRB*)XfrRing->LastTrb)->Chain = 1;
+ }
+
+ // Ring the door bell and see Event Ring update
+ *Doorbell = Dci;
+
+ Status = XhciWaitForEvent(
+ PeiServices, Usb3Hc, Trb, XhciTTransferEvt,
+ &CompletionCode, XHCI_BULK_COMPLETE_TIMEOUT_MS, &ResidualData);
+
+ // Clear Link TRB chain flag
+ ((XHCI_NORMAL_XFR_TRB*)XfrRing->LastTrb)->Chain = 0;
+
+ if (CompletionCode == XHCI_TRB_STALL_ERROR) {
+ XhciClearStalledEp(PeiServices, Usb3Hc, SlotId, Dci);
+ break;
+ }
+ TransferredSize += (RingDataSize - ResidualData);
+ if (ResidualData != 0) break; // Short packet detected, no more transfers
+ RemainingDataSize -= RingDataSize;
+ }
+
+ *DataLength = TransferredSize;
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciHcGetRootHubPortNumber
+//
+// Description:
+// This function returns number of root ports supported by the controller.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS XhciHcGetRootHubPortNumber (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *PortNumber )
+{
+ USB3_CONTROLLER *Usb3Hc = PEI_RECOVERY_USB_XHCI_DEV_FROM_THIS(This);
+
+ *PortNumber = Usb3Hc->MaxPorts;
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UpdatePortStatusSpeed
+//
+// Description:
+// This function converts XHCI speed definition into the terms
+// of PEI_USB_HOST_CONTROLLER_PPI (namely XHCI_DEVSPEED_xyz is converted
+// into USB_PORT_STAT_xyz).
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UpdatePortStatusSpeed(
+ EFI_PEI_SERVICES **PeiServices,
+ UINT8 Speed,
+ UINT16 *PortStatus
+)
+{
+ switch (Speed) {
+ case XHCI_DEVSPEED_UNDEFINED:
+ case XHCI_DEVSPEED_FULL:
+ break;
+ case XHCI_DEVSPEED_LOW:
+ *PortStatus |= USB_PORT_STAT_LOW_SPEED;
+ break;
+ case XHCI_DEVSPEED_HIGH:
+ *PortStatus |= USB_PORT_STAT_HIGH_SPEED;
+ break;
+ case XHCI_DEVSPEED_SUPER:
+ *PortStatus |= USB_PORT_STAT_SUPER_SPEED;
+ break;
+ default:
+ PEI_TRACE((-1, PeiServices, "XHCI ERROR: unknown device speed.\n"));
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciHcGetRootHubPortStatus
+//
+// Description:
+// Host controller API function; returns root hub port status in terms of
+// PEI_USB_HOST_CONTROLLER_PPI definition.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS XhciHcGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus )
+{
+ USB3_CONTROLLER *Usb3Hc = PEI_RECOVERY_USB_XHCI_DEV_FROM_THIS(This);
+ volatile XHCI_PORTSC *PortSC;
+
+ // Find the proper MMIO access offset for a given port
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (PortNumber - 1)));
+
+ PEI_TRACE((-1, PeiServices, "XHCI port[%d] status: %08x\n", PortNumber, PortSC->AllBits));
+
+ *(UINT32*)PortStatus = 0;
+
+ if (PortSC->Field.Ccs != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+ if (PortSC->Field.Ped != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
+ }
+ if (PortSC->Field.Oca != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
+ }
+ if (PortSC->Field.Pr != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_RESET;
+ }
+ if (PortSC->Field.Pp != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_POWER;
+ }
+ if (PortSC->Field.Csc != 0) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+ if (PortSC->Field.Pec != 0) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
+ }
+ if (PortSC->Field.Occ != 0) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
+ }
+ if (PortSC->Field.Prc != 0) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
+ }
+
+ UpdatePortStatusSpeed(PeiServices, PortSC->Field.PortSpeed, &PortStatus->PortStatus);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciHcSetRootHubPortFeature
+//
+// Description:
+// Host controller PEI_USB_HOST_CONTROLLER_PPI API function; sets a requested
+// feature of a root hub port.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS XhciHcSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature )
+{
+ USB3_CONTROLLER *Usb3Hc = PEI_RECOVERY_USB_XHCI_DEV_FROM_THIS(This);
+ volatile XHCI_PORTSC *PortSC;
+
+ if (PortNumber > Usb3Hc->MaxPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (PortNumber - 1)));
+ switch (PortFeature) {
+ case EfiUsbPortEnable:
+ case EfiUsbPortSuspend:
+ break;
+
+ case EfiUsbPortReset:
+ PortSC->AllBits = (PortSC->AllBits & XHCI_PCS_PP) | XHCI_PCS_PR;
+ break;
+
+ case EfiUsbPortPower:
+ PortSC->AllBits = XHCI_PCS_PP;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciHcClearRootHubPortFeature
+//
+// Description:
+// Host controller PEI_USB_HOST_CONTROLLER_PPI API function; clears a requested
+// feature of a root hub port.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS XhciHcClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature )
+{
+ USB3_CONTROLLER *Usb3Hc = PEI_RECOVERY_USB_XHCI_DEV_FROM_THIS(This);
+ volatile XHCI_PORTSC *PortSC;
+
+ if (PortNumber > Usb3Hc->MaxPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PortSC = (XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (PortNumber - 1)));
+
+ switch (PortFeature) {
+ case EfiUsbPortEnable:
+ PortSC->AllBits = (PortSC->AllBits & XHCI_PCS_PP) | XHCI_PCS_PED;
+ break;
+
+ case EfiUsbPortSuspend:
+ case EfiUsbPortReset:
+ break;
+
+ case EfiUsbPortPower:
+ PortSC->AllBits = (PortSC->AllBits & XHCI_PCS_PP) & ~(XHCI_PCS_PP);
+ break;
+
+ case EfiUsbPortOwner:
+ break;
+
+ case EfiUsbPortConnectChange:
+ PortSC->AllBits = (PortSC->AllBits & XHCI_PCS_PP) | XHCI_PCS_CSC;
+ break;
+
+ case EfiUsbPortEnableChange:
+ PortSC->AllBits = (PortSC->AllBits & XHCI_PCS_PP) | XHCI_PCS_PEC;
+ break;
+
+ case EfiUsbPortSuspendChange:
+ break;
+
+ case EfiUsbPortOverCurrentChange:
+ PortSC->AllBits = (PortSC->AllBits & XHCI_PCS_PP) | XHCI_PCS_OCC;
+ break;
+
+ case EfiUsbPortResetChange:
+ PortSC->AllBits = (PortSC->AllBits & XHCI_PCS_PP) | XHCI_PCS_PRC;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciMmio64Write
+//
+// Description:
+// MMIO write; depending on 64-bit access availability executes either one
+// 64-bit write or two 32-bit writes.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+XhciMmio64Write(
+ USB3_CONTROLLER *Usb3Hc,
+ UINTN Address,
+ UINT64 Data
+)
+{
+ if (Usb3Hc->Access64) {
+ *(UINT64*)Address = Data;
+ }
+ else {
+ *(UINT32*)Address = (UINT32)Data;
+ *(UINT32*)(Address + sizeof(UINT32)) = (UINT32)(Shr64(Data, 32));
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciInitRing
+//
+// Description:
+// Transfer ring initialization. There is an option to create a Link TRB in
+// the end of the ring.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciInitRing (
+ IN OUT TRB_RING *Ring,
+ IN UINTN RingBase,
+ IN UINT32 RingSize,
+ IN BOOLEAN PlaceLinkTrb
+)
+{
+ XHCI_LINK_TRB *LinkTrb;
+
+ Ring->Base = (XHCI_TRB*)RingBase;
+ Ring->Size = RingSize;
+ Ring->LastTrb = Ring->Base + RingSize - 1;
+ Ring->CycleBit = 1;
+ Ring->QueuePtr = (XHCI_TRB*)RingBase;
+
+ // Initialize ring with zeroes
+ {
+ UINT8 *p = (UINT8*)RingBase;
+ UINTN i;
+ for (i = 0; i < RingSize*sizeof(XHCI_TRB); i++, p++) *p = 0;
+ }
+
+ if (PlaceLinkTrb) {
+ // Place a Link TRB in the end of the ring pointing to the beginning
+ LinkTrb = (XHCI_LINK_TRB*)Ring->LastTrb;
+ LinkTrb->NextSegPtr = (UINT64)(UINTN)RingBase;
+ LinkTrb->ToggleCycle = 1;
+ LinkTrb->TrbType = XhciTLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XhciAdvanceEnqueuePtr
+//
+// Description:
+// This function advances returns the pointer to the current TRB and anvances
+// dequeue pointer. If the advance pointer is Link TRB, then it: 1) activates
+// Link TRB by updating its cycle bit, 2) updates dequeue pointer to the value
+// pointed by Link TRB.
+//
+// Input:
+// Ring - TRB ring to be updated
+//
+// Output:
+// TRB that can be used for command, transfer, etc.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+XHCI_TRB*
+XhciAdvanceEnqueuePtr(
+ TRB_RING *Ring
+)
+{
+ XHCI_TRB* Trb = Ring->QueuePtr;
+
+ if (Trb->TrbType == XhciTLink) {
+ Trb->CycleBit = Ring->CycleBit;
+ Ring->CycleBit ^= 1;
+ Ring->QueuePtr = Ring->Base;
+
+ Trb = Ring->QueuePtr;
+ }
+ // Clear the TRB
+ {
+ UINT32 *p = (UINT32*)Trb;
+ UINT8 i = 0;
+ for (i=0; i<(sizeof(XHCI_TRB)/sizeof(UINT32)); i++) {
+ *p++ = 0;
+ }
+ }
+
+ Trb->CycleBit = Ring->CycleBit;
+ Ring->QueuePtr++;
+
+ return Trb;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: XHCI_ProcessInterrupt
+//
+// Description: This is the XHCI controller event handler. It walks through
+// the Event Ring and executes the event associated code if needed. Updates
+// the Event Ring Data Pointer in the xHC to let it know which events are
+// completed.
+//
+// Output:
+// EFI_NOT_READY - Need more Interrupt processing
+// EFI_SUCCESS - No interrupts pending
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciProcessInterrupt(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc
+)
+{
+ XHCI_TRB *Trb;
+ XHCI_EVENT_TRB *EvTrb;
+
+ if ((UINT32)Usb3Hc->OpRegs->DcbAap != (UINT32)Usb3Hc->DcbaaPtr) return EFI_SUCCESS;
+/*
+ if (Usb3Hc->OpRegs->UsbSts.Field.Pcd) {
+ XHCI_EnumeratePorts(HcStruc);
+ Usb3Hc->OpRegs->UsbSts.AllBits = XHCI_STS_PCD; // Clear PortChangeDetect
+ }
+*/
+ if (Usb3Hc->OpRegs->UsbSts.Field.Eint)
+ {
+ Usb3Hc->OpRegs->UsbSts.AllBits = XHCI_STS_EVT_INTERRUPT;
+ Usb3Hc->RtRegs->IntRegs[0].IMan |= BIT0;
+ }
+
+ // Check for pending interrupts:
+ // check the USBSTS[3] and IMAN [0] to determine if any interrupt generated
+ if (Usb3Hc->EvtRing.QueuePtr->CycleBit != Usb3Hc->EvtRing.CycleBit) return EFI_SUCCESS;
+
+ // See if there are any TRBs waiting in the event ring
+ //for (Count = 0; Count < Usb3Hc->EvtRing.Size; Count++) {
+ for (;;) {
+ Trb = Usb3Hc->EvtRing.QueuePtr;
+
+ if (Trb->CycleBit != Usb3Hc->EvtRing.CycleBit) break; // past the last
+
+ if (Usb3Hc->EvtRing.QueuePtr == Usb3Hc->EvtRing.LastTrb) {
+ // Reached the end of the ring, wrap around
+ Usb3Hc->EvtRing.QueuePtr = Usb3Hc->EvtRing.Base;
+ Usb3Hc->EvtRing.CycleBit ^= 1;
+ } else {
+ Usb3Hc->EvtRing.QueuePtr++;
+ }
+ // TODO:: error manager
+ if (Trb->CompletionCode == XHCI_TRB_SHORTPACKET) {
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: short packet detected."));
+ }
+
+ if (Trb->CompletionCode == XHCI_TRB_STALL_ERROR) {
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: device STALLs."));
+ }
+
+ if (Trb->CompletionCode != XHCI_TRB_SUCCESS
+ && Trb->CompletionCode != XHCI_TRB_STALL_ERROR
+ && Trb->CompletionCode != XHCI_TRB_SHORTPACKET) {
+ PEI_TRACE((-1, PeiServices, "Trb completion code: %d\n", Trb->CompletionCode));
+ PEI_ASSERT(PeiServices, FALSE);
+ }
+
+ // Process TRB pointed by Usb3Hc->EvtRing->QueuePtr
+ EvTrb = (XHCI_EVENT_TRB*)Trb;
+
+ switch (Trb->TrbType) {
+ case XhciTTransferEvt:
+// very frequent, debug message here might affect timings,
+// uncomment only when needed
+// PEI_TRACE((-1, PeiServices, "TransferEvt\n"));
+
+// DEBUG
+/* XhciProcessXferEvt(
+ PeiServices,
+ Usb3Hc,
+ EvTrb->TransferEvt.TrbPtr,
+ EvTrb->TransferEvt.SlotId,
+ EvTrb->TransferEvt.EndpointId);*/
+ break;
+ case XhciTCmdCompleteEvt:
+ PEI_TRACE((-1, PeiServices, "CmdCompleteEvt\n"));
+ break;
+ case XhciTPortStatusChgEvt:
+ PEI_TRACE((-1, PeiServices, "PortStatusChgEvt, port #%d\n", EvTrb->PortStsChgEvt.PortId));
+ break;
+ case XhciTDoorbellEvt:
+ PEI_TRACE((-1, PeiServices, "DoorbellEvt\n"));
+ break;
+ case XhciTHostControllerEvt:
+ PEI_TRACE((-1, PeiServices, "HostControllerEvt\n"));
+ break;
+ case XhciTDevNotificationEvt:
+ PEI_TRACE((-1, PeiServices, "DevNotificationEvt\n"));
+ break;
+ case XhciTMfIndexWrapEvt:
+ PEI_TRACE((-1, PeiServices, "MfIndexWrapEvt\n"));
+ break;
+ default:
+ PEI_TRACE((-1, PeiServices, "UNKNOWN EVENT\n"));
+ }
+ }
+ //PEI_ASSERT(PeiServices, Count<Usb3Hc->EvtRing.Size); // Event ring is full
+
+ // Update ERDP to inform xHC that we have processed another TRB
+ XhciMmio64Write(Usb3Hc,
+ (UINTN)&Usb3Hc->RtRegs->IntRegs->Erdp, (UINT64)(UINTN)Usb3Hc->EvtRing.QueuePtr | BIT3);
+
+ return EFI_SUCCESS; // Set as interrupt processed
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XhciWaitForEvent
+//
+// Description:
+// This function walks through the active TRBs in the event ring and looks for
+// the command TRB to be complete. If found, returns SlotId and CompletionCode
+// from the completed event TRB. In the end it processes the event ring,
+// adjusting its Dequeue Pointer.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciWaitForEvent(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc,
+ XHCI_TRB *TrbToCheck,
+ TRB_TYPE EventType,
+ UINT8 *CompletionCode,
+ UINT16 TimeOutMs,
+ VOID *Data
+)
+{
+ XHCI_TRB *Trb;
+ UINT32 TimeOut;
+ EFI_STATUS Status;
+ UINT8 CycleBit;
+// UINT32 TimeOutValue = TimeOutMs << 6; // *64, 15 us unit
+ UINT32 TimeOutValue = TimeOutMs + 1;
+
+ for (TimeOut = 0; TimeOut < TimeOutValue; TimeOut++) {
+ for (Trb = Usb3Hc->EvtRing.QueuePtr,
+ CycleBit = Usb3Hc->EvtRing.CycleBit;;) {
+ if (Trb->CycleBit != CycleBit) {
+ // Command is not complete, break and retry
+ break;
+ }
+
+ *CompletionCode = Trb->CompletionCode;
+ if (Trb->CompletionCode == XHCI_TRB_STALL_ERROR ||
+ Trb->CompletionCode == XHCI_TRB_TRANSACTION_ERROR) {
+ Status = EFI_DEVICE_ERROR;
+ goto DoneWaiting;
+ }
+
+ // Active TRB found
+ if (Trb->TrbType == EventType) {
+ if ((*(UINTN*)&Trb->Param1) == (UINTN)TrbToCheck) {
+
+ if (Trb->CompletionCode != XHCI_TRB_SUCCESS && Trb->CompletionCode != XHCI_TRB_SHORTPACKET) {
+ PEI_TRACE((-1, PeiServices, "TRB Completion Error: %d\n", Trb->CompletionCode));
+ PEI_ASSERT(PeiServices, FALSE);
+ }
+
+ if (EventType == XhciTCmdCompleteEvt) {
+ *(UINT8*)Data = ((XHCI_CMDCOMPLETE_EVT_TRB*)Trb)->SlotId;
+ }
+ if (EventType == XhciTTransferEvt) {
+ if (Data != NULL) {
+ *(UINT32*)Data = ((XHCI_TRANSFER_EVT_TRB*)Trb)->TransferLength;
+ }
+ }
+
+ Status = (Trb->CompletionCode == XHCI_TRB_SUCCESS ||
+ Trb->CompletionCode == XHCI_TRB_SHORTPACKET)? EFI_SUCCESS:EFI_DEVICE_ERROR;
+ goto DoneWaiting;
+ }
+ }
+ // Advance TRB pointer
+ if (Trb == Usb3Hc->EvtRing.LastTrb) {
+ Trb = Usb3Hc->EvtRing.Base;
+ CycleBit ^= 1;
+ } else {
+ Trb++;
+ }
+ if (Trb == Usb3Hc->EvtRing.QueuePtr) {
+ // Event ring is full, return error
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: Event Ring is full...\n"));
+ PEI_ASSERT(PeiServices, FALSE);
+ *CompletionCode = XHCI_TRB_EVENTRINGFULL_ERROR;
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ }
+// XHCI_FIXED_DELAY_15MCS(Usb3Hc, 1); // 15 us out of TimeOutMs
+ XHCI_FIXED_DELAY_MS(Usb3Hc, 1); // 1 ms out of TimeOutMs
+ }
+
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: execution time-out.\n"));
+
+ *CompletionCode = XHCI_TRB_EXECUTION_TIMEOUT_ERROR;
+ Status = EFI_DEVICE_ERROR;
+
+DoneWaiting:
+ XhciProcessInterrupt(PeiServices, Usb3Hc);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XhciExecuteCommand
+//
+// Description:
+// This function places a given command in the Command Ring, rings HC doorbell,
+// and waits for the command completion.
+//
+// Output:
+// EFI_DEVICE_ERROR on execution failure, otherwise EFI_SUCCESS
+// Params - pointer to the command specific data.
+//
+// Notes:
+// Caller is responsible for a data placeholder.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciExecuteCommand(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc,
+ TRB_TYPE Cmd,
+ VOID *Params
+)
+{
+ volatile UINT32 *Doorbell;
+ UINT8 CompletionCode;
+ UINT8 SlotId;
+ EFI_STATUS Status;
+ XHCI_TRB *Trb = XhciAdvanceEnqueuePtr(&Usb3Hc->CmdRing);
+
+ Trb->TrbType = Cmd; // Set TRB type
+
+ // Fill in the command TRB fields
+ switch (Cmd) {
+ case XhciTAddressDeviceCmd:
+ case XhciTEvaluateContextCmd:
+ case XhciTConfigureEndpointCmd:
+ ((XHCI_ADDRESSDEV_CMD_TRB*)Trb)->InpCtxAddress = (UINT64)(UINTN)Usb3Hc->InputContext;
+ ((XHCI_ADDRESSDEV_CMD_TRB*)Trb)->SlotId = *((UINT8*)Params);
+ ((XHCI_ADDRESSDEV_CMD_TRB*)Trb)->Bsr = 0;
+ break;
+ case XhciTResetEndpointCmd:
+ ((XHCI_RESET_EP_CMD_TRB*)Trb)->Tsp = 0;
+ ((XHCI_RESET_EP_CMD_TRB*)Trb)->SlotId = *((UINT8*)Params);
+ ((XHCI_RESET_EP_CMD_TRB*)Trb)->EndpointId = *((UINT8*)Params+1);
+ break;
+ case XhciTSetTRDequeuePointerCmd:
+ ((XHCI_SET_TRPTR_CMD_TRB*)Trb)->TrPointer = ((XHCI_SET_TRPTR_CMD_TRB*)Params)->TrPointer;
+ ((XHCI_SET_TRPTR_CMD_TRB*)Trb)->EndpointId = ((XHCI_SET_TRPTR_CMD_TRB*)Params)->EndpointId;
+ ((XHCI_SET_TRPTR_CMD_TRB*)Trb)->SlotId = ((XHCI_SET_TRPTR_CMD_TRB*)Params)->SlotId;
+ break;
+ case XhciTDisableSlotCmd:
+ ((XHCI_DISABLESLOT_CMD_TRB*)Trb)->SlotId = *((UINT8*)Params);
+ break;
+ }
+
+ // Ring the door bell and see Event Ring update
+ Doorbell = (UINT32*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->DbOffset);
+ *Doorbell = 0; // HC doorbell is #0
+
+ Status = XhciWaitForEvent(
+ PeiServices, Usb3Hc, Trb, XhciTCmdCompleteEvt,
+ &CompletionCode, XHCI_CMD_COMPLETE_TIMEOUT_MS, &SlotId);
+
+ if (Status == EFI_DEVICE_ERROR) {
+ PEI_TRACE((-1, PeiServices, "XHCI command completion error code: %d\n", CompletionCode));
+ PEI_ASSERT(PeiServices, Status != EFI_DEVICE_ERROR);
+ return Status;
+ }
+
+ switch (Cmd) {
+ case XhciTEnableSlotCmd:
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: Enable Slot command complete, SlotID %d\n", SlotId));
+ *((UINT8*)Params) = SlotId;
+ break;
+ case XhciTEvaluateContextCmd:
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: Evaluate Context command complete.\n"));
+ break;
+ case XhciTConfigureEndpointCmd:
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: Configure Endpoint command complete.\n"));
+ break;
+ case XhciTResetEndpointCmd:
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: Reset Endpoint command complete (slot#%x dci#%x).\n",
+ *((UINT8*)Params), *((UINT8*)Params+1)));
+ break;
+ case XhciTSetTRDequeuePointerCmd:
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: Set TR pointer command complete.\n"));
+ break;
+ case XhciTDisableSlotCmd:
+ PEI_TRACE((-1, PeiServices, "PEI_XHCI: DisableSlot command complete.\n"));
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciInitXfrRing
+//
+// Description:
+// This function initializes transfer ring of given endpoint
+//
+// Output:
+// Pointer to the transfer ring
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+TRB_RING*
+XhciInitXfrRing(
+ USB3_CONTROLLER* Usb3Hc,
+ UINT8 Slot,
+ UINT8 Ep
+)
+{
+ TRB_RING *XfrRing = Usb3Hc->XfrRings + (Slot-1)*32 + Ep;
+ UINTN Base = Usb3Hc->XfrTrbs + ((Slot-1)*32+Ep)*RING_SIZE;
+
+ XhciInitRing(XfrRing, Base, TRBS_PER_SEGMENT, TRUE);
+
+ return XfrRing;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciTranslateInterval
+//
+// Description:
+// This routine calculates the Interval field to be used in device's endpoint
+// context. Interval is calculated using the following rules (Section 6.2.3.6):
+//
+// For SuperSpeed bulk and control endpoints, the Interval field shall not be
+// used by the xHC. For all other endpoint types and speeds, system software
+// shall translate the bInterval field in the USB Endpoint Descriptor to the
+// appropriate value for this field.
+//
+// For high-speed and SuperSpeed Interrupt and Isoch endpoints the bInterval
+// field the Endpoint Descriptor is computed as 125æs * 2^(bInterval-1), where
+// bInterval = 1 to 16, therefore Interval = bInterval - 1.
+//
+// For low-speed Interrupt and full-speed Interrupt and Isoch endpoints the
+// bInterval field declared by a Full or Low-speed device is computed as
+// bInterval * 1ms., where bInterval = 1 to 255.
+//
+// For Full- and Low-speed devices software shall round the value of Endpoint
+// Context Interval field down to the nearest base 2 multiple of bInterval * 8.
+//
+// Input:
+// EpType Endpoint type, see XHCI_EP_CONTEXT.DW1.EpType field definitions
+// Speed Endpoint speed, 1..4 for XHCI_DEVSPEED_FULL, _LOW, _HIGH, _SUPER
+// Interval Poll interval value from endpoint descriptor
+//
+// Output:
+// Interval value to be written to the endpoint context
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+XhciTranslateInterval(
+ UINT8 EpType,
+ UINT8 Speed,
+ UINT8 Interval
+)
+{
+ UINT8 TempData;
+ UINT8 BitCount;
+
+ if (EpType == XHCI_EPTYPE_CTL ||
+ EpType == XHCI_EPTYPE_BULK_OUT ||
+ EpType == XHCI_EPTYPE_BULK_IN) {
+
+ if (Speed == XHCI_DEVSPEED_HIGH) {
+ return Interval;
+ } else {
+ return 0; // Interval field will not be used for LS, FS and SS
+ }
+ }
+
+ // Control and Bulk endpoints are processed; translate intervals for Isoc and Interrupt
+ // endpoints
+
+ // Translate SS and HS endpoints
+ if (Speed == XHCI_DEVSPEED_SUPER || Speed == XHCI_DEVSPEED_HIGH) {
+ return (Interval - 1);
+ }
+
+ for (TempData = Interval, BitCount = 0; TempData != 0; BitCount++) {
+ TempData >>= 1;
+ }
+ return (BitCount + 2); // return value, where Interval = 0.125*2^value
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciEnableEndpoints
+//
+// Description:
+// This function parses the device descriptor data and enables the endpoints
+// by 1)assigning the Transfer TRB and 2)executing ConfigureEndpoint command
+// for the slot. Section 4.3.5.
+//
+// Input:
+// Desc - Device Configuration Descriptor data pointer
+//
+// Output:
+// EFI_DEVICE_ERROR on error, EFI_SUCCESS on success
+//
+// Notes:
+// 1) This call is executed before SET_CONFIGURATION control transfer
+// 2) Device slot is addressed by gSlotBeingConfigured
+// 3) EP0 information is valid in the Device
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciEnableEndpoints (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 *Desc
+)
+{
+ UINT16 TotalLength;
+ UINT16 CurPos;
+ UINT8 Dci;
+ EFI_USB_INTERFACE_DESCRIPTOR *IntrfDesc;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc;
+ TRB_RING *XfrRing;
+ UINT8 EpType;
+ UINT8 Status;
+ UINT8 IsHub;
+ UINT8 DevSpeed;
+ XHCI_INPUT_CONTROL_CONTEXT *CtlCtx;
+ XHCI_SLOT_CONTEXT *SlotCtx;
+ XHCI_EP_CONTEXT *EpCtx;
+
+ USB3_CONTROLLER *Usb3Hc = PEI_RECOVERY_USB_XHCI_DEV_FROM_THIS(This);
+ UINT8 SlotId = gSlotBeingConfigured;
+ UINT8 *DevCtx = (UINT8*)XhciGetDeviceContext(Usb3Hc, SlotId);
+
+ if (((EFI_USB_CONFIG_DESCRIPTOR*)Desc)->DescriptorType != USB_DT_CONFIG) return EFI_DEVICE_ERROR;
+
+ SlotCtx = (XHCI_SLOT_CONTEXT*)XhciGetContextEntry(Usb3Hc, DevCtx, 0);
+ DevSpeed = SlotCtx->Speed;
+
+ // Note (From 4.6.6): The Add Context flag A1 and Drop Context flags D0 and D1
+ // of the Input Control Context (in the Input Context) shall be cleared to 0.
+ // Endpoint 0 Context does not apply to the Configure Endpoint Command and
+ // shall be ignored by the xHC. A0 shall be set to 1.
+
+ // Note (From 6.2.2.2): If Hub = 1 and Speed = High-Speed (3), then the
+ // TT Think Time and Multi-TT (MTT) fields shall be initialized.
+ // If Hub = 1, then the Number of Ports field shall be initialized, else
+ // Number of Ports = 0.
+
+ // Prepare input context for EvaluateContext comand
+ (**PeiServices).SetMem((UINT8*)Usb3Hc->InputContext, XHCI_INPUT_CONTEXT_ENTRIES * Usb3Hc->ContextSize, 0);
+
+ CtlCtx = (XHCI_INPUT_CONTROL_CONTEXT*)XhciGetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 0);
+ CtlCtx->AddContextFlags = BIT0; // EP0
+
+ SlotCtx = (XHCI_SLOT_CONTEXT*)XhciGetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, 1);
+
+ // Collect the endpoint information and update the Device Input Context
+ TotalLength = ((EFI_USB_CONFIG_DESCRIPTOR*)Desc)->TotalLength;
+
+ if (TotalLength > (MAX_CONTROL_DATA_SIZE - 1)) {
+ TotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ }
+
+ for (CurPos = 0; CurPos < TotalLength; CurPos += EpDesc->Length) {
+ EpDesc = (EFI_USB_ENDPOINT_DESCRIPTOR*)(IntrfDesc = (EFI_USB_INTERFACE_DESCRIPTOR*)(Desc + CurPos));
+
+ if (IntrfDesc->DescriptorType == USB_DT_INTERFACE) {
+ IsHub = IntrfDesc->InterfaceClass == BASE_CLASS_HUB;
+ continue;
+ }
+
+ if (EpDesc->DescriptorType != USB_DT_ENDPOINT) continue;
+
+ // Found Endpoint, fill up the information in the InputContext
+
+ // Calculate Device Context Index (DCI), Section 4.5.1.
+ // 1) For Isoch, Interrupt, or Bulk type endpoints the DCI is calculated
+ // from the Endpoint Number and Direction with the following formula:
+ // DCI = (Endpoint Number * 2) + Direction, where Direction = 0 for OUT
+ // endpoints and 1 for IN endpoints.
+ // 2) For Control type endpoints:
+ // DCI = (Endpoint Number * 2) + 1
+ //
+ // Also calculate XHCI EP type out of EpDesc->bEndpointFlags
+
+ if ((EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) == EP_DESC_FLAG_TYPE_CONT) {
+ Dci = (EpDesc->EndpointAddress & 0xf) * 2 + 1;
+ EpType = XHCI_EPTYPE_CTL;
+ } else {
+ // Isoc, Bulk or Interrupt endpoint
+ Dci = (EpDesc->EndpointAddress & 0xf) * 2;
+ EpType = EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS; // 1, 2, or 3
+
+ if (EpDesc->EndpointAddress & BIT7) {
+ Dci++; // IN
+ EpType += 4; // 5, 6, or 7
+ }
+ }
+
+ // Update ContextEntries in the Slot context
+ if (Dci > SlotCtx->ContextEntries) {
+ SlotCtx->ContextEntries = Dci;
+ }
+
+ EpCtx = (XHCI_EP_CONTEXT*)XhciGetContextEntry(Usb3Hc, (UINT8*)Usb3Hc->InputContext, Dci + 1);
+
+ EpCtx->EpType = EpType;
+ EpCtx->MaxPacketSize = EpDesc->MaxPacketSize;
+ EpCtx->ErrorCount = 3;
+
+ // Set Interval
+ EpCtx->Interval = XhciTranslateInterval(EpType, DevSpeed, EpDesc->Interval);
+
+ XfrRing = XhciInitXfrRing(Usb3Hc, SlotId, Dci - 1);
+ EpCtx->TrDequeuePtr = (UINT64)(UINTN)XfrRing->Base + 1;
+
+ CtlCtx->AddContextFlags |= (1 << Dci);
+ }
+
+ // For a HUB update NumberOfPorts and TTT fields in the Slot context. For that get hub descriptor
+ // and use bNbrPorts and TT Think time fields (11.23.2.1 of USB2 specification)
+ // Notes:
+ // - Slot.Hub field is already updated
+ // - Do not set NumberOfPorts and TTT fields for 0.95 controllers
+
+ if (IsHub) {
+
+ EFI_STATUS Status;
+ EFI_USB_HUB_DESCRIPTOR HubDesc;
+ UINT8 Speed;
+ EFI_USB_DEVICE_REQUEST DevReq;
+ UINT32 Timeout;
+ UINTN DataLength = sizeof(EFI_USB_HUB_DESCRIPTOR);
+ UINT32 TransferResult;
+
+ //
+ // Fill Device request packet
+ //
+ (**PeiServices).SetMem((VOID*)&DevReq, sizeof(EFI_USB_DEVICE_REQUEST), 0);
+ DevReq.RequestType = USB_RT_HUB | 0x80;
+ DevReq.Request = USB_DEV_GET_DESCRIPTOR;
+ DevReq.Value = DevSpeed == XHCI_DEVSPEED_SUPER ? USB_DT_SS_HUB << 8 : USB_DT_HUB << 8;
+ DevReq.Index = 0;
+ DevReq.Length = sizeof(EFI_USB_HUB_DESCRIPTOR);
+
+ Timeout = 3000;
+
+ switch (DevSpeed) {
+ case XHCI_DEVSPEED_HIGH: Speed = USB_HIGH_SPEED_DEVICE; break;
+ case XHCI_DEVSPEED_LOW: Speed = USB_SLOW_SPEED_DEVICE; break;
+ case XHCI_DEVSPEED_FULL: Speed = USB_FULL_SPEED_DEVICE; break;
+ case XHCI_DEVSPEED_SUPER: Speed = USB_SUPER_SPEED_DEVICE;
+ }
+
+ EpCtx = (XHCI_EP_CONTEXT*)XhciGetContextEntry(Usb3Hc, DevCtx, 1);
+
+ Status = XhciHcControlTransfer(PeiServices, This,
+ 0, // Current address
+ Speed,
+ EpCtx->MaxPacketSize,
+ 0, // Transaction translator
+ &DevReq,
+ EfiUsbDataIn,
+ &HubDesc,
+ &DataLength,
+ Timeout,
+ &TransferResult);
+
+ if (!EFI_ERROR(Status)) {
+ SlotCtx->Hub = 1;
+ SlotCtx->PortsNum = HubDesc.NbrPorts;
+
+ if (DevSpeed == XHCI_DEVSPEED_HIGH) {
+ SlotCtx->TThinkTime = (HubDesc.HubCharacteristics[0] >> 5) & 0x3;
+ }
+ }
+ }
+
+// check route string here
+ // Input context is updated with the endpoint information. Execute ConfigureEndpoint command.
+ Status = XhciExecuteCommand(PeiServices, Usb3Hc, XhciTConfigureEndpointCmd, &SlotId);
+ PEI_ASSERT(PeiServices, Status == EFI_SUCCESS);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciGetXfrRing
+//
+// Description:
+// This routine calculates the address of the address ring of a particular
+// Slot/Endpoint.
+//
+// Output:
+// Pointer to the transfer ring
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+TRB_RING*
+XhciGetXfrRing(
+ USB3_CONTROLLER* Usb3Hc,
+ UINT8 Slot,
+ UINT8 Ep
+)
+{
+ return Usb3Hc->XfrRings + (Slot-1)*32 + Ep;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XhciGetTheDoorbell
+//
+// Description:
+// This function calculates and returns the pointer to a doorbell for a
+// given Slot.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32*
+XhciGetTheDoorbell(
+ USB3_CONTROLLER *Usb3Hc,
+ UINT8 SlotId
+)
+{
+ return (UINT32*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->DbOffset + sizeof(UINT32)*SlotId);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XhciGetDeviceContext
+//
+// Description:
+// This function calculates and returns the pointer to a device context for
+// a given Slot.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8*
+XhciGetDeviceContext(
+ USB3_CONTROLLER *Usb3Hc,
+ UINT8 SlotId
+)
+{
+ UINT32 DevCtxSize = XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize;
+ return (UINT8*)((UINTN)Usb3Hc->DeviceContext + (SlotId - 1) * DevCtxSize);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: XhciGetContextEntry
+//
+// Description:
+// This function calculates and returns the pointer to a context entry for
+// a given index.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8*
+XhciGetContextEntry(
+ USB3_CONTROLLER *Usb3Hc,
+ VOID *Context,
+ UINT8 Index
+)
+{
+ return (UINT8*)((UINTN)Context + Index * Usb3Hc->ContextSize);
+}
+ //(EIP75547+)>
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciEnableUsb2Port
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+XhciResetUsb2Port(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc
+)
+{
+ UINT8 Count;
+ UINT8 PortNumber;
+ volatile XHCI_PORTSC *PortSC;
+ UINT32 i;
+
+ if (Usb3Hc->Usb2Protocol) {
+ for(Count = 0; Count < Usb3Hc->Usb2Protocol->PortCount; Count++) {
+ PortNumber = Count + Usb3Hc->Usb2Protocol->PortOffset;
+ PortSC =(XHCI_PORTSC*)((UINTN)Usb3Hc->OpRegs +
+ XHCI_PORTSC_OFFSET + (0x10 * (PortNumber - 1)));
+ if (PortSC->Field.Ccs) {
+ if(!(PortSC->Field.Ped)) {
+ PortSC->AllBits = XHCI_PCS_PR | XHCI_PCS_PP;
+ for (i = 0; i < 200; i++) {
+ XHCI_FIXED_DELAY_MS(Usb3Hc, 1);
+ if (PortSC->Field.Prc) break;
+ }
+ PortSC->AllBits = XHCI_PCS_WRC | XHCI_PCS_PRC | XHCI_PCS_PP;
+ }
+ }
+ }
+ }
+
+ }
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: XhciExtCapParser
+//
+// Description:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+XhciExtCapParser(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc
+)
+{
+ XHCI_EXT_CAP *CurPtr;
+
+ if (Usb3Hc->CapRegs->HcParams.Xecp == 0) return EFI_SUCCESS;
+
+ // Starts from first capability
+ CurPtr = (XHCI_EXT_CAP *)((UINTN)Usb3Hc->CapRegs + (Usb3Hc->CapRegs->HcParams.Xecp << 2));
+
+ // Traverse all capability structures
+ for(;;) {
+ switch (CurPtr->CapId) {
+ case XHCI_EXT_CAP_USB_LEGACY:
+ break;
+ case XHCI_EXT_CAP_SUPPORTED_PROTOCOL:
+ if (((XHCI_EXT_PROTOCOL*)CurPtr)->MajorRev == 0x02) {
+ Usb3Hc->Usb2Protocol = (XHCI_EXT_PROTOCOL*)CurPtr;
+ PEI_TRACE((-1, PeiServices, "XHCI: USB2 Support Protocol %x, PortOffset %x PortCount %x\n",
+ Usb3Hc->Usb2Protocol, Usb3Hc->Usb2Protocol->PortOffset, Usb3Hc->Usb2Protocol->PortCount));
+ } else if (((XHCI_EXT_PROTOCOL*)CurPtr)->MajorRev == 0x03) {
+ Usb3Hc->Usb3Protocol = (XHCI_EXT_PROTOCOL*)CurPtr;
+ PEI_TRACE((-1, PeiServices, "XHCI: USB3 Support Protocol %x, PortOffset %x PortCount %x\n",
+ Usb3Hc->Usb3Protocol, Usb3Hc->Usb3Protocol->PortOffset, Usb3Hc->Usb3Protocol->PortCount));
+ }
+ break;
+
+ case XHCI_EXT_CAP_POWERMANAGEMENT:
+ case XHCI_EXT_CAP_IO_VIRTUALIZATION:
+ case XHCI_EXT_CAP_USB_DEBUG_PORT:
+ break;
+ }
+ if(CurPtr->NextCapPtr == 0) break;
+ // Point to next capability
+ CurPtr=(XHCI_EXT_CAP *)((UINTN)CurPtr+ (((UINTN)CurPtr->NextCapPtr) << 2));
+ }
+
+ return EFI_SUCCESS;
+}
+ //(EIP75547+)
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/UsbRecovery/XhciPEI/XhciPei.cif b/Core/EM/UsbRecovery/XhciPEI/XhciPei.cif
new file mode 100644
index 0000000..918bf2a
--- /dev/null
+++ b/Core/EM/UsbRecovery/XhciPEI/XhciPei.cif
@@ -0,0 +1,9 @@
+<component>
+ name = "XhciPei"
+ category = ModulePart
+ LocalRoot = "core\em\UsbRecovery\XhciPEI\"
+ RefName = "XhciPei"
+[files]
+"XhciPei.c"
+"XhciPei.h"
+<endComponent>
diff --git a/Core/EM/UsbRecovery/XhciPEI/XhciPei.h b/Core/EM/UsbRecovery/XhciPEI/XhciPei.h
new file mode 100644
index 0000000..bb9f667
--- /dev/null
+++ b/Core/EM/UsbRecovery/XhciPEI/XhciPei.h
@@ -0,0 +1,1245 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/XhciPei.h 5 11/24/12 5:45a Ryanchou $
+//
+// $Revision: 5 $
+//
+// $Date: 11/24/12 5:45a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/XhciPei.h $
+//
+// 5 11/24/12 5:45a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 4 4/24/12 10:19p Wilsonlee
+// [TAG] EIP75547
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Xhci recovery funtion failed when SS devices on USB 3.0
+// port.
+// [RootCause] The SS device connected to USB2 port.
+// [Solution] Reset the USB2 port when initial xhci controller, then the
+// SS device reconnect to USB3 port.
+// [Files] XhciPei.c, XhciPei.h
+//
+// 3 1/18/11 1:09a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 2 1/17/11 7:09a Ryanchou
+// [TAG] EIP48013
+// [Category] Improvement
+// [Description] Use 32 or 64 byte Context data structures dynamically.
+// [Files] XhciPei.c, XhciPei.h
+//
+// 1 10/11/10 4:53p Olegi
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: XhciPei.h
+//
+// Description:
+// This file is the main header file for the EHCI PEI USB recovery module. It
+// contains generic constant and type declarations/definitions.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#ifndef _XHCIPEI_H
+#define _XHCIPEI_H
+
+#include <PEI.h>
+#include "PPI\UsbHostController.h"
+#include "PPI\Stall.h"
+
+//----------------------------------------------------------------------------
+// XHCI_PCI_ADDRESS( ControllerIndex, Register )
+//
+// allows easy generation of a valid PCI address using an index into the
+// gXhciControllerPciTable and a register number
+#define XHCI_PCI_ADDRESS( ControllerIndex, Register ) PEI_PCI_CFG_ADDRESS( \
+ gXhciControllerPciTable[ControllerIndex].Bus, \
+ gXhciControllerPciTable[ControllerIndex].Device, \
+ gXhciControllerPciTable[ControllerIndex].Function, \
+ Register )
+
+#define XHCI_FIXED_DELAY_MS( Usb3Hc, milliseconds ) \
+ Usb3Hc->StallPpi->Stall( Usb3Hc->PeiServices, Usb3Hc->StallPpi, milliseconds * 1000 );
+
+#define XHCI_FIXED_DELAY_15MCS( Usb3Hc, units ) \
+ Usb3Hc->StallPpi->Stall( Usb3Hc->PeiServices, Usb3Hc->StallPpi, units * 15 );
+
+// CountTime(milliseconds * 1000, PM_BASE_ADDRESS);
+
+#define XHCI_SWITCH2SS_DELAY_MS 5
+#define MAX_CONTROL_DATA_SIZE 0x200
+
+#define EP_DESC_FLAG_TYPE_BITS 0x03 //Bit 1-0: Indicate type of transfer on endpoint
+#define EP_DESC_FLAG_TYPE_CONT 0x00 //Bit 1-0: 00 = Endpoint does control transfers
+#define EP_DESC_FLAG_TYPE_ISOC 0x01 //Bit 1-0: 01 = Endpoint does isochronous transfers
+#define EP_DESC_FLAG_TYPE_BULK 0x02 //Bit 1-0: 10 = Endpoint does bulk transfers
+#define EP_DESC_FLAG_TYPE_INT 0x03 //Bit 1-0: 11 = Endpoint does interrupt transfers
+
+#pragma pack(push,1)
+
+typedef struct {
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+} PCI_BUS_DEV_FUNCTION;
+
+typedef struct {
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT32 Register;
+ UINT8 Size;
+ UINT32 SetBits;
+ UINT32 ClearBits;
+} PCI_DEV_REGISTER_VALUE;
+/*
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT16 wUsbSpecVersion;
+ UINT8 bBaseClass;
+ UINT8 bSubClass;
+ UINT8 bProtocol;
+ UINT8 bEndp0MaxPacket;
+ UINT16 wVendorId;
+ UINT16 wDeviceId;
+ UINT16 wDeviceRev;
+ UINT8 bMfgStr;
+ UINT8 bProductStr;
+ UINT8 bSerialStr;
+ UINT8 bNumConfigs;
+} DEV_DESC;
+
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT16 wTotalLength;
+ UINT8 bNumInterfaces;
+ UINT8 bConfigValue;
+ UINT8 bConfigString;
+ UINT8 bConfigFlags;
+ UINT8 bConfigPower;
+} CNFG_DESC;
+
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT8 bInterfaceNum;
+ UINT8 bAltSettingNum;
+ UINT8 bNumEndpoints;
+ UINT8 bBaseClass;
+ UINT8 bSubClass;
+ UINT8 bProtocol;
+ UINT8 bInterfaceString;
+}INTRF_DESC;
+
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT8 bNumPorts; // Number of downstream ports on hub
+ UINT16 wHubFlags; // See HUB_FLAG_xxx bit definitions below
+ UINT8 bPowerOnDelay; // Time to delay after turning on power to port (in 2ms units)
+ UINT8 bHubControlAmps; // Milliamps of current needed by hub controller
+
+ UINT8 bDeviceRemovable; // Variable size array of bits (one for each port)
+} HUB_DESC;
+
+typedef struct {
+ UINT8 bDescLength;
+ UINT8 bDescType;
+ UINT8 bEndpointAddr;
+ UINT8 bEndpointFlags;
+ UINT16 wMaxPacketSize;
+ UINT8 bPollInterval;
+} ENDP_DESC;
+*/
+// XHCI_EP_CONTEXT.DW0.State definitions
+#define XHCI_EP_STATE_DISABLED 0
+#define XHCI_EP_STATE_RUNNING 1
+#define XHCI_EP_STATE_HALTED 2
+#define XHCI_EP_STATE_STOPPED 3
+#define XHCI_EP_STATE_ERROR 4
+
+// XHCI_EP_CONTEXT.DW1.EpType definitions
+#define XHCI_EP_TYPE_NOTVALID 0
+#define XHCI_EP_TYPE_ISO_OUT 1
+#define XHCI_EP_TYPE_BLK_OUT 2
+#define XHCI_EP_TYPE_INT_OUT 3
+#define XHCI_EP_TYPE_CONTROL 4
+#define XHCI_EP_TYPE_ISO_IN 5
+#define XHCI_EP_TYPE_BLK_IN 6
+#define XHCI_EP_TYPE_INT_IN 7
+
+//---------------------------------------------------------
+// Device context definition
+//---------------------------------------------------------
+
+// TRB completion codes Table 130
+#define XHCI_TRB_INVALID 0
+#define XHCI_TRB_SUCCESS 1
+#define XHCI_TRB_DATABUF_ERROR 2
+#define XHCI_TRB_BABBLE_ERROR 3
+#define XHCI_TRB_TRANSACTION_ERROR 4
+#define XHCI_TRB_TRB_ERROR 5
+#define XHCI_TRB_STALL_ERROR 6
+#define XHCI_TRB_RESOURCE_ERROR 7
+#define XHCI_TRB_BANDWIDTH_ERROR 8
+#define XHCI_TRB_OUTOFSLOTS_ERROR 9
+#define XHCI_TRB_INVALIDSTREAMTYPE_ERROR 10
+#define XHCI_TRB_SLOTNOTENABLED_ERROR 11
+#define XHCI_TRB_ENDPOINTNOTENABLED_ERROR 12
+#define XHCI_TRB_SHORTPACKET 13
+#define XHCI_TRB_RINGUNDERRUN 14
+#define XHCI_TRB_RINGOVERRUN 15
+#define XHCI_TRB_VFRINGFULL_ERROR 16
+#define XHCI_TRB_PARAMETER_ERROR 17
+#define XHCI_TRB_BANDWIDTHOVERRUN_ERROR 18
+#define XHCI_TRB_CONTEXTSTATE_ERROR 19
+#define XHCI_TRB_NOPINGRESPONSE_ERROR 20
+#define XHCI_TRB_EVENTRINGFULL_ERROR 21
+#define XHCI_TRB_MISSEDSERVICE_ERROR 23
+#define XHCI_TRB_CMDRINGSTOPPED 24
+#define XHCI_TRB_COMMANDABORTED 25
+#define XHCI_TRB_STOPPED 26
+#define XHCI_TRB_STOPPEDLENGTHINVALID 27
+#define XHCI_TRB_CONTROLABORT_ERROR 28
+#define XHCI_TRB_ISOCHBUFOVERRUN 31
+#define XHCI_TRB_EVENTLOST_ERROR 32
+#define XHCI_TRB_UNDEFINED_ERROR 33
+#define XHCI_TRB_INVALIDSTREAMID_ERROR 34
+#define XHCI_TRB_SECONDARYBANDWIDTH_ERROR 35
+#define XHCI_TRB_SPLITTRANSACTION_ERROR 36
+
+#define XHCI_TRB_EXECUTION_TIMEOUT_ERROR 255
+
+//---------------------------------------------------------
+// Transfer Descriptor Block (TRB) definitions, section 4.11
+//---------------------------------------------------------
+// TRB Template
+typedef struct {
+ UINT32 Param1;
+ UINT32 Param2;
+
+ UINT32 RsvdZ1 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 16;
+} XHCI_TRB;
+
+// Event TRB types, Section 6.4.2
+typedef struct {
+ UINT64 TrbPtr;
+
+ UINT32 TransferLength : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ1 : 1;
+ UINT32 EventData : 1;
+ UINT32 RsvdZ2 : 7;
+ UINT32 TrbType : 6;
+ UINT32 EndpointId : 5;
+ UINT32 RzvdZ3 : 3;
+ UINT32 SlotId : 8;
+} XHCI_TRANSFER_EVT_TRB;
+
+typedef struct {
+ UINT64 CmdTrbPtr;
+
+ UINT32 RsvdZ1 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 VfId : 8;
+ UINT32 SlotId : 8;
+} XHCI_CMDCOMPLETE_EVT_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1 : 24;
+ UINT32 PortId : 8;
+
+ UINT32 RsvdZ2;
+
+ UINT32 RsvdZ3 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ4 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ5 : 16;
+} XHCI_PORTSTSCHG_EVT_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1[2];
+
+ UINT32 RsvdZ2 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ3 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 8;
+ UINT32 SlotId : 8;
+} XHCI_BANDWIDTHRQ_EVT_TRB;
+
+typedef struct {
+ UINT32 DbReason : 5;
+ UINT32 RsvdZ1 : 27;
+
+ UINT32 Rsvd2;
+
+ UINT32 RsvdZ3 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ4 : 9;
+ UINT32 TrbType : 6;
+ UINT32 VfId : 8;
+ UINT32 SlotId : 8;
+} XHCI_DORBELL_EVT_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1[2];
+
+ UINT32 RsvdZ2 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ3 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 16;
+} XHCI_HC_EVT_TRB;
+
+typedef struct {
+ UINT8 RsvdZ1 : 4;
+ UINT8 NtfType : 4;
+
+ UINT8 DevNtfData[7];
+
+ UINT32 RsvdZ2 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ3 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 8;
+ UINT32 SlotId : 8;
+} XHCI_DEVNOTIFY_EVT_TRB;
+
+typedef struct {
+ UINT32 RsvdZ[2];
+
+ UINT32 RsvdZ2 : 24;
+ UINT32 CompletionCode : 8;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ3 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 16;
+} XHCI_MFINDXWRAP_EVT_TRB;
+
+typedef union {
+ XHCI_TRANSFER_EVT_TRB TransferEvt;
+ XHCI_CMDCOMPLETE_EVT_TRB CmdEvt;
+ XHCI_PORTSTSCHG_EVT_TRB PortStsChgEvt;
+ XHCI_BANDWIDTHRQ_EVT_TRB BandwidthRqEvt;
+ XHCI_DORBELL_EVT_TRB DoorbellEvt;
+ XHCI_HC_EVT_TRB HcEvt;
+ XHCI_DEVNOTIFY_EVT_TRB DevNotificationEvt;
+ XHCI_MFINDXWRAP_EVT_TRB MicroframeIndxWrapEvt;
+} XHCI_EVENT_TRB;
+
+// Command TRB types, Section 6.4.3
+typedef struct {
+ UINT32 RsvdZ1[3];
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 16;
+} XHCI_COMMON_CMD_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1[3];
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 8;
+ UINT32 SlotId : 8;
+} XHCI_DISABLESLOT_CMD_TRB;
+
+typedef struct {
+ UINT64 InpCtxAddress;
+ UINT32 RsvdZ1;
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 8;
+ UINT32 Bsr : 1;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ3 : 8;
+ UINT32 SlotId : 8;
+} XHCI_ADDRESSDEV_CMD_TRB;
+
+typedef struct {
+ UINT32 RsvdZ1[3];
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 8;
+ UINT32 Tsp : 1;
+ UINT32 TrbType : 6;
+ UINT32 EndpointId : 5;
+ UINT32 RsvdZ3 : 3;
+ UINT32 SlotId : 8;
+} XHCI_RESET_EP_CMD_TRB;
+
+typedef struct {
+ UINT64 TrPointer;
+
+ UINT32 RsvdZ1 :16;
+ UINT32 StreamId :16;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 9;
+ UINT32 TrbType : 6;
+ UINT32 EndpointId : 5;
+ UINT32 RsvdZ3 : 3;
+ UINT32 SlotId : 8;
+} XHCI_SET_TRPTR_CMD_TRB;
+
+typedef union {
+ XHCI_COMMON_CMD_TRB GenericCmdTrb;
+ XHCI_COMMON_CMD_TRB NoOpCmdTrb;
+ XHCI_COMMON_CMD_TRB EnableSlotCmdTrb;
+ XHCI_DISABLESLOT_CMD_TRB DisableSlotCmdTrb;
+ XHCI_ADDRESSDEV_CMD_TRB AddressDevCmdTrb;
+ XHCI_SET_TRPTR_CMD_TRB SetTrPtrCmdTrb;
+} XHCI_CMD_TRB;
+
+// Transfer TRB types, Section 6.4.1
+
+typedef struct {
+ UINT64 DataBuffer;
+
+ UINT32 XferLength : 17;
+ UINT32 TdSize : 5;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 Isp : 1;
+ UINT32 NoSnoop : 1;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 Idt : 1;
+ UINT32 RsvdZ1 : 2;
+ UINT32 Bei : 1;
+ UINT32 TrbType : 6;
+ UINT32 Rsvd2 : 16;
+} XHCI_NORMAL_XFR_TRB;
+
+#define XHCI_XFER_TYPE_NO_DATA 0
+#define XHCI_XFER_TYPE_DATA_OUT 2
+#define XHCI_XFER_TYPE_DATA_IN 3
+
+typedef struct {
+ UINT8 bmRequestType;
+ UINT8 bRequest;
+ UINT16 wValue;
+ UINT16 wIndex;
+ UINT16 wLength;
+
+ UINT32 XferLength : 17;
+ UINT32 RsvdZ1 : 5;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 RsvdZ2 : 4;
+ UINT32 Ioc : 1;
+ UINT32 Idt : 1;
+ UINT32 RsvdZ3 : 3;
+ UINT32 TrbType : 6;
+ UINT32 Trt : 2;
+ UINT32 RsvdZ4 : 14;
+} XHCI_SETUP_XFR_TRB;
+
+typedef struct {
+ UINT64 DataBuffer;
+
+ UINT32 XferLength : 17;
+ UINT32 TdLength : 5;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 Isp : 1;
+ UINT32 NoSnoop : 1;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 Idt : 1;
+ UINT32 RsvdZ1 : 3;
+ UINT32 TrbType : 6;
+ UINT32 Dir : 1;
+ UINT32 Rsvd2 : 15;
+} XHCI_DATA_XFR_TRB;
+
+typedef struct {
+ UINT64 RsvdZ1;
+
+ UINT32 RsvdZ2 : 22;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 RsvdZ3 : 2;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 RsvdZ4 : 4;
+ UINT32 TrbType : 6;
+ UINT32 Dir : 1;
+ UINT32 Rsvd2 : 15;
+} XHCI_STATUS_XFR_TRB;
+
+typedef struct {
+ UINT64 DataBuffer;
+
+ UINT32 XferLength : 17;
+ UINT32 TdLength : 5;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 Isp : 1;
+ UINT32 NoSnoop : 1;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 Idt : 1;
+ UINT32 RsvdZ1 : 3;
+ UINT32 TrbType : 6;
+ UINT32 Rsvd2 : 4;
+ UINT32 FrameId : 11;
+ UINT32 Sia : 1;
+} XHCI_ISOCH_XFR_TRB;
+
+typedef struct {
+ UINT64 RsvdZ1;
+
+ UINT32 RsvdZ2 : 22;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 EvalNext : 1;
+ UINT32 RsvdZ3 : 2;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 RsvdZ4 : 4;
+ UINT32 TrbType : 6;
+ UINT32 Rsvd2 : 16;
+} XHCI_NOOP_XFR_TRB;
+
+typedef union {
+ XHCI_NORMAL_XFR_TRB NormalXfrTrb;
+ XHCI_SETUP_XFR_TRB SetupXfrTrb;
+ XHCI_DATA_XFR_TRB DataXfrTrb;
+ XHCI_STATUS_XFR_TRB StatusXfrTrb;
+ XHCI_ISOCH_XFR_TRB IsockXfrTrb;
+ XHCI_NOOP_XFR_TRB NoopXfrTrb;
+} XHCI_XFR_TRB;
+
+
+// Other TRB types
+typedef struct {
+ UINT64 NextSegPtr;
+
+ UINT32 RsvdZ1 : 22;
+ UINT32 Interrupter : 10;
+
+ UINT32 CycleBit : 1;
+ UINT32 ToggleCycle : 1;
+ UINT32 RsvdZ2 : 2;
+ UINT32 Chain : 1;
+ UINT32 Ioc : 1;
+ UINT32 RsvdZ3 : 4;
+ UINT32 TrbType : 6;
+ UINT32 RsvdZ4 : 16;
+} XHCI_LINK_TRB;
+
+typedef struct {
+ XHCI_TRB *Base;
+ UINT32 Size; // #of TRBs in the ring
+ XHCI_TRB* LastTrb;
+ XHCI_TRB* QueuePtr;
+ UINT8 CycleBit;
+ UINT8 Pad[27-3*sizeof(VOID*)]; // Make size 32 Bytes
+} TRB_RING;
+
+// The following definition fixes the size of ring
+// segment to TRBS_PER_SEGMENT * sizeof(XHCI_TRB)
+#define TRBS_PER_SEGMENT 64
+#define RING_SIZE TRBS_PER_SEGMENT*sizeof(XHCI_TRB)
+
+// Default timeouts
+#define XHCI_CMD_COMPLETE_TIMEOUT_MS 500
+#define XHCI_CTL_COMPLETE_TIMEOUT_MS 2000
+#define XHCI_BULK_COMPLETE_TIMEOUT_MS 10000
+#define XHCI_INT_COMPLETE_TIMEOUT_MS 1500
+
+//#define XHCI_BOT_TD_MAXSIZE 512
+#define XHCI_BOT_TD_MAXSIZE 0x10000
+#define XHCI_BOT_MAX_XFR_SIZE XHCI_BOT_TD_MAXSIZE*8
+
+typedef struct {
+ UINT32 RouteString : 20;
+ UINT32 Speed : 4;
+ UINT32 RsvdZ1 : 1;
+ UINT32 MultiTT : 1;
+ UINT32 Hub : 1;
+ UINT32 ContextEntries : 5;
+
+ UINT32 MaxExitLatency : 16;
+ UINT32 RootHubPort : 8;
+ UINT32 PortsNum : 8;
+
+ UINT32 TtHubSlotId : 8;
+ UINT32 TtPortNumber : 8;
+ UINT32 TThinkTime : 2;
+ UINT32 RsvdZ3 : 4;
+ UINT32 Interrupter : 10;
+
+ UINT32 DevAddr : 8;
+ UINT32 RsvdZ4 : 19;
+ UINT32 SlotState : 5;
+
+ UINT32 RsvdO[4];
+} XHCI_SLOT_CONTEXT;
+
+// XHCI_SLOT_CONTEXT.DW3.SlotState definitions
+#define XHCI_SLOT_STATE_DISABLED 0
+#define XHCI_SLOT_STATE_DEFAULT 1
+#define XHCI_SLOT_STATE_ADDRESSED 2
+#define XHCI_SLOT_STATE_CONFIGURED 3
+
+// Endpoint types, Table 57
+#define XHCI_EPTYPE_NOT_VALID 0
+#define XHCI_EPTYPE_ISOCH_OUT 1
+#define XHCI_EPTYPE_BULK_OUT 2
+#define XHCI_EPTYPE_INT_OUT 3
+#define XHCI_EPTYPE_CTL 4
+#define XHCI_EPTYPE_ISOCH_IN 5
+#define XHCI_EPTYPE_BULK_IN 6
+#define XHCI_EPTYPE_INT_IN 7
+
+typedef struct {
+ UINT32 EpState : 3;
+ UINT32 RsvdZ1 : 5;
+ UINT32 Mult : 2;
+ UINT32 MaxPStreams : 5;
+ UINT32 Lsa : 1;
+ UINT32 Interval : 8;
+ UINT32 RzvdZ2 : 8;
+
+ UINT32 ForceEvent : 1;
+ UINT32 ErrorCount : 2;
+ UINT32 EpType : 3;
+ UINT32 RsvdZ : 1;
+ UINT32 Hid : 1;
+ UINT32 MaxBurstSize : 8;
+ UINT32 MaxPacketSize : 16;
+
+ UINT64 TrDequeuePtr; // BIT0 of this field is DCS (Dequeue Cycle State)
+ UINT16 AvgTrbLength;
+ UINT16 MaxEsitPayload;
+ UINT32 RsvdO[3];
+} XHCI_EP_CONTEXT;
+
+typedef struct {
+ UINT32 DropContextFlags;
+ UINT32 AddContextFlags;
+ UINT32 RzvdZ[6];
+} XHCI_INPUT_CONTROL_CONTEXT;
+
+typedef struct {
+ XHCI_SLOT_CONTEXT Slot;
+ XHCI_EP_CONTEXT Ep[31];
+} XHCI_DEVICE_CONTEXT;
+
+#define XHCI_DEVICE_CONTEXT_ENTRIES 32
+
+typedef struct {
+ XHCI_INPUT_CONTROL_CONTEXT CtlCtx;
+ XHCI_DEVICE_CONTEXT DevCtx;
+} XHCI_INPUT_CONTEXT;
+
+#define XHCI_INPUT_CONTEXT_ENTRIES 33
+
+ //(EIP75547+)>
+//---------------------------------------------------------
+// Extended Capabilities
+//---------------------------------------------------------
+#define XHCI_EXT_CAP_USB_LEGACY 1
+#define XHCI_EXT_CAP_SUPPORTED_PROTOCOL 2
+#define XHCI_EXT_CAP_POWERMANAGEMENT 3
+#define XHCI_EXT_CAP_IO_VIRTUALIZATION 4
+#define XHCI_EXT_CAP_USB_DEBUG_PORT 10
+
+typedef struct {
+ UINT32 CapId:8; // Capability ID
+ UINT32 NextCapPtr:8; // Next xHCI Extended Capability Pointer
+ UINT32 Cap:16; // Capability Specific
+} XHCI_EXT_CAP;
+ //<(EIP75547+)
+
+typedef struct {
+ UINT64 ScratchpadBufArrayPtr;
+ UINT64 DevCntxtAddr[255];
+} XHCI_DCBAA; // Total size is 256 64-bit entries, or 2K Bytes (section 6.1)
+// XHCI PCI Configuration Registers
+//---------------------------------------------------------------------------
+
+// Serial Bus Release Number Register
+#define XHCI_PCI_SBRN 0x60
+
+// Frame Length Adjustment Register
+#define XHCI_PCI_FLADJ 0x61
+
+// Host Controller Capability Registers
+//---------------------------------------------------------------------------
+
+typedef struct {
+ UINT32 MaxSlots : 8; // Number of Device Slots
+ UINT32 MaxIntrs : 11; // Number of Interrupters
+ UINT32 Rsvd : 5; // Reserved
+ UINT32 MaxPorts : 8; // Number of ports
+} HCPARAMS1;
+
+typedef struct {
+ UINT32 Ist : 4; // Isochronous Scheduling Threshold
+ UINT32 ErstMax : 4; // Event Ring Segment Table Max
+ UINT32 Rsvd : 18;
+ UINT32 Spr : 1; // Scratchpad restore
+ UINT32 MaxScratchPadBufs : 5; // Number of scratchpad buffers
+} HCPARAMS2;
+
+typedef struct {
+ UINT32 U1DevExitLatency : 8; // Worst case latency of U1->U0, mks
+ UINT32 Rsvd : 8;
+ UINT32 U2DevExitLatency : 16; // Worst case latency of U2->U0, mks
+} HCPARAMS3;
+
+typedef struct {
+ UINT32 Ac64 : 1; // 64-bit Addressing Capability
+ UINT32 Bnc : 1; // Bandwidth Negotiation Capability
+ UINT32 Csz : 1; // Context data structures width (32 or 64 bit)
+ UINT32 Ppc : 1; // Power Port Control
+ UINT32 Pind : 1; // Port Indicators
+ UINT32 Lhrc : 1; // Light HC Reset Capability
+ UINT32 Ltc : 1; // Latency Tolerance Capability
+ UINT32 Nss : 1; // No Secondary SID Support
+ UINT32 Rsvd : 4;
+ UINT32 MaxPsaSize : 4; // Maximum Primary Stream Array Size
+ UINT32 Xecp : 16; // xHCI Extended Capabilities Pointer
+} HCPARAMS;
+
+typedef struct {
+ UINT8 CapLength; // 00
+ UINT8 Rsvd; // 01
+ UINT16 HciVersion; // 02
+ HCPARAMS1 HcParams1; // 04
+ HCPARAMS2 HcParams2; // 08
+ HCPARAMS3 HcParams3; // 0C
+ HCPARAMS HcParams; // 10
+ UINT32 DbOff; // 14
+ UINT32 RtsOff; // 18
+} XHCI_HC_CAP_REGS;
+
+//-----------------------------------------------------------
+// Host Controller Operational Registers
+//-----------------------------------------------------------
+typedef struct {
+ UINT32 RunStop : 1;
+ UINT32 HcRst : 1; // HC Reset
+ UINT32 Inte : 1; // Interrupter Enable
+ UINT32 HsEe : 1; // Host System Error Enable
+ UINT32 Rsvd : 3;
+ UINT32 LhcRst : 1; // Light Host Controller Reset
+ UINT32 Css : 1; // Controller Save State
+ UINT32 Crs : 1; // Controller Restore State
+ UINT32 Ewe : 1; // Enable Wrap Event
+ UINT32 Eu3S : 1; // Enable U3 MFINDEX Stop
+ UINT32 Rsvd1 : 20;
+} XHCI_USBCMD;
+
+typedef struct {
+ union {
+ UINT32 AllBits; // can be used for clearing status
+ #define XHCI_STS_HALTED BIT0
+ #define XHCI_STS_HOSTSYSTEM_ERROR BIT2
+ #define XHCI_STS_EVT_INTERRUPT BIT3
+ #define XHCI_STS_PCD BIT4
+ struct {
+ UINT32 HcHalted : 1;
+ UINT32 Rsvd1 : 1;
+ UINT32 Hse : 1; // Host System Error
+ UINT32 Eint : 1; // Event Interrupt
+ UINT32 Pcd : 1; // Port Change Detect
+ UINT32 Rsvd2 : 3;
+ UINT32 Sss : 1; // Save State Status
+ UINT32 Rss : 1; // Restore State Status
+ UINT32 Sre : 1; // Save/Restore Error
+ UINT32 Cnr : 1; // Controller Not Ready
+ UINT32 Hce : 1; // Host Controller Error
+ UINT32 Rsvd3 : 19;
+ } Field;
+ };
+} XHCI_USBSTS;
+
+typedef struct {
+ UINT32 Rcs : 1; // Ring Cycle State
+ UINT32 Cs : 1; // Command Stop
+ UINT32 Ca : 1; // Command Abort
+ UINT32 Crr : 1; // Command Ring Running
+ UINT32 Rsvd : 2;
+ UINT32 CrPointer : 26; // Command Ring Pointer
+} XHCI_CRCR;
+
+#define XHCI_PORT_CONNECT BIT0
+#define XHCI_PORT_ENABLE BIT1
+#define XHCI_PORT_RESET BIT4
+#define XHCI_PORT_RESET_CHG BIT21
+
+#define XHCI_PORTSC_OFFSET 0x400
+
+// Port speed definitions as read from PortSpeed field of PORTSC
+#define XHCI_DEVSPEED_UNDEFINED 0
+#define XHCI_DEVSPEED_FULL 1
+#define XHCI_DEVSPEED_LOW 2
+#define XHCI_DEVSPEED_HIGH 3
+#define XHCI_DEVSPEED_SUPER 4
+
+typedef struct {
+ union {
+ UINT32 AllBits; // can be used for clearing status
+ #define XHCI_PCS_CCS BIT0
+ #define XHCI_PCS_PED BIT1
+ #define XHCI_PCS_OCA BIT3
+ #define XHCI_PCS_PR BIT4
+ #define XHCI_PCS_PP BIT9
+ #define XHCI_PCS_CSC BIT17
+ #define XHCI_PCS_PEC BIT18
+ #define XHCI_PCS_WRC BIT19 //(EIP75547+)
+ #define XHCI_PCS_OCC BIT20
+ #define XHCI_PCS_PRC BIT21
+ #define XHCI_PCS_WPR BIT31 //(EIP75547+)
+ struct {
+ UINT32 Ccs : 1; // 0 Current Connect Status - RO
+ UINT32 Ped : 1; // 1 Port Enabled/Disabled - RW1CS
+ UINT32 RsvdZ1 : 1; // 2
+ UINT32 Oca : 1; // 3 Over-current Active - RO
+ UINT32 Pr : 1; // 4 Port Reset - RW1S
+ UINT32 Pls : 4; // 5..8 Port Link State - RWS
+ UINT32 Pp : 1; // 9 Port Power - RWS
+ UINT32 PortSpeed : 4; // 10..13 Port Speed - RO
+ UINT32 Pic : 2; // 14..15 Port Indicator Ctl - RWS
+ UINT32 Lws : 1; // 16 Port Link State Write Strobe - RW
+ UINT32 Csc : 1; // 17 Connect Status Change - RW1CS
+ UINT32 Pec : 1; // 18 Port Enabled/Disabled Change - RW1CS
+ UINT32 Wrc : 1; // 19 Warm Port Reset Change - RW1CS/RsvdZ
+ UINT32 Occ : 1; // 20 Over-current Change - RW1CS
+ UINT32 Prc : 1; // 21 Port Reset Change - RW1CS
+ UINT32 Plc : 1; // 22 Port Link State Change - RW1CS
+ UINT32 Cec : 1; // 23 Port Config Error Change - RW1CS/RsvdZ
+ UINT32 Cas : 1; // 24 Cold Attach Status - RO //(EIP75547)
+ UINT32 Wce : 1; // 25 Wake on Connect Enable - RWS
+ UINT32 Wde : 1; // 26 Wake on Disconnect Enable - RWS
+ UINT32 Woe : 1; // 27 Wake on Over-current Enable - RWS
+ UINT32 RsvdZ2 : 2; // 28..29 //(EIP75547)
+ UINT32 Dr : 1; // 30 Device Removable (0 removable) - RO
+ UINT32 Wpr : 1; // 31 Warm Port Reset - RW1S/RsvdZ
+ } Field;
+ };
+} XHCI_PORTSC;
+
+typedef struct {
+ XHCI_USBCMD UsbCmd; // 00
+ XHCI_USBSTS UsbSts; // 04
+ UINT32 PageSize; // 08
+ UINT8 Rsvd1[8]; // 0C
+ UINT32 DnCtrl; // 14 Device Notification Control
+ UINT64 Crcr; // 18 Command Ring Control
+ UINT8 Rsvd2[16]; // 20
+ UINT64 DcbAap; // 30 Device Context Base Address Array Pointer
+ UINT32 Config; // 38 Max Device Slots Enabled
+} XHCI_HC_OP_REGS;
+
+// Minimum inter-interrupt interval, in 250ns units. The value of 4000 makes 1ms interval.
+#define XHCI_IMODI 4000
+
+// Note: the following structure defines 32-bit and 64-bits fields
+// without detailing; this MMIO data must be accessed using Dword
+// access for 32-bit fields and Qword access for 64-bit, Section 5.5.
+typedef struct {
+ UINT32 IMan; // Interrupter Management
+ UINT32 IMod; // Interrupter Moderation
+ UINT32 Erstz; // Event Ring Segment Table Size
+ UINT32 RsrvP;
+ UINT64 Erstba; // Event Ring Segment Table Base Address
+ UINT64 Erdp; // Event Ring Dequeue Pointer
+} XHCI_INTERRUPTER_REGS;
+
+typedef struct {
+ UINT32 MfIndex;
+ UINT32 Reserved[7];
+ XHCI_INTERRUPTER_REGS IntRegs[1024];
+} XHCI_HC_RT_REGS;
+
+typedef enum {
+ XhciTNormal = 1,
+ XhciTSetupStage, // 2
+ XhciTDataStage, // 3
+ XhciTStatusStage,// 4
+ XhciTIsoch, // 5
+ XhciTLink, // 6
+ XhciTEventData, // 7
+ XhciTNoOp, // 8
+ XhciTEnableSlotCmd, // 9
+ XhciTDisableSlotCmd, // 10
+ XhciTAddressDeviceCmd, // 11
+ XhciTConfigureEndpointCmd, //12
+ XhciTEvaluateContextCmd, //13
+ XhciTResetEndpointCmd, //14
+ XhciTStopEndpointCmd, // 15
+ XhciTSetTRDequeuePointerCmd, //16
+ XhciTResetDeviceCmd, // 17
+ XhciTForceEventCmd, // 18
+ XhciTNegotiateBandwidthCmd, // 19
+ XhciTSetLatencyToleranceCmd, // 20
+ XhciTGetPortBandwidthCmd, // 21
+ XhciTForceHeaderCmd, // 22
+ XhciTNoOpCmd, // 23
+// 24..31 reserved
+ XhciTTransferEvt = 32,
+ XhciTCmdCompleteEvt, // 33
+ XhciTPortStatusChgEvt, // 34
+ XhciTBandwidthRequestEvt, // 35
+ XhciTDoorbellEvt, // 36
+ XhciTHostControllerEvt, // 37
+ XhciTDevNotificationEvt, // 38
+ XhciTMfIndexWrapEvt // 39
+} TRB_TYPE;
+
+typedef struct {
+ UINT64 RsBase;
+ UINT16 RsSize;
+ UINT16 Rsvd1;
+ UINT32 Rsvd2;
+} XHCI_ER_SEGMENT_ENTRY;
+
+#define CRCR_RING_CYCLE_STATE BIT0
+
+#define TRBS_PER_SEGMENT 64
+#define RING_SIZE TRBS_PER_SEGMENT*sizeof(XHCI_TRB)
+
+typedef struct {
+ UINT8 SlotId;
+ UINT8 DevAddr;
+} PEI_XHCI_SLOTADDR_MAP;
+
+// Note that MaxSlots affects the size of USB3_CONTROLLER structure as
+// well as its data boundaries and alignment. Default value is 32; if a
+// different value needs to be assigned, make sure that boundaries and
+// alignment meets the requirements; do the padding as needed.
+// See XHCI specification Chapter 6 for the details.
+
+#define PEI_XHCI_MAX_SLOTS 32
+
+ //(EIP75547+)>
+typedef struct {
+ struct {
+ UINT32 CapId:8;
+ UINT32 NextCapPtr:8;
+ UINT32 MinorRev:8;
+ UINT32 MajorRev:8;
+ };
+
+ UINT32 NameString;
+
+ struct {
+ UINT32 PortOffset:8;
+ UINT32 PortCount:8;
+ UINT32 L1c:1; // L1 Capability
+ UINT32 Hso:1; // High-speed Only
+ UINT32 Ihi:1; // Integrated Hub Implemented
+ UINT32 RsvdZ:13;
+ };
+} XHCI_EXT_PROTOCOL;
+ //<(EIP75547+)
+
+typedef struct _USB3_CONTROLLER {
+ UINTN Dcbaa[PEI_XHCI_MAX_SLOTS]; // 32*4 = 128
+ UINT8 XfrTrb[RING_SIZE*PEI_XHCI_MAX_SLOTS*32];
+ UINT8 CommandRing[RING_SIZE];
+ UINT8 EventRing[RING_SIZE];
+
+ UINT8 DevCtx[PEI_XHCI_MAX_SLOTS * 0x800];
+ UINT8 InpCtx[0x840];
+ XHCI_ER_SEGMENT_ENTRY Erst;
+
+ UINT16 Vid;
+ UINT16 Did;
+ BOOLEAN Access64;
+ UINT16 HciVersion;
+ UINT8 MaxPorts;
+ UINT32 PageSize4K;
+ UINT8 ContextSize;
+ UINT16 MaxIntrs;
+ UINT32 DbOffset;
+ UINT8 MaxSlots;
+ VOID *InputContext;
+ TRB_RING CmdRing;
+ TRB_RING EvtRing;
+ TRB_RING XfrRing[PEI_XHCI_MAX_SLOTS*32]; // 32 endpoints per device
+ TRB_RING *XfrRings;
+ UINTN XfrTrbs;
+ VOID *DeviceContext;
+ XHCI_DCBAA *DcbaaPtr;
+ XHCI_HC_CAP_REGS *CapRegs;
+ XHCI_HC_OP_REGS *OpRegs;
+ XHCI_HC_RT_REGS *RtRegs;
+ XHCI_EXT_PROTOCOL *Usb2Protocol; //(EIP75547+)
+ XHCI_EXT_PROTOCOL *Usb3Protocol; //(EIP75547+)
+
+ PEI_XHCI_SLOTADDR_MAP DeviceMap[PEI_XHCI_MAX_SLOTS];
+
+ EFI_PEI_SERVICES **PeiServices;
+ PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi;
+ EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
+ EFI_PEI_CPU_IO_PPI *CpuIoPpi;
+ EFI_PEI_STALL_PPI *StallPpi;
+ EFI_PEI_PCI_CFG_PPI *PciCfgPpi;
+
+} USB3_CONTROLLER;
+
+#pragma pack(pop)
+
+//----------------------------------------------------------------------------
+// Function prototypes
+//----------------------------------------------------------------------------
+EFI_STATUS XhciHcControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT8 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data OPTIONAL,
+ IN OUT UINTN *DataLength OPTIONAL,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult );
+
+EFI_STATUS XhciHcBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINT16 MaximumPacketLength,
+ IN UINT16 TransactionTranslator OPTIONAL,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult );
+
+EFI_STATUS XhciHcGetRootHubPortNumber (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ OUT UINT8 *PortNumber );
+
+EFI_STATUS XhciHcGetRootHubPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus );
+
+EFI_STATUS XhciHcSetRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature );
+
+EFI_STATUS XhciHcClearRootHubPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature );
+
+EFI_STATUS XhciInitHC(
+ EFI_PEI_SERVICES **PeiServices,
+ struct _USB3_CONTROLLER *Usb3Hc,
+ UINT8 ControllerIndex);
+
+EFI_STATUS XhciHcPreConfigureDevice(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 Port,
+ IN UINT8 Speed,
+ IN UINT16 TransactionTranslator);
+
+EFI_STATUS XhciEnableEndpoints (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This,
+ IN UINT8 *Desc);
+
+VOID
+XhciMmio64Write(
+ USB3_CONTROLLER *Usb3Hc,
+ UINTN Address,
+ UINT64 Data);
+
+EFI_STATUS XhciInitRing(TRB_RING*, UINTN, UINT32, BOOLEAN);
+EFI_STATUS XhciExecuteCommand(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc,
+ TRB_TYPE Cmd,
+ VOID *Params
+);
+
+TRB_RING*
+XhciInitXfrRing(
+ USB3_CONTROLLER* Usb3Hc,
+ UINT8 Slot,
+ UINT8 Ep);
+
+EFI_STATUS
+UpdateDeviceMap(
+ PEI_XHCI_SLOTADDR_MAP *DeviceMap,
+ UINT8 SlotId,
+ UINT8 DevAddr);
+
+EFI_STATUS
+GetSlotId(
+ PEI_XHCI_SLOTADDR_MAP *DeviceMap,
+ UINT8 *SlotId,
+ UINT8 DevAddr);
+
+EFI_STATUS Stall(EFI_PEI_SERVICES**, EFI_PEI_STALL_PPI*, UINTN);
+EFI_STATUS CountTime(UINT, UINT16);
+EFI_STATUS XhciInitDeviceData (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *This
+// HC_STRUC *HcStruc,
+// DEV_INFO *DevInfo,
+// UINT8 PortStatus,
+// UINT8 **DeviceData
+);
+
+TRB_RING* XhciGetXfrRing(
+ USB3_CONTROLLER* Usb3Hc,
+ UINT8 Slot,
+ UINT8 Ep);
+
+UINT32* XhciGetTheDoorbell(
+ USB3_CONTROLLER *Usb3Hc,
+ UINT8 SlotId);
+
+XHCI_TRB* XhciAdvanceEnqueuePtr(
+ TRB_RING *Ring);
+
+EFI_STATUS XhciWaitForEvent(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc,
+ XHCI_TRB *TrbToCheck,
+ TRB_TYPE EventType,
+ UINT8 *CompletionCode,
+ UINT16 TimeOutMs,
+ VOID *Data
+);
+
+UINT8*
+XhciGetDeviceContext(
+ USB3_CONTROLLER *Usb3Hc,
+ UINT8 SlotId
+);
+
+UINT8*
+XhciGetContextEntry(
+ USB3_CONTROLLER *Usb3Hc,
+ VOID *Context,
+ UINT8 Index
+);
+
+ //(EIP75547+)>
+VOID
+XhciResetUsb2Port(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc
+);
+
+EFI_STATUS
+XhciExtCapParser(
+ EFI_PEI_SERVICES **PeiServices,
+ USB3_CONTROLLER *Usb3Hc
+);
+ //<(EIP75547+)
+
+#define _CR( Record, TYPE, Field ) \
+ ( (TYPE *) ( (CHAR8 *) (Record) - (CHAR8 *) &( ( (TYPE *) 0 )->Field ) ) )
+#define PEI_RECOVERY_USB_XHCI_DEV_FROM_THIS( a ) \
+ _CR( a, USB3_CONTROLLER, UsbHostControllerPpi )
+
+#endif // _XHCIPEI_H
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/UsbRecovery/usb.h b/Core/EM/UsbRecovery/usb.h
new file mode 100644
index 0000000..3d120cf
--- /dev/null
+++ b/Core/EM/UsbRecovery/usb.h
@@ -0,0 +1,511 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/usb.h 10 8/23/12 10:02p Wilsonlee $
+//
+// $Revision: 10 $
+//
+// $Date: 8/23/12 10:02p $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/usb.h $
+//
+// 10 8/23/12 10:02p Wilsonlee
+// [TAG] EIP97069
+// [Category] Improvement
+// [Description] Reset root port algorythm update.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// UhcPeim.h, UsbPeim.c, usb.h
+//
+// 9 1/18/11 1:03a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 8 10/11/10 4:51p Olegi
+// XHCI support added.
+//
+// 7 4/06/10 3:35p Fasihm
+// EIP#31987 - Added the generic USBRecovery Fix in the module.
+//
+// 6 11/16/09 1:49p Fasihm
+// Corrected the order of the enum constants in EFI_USB_DATA_DIRECTION.
+//
+// 5 3/17/09 5:10p Olegi
+//
+// 4 7/18/08 5:03p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 3 7/10/08 6:33p Michaela
+// Updated to support OHCI controllers
+//
+// 2 10/23/07 4:39p Ambikas
+//
+// 1 9/22/06 4:07p Sivagarn
+// - Initial Check-in
+// - Included Recovery code in Source
+// - Included appropriate headers for flies and functions
+// - Updated copyright messages
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: USB.H
+//
+// Description: This file belongs to "Framework" and included here for
+// compatibility purposes. This file is modified by AMI to include
+// copyright message and appropriate header
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//
+// This file contains 'Framework Code' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may not be modified, except as allowed by
+// additional terms of your license agreement.
+//
+#ifndef _USB_H
+#define _USB_H
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ usb.h
+
+ Abstract:
+ Support for USB 1.1 standard.
+
+
+
+
+ Revision History
+
+ --*/
+
+// BIT(a) defines a value with one bit set as specified by a.
+#ifndef BIT
+#define BIT( a ) (1 << (a))
+#endif
+
+
+// MASK(high,low) defines a bit mask value with bits set in the bit
+// range specified from high down to low (zero-based)
+#ifndef MASK
+#define MAX_VAL 0xffffffff // maximum value supported by CPU
+#define MAX_BIT 31 // highest bit position in MAX_VAL
+#define MASK( high, low ) (\
+ ( MAX_VAL >> ( MAX_BIT - ( (high) - (low) ) ) ) \
+ << (low) \
+)
+#endif
+
+
+// READ_BITS(src,high,low) extracts a bit field shifted down to bit
+// position 0 from src, where high and low define the bit range
+// (zero-based).
+#ifndef READ_BITS
+#define READ_BITS( src, high, low ) (\
+ ( (src) & MASK( (high), (low) ) ) \
+ >> (low) \
+)
+#endif
+
+// return the modified src after writing a bit field with val, where the bit
+// field's range is specified by high down to low
+// (Note, the user must ensure that the val fits in the bit range)
+#ifndef WRITE_BITS
+#define WRITE_BITS( src, val, high, low ) (\
+ ( (src) & ~MASK( (high), (low) ) ) \
+ | ( (val) << (low) ) \
+)
+#endif
+
+//
+// USB Descriptor types
+//
+#define USB_DT_DEVICE 0x01
+#define USB_DT_CONFIG 0x02
+#define USB_DT_STRING 0x03
+#define USB_DT_INTERFACE 0x04
+#define USB_DT_ENDPOINT 0x05
+#define USB_DT_HUB 0x29
+#define USB_DT_SS_HUB 0x2A
+#define USB_DT_HID 0x21
+
+#define SET_DESCRIPTOR_TYPE( x ) WRITE_BITS( 0x0, x, 15, 8 )
+
+//
+// USB request type
+//
+#define USB_TYPE_STANDARD (0x00 << 5)
+#define USB_TYPE_CLASS (0x01 << 5)
+#define USB_TYPE_VENDOR (0x02 << 5)
+#define USB_TYPE_RESERVED (0x03 << 5)
+
+//
+// USB request targer device
+//
+#define USB_RECIP_DEVICE 0x00
+#define USB_RECIP_INTERFACE 0x01
+#define USB_RECIP_ENDPOINT 0x02
+#define USB_RECIP_OTHER 0x03
+
+//
+// Request target types.
+//
+#define USB_RT_DEVICE 0x00
+#define USB_RT_INTERFACE 0x01
+#define USB_RT_ENDPOINT 0x02
+#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
+#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
+
+
+//
+// USB Transfer Results
+//
+#define EFI_USB_NOERROR 0x00
+#define EFI_USB_ERR_NOTEXECUTE 0x01
+#define EFI_USB_ERR_STALL 0x02
+#define EFI_USB_ERR_BUFFER 0x04
+#define EFI_USB_ERR_BABBLE 0x08
+#define EFI_USB_ERR_NAK 0x10
+#define EFI_USB_ERR_CRC 0x20
+#define EFI_USB_ERR_TIMEOUT 0x40
+#define EFI_USB_ERR_BITSTUFF 0x80
+#define EFI_USB_ERR_SYSTEM 0x100
+
+static CHAR8 *gUsbErrorStrings[] =
+{
+ "EFI_USB_ERR_NOTEXECUTE",
+ "EFI_USB_ERR_STALL",
+ "EFI_USB_ERR_BUFFER",
+ "EFI_USB_ERR_BABBLE",
+ "EFI_USB_ERR_NAK",
+ "EFI_USB_ERR_CRC",
+ "EFI_USB_ERR_TIMEOUT",
+ "EFI_USB_ERR_BITSTUFF",
+ "EFI_USB_ERR_SYSTEM"
+};
+
+#define EFI_USB_INTERRUPT_DELAY 0x10000000
+
+#define EFI_USB_STALL_ERROR \
+ (EFI_USB_ERR_STALL | EFI_USB_ERR_CRC | \
+ EFI_USB_ERR_TIMEOUT | EFI_USB_ERR_BABBLE)
+
+//
+// USB transation direction
+//
+typedef enum {
+ EfiUsbDataIn,
+ EfiUsbDataOut,
+ EfiUsbNoData
+} EFI_USB_DATA_DIRECTION;
+
+//
+// This is how UsbData in/out described in USB spec.
+//
+typedef enum {
+ UsbDataOut,
+ UsbDataIn,
+ UsbNoData
+} USB_DATA_DIRECTION;
+
+//
+// Usb Data recipient type
+//
+typedef enum {
+ EfiUsbDevice,
+ EfiUsbInterface,
+ EfiUsbEndpoint
+} EFI_USB_RECIPIENT;
+
+typedef enum {
+ EfiUsbEndpointHalt,
+ EfiUsbDeviceRemoteWakeup
+} EFI_USB_STANDARD_FEATURE_SELECTOR;
+
+#pragma pack(push,1)
+
+//
+// Usb device request structure
+//
+typedef struct
+{
+ UINT8 RequestType;
+ UINT8 Request;
+ UINT16 Value;
+ UINT16 Index;
+ UINT16 Length;
+} EFI_USB_DEVICE_REQUEST;
+
+
+//
+// Standard USB request
+//
+#define USB_DEV_GET_STATUS 0x00
+
+#define USB_DEV_CLEAR_FEATURE 0x01
+
+#define USB_DEV_SET_FEATURE 0x03
+
+#define USB_DEV_SET_ADDRESS 0x05
+#define USB_DEV_SET_ADDRESS_REQ_TYPE 0x00
+
+#define USB_DEV_GET_DESCRIPTOR 0x06
+#define USB_DEV_GET_DESCRIPTOR_REQ_TYPE 0x80
+
+#define USB_DEV_SET_DESCRIPTOR 0x07
+#define USB_DEV_SET_DESCRIPTOR_REQ_TYPE 0x00
+
+#define USB_DEV_GET_CONFIGURATION 0x08
+#define USB_DEV_GET_CONFIGURATION_REQ_TYPE 0x80
+
+#define USB_DEV_SET_CONFIGURATION 0x09
+#define USB_DEV_SET_CONFIGURATION_REQ_TYPE 0x00
+
+#define USB_DEV_GET_INTERFACE 0x0a
+#define USB_DEV_GET_INTERFACE_REQ_TYPE 0x81
+
+#define USB_DEV_SET_INTERFACE 0x0b
+#define USB_DEV_SET_INTERFACE_REQ_TYPE 0x01
+
+#define USB_DEV_SYNCH_FRAME 0x0c
+#define USB_DEV_SYNCH_FRAME_REQ_TYPE 0x82
+
+
+//
+// Device descriptor. refer USB1.1
+//
+typedef struct usb_device_descriptor
+{
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT16 BcdUSB;
+ UINT8 DeviceClass;
+ UINT8 DeviceSubClass;
+ UINT8 DeviceProtocol;
+ UINT8 MaxPacketSize0;
+ UINT16 IdVendor;
+ UINT16 IdProduct;
+ UINT16 BcdDevice;
+ UINT8 StrManufacturer;
+ UINT8 StrProduct;
+ UINT8 StrSerialNumber;
+ UINT8 NumConfigurations;
+} EFI_USB_DEVICE_DESCRIPTOR;
+
+//
+// Endpoint descriptor
+//
+typedef struct
+{
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 EndpointAddress;
+ UINT8 Attributes;
+ UINT16 MaxPacketSize;
+ UINT8 Interval;
+} EFI_USB_ENDPOINT_DESCRIPTOR;
+
+//
+// Interface descriptor
+//
+typedef struct
+{
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 InterfaceNumber;
+ UINT8 AlternateSetting;
+ UINT8 NumEndpoints;
+ UINT8 InterfaceClass;
+ UINT8 InterfaceSubClass;
+ UINT8 InterfaceProtocol;
+ UINT8 Interface;
+} EFI_USB_INTERFACE_DESCRIPTOR;
+
+//
+// USB alternate setting
+//
+typedef struct
+{
+ EFI_USB_INTERFACE_DESCRIPTOR *Interface;
+} USB_ALT_SETTING;
+
+//
+// Configuration descriptor
+//
+typedef struct
+{
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT16 TotalLength;
+ UINT8 NumInterfaces;
+ UINT8 ConfigurationValue;
+ UINT8 Configuration;
+ UINT8 Attributes;
+ UINT8 MaxPower;
+} EFI_USB_CONFIG_DESCRIPTOR;
+
+//
+// Supported String Languages
+//
+typedef struct
+{
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT16 SupportedLanID[1];
+} EFI_USB_SUPPORTED_LANGUAGES;
+
+//
+// String descriptor
+//
+typedef struct
+{
+ UINT8 Length;
+ UINT8 DescriptorType;
+ CHAR16 String[1];
+} EFI_USB_STRING_DESCRIPTOR;
+
+//
+// Hub descriptor
+//
+//#define MAXBYTES 8
+typedef struct
+{
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 NbrPorts;
+ UINT8 HubCharacteristics[2];
+ UINT8 PwrOn2PwrGood;
+ UINT8 HubContrCurrent;
+ UINT8 HubHdrDecLat;
+ UINT16 HubDelay;
+ UINT16 DeviceRemovable;
+} EFI_USB_HUB_DESCRIPTOR;
+
+typedef struct
+{
+ UINT16 PortStatus;
+ UINT16 PortChangeStatus;
+} EFI_USB_PORT_STATUS;
+
+//
+// Constant value for Port Status & Port Change Status
+//
+#define USB_PORT_STAT_CONNECTION BIT(0)
+#define USB_PORT_STAT_ENABLE BIT(1)
+#define USB_PORT_STAT_SUSPEND BIT(2)
+#define USB_PORT_STAT_OVERCURRENT BIT(3)
+#define USB_PORT_STAT_RESET BIT(4)
+#define USB_PORT_STAT_POWER BIT(8)
+#define USB_PORT_STAT_LOW_SPEED BIT(9)
+#define USB_PORT_STAT_HIGH_SPEED BIT(10)
+#define USB_PORT_STAT_SUPER_SPEED BIT(11)
+#define USB_PORT_STAT_OWNER BIT(13)
+
+#define USB_PORT_STAT_C_CONNECTION BIT(0)
+#define USB_PORT_STAT_C_ENABLE BIT(1)
+#define USB_PORT_STAT_C_SUSPEND BIT(2)
+#define USB_PORT_STAT_C_OVERCURRENT BIT(3)
+#define USB_PORT_STAT_C_RESET BIT(4)
+
+//
+// Used for set/clear port feature request
+//
+typedef enum {
+ EfiUsbPortConnection = 0,
+ EfiUsbPortEnable = 1,
+ EfiUsbPortSuspend = 2,
+ EfiUsbPortOverCurrent = 3,
+ EfiUsbPortReset = 4,
+ EfiUsbPortLinkState = 5,
+ EfiUsbPortPower = 8,
+ EfiUsbPortOwner = 13,
+ EfiUsbPortConnectChange = 16,
+ EfiUsbPortEnableChange = 17,
+ EfiUsbPortSuspendChange = 18,
+ EfiUsbPortOverCurrentChange = 19,
+ EfiUsbPortResetChange = 20,
+ EfiUsbPortTest = 21,
+ EfiUsbPortIndicator = 22,
+ EfiUsbPortU1Timeout = 23,
+ EfiUsbPortU2Timeout = 24,
+ EfiUsbPortLinkStateChange = 25,
+ EfiUsbPortConfigErrorChange = 26,
+ EfiUsbPortRemoteWakeMask = 27,
+ EfiUsbPortBhPortReset = 28,
+ EfiUsbPortBhPortResetChange = 29,
+ EfiUsbPortForceLinkPmAccept = 30
+} EFI_USB_PORT_FEATURE;
+
+#pragma pack(pop)
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//********************************************************************** \ No newline at end of file