summaryrefslogtreecommitdiff
path: root/Core/EM/UsbRecovery/OhciPEI
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/UsbRecovery/OhciPEI')
-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
4 files changed, 2884 insertions, 0 deletions
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