diff options
Diffstat (limited to 'Core/EM/UsbRecovery/OhciPEI')
-rw-r--r-- | Core/EM/UsbRecovery/OhciPEI/OhciPei.c | 1455 | ||||
-rw-r--r-- | Core/EM/UsbRecovery/OhciPEI/OhciPei.cif | 12 | ||||
-rw-r--r-- | Core/EM/UsbRecovery/OhciPEI/OhciPei.h | 909 | ||||
-rw-r--r-- | Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c | 508 |
4 files changed, 2884 insertions, 0 deletions
diff --git a/Core/EM/UsbRecovery/OhciPEI/OhciPei.c b/Core/EM/UsbRecovery/OhciPEI/OhciPei.c new file mode 100644 index 0000000..7ecb23d --- /dev/null +++ b/Core/EM/UsbRecovery/OhciPEI/OhciPei.c @@ -0,0 +1,1455 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//********************************************************************** +// +// $Header: /Alaska/SOURCE/Modules/USBRecovery/OhciPei.c 12 11/24/12 5:44a Ryanchou $ +// +// $Revision: 12 $ +// +// $Date: 11/24/12 5:44a $ +// +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/USBRecovery/OhciPei.c $ +// +// 12 11/24/12 5:44a Ryanchou +// [TAG] EIP103990 +// [Category] Improvement +// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24. +// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c, +// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h, +// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c, +// PeiUsbLib.h, UsbPeim.h +// +// 11 8/23/12 9:59p Wilsonlee +// [TAG] EIP97069 +// [Category] Improvement +// [Description] Reset root port algorythm update. +// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c, +// UhcPeim.h, UsbPeim.c, usb.h +// +// 10 1/18/11 12:59a Ryanchou +// [TAG] EIP47931 +// [Category] Improvement +// [Description] Added USB 3.0 hub support. +// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c, +// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h, +// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h +// +// 9 10/11/10 4:51p Olegi +// XHCI support added. +// +// 8 3/17/09 5:09p Olegi +// Added TransactionTranslator for slow/full speed devices behind USB2 +// hub. +// +// 7 3/03/09 7:26p Olegi +// MaximumPacketLength changed from UINT8 to UINT16. +// +// 6 10/21/08 5:57p Michaela +// Added EHCI-related fixes for issues +// that may occur if EHCI is used before +// USB Recovery is invoked: +// Added SDL Tokens: +// PEI_EHCI_PCI_BDFS and +// PEI_EHCI_MEM_BASE_ADDRESSES. +// +// Removed/modified some debugging +// development code: +// Removed SDL Tokens: +// USBR_DEBUG_SUPPORT and +// USBR_SERIAL_PORT_AVAILABLE +// Removed Elinks: +// UsbRecoveryDebug_DIR and +// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs +// Modified SDL Token: +// FORCE_RECOVERY to default value of 0. +// +// (See this module's Help documentation +// for more information.) +// +// 5 7/29/08 5:50p Michaela +// 1) Updated code to move most porting tasks to SDL +// 2) Added more debug break points and improved interactive +// debugging capability for when a serial port is not available. +// 3) Updated help files +// +// 4 7/18/08 5:04p Michaela +// 1 File-level debugging is now available +// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns +// the keypress so that conditional debugging can +// be dynamic (alphanumeric keys only) +// 3 Added more function headers. +// 4 Removed code that will never be used (I.e., Bala?). +// 5 Moved typedef, contants and extern declarations +// into header files. +// 6 Now all controller blocks are enabled for SB700 +// (EHCI controllers route to companion controller +// by default) +// 7 Removed unused constants and typedefs n OhciPei.h +// (also reorganized the file to make it more +// readable.) +// 8 Renamed many functions/variables according to +// coding standard. +// 9 Removed code initializing data structures for +// periodic lists, as this is not needed. +// 10 Removed the CONTROLLER_TYPE SDL token to +// allow UHCI and OHCI controllers to supported +// simultaneously. (modified MAKE files +// accordingly) +// +// 3 7/10/08 6:36p Michaela +// Updated to support OHCI controllers +// +// 2 9/22/06 12:23p Sivagarn +// - Included appropriate headers for flies and functions +// - Updated copyright messages +// - Merged multiple MAK and SDL files into one MAK and SDL file +// - Removed unnecessary files +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: OhciPei.c +// +// Description: +// This file is the main source file for the OHCI PEI USB +// recovery module. Its entry point at OhciPeiUsbEntryPoint +// will be executed from the UsbRecoveryInitialize INIT_LIST. +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <PEI.h> +#include <AmiPeiLib.h> +#include <token.h> +#include <PPI\PeiGetUCtrl.h> +#include <PPI\OhciPPI.h> +#include <PPI\stall.h> +#include "Ppi\UsbHostController.h" +#include "OhciPei.h" +#include "usb.h" + +// List of PCI addresses for OHCI controllers +extern PCI_BUS_DEV_FUNCTION gOhciControllerPciTable[]; +extern UINT16 gOhciControllerCount; + +extern EFI_GUID gPeiStallPpiGuid; +extern EFI_GUID gPeiUsbHostControllerPpiGuid; +extern EFI_STATUS OhciPeiBoardInit ( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PEI_PCI_CFG_PPI *PciCfgPpi, + EFI_PEI_STALL_PPI *StallPpi ); +extern VOID ZeroMem ( + OUT VOID *Buffer, + IN UINTN Size ); + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciGetOperationalRegisterBase +// +// Description: +// This function uses ControllerIndex and the global PCI_BUS_DEV_FUNCTION +// array to access a particular controller's PCI configuration space in +// order to obtain the Operational Register base address. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- PEI Sevices table pointer +// IN UINT16 ControllerIndex +// -- Index of the controller in the global +// PCI_BUS_DEV_FUNCTION array +// +// Output: +// UINT32 (Return Value) +// = Base address for this controller's operational +// registers. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT32 OhciGetOperationalRegisterBase ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT16 ControllerIndex ) +{ + UINT32 OhciBaseAddress; + + (*PeiServices)->PciCfg->Read( + PeiServices, + (*PeiServices)->PciCfg, + EfiPeiPciCfgWidthUint32, + OHCI_PCI_ADDRESS( ControllerIndex, OHCI_BASE_ADDR_REG ), + &OhciBaseAddress + ); + + + return OhciBaseAddress &= 0xfffffff0; // Mask lower bits +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciPeiUsbEntryPoint +// +// Description: +// This is the entry point into the OHCI controller initialization +// subsystem. +// +// Input: +// IN EFI_FFS_FILE_HEADER *FfsHeader +// -- EFI_FFS_FILE_HEADER pointer +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OhciPeiUsbEntryPoint ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices ) +{ + UINT8 Index; + UINTN MemPages; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS TempPtr; + PEI_OHCI_DEV *OhciDevPtr; + EFI_PEI_STALL_PPI *StallPpi; + + //------------------------------------------- + // Initialize the EFI_PEI_STALL_PPI interface + //------------------------------------------- + Status = (**PeiServices).LocatePpi( PeiServices, &gPeiStallPpiGuid, + 0, NULL, &StallPpi ); + if ( EFI_ERROR( Status ) ) { + return EFI_UNSUPPORTED; + } + + //----------------------------------------- + // board specific initialization to program + // PCI bridges and enable MMIO + //----------------------------------------- + + Status = OhciPeiBoardInit( + PeiServices, + (*PeiServices)->PciCfg, + StallPpi ); + if ( EFI_ERROR( Status ) ) { + return EFI_UNSUPPORTED; + } + + //---------------------------------------------------------- + // Allocate OHCI DEVICE OBJECT that holds all necessary + // information for the Host Controller operational registers + // for each controller. Initialze the controller and setup + // data structures for ready for operation + //---------------------------------------------------------- + + for (Index = 0; Index < gOhciControllerCount; Index++) + { + + // PAGESIZE = 0x1000 + MemPages = sizeof (PEI_OHCI_DEV) / 0x1000 + 1; + Status = (**PeiServices).AllocatePages( + PeiServices, + EfiConventionalMemory, + MemPages, + &TempPtr + ); + if ( EFI_ERROR( Status ) ) + { + return EFI_OUT_OF_RESOURCES; + } + + OhciDevPtr = (PEI_OHCI_DEV *) ( (UINTN) TempPtr ); + OhciDevPtr->Signature = PEI_OHCI_DEV_SIGNATURE; + OhciDevPtr->PeiServices = PeiServices; + OhciDevPtr->CpuIoPpi = (*PeiServices)->CpuIo; + OhciDevPtr->StallPpi = StallPpi; + OhciDevPtr->PciCfgPpi = (*PeiServices)->PciCfg; + ; + OhciDevPtr->UsbHostControllerBaseAddress = + OhciGetOperationalRegisterBase( PeiServices, Index ); + + //Initialize the OHCI Controller for operation + + OhciInitHC( PeiServices, OhciDevPtr, Index ); // 0xff03 + + //Setup PPI entry point + OhciDevPtr->UsbHostControllerPpi.ControlTransfer = + OhciHcControlTransfer; + OhciDevPtr->UsbHostControllerPpi.BulkTransfer = + OhciHcBulkTransfer; + OhciDevPtr->UsbHostControllerPpi.GetRootHubPortNumber = + OhciHcGetRootHubPortNumber; + OhciDevPtr->UsbHostControllerPpi.GetRootHubPortStatus = + OhciHcGetRootHubPortStatus; + OhciDevPtr->UsbHostControllerPpi.SetRootHubPortFeature = + OhciHcSetRootHubPortFeature; + OhciDevPtr->UsbHostControllerPpi.ClearRootHubPortFeature = + OhciHcClearRootHubPortFeature; + OhciDevPtr->UsbHostControllerPpi.PreConfigureDevice = NULL; + OhciDevPtr->UsbHostControllerPpi.EnableEndpoints = NULL; + + OhciDevPtr->PpiDescriptor.Flags = + (EFI_PEI_PPI_DESCRIPTOR_PPI | + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + OhciDevPtr->PpiDescriptor.Guid = &gPeiUsbHostControllerPpiGuid; + OhciDevPtr->PpiDescriptor.Ppi = &OhciDevPtr->UsbHostControllerPpi; + + //Now is the time to install the PPI + Status = (**PeiServices).InstallPpi( + PeiServices, &OhciDevPtr->PpiDescriptor ); + if ( EFI_ERROR( Status ) ) + { + return EFI_NOT_FOUND; + } + + } + + return EFI_SUCCESS; + +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciInitHcca +// +// Description: +// This routine allocates memory for the the Host Controller +// Communications Area (HCCA), aligned on a 256 byte boundary, +// and updates the HcHcca operational register pointer, as +// well as the corresponding PEI_OHCI_DEV.pFrameList +// pointer. +// +// Input: +// IN PEI_OHCI_DEV *OhciDevPtr +// -- This is a pointer to a PEI_OHCI_DEV structure +// for an OHCI controller. +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OhciInitHcca ( + IN PEI_OHCI_DEV *OhciDevPtr ) +{ + OHCI_HC_REGISTERS *OhciHcReg = + (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress; + + // Allocate 256 byte aligned Communication Channel area + // to the PEI_OHCI_DEV.pFrameList pointer. + ABORT_ON_ERROR( + (*OhciDevPtr->PeiServices)->AllocatePages( + OhciDevPtr->PeiServices, + EfiConventionalMemory, + (UINTN) (256 / 0x1000) + 1, + (EFI_PHYSICAL_ADDRESS *) &OhciDevPtr->pFrameList ) + ); + + // Zero the memory and update the HcHCCA Host Controller + // Operational Register. + ZeroMem((VOID*)OhciDevPtr->pFrameList, sizeof(HC_HCCA)); + OhciHcReg->HcHcca = (HC_HCCA*) OhciDevPtr->pFrameList; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciInitHC +// +// Description: All leading whitespace on this line is removed by Helpbuilder +// Description of this function can be block aligned in this section. +// The first tab that Helpbuilder will recognize will be at tab stop 21, +// which will indent 4 spaces in Helpbuilder. +// +// This text is indented 4 spaces in Helpbuilder +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// IN PEI_OHCI_DEV *OhciDevPtr +// -- PEI_OHCI_DEV pointer +// IN UINT8 Index +// -- Index of this controller in the global +// PCI_BUS_DEV_FUNCTION array +// +// Output: +// VOID (Return Value) +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID OhciInitHC ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_OHCI_DEV *OhciDevPtr, + IN UINT8 Index ) +{ + UINT8 bPortNum; + UINT8 *pPtr; + UINTN MemPages; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS TempPtr; + EFI_PEI_PCI_CFG_PPI *PciCfgPpi = OhciDevPtr->PciCfgPpi; + POHCI_DESC_PTRS pstOHCIDescPtrs = &(OhciDevPtr->stOHCIDescPtrs); + OHCI_HC_REGISTERS *OhciHcReg = + (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress; + + OhciDevPtr->wAsyncListSize = 0; // not used + OhciDevPtr->dMaxBulkDataSize = MAX_OHCI_BULK_DATA_SIZE; + //OhciDevPtr->wEndp0MaxPacket = 0x40; + //OhciDevPtr->bEndpointSpeed = USBSPEED_FULL; + + + // Do a Host Controller reset first + OhciHcReset( PeiServices, OhciDevPtr ); + + + //----------------------------------------------------------------- + // Allocate and initialize the Host Controller Communication + // area aligned on a 256 byte boundary. + // + // This is needed only to poll the HccaDoneHead register + // in the HCCA, as the periodic list is not implemented. + //----------------------------------------------------------------- + + // Store number of downstream ports into PEI_OHCI_DEV struct + OhciDevPtr->bNumPorts = + OhciHcReg->HcRhDescriptorA.Field.NumberDownstreamPorts; + + // Program root hub characteristics: + OhciHcReg->HcRhDescriptorA.AllBits = + (NO_OVERCURRENT_PROTECTION | // No over current protection + POWERED_INDIVIDUALLY | // Ports powered individually + POWER_SWITCHED); // Ports individually power switched + OhciHcReg->HcRhDescriptorB.AllBits = + (ALL_REMOVEABLE | // All devices are removbale + ALL_PER_PORT_POWER_SWITCHED); // Power control is per-port + + OhciHcReg->HcRhStatus.Field.LocalPowerStatusChange = + SET_GLOBAL_POWER; // Turn on power to all ports + + // Initialize the frame interval register + OhciHcReg->HcFmInterval.Field.FrameInterval = + FM_INTERVAL_DEFAULT; // Between Start of Frames (SOFs) + OhciHcReg->HcFmInterval.Field.FsLargestDataPacket = + FS_LARGEST_PACKET_DEFAULT; // Largest for single transaction + + // Enable the host controller list processing (Bulk/Control only) + OhciHcReg->HcControl.Field.BulkListEnable = TRUE; + OhciHcReg->HcControl.Field.ControlListEnable = TRUE; + + // Set the operational bit in the host controller so that power + // can be applied to the ports. + OhciHcReg->HcControl.Field.HostControllerFunctionalState = + SET_USB_OPERATIONAL; + + // Enable all the ports. + for ( bPortNum = 0; bPortNum < OhciDevPtr->bNumPorts; bPortNum++ ) { + OhciHcReg->HcRhPortStatus[bPortNum].AllBits = SET_PORT_POWER; + } + + // Allocate a block of memory and define/initialize + // Setup Control and Bulk EDs/TDs + pstOHCIDescPtrs = &(OhciDevPtr->stOHCIDescPtrs); + + MemPages = ( 3 * + sizeof (OHCI_ED) ) + ( 5 * sizeof(OHCI_TD) ) / 0x1000 + 1; + Status = (**PeiServices).AllocatePages( + PeiServices, + EfiConventionalMemory, + MemPages, + &TempPtr + ); + + pPtr = (UINT8 *) ( (UINTN) TempPtr ); + MemSet( pPtr, 3 * sizeof (OHCI_ED) + 5 * sizeof(OHCI_TD), 0 ); + if (!pPtr) { + return; + } + pstOHCIDescPtrs->pstEDControl = (POHCI_ED) pPtr; + pPtr += sizeof (OHCI_ED); //This should be okay + pstOHCIDescPtrs->pstTDControlSetup = (POHCI_TD) pPtr; + pPtr += sizeof (OHCI_TD); + pstOHCIDescPtrs->pstTDControlData = (POHCI_TD) pPtr; + pPtr += sizeof (OHCI_TD); + pstOHCIDescPtrs->pstTDControlStatus = (POHCI_TD) pPtr; + pPtr += sizeof (OHCI_TD); + pstOHCIDescPtrs->pstEDBulk = (POHCI_ED) pPtr; + pPtr += sizeof (OHCI_ED); + pstOHCIDescPtrs->pstTDBulkData = (POHCI_TD) pPtr; + pPtr += sizeof (OHCI_TD); + pstOHCIDescPtrs->pstEDInterrupt = (POHCI_ED) pPtr; + pPtr += sizeof (OHCI_ED); + pstOHCIDescPtrs->pstTDInterruptData = (POHCI_TD) pPtr; + +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciHcReset +// +// Description: +// This function performs a software reset of the host controller. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// IN PEI_OHCI_DEV *OhciDevPtr +// -- PEI_OHCI_DEV pointer +// +// Output: +// VOID (Return Value) +// +// Notes: +// It is assumed that all necessary operational register data has been +// saved prior to calling this function. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID OhciHcReset ( + EFI_PEI_SERVICES **PeiServices, + PEI_OHCI_DEV *OhciDevPtr ) +{ + OHCI_HC_REGISTERS *OhciHcReg = + (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress; + + // Initiate a software reset + OhciHcReg->HcCommandStatus.AllBits = SET_CONTROLLER_RESET; + + //Wait for 2ms + OHCI_FIXED_DELAY_MS( OhciDevPtr, 2); + + //Do USBRESET to reset roothub and downstream port + OhciHcReg->HcControl.Field.HostControllerFunctionalState = SET_USB_RESET; + + //wait for 10ms + OHCI_FIXED_DELAY_MS( OhciDevPtr, 10); + + // Note: HcInterruptStatus.Field.RootHubStatusChange bit should + // now be set if any devices are connected to a port + // on this controller. + + return; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciHcGetRootHubPortStatus +// +// Description: +// This function obtains the port status and port change status for +// a port specified by PortNumber and updates the EFI_USB_PORT_STATUS +// data structure as specified the the PortStatus pointer parameter. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// IN PEI_USB_HOST_CONTROLLER_PPI *This +// -- PEI_USB_HOST_CONTROLLER_PPI pointer +// IN UINT8 PortNumber +// -- Port number for which status is requested +// OUT EFI_USB_PORT_STATUS *PortStatus +// -- EFI_USB_PORT_STATUS pointer's data is updated +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OhciHcGetRootHubPortStatus ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus ) +{ + PEI_OHCI_DEV *OhciDevPtr = + PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This ); + HC_RH_PORT_STATUS HcPortStatus; + + HcPortStatus = ( (OHCI_HC_REGISTERS *) + OhciDevPtr->UsbHostControllerBaseAddress )-> + HcRhPortStatus[PortNumber - 1]; + + PortStatus->PortStatus = 0; + PortStatus->PortChangeStatus = 0; + + if (HcPortStatus.Field.CurrentConnectStatus) { + PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION; + } + if (HcPortStatus.Field.PortEnableStatus) { + PortStatus->PortStatus |= USB_PORT_STAT_ENABLE; + } + if (HcPortStatus.Field.PortSuspendStatus) { + PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND; + } + if (HcPortStatus.Field.PortResetStatus) { + PortStatus->PortStatus |= USB_PORT_STAT_RESET; + } + if (HcPortStatus.Field.LowSpeedDeviceAttached) { + PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED; + } + if (HcPortStatus.Field.ConnectStatusChange) { + PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION; + } + if (HcPortStatus.Field.PortEnableStatusChange) { + PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE; + } + if (HcPortStatus.Field.CurrentConnectStatus) { + PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION; + } + + return EFI_SUCCESS; + +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciHcGetRootHubPortNumber +// +// Description: +// This function returns the number of downstream ports as specified +// in the HcRhDescriptorA operational register. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// IN PEI_USB_HOST_CONTROLLER_PPI *This +// -- PEI_USB_HOST_CONTROLLER_PPI pointer +// OUT UINT8 *PortNumber +// -- Number of downstream ports +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OhciHcGetRootHubPortNumber ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + OUT UINT8 *PortNumber ) +{ + + PEI_OHCI_DEV *OhciDevPtr = PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This ); + OHCI_HC_REGISTERS *OhciHcReg = + (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress; + + if (PortNumber == NULL) { + return EFI_INVALID_PARAMETER; + } + + *PortNumber = OhciHcReg->HcRhDescriptorA.Field.NumberDownstreamPorts; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciHcSetRootHubPortFeature +// +// Description: +// This function sets an OHCI specification port feature as specified by +// PortFeature for the port specified by PortNumber. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// IN PEI_USB_HOST_CONTROLLER_PPI *This +// -- PEI_USB_HOST_CONTROLLER_PPI pointer +// IN UINT8 PortNumber +// -- Port number whose feature is to be set +// IN EFI_USB_PORT_FEATURE PortFeature +// -- Feature to set +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OhciHcSetRootHubPortFeature ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature ) +{ + PEI_OHCI_DEV *OhciDevPtr = + PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This ); + OHCI_HC_REGISTERS *OhciHcReg = + (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress; + + if (PortNumber > OhciHcReg->HcRhDescriptorA.Field.NumberDownstreamPorts){ + return EFI_INVALID_PARAMETER; + } + + switch (PortFeature) + { + + case EfiUsbPortSuspend: + OhciHcReg->HcRhPortStatus[PortNumber - 1].AllBits = SET_PORT_SUSPEND; + break; + + case EfiUsbPortReset: + OhciHcReg->HcRhPortStatus[PortNumber - 1].AllBits = SET_PORT_RESET; + break; + + case EfiUsbPortPower: + break; + + case EfiUsbPortEnable: + OhciHcReg->HcRhPortStatus[PortNumber - 1].AllBits = SET_PORT_ENABLE; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciHcClearRootHubPortFeature +// +// Description: +// This function clears an OHCI specification port feature as specified +// by PortFeature for the port specified by PortNumber. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// IN PEI_USB_HOST_CONTROLLER_PPI *This +// -- PEI_USB_HOST_CONTROLLER_PPI pointer +// IN UINT8 PortNumber +// -- Port number whose feature is to be set +// IN EFI_USB_PORT_FEATURE PortFeature +// -- Feature to set +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OhciHcClearRootHubPortFeature ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature ) +{ + PEI_OHCI_DEV *OhciDevPtr = + PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This ); + OHCI_HC_REGISTERS *OhciHcReg = + (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress; + HC_RH_PORT_STATUS *Pstatus; + + if (PortNumber > OhciHcReg->HcRhDescriptorA.Field.NumberDownstreamPorts){ + return EFI_INVALID_PARAMETER; + } + + Pstatus = &OhciHcReg->HcRhPortStatus[PortNumber - 1]; + + switch (PortFeature) + { + // clear PORT_ENABLE feature means disable port. + // This is accomplished by writing a 1 to the CurrentConnectStatus + // field. + case EfiUsbPortEnable: + Pstatus->AllBits = CLEAR_PORT_ENABLE; + break; + + // clear PORT_SUSPEND feature means resume the port. + // (cause a resume on the specified port if in suspend mode) + // This is accomplished by writing a 1 to the PortOverCurrentIndicator + // field. + case EfiUsbPortSuspend: + Pstatus->AllBits = CLEAR_SUSPEND_STATUS; + break; + + case EfiUsbPortPower: + break; + + + // clear PORT_RESET means clear the reset signal. + // This is accomplished by writing a 1 to the PortResetStatusChange + // field. No assumption is made that the appropriate delay + // was implemented. + case EfiUsbPortReset: + + break; + + // clear connect status change by writing + // a 1 to the ConnectStatusChange field + case EfiUsbPortConnectChange: + Pstatus->AllBits = CLEAR_CONNECT_STATUS_CHANGE; + break; + + // clear enable/disable status change by writing + // a 1 to the PortEnableStatusChange field + case EfiUsbPortEnableChange: + Pstatus->AllBits = CLEAR_PORT_ENABLE_STATUS_CHANGE; + break; + + // root hub does not support these requests + case EfiUsbPortSuspendChange: + case EfiUsbPortOverCurrentChange: + case EfiUsbPortResetChange: + Pstatus->AllBits = CLEAR_PORT_RESET_STATUS_CHANGE; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciHcControlTransfer +// +// Description: +// This function intiates a USB control transfer and waits on it to +// complete. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// IN PEI_USB_HOST_CONTROLLER_PPI *This +// -- PEI_USB_HOST_CONTROLLER_PPI pointer +// IN UINT8 bDeviceAddress +// -- USB address of the device for which the control +// transfer is to be issued +// IN UINT8 DeviceType +// -- Not used +// IN UINT8 MaximumPacketLength +// -- Maximum number of bytes that can be sent to or +// received from the endpoint in a single data packet +// IN EFI_USB_DEVICE_REQUEST *Request +// -- EFI_USB_DEVICE_REQUEST pointer +// IN EFI_USB_DATA_DIRECTION TransferDirection +// -- Direction of transfer +// OPTIONAL IN OUT VOID *DataBuffer +// -- Pointer to source or destination buffer +// OPTIONAL IN OUT UINTN *DataLength +// -- Length of buffer +// IN UINTN TimeOut +// -- Not used +// OUT UINT32 *TransferResult +// -- Not used +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +typedef struct _D_REQUEST +{ + UINT8 RequestType; + UINT8 Request; + UINT16 Value; + UINT16 Index; + UINT16 Length; +} D_REQUEST; + +EFI_STATUS OhciHcControlTransfer ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 bDeviceAddress, + IN UINT8 DeviceSpeed, + IN UINT8 MaximumPacketLength, + IN UINT16 TransactionTranslator OPTIONAL, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *DataBuffer OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + OUT UINT32 *TransferResult ) +{ + UINT16 *fpData; + POHCI_ED fpED; + POHCI_TD fpTD; + UINT32 DwordData; + UINT16 WordData; + UINT16 WordRequest; + UINT16 WordIndex; + UINT16 WordValue; + EFI_STATUS Status = EFI_SUCCESS; + PEI_OHCI_DEV *OhciDevPtr = + PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This ); + POHCI_DESC_PTRS fpDescPtrs = + &(OhciDevPtr->stOHCIDescPtrs); + OHCI_HC_REGISTERS *HcReg = + (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress; + + // 5 ms delay is necessary for OHCI host controllers + OHCI_FIXED_DELAY_MS( OhciDevPtr, 5 ); + + WordRequest = (Request->Request << 8) | Request->RequestType; + WordValue = Request->Value; + WordIndex = Request->Index; + + // + // Build the device request in the data area of the control setup qTD + // + fpData = (UINT16 *) fpDescPtrs->pstTDControlSetup->aSetupData; + *fpData++ = WordRequest; + *fpData++ = WordValue; + *fpData++ = WordIndex; + *fpData++ = (UINT16) *DataLength; + *(UINT32 *) fpData = (UINT32) DataBuffer; + + // + // Prepare some registers that will be used in building the TDs below. + // wLength contains the data length. + // fpBuffer contains the absolute address of the data buffer. + // WordRequest contains the request type (bit 7 = 0/1 for Out/In). + // fpDevInfo will contain a pointer to the DeviceInfo structure for + // the given device. + // + // Ready the EDControl for the control transfer. + // + fpED = fpDescPtrs->pstEDControl; + // + // The ED control field will be set so + // Function address & Endpoint number = ESI, + // Direction = From TD, + // Speed = DeviceInfo.bEndpointSpeed, + // Skip = 1, Format = 0, + // Max packet size = DeviceInfo.wEndp0MaxPacket + // The HeadPointer field will be set to TDControlSetup + // The TailPointer field will be set to OHCI_TERMINATE + // The LinkPointer field will be set to OHCI_TERMINATE + // + + // if wEndp0MaxPacket is NULL, then use default + // packet size + DwordData = MaximumPacketLength; + + // Force the max packet size to 64 bytes + if (DwordData > 0x40 || DwordData == 0) { + DwordData = 0x40; + } + DwordData <<= 16; // DwordData[26:16] = device's packet size + WordData = (UINT16) DeviceSpeed; // 00/01/10 for HI/LO/FULL + WordData = (WordData & 1) << 13; // WordData[13] = full/low speed flag + WordData |= bDeviceAddress | ED_SKIP_TDQ; + fpED->dControl = DwordData | WordData; + fpED->fpTailPointer = 0; + fpED->fpEDLinkPointer = 0; + + fpTD = fpDescPtrs->pstTDControlSetup; + // + // The ControlStatus field will be set so + // Buffer Rounding = 1, + // Direction PID = GTD_SETUP_PACKET, + // Delay Interrupt = GTD_INTD, + // Data Toggle = GTD_SETUP_TOGGLE, + // Error Count = GTD_NO_ERRORS, + // Condition Code = GTD_NOT_ACCESSED + // The CurrentBufferPointer field will point to the TD's SetupData buffer + // which was before initialized to contain a DeviceRequest struc. + // The BufferEnd field will point to the last byte of the TD's SetupData + // buffer. + // The LinkPointer field will point to the TDControlData if data will + // be sent/received or to the TDControlStatus if no data is expected. + // The CSReloadValue field will contain 0 because this is a "one shot" + // packet. + // The pCallback will be set to point to the OHCI_ControlTDCallback + // routine. + // The ActiveFlag field will be set to TRUE. + // The DeviceAddress field does not need to be set since the Control TDs + // do not need rebinding to the EDControl. + // + fpTD->dControlStatus = (UINT32) ( GTD_BUFFER_ROUNDING | + GTD_SETUP_PACKET | GTD_SETUP_TOGGLE | + GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28) ); + + fpTD->fpCurrentBufferPointer = fpTD->aSetupData; + fpTD->fpBufferEnd = fpTD->aSetupData + 7; // size of aSetupData - 1 + + if (*DataLength) { // some data to transfer + + // Fill in various fields in the TDControlData. + fpTD = fpDescPtrs->pstTDControlData; + // + // The ControlStatus field will be set so + // Buffer Rounding = 1, + // Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET, + // Delay Interrupt = GTD_INTD, + // Data Toggle = GTD_DATA1_TOGGLE, + // Error Count = GTD_NO_ERRORS, + // Condition Code = GTD_NOT_ACCESSED + // The CurrentBufferPointer field will point to the caller's buffer + // which is now in EBP. + // The BufferEnd field will point to the last byte of the caller's + // buffer. + // The LinkPointer field will point to the TDControlStatus. + // The CSReloadValue field will contain 0 because this is a + // "one shot" packet. + // The pCallback will be set to point to the OHCI_ControlTDCallback + // routine. + // The ActiveFlag field will be set to TRUE. + // The DeviceAddress field does not need to be set since the Control + // TDs do not need rebinding to the EDControl. + // The CSReloadValue field will contain 0 because this is a + // "one shot" packet. + // The pCallback will be set to point to the OHCI_ControlTDCallback + // routine. + // The ActiveFlag field will be set to TRUE. return USB_SUCCESS; + // The DeviceAddress field does not need to be set since the Control + // TDs do not need rebinding to the EDControl. + // + DwordData = (UINT32) ( GTD_BUFFER_ROUNDING | GTD_DATA1_TOGGLE + | GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28) ); + DwordData = (WordRequest & BIT7) + ? (DwordData | GTD_IN_PACKET | GTD_INTD) + : (DwordData | GTD_OUT_PACKET); + fpTD->dControlStatus = DwordData; + fpTD->fpCurrentBufferPointer = (UINT8 *) DataBuffer; + + WordData = (*DataLength < MAX_CONTROL_DATA_SIZE) + ? *DataLength + : MAX_CONTROL_DATA_SIZE; + fpTD->fpBufferEnd = (UINT8 *) DataBuffer + WordData - 1; + } + + // Fill in various fields in the TDControlStatus. + fpTD = fpDescPtrs->pstTDControlStatus; + // + // The ControlStaus field will be set so + // Buffer Rounding = 1, + // Direction PID = GTD_OUT_PACKET/GTD_IN_PACKET, + // Delay Interrupt = GTD_INTD, + // Data Toggle = GTD_DATA1_TOGGLE, + // Error Count = GTD_NO_ERRORS, + // Condition Code = GTD_NOT_ACCESSED + // The CurrentBufferPointer field will point to NULL + // The BufferEnd field will point to NULL. + // The LinkPointer field will point to OHCI_TERMINATE. + // The CSReloadValue field will contain 0 because this is a + // "one shot" packet. + // The pCallback will be set to point to the OHCI_ControlTdCallback + // routine. + // The ActiveFlag field will be set to TRUE. + // The DeviceAddress field does not need to be set since the Control + // TDs do not need rebinding to the EdControl. + // + // Note: For OUT control transfer status should be IN and + // for IN cotrol transfer, status should be OUT. + // + DwordData = (UINT32) ( GTD_BUFFER_ROUNDING | GTD_DATA1_TOGGLE + | GTD_NO_ERRORS | (GTD_NOT_ACCESSED << 28) ); + DwordData = (WordRequest & BIT7) + ? (DwordData | GTD_OUT_PACKET) + : (DwordData | GTD_IN_PACKET | GTD_INTD); + fpTD->dControlStatus = DwordData; + fpTD->fpCurrentBufferPointer = NULL; + fpTD->fpBufferEnd = NULL; + fpTD->fpLinkPointer = NULL; + + // + // Link all the pointers together + // + fpTD = fpDescPtrs->pstTDControlSetup; + fpED->fpHeadPointer = fpTD; + if (*DataLength) { // chain in data TD + fpTD->fpLinkPointer = (UINT8 *) fpDescPtrs->pstTDControlData; + fpTD = fpDescPtrs->pstTDControlData; + } + fpTD->fpLinkPointer = (UINT8 *) fpDescPtrs->pstTDControlStatus; + + fpDescPtrs->pstTDControlStatus->fpLinkPointer = NULL; + + fpTD = fpDescPtrs->pstTDControlSetup; + do { + fpTD->dCSReloadValue = 0; + fpTD->bActiveFlag = TRUE; + fpTD = (POHCI_TD) fpTD->fpLinkPointer; + } while (fpTD); + + // clear the WriteBackDoneHead status bit in + // the HcInterruptStatus register + HcReg->HcInterruptStatus.Field.WriteBackDoneHead = HCINT_STATUS_CLEAR; + + // + // Now control queue is complete, so set ED_SKIP_TDQ=0 + // + fpED->dControl &= ~ED_SKIP_TDQ; + // + // Set the HcControlHeadED register to point to the EDControl. + // + HcReg->HcControlHeadEd = (UINTN) fpED; + + // + // Now put the control setup, data and status into the HC's schedule by + // setting the ControllListFilled field of HcCommandStatus reg. + // This will cause the HC to execute the transaction in the next + // active frame. + // + HcReg->HcCommandStatus.AllBits = SET_CONTROL_LIST_FILLED; + + // + // Now wait for the control status TD to complete. When it has completed, + // the OHCI_ControlTDCallback will set its active flag to FALSE. + Status = OhciHcWaitForTransferComplete( PeiServices, OhciDevPtr, + fpDescPtrs->pstTDControlStatus ); + + // + // Stop the HC from processing the EDControl by setting its Skip bit. + // + fpED->dControl |= ED_SKIP_TDQ; + + // + // Finally check for any error bits set in both the TDControlStatus. + // If the TD did not complete successfully, return STC. + // + + // DwordData[3:0] = Completion status + DwordData = fpDescPtrs->pstTDControlStatus->dControlStatus >> 28; + + return ( (UINT8) DwordData == 0 ) ? EFI_SUCCESS : EFI_DEVICE_ERROR; + //TODO: CHange the return status more meaningfull +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciHcBulkTransfer +// +// Description: +// This function intiates a USB bulk transfer and waits on it to +// complete. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// IN PEI_USB_HOST_CONTROLLER_PPI *This +// -- PEI_USB_HOST_CONTROLLER_PPI pointer +// IN UINT8 DeviceAddress +// -- USB address of the device for which the control +// transfer is to be issued +// IN UINT8 EndPointAddress +// -- Particular endpoint for the device +// IN UINT8 MaximumPacketLength +// -- Maximum number of bytes that can be sent to or +// received from the endpoint in a single data packet +// OPTIONAL IN OUT VOID *DataBuffer +// -- Pointer to source or destination buffer +// OPTIONAL IN OUT UINTN *DataLength +// -- Length of buffer +// IN OUT UINT8 *DataToggle +// -- Used to update the control/status DataToggle field +// of the Transfer Descriptor +// IN UINTN TimeOut +// -- Not used +// OUT UINT32 *TransferResult +// -- Not used +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OhciHcBulkTransfer ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINT16 MaximumPacketLength, + IN UINT16 TransactionTranslator OPTIONAL, + IN OUT VOID *DataBuffer, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult ) +{ + UINT32 DwordData; + UINT8 ByteData; + UINT16 wMaxPkt; + EFI_STATUS Status; + UINT8 bEndp; + UINT8 Toggle; + PEI_OHCI_DEV *OhciDevPtr = + PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( This ); + POHCI_DESC_PTRS fpDescPtrs = &(OhciDevPtr->stOHCIDescPtrs); + OHCI_HC_REGISTERS *HcReg = + (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress; + + wMaxPkt = MaximumPacketLength; + + if (wMaxPkt == 0) { + *DataLength = 0; + return EFI_NOT_FOUND; + } + + //Clear Bulk ED and TD + MemSet( fpDescPtrs->pstEDBulk, sizeof(OHCI_ED), 0 ); + MemSet( fpDescPtrs->pstTDBulkData, sizeof(OHCI_TD), 0 ); + // + // Set the SKIP bit in the EdBulk to avoid accidental scheduling + // + fpDescPtrs->pstEDBulk->dControl = ED_SKIP_TDQ; + // + // Set the ED's head pointer field to bulk data TD and tail pointer + // field to OHCI_TERMINATE. Also set ED's link pointer to + // OHCI_TERMINATE. + // + fpDescPtrs->pstEDBulk->fpHeadPointer = fpDescPtrs->pstTDBulkData; + fpDescPtrs->pstEDBulk->fpTailPointer = OHCI_TERMINATE; + fpDescPtrs->pstEDBulk->fpEDLinkPointer = OHCI_TERMINATE; + // + // Form the data needed for ED's control field with the available + // information + // + bEndp = EndPointAddress & 0x7f; + DwordData = (EndPointAddress & 0x80) ? ED_IN_PACKET : ED_OUT_PACKET; + DwordData |= DeviceAddress; + DwordData |= (UINT16) bEndp << 7; + DwordData |= (UINT32) wMaxPkt << 16; + + // + // Update the ED's control field with the data formed + // ASSUME ALL MASS DEVICES ARE FULL SPEED DEVICES. + // + fpDescPtrs->pstEDBulk->dControl = DwordData; + // + // Fill the general bulk data TD with relevant information. Set the + // TD's control field with buffer rounding set to 1, direction PID to + // don't care, delay interrupt to INTD, data toggle to the latest data + // toggle value, error count to no errors and condition code to not + // accessed. + // + // Set the data toggle to DATA0 (SETUP_TOGGLE) + fpDescPtrs->pstTDBulkData->dControlStatus = (UINT32) ( + GTD_BUFFER_ROUNDING | + GTD_IN_PACKET | + GTD_INTD | + GTD_SETUP_TOGGLE | + GTD_NO_ERRORS | + (GTD_NOT_ACCESSED << 28) + ); + fpDescPtrs->pstTDBulkData->dControlStatus |= (UINT32) *DataToggle << 24; + + // + // GTD current buffer pointer field will point to the caller's buffer which + // now in the variable fpBuffer + // + fpDescPtrs->pstTDBulkData->fpCurrentBufferPointer = (UINT8 *) DataBuffer; + fpDescPtrs->pstTDBulkData->fpBufferEnd = (UINT8 *) DataBuffer + + *DataLength - 1; + fpDescPtrs->pstTDBulkData->fpLinkPointer = OHCI_TERMINATE; + // + // GTD's CSReloadValue field will contain 0 because this is a + // "one shot" packet + // + fpDescPtrs->pstTDBulkData->dCSReloadValue = 0; + fpDescPtrs->pstTDBulkData->bActiveFlag = TRUE; + + // Set the HCBulkHeadED register to point to the bulk ED + fpDescPtrs->pstEDBulk->dControl &= ~ED_SKIP_TDQ; + HcReg->HcBulkHeadEd = (UINT32) fpDescPtrs->pstEDBulk; + + // Enable the bulk list processing + HcReg->HcCommandStatus.AllBits = SET_BULK_LIST_FILLED; + + Status = OhciHcWaitForTransferComplete( PeiServices, OhciDevPtr, + fpDescPtrs->pstTDBulkData ); + // + // Stop the HC from processing the EDBulk by setting its Skip bit. + // + fpDescPtrs->pstEDBulk->dControl |= ED_SKIP_TDQ; + // + // Update the data toggle value into the mass info structure + // + + *DataToggle = (UINT8) ( ( (fpDescPtrs->pstTDBulkData->dControlStatus & + GTD_DATA_TOGGLE) >> 24 ) & 1 ); + Toggle = (UINT8) ( (fpDescPtrs->pstTDBulkData->dControlStatus & + GTD_DATA_TOGGLE) >> 24 ); + if ( (Toggle & 0x02) == 0 ) + { + //Use the Carry + DwordData = (UINT32) fpDescPtrs->pstEDBulk->fpHeadPointer; + DwordData &= 0x00000002; + DwordData = DwordData >> 1; + DwordData &= 0x00000001; + *DataToggle = DwordData; + } + // + // Check for the error conditions - if possible recover from them + // + ByteData = (UINT8) (fpDescPtrs->pstTDBulkData->dControlStatus >> 28); + if (ByteData) { + if (ByteData == GTD_DEVICE_NOT_RESPOND) { + //TODO fpUSBData->bLastCommandStatus |= USB_BULK_TIMEDOUT; + *DataLength = 0; + return EFI_NOT_FOUND; + } + if (ByteData == GTD_STALL) { + //TODO fpUSBData->bLastCommandStatus |= USB_BULK_STALLED; + *DataLength = 0; + return EFI_NOT_FOUND; + } + } + // + // Get the size of data transferred + // + // Size transferred is calculated by subtracting end address with current + // buffer pointer and subtracting that value from the total size + // + if (!fpDescPtrs->pstTDBulkData->fpCurrentBufferPointer) + { + //All data are transfered. + return EFI_SUCCESS; + } + DwordData = (UINT32) fpDescPtrs->pstTDBulkData->fpBufferEnd; + DwordData = DwordData - + (UINT32) fpDescPtrs->pstTDBulkData->fpCurrentBufferPointer; + if (DwordData != 0) + { + *DataLength = *DataLength - DwordData - 1; + } + else { + ; + } + return Status; + +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: OhciHcWaitForTransferComplete +// +// Description: +// This function waits for a tranfer to complete by polling the +// HcInterruptStatus register's WritebackDoneHead field. +// +// Input: +// IN PEI_OHCI_DEV *OhciDevPtr +// -- PEI_OHCI_DEV pointer +// IN POHCI_TD Td +// -- Not used +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OhciHcWaitForTransferComplete ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_OHCI_DEV *OhciDevPtr, + IN POHCI_TD Td ) +{ + UINT32 Count; + OHCI_HC_REGISTERS *HcReg = + (OHCI_HC_REGISTERS *) OhciDevPtr->UsbHostControllerBaseAddress; + HC_INTERRUPT_STATUS *HcIntStatus = &HcReg->HcInterruptStatus; + UINT32 DoneHead = 0; + + // Poll (up to 4 seconds) or until the + // WriteBackDoneHead status bit is set in + // the HcInterruptStatus operational register. + + // if the WriteBackDoneHead is set, then clear + // HccaDoneHead in the HCCA and WriteBackDoneHead + // and then return EFI_SUCCESS to continue execution. + + for (Count = 0; Count < 1000; Count++) { + if (HcIntStatus->Field.WriteBackDoneHead == HCINT_WB_DONE ) { + DoneHead = HcReg->HcHcca->HccaDoneHead; + HcReg->HcHcca->HccaDoneHead = 0; + HcIntStatus->Field.WriteBackDoneHead = HCINT_STATUS_CLEAR; + if (DoneHead == (UINT32)Td) { + return EFI_SUCCESS; + } + } + OHCI_FIXED_DELAY_MS( OhciDevPtr, 4 ); // 4 ms + + } + + PEI_TRACE ((EFI_D_ERROR, PeiServices, "OHCI Time-Out:\n")); + return EFI_NOT_FOUND; + +} + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/EM/UsbRecovery/OhciPEI/OhciPei.cif b/Core/EM/UsbRecovery/OhciPEI/OhciPei.cif new file mode 100644 index 0000000..49ec85b --- /dev/null +++ b/Core/EM/UsbRecovery/OhciPEI/OhciPei.cif @@ -0,0 +1,12 @@ +<component> + name = "OhciPei" + category = ModulePart + LocalRoot = "core\em\UsbRecovery\OhciPEI\" + RefName = "OhciPei" +[files] +"OhciPei.c" +"OhciPei.h" +"OhciPeiBoard.c" +[parts] +"OHCI PPI" +<endComponent> diff --git a/Core/EM/UsbRecovery/OhciPEI/OhciPei.h b/Core/EM/UsbRecovery/OhciPEI/OhciPei.h new file mode 100644 index 0000000..d743f61 --- /dev/null +++ b/Core/EM/UsbRecovery/OhciPEI/OhciPei.h @@ -0,0 +1,909 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//********************************************************************** +// +// $Header: /Alaska/SOURCE/Modules/USBRecovery/OhciPei.h 9 11/24/12 5:44a Ryanchou $ +// +// $Revision: 9 $ +// +// $Date: 11/24/12 5:44a $ +// +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/USBRecovery/OhciPei.h $ +// +// 9 11/24/12 5:44a Ryanchou +// [TAG] EIP103990 +// [Category] Improvement +// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24. +// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c, +// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h, +// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c, +// PeiUsbLib.h, UsbPeim.h +// +// 8 8/23/12 9:59p Wilsonlee +// [TAG] EIP97069 +// [Category] Improvement +// [Description] Reset root port algorythm update. +// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c, +// UhcPeim.h, UsbPeim.c, usb.h +// +// 7 1/18/11 1:00a Ryanchou +// [TAG] EIP47931 +// [Category] Improvement +// [Description] Added USB 3.0 hub support. +// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c, +// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h, +// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h +// +// 6 3/17/09 5:09p Olegi +// +// 5 3/03/09 7:26p Olegi +// MaximumPacketLength changed from UINT8 to UINT16. +// +// 4 7/18/08 5:04p Michaela +// 1 File-level debugging is now available +// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns +// the keypress so that conditional debugging can +// be dynamic (alphanumeric keys only) +// 3 Added more function headers. +// 4 Removed code that will never be used (I.e., Bala?). +// 5 Moved typedef, contants and extern declarations +// into header files. +// 6 Now all controller blocks are enabled for SB700 +// (EHCI controllers route to companion controller +// by default) +// 7 Removed unused constants and typedefs n OhciPei.h +// (also reorganized the file to make it more +// readable.) +// 8 Renamed many functions/variables according to +// coding standard. +// 9 Removed code initializing data structures for +// periodic lists, as this is not needed. +// 10 Removed the CONTROLLER_TYPE SDL token to +// allow UHCI and OHCI controllers to supported +// simultaneously. (modified MAKE files +// accordingly) +// +// 3 7/10/08 6:36p Michaela +// Updated to support OHCI controllers +// +// 2 9/22/06 12:23p Sivagarn +// - Included appropriate headers for flies and functions +// - Updated copyright messages +// - Merged multiple MAK and SDL files into one MAK and SDL file +// - Removed unnecessary files +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: OhciPei.h +// +// Description: This file is the main header file for the OHCI PEI USB +// recovery module. It contains generic constant and type +// declarations/definitions. +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#ifndef _OHCIPEI_H +#define _OHCIPEI_H + +#include "Efi.h" +#include "Pei.h" +#include "Ppi\UsbHostController.h" + + + +//---------------------------------------------------------------------------- +// Macros +//---------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +// OHCI_FIXED_DELAY_MS( OhciDevPtr, milliseconds ) +// +// invokes a delay specified in milliseconds using the PEI_OHCI_DEV.StallPpi +// member interface pointer, which is initialized from a EFI_PEI_STALL_PPI +// interface. +#define OHCI_FIXED_DELAY_MS( OhciDevPtr, milliseconds ) \ + OhciDevPtr->StallPpi->Stall( OhciDevPtr->PeiServices, \ + OhciDevPtr->StallPpi, milliseconds * 1000 ); + + +//---------------------------------------------------------------------------- +// MASK(high,low) +// +// defines a bit mask value with bits set in the bit +// range specified from high down to low (zero-based) +// +// Notes: +// 1) this is expected to be used only in 32-bit compiled code +#ifndef MASK +#define MAX_VAL 0xffffffff // maximum value supported by CPU +#define MAX_BIT 31 // highest bit position in MAX_VAL +#define MASK( high, low ) (\ + ( MAX_VAL >> ( MAX_BIT - ( (high) - (low) ) ) ) \ + << (low) \ +) +#endif + + +//---------------------------------------------------------------------------- +// READ_BITS(src,high,low) +// +// extracts a bit field shifted down to bit position 0 from src, where high +// and low define the bit range (zero-based). +// +// Notes: +// 1) this is expected to be used only in 32-bit compiled code +#ifndef READ_BITS +#define READ_BITS( src, high, low ) (\ + ( (src) & MASK( (high), (low) ) ) \ + >> (low) \ +) +#endif + + +//---------------------------------------------------------------------------- +// WRITE_BITS( src, val, high, low ) +// +// returns the modified src after writing a bit field with val, where the bit +// field's range is specified by high down to low. +// +// Notes: +// 1) the user must ensure that the val fits in the bit range +// 2) the bits in the range high:low are the only bits touched and +// they are cleared and replaced with val +// 3) this is expected to be used only in 32-bit compiled code +#ifndef WRITE_BITS +#define WRITE_BITS( src, val, high, low ) (\ + ( (src) & ~MASK( (high), (low) ) ) \ + | ( (val) << (low) ) \ +) +#endif + + +//---------------------------------------------------------------------------- +// ABORT_ON_ERROR( call ) +// +// simplifies the task of returning EFI_STATUS value after an unsuccessful +// function execution. +#define ABORT_ON_ERROR( call ) {\ + EFI_STATUS status = call; \ + if ( EFI_ERROR( status ) ) {\ + return status;}} + + +//---------------------------------------------------------------------------- +// OHCI_PCI_ADDRESS( ControllerIndex, Register ) +// +// allows easy generation of a valid PCI address using an index into the +// gOhciControllerPciTable and a register number +#define OHCI_PCI_ADDRESS( ControllerIndex, Register ) PEI_PCI_CFG_ADDRESS( \ + gOhciControllerPciTable[ControllerIndex].Bus, \ + gOhciControllerPciTable[ControllerIndex].Device, \ + gOhciControllerPciTable[ControllerIndex].Function, \ + Register ) + + +//---------------------------------------------------------------------------- +// EFI_SIGNATURE_32( A, B, C, D) +// +// defines a signature that can be used with the PEI_CR macro to return a +// pointer to the data structure that contains the specified field and +// signature +#define EFI_SIGNATURE_16(A,B) ((A) | ((B)<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) \ + (EFI_SIGNATURE_16((A),(B)) | (EFI_SIGNATURE_16((C),(D)) << 16)) + + +//---------------------------------------------------------------------------- +// PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( a ) +// +// uses the _CR macro to obtain a pointer to a PEI_OHCI_DEV structure from +// a PEI_USB_HOST_CONTROLLER_PPI interface pointer +#define _CR( Record, TYPE, Field ) \ + ( (TYPE *) ( (CHAR8 *) (Record) - (CHAR8 *) &( ( (TYPE *) 0 )->Field ) ) ) +#define PEI_RECOVERY_USB_OHCI_DEV_FROM_THIS( a ) \ + _CR( a, PEI_OHCI_DEV, UsbHostControllerPpi ) + + +//---------------------------------------------------------------------------- +// GET_PORT_STATUS_REG_OFFSET( x ) +// +//Macro to get the RhPortStatus register offset +#define GET_PORT_STATUS_REG_OFFSET( x ) ( (x) + 21 ) // 0x54 / 4 = 21 + + + +//---------------------------------------------------------------------------- +// Constants +// +// Notes: +// 1) These constants are not associated with a particular structure +// and are used globally withing OHCI-specific code +//---------------------------------------------------------------------------- + + + +// Standard OHCI PCI configuration space registers +#define OHCI_BASE_ADDR_REG 0x10 // OHCI BAR register +#define OHCI_CMD_REGISTER 0x04 // OHCI command register + +// Stantdard ED and TD list structure constants +#define OHCI_TERMINATE 0x00000000 + + + +//---------------------------------------------------------------------------- +// Structure types +// +// Notes: +// 1) Constants that are associated with a particular structure +// are defined locally within the structure to facilitate easier +// maintenance. +//---------------------------------------------------------------------------- + + + +#pragma pack(push,1) + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: PCI_BUS_DEV_FUNCTION +// +// Description: +// This structure type defines the bus, device and function number +// that compose a PCI address. +// +// Fields: Type Name Description +// ---------------------------------- +// UINT8 Bus PCI Bus on which a particular OHCI controller resides +// UINT8 Device PCI Device number for a particular OHCI controller +// UINT8 Function PCI Function number for a particular OHCI controller +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct +{ + UINT8 Bus; + UINT8 Device; + UINT8 Function; +} PCI_BUS_DEV_FUNCTION; + + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: OHCI_PCI_PROGRAMMING_TABLE +// +// Description: +// This structure type defines the parameters to be used in a call +// to EFI_PEI_PCI_CFG_PPI.Modify(), when programming the PCI +// configuration space for a particular OHCI controller. +// +// Fields: Type Name Description +// ---------------------------------- +// EFI_PEI_PCI_CFG_PPI_WIDTH Size Size of the access +// UINT32 Register Register/offset within the PCI configuration space +// UINT32 SetBits Bits to set +// UINT32 ClearBits Bits to clear +// +// Notes: +// See also +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct +{ + EFI_PEI_PCI_CFG_PPI_WIDTH Size; + UINT32 Register; + UINT32 SetBits; + UINT32 ClearBits; +} OHCI_PCI_PROGRAMMING_TABLE; + + +typedef struct _HC_CONTROL +{ + union { + UINT32 AllBits; + // Set bits using the following + #define CONTROL_LIST_ENABLE BIT4 + #define BULK_LIST_ENABLE BIT5 + #define USB_RESET 0 << 6 + #define USB_RESUME 1 << 6 + #define USB_OPERATIONAL 2 << 6 + #define USB_SUSPEND 3 << 6 + + struct + { + UINT32 ControlBulkServiceRatio : 2; // [1:0] CBSR + UINT32 PeriodicListEnable : 1; // [2] PLE + UINT32 IsochronousEnable : 1; // [3] IE + UINT32 ControlListEnable : 1; // [4] CLE + // Read: TRUE or FALSE + + UINT32 BulkListEnable : 1; // [5] BLE + // Read: TRUE or FALSE + + UINT32 HostControllerFunctionalState : 2; // [7:6] HCFS + // Write: + #define SET_USB_RESET 0 + #define SET_USB_RESUME 1 + #define SET_USB_OPERATIONAL 2 + #define SET_USB_SUSPEND 3 + + UINT32 InterruptRouting : 1; // [8] IR + UINT32 RemoteWakeupConnected : 1; // [9] RWC + UINT32 RemoteWakeupEnable : 1; // [10] RWE + UINT32 Reserved : 21; // [31:11] + } Field; + }; +} HC_CONTROL; + +// +// Notes: +// To ensure proper updating, follow these guidelines: +// +// 1) Write all bits using the AllBits union element +// (OR bit-constants if modifying multiple fields). +// +// * Writing individual bits may have adverse +// effects. +// +// 2) Typically you will read individual bits using the +// Field union element. +// +// 3) Writing a zero to any field in this register has +// no effect. +// +typedef struct _HC_RH_PORT_STATUS +{ + union { + UINT32 AllBits; + #define SET_PORT_ENABLE BIT1 + #define SET_PORT_SUSPEND BIT2 + #define SET_PORT_RESET BIT4 + #define SET_PORT_POWER BIT8 + + #define CLEAR_PORT_ENABLE BIT0 + #define CLEAR_SUSPEND_STATUS BIT3 + #define CLEAR_PORT_POWER BIT9 + #define CLEAR_CONNECT_STATUS_CHANGE BIT16 + #define CLEAR_PORT_ENABLE_STATUS_CHANGE BIT17 + #define CLEAR_PORT_SUSPEND_STATUS_CHANGE BIT18 + #define CLEAR_PORT_OVERCURRENT_INDICATOR_CHANGE BIT19 + #define CLEAR_PORT_RESET_STATUS_CHANGE BIT20 + + struct + { + UINT32 CurrentConnectStatus : 1; // [0] CCS + #define RH_PORT_CLEAR_ENABLE 1 + UINT32 PortEnableStatus : 1; // [1] PES + #define RH_PORT_SET_ENABLE 1 + UINT32 PortSuspendStatus : 1; // [2] PSS + #define RH_PORT_SET_SUSPEND 1 + UINT32 PortOverCurrentIndicator : 1; // [3] POCI + #define RH_PORT_CLEAR_SUSPEND 1 + UINT32 PortResetStatus : 1; // [4] PRS + #define RH_SET_PORT_RESET 1 // write to initiate reset + #define RH_RESET_ACTIVE 1 // read set if reset active + UINT32 Reserved1 : 3; // [7:5] + UINT32 PortPowerStatus : 1; // [8] PPS + #define RH_PORT_POWER_ON 1 + + UINT32 LowSpeedDeviceAttached : 1; // [9] LSDA + UINT32 Reserved2 : 6; // [15:10] + UINT32 ConnectStatusChange : 1; // [16] CSC + #define RH_PORT_CLEAR_CONNECT_CHANGE 1 + UINT32 PortEnableStatusChange : 1; // [17] PESC + #define RH_PORT_CLEAR_ENABLE_CHANGE 1 + UINT32 PortSuspendStatusChange : 1; // [18] PSSC + UINT32 PortOverCurrentIndicatorChange : 1; // [19] OCIC + UINT32 PortResetStatusChange : 1; // [20] PRSC + #define RH_PORT_CLEAR_RESET_CHANGE 1 + #define PORT_RESET_NOT_COMPLETE 0 + #define PORT_RESET_COMPLETE 1 + UINT32 Reserved3 : 11; // [31:21] + } Field; + }; +} HC_RH_PORT_STATUS; + + +typedef struct _HC_INTERRUPT_STATUS +{ + union { + UINT32 AllBits; + struct + { + #define HCINT_STATUS_CLEAR 1 // write 1 to clear a status bit + + UINT32 SchedulingOverrun : 1; // [0] SO + UINT32 WriteBackDoneHead : 1; // [1] WDH + #define HCINT_WB_DONE 1 + + UINT32 StartofFrame : 1; // [2] SF + UINT32 ResumeDetected : 1; // [3] RD + UINT32 UnrecoverableError : 1; // [4] UE + UINT32 FrameNumberOverflow : 1; // [5] FNO + UINT32 RootHubStatusChange : 1; // [6] RHSC + UINT32 Reserved1 : 23; // [29:7] + UINT32 OwnershipChange : 1; // [30] OC + UINT32 Reserved2 : 1; // [31] + } Field; + }; +} HC_INTERRUPT_STATUS; + + +typedef struct _HC_RH_DESCRIPTORA +{ + union { + UINT32 AllBits; + #define POWERED_SAME (0 << 8) + #define POWERED_INDIVIDUALLY (1 << 8) + #define POWER_SWITCHED (0 << 9) + #define ALWAYS_POWERED (1 << 9) + #define OVERCURRENT_REPORTED_COLLECTIVELY (0 << 11) + #define OVERCURRENT_REPORTED_PER_PORT (1 << 11) + #define OVERCURRENT_COLLECTIVE_PROTECTION (0 << 12) + #define NO_OVERCURRENT_PROTECTION (1 << 12) + + struct + { + UINT32 NumberDownstreamPorts : 8; // [7:0] NDP + UINT32 PowerSwitchingMode : 1; // [8] PSM + #define PSM_COLLECTIVE 0 // all ports powered same + #define PSM_PER_PORT 1 // ports powered individually + + UINT32 NoPowerSwitching : 1; // [9] NPS + #define NPS_SWITCHED 0 // ports are individually + // power switched + #define NPS_NOT_SWITCHED 1 // ports are always on when + // HC is powered + + UINT32 DeviceType : 1; // [10] DT (always 0) + UINT32 OverCurrentProtectionMode : 1; // [11] OCPM + #define OCPM_COLLECTIVE 0 // reported collectively + #define OCPM_PER_PORT 1 // reported per-port + + UINT32 NoOverCurrentProtection : 1; // [12] NOCP + #define NOCP_PROTECTED 0 // reported collectively + #define NOCP_NOT_PROTECTED 1 // no support + + UINT32 Reservered : 11; // [23:13] + UINT32 PowerOnToPowerGoodTime : 8; // [31:24] POTPGT + // (in units of 2ms) + } Field; + }; +} HC_RH_DESCRIPTORA; + + +typedef struct _HC_RH_DESCRIPTORB +{ + union { + UINT32 AllBits; + #define ALL_REMOVEABLE (0x0000 << 0) + #define ALL_PER_PORT_POWER_SWITCHED (0xfffe << 15) + struct + { + UINT32 DeviceRemovable : 16; // [15:0] DR + // Each bit represents a port + // 0 = removable + // 1 = not removable + UINT32 PortPowerControlMask : 16; // [31:16] PPCM + // Each bit represents a port + // 0 = controlled by global + // power switch + // 1 = per-port power control + } Field; + }; +} HC_RH_DESCRIPTORB; + +typedef struct _HC_RH_STATUS +{ + union { + UINT32 AllBits; + struct + { + UINT32 LocalPowerStatus : 1; // [0] LPS + UINT32 OverCurrentIndicator : 1; // [1] OCI + UINT32 Reserved1 : 13; // [14:2] + UINT32 DeviceRemoteWakeupEnable : 1; // [15] DRWE + UINT32 LocalPowerStatusChange : 1; // [16] LPSC + // Write 1 to turn on power to all ports or to ports + // specified by PortPowerControlMask, depending on + // PowerSwitchingMode. + #define SET_GLOBAL_POWER 1 + + UINT32 OverCurrentIndicatorChange : 1; // [17] OCIC + UINT32 Reserved2 : 13; // [30:18] + UINT32 ClearRemoteWakeupEnable : 1; // [31] CRWE + } Field; + }; +} HC_RH_STATUS; + +typedef struct _HC_FM_INTERVAL +{ + union { + UINT32 AllBits; + struct + { + UINT32 FrameInterval : 14; // [13:0] FI + #define FM_INTERVAL_DEFAULT 0x2edf + + UINT32 Reserved : 2; // [15:14] + UINT32 FsLargestDataPacket : 15; // [30:16] FSMPS + // (FrameInterval-210) * 6/7 ==> 0x2778 + // (See OHCI specification) + #define FS_LARGEST_PACKET_DEFAULT 0x2778 + + UINT32 FrameIntervalToggle : 1; // [31] FIT + } Field; + }; +} HC_FM_INTERVAL; + +typedef struct _HC_HCCA +{ + #define OHCI_FRAME_LIST_SIZE 32 + UINT32 HccaInterrruptTable[OHCI_FRAME_LIST_SIZE]; // Offset 0x00 + UINT16 HccaFrameNumber; // Offset 0x80 + UINT16 HccaPad1; // Offset 0x82 + UINT32 HccaDoneHead; // Offset 0x84 + UINT8 HccaReserved[120]; // Offset 0x88 +} HC_HCCA; + +typedef struct _HC_COMMAND_STATUS +{ + union { + UINT32 AllBits; + // Typically write to this entire register + #define SET_CONTROLLER_RESET (1 << 0) + #define SET_CONTROL_LIST_FILLED (1 << 1) + #define SET_BULK_LIST_FILLED (1 << 2) + + struct + { + UINT32 HostControllerReset : 1; // [0] HCR + UINT32 ControlListFilled : 1; // [1] CLF + UINT32 BulkListFilled : 1; // [2] BLF + UINT32 OwnershipChangeRequest : 1; // [3] OCR + UINT32 Reserved1 : 12; // [15:4] + UINT32 SchedulingOverrunCount : 2; // [17:16] SOC + UINT32 Reserved2 : 14; // [31:18] + } Field; + }; +} HC_COMMAND_STATUS; + +typedef struct _OHCI_HC_REGISTERS_ +{ + UINT32 HcRevision; // [31:0] (Offset 00) + HC_CONTROL HcControl; // [63:32] (Offset 04) + HC_COMMAND_STATUS HcCommandStatus; // [95:64] (Offset 08) + HC_INTERRUPT_STATUS HcInterruptStatus; // [127:96] (Offset 0C) + UINT32 HcInterruptEnable; // [159:128] (Offset 10) + UINT32 HcInterruptDisable; // [191:160] (Offset 14) + HC_HCCA *HcHcca; // [223:192] (Offset 18) + UINT32 HcPeriodCurrentEd; // [255:224] (Offset 1C) + UINT32 HcControlHeadEd; // [287:256] (Offset 20) + UINT32 HcControlCurrentEd; // [319:288] (Offset 24) + UINT32 HcBulkHeadEd; // [351:320] (Offset 28) + UINT32 HcBulkCurrentEd; // [383:352] (Offset 2C) + UINT32 HcDoneHead; // [415:384] (Offset 30) + HC_FM_INTERVAL HcFmInterval; // [447:416] (Offset 34) + UINT32 HcFmRemaining; // [479:448] (Offset 38) + HC_FM_INTERVAL HcFmNumber; // [511:480] (Offset 3C) + UINT32 HcPeriodicStart; // [543:512] (Offset 40) + UINT32 HcLsThreshold; // [575:544] (Offset 44) + HC_RH_DESCRIPTORA HcRhDescriptorA; // [607:576] (Offset 48) + HC_RH_DESCRIPTORB HcRhDescriptorB; // [639:608] (Offset 4C) + HC_RH_STATUS HcRhStatus; // [671:640] (Offset 50) + HC_RH_PORT_STATUS HcRhPortStatus[3]; // [767:672] (Offset 54) + UINT32 Reserved[40]; // [2047:768] (Offset 60) + UINT32 HceControl; // [2079:2048] (Offset 100) + UINT32 HceInput; // [2111:2080] (Offset 104) + UINT32 HceOutput; // [2143:2112] (Offset 108) + UINT32 HceStatus; // [2175:2144] (Offset 10C) +} OHCI_HC_REGISTERS; + + +typedef struct _OHCI_TD_ +{ + UINT32 dControlStatus; // Control and status fields + #define GTD_BUFFER_ROUNDING (1 << 18) // [18] BufferRounding + #define GTD_SETUP_PACKET (0 << 19) // [20:19] Direction/PID + #define GTD_OUT_PACKET (1 << 19) + #define GTD_IN_PACKET (2 << 19) + #define GTD_INTD (0 << 21) // [23:21] DelayInterrupt + // depends on device + #define GTD_DATA_TOGGLE (3 << 24) // [25:24] DataToggle + #define GTD_SETUP_TOGGLE (2 << 24) // (see MSB of data toggle) + #define GTD_DATA1_TOGGLE (3 << 24) + #define GTD_NO_ERRORS (0 << 26) // [27:26] ErrorCount + #define GTD_STALL 0x04 // [31:28] ConditionCode + #define GTD_DEVICE_NOT_RESPOND 0x05 + #define GTD_NOT_ACCESSED 0x0f + + UINT8 *fpCurrentBufferPointer; // Current buffer pointer + UINT8 *fpLinkPointer; // Pointer to the next TD + UINT8 *fpBufferEnd; // End pointer of data buffer + #define MAX_CONTROL_DATA_SIZE 0x200 + + UINT32 dCSReloadValue; // Control status reload value + UINT8 bCallBackIndex; // Index of the routine to + // call + // on completion + UINT8 bActiveFlag; // Routine to call on + // completion + UINT8 bDeviceAddr; // Device Address + UINT8 bResvd; + UINT8 aSetupData[8]; // Used for setup packet +} OHCI_TD, *POHCI_TD; + +typedef struct _OHCI_TD_DESCRIPTOR OHCI_TD_DESCRIPTOR; +typedef struct _OHCI_TD_DESCRIPTOR +{ + union { + UINT32 AllBits; + struct + { + UINT32 Reserved : 18; // [17:0] + UINT32 BufferRounding : 1; // [18] R + UINT32 DirectionPid : 2; // [20:19] DP + UINT32 DelayInterrupt : 3; // [23:21] DI + UINT32 DataToggle : 2; // [25:24] T + UINT32 ErrorCount : 2; // [27:26] EC + UINT32 ConditionCode : 4; // [31:28] CC + // 0000 NOERROR + // 0001 CRC + // 0010 BITSTUFFING + // 0011 DATATOGGLEMISMATCH + // 0100 STALL + // 0101 DEVICENOTRESPONDING + // 0110 PIDCHECKFAILURE + // 0111 UNEXPECTEDPID + // 1000 DATAOVERRUN + // 1001 DATAUNDERRUN + // 1010 reserved + // 1011 reserved + // 1100 BUFFEROVERRUN + // 1101 BUFFERUNDERRUN + // 111x NOT ACCESSED + } Field; + } Controlfield; + UINT32 CurrentBufferPointer; + UINT32 NextTd; + UINT32 BufferEnd; +} OHCI_TD_DESCRIPTOR; + + +typedef struct _OHCI_ED_ +{ + UINT32 dControl; // ED control fields + #define ED_OUT_PACKET 0x00000800 + #define ED_IN_PACKET 0x00001000 + #define ED_SKIP_TDQ BIT14 + POHCI_TD fpTailPointer; // TD queue tail pointer + POHCI_TD fpHeadPointer; // TD queue head pointer + struct _OHCI_ED_ *fpEDLinkPointer; // Pointer to next ED + UINT8 aReserved[16]; +} OHCI_ED, *POHCI_ED; + +typedef struct _OHCI_EP_DESCRIPTOR OHCI_EP_DESCRIPTOR; +typedef struct _OHCI_EP_DESCRIPTOR +{ + union { + UINT32 AllBits; + struct + { + UINT32 FunctionAddress : 7; // [6:0] FA + UINT32 EndpointNumber : 4; // [10:7] EN + UINT32 Direction : 2; // [12:11] D + UINT32 Speed : 1; // [13] S + UINT32 Skip : 1; // [14] K + UINT32 Format : 1; // [15] F + UINT32 MaximumPacketSize : 11; // [26:16] MPS + UINT32 Reserved : 5; // [31:27] Reserved + } Field; + } Controlfield; + UINT32 TailPointer; + union { + UINT32 AllBits; + struct + { + UINT32 Halted : 1; // [0] H + UINT32 ToggleCarry : 1; // [1] C + UINT32 Reserved : 29; // [31:2] Reserved + } Field; + } HeadPointer; + OHCI_EP_DESCRIPTOR *NextEndpointDescriptor; +} OHCI_EP_DESCRIPTOR; + + +typedef struct _OHCI_DESC_PTRS_ +{ + POHCI_ED pstED1ms; + POHCI_ED pstED2ms; + POHCI_ED pstED8ms; + // Do not change the following order of ED32ms and TD32ms + POHCI_ED pstED32ms; + POHCI_TD pstTD32ms; + // Do not change the following order of EDRepeat and TDRepeat + POHCI_ED pstEDRepeat; + POHCI_TD pstTDRepeat; + + POHCI_ED pstEDControl; + POHCI_TD pstTDControlSetup; + POHCI_TD pstTDControlData; + POHCI_TD pstTDControlStatus; + + POHCI_ED pstEDInterrupt; + POHCI_TD pstTDInterruptData; + + POHCI_ED pstEDBulk; + POHCI_TD pstTDBulkData; + +} OHCI_DESC_PTRS, *POHCI_DESC_PTRS; + +typedef struct _USB_HC_INFO_ +{ + UINT32 dStateFlag; + UINT8 bHCNum; + UINT8 bHCType; + UINTN *HCCommArea; + UINTN BaseAddr; + UINT8 bPortNum; + UINT16 wBusDevFuncNum; + // FPIRQ_INFO + UINT16 wAsyncListSize; + UINT8 bOpRegOffset; + UINT32 dMaxBulkDataSize; + UINT8 bHCFlag; + // UINT8 bExtCapPtr; //EHCI + // UINT8 bRegOff; + VOID *usb_bus_data; + // EFI_HANDLE Controller; + // EFI_DEVICE_PATH_PROTOCOL *pHCdp; + +} USB_HC_INFO, *PUSB_HC_INFO; + + +typedef struct _PEI_OHCI_DEV +{ + UINTN Signature; + #define PEI_OHCI_DEV_SIGNATURE EFI_SIGNATURE_32( 'p', 'u', 'h', 'c' ) + EFI_PEI_SERVICES **PeiServices; + PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi; + EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; + EFI_PEI_CPU_IO_PPI *CpuIoPpi; + EFI_PEI_STALL_PPI *StallPpi; + EFI_PEI_PCI_CFG_PPI *PciCfgPpi; + UINT32 UsbHostControllerBaseAddress; + + UINT8 bNumPorts; + OHCI_DESC_PTRS stOHCIDescPtrs; + UINT16 wAsyncListSize; + UINT32 dMaxBulkDataSize; + #define MAX_OHCI_BULK_DATA_SIZE 4096 + + UINT32 *pFrameList; // HC Communication Area base + // & HccaInterruptTable base +} PEI_OHCI_DEV, *PPEI_OHCI_DEV; + +#pragma pack(pop) + + + +//---------------------------------------------------------------------------- +// Function prototypes +//---------------------------------------------------------------------------- + + + +EFI_STATUS InitializeUsbHC ( + PEI_OHCI_DEV *UhcDev ); + +VOID OhciInitHC ( + EFI_PEI_SERVICES **PeiServices, + PEI_OHCI_DEV *pUhcDev, + UINT8 Index ); + +VOID OhciHcReset ( + EFI_PEI_SERVICES **PeiServices, + PEI_OHCI_DEV *pUhcDev ); + + +VOID OhciHcEnableRootHub ( + PEI_OHCI_DEV *OhciDevPtr, + UINT8 PortNumber ); + +EFI_STATUS OhciHcWaitForTransferComplete ( + EFI_PEI_SERVICES **PeiServices, + PEI_OHCI_DEV *OhciDevPtr, + POHCI_TD Td ); + +EFI_STATUS OhciHcControlTransfer ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINT8 MaximumPacketLength, + IN UINT16 TransactionTranslator OPTIONAL, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + OUT UINT32 *TransferResult ); + +EFI_STATUS OhciHcBulkTransfer ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINT16 MaximumPacketLength, + IN UINT16 TransactionTranslator OPTIONAL, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult ); + +EFI_STATUS OhciHcGetRootHubPortNumber ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + OUT UINT8 *PortNumber ); + +EFI_STATUS OhciHcGetRootHubPortStatus ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus ); + +EFI_STATUS OhciHcSetRootHubPortFeature ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature ); + +EFI_STATUS OhciHcClearRootHubPortFeature ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_HOST_CONTROLLER_PPI *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature ); + + +#endif + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c b/Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c new file mode 100644 index 0000000..4256cdf --- /dev/null +++ b/Core/EM/UsbRecovery/OhciPEI/OhciPeiBoard.c @@ -0,0 +1,508 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//********************************************************************** +// +// $Header: /Alaska/SOURCE/Modules/USBRecovery/OhciPeiBoard.c 6 4/11/11 11:59p Rameshr $ +// +// $Revision: 6 $ +// +// $Date: 4/11/11 11:59p $ +// +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/USBRecovery/OhciPeiBoard.c $ +// +// 6 4/11/11 11:59p Rameshr +// [TAG]- EIP 57444 +// [Category]-IMPROVEMENT +// [Description]- PI1.1 Support. +// [Files]- OhciPeiboard.c,Xhcipei.c, Peiusblib.c +// +// 5 10/21/08 5:57p Michaela +// Added EHCI-related fixes for issues +// that may occur if EHCI is used before +// USB Recovery is invoked: +// Added SDL Tokens: +// PEI_EHCI_PCI_BDFS and +// PEI_EHCI_MEM_BASE_ADDRESSES. +// +// Removed/modified some debugging +// development code: +// Removed SDL Tokens: +// USBR_DEBUG_SUPPORT and +// USBR_SERIAL_PORT_AVAILABLE +// Removed Elinks: +// UsbRecoveryDebug_DIR and +// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs +// Modified SDL Token: +// FORCE_RECOVERY to default value of 0. +// +// (See this module's Help documentation +// for more information.) +// +// 4 7/29/08 7:50p Michaela +// cleaned-up SB700-specific code +// +// 3 7/29/08 5:50p Michaela +// 1) Updated code to move most porting tasks to SDL +// 2) Added more debug break points and improved interactive +// debugging capability for when a serial port is not available. +// 3) Updated help files +// +// 2 7/18/08 5:04p Michaela +// 1 File-level debugging is now available +// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns +// the keypress so that conditional debugging can +// be dynamic (alphanumeric keys only) +// 3 Added more function headers. +// 4 Removed code that will never be used (I.e., Bala?). +// 5 Moved typedef, contants and extern declarations +// into header files. +// 6 Now all controller blocks are enabled for SB700 +// (EHCI controllers route to companion controller +// by default) +// 7 Removed unused constants and typedefs n OhciPei.h +// (also reorganized the file to make it more +// readable.) +// 8 Renamed many functions/variables according to +// coding standard. +// 9 Removed code initializing data structures for +// periodic lists, as this is not needed. +// 10 Removed the CONTROLLER_TYPE SDL token to +// allow UHCI and OHCI controllers to supported +// simultaneously. (modified MAKE files +// accordingly) +// +// 1 7/10/08 6:35p Michaela +// Updated to support OHCI controllers +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: OhciPeiBoard.c +// +// Description: This file contains routines that are board specific for +// initializing the OHCI controller in the USB Recovery module. +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <PEI.h> +#include <AmiPeiLib.h> +#include <token.h> +#include <PPI/PeiGetUCtrl.h> +#include <PPI/OhciPPI.h> +#include <PPI/stall.h> +#include "OhciPei.h" + +#ifndef PI_SPECIFICATION_VERSION //old Core +extern EFI_STATUS PciCfgModify( +IN CONST EFI_PEI_SERVICES **PeiServices, +IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, +IN UINT64 Address, +IN UINTN SetBits, +IN UINTN ClearBits +); +#endif + +//---------------------------------------------------------------------------- +// Porting Steps: +// +// 1) define/undefine the appropriate southbridge type +// 2) define the OHCI_BASE register +// 3) define registers and their set/clear bits for each register to be +// modified in each controller's PCI configuration space +// +//---------------------------------------------------------------------------- + + +// #define AMD_8111 // define to initialize AMD 8111 SB + +// #define AMD_SB700 // define to initialize AMD SB700 SB + +#define OHCI_BASE PEI_OHCI_IOBASE // first OHCI device is defined + // by SDL token and others + // are programmatically + // determined + +#define OHCI_MMIO_SIZE 0x1000 // size of each MMIO region + +// For the SB700, the SMBUS PCI configuration space is used +// to enable USB hardware in the Southbridge +#define SMBUS_PCI_USB_ENABLE_CFG PEI_PCI_CFG_ADDRESS( 0, 0x14, 0, 0x68 ) +#define SMBUS_PCI_EHCI_BITS BIT2 | BIT6 +#define SMBUS_PCI_OHCI_BITS BIT0 | BIT1 | BIT4 | BIT5 | BIT7 + + + +//<AMI_THDR_START> +//--------------------------------------------------------------------------- +// +// Name: gOhciControllerPciTable +// +// Description: +// This is an array of type: PCI_BUS_DEV_FUNCTION +// +// This array is initialized from the PEI_OHCI_PCI_DEVICES SDL +// token, which specifies a {bus,device,function} entry for each OHCI +// controller. If no OHCI controllers exist, there will be only one +// NULL entry. +// +// This array is used for PCI initialization of OHCI controllers, +// as well as access to PCI configuration registers. +// +// Notes: +// gOhciControllerPciTable and gOhciControllerCount are accessed via +// extern declarations by OHCI generic code to access PCI configuration +// space registers. +// +//--------------------------------------------------------------------------- +//<AMI_THDR_END> + +PCI_BUS_DEV_FUNCTION gOhciControllerPciTable[] = {USBR_OHCI_CONTROLLER_PCI_ADDRESS}; +UINT16 gOhciControllerCount = \ + sizeof(gOhciControllerPciTable) / sizeof(PCI_BUS_DEV_FUNCTION); + + +//<AMI_THDR_START> +//--------------------------------------------------------------------------- +// +// Name: gOhciPciRegisterTable +// +// Description: +// This is an array of type: OHCI_PCI_PROGRAMMING_TABLE +// +// This array is initialized from the OHCI_CONTROLLER_PCI_REGISTER_VALUE +// SDL eLink, which specifies a { RegisterSize, Register, BitsToSet, +// BitsToClear } entry for each register in the PCI configuration space +// that needs to be modified. +// +// This array is used for PCI initialization of OHCI controllers. +// +// Notes: +// If no OHCI controllers exist, there will be only one +// NULL entry. +// +// When this table is used, it is assumed that all OHCI controllers +// are identically programmed for the platform. +// +// Other important notes are: +// +// 1) do not include the BAR register (the first BAR is +// PEI_OHCI_IOBASE and subsequent BAR values are +// calculated from there), +// 2) the command register should be last, as it enables +// the devices MMIO access space. +// +//--------------------------------------------------------------------------- +//<AMI_THDR_END> + +OHCI_PCI_PROGRAMMING_TABLE gOhciPciRegisterTable[] = {USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE}; +#define OHCI_PCI_REGISTER_TABLE_SIZE \ + sizeof(gOhciPciRegisterTable) / sizeof(OHCI_PCI_PROGRAMMING_TABLE) + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DefaultInit +// +// Description: +// This function generically initializes the PCI configuration space +// registers for all the OHCI controllers whose PCI addresses are +// specified by the global PCI_BUS_DEV_FUNCTION array and whose PCI +// register programming details are specified by the global +// OHCI_PCI_PROGRAMMING_TABLE array. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- EFI_PEI_SERVICES pointer +// IN EFI_PEI_PCI_CFG_PPI *Pci +// -- EFI_PEI_PCI_CFG_PPI pointer +// IN EFI_PEI_STALL_PPI *StallPpi +// -- EFI_PEI_STALL_PPI pointer +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS on successful completion +// or valid EFI error code +// +// Notes: +// This function should not need porting. All porting is accomplished +// in the global PCI_BUS_DEV_FUNCTION and OHCI_PCI_PROGRAMMING_TABLE +// arrays, where the former is defined by the +// USBR_OHCI_CONTROLLER_PCI_ADDRESS SDL eLink and the latter is defined +// by the USBR_OHCI_CONTROLLER_PCI_REGISTER_VALUE SDL eLink. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS DefaultInit ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PCI_CFG_PPI *Pci, + IN EFI_PEI_STALL_PPI *StallPpi ) +{ + EFI_STATUS Status; + UINT32 OhciBaseAddress = OHCI_BASE; + UINT16 ControllerIndex; + UINT16 RegisterIndex; + + + //------------------------------------------------------------------------ + // PCI configuration space programming for all OHCI controllers + //------------------------------------------------------------------------ + for (ControllerIndex = 0; + ControllerIndex < gOhciControllerCount; + ControllerIndex++, OhciBaseAddress += OHCI_MMIO_SIZE) + { + + // Program the BAR + //~~~~~~~~~~~~~~~~ + ABORT_ON_ERROR( + Pci->Write( PeiServices, Pci, + EfiPeiPciCfgWidthUint32, + OHCI_PCI_ADDRESS( ControllerIndex, OHCI_BASE_ADDR_REG ), + &OhciBaseAddress ); + ) + + // Program all other registers using gOhciPciRegisterTable[] + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + for (RegisterIndex = 0; + RegisterIndex < OHCI_PCI_REGISTER_TABLE_SIZE; + RegisterIndex++) + { + EFI_PEI_PCI_CFG_PPI_WIDTH Width; + + switch (gOhciPciRegisterTable[RegisterIndex].Size) + { + case 8: + Width = EfiPeiPciCfgWidthUint8; + break; + case 16: + Width = EfiPeiPciCfgWidthUint16; + break; + case 32: + Width = EfiPeiPciCfgWidthUint32; + break; + case 64: + Width = EfiPeiPciCfgWidthUint64; + break; + default: + continue; + } + + ABORT_ON_ERROR( + PciCfgModify( + PeiServices, + Width, + OHCI_PCI_ADDRESS( ControllerIndex, + gOhciPciRegisterTable[RegisterIndex].Register ), + gOhciPciRegisterTable[RegisterIndex].SetBits, + gOhciPciRegisterTable[RegisterIndex].ClearBits ); + ) + } + } + + return Status = EFI_SUCCESS; +} + + +#ifdef AMD_8111 +//----------------------------------------------------- +// This code is not tested, it is simply preserved here +//----------------------------------------------------- + +#define REG_PRI_MEMBASE 0x20 +#define REG_PRI_MEMLIM 0x22 + +EFI_STATUS Amd8111Init ( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PEI_PCI_CFG_PPI *Pci, + EFI_PEI_STALL_PPI *StallPpi ) +{ + EFI_STATUS Status; + UINT32 Buffer32; + UINT16 Buffer16; + UINT16 CmdReg; + volatile UINT32 BaseAddress; + + // + // OHCI is sits behind the PCI brige. So program the PCI bridge + // First program bus numbers so that PCI slots are available + // + Buffer32 = 0x080800; + Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint32, + PEI_PCI_CFG_ADDRESS( 0, 30, 0, REG_PRI_BNUM ), + &Buffer32 + ); + + + // Defines the base of memory range for PCI. 15:4 this 12 bits corresponds + // to 31:20 of mem addr 1MB boundary + BaseAddress = 0xc0c00000; + BaseAddress >>= 16; + BaseAddress &= 0xfffffff0; + Buffer16 = (UINT16) BaseAddress; + Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint16, + PEI_PCI_CFG_ADDRESS( 0, 30, 0, REG_PRI_MEMBASE ), + &Buffer16 + ); + + //Defines the top of the memory range + // BaseAddress = 0xc0c00000; + // BaseAddress += 0x00100000; + // BaseAddress >>= 16; + // BaseAddress &= 0xfffffff0; + // Buffer16 = (UINT16)BaseAddress; + Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint16, + PEI_PCI_CFG_ADDRESS( 0, 30, 0, REG_PRI_MEMLIM ), + &Buffer16 + ); + + //Program the prefectable memory space also. + BaseAddress = 0xc0c00000; + BaseAddress += 0x00100000; + BaseAddress >>= 16; + BaseAddress &= 0xfffffff0; + Buffer16 = (UINT16) BaseAddress; + Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint16, + PEI_PCI_CFG_ADDRESS( 0, 30, 0, 0x24 ), + &Buffer16 + ); + + Pci->Write( PeiServices, Pci, EfiPeiPciCfgWidthUint16, + PEI_PCI_CFG_ADDRESS( 0, 30, 0, 0x26 ), + &Buffer16 + ); + + + //Enable memory space, bus mastering of the root bridge + Pci->Read( + PeiServices, + Pci, + EfiPeiPciCfgWidthUint16, + PEI_PCI_CFG_ADDRESS( 0, 30, 0, 0x04 ), + &CmdReg + ); + CmdReg = (UINT16) (CmdReg | 0x06); + Pci->Write( + PeiServices, + Pci, + EfiPeiPciCfgWidthUint16, + PEI_PCI_CFG_ADDRESS( 0, 30, 0, 0x04 ), + &CmdReg + ); +} +#endif // #ifdef AMD_8111 + + +#ifdef AMD_SB700 +EFI_STATUS AmdSb700Init ( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PEI_PCI_CFG_PPI *Pci, + EFI_PEI_STALL_PPI *StallPpi ) +{ + + //----------------------------------------------------------------------- + // Enable OHCI controllers from the SMBUS PCI configuration space + // using the SMBUS PCI space USB enable register + // + // By default, the companion controller (OHCI) should be the owner + // of the root hub port, so the EHCI controller hardware block + // does not need to be disabled. + //----------------------------------------------------------------------- + ABORT_ON_ERROR( + PciCfgModify( PeiServices, + EfiPeiPciCfgWidthUint8, + SMBUS_PCI_USB_ENABLE_CFG, + SMBUS_PCI_OHCI_BITS + SMBUS_PCI_EHCI_BITS, + 0 + ) + ) + + return EFI_SUCCESS; +} +#endif // #ifdef AMD_SB700 + + + + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: OhciPeiBoardInit +// +// Description: +// This is a porting hook for board-specific OHCI controller +// initialization +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices - +// IN EFI_PEI_PCI_CFG_PPI *Pci - +// IN EFI_PEI_STALL_PPI *StallPpi - +// +// Output: +// VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS OhciPeiBoardInit ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PCI_CFG_PPI *Pci, + IN EFI_PEI_STALL_PPI *StallPpi ) +{ + EFI_STATUS Status = EFI_SUCCESS; + + // SB-specific programming + #if defined (AMD_8111) + Status = Amd8111Init( PeiServices, Pci, StallPpi ); + #elif defined (AMD_SB700) + Status = AmdSb700Init( PeiServices, Pci, StallPpi ); + #endif + + // Generic programming for all OHCI SB, should be called + // for all types of southbridges after platform-specific + // programming has been done. + if (!EFI_ERROR(Status)){ + Status = DefaultInit( PeiServices, Pci, StallPpi ); + } + + // PCI root bridge programming is done. + // At this stage the OHCI controller should be visible and + // Memory mapped IO space should be visible + + return Status; + +} + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2006, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//**********************************************************************
\ No newline at end of file |