QuarkSocPkg: Add new package for Quark SoC X1000

Changes for V4
==============
1) Remove Unicode character from C source file
2) Move delete of QuarkSocPkg\QuarkNorthCluster\Binary\QuarkMicrocode
   from QuarkPlatformPkg commit to QuarkSocPkg commit

Changes for V2
==============
1) Sync with new APIs in SmmCpuFeaturesLib class
2) Use new generic PCI serial driver PciSioSerialDxe in MdeModulePkg
3) Remove PCI serial driver from QuarkSocPkg
4) Apply optimizations to MtrrLib from MtrrLib in UefiCpuPkg
5) Convert all UNI files to utf-8
6) Replace tabs with spaces and remove trailing spaces
7) Add License.txt

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Kinney <michael.d.kinney@intel.com>
Acked-by: Jordan Justen <jordan.l.justen@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19286 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Michael Kinney
2015-12-15 19:22:23 +00:00
committed by mdkinney
parent 46ff196fde
commit 9b6bbcdbfd
176 changed files with 54761 additions and 0 deletions

View File

@@ -0,0 +1,326 @@
/** @file
Implementation of Usb Controller PPI.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <PiPei.h>
#include <Ppi/UsbController.h>
#include <Library/DebugLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PcdLib.h>
#include <Library/PciLib.h>
#include <Library/IoLib.h>
#include "UsbPei.h"
//
// Globals
//
//
EFI_PEI_PPI_DESCRIPTOR mPpiList = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gPeiUsbControllerPpiGuid,
NULL
};
UINTN mIohOhciPciReg[IOH_MAX_OHCI_USB_CONTROLLERS] = {
PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USB_OHCI_DEVICE_NUMBER, IOH_OHCI_FUNCTION_NUMBER, 0)
};
UINTN mIohEhciPciReg[IOH_MAX_EHCI_USB_CONTROLLERS] = {
PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USB_EHCI_DEVICE_NUMBER, IOH_EHCI_FUNCTION_NUMBER, 0),
};
/**
When EHCI get started in DXE, OHCI couldn't get the ownership
of roothub after warm reset because CF@EHCI hasn't been cleared.
We should clear that reg before UpdateBootMode. But Reg@EHCI is
memory-mapped, so need assume a range of space without conflict
in PCI memory space.
@param[in] PeiServices The pointer of EFI_PEI_SERVICES
**/
VOID
SwitchConfigFlag (
IN EFI_PEI_SERVICES **PeiServices
)
{
UINT32 SavBaseAddr;
UINT32 UsbBaseAddr;
UINT16 SaveCmdData;
UINT8 EhciCapLen;
UINT8 Index;
UsbBaseAddr = 0;
for (Index = 0; Index < IOH_MAX_EHCI_USB_CONTROLLERS; Index++) {
UsbBaseAddr = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress);
//
// Manage EHCI on IOH, set UsbBaseAddr
//
SavBaseAddr = PciRead32 (mIohEhciPciReg[Index] | R_IOH_USB_MEMBAR);
PciWrite32 (mIohEhciPciReg[Index] | R_IOH_USB_MEMBAR, UsbBaseAddr);
//
// Save Cmd register
//
SaveCmdData = PciRead16 (mIohEhciPciReg[Index] | R_IOH_USB_COMMAND);
//
// Enable EHCI on IOH
//
PciOr16 (mIohEhciPciReg[Index] | R_IOH_USB_COMMAND, B_IOH_USB_COMMAND_BME | B_IOH_USB_COMMAND_MSE );
//
// Clear CF register on EHCI
//
EhciCapLen = MmioRead8 (UsbBaseAddr + R_IOH_EHCI_CAPLENGTH);
MmioWrite32 (UsbBaseAddr + EhciCapLen + R_IOH_EHCI_CONFIGFLAGS, 0);
DEBUG ((EFI_D_INFO, "CF@EHCI = %x \n", UsbBaseAddr + EhciCapLen + R_IOH_EHCI_CONFIGFLAGS));
//
// Restore EHCI UsbBaseAddr in PCI space
//
PciWrite32 (mIohEhciPciReg[Index] | R_IOH_USB_MEMBAR, SavBaseAddr);
//
// Restore EHCI Command register in PCI space
//
PciWrite16(mIohEhciPciReg[Index] | R_IOH_USB_COMMAND, SaveCmdData);
}
}
/**
Retrieved specified the USB controller information.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This This PEI_USB_CONTROLLER_PPI instance.
@param UsbControllerId Indicate which usb controller information will be retrieved.
@param ControllerType Indicate the controller is Ehci, Ohci, OHCI
@param BaseAddress Indicate the memory bar of the controller
@retval EFI_SUCCESS The reset operation succeeded.
@retval EFI_INVALID_PARAMETER Attributes is not valid.
**/
EFI_STATUS
GetOhciController (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_CONTROLLER_PPI *This,
IN UINT8 UsbControllerId,
IN UINTN *ControllerType,
IN UINTN *BaseAddress
)
{
IOH_OHCI_DEVICE *PeiIohOhciDev;
PeiIohOhciDev = IOH_OHCI_DEVICE_FROM_THIS (This);
if (UsbControllerId >= IOH_MAX_OHCI_USB_CONTROLLERS) {
return EFI_INVALID_PARAMETER;
}
*ControllerType = PEI_OHCI_CONTROLLER;
*BaseAddress = PeiIohOhciDev->MmioBase[UsbControllerId];
return EFI_SUCCESS;
}
/**
Retrieved specified the USB controller information.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This This PEI_USB_CONTROLLER_PPI instance.
@param UsbControllerId Indicate which usb controller information will be retrieved.
@param ControllerType Indicate the controller is Ehci, Ohci, OHCI
@param BaseAddress Indicate the memory bar of the controller
@retval EFI_SUCCESS The reset operation succeeded.
@retval EFI_INVALID_PARAMETER Attributes is not valid.
**/
EFI_STATUS
GetEhciController (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_CONTROLLER_PPI *This,
IN UINT8 UsbControllerId,
IN UINTN *ControllerType,
IN UINTN *BaseAddress
)
{
IOH_EHCI_DEVICE *PeiIohEhciDev;
PeiIohEhciDev = IOH_EHCI_DEVICE_FROM_THIS (This);
if (UsbControllerId >= IOH_MAX_EHCI_USB_CONTROLLERS) {
return EFI_INVALID_PARAMETER;
}
*ControllerType = PEI_EHCI_CONTROLLER;
*BaseAddress = PeiIohEhciDev->MmioBase[UsbControllerId];
return EFI_SUCCESS;
}
/**
Retrieved specified the USB controller information.
@param IohOhciPciReg Ohci device address list.
@param OhciCount The count of the OHCI
@param IohEhciPciReg Ehci device address list.
@param EhciCount The count of the EHCI
**/
VOID
EnableBusMaster (
IN UINTN IohOhciPciReg[],
IN UINT8 OhciCount,
IN UINTN IohEhciPciReg[],
IN UINT8 EhciCount
)
{
UINT8 Index;
UINT16 CmdReg;
for (Index = 0; Index < OhciCount; Index ++) {
CmdReg = PciRead16 (IohOhciPciReg[Index] | R_IOH_USB_COMMAND);
CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_BME );
PciWrite16 (IohOhciPciReg[Index] | R_IOH_USB_COMMAND, CmdReg);
}
for (Index = 0; Index < EhciCount; Index ++) {
CmdReg = PciRead16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND);
CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_BME );
PciWrite16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND, CmdReg);
}
}
PEI_USB_CONTROLLER_PPI mUsbControllerPpi[2] = { {GetOhciController}, {GetEhciController}};
/**
@param FileHandle Handle of the file being invoked.
@param PeiServices Describes the list of possible PEI Services.
@retval EFI_SUCCESS PPI successfully installed
**/
EFI_STATUS
PeimInitializeIchUsb (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
UINTN i;
EFI_PHYSICAL_ADDRESS AllocateAddress;
IOH_OHCI_DEVICE *PeiIohOhciDev;
IOH_EHCI_DEVICE *PeiIohEhciDev;
UINT16 CmdReg;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
1,
&AllocateAddress
);
ASSERT_EFI_ERROR (Status);
EnableBusMaster (
mIohOhciPciReg,
IOH_MAX_OHCI_USB_CONTROLLERS,
mIohEhciPciReg,
IOH_MAX_EHCI_USB_CONTROLLERS
);
if (FeaturePcdGet (PcdEhciRecoveryEnabled)) {
DEBUG ((EFI_D_INFO, "UsbPei:EHCI is used for recovery\n"));
//
// EHCI recovery is enabled
//
PeiIohEhciDev = (IOH_EHCI_DEVICE *)((UINTN)AllocateAddress);
ZeroMem (PeiIohEhciDev, sizeof(IOH_EHCI_DEVICE));
PeiIohEhciDev->Signature = PEI_IOH_EHCI_SIGNATURE;
CopyMem(&(PeiIohEhciDev->UsbControllerPpi), &mUsbControllerPpi[1], sizeof(PEI_USB_CONTROLLER_PPI));
CopyMem(&(PeiIohEhciDev->PpiList), &mPpiList, sizeof(mPpiList));
PeiIohEhciDev->PpiList.Ppi = &PeiIohEhciDev->UsbControllerPpi;
//
// Assign resources and enable Ehci controllers
//
for (i = 0; i < IOH_MAX_EHCI_USB_CONTROLLERS; i++) {
DEBUG ((EFI_D_INFO, "UsbPei:Enable the %dth EHCI controller for recovery\n", i));
PeiIohEhciDev->MmioBase[i] = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress) + IOH_USB_CONTROLLER_MMIO_RANGE * i;
//
// Assign base address register, Enable Bus Master and Memory Io
//
PciWrite32 (mIohEhciPciReg[i] | R_IOH_USB_MEMBAR, PeiIohEhciDev->MmioBase[i]);
CmdReg = PciRead16 (mIohEhciPciReg[i] | R_IOH_USB_COMMAND);
CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_MSE | B_IOH_USB_COMMAND_BME );
PciWrite16 (mIohEhciPciReg[i] | R_IOH_USB_COMMAND, CmdReg);
}
//
// Install USB Controller PPI
//
Status = (**PeiServices).InstallPpi (
PeiServices,
&PeiIohEhciDev->PpiList
);
ASSERT_EFI_ERROR (Status);
} else {
DEBUG ((EFI_D_INFO, "UsbPei:OHCI is used for recovery\n"));
//
// OHCI recovery is enabled
//
SwitchConfigFlag ((EFI_PEI_SERVICES**)PeiServices);
PeiIohOhciDev = (IOH_OHCI_DEVICE *)((UINTN)AllocateAddress);
ZeroMem (PeiIohOhciDev, sizeof(IOH_OHCI_DEVICE));
PeiIohOhciDev->Signature = PEI_IOH_OHCI_SIGNATURE;
CopyMem(&(PeiIohOhciDev->UsbControllerPpi), &mUsbControllerPpi[0], sizeof(PEI_USB_CONTROLLER_PPI));
CopyMem(&(PeiIohOhciDev->PpiList), &mPpiList, sizeof(mPpiList));
PeiIohOhciDev->PpiList.Ppi = &PeiIohOhciDev->UsbControllerPpi;
//
// Assign resources and enable OHCI controllers
//
for (i = 0; i < IOH_MAX_OHCI_USB_CONTROLLERS; i++) {
DEBUG ((EFI_D_INFO, "UsbPei:Enable the %dth OHCI controller for recovery\n", i));
PeiIohOhciDev->MmioBase[i] = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress) + IOH_USB_CONTROLLER_MMIO_RANGE * i;
//
// Assign base address register, Enable Bus Master and Memory Io
//
PciWrite32 (mIohOhciPciReg[i] | R_IOH_USB_MEMBAR, PeiIohOhciDev->MmioBase[i]);
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
1,
&AllocateAddress
);
ASSERT_EFI_ERROR (Status);
MmioWrite32(PeiIohOhciDev->MmioBase[i] + R_IOH_USB_OHCI_HCCABAR, (UINT32)AllocateAddress);
CmdReg = PciRead16 (mIohOhciPciReg[i] | R_IOH_USB_COMMAND);
CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_MSE | B_IOH_USB_COMMAND_BME );
PciWrite16 (mIohOhciPciReg[i] | R_IOH_USB_COMMAND, CmdReg);
}
//
// Install USB Controller PPI
//
Status = (**PeiServices).InstallPpi (
PeiServices,
&PeiIohOhciDev->PpiList
);
ASSERT_EFI_ERROR (Status);
}
return Status;
}

View File

@@ -0,0 +1,44 @@
/** @file
Define private data structure for UHCI and EHCI.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _USB_PEI_H
#define _USB_PEI_H
#include "Ioh.h"
#define PEI_IOH_OHCI_SIGNATURE SIGNATURE_32 ('O', 'H', 'C', 'I')
#define PEI_IOH_EHCI_SIGNATURE SIGNATURE_32 ('E', 'H', 'C', 'I')
typedef struct {
UINTN Signature;
PEI_USB_CONTROLLER_PPI UsbControllerPpi;
EFI_PEI_PPI_DESCRIPTOR PpiList;
UINTN MmioBase[IOH_MAX_OHCI_USB_CONTROLLERS];
} IOH_OHCI_DEVICE;
typedef struct {
UINTN Signature;
PEI_USB_CONTROLLER_PPI UsbControllerPpi;
EFI_PEI_PPI_DESCRIPTOR PpiList;
UINTN MmioBase[IOH_MAX_EHCI_USB_CONTROLLERS];
} IOH_EHCI_DEVICE;
#define IOH_OHCI_DEVICE_FROM_THIS(a) \
CR(a, IOH_OHCI_DEVICE, UsbControllerPpi, PEI_IOH_OHCI_SIGNATURE)
#define IOH_EHCI_DEVICE_FROM_THIS(a) \
CR (a, IOH_EHCI_DEVICE, UsbControllerPpi, PEI_IOH_EHCI_SIGNATURE)
#endif

View File

@@ -0,0 +1,59 @@
## @file
# Component description file for UsbPei module.
#
# Copyright (c) 2013-2015 Intel Corporation.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = UsbPei
FILE_GUID = 73E6F6B4-D029-4e87-8405-6067C8BD02A6
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = PeimInitializeIchUsb
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
UsbPei.c
UsbPei.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
QuarkSocPkg/QuarkSocPkg.dec
[LibraryClasses]
IoLib
PciLib
PcdLib
BaseMemoryLib
PeimEntryPoint
DebugLib
[Ppis]
gPeiUsbControllerPpiGuid # PPI ALWAYS_PRODUCED
[FeaturePcd]
gEfiQuarkSCSocIdTokenSpaceGuid.PcdEhciRecoveryEnabled
[Pcd]
gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiQNCUsbControllerMemoryBaseAddress
gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiP2PMemoryBaseAddress
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid

View File

@@ -0,0 +1,225 @@
/** @file
UEFI Component Name and Name2 protocol for OHCI driver.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ohci.h"
//
// EFI Component Name Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gOhciComponentName = {
OhciComponentNameGetDriverName,
OhciComponentNameGetControllerName,
"eng"
};
//
// EFI Component Name 2 Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gOhciComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) OhciComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) OhciComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mOhciDriverNameTable[] = {
{ "eng;en", L"Usb Ohci Driver" },
{ NULL, NULL }
};
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param DriverName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
OhciComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mOhciDriverNameTable,
DriverName,
(BOOLEAN)(This == &gOhciComponentName)
);
}
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param ControllerHandle[in] The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param ChildHandle[in] The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param ControllerName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
OhciComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
EFI_STATUS Status;
USB_OHCI_HC_DEV *OhciDev;
EFI_USB_HC_PROTOCOL *UsbHc;
//
// This is a device driver, so ChildHandle must be NULL.
//
if (ChildHandle != NULL) {
return EFI_UNSUPPORTED;
}
//
// Make sure this driver is currently managing ControllerHandle
//
Status = EfiTestManagedDevice (
ControllerHandle,
gOhciDriverBinding.DriverBindingHandle,
&gEfiPciIoProtocolGuid
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the device context
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiUsbHcProtocolGuid,
(VOID **) &UsbHc,
gOhciDriverBinding.DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
OhciDev = USB_OHCI_HC_DEV_FROM_THIS (UsbHc);
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
OhciDev->ControllerNameTable,
ControllerName,
(BOOLEAN)(This == &gOhciComponentName)
);
}

View File

@@ -0,0 +1,147 @@
/** @file
This file contains the delarations for componet name routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _COMPONENT_NAME_H_
#define _COMPONENT_NAME_H_
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param DriverName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
OhciComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param ControllerHandle[in] The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param ChildHandle[in] The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param ControllerName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
OhciComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
#endif

View File

@@ -0,0 +1,138 @@
/** @file
This file contains the descriptor definination of OHCI spec
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _DESCRIPTOR_H
#define _DESCRIPTOR_H
#define ED_FUNC_ADD 0x0001
#define ED_ENDPT_NUM 0x0002
#define ED_DIR 0x0004
#define ED_SPEED 0x0008
#define ED_SKIP 0x0010
#define ED_FORMAT 0x0020
#define ED_MAX_PACKET 0x0040
#define ED_TDTAIL_PTR 0x0080
#define ED_HALTED 0x0100
#define ED_DTTOGGLE 0x0200
#define ED_TDHEAD_PTR 0x0400
#define ED_NEXT_EDPTR 0x0800
#define ED_PDATA 0x1000
#define ED_ZERO 0x2000
#define TD_BUFFER_ROUND 0x0001
#define TD_DIR_PID 0x0002
#define TD_DELAY_INT 0x0004
#define TD_DT_TOGGLE 0x0008
#define TD_ERROR_CNT 0x0010
#define TD_COND_CODE 0x0020
#define TD_CURR_BUFFER_PTR 0x0040
#define TD_NEXT_PTR 0x0080
#define TD_BUFFER_END_PTR 0x0100
#define TD_PDATA 0x0200
#define ED_FROM_TD_DIR 0x0
#define ED_OUT_DIR 0x1
#define ED_IN_DIR 0x2
#define ED_FROM_TD_ALSO_DIR 0x3
#define TD_SETUP_PID 0x00
#define TD_OUT_PID 0x01
#define TD_IN_PID 0x02
#define TD_NODATA_PID 0x03
#define HI_SPEED 0
#define LO_SPEED 1
#define TD_NO_ERROR 0x00
#define TD_CRC_ERROR 0x01
#define TD_BITSTUFFING_ERROR 0x02
#define TD_TOGGLE_ERROR 0x03
#define TD_DEVICE_STALL 0x04
#define TD_NO_RESPONSE 0x05
#define TD_PIDCHK_FAIL 0x06
#define TD_PID_UNEXPECTED 0x07
#define TD_DATA_OVERRUN 0x08
#define TD_DATA_UNDERRUN 0x09
#define TD_BUFFER_OVERRUN 0x0C
#define TD_BUFFER_UNDERRUN 0x0D
#define TD_TOBE_PROCESSED 0x0E
#define TD_TOBE_PROCESSED_2 0x0F
#define TD_NO_DELAY 0x7
#define TD_INT 0x1
#define TD_CTL 0x2
#define TD_BLK 0x3
typedef struct {
UINT32 Reserved:18;
UINT32 BufferRounding:1;
UINT32 DirPID:2;
UINT32 DelayInterrupt:3;
UINT32 DataToggle:2;
UINT32 ErrorCount:2;
UINT32 ConditionCode:4;
} TD_DESCRIPTOR_WORD0;
typedef struct _TD_DESCRIPTOR {
TD_DESCRIPTOR_WORD0 Word0;
UINT32 CurrBufferPointer; // 32-bit Physical Address of buffer
UINT32 NextTD; // 32-bit Physical Address of TD_DESCRIPTOR
UINT32 BufferEndPointer; // 32-bit Physical Address of buffer
UINT32 NextTDPointer; // 32-bit Physical Address of TD_DESCRIPTOR
UINT32 DataBuffer; // 32-bit Physical Address of buffer
UINT32 ActualSendLength;
UINT32 Reserved;
} TD_DESCRIPTOR;
typedef struct {
UINT32 FunctionAddress:7;
UINT32 EndPointNum:4;
UINT32 Direction:2;
UINT32 Speed:1;
UINT32 Skip:1;
UINT32 Format:1;
UINT32 MaxPacketSize:11;
UINT32 FreeSpace:5;
} ED_DESCRIPTOR_WORD0;
typedef struct {
UINT32 Halted:1;
UINT32 ToggleCarry:1;
UINT32 Zero:2;
UINT32 TdHeadPointer:28;
} ED_DESCRIPTOR_WORD2;
typedef struct _ED_DESCRIPTOR {
ED_DESCRIPTOR_WORD0 Word0;
UINT32 TdTailPointer; // 32-bit Physical Address of TD_DESCRIPTOR
ED_DESCRIPTOR_WORD2 Word2;
UINT32 NextED; // 32-bit Physical Address of ED_DESCRIPTOR
} ED_DESCRIPTOR;
#define TD_PTR(p) ((TD_DESCRIPTOR *)(UINTN)((p) << 4))
#define ED_PTR(p) ((ED_DESCRIPTOR *)(UINTN)((p) << 4))
#define RIGHT_SHIFT_4(p) ((UINT32)(p) >> 4)
typedef enum {
CONTROL_LIST,
BULK_LIST,
INTERRUPT_LIST,
ISOCHRONOUS_LIST
} DESCRIPTOR_LIST_TYPE;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,669 @@
/** @file
Provides the definition of Usb Hc Protocol and OHCI controller
private data structure.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_H
#define _OHCI_H
#include <Uefi.h>
#include <Protocol/UsbHostController.h>
#include <Protocol/PciIo.h>
#include <Guid/EventGroup.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/MemoryAllocationLib.h>
#include <IndustryStandard/Pci.h>
typedef struct _USB_OHCI_HC_DEV USB_OHCI_HC_DEV;
#include "UsbHcMem.h"
#include "OhciReg.h"
#include "OhciSched.h"
#include "OhciUrb.h"
#include "Descriptor.h"
#include "ComponentName.h"
#include "OhciDebug.h"
extern EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL gOhciComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gOhciComponentName2;
#define USB_OHCI_HC_DEV_SIGNATURE SIGNATURE_32('o','h','c','i')
typedef struct _HCCA_MEMORY_BLOCK{
UINT32 HccaInterruptTable[32]; // 32-bit Physical Address to ED_DESCRIPTOR
UINT16 HccaFrameNumber;
UINT16 HccaPad;
UINT32 HccaDoneHead; // 32-bit Physical Address to TD_DESCRIPTOR
UINT8 Reserved[116];
} HCCA_MEMORY_BLOCK;
struct _USB_OHCI_HC_DEV {
UINTN Signature;
EFI_USB_HC_PROTOCOL UsbHc;
EFI_USB2_HC_PROTOCOL Usb2Hc;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT64 OriginalPciAttributes;
HCCA_MEMORY_BLOCK *HccaMemoryBlock;
VOID *HccaMemoryBuf;
VOID *HccaMemoryMapping;
UINTN HccaMemoryPages;
ED_DESCRIPTOR *IntervalList[6][32];
INTERRUPT_CONTEXT_ENTRY *InterruptContextList;
VOID *MemPool;
UINT32 ToggleFlag;
EFI_EVENT HouseKeeperTimer;
//
// ExitBootServicesEvent is used to stop the OHC DMA operation
// after exit boot service.
//
EFI_EVENT ExitBootServiceEvent;
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
};
#define USB_OHCI_HC_DEV_FROM_THIS(a) CR(a, USB_OHCI_HC_DEV, UsbHc, USB_OHCI_HC_DEV_SIGNATURE)
#define USB2_OHCI_HC_DEV_FROM_THIS(a) CR(a, USB_OHCI_HC_DEV, Usb2Hc, USB_OHCI_HC_DEV_SIGNATURE)
//
// Func List
//
/**
Provides software reset for the USB host controller.
@param This This EFI_USB_HC_PROTOCOL instance.
@param Attributes A bit mask of the reset operation to perform.
@retval EFI_SUCCESS The reset operation succeeded.
@retval EFI_INVALID_PARAMETER Attributes is not valid.
@retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
not currently supported by the host controller.
@retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
**/
EFI_STATUS
EFIAPI
OhciReset (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT16 Attributes
);
/**
Retrieve the current state of the USB host controller.
@param This This EFI_USB_HC_PROTOCOL instance.
@param State Variable to return the current host controller
state.
@retval EFI_SUCCESS Host controller state was returned in State.
@retval EFI_INVALID_PARAMETER State is NULL.
@retval EFI_DEVICE_ERROR An error was encountered while attempting to
retrieve the host controller's current state.
**/
EFI_STATUS
EFIAPI
OhciGetState (
IN EFI_USB_HC_PROTOCOL *This,
OUT EFI_USB_HC_STATE *State
);
/**
Sets the USB host controller to a specific state.
@param This This EFI_USB_HC_PROTOCOL instance.
@param State The state of the host controller that will be set.
@retval EFI_SUCCESS The USB host controller was successfully placed
in the state specified by State.
@retval EFI_INVALID_PARAMETER State is invalid.
@retval EFI_DEVICE_ERROR Failed to set the state due to device error.
**/
EFI_STATUS
EFIAPI
OhciSetState(
IN EFI_USB_HC_PROTOCOL *This,
IN EFI_USB_HC_STATE State
);
/**
Submits control transfer to a target USB device.
@param This A pointer to the EFI_USB_HC_PROTOCOL instance.
@param DeviceAddress Represents the address of the target device on the USB,
which is assigned during USB enumeration.
@param IsSlowDevice Indicates whether the target device is slow device
or full-speed device.
@param MaxPaketLength Indicates the maximum packet size that the
default control transfer endpoint is capable of
sending or receiving.
@param Request A pointer to the USB device request that will be sent
to the USB device.
@param TransferDirection Specifies the data direction for the transfer.
There are three values available, DataIn, DataOut
and NoData.
@param Data A pointer to the buffer of data that will be transmitted
to USB device or received from USB device.
@param DataLength Indicates the size, in bytes, of the data buffer
specified by Data.
@param TimeOut Indicates the maximum time, in microseconds,
which the transfer is allowed to complete.
@param TransferResult A pointer to the detailed result information generated
by this control transfer.
@retval EFI_SUCCESS The control transfer was completed successfully.
@retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_TIMEOUT The control transfer failed due to timeout.
@retval EFI_DEVICE_ERROR The control transfer failed due to host controller or device error.
Caller should check TranferResult for detailed error information.
--*/
EFI_STATUS
EFIAPI
OhciControlTransfer (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 DeviceAddress,
IN BOOLEAN IsSlowDevice,
IN UINT8 MaxPacketLength,
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
);
/**
Submits bulk transfer to a bulk endpoint of a USB device.
@param This A pointer to the EFI_USB_HC_PROTOCOL instance.
@param DeviceAddress Represents the address of the target device on the USB,
which is assigned during USB enumeration.
@param EndPointAddress The combination of an endpoint number and an
endpoint direction of the target USB device.
Each endpoint address supports data transfer in
one direction except the control endpoint
(whose default endpoint address is 0).
It is the caller's responsibility to make sure that
the EndPointAddress represents a bulk endpoint.
@param MaximumPacketLength Indicates the maximum packet size the target endpoint
is capable of sending or receiving.
@param Data A pointer to the buffer of data that will be transmitted
to USB device or received from USB device.
@param DataLength When input, indicates the size, in bytes, of the data buffer
specified by Data. When output, indicates the actually
transferred data size.
@param DataToggle A pointer to the data toggle value. On input, it indicates
the initial data toggle value the bulk transfer should adopt;
on output, it is updated to indicate the data toggle value
of the subsequent bulk transfer.
@param TimeOut Indicates the maximum time, in microseconds, which the
transfer is allowed to complete.
TransferResult A pointer to the detailed result information of the
bulk transfer.
@retval EFI_SUCCESS The bulk transfer was completed successfully.
@retval EFI_OUT_OF_RESOURCES The bulk transfer could not be submitted due to lack of resource.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_TIMEOUT The bulk transfer failed due to timeout.
@retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error.
Caller should check TranferResult for detailed error information.
**/
EFI_STATUS
EFIAPI
OhciBulkTransfer(
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN UINT8 MaxPacketLength,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN OUT UINT8 *DataToggle,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
);
/**
Submits an interrupt transfer to an interrupt endpoint of a USB device.
@param Ohc Device private data
@param DeviceAddress Represents the address of the target device on the USB,
which is assigned during USB enumeration.
@param EndPointAddress The combination of an endpoint number and an endpoint
direction of the target USB device. Each endpoint address
supports data transfer in one direction except the
control endpoint (whose default endpoint address is 0).
It is the caller's responsibility to make sure that
the EndPointAddress represents an interrupt endpoint.
@param IsSlowDevice Indicates whether the target device is slow device
or full-speed device.
@param MaxPacketLength Indicates the maximum packet size the target endpoint
is capable of sending or receiving.
@param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
the host and the target interrupt endpoint.
If FALSE, the specified asynchronous interrupt pipe
is canceled.
@param DataToggle A pointer to the data toggle value. On input, it is valid
when IsNewTransfer is TRUE, and it indicates the initial
data toggle value the asynchronous interrupt transfer
should adopt.
On output, it is valid when IsNewTransfer is FALSE,
and it is updated to indicate the data toggle value of
the subsequent asynchronous interrupt transfer.
@param PollingInterval Indicates the interval, in milliseconds, that the
asynchronous interrupt transfer is polled.
This parameter is required when IsNewTransfer is TRUE.
@param UCBuffer Uncacheable buffer
@param DataLength Indicates the length of data to be received at the
rate specified by PollingInterval from the target
asynchronous interrupt endpoint. This parameter
is only required when IsNewTransfer is TRUE.
@param CallBackFunction The Callback function.This function is called at the
rate specified by PollingInterval.This parameter is
only required when IsNewTransfer is TRUE.
@param Context The context that is passed to the CallBackFunction.
This is an optional parameter and may be NULL.
@param IsPeriodic Periodic interrupt or not
@param OutputED The correspoding ED carried out
@param OutputTD The correspoding TD carried out
@retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
submitted or canceled.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
**/
EFI_STATUS
OhciInterruptTransfer (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN BOOLEAN IsSlowDevice,
IN UINT8 MaxPacketLength,
IN BOOLEAN IsNewTransfer,
IN OUT UINT8 *DataToggle OPTIONAL,
IN UINTN PollingInterval OPTIONAL,
IN VOID *UCBuffer OPTIONAL,
IN UINTN DataLength OPTIONAL,
IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,
IN VOID *Context OPTIONAL,
IN BOOLEAN IsPeriodic OPTIONAL,
OUT ED_DESCRIPTOR **OutputED OPTIONAL,
OUT TD_DESCRIPTOR **OutputTD OPTIONAL
);
/**
Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.
@param This A pointer to the EFI_USB_HC_PROTOCOL instance.
@param DeviceAddress Represents the address of the target device on the USB,
which is assigned during USB enumeration.
@param EndPointAddress The combination of an endpoint number and an endpoint
direction of the target USB device. Each endpoint address
supports data transfer in one direction except the
control endpoint (whose default endpoint address is 0).
It is the caller's responsibility to make sure that
the EndPointAddress represents an interrupt endpoint.
@param IsSlowDevice Indicates whether the target device is slow device
or full-speed device.
@param MaxiumPacketLength Indicates the maximum packet size the target endpoint
is capable of sending or receiving.
@param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
the host and the target interrupt endpoint.
If FALSE, the specified asynchronous interrupt pipe
is canceled.
@param DataToggle A pointer to the data toggle value. On input, it is valid
when IsNewTransfer is TRUE, and it indicates the initial
data toggle value the asynchronous interrupt transfer
should adopt.
On output, it is valid when IsNewTransfer is FALSE,
and it is updated to indicate the data toggle value of
the subsequent asynchronous interrupt transfer.
@param PollingInterval Indicates the interval, in milliseconds, that the
asynchronous interrupt transfer is polled.
This parameter is required when IsNewTransfer is TRUE.
@param DataLength Indicates the length of data to be received at the
rate specified by PollingInterval from the target
asynchronous interrupt endpoint. This parameter
is only required when IsNewTransfer is TRUE.
@param CallBackFunction The Callback function.This function is called at the
rate specified by PollingInterval.This parameter is
only required when IsNewTransfer is TRUE.
@param Context The context that is passed to the CallBackFunction.
This is an optional parameter and may be NULL.
@retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
submitted or canceled.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
**/
EFI_STATUS
EFIAPI
OhciAsyncInterruptTransfer (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN BOOLEAN IsSlowDevice,
IN UINT8 MaxPacketLength,
IN BOOLEAN IsNewTransfer,
IN OUT UINT8 *DataToggle OPTIONAL,
IN UINTN PollingInterval OPTIONAL,
IN UINTN DataLength OPTIONAL,
IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,
IN VOID *Context OPTIONAL
);
/**
Submits synchronous interrupt transfer to an interrupt endpoint
of a USB device.
@param This A pointer to the EFI_USB_HC_PROTOCOL instance.
@param DeviceAddress Represents the address of the target device on the USB,
which is assigned during USB enumeration.
@param EndPointAddress The combination of an endpoint number and an endpoint
direction of the target USB device. Each endpoint
address supports data transfer in one direction
except the control endpoint (whose default
endpoint address is 0). It is the caller's responsibility
to make sure that the EndPointAddress represents
an interrupt endpoint.
@param IsSlowDevice Indicates whether the target device is slow device
or full-speed device.
@param MaxPacketLength Indicates the maximum packet size the target endpoint
is capable of sending or receiving.
@param Data A pointer to the buffer of data that will be transmitted
to USB device or received from USB device.
@param DataLength On input, the size, in bytes, of the data buffer specified
by Data. On output, the number of bytes transferred.
@param DataToggle A pointer to the data toggle value. On input, it indicates
the initial data toggle value the synchronous interrupt
transfer should adopt;
on output, it is updated to indicate the data toggle value
of the subsequent synchronous interrupt transfer.
@param TimeOut Indicates the maximum time, in microseconds, which the
transfer is allowed to complete.
@param TransferResult A pointer to the detailed result information from
the synchronous interrupt transfer.
@retval EFI_UNSUPPORTED This interface not available.
@retval EFI_INVALID_PARAMETER Parameters not follow spec
**/
EFI_STATUS
EFIAPI
OhciSyncInterruptTransfer (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN BOOLEAN IsSlowDevice,
IN UINT8 MaxPacketLength,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN OUT UINT8 *DataToggle,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
);
/**
Submits isochronous transfer to a target USB device.
@param This A pointer to the EFI_USB_HC_PROTOCOL instance.
@param DeviceAddress Represents the address of the target device on the USB,
which is assigned during USB enumeration.
@param EndPointAddress End point address
@param MaximumPacketLength Indicates the maximum packet size that the
default control transfer endpoint is capable of
sending or receiving.
@param Data A pointer to the buffer of data that will be transmitted
to USB device or received from USB device.
@param DataLength Indicates the size, in bytes, of the data buffer
specified by Data.
@param TransferResult A pointer to the detailed result information generated
by this control transfer.
@retval EFI_UNSUPPORTED This interface not available
@retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL
**/
EFI_STATUS
EFIAPI
OhciIsochronousTransfer (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN UINT8 MaximumPacketLength,
IN OUT VOID *Data,
IN OUT UINTN DataLength,
OUT UINT32 *TransferResult
);
/**
Submits Async isochronous transfer to a target USB device.
@param his A pointer to the EFI_USB_HC_PROTOCOL instance.
@param DeviceAddress Represents the address of the target device on the USB,
which is assigned during USB enumeration.
@param EndPointAddress End point address
@param MaximumPacketLength Indicates the maximum packet size that the
default control transfer endpoint is capable of
sending or receiving.
@param Data A pointer to the buffer of data that will be transmitted
to USB device or received from USB device.
@param IsochronousCallBack When the transfer complete, the call back function will be called
@param Context Pass to the call back function as parameter
@retval EFI_UNSUPPORTED This interface not available
@retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0
**/
EFI_STATUS
EFIAPI
OhciAsyncIsochronousTransfer (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN UINT8 MaximumPacketLength,
IN OUT VOID *Data,
IN OUT UINTN DataLength,
IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
IN VOID *Context OPTIONAL
);
/**
Retrieves the number of root hub ports.
@param This A pointer to the EFI_USB_HC_PROTOCOL instance.
@param NumOfPorts A pointer to the number of the root hub ports.
@retval EFI_SUCCESS The port number was retrieved successfully.
**/
EFI_STATUS
EFIAPI
OhciGetRootHubNumOfPorts (
IN EFI_USB_HC_PROTOCOL *This,
OUT UINT8 *NumOfPorts
);
/**
Retrieves the current status of a USB root hub port.
@param This A pointer to the EFI_USB_HC_PROTOCOL.
@param PortNumber Specifies the root hub port from which the status
is to be retrieved. This value is zero-based. For example,
if a root hub has two ports, then the first port is numbered 0,
and the second port is numbered 1.
@param PortStatus A pointer to the current port status bits and
port status change bits.
@retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber
was returned in PortStatus.
@retval EFI_INVALID_PARAMETER Port number not valid
**/
EFI_STATUS
EFIAPI
OhciGetRootHubPortStatus (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 PortNumber,
OUT EFI_USB_PORT_STATUS *PortStatus
);
/**
Sets a feature for the specified root hub port.
@param This A pointer to the EFI_USB_HC_PROTOCOL.
@param PortNumber Specifies the root hub port whose feature
is requested to be set.
@param PortFeature Indicates the feature selector associated
with the feature set request.
@retval EFI_SUCCESS The feature specified by PortFeature was set for the
USB root hub port specified by PortNumber.
@retval EFI_DEVICE_ERROR Set feature failed because of hardware issue
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
**/
EFI_STATUS
EFIAPI
OhciSetRootHubPortFeature (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
/**
Clears a feature for the specified root hub port.
@param This A pointer to the EFI_USB_HC_PROTOCOL instance.
@param PortNumber Specifies the root hub port whose feature
is requested to be cleared.
@param PortFeature Indicates the feature selector associated with the
feature clear request.
@retval EFI_SUCCESS The feature specified by PortFeature was cleared for the
USB root hub port specified by PortNumber.
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
@retval EFI_DEVICE_ERROR Some error happened when clearing feature
**/
EFI_STATUS
EFIAPI
OhciClearRootHubPortFeature (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
/**
Test to see if this driver supports ControllerHandle. Any
ControllerHandle that has UsbHcProtocol installed will be supported.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
@param RemainingDevicePath Not used.
@return EFI_SUCCESS This driver supports this device.
@return EFI_UNSUPPORTED This driver does not support this device.
**/
EFI_STATUS
EFIAPI
OHCIDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
/**
Starting the Usb OHCI Driver.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
@param RemainingDevicePath Not used.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_UNSUPPORTED This driver does not support this device.
@retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
**/
EFI_STATUS
EFIAPI
OHCIDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
/**
Stop this driver on ControllerHandle. Support stoping any child handles
created by this driver.
@param This Protocol instance pointer.
@param Controller Handle of device to stop driver on.
@param NumberOfChildren Number of Children in the ChildHandleBuffer.
@param ChildHandleBuffer List of handles for the children we need to stop.
@return EFI_SUCCESS
@return others
**/
EFI_STATUS
EFIAPI
OHCIDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
#endif

View File

@@ -0,0 +1,84 @@
/** @file
This file provides the information dump support for OHCI when in debug mode.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ohci.h"
/*++
Print the data of ED and the TDs attached to the ED
@param Uhc Pointer to OHCI private data
@param Ed Pointer to a ED to free
@param Td Pointer to the Td head
@retval EFI_SUCCESS ED
**/
EFI_STATUS
OhciDumpEdTdInfo (
IN USB_OHCI_HC_DEV *Uhc,
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *Td,
BOOLEAN Stage
)
{
UINT32 Index;
if (Stage) {
DEBUG ((EFI_D_INFO, "\n Before executing command\n"));
}else{
DEBUG ((EFI_D_INFO, "\n after executing command\n"));
}
if (Ed != NULL) {
DEBUG ((EFI_D_INFO, "\nED Address:%p, ED buffer:\n", Ed));
DEBUG ((EFI_D_INFO, "DWord0 :TD Tail :TD Head :Next ED\n"));
for (Index = 0; Index < sizeof (ED_DESCRIPTOR)/4; Index ++) {
DEBUG ((EFI_D_INFO, "%8x ", *((UINT32*)(Ed) + Index) ));
}
DEBUG ((EFI_D_INFO, "\nNext TD buffer:%p\n", Td));
}
while (Td != NULL) {
if (Td->Word0.DirPID == TD_SETUP_PID) {
DEBUG ((EFI_D_INFO, "\nSetup PID "));
}else if (Td->Word0.DirPID == TD_OUT_PID) {
DEBUG ((EFI_D_INFO, "\nOut PID "));
}else if (Td->Word0.DirPID == TD_IN_PID) {
DEBUG ((EFI_D_INFO, "\nIn PID "));
}else if (Td->Word0.DirPID == TD_NODATA_PID) {
DEBUG ((EFI_D_INFO, "\nNo data PID "));
}
DEBUG ((EFI_D_INFO, "TD Address:%p, TD buffer:\n", Td));
DEBUG ((EFI_D_INFO, "DWord0 :CuBuffer:Next TD :Buff End:Next TD :DataBuff:ActLength\n"));
for (Index = 0; Index < sizeof (TD_DESCRIPTOR)/4; Index ++) {
DEBUG ((EFI_D_INFO, "%8x ", *((UINT32*)(Td) + Index) ));
}
DEBUG ((EFI_D_INFO, "\nCurrent TD Data buffer(size%d)\n", (UINT32)Td->ActualSendLength));
for (Index = 0; Index < Td->ActualSendLength; Index ++) {
DEBUG ((EFI_D_INFO, "%2x ", *(UINT8 *)(UINTN)(Td->DataBuffer + Index) ));
}
Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);
}
DEBUG ((EFI_D_INFO, "\n TD buffer End\n"));
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,48 @@
/** @file
This file contains the definination for host controller
debug support routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
/*++
Routine Description:
Print the data of ED and the TDs attached to the ED
@param Uhc Pointer to OHCI private data
@param Ed Pointer to a ED to free
@param Td Pointer to the Td head
@retval EFI_SUCCESS ED
**/
EFI_STATUS
OhciDumpEdTdInfo (
IN USB_OHCI_HC_DEV *Uhc,
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *Td,
BOOLEAN Stage
);

View File

@@ -0,0 +1,77 @@
## @file
# OHCI USB Host Controller UEFI Driver
#
# Copyright (c) 2013-2015 Intel Corporation.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = OhciDxe
FILE_GUID = 4ACA697E-F883-446f-98F7-096416FFFFFF
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = OHCIDriverEntryPoint
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
# DRIVER_BINDING = gOhciDriverBinding
# COMPONENT_NAME = gOhciComponentName
# COMPONENT_NAME2 = gOhciComponentName2
#
[Sources]
Descriptor.h
Ohci.c
Ohci.h
OhciSched.c
OhciSched.h
OhciReg.c
OhciReg.h
OhciUrb.c
OhciUrb.h
OhciDebug.c
OhciDebug.h
ComponentName.c
ComponentName.h
UsbHcMem.c
UsbHcMem.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
QuarkSocPkg/QuarkSocPkg.dec
[LibraryClasses]
MemoryAllocationLib
BaseLib
UefiLib
UefiBootServicesTableLib
UefiDriverEntryPoint
BaseMemoryLib
DebugLib
[Guids]
gEfiEventExitBootServicesGuid ## SOMETIMES_CONSUMES ## Event
[Protocols]
gEfiPciIoProtocolGuid ## TO_START
gEfiUsbHcProtocolGuid ## BY_START
#
# [Event]
# ##
# # Periodic timer event for checking the result of interrupt transfer execution.
# #
# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES
#

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,926 @@
/** @file
This file contains the definination for host controller
register operation routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_REG_H
#define _OHCI_REG_H
#define HC_STATE_RESET 0x0
#define HC_STATE_RESUME 0x1
#define HC_STATE_OPERATIONAL 0x2
#define HC_STATE_SUSPEND 0x3
#define PERIODIC_ENABLE 0x01
#define ISOCHRONOUS_ENABLE 0x02
#define CONTROL_ENABLE 0x04
#define BULK_ENABLE 0x08
#define CONTROL_BULK_RATIO 0x10
#define HC_FUNCTIONAL_STATE 0x20
#define INTERRUPT_ROUTING 0x40
#define HC_RESET 0x01
#define CONTROL_LIST_FILLED 0x02
#define BULK_LIST_FILLED 0x04
#define CHANGE_OWNER_REQUEST 0x08
#define SCHEDULE_OVERRUN_COUNT 0x10
#define SCHEDULE_OVERRUN 0x00001
#define WRITEBACK_DONE_HEAD 0x00002
#define START_OF_FRAME 0x00004
#define RESUME_DETECT 0x00008
#define UNRECOVERABLE_ERROR 0x00010
#define FRAME_NUMBER_OVERFLOW 0x00020
#define ROOTHUB_STATUS_CHANGE 0x00040
#define OWNERSHIP_CHANGE 0x00080
#define MASTER_INTERRUPT 0x00400
#define CONTROL_HEAD 0x001
#define BULK_HEAD 0x002
#define DONE_HEAD 0x004
#define Hc_HCCA 0x001
#define Hc_PERIODIC_CURRENT 0x002
#define Hc_CONTOL_HEAD 0x004
#define Hc_CONTROL_CURRENT_PTR 0x008
#define Hc_BULK_HEAD 0x010
#define Hc_BULK_CURRENT_PTR 0x020
#define Hc_DONE_HEAD 0x040
#define FRAME_INTERVAL 0x008
#define FS_LARGEST_DATA_PACKET 0x010
#define FRMINT_TOGGLE 0x020
#define FRAME_REMAINING 0x040
#define FRAME_REMAIN_TOGGLE 0x080
#define RH_DESC_A 0x00001
#define RH_DESC_B 0x00002
#define RH_NUM_DS_PORTS 0x00004
#define RH_NO_PSWITCH 0x00008
#define RH_PSWITCH_MODE 0x00010
#define RH_DEVICE_TYPE 0x00020
#define RH_OC_PROT_MODE 0x00040
#define RH_NOC_PROT 0x00080
#define RH_POTPGT 0x00100
#define RH_NO_POTPGT 0x00200
#define RH_DEV_REMOVABLE 0x00400
#define RH_PORT_PWR_CTRL_MASK 0x00800
#define RH_LOCAL_PSTAT 0x00001
#define RH_OC_ID 0x00002
#define RH_REMOTE_WK_ENABLE 0x00004
#define RH_LOCAL_PSTAT_CHANGE 0x00008
#define RH_OC_ID_CHANGE 0x00010
#define RH_CLR_RMT_WK_ENABLE 0x00020
#define RH_CLEAR_PORT_ENABLE 0x0001
#define RH_SET_PORT_ENABLE 0x0002
#define RH_SET_PORT_SUSPEND 0x0004
#define RH_CLEAR_SUSPEND_STATUS 0x0008
#define RH_SET_PORT_RESET 0x0010
#define RH_SET_PORT_POWER 0x0020
#define RH_CLEAR_PORT_POWER 0x0040
#define RH_CONNECT_STATUS_CHANGE 0x10000
#define RH_PORT_ENABLE_STAT_CHANGE 0x20000
#define RH_PORT_SUSPEND_STAT_CHANGE 0x40000
#define RH_OC_INDICATOR_CHANGE 0x80000
#define RH_PORT_RESET_STAT_CHANGE 0x100000
#define RH_CURR_CONNECT_STAT 0x0001
#define RH_PORT_ENABLE_STAT 0x0002
#define RH_PORT_SUSPEND_STAT 0x0004
#define RH_PORT_OC_INDICATOR 0x0008
#define RH_PORT_RESET_STAT 0x0010
#define RH_PORT_POWER_STAT 0x0020
#define RH_LSDEVICE_ATTACHED 0x0040
#define RESET_SYSTEM_BUS (1 << 0)
#define RESET_HOST_CONTROLLER (1 << 1)
#define RESET_CLOCK_GENERATION (1 << 2)
#define RESET_SSE_GLOBAL (1 << 5)
#define RESET_PSPL (1 << 6)
#define RESET_PCPL (1 << 7)
#define RESET_SSEP1 (1 << 9)
#define RESET_SSEP2 (1 << 10)
#define RESET_SSEP3 (1 << 11)
#define ONE_SECOND 1000000
#define ONE_MILLI_SEC 1000
#define MAX_BYTES_PER_TD 0x1000
#define MAX_RETRY_TIMES 100
#define PORT_NUMBER_ON_MAINSTONE2 1
//
// Operational Register Offsets
//
//
// Command & Status Registers Offsets
//
#define HC_REVISION 0x00
#define HC_CONTROL 0x04
#define HC_COMMAND_STATUS 0x08
#define HC_INTERRUPT_STATUS 0x0C
#define HC_INTERRUPT_ENABLE 0x10
#define HC_INTERRUPT_DISABLE 0x14
//
// Memory Pointer Offsets
//
#define HC_HCCA 0x18
#define HC_PERIODIC_CURRENT 0x1C
#define HC_CONTROL_HEAD 0x20
#define HC_CONTROL_CURRENT_PTR 0x24
#define HC_BULK_HEAD 0x28
#define HC_BULK_CURRENT_PTR 0x2C
#define HC_DONE_HEAD 0x30
//
// Frame Register Offsets
//
#define HC_FRM_INTERVAL 0x34
#define HC_FRM_REMAINING 0x38
#define HC_FRM_NUMBER 0x3C
#define HC_PERIODIC_START 0x40
#define HC_LS_THREASHOLD 0x44
//
// Root Hub Register Offsets
//
#define HC_RH_DESC_A 0x48
#define HC_RH_DESC_B 0x4C
#define HC_RH_STATUS 0x50
#define HC_RH_PORT_STATUS 0x54
#define USBHOST_OFFSET_UHCHR 0x64 // Usb Host reset register
#define OHC_BAR_INDEX 0
//
// Usb Host controller register offset
//
#define USBHOST_OFFSET_UHCREV 0x0 // Usb Host revision register
#define USBHOST_OFFSET_UHCHCON 0x4 // Usb Host control register
#define USBHOST_OFFSET_UHCCOMS 0x8 // Usb Host Command Status register
#define USBHOST_OFFSET_UHCINTS 0xC // Usb Host Interrupt Status register
#define USBHOST_OFFSET_UHCINTE 0x10 // Usb Host Interrupt Enable register
#define USBHOST_OFFSET_UHCINTD 0x14 // Usb Host Interrupt Disable register
#define USBHOST_OFFSET_UHCHCCA 0x18 // Usb Host Controller Communication Area
#define USBHOST_OFFSET_UHCPCED 0x1C // Usb Host Period Current Endpoint Descriptor
#define USBHOST_OFFSET_UHCCHED 0x20 // Usb Host Control Head Endpoint Descriptor
#define USBHOST_OFFSET_UHCCCED 0x24 // Usb Host Control Current Endpoint Descriptor
#define USBHOST_OFFSET_UHCBHED 0x28 // Usb Host Bulk Head Endpoint Descriptor
#define USBHOST_OFFSET_UHCBCED 0x2C // Usb Host Bulk Current Endpoint Descriptor
#define USBHOST_OFFSET_UHCDHEAD 0x30 // Usb Host Done Head register
#define USBHOST_OFFSET_UHCFMI 0x34 // Usb Host Frame Interval register
#define USBHOST_OFFSET_UHCFMR 0x38 // Usb Host Frame Remaining register
#define USBHOST_OFFSET_UHCFMN 0x3C // Usb Host Frame Number register
#define USBHOST_OFFSET_UHCPERS 0x40 // Usb Host Periodic Start register
#define USBHOST_OFFSET_UHCLST 0x44 // Usb Host Low-Speed Threshold register
#define USBHOST_OFFSET_UHCRHDA 0x48 // Usb Host Root Hub Descriptor A register
#define USBHOST_OFFSET_UHCRHDB 0x4C // Usb Host Root Hub Descriptor B register
#define USBHOST_OFFSET_UHCRHS 0x50 // Usb Host Root Hub Status register
#define USBHOST_OFFSET_UHCRHPS1 0x54 // Usb Host Root Hub Port Status 1 register
//
// Usb Host controller register bit fields
//
#pragma pack(1)
typedef struct {
UINT8 ProgInterface;
UINT8 SubClassCode;
UINT8 BaseCode;
} USB_CLASSC;
typedef struct {
UINT32 Revision:8;
UINT32 Rsvd:24;
} HcREVISION;
typedef struct {
UINT32 ControlBulkRatio:2;
UINT32 PeriodicEnable:1;
UINT32 IsochronousEnable:1;
UINT32 ControlEnable:1;
UINT32 BulkEnable:1;
UINT32 FunctionalState:2;
UINT32 InterruptRouting:1;
UINT32 RemoteWakeup:1;
UINT32 RemoteWakeupEnable:1;
UINT32 Reserved:21;
} HcCONTROL;
typedef struct {
UINT32 HcReset:1;
UINT32 ControlListFilled:1;
UINT32 BulkListFilled:1;
UINT32 ChangeOwnerRequest:1;
UINT32 Reserved1:12;
UINT32 ScheduleOverrunCount:2;
UINT32 Reserved:14;
} HcCOMMAND_STATUS;
typedef struct {
UINT32 SchedulingOverrun:1;
UINT32 WriteBackDone:1;
UINT32 Sof:1;
UINT32 ResumeDetected:1;
UINT32 UnrecoverableError:1;
UINT32 FrameNumOverflow:1;
UINT32 RHStatusChange:1;
UINT32 Reserved1:23;
UINT32 OwnerChange:1;
UINT32 Reserved2:1;
} HcINTERRUPT_STATUS;
typedef struct {
UINT32 SchedulingOverrunInt:1;
UINT32 WriteBackDoneInt:1;
UINT32 SofInt:1;
UINT32 ResumeDetectedInt:1;
UINT32 UnrecoverableErrorInt:1;
UINT32 FrameNumOverflowInt:1;
UINT32 RHStatusChangeInt:1;
UINT32 Reserved:23;
UINT32 OwnerChangedInt:1;
UINT32 MasterInterruptEnable:1;
} HcINTERRUPT_CONTROL;
typedef struct {
UINT32 Rerserved:8;
UINT32 Hcca:24;
} HcHCCA;
typedef struct {
UINT32 Reserved:4;
UINT32 MemoryPtr:28;
} HcMEMORY_PTR;
typedef struct {
UINT32 FrameInterval:14;
UINT32 Reserved:2;
UINT32 FSMaxDataPacket:15;
UINT32 FrmIntervalToggle:1;
} HcFRM_INTERVAL;
typedef struct {
UINT32 FrameRemaining:14;
UINT32 Reserved:17;
UINT32 FrameRemainingToggle:1;
} HcFRAME_REMAINING;
typedef struct {
UINT32 FrameNumber:16;
UINT32 Reserved:16;
} HcFRAME_NUMBER;
typedef struct {
UINT32 PeriodicStart:14;
UINT32 Reserved:18;
} HcPERIODIC_START;
typedef struct {
UINT32 LsThreshold:12;
UINT32 Reserved:20;
} HcLS_THRESHOLD;
typedef struct {
UINT32 NumDownStrmPorts:8;
UINT32 PowerSwitchMode:1;
UINT32 NoPowerSwitch:1;
UINT32 DeviceType:1;
UINT32 OverCurrentProtMode:1;
UINT32 NoOverCurrentProtMode:1;
UINT32 Reserved:11;
UINT32 PowerOnToPowerGoodTime:8;
} HcRH_DESC_A;
typedef struct {
UINT32 DeviceRemovable:16;
UINT32 PortPowerControlMask:16;
} HcRH_DESC_B;
typedef struct {
UINT32 LocalPowerStat:1;
UINT32 OverCurrentIndicator:1;
UINT32 Reserved1:13;
UINT32 DevRemoteWakeupEnable:1;
UINT32 LocalPowerStatChange:1;
UINT32 OverCurrentIndicatorChange:1;
UINT32 Reserved2:13;
UINT32 ClearRemoteWakeupEnable:1;
} HcRH_STATUS;
typedef struct {
UINT32 CurrentConnectStat:1;
UINT32 EnableStat:1;
UINT32 SuspendStat:1;
UINT32 OCIndicator:1;
UINT32 ResetStat:1;
UINT32 Reserved1:3;
UINT32 PowerStat:1;
UINT32 LsDeviceAttached:1;
UINT32 Reserved2:6;
UINT32 ConnectStatChange:1;
UINT32 EnableStatChange:1;
UINT32 SuspendStatChange:1;
UINT32 OCIndicatorChange:1;
UINT32 ResetStatChange:1;
UINT32 Reserved3:11;
} HcRHPORT_STATUS;
typedef struct {
UINT32 FSBIR:1;
UINT32 FHR:1;
UINT32 CGR:1;
UINT32 SSDC:1;
UINT32 UIT:1;
UINT32 SSE:1;
UINT32 PSPL:1;
UINT32 PCPL:1;
UINT32 Reserved0:1;
UINT32 SSEP1:1;
UINT32 SSEP2:1;
UINT32 SSEP3:1;
UINT32 Reserved1:20;
} HcRESET;
#pragma pack()
//
// Func List
//
/**
Get OHCI operational reg value
@param PciIo PciIo protocol instance
@param Offset Offset of the operational reg
@retval Value of the register
**/
UINT32
OhciGetOperationalReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 Offset
);
/**
Set OHCI operational reg value
@param PciIo PCI Bus Io protocol instance
@param Offset Offset of the operational reg
@param Value Value to set
@retval EFI_SUCCESS Value set to the reg
**/
EFI_STATUS
OhciSetOperationalReg (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 Offset,
IN VOID *Value
);
/**
Get HcRevision reg value
@param PciIo PCI Bus Io protocol instance
@retval Value of the register
**/
UINT32
OhciGetHcRevision (
IN EFI_PCI_IO_PROTOCOL *PciIo
);
/**
Set HcReset reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetHcReset (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Field,
IN UINT32 Value
);
/**
Get specific field of HcReset reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcReset (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Field
);
/**
Set HcControl reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetHcControl (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get specific field of HcControl reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcControl (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set HcCommand reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetHcCommandStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get specific field of HcCommand reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcCommandStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Clear specific fields of Interrupt Status
@param Ohc UHC private data
@param Field Field to clear
@retval EFI_SUCCESS Fields cleared
**/
EFI_STATUS
OhciClearInterruptStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Get fields of HcInterrupt reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcInterruptStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Interrupt Control reg value
@param Ohc UHC private data
@param StatEnable Enable or Disable
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetInterruptControl (
IN USB_OHCI_HC_DEV *Ohc,
IN BOOLEAN StatEnable,
IN UINTN Field,
IN UINT32 Value
);
/**
Get field of HcInterruptControl reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcInterruptControl (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set memory pointer of specific type
@param Ohc UHC private data
@param PointerType Type of the pointer to set
@param Value Value to set
@retval EFI_SUCCESS Memory pointer set
**/
EFI_STATUS
OhciSetMemoryPointer(
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 PointerType,
IN VOID *Value
);
/**
Get memory pointer of specific type
@param Ohc UHC private data
@param PointerType Type of pointer
@retval Memory pointer of the specific type
**/
VOID *
OhciGetMemoryPointer (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 PointerType
);
/**
Set Frame Interval value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetFrameInterval (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get field of frame interval reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetFrameInterval (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Frame Remaining reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetFrameRemaining (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get value of frame remaining reg
@param Ohc UHC private data
@param Field Field to get
@retval Value of frame remaining reg
**/
UINT32
OhciGetFrameRemaining (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set frame number reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetFrameNumber(
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get frame number reg value
@param Ohc UHC private data
@retval Value of frame number reg
**/
UINT32
OhciGetFrameNumber (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Set period start reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetPeriodicStart (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get periodic start reg value
@param Ohc UHC private data
@param Value of periodic start reg
**/
UINT32
OhciGetPeriodicStart (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Set Ls Threshold reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetLsThreshold (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get Ls Threshold reg value
@param Ohc UHC private data
@retval Value of Ls Threshold reg
**/
UINT32
OhciGetLsThreshold (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Set Root Hub Descriptor reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetRootHubDescriptor (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get Root Hub Descriptor reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetRootHubDescriptor (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Root Hub Status reg value
@param Ohc UHC private data
@param Field Field to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetRootHubStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Get Root Hub Status reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetRootHubStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Root Hub Port Status reg value
@param Ohc UHC private data
@param Index Index of the port
@param Field Field to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetRootHubPortStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Index,
IN UINTN Field
);
/**
Get Root Hub Port Status reg value
@param Ohc UHC private data
@param Index Index of the port
@param Field Field to get
@retval Value of the field and index
**/
UINT32
OhciReadRootHubPortStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Index,
IN UINTN Field
);
#endif

View File

@@ -0,0 +1,534 @@
/** @file
OHCI transfer scheduling routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ohci.h"
/**
Add an item of interrupt context
@param Ohc UHC private data
@param NewEntry New entry to add
@retval EFI_SUCCESS Item successfully added
**/
EFI_STATUS
OhciAddInterruptContextEntry (
IN USB_OHCI_HC_DEV *Ohc,
IN INTERRUPT_CONTEXT_ENTRY *NewEntry
)
{
INTERRUPT_CONTEXT_ENTRY *Entry;
EFI_TPL OriginalTPL;
OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
if (Ohc->InterruptContextList == NULL) {
Ohc->InterruptContextList = NewEntry;
} else {
Entry = Ohc->InterruptContextList;
while (Entry->NextEntry != NULL) {
Entry = Entry->NextEntry;
}
Entry->NextEntry = NewEntry;
}
gBS->RestoreTPL (OriginalTPL);
return EFI_SUCCESS;
}
/**
Free a interrupt context entry
@param Ohc UHC private data
@param Entry Pointer to an interrupt context entry
@retval EFI_SUCCESS Entry freed
@retval EFI_INVALID_PARAMETER Entry is NULL
**/
EFI_STATUS
OhciFreeInterruptContextEntry (
IN USB_OHCI_HC_DEV *Ohc,
IN INTERRUPT_CONTEXT_ENTRY *Entry
)
{
TD_DESCRIPTOR *Td;
if (Entry == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Entry->UCBufferMapping != NULL) {
Ohc->PciIo->Unmap(Ohc->PciIo, Entry->UCBufferMapping);
}
if (Entry->UCBuffer != NULL) {
FreePool(Entry->UCBuffer);
}
while (Entry->DataTd) {
Td = Entry->DataTd;
Entry->DataTd = (TD_DESCRIPTOR *)(UINTN)(Entry->DataTd->NextTDPointer);
UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
}
FreePool(Entry);
return EFI_SUCCESS;
}
/**
Free entries match the device address and endpoint address
@Param Ohc UHC private date
@Param DeviceAddress Item to free must match this device address
@Param EndPointAddress Item to free must match this end point address
@Param DataToggle DataToggle for output
@retval EFI_SUCCESS Items match the requirement removed
**/
EFI_STATUS
OhciFreeInterruptContext(
IN USB_OHCI_HC_DEV *Ohc,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
OUT UINT8 *DataToggle
)
{
INTERRUPT_CONTEXT_ENTRY *Entry;
INTERRUPT_CONTEXT_ENTRY *TempEntry;
EFI_TPL OriginalTPL;
OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
while (Ohc->InterruptContextList != NULL &&
Ohc->InterruptContextList->DeviceAddress == DeviceAddress &&
Ohc->InterruptContextList->EndPointAddress == EndPointAddress) {
TempEntry = Ohc->InterruptContextList;
Ohc->InterruptContextList = Ohc->InterruptContextList->NextEntry;
if (DataToggle != NULL) {
*DataToggle = (UINT8) (TempEntry->DataTd->Word0.DataToggle & 0x1);
}
OhciFreeInterruptContextEntry (Ohc, TempEntry);
}
Entry = Ohc->InterruptContextList;
if (Entry == NULL) {
gBS->RestoreTPL (OriginalTPL);
return EFI_SUCCESS;
}
while (Entry->NextEntry != NULL) {
if (Entry->NextEntry->DeviceAddress == DeviceAddress &&
Entry->NextEntry->EndPointAddress == EndPointAddress) {
TempEntry = Entry->NextEntry;
Entry->NextEntry = Entry->NextEntry->NextEntry;
if (DataToggle != NULL) {
*DataToggle = (UINT8) (TempEntry->DataTd->Word0.DataToggle & 0x1);
}
OhciFreeInterruptContextEntry (Ohc, TempEntry);
} else {
Entry = Entry->NextEntry;
}
}
gBS->RestoreTPL (OriginalTPL);
return EFI_SUCCESS;
}
/**
Convert Error code from OHCI format to EFI format
@Param ErrorCode ErrorCode in OHCI format
@retval ErrorCode in EFI format
**/
UINT32
ConvertErrorCode (
IN UINT32 ErrorCode
)
{
UINT32 TransferResult;
switch (ErrorCode) {
case TD_NO_ERROR:
TransferResult = EFI_USB_NOERROR;
break;
case TD_TOBE_PROCESSED:
case TD_TOBE_PROCESSED_2:
TransferResult = EFI_USB_ERR_NOTEXECUTE;
break;
case TD_DEVICE_STALL:
TransferResult = EFI_USB_ERR_STALL;
break;
case TD_BUFFER_OVERRUN:
case TD_BUFFER_UNDERRUN:
TransferResult = EFI_USB_ERR_BUFFER;
break;
case TD_CRC_ERROR:
TransferResult = EFI_USB_ERR_CRC;
break;
case TD_NO_RESPONSE:
TransferResult = EFI_USB_ERR_TIMEOUT;
break;
case TD_BITSTUFFING_ERROR:
TransferResult = EFI_USB_ERR_BITSTUFF;
break;
default:
TransferResult = EFI_USB_ERR_SYSTEM;
}
return TransferResult;
}
/**
Check TDs Results
@Param Ohc UHC private data
@Param Td TD_DESCRIPTOR
@Param Result Result to return
@retval TRUE means OK
@retval FLASE means Error or Short packet
**/
BOOLEAN
OhciCheckTDsResults (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td,
OUT UINT32 *Result
)
{
UINT32 TdCompletionCode;
*Result = EFI_USB_NOERROR;
while (Td) {
TdCompletionCode = Td->Word0.ConditionCode;
*Result |= ConvertErrorCode(TdCompletionCode);
//
// if any error encountered, stop processing the left TDs.
//
if (*Result) {
return FALSE;
}
Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);
}
return TRUE;
}
/**
Check the task status on an ED
@Param Ed Pointer to the ED task that TD hooked on
@Param HeadTd TD header for current transaction
@retval Task Status Code
**/
UINT32
CheckEDStatus (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd,
OUT OHCI_ED_RESULT *EdResult
)
{
while(HeadTd != NULL) {
if (HeadTd->NextTDPointer == 0) {
return TD_NO_ERROR;
}
if (HeadTd->Word0.ConditionCode != 0) {
return HeadTd->Word0.ConditionCode;
}
EdResult->NextToggle = ((UINT8)(HeadTd->Word0.DataToggle) & BIT0) ^ BIT0;
HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
}
if (OhciGetEDField (Ed, ED_TDHEAD_PTR) != OhciGetEDField (Ed, ED_TDTAIL_PTR)) {
return TD_TOBE_PROCESSED;
}
return TD_NO_ERROR;
}
/**
Check the task status
@Param Ohc UHC private data
@Param ListType Pipe type
@Param Ed Pointer to the ED task hooked on
@Param HeadTd Head of TD corresponding to the task
@Param ErrorCode return the ErrorCode
@retval EFI_SUCCESS Task done
@retval EFI_NOT_READY Task on processing
@retval EFI_DEVICE_ERROR Some error occured
**/
EFI_STATUS
CheckIfDone (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd,
OUT OHCI_ED_RESULT *EdResult
)
{
EdResult->ErrorCode = TD_TOBE_PROCESSED;
switch (ListType) {
case CONTROL_LIST:
if (OhciGetHcCommandStatus (Ohc, CONTROL_LIST_FILLED) != 0) {
return EFI_NOT_READY;
}
break;
case BULK_LIST:
if (OhciGetHcCommandStatus (Ohc, BULK_LIST_FILLED) != 0) {
return EFI_NOT_READY;
}
break;
default:
break;
}
EdResult->ErrorCode = CheckEDStatus (Ed, HeadTd, EdResult);
if (EdResult->ErrorCode == TD_NO_ERROR) {
return EFI_SUCCESS;
} else if (EdResult->ErrorCode == TD_TOBE_PROCESSED) {
return EFI_NOT_READY;
} else {
return EFI_DEVICE_ERROR;
}
}
/**
Convert TD condition code to Efi Status
@Param ConditionCode Condition code to convert
@retval EFI_SUCCESS No error occured
@retval EFI_NOT_READY TD still on processing
@retval EFI_DEVICE_ERROR Error occured in processing TD
**/
EFI_STATUS
OhciTDConditionCodeToStatus (
IN UINT32 ConditionCode
)
{
if (ConditionCode == TD_NO_ERROR) {
return EFI_SUCCESS;
}
if (ConditionCode == TD_TOBE_PROCESSED) {
return EFI_NOT_READY;
}
return EFI_DEVICE_ERROR;
}
/**
Invoke callbacks hooked on done TDs
@Param Entry Interrupt transfer transaction information data structure
@Param Context Ohc private data
**/
VOID
OhciInvokeInterruptCallBack(
IN INTERRUPT_CONTEXT_ENTRY *Entry,
IN UINT32 Result
)
{
//Generally speaking, Keyboard driver should not
//check the Keyboard buffer if an error happens, it will be robust
//if we NULLed the buffer once error happens
if (Result) {
Entry->CallBackFunction (
NULL,
0,
Entry->Context,
Result
);
}else{
Entry->CallBackFunction (
(VOID *)(UINTN)(Entry->DataTd->DataBuffer),
Entry->DataTd->ActualSendLength,
Entry->Context,
Result
);
}
}
/**
Timer to submit periodic interrupt transfer, and invoke callbacks hooked on done TDs
@param Event Event handle
@param Context Device private data
**/
VOID
EFIAPI
OhciHouseKeeper (
IN EFI_EVENT Event,
IN VOID *Context
)
{
USB_OHCI_HC_DEV *Ohc;
INTERRUPT_CONTEXT_ENTRY *Entry;
INTERRUPT_CONTEXT_ENTRY *PreEntry;
ED_DESCRIPTOR *Ed;
TD_DESCRIPTOR *DataTd;
TD_DESCRIPTOR *HeadTd;
UINT8 Toggle;
EFI_TPL OriginalTPL;
UINT32 Result;
Ohc = (USB_OHCI_HC_DEV *) Context;
OriginalTPL = gBS->RaiseTPL(TPL_NOTIFY);
Entry = Ohc->InterruptContextList;
PreEntry = NULL;
while(Entry != NULL) {
OhciCheckTDsResults(Ohc, Entry->DataTd, &Result );
if (((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) ||
((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE)) {
PreEntry = Entry;
Entry = Entry->NextEntry;
continue;
}
if (Entry->CallBackFunction != NULL) {
OhciInvokeInterruptCallBack (Entry, Result);
if (Ohc->InterruptContextList == NULL) {
gBS->RestoreTPL (OriginalTPL);
return;
}
}
if (Entry->IsPeriodic) {
Ed = Entry->Ed;
HeadTd = Entry->DataTd;
DataTd = HeadTd;
Toggle = 0;
if (Result == EFI_USB_NOERROR) {
//
// Update toggle if there is no error, and re-submit the interrupt Ed&Tds
//
if ((Ed != NULL) && (DataTd != NULL)) {
Ed->Word0.Skip = 1;
}
//
// From hcir1_0a.pdf 4.2.2
// ToggleCarry:This bit is the data toggle carry bit,
// Whenever a TD is retired, this bit is written to
// contain the last data toggle value(LSb of data Toggel
// file) from the retired TD.
// This field is not used for Isochronous Endpoints
//
if (Ed == NULL) {
return;
}
Toggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
while(DataTd != NULL) {
if (DataTd->NextTDPointer == 0) {
DataTd->Word0.DataToggle = 0;
break;
} else {
OhciSetTDField (DataTd, TD_DT_TOGGLE, Toggle);
}
DataTd = (TD_DESCRIPTOR *)(UINTN)(DataTd->NextTDPointer);
Toggle ^= 1;
}
//
// HC will only update DataToggle, ErrorCount, ConditionCode
// CurrentBufferPointer & NextTD, so we only need to update
// them once we want to active them again
//
DataTd = HeadTd;
while (DataTd != NULL) {
if (DataTd->NextTDPointer == 0) {
OhciSetTDField (DataTd, TD_ERROR_CNT | TD_COND_CODE | TD_CURR_BUFFER_PTR | TD_NEXT_PTR, 0);
break;
}
OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
DataTd->NextTD = DataTd->NextTDPointer;
DataTd->CurrBufferPointer = DataTd->DataBuffer;
DataTd = (TD_DESCRIPTOR *)(UINTN)(DataTd->NextTDPointer);
}
//
// Active current Ed,Td
//
// HC will only update Halted, ToggleCarry & TDQueueHeadPointer,
// So we only need to update them once we want to active them again.
//
if ((Ed != NULL) && (DataTd != NULL)) {
Ed->Word2.TdHeadPointer = (UINT32)((UINTN)HeadTd>>4);
OhciSetEDField (Ed, ED_HALTED | ED_DTTOGGLE, 0);
Ed->Word0.Skip = 0;
}
}
} else {
if (PreEntry == NULL) {
Ohc->InterruptContextList = Entry->NextEntry;
} else {
PreEntry = Entry;
PreEntry->NextEntry = Entry->NextEntry;
}
OhciFreeInterruptContextEntry (Ohc, PreEntry);
gBS->RestoreTPL (OriginalTPL);
return;
}
PreEntry = Entry;
Entry = Entry->NextEntry;
}
gBS->RestoreTPL (OriginalTPL);
}

View File

@@ -0,0 +1,231 @@
/** @file
This file contains the definination for host controller schedule routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_SCHED_H
#define _OHCI_SCHED_H
#include "Descriptor.h"
#define HCCA_MEM_SIZE 256
#define GRID_SIZE 16
#define GRID_SHIFT 4
typedef struct _INTERRUPT_CONTEXT_ENTRY INTERRUPT_CONTEXT_ENTRY;
struct _INTERRUPT_CONTEXT_ENTRY{
UINT8 DeviceAddress;
UINT8 EndPointAddress;
ED_DESCRIPTOR *Ed;
TD_DESCRIPTOR *DataTd;
BOOLEAN IsSlowDevice;
UINT8 MaxPacketLength;
UINTN PollingInterval;
EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction;
VOID *Context;
BOOLEAN IsPeriodic;
VOID *Buffer;
UINTN DataLength;
VOID *UCBuffer;
VOID *UCBufferMapping;
UINT8 *Toggle;
INTERRUPT_CONTEXT_ENTRY *NextEntry;
};
typedef struct {
UINT32 ErrorCode;
UINT8 NextToggle;
} OHCI_ED_RESULT;
/**
Add an item of interrupt context
@param Ohc UHC private data
@param NewEntry New entry to add
@retval EFI_SUCCESS Item successfully added
**/
EFI_STATUS
OhciAddInterruptContextEntry (
IN USB_OHCI_HC_DEV *Ohc,
IN INTERRUPT_CONTEXT_ENTRY *NewEntry
);
/**
Free a interrupt context entry
@param Ohc UHC private data
@param Entry Pointer to an interrupt context entry
@retval EFI_SUCCESS Entry freed
@retval EFI_INVALID_PARAMETER Entry is NULL
**/
EFI_STATUS
OhciFreeInterruptContextEntry (
IN USB_OHCI_HC_DEV *Ohc,
IN INTERRUPT_CONTEXT_ENTRY *Entry
);
/**
Free entries match the device address and endpoint address
@Param Ohc UHC private date
@Param DeviceAddress Item to free must match this device address
@Param EndPointAddress Item to free must match this end point address
@Param DataToggle DataToggle for output
@retval EFI_SUCCESS Items match the requirement removed
**/
EFI_STATUS
OhciFreeInterruptContext(
IN USB_OHCI_HC_DEV *Ohc,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
OUT UINT8 *DataToggle
);
/**
Convert Error code from OHCI format to EFI format
@Param ErrorCode ErrorCode in OHCI format
@retval ErrorCode in EFI format
**/
UINT32
ConvertErrorCode (
IN UINT32 ErrorCode
);
/**
Check TDs Results
@Param Ohc UHC private data
@Param Td TD_DESCRIPTOR
@Param Result Result to return
@retval TRUE means OK
@retval FLASE means Error or Short packet
**/
BOOLEAN
OhciCheckTDsResults (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td,
OUT UINT32 *Result
);
/**
Check the task status on an ED
@Param Ed Pointer to the ED task that TD hooked on
@Param HeadTd TD header for current transaction
@retval Task Status Code
**/
UINT32
CheckEDStatus (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd,
OUT OHCI_ED_RESULT *EdResult
);
/**
Check the task status
@Param Ohc UHC private data
@Param ListType Pipe type
@Param Ed Pointer to the ED task hooked on
@Param HeadTd Head of TD corresponding to the task
@Param ErrorCode return the ErrorCode
@retval EFI_SUCCESS Task done
@retval EFI_NOT_READY Task on processing
@retval EFI_DEVICE_ERROR Some error occured
**/
EFI_STATUS
CheckIfDone (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd,
OUT OHCI_ED_RESULT *EdResult
);
/**
Convert TD condition code to Efi Status
@Param ConditionCode Condition code to convert
@retval EFI_SUCCESS No error occured
@retval EFI_NOT_READY TD still on processing
@retval EFI_DEVICE_ERROR Error occured in processing TD
**/
EFI_STATUS
OhciTDConditionCodeToStatus (
IN UINT32 ConditionCode
);
/**
Invoke callbacks hooked on done TDs
@Param Entry Interrupt transfer transaction information data structure
@Param Context Ohc private data
**/
VOID
OhciInvokeInterruptCallBack(
IN INTERRUPT_CONTEXT_ENTRY *Entry,
IN UINT32 Result
);
/**
Timer to submit periodic interrupt transfer, and invoke callbacks hooked on done TDs
@param Event Event handle
@param Context Device private data
**/
VOID
EFIAPI
OhciHouseKeeper (
IN EFI_EVENT Event,
IN VOID *Context
);
#endif

View File

@@ -0,0 +1,895 @@
/** @file
This file contains URB request, each request is warpped in a
URB (Usb Request Block).
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ohci.h"
/**
Create a TD
@Param Ohc UHC private data
@retval TD structure pointer
**/
TD_DESCRIPTOR *
OhciCreateTD (
IN USB_OHCI_HC_DEV *Ohc
)
{
TD_DESCRIPTOR *Td;
Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR));
if (Td == NULL) {
DEBUG ((EFI_D_INFO, "STV allocate TD fail !\r\n"));
return NULL;
}
Td->CurrBufferPointer = 0;
Td->NextTD = 0;
Td->BufferEndPointer = 0;
Td->NextTDPointer = 0;
return Td;
}
/**
Free a TD
@Param Ohc UHC private data
@Param Td Pointer to a TD to free
@retval EFI_SUCCESS TD freed
**/
EFI_STATUS
OhciFreeTD (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td
)
{
if (Td == NULL) {
return EFI_SUCCESS;
}
UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
return EFI_SUCCESS;
}
/**
Create a ED
@Param Ohc Device private data
@retval ED descriptor pointer
**/
ED_DESCRIPTOR *
OhciCreateED (
USB_OHCI_HC_DEV *Ohc
)
{
ED_DESCRIPTOR *Ed;
Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR));
if (Ed == NULL) {
DEBUG ((EFI_D_INFO, "STV allocate ED fail !\r\n"));
return NULL;
}
Ed->Word0.Skip = 1;
Ed->TdTailPointer = 0;
Ed->Word2.TdHeadPointer = 0;
Ed->NextED = 0;
return Ed;
}
/**
Free a ED
@Param Ohc UHC private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
)
{
if (Ed == NULL) {
return EFI_SUCCESS;
}
UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
return EFI_SUCCESS;
}
/**
Free ED
@Param Ohc Device private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeAllTDFromED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
)
{
TD_DESCRIPTOR *HeadTd;
TD_DESCRIPTOR *TailTd;
TD_DESCRIPTOR *Td;
TD_DESCRIPTOR *TempTd;
if (Ed == NULL) {
return EFI_SUCCESS;
}
HeadTd = TD_PTR (Ed->Word2.TdHeadPointer);
TailTd = (TD_DESCRIPTOR *)(UINTN)(Ed->TdTailPointer);
Td = HeadTd;
while (Td != TailTd) {
TempTd = Td;
Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);
OhciFreeTD (Ohc, TempTd);
}
return EFI_SUCCESS;
}
/**
Find a working ED match the requirement
@Param EdHead Head of the ED list
@Param DeviceAddress Device address to search
@Param EndPointNum End point num to search
@Param EdDir ED Direction to search
@retval ED descriptor searched
**/
ED_DESCRIPTOR *
OhciFindWorkingEd (
IN ED_DESCRIPTOR *EdHead,
IN UINT8 DeviceAddress,
IN UINT8 EndPointNum,
IN UINT8 EdDir
)
{
ED_DESCRIPTOR *Ed;
for (Ed = EdHead; Ed != NULL; Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED)) {
if (Ed->Word2.Halted == 0 && Ed->Word0.Skip == 0 &&
Ed->Word0.FunctionAddress == DeviceAddress && Ed->Word0.EndPointNum == EndPointNum &&
Ed->Word0.Direction == EdDir) {
break;
}
}
return Ed;
}
/**
Initialize interrupt list.
@Param Ohc Device private data
@retval EFI_SUCCESS Initialization done
**/
EFI_STATUS
OhciInitializeInterruptList (
USB_OHCI_HC_DEV *Ohc
)
{
static UINT32 Leaf[32] = {0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17,
9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31};
UINT32 *HccaInterruptTable;
UINTN Index;
UINTN Level;
UINTN Count;
ED_DESCRIPTOR *NewEd;
HccaInterruptTable = Ohc->HccaMemoryBlock->HccaInterruptTable;
for (Index = 0; Index < 32; Index++) {
NewEd = OhciCreateED (Ohc);
if (NewEd == NULL) {
return EFI_OUT_OF_RESOURCES;
}
HccaInterruptTable[Index] = (UINT32)(UINTN)NewEd;
}
for (Index = 0; Index < 32; Index++) {
Ohc->IntervalList[0][Index] = (ED_DESCRIPTOR *)(UINTN)HccaInterruptTable[Leaf[Index]];
}
Count = 32;
for (Level = 1; Level <= 5; Level++) {
Count = Count >> 1;
for (Index = 0; Index < Count; Index++) {
Ohc->IntervalList[Level][Index] = OhciCreateED (Ohc);
if (HccaInterruptTable[Index] == 0) {
return EFI_OUT_OF_RESOURCES;
}
Ohc->IntervalList[Level - 1][Index * 2 ]->NextED = (UINT32)(UINTN)Ohc->IntervalList[Level][Index];
Ohc->IntervalList[Level - 1][Index * 2 + 1]->NextED = (UINT32)(UINTN)Ohc->IntervalList[Level][Index];
}
}
return EFI_SUCCESS;
}
/**
Attach an ED
@Param Ed Ed to be attached
@Param NewEd Ed to attach
@retval EFI_SUCCESS NewEd attached to Ed
@retval EFI_INVALID_PARAMETER Ed is NULL
**/
EFI_STATUS
OhciAttachED (
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *NewEd
)
{
ED_DESCRIPTOR *Temp;
if (Ed == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Ed->NextED == 0){
Ed->NextED = (UINT32)(UINTN)NewEd;
} else {
Temp = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
Ed->NextED = (UINT32)(UINTN)NewEd;
NewEd->NextED = (UINT32)(UINTN)Temp;
}
return EFI_SUCCESS;
}
/**
Count ED number on a ED chain
@Param Ed Head of the ED chain
@retval ED number on the chain
**/
UINTN
CountEdNum (
IN ED_DESCRIPTOR *Ed
)
{
UINTN Count;
Count = 0;
while (Ed) {
Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
Count++;
}
return Count;
}
/**
Find the minimal burn ED list on a specific depth level
@Param Ohc Device private data
@Param Depth Depth level
@retval ED list found
**/
ED_DESCRIPTOR *
OhciFindMinInterruptEDList (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Depth
)
{
UINTN EdNum;
UINTN MinEdNum;
ED_DESCRIPTOR *TempEd;
ED_DESCRIPTOR *HeadEd;
UINTN Index;
if (Depth > 5) {
return NULL;
}
MinEdNum = 0xFFFFFFFF;
TempEd = NULL;
for (Index = 0; Index < (UINTN)(32 >> Depth); Index++) {
HeadEd = Ohc->IntervalList[Depth][Index];
EdNum = CountEdNum (HeadEd);
if (EdNum < MinEdNum) {
MinEdNum = EdNum;
TempEd = HeadEd;
}
}
ASSERT (TempEd != NULL);
return TempEd;
}
/**
Attach an ED to an ED list
@Param OHC UHC private data
@Param ListType Type of the ED list
@Param Ed ED to attach
@Param EdList ED list to be attached
@retval EFI_SUCCESS ED attached to ED list
**/
ED_DESCRIPTOR *
OhciAttachEDToList (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *EdList
)
{
ED_DESCRIPTOR *HeadEd;
HeadEd = NULL;
switch(ListType) {
case CONTROL_LIST:
HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD);
if (HeadEd == NULL) {
OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed);
HeadEd = Ed;
} else {
OhciAttachED (HeadEd, Ed);
}
break;
case BULK_LIST:
HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD);
if (HeadEd == NULL) {
OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed);
HeadEd = Ed;
} else {
OhciAttachED (HeadEd, Ed);
}
break;
case INTERRUPT_LIST:
OhciAttachED (EdList, Ed);
break;
default:
ASSERT (FALSE);
}
return HeadEd;
}
/**
Remove interrupt EDs that match requirement
@Param Ohc UHC private data
@Param IntEd The address of Interrupt endpoint
@retval EFI_SUCCESS EDs match requirement removed
**/
EFI_STATUS
OhciFreeInterruptEdByEd (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *IntEd
)
{
ED_DESCRIPTOR *Ed;
ED_DESCRIPTOR *TempEd;
UINTN Index;
if (IntEd == NULL)
return EFI_SUCCESS;
for (Index = 0; Index < 32; Index++) {
Ed = (ED_DESCRIPTOR *)(UINTN)Ohc->HccaMemoryBlock->HccaInterruptTable[Index];
if (Ed == NULL) {
continue;
}
while (Ed->NextED != 0) {
if (Ed->NextED == (UINT32)(UINTN)IntEd ) {
TempEd = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
Ed->NextED = TempEd->NextED;
OhciFreeED (Ohc, TempEd);
} else {
Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
}
}
}
return EFI_SUCCESS;
}
/**
Remove interrupt EDs that match requirement
@Param Ohc UHC private data
@Param FunctionAddress Requirement on function address
@Param EndPointNum Requirement on end point number
@retval EFI_SUCCESS EDs match requirement removed
**/
EFI_STATUS
OhciFreeInterruptEdByAddr (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT8 FunctionAddress,
IN UINT8 EndPointNum
)
{
ED_DESCRIPTOR *Ed;
ED_DESCRIPTOR *TempEd;
UINTN Index;
for (Index = 0; Index < 32; Index++) {
Ed = (ED_DESCRIPTOR *)(UINTN)Ohc->HccaMemoryBlock->HccaInterruptTable[Index];
if (Ed == NULL) {
continue;
}
while (Ed->NextED != 0) {
TempEd = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
if (TempEd->Word0.FunctionAddress == FunctionAddress &&
TempEd->Word0.EndPointNum == EndPointNum ) {
Ed->NextED = TempEd->NextED;
OhciFreeED (Ohc, TempEd);
} else {
Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
}
}
}
return EFI_SUCCESS;
}
/**
Link Td2 to the end of Td1
@Param Td1 TD to be linked
@Param Td2 TD to link
@retval EFI_SUCCESS TD successfully linked
@retval EFI_INVALID_PARAMETER Td1 is NULL
**/
EFI_STATUS
OhciLinkTD (
IN TD_DESCRIPTOR *Td1,
IN TD_DESCRIPTOR *Td2
)
{
TD_DESCRIPTOR *TempTd;
if (Td1 == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Td1 == Td2) {
return EFI_SUCCESS;
}
TempTd = Td1;
while (TempTd->NextTD != 0) {
TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD);
}
TempTd->NextTD = (UINT32)(UINTN)Td2;
TempTd->NextTDPointer = (UINT32)(UINTN)Td2;
return EFI_SUCCESS;
}
/**
Attach TD list to ED
@Param Ed ED which TD list attach on
@Param HeadTd Head of the TD list to attach
@retval EFI_SUCCESS TD list attached on the ED
**/
EFI_STATUS
OhciAttachTDListToED (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
)
{
TD_DESCRIPTOR *TempTd;
TempTd = TD_PTR (Ed->Word2.TdHeadPointer);
if (TempTd != NULL) {
while (TempTd->NextTD != 0) {
TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD);
}
TempTd->NextTD = (UINT32)(UINTN)HeadTd;
TempTd->NextTDPointer = (UINT32)(UINTN)HeadTd;
} else {
Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32)(UINTN)HeadTd);
}
return EFI_SUCCESS;
}
/**
Set value to ED specific field
@Param Ed ED to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field,
IN UINT32 Value
)
{
if (Field & ED_FUNC_ADD) {
Ed->Word0.FunctionAddress = Value;
}
if (Field & ED_ENDPT_NUM) {
Ed->Word0.EndPointNum = Value;
}
if (Field & ED_DIR) {
Ed->Word0.Direction = Value;
}
if (Field & ED_SPEED) {
Ed->Word0.Speed = Value;
}
if (Field & ED_SKIP) {
Ed->Word0.Skip = Value;
}
if (Field & ED_FORMAT) {
Ed->Word0.Format = Value;
}
if (Field & ED_MAX_PACKET) {
Ed->Word0.MaxPacketSize = Value;
}
if (Field & ED_PDATA) {
Ed->Word0.FreeSpace = Value;
}
if (Field & ED_ZERO) {
Ed->Word2.Zero = Value;
}
if (Field & ED_TDTAIL_PTR) {
Ed->TdTailPointer = Value;
}
if (Field & ED_HALTED) {
Ed->Word2.Halted = Value;
}
if (Field & ED_DTTOGGLE) {
Ed->Word2.ToggleCarry = Value;
}
if (Field & ED_TDHEAD_PTR) {
Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value);
}
if (Field & ED_NEXT_EDPTR) {
Ed->NextED = Value;
}
return EFI_SUCCESS;
}
/**
Get value from an ED's specific field
@Param Ed ED pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field
)
{
switch (Field) {
case ED_FUNC_ADD:
return Ed->Word0.FunctionAddress;
break;
case ED_ENDPT_NUM:
return Ed->Word0.EndPointNum;
break;
case ED_DIR:
return Ed->Word0.Direction;
break;
case ED_SPEED:
return Ed->Word0.Speed;
break;
case ED_SKIP:
return Ed->Word0.Skip;
break;
case ED_FORMAT:
return Ed->Word0.Format;
break;
case ED_MAX_PACKET:
return Ed->Word0.MaxPacketSize;
break;
case ED_TDTAIL_PTR:
return Ed->TdTailPointer;
break;
case ED_HALTED:
return Ed->Word2.Halted;
break;
case ED_DTTOGGLE:
return Ed->Word2.ToggleCarry;
break;
case ED_TDHEAD_PTR:
return Ed->Word2.TdHeadPointer << 4;
break;
case ED_NEXT_EDPTR:
return Ed->NextED;
break;
default:
ASSERT (FALSE);
}
return 0;
}
/**
Set value to TD specific field
@Param Td TD to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field,
IN UINT32 Value
)
{
if (Field & TD_PDATA) {
Td->Word0.Reserved = Value;
}
if (Field & TD_BUFFER_ROUND) {
Td->Word0.BufferRounding = Value;
}
if (Field & TD_DIR_PID) {
Td->Word0.DirPID = Value;
}
if (Field & TD_DELAY_INT) {
Td->Word0.DelayInterrupt = Value;
}
if (Field & TD_DT_TOGGLE) {
Td->Word0.DataToggle = Value | 0x2;
}
if (Field & TD_ERROR_CNT) {
Td->Word0.ErrorCount = Value;
}
if (Field & TD_COND_CODE) {
Td->Word0.ConditionCode = Value;
}
if (Field & TD_CURR_BUFFER_PTR) {
Td->CurrBufferPointer = Value;
}
if (Field & TD_NEXT_PTR) {
Td->NextTD = Value;
}
if (Field & TD_BUFFER_END_PTR) {
Td->BufferEndPointer = Value;
}
return EFI_SUCCESS;
}
/**
Get value from ED specific field
@Param Td TD pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field
)
{
switch (Field){
case TD_BUFFER_ROUND:
return Td->Word0.BufferRounding;
break;
case TD_DIR_PID:
return Td->Word0.DirPID;
break;
case TD_DELAY_INT:
return Td->Word0.DelayInterrupt;
break;
case TD_DT_TOGGLE:
return Td->Word0.DataToggle;
break;
case TD_ERROR_CNT:
return Td->Word0.ErrorCount;
break;
case TD_COND_CODE:
return Td->Word0.ConditionCode;
break;
case TD_CURR_BUFFER_PTR:
return Td->CurrBufferPointer;
break;
case TD_NEXT_PTR:
return Td->NextTD;
break;
case TD_BUFFER_END_PTR:
return Td->BufferEndPointer;
break;
default:
ASSERT (FALSE);
}
return 0;
}
/**
Free the Ed,Td,buffer that were created during transferring
@Param Ohc Device private data
**/
VOID
OhciFreeDynamicIntMemory(
IN USB_OHCI_HC_DEV *Ohc
)
{
INTERRUPT_CONTEXT_ENTRY *Entry;
if (Ohc != NULL) {
while (Ohc->InterruptContextList != NULL) {
Entry = Ohc->InterruptContextList;
Ohc->InterruptContextList = Ohc->InterruptContextList->NextEntry;
OhciFreeInterruptEdByEd (Ohc, Entry->Ed);
OhciFreeInterruptContextEntry (Ohc, Entry);
}
}
}
/**
Free the Ed that were initilized during driver was starting,
those memory were used as interrupt ED head
@Param Ohc Device private data
**/
VOID
OhciFreeFixedIntMemory (
IN USB_OHCI_HC_DEV *Ohc
)
{
static UINT32 Leaf[] = {32,16,8,4,2,1};
UINTN Index;
UINTN Level;
for (Level = 0; Level < 6; Level++) {
for (Index = 0; Index < Leaf[Level]; Index++) {
if (Ohc->IntervalList[Level][Index] != NULL) {
UsbHcFreeMem(Ohc->MemPool, Ohc->IntervalList[Level][Index], sizeof(ED_DESCRIPTOR));
}
}
}
}
/**
Release all OHCI used memory when OHCI going to quit
@Param Ohc Device private data
@retval EFI_SUCCESS Memory released
**/
EFI_STATUS
OhciFreeIntTransferMemory (
IN USB_OHCI_HC_DEV *Ohc
)
{
//
// Free the Ed,Td,buffer that were created during transferring
//
OhciFreeDynamicIntMemory (Ohc);
//
// Free the Ed that were initilized during driver was starting
//
OhciFreeFixedIntMemory (Ohc);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,393 @@
/** @file
Provides some data struct used by OHCI controller driver.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_URB_H
#define _OHCI_URB_H
#include "Descriptor.h"
//
// Func List
//
/**
Create a TD
@Param Ohc UHC private data
@retval TD structure pointer
**/
TD_DESCRIPTOR *
OhciCreateTD (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Free a TD
@Param Ohc UHC private data
@Param Td Pointer to a TD to free
@retval EFI_SUCCESS TD freed
**/
EFI_STATUS
OhciFreeTD (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td
);
/**
Create a ED
@Param Ohc Device private data
@retval ED descriptor pointer
**/
ED_DESCRIPTOR *
OhciCreateED (
USB_OHCI_HC_DEV *Ohc
);
/**
Free a ED
@Param Ohc UHC private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
);
/**
Free ED
@Param Ohc Device private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeAllTDFromED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
);
/**
Find a working ED match the requirement
@Param EdHead Head of the ED list
@Param DeviceAddress Device address to search
@Param EndPointNum End point num to search
@Param EdDir ED Direction to search
@retval ED descriptor searched
**/
ED_DESCRIPTOR *
OhciFindWorkingEd (
IN ED_DESCRIPTOR *EdHead,
IN UINT8 DeviceAddress,
IN UINT8 EndPointNum,
IN UINT8 EdDir
);
/**
Initialize interrupt list.
@Param Ohc Device private data
@retval EFI_SUCCESS Initialization done
**/
EFI_STATUS
OhciInitializeInterruptList (
USB_OHCI_HC_DEV *Ohc
);
/**
Attach an ED
@Param Ed Ed to be attached
@Param NewEd Ed to attach
@retval EFI_SUCCESS NewEd attached to Ed
@retval EFI_INVALID_PARAMETER Ed is NULL
**/
EFI_STATUS
OhciAttachED (
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *NewEd
);
/**
Count ED number on a ED chain
@Param Ed Head of the ED chain
@retval ED number on the chain
**/
UINTN
CountEdNum (
IN ED_DESCRIPTOR *Ed
);
/**
Find the minimal burn ED list on a specific depth level
@Param Ohc Device private data
@Param Depth Depth level
@retval ED list found
**/
ED_DESCRIPTOR *
OhciFindMinInterruptEDList (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Depth
);
/**
Attach an ED to an ED list
@Param OHC UHC private data
@Param ListType Type of the ED list
@Param Ed ED to attach
@Param EdList ED list to be attached
@retval EFI_SUCCESS ED attached to ED list
**/
ED_DESCRIPTOR *
OhciAttachEDToList (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *EdList
);
/**
Remove interrupt EDs that match requirement
@Param Ohc UHC private data
@Param IntEd The address of Interrupt endpoint
@retval EFI_SUCCESS EDs match requirement removed
**/
EFI_STATUS
OhciFreeInterruptEdByEd (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *IntEd
);
/**
Remove interrupt EDs that match requirement
@Param Ohc UHC private data
@Param FunctionAddress Requirement on function address
@Param EndPointNum Requirement on end point number
@retval EFI_SUCCESS EDs match requirement removed
**/
EFI_STATUS
OhciFreeInterruptEdByAddr (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT8 FunctionAddress,
IN UINT8 EndPointNum
);
/**
Link Td2 to the end of Td1
@Param Td1 TD to be linked
@Param Td2 TD to link
@retval EFI_SUCCESS TD successfully linked
@retval EFI_INVALID_PARAMETER Td1 is NULL
**/
EFI_STATUS
OhciLinkTD (
IN TD_DESCRIPTOR *Td1,
IN TD_DESCRIPTOR *Td2
);
/**
Attach TD list to ED
@Param Ed ED which TD list attach on
@Param HeadTd Head of the TD list to attach
@retval EFI_SUCCESS TD list attached on the ED
**/
EFI_STATUS
OhciAttachTDListToED (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
);
/**
Set value to ED specific field
@Param Ed ED to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field,
IN UINT32 Value
);
/**
Get value from an ED's specific field
@Param Ed ED pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field
);
/**
Set value to TD specific field
@Param Td TD to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field,
IN UINT32 Value
);
/**
Get value from ED specific field
@Param Td TD pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field
);
/**
Free the Ed,Td,buffer that were created during transferring
@Param Ohc Device private data
**/
VOID
OhciFreeDynamicIntMemory(
IN USB_OHCI_HC_DEV *Ohc
);
/**
Free the Ed that were initilized during driver was starting,
those memory were used as interrupt ED head
@Param Ohc Device private data
**/
VOID
OhciFreeFixedIntMemory (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Release all OHCI used memory when OHCI going to quit
@Param Ohc Device private data
@retval EFI_SUCCESS Memory released
**/
EFI_STATUS
OhciFreeIntTransferMemory (
IN USB_OHCI_HC_DEV *Ohc
);
#endif

View File

@@ -0,0 +1,566 @@
/** @file
Routine procedures for memory allocate/free.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Ohci.h"
/**
Allocate a block of memory to be used by the buffer pool.
@param Pool The buffer pool to allocate memory for.
@param Pages How many pages to allocate.
@return The allocated memory block or NULL if failed.
**/
USBHC_MEM_BLOCK *
UsbHcAllocMemBlock (
IN USBHC_MEM_POOL *Pool,
IN UINTN Pages
)
{
USBHC_MEM_BLOCK *Block;
EFI_PCI_IO_PROTOCOL *PciIo;
VOID *BufHost;
VOID *Mapping;
EFI_PHYSICAL_ADDRESS MappedAddr;
UINTN Bytes;
EFI_STATUS Status;
PciIo = Pool->PciIo;
Block = AllocateZeroPool (sizeof (USBHC_MEM_BLOCK));
if (Block == NULL) {
return NULL;
}
//
// each bit in the bit array represents USBHC_MEM_UNIT
// bytes of memory in the memory block.
//
ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
Block->Bits = AllocateZeroPool (Block->BitsLen);
if (Block->Bits == NULL) {
gBS->FreePool (Block);
return NULL;
}
//
// Allocate the number of Pages of memory, then map it for
// bus master read and write.
//
Status = PciIo->AllocateBuffer (
PciIo,
AllocateAnyPages,
EfiBootServicesData,
Pages,
&BufHost,
0
);
if (EFI_ERROR (Status)) {
goto FREE_BITARRAY;
}
Bytes = EFI_PAGES_TO_SIZE (Pages);
Status = PciIo->Map (
PciIo,
EfiPciIoOperationBusMasterCommonBuffer,
BufHost,
&Bytes,
&MappedAddr,
&Mapping
);
if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (Pages))) {
goto FREE_BUFFER;
}
//
// Check whether the data structure used by the host controller
// should be restricted into the same 4G
//
if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {
PciIo->Unmap (PciIo, Mapping);
goto FREE_BUFFER;
}
Block->BufHost = BufHost;
Block->Buf = (UINT8 *) ((UINTN) MappedAddr);
Block->Mapping = Mapping;
return Block;
FREE_BUFFER:
PciIo->FreeBuffer (PciIo, Pages, BufHost);
FREE_BITARRAY:
gBS->FreePool (Block->Bits);
gBS->FreePool (Block);
return NULL;
}
/**
Free the memory block from the memory pool.
@param Pool The memory pool to free the block from.
@param Block The memory block to free.
**/
VOID
UsbHcFreeMemBlock (
IN USBHC_MEM_POOL *Pool,
IN USBHC_MEM_BLOCK *Block
)
{
EFI_PCI_IO_PROTOCOL *PciIo;
ASSERT ((Pool != NULL) && (Block != NULL));
PciIo = Pool->PciIo;
//
// Unmap the common buffer then free the structures
//
PciIo->Unmap (PciIo, Block->Mapping);
PciIo->FreeBuffer (PciIo, EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost);
gBS->FreePool (Block->Bits);
gBS->FreePool (Block);
}
/**
Alloc some memory from the block.
@param Block The memory block to allocate memory from.
@param Units Number of memory units to allocate.
@return The pointer to the allocated memory. If couldn't allocate the needed memory,
the return value is NULL.
**/
VOID *
UsbHcAllocMemFromBlock (
IN USBHC_MEM_BLOCK *Block,
IN UINTN Units
)
{
UINTN Byte;
UINT8 Bit;
UINTN StartByte;
UINT8 StartBit;
UINTN Available;
UINTN Count;
ASSERT ((Block != 0) && (Units != 0));
StartByte = 0;
StartBit = 0;
Available = 0;
for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
//
// If current bit is zero, the corresponding memory unit is
// available, otherwise we need to restart our searching.
// Available counts the consective number of zero bit.
//
if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
Available++;
if (Available >= Units) {
break;
}
NEXT_BIT (Byte, Bit);
} else {
NEXT_BIT (Byte, Bit);
Available = 0;
StartByte = Byte;
StartBit = Bit;
}
}
if (Available < Units) {
return NULL;
}
//
// Mark the memory as allocated
//
Byte = StartByte;
Bit = StartBit;
for (Count = 0; Count < Units; Count++) {
ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | USB_HC_BIT (Bit));
NEXT_BIT (Byte, Bit);
}
return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
}
/**
Calculate the corresponding pci bus address according to the Mem parameter.
@param Pool The memory pool of the host controller.
@param Mem The pointer to host memory.
@param Size The size of the memory region.
@return the pci memory address
**/
EFI_PHYSICAL_ADDRESS
UsbHcGetPciAddressForHostMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
)
{
USBHC_MEM_BLOCK *Head;
USBHC_MEM_BLOCK *Block;
UINTN AllocSize;
EFI_PHYSICAL_ADDRESS PhyAddr;
UINTN Offset;
Head = Pool->Head;
AllocSize = USBHC_MEM_ROUND (Size);
if (Mem == NULL) {
return 0;
}
for (Block = Head; Block != NULL; Block = Block->Next) {
//
// scan the memory block list for the memory block that
// completely contains the allocated memory.
//
if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {
break;
}
}
ASSERT ((Block != NULL));
//
// calculate the pci memory address for host memory address.
//
Offset = (UINT8 *)Mem - Block->BufHost;
PhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->Buf + Offset);
return PhyAddr;
}
/**
Insert the memory block to the pool's list of the blocks.
@param Head The head of the memory pool's block list.
@param Block The memory block to insert.
**/
VOID
UsbHcInsertMemBlockToPool (
IN USBHC_MEM_BLOCK *Head,
IN USBHC_MEM_BLOCK *Block
)
{
ASSERT ((Head != NULL) && (Block != NULL));
Block->Next = Head->Next;
Head->Next = Block;
}
/**
Is the memory block empty?
@param Block The memory block to check.
@retval TRUE The memory block is empty.
@retval FALSE The memory block isn't empty.
**/
BOOLEAN
UsbHcIsMemBlockEmpty (
IN USBHC_MEM_BLOCK *Block
)
{
UINTN Index;
for (Index = 0; Index < Block->BitsLen; Index++) {
if (Block->Bits[Index] != 0) {
return FALSE;
}
}
return TRUE;
}
/**
Unlink the memory block from the pool's list.
@param Head The block list head of the memory's pool.
@param BlockToUnlink The memory block to unlink.
**/
VOID
UsbHcUnlinkMemBlock (
IN USBHC_MEM_BLOCK *Head,
IN USBHC_MEM_BLOCK *BlockToUnlink
)
{
USBHC_MEM_BLOCK *Block;
ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
for (Block = Head; Block != NULL; Block = Block->Next) {
if (Block->Next == BlockToUnlink) {
Block->Next = BlockToUnlink->Next;
BlockToUnlink->Next = NULL;
break;
}
}
}
/**
Initialize the memory management pool for the host controller.
@param PciIo The PciIo that can be used to access the host controller.
@param Check4G Whether the host controller requires allocated memory
from one 4G address space.
@param Which4G The 4G memory area each memory allocated should be from.
@retval EFI_SUCCESS The memory pool is initialized.
@retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
**/
USBHC_MEM_POOL *
UsbHcInitMemPool (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN BOOLEAN Check4G,
IN UINT32 Which4G
)
{
USBHC_MEM_POOL *Pool;
Pool = AllocatePool (sizeof (USBHC_MEM_POOL));
if (Pool == NULL) {
return Pool;
}
Pool->PciIo = PciIo;
Pool->Check4G = Check4G;
Pool->Which4G = Which4G;
Pool->Head = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);
if (Pool->Head == NULL) {
gBS->FreePool (Pool);
Pool = NULL;
}
return Pool;
}
/**
Release the memory management pool.
@param Pool The USB memory pool to free.
@retval EFI_SUCCESS The memory pool is freed.
@retval EFI_DEVICE_ERROR Failed to free the memory pool.
**/
EFI_STATUS
UsbHcFreeMemPool (
IN USBHC_MEM_POOL *Pool
)
{
USBHC_MEM_BLOCK *Block;
ASSERT (Pool->Head != NULL);
//
// Unlink all the memory blocks from the pool, then free them.
// UsbHcUnlinkMemBlock can't be used to unlink and free the
// first block.
//
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
UsbHcUnlinkMemBlock (Pool->Head, Block);
UsbHcFreeMemBlock (Pool, Block);
}
UsbHcFreeMemBlock (Pool, Pool->Head);
gBS->FreePool (Pool);
return EFI_SUCCESS;
}
/**
Allocate some memory from the host controller's memory pool
which can be used to communicate with host controller.
@param Pool The host controller's memory pool.
@param Size Size of the memory to allocate.
@return The allocated memory or NULL.
**/
VOID *
UsbHcAllocateMem (
IN USBHC_MEM_POOL *Pool,
IN UINTN Size
)
{
USBHC_MEM_BLOCK *Head;
USBHC_MEM_BLOCK *Block;
USBHC_MEM_BLOCK *NewBlock;
VOID *Mem;
UINTN AllocSize;
UINTN Pages;
Mem = NULL;
AllocSize = USBHC_MEM_ROUND (Size);
Head = Pool->Head;
ASSERT (Head != NULL);
//
// First check whether current memory blocks can satisfy the allocation.
//
for (Block = Head; Block != NULL; Block = Block->Next) {
Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
if (Mem != NULL) {
ZeroMem (Mem, Size);
break;
}
}
if (Mem != NULL) {
return Mem;
}
//
// Create a new memory block if there is not enough memory
// in the pool. If the allocation size is larger than the
// default page number, just allocate a large enough memory
// block. Otherwise allocate default pages.
//
if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
} else {
Pages = USBHC_MEM_DEFAULT_PAGES;
}
NewBlock = UsbHcAllocMemBlock (Pool, Pages);
if (NewBlock == NULL) {
DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));
return NULL;
}
//
// Add the new memory block to the pool, then allocate memory from it
//
UsbHcInsertMemBlockToPool (Head, NewBlock);
Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
if (Mem != NULL) {
ZeroMem (Mem, Size);
}
return Mem;
}
/**
Free the allocated memory back to the memory pool.
@param Pool The memory pool of the host controller.
@param Mem The memory to free.
@param Size The size of the memory to free.
**/
VOID
UsbHcFreeMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
)
{
USBHC_MEM_BLOCK *Head;
USBHC_MEM_BLOCK *Block;
UINT8 *ToFree;
UINTN AllocSize;
UINTN Byte;
UINTN Bit;
UINTN Count;
Head = Pool->Head;
AllocSize = USBHC_MEM_ROUND (Size);
ToFree = (UINT8 *) Mem;
for (Block = Head; Block != NULL; Block = Block->Next) {
//
// scan the memory block list for the memory block that
// completely contains the memory to free.
//
if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {
//
// compute the start byte and bit in the bit array
//
Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;
Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;
//
// reset associated bits in bit arry
//
for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
NEXT_BIT (Byte, Bit);
}
break;
}
}
//
// If Block == NULL, it means that the current memory isn't
// in the host controller's pool. This is critical because
// the caller has passed in a wrong memory point
//
ASSERT (Block != NULL);
//
// Release the current memory block if it is empty and not the head
//
if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
UsbHcUnlinkMemBlock (Head, Block);
UsbHcFreeMemBlock (Pool, Block);
}
return ;
}

View File

@@ -0,0 +1,158 @@
/** @file
This file contains the definination for host controller memory
management routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _USB_HC_MEM_H_
#define _USB_HC_MEM_H_
#define USB_HC_BIT(a) ((UINTN)(1 << (a)))
#define USB_HC_BIT_IS_SET(Data, Bit) \
((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))
#define USB_HC_HIGH_32BIT(Addr64) \
((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))
typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;
struct _USBHC_MEM_BLOCK {
UINT8 *Bits; // Bit array to record which unit is allocated
UINTN BitsLen;
UINT8 *Buf;
UINT8 *BufHost;
UINTN BufLen; // Memory size in bytes
VOID *Mapping;
USBHC_MEM_BLOCK *Next;
};
//
// USBHC_MEM_POOL is used to manage the memory used by USB
// host controller. EHCI requires the control memory and transfer
// data to be on the same 4G memory.
//
typedef struct _USBHC_MEM_POOL {
EFI_PCI_IO_PROTOCOL *PciIo;
BOOLEAN Check4G;
UINT32 Which4G;
USBHC_MEM_BLOCK *Head;
} USBHC_MEM_POOL;
//
// Memory allocation unit, must be 2^n, n>4
//
#define USBHC_MEM_UNIT 64
#define USBHC_MEM_UNIT_MASK (USBHC_MEM_UNIT - 1)
#define USBHC_MEM_DEFAULT_PAGES 16
#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))
//
// Advance the byte and bit to the next bit, adjust byte accordingly.
//
#define NEXT_BIT(Byte, Bit) \
do { \
(Bit)++; \
if ((Bit) > 7) { \
(Byte)++; \
(Bit) = 0; \
} \
} while (0)
/**
Initialize the memory management pool for the host controller.
@param PciIo The PciIo that can be used to access the host controller.
@param Check4G Whether the host controller requires allocated memory
from one 4G address space.
@param Which4G The 4G memory area each memory allocated should be from.
@retval EFI_SUCCESS The memory pool is initialized.
@retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
**/
USBHC_MEM_POOL *
UsbHcInitMemPool (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN BOOLEAN Check4G,
IN UINT32 Which4G
);
/**
Release the memory management pool.
@param Pool The USB memory pool to free.
@retval EFI_SUCCESS The memory pool is freed.
@retval EFI_DEVICE_ERROR Failed to free the memory pool.
**/
EFI_STATUS
UsbHcFreeMemPool (
IN USBHC_MEM_POOL *Pool
);
/**
Allocate some memory from the host controller's memory pool
which can be used to communicate with host controller.
@param Pool The host controller's memory pool.
@param Size Size of the memory to allocate.
@return The allocated memory or NULL.
**/
VOID *
UsbHcAllocateMem (
IN USBHC_MEM_POOL *Pool,
IN UINTN Size
);
/**
Free the allocated memory back to the memory pool.
@param Pool The memory pool of the host controller.
@param Mem The memory to free.
@param Size The size of the memory to free.
**/
VOID
UsbHcFreeMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
);
/**
Calculate the corresponding pci bus address according to the Mem parameter.
@param Pool The memory pool of the host controller.
@param Mem The pointer to host memory.
@param Size The size of the memory region.
@return the pci memory address
**/
EFI_PHYSICAL_ADDRESS
UsbHcGetPciAddressForHostMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
);
#endif

View File

@@ -0,0 +1,137 @@
/** @file
This file contains the descriptor definination of OHCI spec
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _DESCRIPTOR_H
#define _DESCRIPTOR_H
#define ED_FUNC_ADD 0x0001
#define ED_ENDPT_NUM 0x0002
#define ED_DIR 0x0004
#define ED_SPEED 0x0008
#define ED_SKIP 0x0010
#define ED_FORMAT 0x0020
#define ED_MAX_PACKET 0x0040
#define ED_TDTAIL_PTR 0x0080
#define ED_HALTED 0x0100
#define ED_DTTOGGLE 0x0200
#define ED_TDHEAD_PTR 0x0400
#define ED_NEXT_EDPTR 0x0800
#define ED_PDATA 0x1000
#define ED_ZERO 0x2000
#define TD_BUFFER_ROUND 0x0001
#define TD_DIR_PID 0x0002
#define TD_DELAY_INT 0x0004
#define TD_DT_TOGGLE 0x0008
#define TD_ERROR_CNT 0x0010
#define TD_COND_CODE 0x0020
#define TD_CURR_BUFFER_PTR 0x0040
#define TD_NEXT_PTR 0x0080
#define TD_BUFFER_END_PTR 0x0100
#define TD_PDATA 0x0200
#define ED_FROM_TD_DIR 0x0
#define ED_OUT_DIR 0x1
#define ED_IN_DIR 0x2
#define ED_FROM_TD_ALSO_DIR 0x3
#define TD_SETUP_PID 0x00
#define TD_OUT_PID 0x01
#define TD_IN_PID 0x02
#define TD_NODATA_PID 0x03
#define HI_SPEED 0
#define LO_SPEED 1
#define TD_NO_ERROR 0x00
#define TD_CRC_ERROR 0x01
#define TD_BITSTUFFING_ERROR 0x02
#define TD_TOGGLE_ERROR 0x03
#define TD_DEVICE_STALL 0x04
#define TD_NO_RESPONSE 0x05
#define TD_PIDCHK_FAIL 0x06
#define TD_PID_UNEXPECTED 0x07
#define TD_DATA_OVERRUN 0x08
#define TD_DATA_UNDERRUN 0x09
#define TD_BUFFER_OVERRUN 0x0C
#define TD_BUFFER_UNDERRUN 0x0D
#define TD_TOBE_PROCESSED 0x0E
#define TD_TOBE_PROCESSED_2 0x0F
#define TD_NO_DELAY 0x7
#define TD_INT 0x1
#define TD_CTL 0x2
#define TD_BLK 0x3
typedef struct {
UINT32 Reserved:18;
UINT32 BufferRounding:1;
UINT32 DirPID:2;
UINT32 DelayInterrupt:3;
UINT32 DataToggle:2;
UINT32 ErrorCount:2;
UINT32 ConditionCode:4;
} TD_DESCRIPTOR_WORD0;
typedef struct _TD_DESCRIPTOR {
TD_DESCRIPTOR_WORD0 Word0;
VOID *CurrBufferPointer;
struct _TD_DESCRIPTOR *NextTD;
VOID *BufferEndPointer;
struct _TD_DESCRIPTOR *NextTDPointer;
UINT8 *DataBuffer;
UINT32 ActualSendLength;
} TD_DESCRIPTOR;
typedef struct {
UINT32 FunctionAddress:7;
UINT32 EndPointNum:4;
UINT32 Direction:2;
UINT32 Speed:1;
UINT32 Skip:1;
UINT32 Format:1;
UINT32 MaxPacketSize:11;
UINT32 FreeSpace:5;
} ED_DESCRIPTOR_WORD0;
typedef struct {
UINT32 Halted:1;
UINT32 ToggleCarry:1;
UINT32 Zero:2;
UINT32 TdHeadPointer:28;
} ED_DESCRIPTOR_WORD2;
typedef struct _ED_DESCRIPTOR {
ED_DESCRIPTOR_WORD0 Word0;
TD_DESCRIPTOR *TdTailPointer;
ED_DESCRIPTOR_WORD2 Word2;
struct _ED_DESCRIPTOR *NextED;
} ED_DESCRIPTOR;
#define TD_PTR(p) ((TD_DESCRIPTOR *)((p) << 4))
#define ED_PTR(p) ((ED_DESCRIPTOR *)((p) << 4))
#define RIGHT_SHIFT_4(p) ((UINT32)(p) >> 4)
typedef enum {
CONTROL_LIST,
BULK_LIST,
INTERRUPT_LIST,
ISOCHRONOUS_LIST
} DESCRIPTOR_LIST_TYPE;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,258 @@
/** @file
Provides the definition of Usb Hc Protocol and OHCI controller
private data structure.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_PEIM_H
#define _OHCI_PEIM_H
#include <PiPei.h>
#include <Ppi/UsbController.h>
#include <Ppi/UsbHostController.h>
#include <Library/DebugLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/TimerLib.h>
#include <Library/IoLib.h>
typedef struct _USB_OHCI_HC_DEV USB_OHCI_HC_DEV;
#include "UsbHcMem.h"
#include "OhciReg.h"
#include "OhciSched.h"
#include "OhciUrb.h"
#include "Descriptor.h"
#define EFI_USB_SPEED_FULL 0x0000
#define EFI_USB_SPEED_LOW 0x0001
#define EFI_USB_SPEED_HIGH 0x0002
#define PAGESIZE 4096
#define HC_1_MICROSECOND 1
#define HC_1_MILLISECOND (1000 * HC_1_MICROSECOND)
#define HC_1_SECOND (1000 * HC_1_MILLISECOND)
#define USB_OHCI_HC_DEV_SIGNATURE SIGNATURE_32('o','h','c','i')
struct _USB_OHCI_HC_DEV {
UINTN Signature;
PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi;
EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
UINT32 UsbHostControllerBaseAddress;
VOID *MemPool;
};
#define PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(a) CR (a, USB_OHCI_HC_DEV, UsbHostControllerPpi, USB_OHCI_HC_DEV_SIGNATURE)
//
// Func List
//
/**
Provides software reset for the USB host controller.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param Attributes A bit mask of the reset operation to perform.
@retval EFI_SUCCESS The reset operation succeeded.
@retval EFI_INVALID_PARAMETER Attributes is not valid.
@retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
not currently supported by the host controller.
@retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
**/
EFI_STATUS
InitializeUsbHC (
IN EFI_PEI_SERVICES **PeiServices,
IN USB_OHCI_HC_DEV *Ohc,
IN UINT16 Attributes
);
/**
Submits control transfer to a target USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param DeviceAddress The target device address.
@param DeviceSpeed Target device speed.
@param MaximumPacketLength Maximum packet size the default control transfer
endpoint is capable of sending or receiving.
@param Request USB device request to send.
@param TransferDirection Specifies the data direction for the data stage.
@param Data Data buffer to be transmitted or received from USB device.
@param DataLength The size (in bytes) of the data buffer.
@param TimeOut Indicates the maximum timeout, in millisecond.
@param TransferResult Return the result of this control transfer.
@retval EFI_SUCCESS Transfer was completed successfully.
@retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_TIMEOUT Transfer failed due to timeout.
@retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
**/
EFI_STATUS
EFIAPI
OhciControlTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 DeviceAddress,
IN UINT8 DeviceSpeed,
IN UINT8 MaxPacketLength,
IN EFI_USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION TransferDirection,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
);
/**
Submits bulk transfer to a bulk endpoint of a USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param DeviceAddress Target device address.
@param EndPointAddress Endpoint number and its direction in bit 7.
@param MaxiPacketLength Maximum packet size the endpoint is capable of
sending or receiving.
@param Data A pointers to the buffers of data to transmit
from or receive into.
@param DataLength The lenght of the data buffer.
@param DataToggle On input, the initial data toggle for the transfer;
On output, it is updated to to next data toggle to use of
the subsequent bulk transfer.
@param TimeOut Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@param TransferResult A pointer to the detailed result information of the
bulk transfer.
@retval EFI_SUCCESS The transfer was completed successfully.
@retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
@retval EFI_INVALID_PARAMETER Parameters are invalid.
@retval EFI_TIMEOUT The transfer failed due to timeout.
@retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
**/
EFI_STATUS
EFIAPI
OhciBulkTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN UINT8 MaxPacketLength,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN OUT UINT8 *DataToggle,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
);
/**
Retrieves the number of root hub ports.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB_HOST_CONTROLLER_PPI.
@param[out] NumOfPorts The pointer to the number of the root hub ports.
@retval EFI_SUCCESS The port number was retrieved successfully.
@retval EFI_INVALID_PARAMETER PortNumber is NULL.
**/
EFI_STATUS
EFIAPI
OhciGetRootHubNumOfPorts (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
OUT UINT8 *NumOfPorts
);
/**
Retrieves the current status of a USB root hub port.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param PortNumber The root hub port to retrieve the state from.
@param PortStatus Variable to receive the port state.
@retval EFI_SUCCESS The status of the USB root hub port specified.
by PortNumber was returned in PortStatus.
@retval EFI_INVALID_PARAMETER PortNumber is invalid.
**/
EFI_STATUS
EFIAPI
OhciGetRootHubPortStatus (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
OUT EFI_USB_PORT_STATUS *PortStatus
);
/**
Sets a feature for the specified root hub port.
@param This A pointer to the EFI_USB_HC_PROTOCOL.
@param PortNumber Specifies the root hub port whose feature
is requested to be set.
@param PortFeature Indicates the feature selector associated
with the feature set request.
@retval EFI_SUCCESS The feature specified by PortFeature was set for the
USB root hub port specified by PortNumber.
@retval EFI_DEVICE_ERROR Set feature failed because of hardware issue
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
**/
EFI_STATUS
EFIAPI
OhciSetRootHubPortFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
/**
Clears a feature for the specified root hub port.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
@param PortNumber Specifies the root hub port whose feature
is requested to be cleared.
@param PortFeature Indicates the feature selector associated with the
feature clear request.
@retval EFI_SUCCESS The feature specified by PortFeature was cleared
for the USB root hub port specified by PortNumber.
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
**/
EFI_STATUS
EFIAPI
OhciClearRootHubPortFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
#endif

View File

@@ -0,0 +1,62 @@
## @file
# OHCI USB Host Controller PEIM
#
# Copyright (c) 2013-2015 Intel Corporation.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = OhciPei
FILE_GUID = 332A0926-429B-4624-9211-A36B23DF0389
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = OhcPeimEntry
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
Descriptor.h
OhcPeim.c
OhcPeim.h
OhciSched.c
OhciSched.h
OhciReg.c
OhciReg.h
OhciUrb.c
OhciUrb.h
UsbHcMem.c
UsbHcMem.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
QuarkSocPkg/QuarkSocPkg.dec
[LibraryClasses]
IoLib
TimerLib
BaseMemoryLib
PeimEntryPoint
PeiServicesLib
[Ppis]
gPeiUsbHostControllerPpiGuid # PPI ALWAYS_PRODUCED
gPeiUsbControllerPpiGuid # PPI ALWAYS_CONSUMED
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,881 @@
/** @file
This file contains the definination for host controller
register operation routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_REGS_H
#define _OHCI_REGS_H
#define HC_STATE_RESET 0x0
#define HC_STATE_RESUME 0x1
#define HC_STATE_OPERATIONAL 0x2
#define HC_STATE_SUSPEND 0x3
#define PERIODIC_ENABLE 0x01
#define ISOCHRONOUS_ENABLE 0x02
#define CONTROL_ENABLE 0x04
#define BULK_ENABLE 0x08
#define CONTROL_BULK_RATIO 0x10
#define HC_FUNCTIONAL_STATE 0x20
#define INTERRUPT_ROUTING 0x40
#define HC_RESET 0x01
#define CONTROL_LIST_FILLED 0x02
#define BULK_LIST_FILLED 0x04
#define CHANGE_OWNER_REQUEST 0x08
#define SCHEDULE_OVERRUN_COUNT 0x10
#define SCHEDULE_OVERRUN 0x00001
#define WRITEBACK_DONE_HEAD 0x00002
#define START_OF_FRAME 0x00004
#define RESUME_DETECT 0x00008
#define UNRECOVERABLE_ERROR 0x00010
#define FRAME_NUMBER_OVERFLOW 0x00020
#define ROOTHUB_STATUS_CHANGE 0x00040
#define OWNERSHIP_CHANGE 0x00080
#define MASTER_INTERRUPT 0x00400
#define CONTROL_HEAD 0x001
#define BULK_HEAD 0x002
#define DONE_HEAD 0x004
#define Hc_HCCA 0x001
#define Hc_PERIODIC_CURRENT 0x002
#define Hc_CONTOL_HEAD 0x004
#define Hc_CONTROL_CURRENT_PTR 0x008
#define Hc_BULK_HEAD 0x010
#define Hc_BULK_CURRENT_PTR 0x020
#define Hc_DONE_HEAD 0x040
#define FRAME_INTERVAL 0x008
#define FS_LARGEST_DATA_PACKET 0x010
#define FRMINT_TOGGLE 0x020
#define FRAME_REMAINING 0x040
#define FRAME_REMAIN_TOGGLE 0x080
#define RH_DESC_A 0x00001
#define RH_DESC_B 0x00002
#define RH_NUM_DS_PORTS 0x00004
#define RH_NO_PSWITCH 0x00008
#define RH_PSWITCH_MODE 0x00010
#define RH_DEVICE_TYPE 0x00020
#define RH_OC_PROT_MODE 0x00040
#define RH_NOC_PROT 0x00080
#define RH_POTPGT 0x00100
#define RH_NO_POTPGT 0x00200
#define RH_DEV_REMOVABLE 0x00400
#define RH_PORT_PWR_CTRL_MASK 0x00800
#define RH_LOCAL_PSTAT 0x00001
#define RH_OC_ID 0x00002
#define RH_REMOTE_WK_ENABLE 0x00004
#define RH_LOCAL_PSTAT_CHANGE 0x00008
#define RH_OC_ID_CHANGE 0x00010
#define RH_CLR_RMT_WK_ENABLE 0x00020
#define RH_CLEAR_PORT_ENABLE 0x0001
#define RH_SET_PORT_ENABLE 0x0002
#define RH_SET_PORT_SUSPEND 0x0004
#define RH_CLEAR_SUSPEND_STATUS 0x0008
#define RH_SET_PORT_RESET 0x0010
#define RH_SET_PORT_POWER 0x0020
#define RH_CLEAR_PORT_POWER 0x0040
#define RH_CONNECT_STATUS_CHANGE 0x10000
#define RH_PORT_ENABLE_STAT_CHANGE 0x20000
#define RH_PORT_SUSPEND_STAT_CHANGE 0x40000
#define RH_OC_INDICATOR_CHANGE 0x80000
#define RH_PORT_RESET_STAT_CHANGE 0x100000
#define RH_CURR_CONNECT_STAT 0x0001
#define RH_PORT_ENABLE_STAT 0x0002
#define RH_PORT_SUSPEND_STAT 0x0004
#define RH_PORT_OC_INDICATOR 0x0008
#define RH_PORT_RESET_STAT 0x0010
#define RH_PORT_POWER_STAT 0x0020
#define RH_LSDEVICE_ATTACHED 0x0040
#define RESET_SYSTEM_BUS (1 << 0)
#define RESET_HOST_CONTROLLER (1 << 1)
#define RESET_CLOCK_GENERATION (1 << 2)
#define RESET_SSE_GLOBAL (1 << 5)
#define RESET_PSPL (1 << 6)
#define RESET_PCPL (1 << 7)
#define RESET_SSEP1 (1 << 9)
#define RESET_SSEP2 (1 << 10)
#define RESET_SSEP3 (1 << 11)
#define ONE_SECOND 1000000
#define ONE_MILLI_SEC 1000
#define MAX_BYTES_PER_TD 0x1000
#define MAX_RETRY_TIMES 100
#define PORT_NUMBER_ON_MAINSTONE2 1
//
// Operational Register Offsets
//
//
// Command & Status Registers Offsets
//
#define HC_REVISION 0x00
#define HC_CONTROL 0x04
#define HC_COMMAND_STATUS 0x08
#define HC_INTERRUPT_STATUS 0x0C
#define HC_INTERRUPT_ENABLE 0x10
#define HC_INTERRUPT_DISABLE 0x14
//
// Memory Pointer Offsets
//
#define HC_HCCA 0x18
#define HC_PERIODIC_CURRENT 0x1C
#define HC_CONTROL_HEAD 0x20
#define HC_CONTROL_CURRENT_PTR 0x24
#define HC_BULK_HEAD 0x28
#define HC_BULK_CURRENT_PTR 0x2C
#define HC_DONE_HEAD 0x30
//
// Frame Register Offsets
//
#define HC_FRM_INTERVAL 0x34
#define HC_FRM_REMAINING 0x38
#define HC_FRM_NUMBER 0x3C
#define HC_PERIODIC_START 0x40
#define HC_LS_THREASHOLD 0x44
//
// Root Hub Register Offsets
//
#define HC_RH_DESC_A 0x48
#define HC_RH_DESC_B 0x4C
#define HC_RH_STATUS 0x50
#define HC_RH_PORT_STATUS 0x54
#define USBHOST_OFFSET_UHCHR 0x64 // Usb Host reset register
#define OHC_BAR_INDEX 0
//
// Usb Host controller register offset
//
#define USBHOST_OFFSET_UHCREV 0x0 // Usb Host revision register
#define USBHOST_OFFSET_UHCHCON 0x4 // Usb Host control register
#define USBHOST_OFFSET_UHCCOMS 0x8 // Usb Host Command Status register
#define USBHOST_OFFSET_UHCINTS 0xC // Usb Host Interrupt Status register
#define USBHOST_OFFSET_UHCINTE 0x10 // Usb Host Interrupt Enable register
#define USBHOST_OFFSET_UHCINTD 0x14 // Usb Host Interrupt Disable register
#define USBHOST_OFFSET_UHCHCCA 0x18 // Usb Host Controller Communication Area
#define USBHOST_OFFSET_UHCPCED 0x1C // Usb Host Period Current Endpoint Descriptor
#define USBHOST_OFFSET_UHCCHED 0x20 // Usb Host Control Head Endpoint Descriptor
#define USBHOST_OFFSET_UHCCCED 0x24 // Usb Host Control Current Endpoint Descriptor
#define USBHOST_OFFSET_UHCBHED 0x28 // Usb Host Bulk Head Endpoint Descriptor
#define USBHOST_OFFSET_UHCBCED 0x2C // Usb Host Bulk Current Endpoint Descriptor
#define USBHOST_OFFSET_UHCDHEAD 0x30 // Usb Host Done Head register
#define USBHOST_OFFSET_UHCFMI 0x34 // Usb Host Frame Interval register
#define USBHOST_OFFSET_UHCFMR 0x38 // Usb Host Frame Remaining register
#define USBHOST_OFFSET_UHCFMN 0x3C // Usb Host Frame Number register
#define USBHOST_OFFSET_UHCPERS 0x40 // Usb Host Periodic Start register
#define USBHOST_OFFSET_UHCLST 0x44 // Usb Host Low-Speed Threshold register
#define USBHOST_OFFSET_UHCRHDA 0x48 // Usb Host Root Hub Descriptor A register
#define USBHOST_OFFSET_UHCRHDB 0x4C // Usb Host Root Hub Descriptor B register
#define USBHOST_OFFSET_UHCRHS 0x50 // Usb Host Root Hub Status register
#define USBHOST_OFFSET_UHCRHPS1 0x54 // Usb Host Root Hub Port Status 1 register
//
// Usb Host controller register bit fields
//
#pragma pack(1)
typedef struct {
UINT8 ProgInterface;
UINT8 SubClassCode;
UINT8 BaseCode;
} USB_CLASSC;
typedef struct {
UINT32 Revision:8;
UINT32 Rsvd:24;
} HcREVISION;
typedef struct {
UINT32 ControlBulkRatio:2;
UINT32 PeriodicEnable:1;
UINT32 IsochronousEnable:1;
UINT32 ControlEnable:1;
UINT32 BulkEnable:1;
UINT32 FunctionalState:2;
UINT32 InterruptRouting:1;
UINT32 RemoteWakeup:1;
UINT32 RemoteWakeupEnable:1;
UINT32 Reserved:21;
} HcCONTROL;
typedef struct {
UINT32 HcReset:1;
UINT32 ControlListFilled:1;
UINT32 BulkListFilled:1;
UINT32 ChangeOwnerRequest:1;
UINT32 Reserved1:12;
UINT32 ScheduleOverrunCount:2;
UINT32 Reserved:14;
} HcCOMMAND_STATUS;
typedef struct {
UINT32 SchedulingOverrun:1;
UINT32 WriteBackDone:1;
UINT32 Sof:1;
UINT32 ResumeDetected:1;
UINT32 UnrecoverableError:1;
UINT32 FrameNumOverflow:1;
UINT32 RHStatusChange:1;
UINT32 Reserved1:23;
UINT32 OwnerChange:1;
UINT32 Reserved2:1;
} HcINTERRUPT_STATUS;
typedef struct {
UINT32 SchedulingOverrunInt:1;
UINT32 WriteBackDoneInt:1;
UINT32 SofInt:1;
UINT32 ResumeDetectedInt:1;
UINT32 UnrecoverableErrorInt:1;
UINT32 FrameNumOverflowInt:1;
UINT32 RHStatusChangeInt:1;
UINT32 Reserved:23;
UINT32 OwnerChangedInt:1;
UINT32 MasterInterruptEnable:1;
} HcINTERRUPT_CONTROL;
typedef struct {
UINT32 Rerserved:8;
UINT32 Hcca:24;
} HcHCCA;
typedef struct {
UINT32 Reserved:4;
UINT32 MemoryPtr:28;
} HcMEMORY_PTR;
typedef struct {
UINT32 FrameInterval:14;
UINT32 Reserved:2;
UINT32 FSMaxDataPacket:15;
UINT32 FrmIntervalToggle:1;
} HcFRM_INTERVAL;
typedef struct {
UINT32 FrameRemaining:14;
UINT32 Reserved:17;
UINT32 FrameRemainingToggle:1;
} HcFRAME_REMAINING;
typedef struct {
UINT32 FrameNumber:16;
UINT32 Reserved:16;
} HcFRAME_NUMBER;
typedef struct {
UINT32 PeriodicStart:14;
UINT32 Reserved:18;
} HcPERIODIC_START;
typedef struct {
UINT32 LsThreshold:12;
UINT32 Reserved:20;
} HcLS_THRESHOLD;
typedef struct {
UINT32 NumDownStrmPorts:8;
UINT32 PowerSwitchMode:1;
UINT32 NoPowerSwitch:1;
UINT32 DeviceType:1;
UINT32 OverCurrentProtMode:1;
UINT32 NoOverCurrentProtMode:1;
UINT32 Reserved:11;
UINT32 PowerOnToPowerGoodTime:8;
} HcRH_DESC_A;
typedef struct {
UINT32 DeviceRemovable:16;
UINT32 PortPowerControlMask:16;
} HcRH_DESC_B;
typedef struct {
UINT32 LocalPowerStat:1;
UINT32 OverCurrentIndicator:1;
UINT32 Reserved1:13;
UINT32 DevRemoteWakeupEnable:1;
UINT32 LocalPowerStatChange:1;
UINT32 OverCurrentIndicatorChange:1;
UINT32 Reserved2:13;
UINT32 ClearRemoteWakeupEnable:1;
} HcRH_STATUS;
typedef struct {
UINT32 CurrentConnectStat:1;
UINT32 EnableStat:1;
UINT32 SuspendStat:1;
UINT32 OCIndicator:1;
UINT32 ResetStat:1;
UINT32 Reserved1:3;
UINT32 PowerStat:1;
UINT32 LsDeviceAttached:1;
UINT32 Reserved2:6;
UINT32 ConnectStatChange:1;
UINT32 EnableStatChange:1;
UINT32 SuspendStatChange:1;
UINT32 OCIndicatorChange:1;
UINT32 ResetStatChange:1;
UINT32 Reserved3:11;
} HcRHPORT_STATUS;
typedef struct {
UINT32 FSBIR:1;
UINT32 FHR:1;
UINT32 CGR:1;
UINT32 SSDC:1;
UINT32 UIT:1;
UINT32 SSE:1;
UINT32 PSPL:1;
UINT32 PCPL:1;
UINT32 Reserved0:1;
UINT32 SSEP1:1;
UINT32 SSEP2:1;
UINT32 SSEP3:1;
UINT32 Reserved1:20;
} HcRESET;
#pragma pack()
//
// Func List
//
/**
Get OHCI operational reg value
@param Ohc UHC private data
@param Offset Offset of the operational reg
@retval Value of the register
**/
UINT32
OhciGetOperationalReg (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Offset
);
/**
Set OHCI operational reg value
@param Ohc UHC private data
@param Offset Offset of the operational reg
@param Value Value to set
@retval EFI_SUCCESS Value set to the reg
**/
EFI_STATUS
OhciSetOperationalReg (
USB_OHCI_HC_DEV *Ohc,
IN UINT32 Offset,
IN UINT32 *Value
);
/**
Get HcRevision reg value
@param Ohc UHC private data
@retval Value of the register
**/
UINT32
OhciGetHcRevision (
USB_OHCI_HC_DEV *Ohc
);
/**
Set HcReset reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetHcReset (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Field,
IN UINT32 Value
);
/**
Get specific field of HcReset reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcReset (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Field
);
/**
Set HcControl reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetHcControl (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get specific field of HcControl reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcControl (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set HcCommand reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetHcCommandStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get specific field of HcCommand reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcCommandStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Clear specific fields of Interrupt Status
@param Ohc UHC private data
@param Field Field to clear
@retval EFI_SUCCESS Fields cleared
**/
EFI_STATUS
OhciClearInterruptStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Get fields of HcInterrupt reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcInterruptStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Interrupt Control reg value
@param Ohc UHC private data
@param StatEnable Enable or Disable
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetInterruptControl (
IN USB_OHCI_HC_DEV *Ohc,
IN BOOLEAN StatEnable,
IN UINTN Field,
IN UINT32 Value
);
/**
Get field of HcInterruptControl reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetHcInterruptControl (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set memory pointer of specific type
@param Ohc UHC private data
@param PointerType Type of the pointer to set
@param Value Value to set
@retval EFI_SUCCESS Memory pointer set
**/
EFI_STATUS
OhciSetMemoryPointer(
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN PointerType,
IN VOID *Value
);
/**
Get memory pointer of specific type
@param Ohc UHC private data
@param PointerType Type of pointer
@retval Memory pointer of the specific type
**/
VOID *
OhciGetMemoryPointer (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN PointerType
);
/**
Set Frame Interval value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetFrameInterval (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get field of frame interval reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetFrameInterval (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Frame Remaining reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetFrameRemaining (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get value of frame remaining reg
@param Ohc UHC private data
@param Field Field to get
@retval Value of frame remaining reg
**/
UINT32
OhciGetFrameRemaining (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set frame number reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetFrameNumber(
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get frame number reg value
@param Ohc UHC private data
@retval Value of frame number reg
**/
UINT32
OhciGetFrameNumber (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Set period start reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetPeriodicStart (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get periodic start reg value
@param Ohc UHC private data
@param Value of periodic start reg
**/
UINT32
OhciGetPeriodicStart (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Set Ls Threshold reg value
@param Ohc UHC private data
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetLsThreshold (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Value
);
/**
Get Ls Threshold reg value
@param Ohc UHC private data
@retval Value of Ls Threshold reg
**/
UINT32
OhciGetLsThreshold (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Set Root Hub Descriptor reg value
@param Ohc UHC private data
@param Field Field to set
@param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetRootHubDescriptor (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field,
IN UINT32 Value
);
/**
Get Root Hub Descriptor reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetRootHubDescriptor (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Root Hub Status reg value
@param Ohc UHC private data
@param Field Field to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetRootHubStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Get Root Hub Status reg value
@param Ohc UHC private data
@param Field Field to get
@retval Value of the field
**/
UINT32
OhciGetRootHubStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINTN Field
);
/**
Set Root Hub Port Status reg value
@param Ohc UHC private data
@param Index Index of the port
@param Field Field to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetRootHubPortStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Index,
IN UINTN Field
);
/**
Get Root Hub Port Status reg value
@param Ohc UHC private data
@param Index Index of the port
@param Field Field to get
@retval Value of the field and index
**/
UINT32
OhciReadRootHubPortStatus (
IN USB_OHCI_HC_DEV *Ohc,
IN UINT32 Index,
IN UINTN Field
);
#endif

View File

@@ -0,0 +1,229 @@
/** @file
OHCI transfer scheduling routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "OhcPeim.h"
/**
Convert Error code from OHCI format to EFI format
@Param ErrorCode ErrorCode in OHCI format
@retval ErrorCode in EFI format
**/
UINT32
ConvertErrorCode (
IN UINT32 ErrorCode
)
{
UINT32 TransferResult;
switch (ErrorCode) {
case TD_NO_ERROR:
TransferResult = EFI_USB_NOERROR;
break;
case TD_TOBE_PROCESSED:
case TD_TOBE_PROCESSED_2:
TransferResult = EFI_USB_ERR_NOTEXECUTE;
break;
case TD_DEVICE_STALL:
TransferResult = EFI_USB_ERR_STALL;
break;
case TD_BUFFER_OVERRUN:
case TD_BUFFER_UNDERRUN:
TransferResult = EFI_USB_ERR_BUFFER;
break;
case TD_CRC_ERROR:
TransferResult = EFI_USB_ERR_CRC;
break;
case TD_NO_RESPONSE:
TransferResult = EFI_USB_ERR_TIMEOUT;
break;
case TD_BITSTUFFING_ERROR:
TransferResult = EFI_USB_ERR_BITSTUFF;
break;
default:
TransferResult = EFI_USB_ERR_SYSTEM;
}
return TransferResult;
}
/**
Check TDs Results
@Param Ohc UHC private data
@Param Td TD_DESCRIPTOR
@Param Result Result to return
@retval TRUE means OK
@retval FLASE means Error or Short packet
**/
BOOLEAN
OhciCheckTDsResults (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td,
OUT UINT32 *Result
)
{
UINT32 TdCompletionCode;
*Result = EFI_USB_NOERROR;
while (Td) {
TdCompletionCode = Td->Word0.ConditionCode;
*Result |= ConvertErrorCode(TdCompletionCode);
//
// if any error encountered, stop processing the left TDs.
//
if (*Result) {
return FALSE;
}
Td = Td->NextTDPointer;
}
return TRUE;
}
/**
Check the task status on an ED
@Param Ed Pointer to the ED task that TD hooked on
@Param HeadTd TD header for current transaction
@retval Task Status Code
**/
UINT32
CheckEDStatus (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
)
{
while(HeadTd != NULL) {
if (HeadTd->Word0.ConditionCode != 0) {
return HeadTd->Word0.ConditionCode;
}
HeadTd = HeadTd->NextTDPointer;
}
if (OhciGetEDField (Ed, ED_TDHEAD_PTR) != OhciGetEDField (Ed, ED_TDTAIL_PTR)) {
return TD_TOBE_PROCESSED;
}
return TD_NO_ERROR;
}
/**
Check the task status
@Param Ohc UHC private data
@Param ListType Pipe type
@Param Ed Pointer to the ED task hooked on
@Param HeadTd Head of TD corresponding to the task
@Param ErrorCode return the ErrorCode
@retval EFI_SUCCESS Task done
@retval EFI_NOT_READY Task on processing
@retval EFI_DEVICE_ERROR Some error occured
**/
EFI_STATUS
CheckIfDone (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd,
OUT UINT32 *ErrorCode
)
{
*ErrorCode = TD_TOBE_PROCESSED;
switch (ListType) {
case CONTROL_LIST:
if (OhciGetHcCommandStatus (Ohc, CONTROL_LIST_FILLED) != 0) {
return EFI_NOT_READY;
}
break;
case BULK_LIST:
if (OhciGetHcCommandStatus (Ohc, BULK_LIST_FILLED) != 0) {
return EFI_NOT_READY;
}
break;
default:
break;
}
*ErrorCode = CheckEDStatus (Ed, HeadTd);
if (*ErrorCode == TD_NO_ERROR) {
return EFI_SUCCESS;
} else if (*ErrorCode == TD_TOBE_PROCESSED) {
return EFI_NOT_READY;
} else {
return EFI_DEVICE_ERROR;
}
}
/**
Convert TD condition code to Efi Status
@Param ConditionCode Condition code to convert
@retval EFI_SUCCESS No error occured
@retval EFI_NOT_READY TD still on processing
@retval EFI_DEVICE_ERROR Error occured in processing TD
**/
EFI_STATUS
OhciTDConditionCodeToStatus (
IN UINT32 ConditionCode
)
{
if (ConditionCode == TD_NO_ERROR) {
return EFI_SUCCESS;
}
if (ConditionCode == TD_TOBE_PROCESSED) {
return EFI_NOT_READY;
}
return EFI_DEVICE_ERROR;
}

View File

@@ -0,0 +1,114 @@
/** @file
This file contains the definination for host controller schedule routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_SCHED_H
#define _OHCI_SCHED_H
#include "Descriptor.h"
#define HCCA_MEM_SIZE 256
#define GRID_SIZE 16
#define GRID_SHIFT 4
/**
Convert Error code from OHCI format to EFI format
@Param ErrorCode ErrorCode in OHCI format
@retval ErrorCode in EFI format
**/
UINT32
ConvertErrorCode (
IN UINT32 ErrorCode
);
/**
Check TDs Results
@Param Ohc UHC private data
@Param Td TD_DESCRIPTOR
@Param Result Result to return
@retval TRUE means OK
@retval FLASE means Error or Short packet
**/
BOOLEAN
OhciCheckTDsResults (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td,
OUT UINT32 *Result
);
/**
Check the task status on an ED
@Param Ed Pointer to the ED task that TD hooked on
@Param HeadTd TD header for current transaction
@retval Task Status Code
**/
UINT32
CheckEDStatus (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
);
/**
Check the task status
@Param Ohc UHC private data
@Param ListType Pipe type
@Param Ed Pointer to the ED task hooked on
@Param HeadTd Head of TD corresponding to the task
@Param ErrorCode return the ErrorCode
@retval EFI_SUCCESS Task done
@retval EFI_NOT_READY Task on processing
@retval EFI_DEVICE_ERROR Some error occured
**/
EFI_STATUS
CheckIfDone (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd,
OUT UINT32 *ErrorCode
);
/**
Convert TD condition code to Efi Status
@Param ConditionCode Condition code to convert
@retval EFI_SUCCESS No error occured
@retval EFI_NOT_READY TD still on processing
@retval EFI_DEVICE_ERROR Error occured in processing TD
**/
EFI_STATUS
OhciTDConditionCodeToStatus (
IN UINT32 ConditionCode
);
#endif

View File

@@ -0,0 +1,566 @@
/** @file
This file contains URB request, each request is warpped in a
URB (Usb Request Block).
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "OhcPeim.h"
/**
Create a TD
@Param Ohc UHC private data
@retval TD structure pointer
**/
TD_DESCRIPTOR *
OhciCreateTD (
IN USB_OHCI_HC_DEV *Ohc
)
{
TD_DESCRIPTOR *Td;
Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR));
if (Td == NULL) {
return NULL;
}
Td->CurrBufferPointer = NULL;
Td->NextTD = NULL;
Td->BufferEndPointer = NULL;
Td->NextTDPointer = NULL;
return Td;
}
/**
Free a TD
@Param Ohc UHC private data
@Param Td Pointer to a TD to free
@retval EFI_SUCCESS TD freed
**/
EFI_STATUS
OhciFreeTD (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td
)
{
if (Td == NULL) {
return EFI_SUCCESS;
}
UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
return EFI_SUCCESS;
}
/**
Create a ED
@Param Ohc Device private data
@retval ED descriptor pointer
**/
ED_DESCRIPTOR *
OhciCreateED (
USB_OHCI_HC_DEV *Ohc
)
{
ED_DESCRIPTOR *Ed;
Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR));
if (Ed == NULL) {
return NULL;
}
Ed->Word0.Skip = 1;
Ed->TdTailPointer = NULL;
Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) NULL);
Ed->NextED = NULL;
return Ed;
}
/**
Free a ED
@Param Ohc UHC private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
)
{
if (Ed == NULL) {
return EFI_SUCCESS;
}
UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
return EFI_SUCCESS;
}
/**
Free ED
@Param Ohc Device private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeAllTDFromED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
)
{
TD_DESCRIPTOR *HeadTd;
TD_DESCRIPTOR *TailTd;
TD_DESCRIPTOR *Td;
TD_DESCRIPTOR *TempTd;
if (Ed == NULL) {
return EFI_SUCCESS;
}
HeadTd = TD_PTR (Ed->Word2.TdHeadPointer);
TailTd = Ed->TdTailPointer;
Td = HeadTd;
while (Td != TailTd) {
TempTd = Td;
Td = Td->NextTDPointer;
OhciFreeTD (Ohc, TempTd);
}
return EFI_SUCCESS;
}
/**
Attach an ED
@Param Ed Ed to be attached
@Param NewEd Ed to attach
@retval EFI_SUCCESS NewEd attached to Ed
@retval EFI_INVALID_PARAMETER Ed is NULL
**/
EFI_STATUS
OhciAttachED (
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *NewEd
)
{
ED_DESCRIPTOR *Temp;
if (Ed == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Ed->NextED == NULL){
Ed->NextED = NewEd;
} else {
Temp = Ed->NextED;
Ed->NextED = NewEd;
NewEd->NextED = Temp;
}
return EFI_SUCCESS;
}
/**
Attach an ED to an ED list
@Param OHC UHC private data
@Param ListType Type of the ED list
@Param Ed ED to attach
@Param EdList ED list to be attached
@retval EFI_SUCCESS ED attached to ED list
**/
EFI_STATUS
OhciAttachEDToList (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *EdList
)
{
ED_DESCRIPTOR *HeadEd;
switch(ListType) {
case CONTROL_LIST:
HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD);
if (HeadEd == NULL) {
OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed);
} else {
OhciAttachED (HeadEd, Ed);
}
break;
case BULK_LIST:
HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD);
if (HeadEd == NULL) {
OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed);
} else {
OhciAttachED (HeadEd, Ed);
}
break;
case INTERRUPT_LIST:
OhciAttachED (EdList, Ed);
break;
default:
ASSERT (FALSE);
}
return EFI_SUCCESS;
}
/**
Link Td2 to the end of Td1
@Param Td1 TD to be linked
@Param Td2 TD to link
@retval EFI_SUCCESS TD successfully linked
@retval EFI_INVALID_PARAMETER Td1 is NULL
**/
EFI_STATUS
OhciLinkTD (
IN TD_DESCRIPTOR *Td1,
IN TD_DESCRIPTOR *Td2
)
{
TD_DESCRIPTOR *TempTd;
if (Td1 == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Td1 == Td2) {
return EFI_SUCCESS;
}
TempTd = Td1;
while (TempTd->NextTD != NULL) {
TempTd = TempTd->NextTD;
}
TempTd->NextTD = Td2;
TempTd->NextTDPointer = Td2;
return EFI_SUCCESS;
}
/**
Attach TD list to ED
@Param Ed ED which TD list attach on
@Param HeadTd Head of the TD list to attach
@retval EFI_SUCCESS TD list attached on the ED
**/
EFI_STATUS
OhciAttachTDListToED (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
)
{
TD_DESCRIPTOR *TempTd;
TempTd = TD_PTR (Ed->Word2.TdHeadPointer);
if (TempTd != NULL) {
while (TempTd->NextTD != NULL) {
TempTd = TempTd->NextTD;
}
TempTd->NextTD = HeadTd;
TempTd->NextTDPointer = HeadTd;
} else {
Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) HeadTd);
}
return EFI_SUCCESS;
}
/**
Set value to ED specific field
@Param Ed ED to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field,
IN UINT32 Value
)
{
if (Field & ED_FUNC_ADD) {
Ed->Word0.FunctionAddress = Value;
}
if (Field & ED_ENDPT_NUM) {
Ed->Word0.EndPointNum = Value;
}
if (Field & ED_DIR) {
Ed->Word0.Direction = Value;
}
if (Field & ED_SPEED) {
Ed->Word0.Speed = Value;
}
if (Field & ED_SKIP) {
Ed->Word0.Skip = Value;
}
if (Field & ED_FORMAT) {
Ed->Word0.Format = Value;
}
if (Field & ED_MAX_PACKET) {
Ed->Word0.MaxPacketSize = Value;
}
if (Field & ED_PDATA) {
Ed->Word0.FreeSpace = Value;
}
if (Field & ED_ZERO) {
Ed->Word2.Zero = Value;
}
if (Field & ED_TDTAIL_PTR) {
Ed->TdTailPointer = (VOID *) Value;
}
if (Field & ED_HALTED) {
Ed->Word2.Halted = Value;
}
if (Field & ED_DTTOGGLE) {
Ed->Word2.ToggleCarry = Value;
}
if (Field & ED_TDHEAD_PTR) {
Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value);
}
if (Field & ED_NEXT_EDPTR) {
Ed->NextED = (VOID *) Value;
}
return EFI_SUCCESS;
}
/**
Get value from an ED's specific field
@Param Ed ED pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field
)
{
switch (Field) {
case ED_FUNC_ADD:
return Ed->Word0.FunctionAddress;
break;
case ED_ENDPT_NUM:
return Ed->Word0.EndPointNum;
break;
case ED_DIR:
return Ed->Word0.Direction;
break;
case ED_SPEED:
return Ed->Word0.Speed;
break;
case ED_SKIP:
return Ed->Word0.Skip;
break;
case ED_FORMAT:
return Ed->Word0.Format;
break;
case ED_MAX_PACKET:
return Ed->Word0.MaxPacketSize;
break;
case ED_TDTAIL_PTR:
return (UINT32) Ed->TdTailPointer;
break;
case ED_HALTED:
return Ed->Word2.Halted;
break;
case ED_DTTOGGLE:
return Ed->Word2.ToggleCarry;
break;
case ED_TDHEAD_PTR:
return Ed->Word2.TdHeadPointer << 4;
break;
case ED_NEXT_EDPTR:
return (UINT32) Ed->NextED;
break;
default:
ASSERT (FALSE);
}
return 0;
}
/**
Set value to TD specific field
@Param Td TD to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field,
IN UINT32 Value
)
{
if (Field & TD_PDATA) {
Td->Word0.Reserved = Value;
}
if (Field & TD_BUFFER_ROUND) {
Td->Word0.BufferRounding = Value;
}
if (Field & TD_DIR_PID) {
Td->Word0.DirPID = Value;
}
if (Field & TD_DELAY_INT) {
Td->Word0.DelayInterrupt = Value;
}
if (Field & TD_DT_TOGGLE) {
Td->Word0.DataToggle = Value | 0x2;
}
if (Field & TD_ERROR_CNT) {
Td->Word0.ErrorCount = Value;
}
if (Field & TD_COND_CODE) {
Td->Word0.ConditionCode = Value;
}
if (Field & TD_CURR_BUFFER_PTR) {
Td->CurrBufferPointer = (VOID *) Value;
}
if (Field & TD_NEXT_PTR) {
Td->NextTD = (VOID *) Value;
}
if (Field & TD_BUFFER_END_PTR) {
Td->BufferEndPointer = (VOID *) Value;
}
return EFI_SUCCESS;
}
/**
Get value from ED specific field
@Param Td TD pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field
)
{
switch (Field){
case TD_BUFFER_ROUND:
return Td->Word0.BufferRounding;
break;
case TD_DIR_PID:
return Td->Word0.DirPID;
break;
case TD_DELAY_INT:
return Td->Word0.DelayInterrupt;
break;
case TD_DT_TOGGLE:
return Td->Word0.DataToggle;
break;
case TD_ERROR_CNT:
return Td->Word0.ErrorCount;
break;
case TD_COND_CODE:
return Td->Word0.ConditionCode;
break;
case TD_CURR_BUFFER_PTR:
return (UINT32) Td->CurrBufferPointer;
break;
case TD_NEXT_PTR:
return (UINT32) Td->NextTD;
break;
case TD_BUFFER_END_PTR:
return (UINT32) Td->BufferEndPointer;
break;
default:
ASSERT (FALSE);
}
return 0;
}

View File

@@ -0,0 +1,237 @@
/** @file
Provides some data struct used by OHCI controller driver.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _OHCI_URB_H
#define _OHCI_URB_H
#include "Descriptor.h"
//
// Func List
//
/**
Create a TD
@Param Ohc UHC private data
@retval TD structure pointer
**/
TD_DESCRIPTOR *
OhciCreateTD (
IN USB_OHCI_HC_DEV *Ohc
);
/**
Free a TD
@Param Ohc UHC private data
@Param Td Pointer to a TD to free
@retval EFI_SUCCESS TD freed
**/
EFI_STATUS
OhciFreeTD (
IN USB_OHCI_HC_DEV *Ohc,
IN TD_DESCRIPTOR *Td
);
/**
Create a ED
@Param Ohc Device private data
@retval ED descriptor pointer
**/
ED_DESCRIPTOR *
OhciCreateED (
USB_OHCI_HC_DEV *Ohc
);
/**
Free a ED
@Param Ohc UHC private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
);
/**
Free ED
@Param Ohc Device private data
@Param Ed Pointer to a ED to free
@retval EFI_SUCCESS ED freed
**/
EFI_STATUS
OhciFreeAllTDFromED (
IN USB_OHCI_HC_DEV *Ohc,
IN ED_DESCRIPTOR *Ed
);
/**
Attach an ED
@Param Ed Ed to be attached
@Param NewEd Ed to attach
@retval EFI_SUCCESS NewEd attached to Ed
@retval EFI_INVALID_PARAMETER Ed is NULL
**/
EFI_STATUS
OhciAttachED (
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *NewEd
);
/**
Attach an ED to an ED list
@Param OHC UHC private data
@Param ListType Type of the ED list
@Param Ed ED to attach
@Param EdList ED list to be attached
@retval EFI_SUCCESS ED attached to ED list
**/
EFI_STATUS
OhciAttachEDToList (
IN USB_OHCI_HC_DEV *Ohc,
IN DESCRIPTOR_LIST_TYPE ListType,
IN ED_DESCRIPTOR *Ed,
IN ED_DESCRIPTOR *EdList
);
EFI_STATUS
OhciLinkTD (
IN TD_DESCRIPTOR *Td1,
IN TD_DESCRIPTOR *Td2
);
/**
Attach TD list to ED
@Param Ed ED which TD list attach on
@Param HeadTd Head of the TD list to attach
@retval EFI_SUCCESS TD list attached on the ED
**/
EFI_STATUS
OhciAttachTDListToED (
IN ED_DESCRIPTOR *Ed,
IN TD_DESCRIPTOR *HeadTd
);
/**
Set value to ED specific field
@Param Ed ED to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field,
IN UINT32 Value
);
/**
Get value from an ED's specific field
@Param Ed ED pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetEDField (
IN ED_DESCRIPTOR *Ed,
IN UINT32 Field
);
/**
Set value to TD specific field
@Param Td TD to be set
@Param Field Field to be set
@Param Value Value to set
@retval EFI_SUCCESS Value set
**/
EFI_STATUS
OhciSetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field,
IN UINT32 Value
);
/**
Get value from ED specific field
@Param Td TD pointer
@Param Field Field to get value from
@retval Value of the field
**/
UINT32
OhciGetTDField (
IN TD_DESCRIPTOR *Td,
IN UINT32 Field
);
#endif

View File

@@ -0,0 +1,497 @@
/** @file
Routine procedures for memory allocate/free.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "OhcPeim.h"
/**
Allocate a block of memory to be used by the buffer pool.
Use Redirect memory services to allocate memmory so that USB DMA transfers do
not cause IMR violations on Quark.
@param Pool The buffer pool to allocate memory for.
@param Pages How many pages to allocate.
@return The allocated memory block or NULL if failed.
**/
USBHC_MEM_BLOCK *
UsbHcAllocMemBlock (
IN USBHC_MEM_POOL *Pool,
IN UINTN Pages
)
{
USBHC_MEM_BLOCK *Block;
VOID *BufHost;
VOID *Mapping;
EFI_PHYSICAL_ADDRESS MappedAddr;
EFI_STATUS Status;
UINTN PageNumber;
EFI_PHYSICAL_ADDRESS TempPtr;
Mapping = NULL;
PageNumber = sizeof(USBHC_MEM_BLOCK)/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
&TempPtr
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
//
// each bit in the bit array represents USBHC_MEM_UNIT
// bytes of memory in the memory block.
//
ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
Block = (USBHC_MEM_BLOCK*)(UINTN)TempPtr;
Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
PageNumber = (Block->BitsLen)/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
&TempPtr
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
Block->Bits = (UINT8 *)(UINTN)TempPtr;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
Pages,
&TempPtr
);
ZeroMem ((VOID *)(UINTN)TempPtr, Pages*EFI_PAGE_SIZE);
BufHost = (VOID *)(UINTN)TempPtr;
MappedAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) BufHost;
//
// Check whether the data structure used by the host controller
// should be restricted into the same 4G
//
if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {
return NULL;
}
Block->BufHost = BufHost;
Block->Buf = (UINT8 *) ((UINTN) MappedAddr);
Block->Mapping = Mapping;
Block->Next = NULL;
return Block;
}
/**
Free the memory block from the memory pool.
@param Pool The memory pool to free the block from.
@param Block The memory block to free.
**/
VOID
UsbHcFreeMemBlock (
IN USBHC_MEM_POOL *Pool,
IN USBHC_MEM_BLOCK *Block
)
{
ASSERT ((Pool != NULL) && (Block != NULL));
}
/**
Alloc some memory from the block.
@param Block The memory block to allocate memory from.
@param Units Number of memory units to allocate.
@return The pointer to the allocated memory. If couldn't allocate the needed memory,
the return value is NULL.
**/
VOID *
UsbHcAllocMemFromBlock (
IN USBHC_MEM_BLOCK *Block,
IN UINTN Units
)
{
UINTN Byte;
UINT8 Bit;
UINTN StartByte;
UINT8 StartBit;
UINTN Available;
UINTN Count;
ASSERT ((Block != 0) && (Units != 0));
StartByte = 0;
StartBit = 0;
Available = 0;
for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
//
// If current bit is zero, the corresponding memory unit is
// available, otherwise we need to restart our searching.
// Available counts the consective number of zero bit.
//
if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
Available++;
if (Available >= Units) {
break;
}
NEXT_BIT (Byte, Bit);
} else {
NEXT_BIT (Byte, Bit);
Available = 0;
StartByte = Byte;
StartBit = Bit;
}
}
if (Available < Units) {
return NULL;
}
//
// Mark the memory as allocated
//
Byte = StartByte;
Bit = StartBit;
for (Count = 0; Count < Units; Count++) {
ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) USB_HC_BIT (Bit));
NEXT_BIT (Byte, Bit);
}
return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
}
/**
Insert the memory block to the pool's list of the blocks.
@param Head The head of the memory pool's block list.
@param Block The memory block to insert.
**/
VOID
UsbHcInsertMemBlockToPool (
IN USBHC_MEM_BLOCK *Head,
IN USBHC_MEM_BLOCK *Block
)
{
ASSERT ((Head != NULL) && (Block != NULL));
Block->Next = Head->Next;
Head->Next = Block;
}
/**
Is the memory block empty?
@param Block The memory block to check.
@retval TRUE The memory block is empty.
@retval FALSE The memory block isn't empty.
**/
BOOLEAN
UsbHcIsMemBlockEmpty (
IN USBHC_MEM_BLOCK *Block
)
{
UINTN Index;
for (Index = 0; Index < Block->BitsLen; Index++) {
if (Block->Bits[Index] != 0) {
return FALSE;
}
}
return TRUE;
}
/**
Unlink the memory block from the pool's list.
@param Head The block list head of the memory's pool.
@param BlockToUnlink The memory block to unlink.
**/
VOID
UsbHcUnlinkMemBlock (
IN USBHC_MEM_BLOCK *Head,
IN USBHC_MEM_BLOCK *BlockToUnlink
)
{
USBHC_MEM_BLOCK *Block;
ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
for (Block = Head; Block != NULL; Block = Block->Next) {
if (Block->Next == BlockToUnlink) {
Block->Next = BlockToUnlink->Next;
BlockToUnlink->Next = NULL;
break;
}
}
}
/**
Initialize the memory management pool for the host controller.
@param PciIo The PciIo that can be used to access the host controller.
@param Check4G Whether the host controller requires allocated memory
from one 4G address space.
@param Which4G The 4G memory area each memory allocated should be from.
@retval EFI_SUCCESS The memory pool is initialized.
@retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
**/
USBHC_MEM_POOL *
UsbHcInitMemPool (
IN BOOLEAN Check4G,
IN UINT32 Which4G
)
{
USBHC_MEM_POOL *Pool;
UINTN PageNumber;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS TempPtr;
PageNumber = sizeof(USBHC_MEM_POOL)/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
&TempPtr
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
Pool = (USBHC_MEM_POOL *) ((UINTN) TempPtr);
Pool->Check4G = Check4G;
Pool->Which4G = Which4G;
Pool->Head = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);
if (Pool->Head == NULL) {
Pool = NULL;
}
return Pool;
}
/**
Release the memory management pool.
@param Pool The USB memory pool to free.
@retval EFI_SUCCESS The memory pool is freed.
@retval EFI_DEVICE_ERROR Failed to free the memory pool.
**/
EFI_STATUS
UsbHcFreeMemPool (
IN USBHC_MEM_POOL *Pool
)
{
USBHC_MEM_BLOCK *Block;
ASSERT (Pool->Head != NULL);
//
// Unlink all the memory blocks from the pool, then free them.
// UsbHcUnlinkMemBlock can't be used to unlink and free the
// first block.
//
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
UsbHcFreeMemBlock (Pool, Block);
}
UsbHcFreeMemBlock (Pool, Pool->Head);
return EFI_SUCCESS;
}
/**
Allocate some memory from the host controller's memory pool
which can be used to communicate with host controller.
@param Pool The host controller's memory pool.
@param Size Size of the memory to allocate.
@return The allocated memory or NULL.
**/
VOID *
UsbHcAllocateMem (
IN USBHC_MEM_POOL *Pool,
IN UINTN Size
)
{
USBHC_MEM_BLOCK *Head;
USBHC_MEM_BLOCK *Block;
USBHC_MEM_BLOCK *NewBlock;
VOID *Mem;
UINTN AllocSize;
UINTN Pages;
Mem = NULL;
AllocSize = USBHC_MEM_ROUND (Size);
Head = Pool->Head;
ASSERT (Head != NULL);
//
// First check whether current memory blocks can satisfy the allocation.
//
for (Block = Head; Block != NULL; Block = Block->Next) {
Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
if (Mem != NULL) {
ZeroMem (Mem, Size);
break;
}
}
if (Mem != NULL) {
return Mem;
}
//
// Create a new memory block if there is not enough memory
// in the pool. If the allocation size is larger than the
// default page number, just allocate a large enough memory
// block. Otherwise allocate default pages.
//
if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
} else {
Pages = USBHC_MEM_DEFAULT_PAGES;
}
NewBlock = UsbHcAllocMemBlock (Pool, Pages);
if (NewBlock == NULL) {
DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));
return NULL;
}
//
// Add the new memory block to the pool, then allocate memory from it
//
UsbHcInsertMemBlockToPool (Head, NewBlock);
Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
if (Mem != NULL) {
ZeroMem (Mem, Size);
}
return Mem;
}
/**
Free the allocated memory back to the memory pool.
@param Pool The memory pool of the host controller.
@param Mem The memory to free.
@param Size The size of the memory to free.
**/
VOID
UsbHcFreeMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
)
{
USBHC_MEM_BLOCK *Head;
USBHC_MEM_BLOCK *Block;
UINT8 *ToFree;
UINTN AllocSize;
UINTN Byte;
UINTN Bit;
UINTN Count;
Head = Pool->Head;
AllocSize = USBHC_MEM_ROUND (Size);
ToFree = (UINT8 *) Mem;
for (Block = Head; Block != NULL; Block = Block->Next) {
//
// scan the memory block list for the memory block that
// completely contains the memory to free.
//
if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {
//
// compute the start byte and bit in the bit array
//
Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;
Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;
//
// reset associated bits in bit arry
//
for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
NEXT_BIT (Byte, Bit);
}
break;
}
}
//
// If Block == NULL, it means that the current memory isn't
// in the host controller's pool. This is critical because
// the caller has passed in a wrong memory point
//
ASSERT (Block != NULL);
//
// Release the current memory block if it is empty and not the head
//
if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
UsbHcFreeMemBlock (Pool, Block);
}
return ;
}

View File

@@ -0,0 +1,140 @@
/** @file
This file contains the definination for host controller memory
management routines.
Copyright (c) 2013-2015 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _USB_HC_MEM_H_
#define _USB_HC_MEM_H_
#define USB_HC_BIT(a) ((UINTN)(1 << (a)))
#define USB_HC_BIT_IS_SET(Data, Bit) \
((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))
#define USB_HC_HIGH_32BIT(Addr64) \
((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))
typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;
struct _USBHC_MEM_BLOCK {
UINT8 *Bits; // Bit array to record which unit is allocated
UINTN BitsLen;
UINT8 *Buf;
UINT8 *BufHost;
UINTN BufLen; // Memory size in bytes
VOID *Mapping;
USBHC_MEM_BLOCK *Next;
};
//
// USBHC_MEM_POOL is used to manage the memory used by USB
// host controller. EHCI requires the control memory and transfer
// data to be on the same 4G memory.
//
typedef struct _USBHC_MEM_POOL {
BOOLEAN Check4G;
UINT32 Which4G;
USBHC_MEM_BLOCK *Head;
} USBHC_MEM_POOL;
//
// Memory allocation unit, must be 2^n, n>4
//
#define USBHC_MEM_UNIT 64
#define USBHC_MEM_UNIT_MASK (USBHC_MEM_UNIT - 1)
#define USBHC_MEM_DEFAULT_PAGES 16
#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))
//
// Advance the byte and bit to the next bit, adjust byte accordingly.
//
#define NEXT_BIT(Byte, Bit) \
do { \
(Bit)++; \
if ((Bit) > 7) { \
(Byte)++; \
(Bit) = 0; \
} \
} while (0)
/**
Initialize the memory management pool for the host controller.
@param PciIo The PciIo that can be used to access the host controller.
@param Check4G Whether the host controller requires allocated memory
from one 4G address space.
@param Which4G The 4G memory area each memory allocated should be from.
@retval EFI_SUCCESS The memory pool is initialized.
@retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
**/
USBHC_MEM_POOL *
UsbHcInitMemPool (
IN BOOLEAN Check4G,
IN UINT32 Which4G
);
/**
Release the memory management pool.
@param Pool The USB memory pool to free.
@retval EFI_SUCCESS The memory pool is freed.
@retval EFI_DEVICE_ERROR Failed to free the memory pool.
**/
EFI_STATUS
UsbHcFreeMemPool (
IN USBHC_MEM_POOL *Pool
);
/**
Allocate some memory from the host controller's memory pool
which can be used to communicate with host controller.
@param Pool The host controller's memory pool.
@param Size Size of the memory to allocate.
@return The allocated memory or NULL.
**/
VOID *
UsbHcAllocateMem (
IN USBHC_MEM_POOL *Pool,
IN UINTN Size
);
/**
Free the allocated memory back to the memory pool.
@param Pool The memory pool of the host controller.
@param Mem The memory to free.
@param Size The size of the memory to free.
**/
VOID
UsbHcFreeMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
);
#endif