From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- Core/EM/UsbRecovery/AmiMapping.h | 102 + Core/EM/UsbRecovery/EhciPEI/EhciPei.c | 1847 +++++++++++ Core/EM/UsbRecovery/EhciPEI/EhciPei.cif | 10 + Core/EM/UsbRecovery/EhciPEI/EhciPei.h | 592 ++++ Core/EM/UsbRecovery/EhciPEI/EhciPeiBoard.c | 108 + Core/EM/UsbRecovery/HubPeim.h | 317 ++ Core/EM/UsbRecovery/OhciPEI/OhciPei.c | 1455 +++++++++ Core/EM/UsbRecovery/OhciPEI/OhciPei.cif | 12 + Core/EM/UsbRecovery/OhciPEI/OhciPei.h | 909 ++++++ Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c | 508 +++ Core/EM/UsbRecovery/PeiUsbLib.c | 825 +++++ Core/EM/UsbRecovery/PeiUsbLib.h | 171 ++ Core/EM/UsbRecovery/USBRecoverySrc.chm | Bin 0 -> 150255 bytes Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.c | 3575 ++++++++++++++++++++++ Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.h | 865 ++++++ Core/EM/UsbRecovery/UhcPeimSrc/UhcPeimSrc.cif | 11 + Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.c | 376 +++ Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.cif | 10 + Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.c | 482 +++ Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.h | 201 ++ Core/EM/UsbRecovery/UsbBotPeimSrc/PeiAtapi.c | 832 +++++ Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.c | 726 +++++ Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.cif | 14 + Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.dxs | 106 + Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.h | 362 +++ Core/EM/UsbRecovery/UsbBotPeimSrc/atapi.h | 418 +++ Core/EM/UsbRecovery/UsbPeim.h | 244 ++ Core/EM/UsbRecovery/UsbPeimSrc/HubPeim.c | 889 ++++++ Core/EM/UsbRecovery/UsbPeimSrc/UsbIoPeim.c | 334 ++ Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c | 1006 ++++++ Core/EM/UsbRecovery/UsbPeimSrc/UsbPeimSrc.cif | 12 + Core/EM/UsbRecovery/UsbRecov.mak | 457 +++ Core/EM/UsbRecovery/UsbRecov.sdl | 237 ++ Core/EM/UsbRecovery/UsbRecovery.cif | 24 + Core/EM/UsbRecovery/XhciPEI/XhciPei.c | 2314 ++++++++++++++ Core/EM/UsbRecovery/XhciPEI/XhciPei.cif | 9 + Core/EM/UsbRecovery/XhciPEI/XhciPei.h | 1245 ++++++++ Core/EM/UsbRecovery/usb.h | 511 ++++ 38 files changed, 22116 insertions(+) create mode 100644 Core/EM/UsbRecovery/AmiMapping.h create mode 100644 Core/EM/UsbRecovery/EhciPEI/EhciPei.c create mode 100644 Core/EM/UsbRecovery/EhciPEI/EhciPei.cif create mode 100644 Core/EM/UsbRecovery/EhciPEI/EhciPei.h create mode 100644 Core/EM/UsbRecovery/EhciPEI/EhciPeiBoard.c create mode 100644 Core/EM/UsbRecovery/HubPeim.h create mode 100644 Core/EM/UsbRecovery/OhciPEI/OhciPei.c create mode 100644 Core/EM/UsbRecovery/OhciPEI/OhciPei.cif create mode 100644 Core/EM/UsbRecovery/OhciPEI/OhciPei.h create mode 100644 Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c create mode 100644 Core/EM/UsbRecovery/PeiUsbLib.c create mode 100644 Core/EM/UsbRecovery/PeiUsbLib.h create mode 100644 Core/EM/UsbRecovery/USBRecoverySrc.chm create mode 100644 Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.c create mode 100644 Core/EM/UsbRecovery/UhcPeimSrc/UhcPeim.h create mode 100644 Core/EM/UsbRecovery/UhcPeimSrc/UhcPeimSrc.cif create mode 100644 Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.c create mode 100644 Core/EM/UsbRecovery/UhciPeiUsb/UhciPeiUsb.cif create mode 100644 Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.c create mode 100644 Core/EM/UsbRecovery/UsbBotPeimSrc/BotPeim.h create mode 100644 Core/EM/UsbRecovery/UsbBotPeimSrc/PeiAtapi.c create mode 100644 Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.c create mode 100644 Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.cif create mode 100644 Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.dxs create mode 100644 Core/EM/UsbRecovery/UsbBotPeimSrc/UsbBotPeim.h create mode 100644 Core/EM/UsbRecovery/UsbBotPeimSrc/atapi.h create mode 100644 Core/EM/UsbRecovery/UsbPeim.h create mode 100644 Core/EM/UsbRecovery/UsbPeimSrc/HubPeim.c create mode 100644 Core/EM/UsbRecovery/UsbPeimSrc/UsbIoPeim.c create mode 100644 Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c create mode 100644 Core/EM/UsbRecovery/UsbPeimSrc/UsbPeimSrc.cif create mode 100644 Core/EM/UsbRecovery/UsbRecov.mak create mode 100644 Core/EM/UsbRecovery/UsbRecov.sdl create mode 100644 Core/EM/UsbRecovery/UsbRecovery.cif create mode 100644 Core/EM/UsbRecovery/XhciPEI/XhciPei.c create mode 100644 Core/EM/UsbRecovery/XhciPEI/XhciPei.cif create mode 100644 Core/EM/UsbRecovery/XhciPEI/XhciPei.h create mode 100644 Core/EM/UsbRecovery/usb.h (limited to 'Core/EM/UsbRecovery') 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 +// +//********************************************************************** + + +// +//---------------------------------------------------------------------------- +// +// Name: AMIMAPPING.H +// +// Description: This file is the mapping header file that maps Tiano related +// equates to AMI equates +// +//---------------------------------------------------------------------------- +// + + +#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 +// +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +#include +#include +#include +#include +#include +#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; + +// +//--------------------------------------------------------------------------- +// +// 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. +// +//--------------------------------------------------------------------------- +// + +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; +} + +// +//--------------------------------------------------------------------------- +// +// 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. +//--------------------------------------------------------------------------- +// + +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; + } +} + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; + +} + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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 + +} + + +// +//--------------------------------------------------------------------------- +// +// 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. +// +//--------------------------------------------------------------------------- +// + +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; +} + +// +//---------------------------------------------------------------------------- +// +// Procedure: EhciReleasePortOwner +// +// Description: +// +// Input: +// +// Output: None +// +//---------------------------------------------------------------------------- +// + +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; +} + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; + +} + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// Procedure: EHCIInitializeQueueHead +// +// Description: This function initializes the queue head with default values +// +// Input: fpQH Pointer to queue head +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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 + } +} + + +// +//---------------------------------------------------------------------------- +// +// Procedure: EHCIStartAsyncSchedule +// +// Description: This function starts the asynchronous schedule +// +//---------------------------------------------------------------------------- +// + +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;) {} +} + + +// +//---------------------------------------------------------------------------- +// +// Procedure: EHCIStopAsyncSchedule +// +// Description: This function stops the asynchronous transfer and sets the +// asynchronous pointer to null +// +//---------------------------------------------------------------------------- +// + +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;) {} +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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; + } +} + + +// +//---------------------------------------------------------------------------- +// +// Procedure: EHCIWaitForAsyncTransferComplete +// +// Description: This function waits for asynchronous transfer completion. +// +//---------------------------------------------------------------------------- +// + +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")); +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +UINT32 +DwordReadMem(UINT32 dBaseAddr, UINT16 wOffset) +{ + return *(volatile UINT32*)(UINTN)(dBaseAddr+wOffset); +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +VOID +DwordWriteMem(UINT32 dBaseAddr, UINT16 wOffset, UINT32 dValue) +{ + *(volatile UINT32*)(UINTN)(dBaseAddr+wOffset) = dValue; +} + +// +//---------------------------------------------------------------------------- +// Procedure: NotifyOnRecoveryCapsuleLoaded +// +// Description: This routine halts the all available EHCI host controller +// +// Input: PeiServices +// dMemAddr - EHCI HC Mem_Base address +// +//---------------------------------------------------------------------------- +// +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 @@ + + name = "EhciPei" + category = ModulePart + LocalRoot = "core\em\UsbRecovery\EhciPEI\" + RefName = "EhciPei" +[files] +"EhciPei.c" +"EhciPei.h" +"EhciPeiBoard.c" + 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 +// +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +#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 +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// Name: EhciPeiBoard.c +// +// Description: This file contains routines that are board specific for +// initializing the EHCI controller in the USB Recovery module. +// +//---------------------------------------------------------------------------- +// + +#include +#include +#include +#include +#include +#include +#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 +// +//---------------------------------------------------------------------------- + + + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +// +// 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 +// +// +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +#include +#include +#include +#include +#include +#include +#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 ); + +// +//--------------------------------------------------------------------------- +// +// 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. +// +//--------------------------------------------------------------------------- +// + +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 +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; + +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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) +// +//--------------------------------------------------------------------------- +// + +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; + +} + + +// +//--------------------------------------------------------------------------- +// +// 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. +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; + +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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 +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; + +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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 @@ + + name = "OhciPei" + category = ModulePart + LocalRoot = "core\em\UsbRecovery\OhciPEI\" + RefName = "OhciPei" +[files] +"OhciPei.c" +"OhciPei.h" +"OhciPeiBoard.c" +[parts] +"OHCI PPI" + 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 +// +// +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +#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) + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +typedef struct +{ + UINT8 Bus; + UINT8 Device; + UINT8 Function; +} PCI_BUS_DEV_FUNCTION; + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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 +// +// +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// Name: OhciPeiBoard.c +// +// Description: This file contains routines that are board specific for +// initializing the OHCI controller in the USB Recovery module. +// +//---------------------------------------------------------------------------- +// + +#include +#include +#include +#include +#include +#include +#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 + + + +// +//--------------------------------------------------------------------------- +// +// 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. +// +//--------------------------------------------------------------------------- +// + +PCI_BUS_DEV_FUNCTION gOhciControllerPciTable[] = {USBR_OHCI_CONTROLLER_PCI_ADDRESS}; +UINT16 gOhciControllerCount = \ + sizeof(gOhciControllerPciTable) / sizeof(PCI_BUS_DEV_FUNCTION); + + +// +//--------------------------------------------------------------------------- +// +// 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. +// +//--------------------------------------------------------------------------- +// + +OHCI_PCI_PROGRAMMING_TABLE gOhciPciRegisterTable[] = {USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE}; +#define OHCI_PCI_REGISTER_TABLE_SIZE \ + sizeof(gOhciPciRegisterTable) / sizeof(OHCI_PCI_PROGRAMMING_TABLE) + + +// +//---------------------------------------------------------------------------- +// 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. +// +//---------------------------------------------------------------------------- +// + +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 + + + + + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +/*++ + 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" + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +VOID ZeroMem ( + OUT VOID *Buffer, + IN UINTN Size ) +{ + UINT8 *Ptr; + + Ptr = Buffer; + while (Size--) { + *(Ptr++) = 0; + } +} + + +// +//---------------------------------------------------------------------------- +// 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) +// +//---------------------------------------------------------------------------- +// + +VOID PeiCopyMem ( + OUT VOID *Destination, + IN VOID *Source, + IN UINTN Length ) +{ + CHAR8 *Destination8; + CHAR8 *Source8; + + Destination8 = Destination; + Source8 = Source; + while (Length--) { + *(Destination8++) = *(Source8++); + } +} + + +// +//--------------------------------------------------------------------------- +// +// 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) +// +//--------------------------------------------------------------------------- +// + +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 + ); + +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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 + ); + +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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 + ); + +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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 + ); +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +BOOLEAN IsPortConnect ( + IN UINT16 PortStatus ) +{ + // + // return the bit 0 value of PortStatus + // + if ( (PortStatus & USB_PORT_STAT_CONNECTION) != 0 ) { + return TRUE; + } + else { + return FALSE; + } +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: IsPortEnable +// +// Description: +// +// Input: +// +// Output: +// +//--------------------------------------------------------------------------- +// + +BOOLEAN IsPortEnable ( + IN UINT16 PortStatus ) +{ + // + // return the bit 0 value of PortStatus + // + if ( (PortStatus & USB_PORT_STAT_ENABLE) != 0 ) { + return TRUE; + } + else { + return FALSE; + } +} + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +BOOLEAN IsPortLowSpeedDeviceAttached ( + UINT16 PortStatus ) +{ + // + // return the bit 9 value of PortStatus + // + if ( (PortStatus & USB_PORT_STAT_LOW_SPEED) != 0 ) { + return TRUE; + } + else { + return FALSE; + } +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +BOOLEAN IsPortHighSpeedDeviceAttached ( + UINT16 PortStatus ) +{ + // + // return the bit 10 value of PortStatus + // + if ( (PortStatus & USB_PORT_STAT_HIGH_SPEED) != 0 ) { + return TRUE; + } + else { + return FALSE; + } +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +BOOLEAN IsPortSuperSpeedDeviceAttached ( + UINT16 PortStatus ) +{ + // + // return the bit 10 value of PortStatus + // + if ( (PortStatus & USB_PORT_STAT_SUPER_SPEED) != 0 ) { + return TRUE; + } + else { + return FALSE; + } +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +// +// 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 Binary files /dev/null and b/Core/EM/UsbRecovery/USBRecoverySrc.chm 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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +/*++ + 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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// Name: UhcPeim.h +// +// Description: This file belongs to "Framework". +// This file is modified by AMI to include copyright message, +// appropriate header and integration code. +// +//---------------------------------------------------------------------------- +// + +// +// 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 @@ + + name = "UhcPeimSrc" + category = ModulePart + LocalRoot = "Core\em\UsbRecovery\UhcPeimSrc" + RefName = "UhcPeimSrc" +[files] +"UhcPeim.c" +"UhcPeim.h" +[parts] +"UsbHCPpi" + 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 +// +// +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// Name: UhciPeiUsb.C +// +// Description: This file is the main source file for the UHCI PEI USB +// recovery module +// +//---------------------------------------------------------------------------- +// + +#include +#include +#include +#include + + +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + + +// +//---------------------------------------------------------------------------- +// 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. +// +//---------------------------------------------------------------------------- +// + +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 ); +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// Procedure: ClearEhciConfigFlagReg +// +// Description: +// +// Input: **PeiServices Pointer to the PEI services table +// *PciCfgPpi Pointer to the PCI Configuration PPI +// +//---------------------------------------------------------------------------- +// +#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 + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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 @@ + + name = "UhciPeiUsb" + category = ModulePart + LocalRoot = "core\em\UsbRecovery\UhciPeiUsb\" + RefName = "UhciPeiUsb" +[files] +"UhciPeiUsb.c" +[parts] +"UHCI PPI" + 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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +/*++ + 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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// Name: BotPeim.h +// +// Description: This file belongs to "Framework". +// This file is modified by AMI to include copyright message, +// appropriate header and integration code. +// +//---------------------------------------------------------------------------- +// + +// +// 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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + + +/*++ + 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 ); + + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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 ->> + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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 + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// 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 +// +//---------------------------------------------------------------------------- +// + +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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + + +/*++ + 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 @@ + + 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" + 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 +// +// +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// Name: UsbBotPeim.DXS +// +// Description: This file is the dependency file for the USB BOT protocol PEIM +// +//---------------------------------------------------------------------------- +// + +/*++ + 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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// Name: UsbBotPeim.h +// +// Description: This file belongs to "Framework". +// This file is modified by AMI to include copyright message, +// appropriate header and integration code. +// +//---------------------------------------------------------------------------- +// + + +// +// 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 + +#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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// Name: Atapi.h +// +// Description: This file belongs to "Framework". +// This file is modified by AMI to include copyright message, +// appropriate header and integration code. +// +//---------------------------------------------------------------------------- +// + +// +// 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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +// +// 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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +/*++ + 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} +}; + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +/*++ + 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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +/*++ + 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 @@ + + name = "UsbPeimSrc" + category = ModulePart + LocalRoot = "Core\EM\UsbRecovery\UsbPeimSrc\" + RefName = "UsbPeimSrc" +[files] +"HubPeim.c" +"UsbIoPeim.c" +"UsbPeim.c" +[parts] +"UsbIoPpi" + 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 +# +#********************************************************************** + + +# +#----------------------------------------------------------------------- +# +# Name: UsbRecov.mak +# +# Description: Contains make script to build USB Recovery related +# PEIM. This script file generates UhciPeiUsb, OhciPei, +# UhcPeim, UsbPeim and UsbBotPeim +# +#----------------------------------------------------------------------- +# + +# 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 @@ + + 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" + 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 +// +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +#include +#include "XhciPei.h" +#include +#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 + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; PortNumberMaxPorts; + 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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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); +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; + +} + + +// +//--------------------------------------------------------------------------- +// +// Name: XhciHcGetRootHubPortNumber +// +// Description: +// This function returns number of root ports supported by the controller. +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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). +// +//--------------------------------------------------------------------------- +// + +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")); + } +} + + +// +//--------------------------------------------------------------------------- +// +// Name: XhciHcGetRootHubPortStatus +// +// Description: +// Host controller API function; returns root hub port status in terms of +// PEI_USB_HOST_CONTROLLER_PPI definition. +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// Name: XhciHcSetRootHubPortFeature +// +// Description: +// Host controller PEI_USB_HOST_CONTROLLER_PPI API function; sets a requested +// feature of a root hub port. +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// Name: XhciHcClearRootHubPortFeature +// +// Description: +// Host controller PEI_USB_HOST_CONTROLLER_PPI API function; clears a requested +// feature of a root hub port. +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// Name: XhciMmio64Write +// +// Description: +// MMIO write; depending on 64-bit access availability executes either one +// 64-bit write or two 32-bit writes. +// +//--------------------------------------------------------------------------- +// + +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)); + } +} + + +// +//--------------------------------------------------------------------------- +// +// Name: XhciInitRing +// +// Description: +// Transfer ring initialization. There is an option to create a Link TRB in +// the end of the ring. +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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, CountEvtRing.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 +} + + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// Name: XhciInitXfrRing +// +// Description: +// This function initializes transfer ring of given endpoint +// +// Output: +// Pointer to the transfer ring +// +//--------------------------------------------------------------------------- +// + +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; +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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 +} + + +// +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +// + +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; +} + +// +//--------------------------------------------------------------------------- +// +// Name: XhciGetXfrRing +// +// Description: +// This routine calculates the address of the address ring of a particular +// Slot/Endpoint. +// +// Output: +// Pointer to the transfer ring +// +//--------------------------------------------------------------------------- +// + +TRB_RING* +XhciGetXfrRing( + USB3_CONTROLLER* Usb3Hc, + UINT8 Slot, + UINT8 Ep +) +{ + return Usb3Hc->XfrRings + (Slot-1)*32 + Ep; +} + + +// +//---------------------------------------------------------------------------- +// +// Procedure: XhciGetTheDoorbell +// +// Description: +// This function calculates and returns the pointer to a doorbell for a +// given Slot. +// +//---------------------------------------------------------------------------- +// + +UINT32* +XhciGetTheDoorbell( + USB3_CONTROLLER *Usb3Hc, + UINT8 SlotId +) +{ + return (UINT32*)((UINTN)Usb3Hc->CapRegs + Usb3Hc->DbOffset + sizeof(UINT32)*SlotId); +} + +// +//---------------------------------------------------------------------------- +// +// Procedure: XhciGetDeviceContext +// +// Description: +// This function calculates and returns the pointer to a device context for +// a given Slot. +// +//---------------------------------------------------------------------------- +// + +UINT8* +XhciGetDeviceContext( + USB3_CONTROLLER *Usb3Hc, + UINT8 SlotId +) +{ + UINT32 DevCtxSize = XHCI_DEVICE_CONTEXT_ENTRIES * Usb3Hc->ContextSize; + return (UINT8*)((UINTN)Usb3Hc->DeviceContext + (SlotId - 1) * DevCtxSize); +} + +// +//---------------------------------------------------------------------------- +// +// Procedure: XhciGetContextEntry +// +// Description: +// This function calculates and returns the pointer to a context entry for +// a given index. +// +//---------------------------------------------------------------------------- +// + +UINT8* +XhciGetContextEntry( + USB3_CONTROLLER *Usb3Hc, + VOID *Context, + UINT8 Index +) +{ + return (UINT8*)((UINTN)Context + Index * Usb3Hc->ContextSize); +} + //(EIP75547+)> +// +//--------------------------------------------------------------------------- +// +// Name: XhciEnableUsb2Port +// +// Description: +// +//--------------------------------------------------------------------------- +// + +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; + } + } + } + } + + } + +// +//--------------------------------------------------------------------------- +// +// Name: XhciExtCapParser +// +// Description: +// +//--------------------------------------------------------------------------- +// + +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 @@ + + name = "XhciPei" + category = ModulePart + LocalRoot = "core\em\UsbRecovery\XhciPEI\" + RefName = "XhciPei" +[files] +"XhciPei.c" +"XhciPei.h" + 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 +// +//********************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// + +#ifndef _XHCIPEI_H +#define _XHCIPEI_H + +#include +#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 +// +//***************************************************************************** + +// +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- +// + +// +// 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 -- cgit v1.2.3