audk/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c

1731 lines
29 KiB
C

/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. 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.
Module Name:
Ehchlp.c
Abstract:
Revision History
--*/
#include "Ehci.h"
VOID
HostReset (
IN USB2_HC_DEV *HcDev
)
{
UINT32 Value;
UINT32 TimeOut;
ReadEhcOperationalReg (
HcDev,
USBCMD,
&Value
);
Value = Value & (~USBCMD_RS);
WriteEhcOperationalReg (
HcDev,
USBCMD,
Value
);
TimeOut = 40;
while (TimeOut --) {
gBS->Stall (500);
ReadEhcOperationalReg (
HcDev,
USBSTS,
&Value
);
if ((Value & USBSTS_HCH) != 0) {
break;
}
}
if (TimeOut == 0) {
DEBUG((gEHCErrorLevel, "TimeOut for clearing Run/Stop bit\n"));
}
ReadEhcOperationalReg (
HcDev,
USBCMD,
&Value
);
Value = Value | USBCMD_HCRESET;
WriteEhcOperationalReg (
HcDev,
USBCMD,
Value
);
TimeOut = 40;
while (TimeOut --) {
gBS->Stall (500);
ReadEhcOperationalReg (
HcDev,
USBCMD,
&Value
);
if ((Value & USBCMD_HCRESET) == 0) {
break;
}
}
if (TimeOut == 0) {
DEBUG((gEHCErrorLevel, "TimeOut for Host Reset\n"));
}
}
EFI_STATUS
ReadEhcCapabiltiyReg (
IN USB2_HC_DEV *HcDev,
IN UINT32 CapabiltiyRegAddr,
IN OUT UINT32 *Data
)
/*++
Routine Description:
Read Ehc Capabitlity register
Arguments:
HcDev - USB2_HC_DEV
CapabiltiyRegAddr - Ehc Capability register address
Data - A pointer to data read from register
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
return HcDev->PciIo->Mem.Read (
HcDev->PciIo,
EfiPciIoWidthUint32,
USB_BAR_INDEX,
(UINT64) CapabiltiyRegAddr,
1,
Data
);
}
EFI_STATUS
ReadEhcOperationalReg (
IN USB2_HC_DEV *HcDev,
IN UINT32 OperationalRegAddr,
IN OUT UINT32 *Data
)
/*++
Routine Description:
Read Ehc Operation register
Arguments:
HcDev - USB2_HC_DEV
OperationalRegAddr - Ehc Operation register address
Data - A pointer to data read from register
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
ASSERT (HcDev->UsbCapabilityLen);
return HcDev->PciIo->Mem.Read (
HcDev->PciIo,
EfiPciIoWidthUint32,
USB_BAR_INDEX,
(UINT64) (OperationalRegAddr + HcDev->UsbCapabilityLen),
1,
Data
);
}
EFI_STATUS
WriteEhcOperationalReg (
IN USB2_HC_DEV *HcDev,
IN UINT32 OperationalRegAddr,
IN UINT32 Data
)
/*++
Routine Description:
Write Ehc Operation register
Arguments:
HcDev - USB2_HC_DEV
OperationalRegAddr - Ehc Operation register address
Data - 32bit write to register
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
ASSERT (HcDev->UsbCapabilityLen);
return HcDev->PciIo->Mem.Write (
HcDev->PciIo,
EfiPciIoWidthUint32,
USB_BAR_INDEX,
(UINT64) (OperationalRegAddr + HcDev->UsbCapabilityLen),
1,
&Data
);
}
VOID
ClearLegacySupport (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Stop the legacy USB SMI
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
UINT32 EECP;
UINT32 Value;
UINT32 TimeOut;
ReadEhcCapabiltiyReg (
HcDev,
HCCPARAMS,
&EECP
);
EECP = (EECP >> 8) & 0xFF;
DEBUG ((gEHCDebugLevel, "EHCI: EECPBase = 0x%x\n", EECP));
HcDev->PciIo->Pci.Read (
HcDev->PciIo,
EfiPciIoWidthUint32,
EECP,
1,
&Value
);
DEBUG((gEHCDebugLevel, "EECP[0] = 0x%x\n", Value));
HcDev->PciIo->Pci.Read (
HcDev->PciIo,
EfiPciIoWidthUint32,
EECP + 0x4,
1,
&Value
);
DEBUG((gEHCDebugLevel, "EECP[4] = 0x%x\n", Value));
HcDev->PciIo->Pci.Read (
HcDev->PciIo,
EfiPciIoWidthUint32,
EECP,
1,
&Value
);
Value = Value | (0x1 << 24);
DEBUG((gEHCErrorLevel, "Value Written = 0x%x\n", Value));
HcDev->PciIo->Pci.Write (
HcDev->PciIo,
EfiPciIoWidthUint32,
EECP,
1,
&Value
);
TimeOut = 40;
while (TimeOut --) {
gBS->Stall (500);
HcDev->PciIo->Pci.Read (
HcDev->PciIo,
EfiPciIoWidthUint32,
EECP,
1,
&Value
);
if ((Value & 0x01010000) == 0x01000000) {
break;
}
}
if (TimeOut == 0) {
DEBUG((gEHCErrorLevel, "Timeout for getting HC OS Owned Semaphore\n" ));
}
DEBUG((gEHCErrorLevel, "After Release Value\n" ));
HcDev->PciIo->Pci.Read (
HcDev->PciIo,
EfiPciIoWidthUint32,
EECP,
1,
&Value
);
DEBUG((gEHCDebugLevel, "EECP[0] = 0x%x\n", Value));
HcDev->PciIo->Pci.Read (
HcDev->PciIo,
EfiPciIoWidthUint32,
EECP + 0x4,
1,
&Value
);
DEBUG((gEHCDebugLevel, "EECP[4] = 0x%x\n", Value));
}
EFI_STATUS
GetCapabilityLen (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Get the length of capability register
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 CapabilityLenAddr;
CapabilityLenAddr = CAPLENGTH;
Status = ReadEhcCapabiltiyReg (
HcDev,
CapabilityLenAddr,
&(HcDev->UsbCapabilityLen)
);
HcDev->UsbCapabilityLen = (UINT8) HcDev->UsbCapabilityLen;
return Status;
}
EFI_STATUS
SetFrameListLen (
IN USB2_HC_DEV *HcDev,
IN UINTN Length
)
/*++
Routine Description:
Set the length of Frame List
Arguments:
HcDev - USB2_HC_DEV
Length - the required length of frame list
Returns:
EFI_SUCCESS Success
EFI_INVALID_PARAMETER Invalid parameter
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UsbCommandAddr = USBCMD;
if (256 != Length && 512 != Length) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
Status = ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
if (256 == Length) {
UsbCommandReg |= USBCMD_FLS_256;
} else {
UsbCommandReg |= USBCMD_FLS_512;
}
Status = WriteEhcOperationalReg (
HcDev,
UsbCommandAddr,
UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
exit:
return Status;
}
EFI_STATUS
SetFrameListBaseAddr (
IN USB2_HC_DEV *HcDev,
IN UINT32 FrameBuffer
)
/*++
Routine Description:
Set base address of frame list first entry
Arguments:
HcDev - USB2_HC_DEV
FrameBuffer - base address of first entry of frame list
Returns:
--*/
{
EFI_STATUS Status;
UINT32 PeriodicListBaseAddr;
UINT32 PeriodicListBaseReg;
Status = EFI_SUCCESS;
PeriodicListBaseAddr = PERIODICLISTBASE;
PeriodicListBaseReg = FrameBuffer & 0xfffff000;
if (IsEhcHalted (HcDev)) {
Status = WriteEhcOperationalReg (
HcDev,
PeriodicListBaseAddr,
PeriodicListBaseReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
}
exit:
return Status;
}
EFI_STATUS
SetAsyncListAddr (
IN USB2_HC_DEV *HcDev,
IN EHCI_QH_ENTITY *QhPtr
)
/*++
Routine Description:
Set address of first Async schedule Qh
Arguments:
HcDev - USB2_HC_DEV
QhPtr - A pointer to first Qh in the Async schedule
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 AsyncListAddr;
UINT32 AsyncListReg;
AsyncListAddr = ASYNCLISTADDR;
AsyncListReg = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh));
Status = WriteEhcOperationalReg (
HcDev,
AsyncListAddr,
AsyncListReg
);
return Status;
}
EFI_STATUS
SetCtrlDataStructSeg (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Set register of control and data structure segment
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 CtrlDsSegmentAddr;
UINT32 CtrlDsSegmentReg;
CtrlDsSegmentAddr = CTRLDSSGMENT;
CtrlDsSegmentReg = HcDev->High32BitAddr;
Status = WriteEhcOperationalReg (
HcDev,
CtrlDsSegmentAddr,
CtrlDsSegmentReg
);
return Status;
}
EFI_STATUS
SetPortRoutingEhc (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Set Ehc port routing bit
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 ConfigFlagAddr;
UINT32 ConfigFlagReg;
ConfigFlagAddr = CONFIGFLAG;
Status = ReadEhcOperationalReg (
HcDev,
ConfigFlagAddr,
&ConfigFlagReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
ConfigFlagReg |= CONFIGFLAG_CF;
Status = WriteEhcOperationalReg (
HcDev,
ConfigFlagAddr,
ConfigFlagReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
exit:
return Status;
}
EFI_STATUS
SetEhcDoorbell (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Set Ehc door bell bit
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UsbCommandAddr = USBCMD;
Status = ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
UsbCommandReg |= USBCMD_IAAD;
Status = WriteEhcOperationalReg (
HcDev,
UsbCommandAddr,
UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
exit:
return Status;
}
EFI_STATUS
ClearEhcAllStatus (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Clear Ehc all status bits
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
UINT32 UsbStatusAddr;
UsbStatusAddr = USBSTS;
return WriteEhcOperationalReg (
HcDev,
UsbStatusAddr,
0x003F
);
}
EFI_STATUS
EnablePeriodicSchedule (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Enable periodic schedule
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UsbCommandAddr = USBCMD;
Status = ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
UsbCommandReg |= USBCMD_PSE;
Status = WriteEhcOperationalReg (
HcDev,
UsbCommandAddr,
UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
exit:
return Status;
}
EFI_STATUS
DisablePeriodicSchedule (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Disable periodic schedule
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UsbCommandAddr = USBCMD;
Status = ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
UsbCommandReg &= ~USBCMD_PSE;
Status = WriteEhcOperationalReg (
HcDev,
UsbCommandAddr,
UsbCommandReg
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
return Status;
}
EFI_STATUS
EnableAsynchronousSchedule (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Enable asynchrounous schedule
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UsbCommandAddr = USBCMD;
Status = ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
UsbCommandReg |= USBCMD_ASE;
Status = WriteEhcOperationalReg (
HcDev,
UsbCommandAddr,
UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
exit:
return Status;
}
EFI_STATUS
DisableAsynchronousSchedule (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Disable asynchrounous schedule
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UsbCommandAddr = USBCMD;
Status = ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
UsbCommandReg &= ~USBCMD_ASE;
Status = WriteEhcOperationalReg (
HcDev,
UsbCommandAddr,
UsbCommandReg
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
return Status;
}
EFI_STATUS
ResetEhc (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Reset Ehc
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UsbCommandAddr = USBCMD;
Status = ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
UsbCommandReg |= USBCMD_HCRESET;
Status = WriteEhcOperationalReg (
HcDev,
UsbCommandAddr,
UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
exit:
return Status;
}
EFI_STATUS
StartScheduleExecution (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Start Ehc schedule execution
Arguments:
HcDev - USB2_HC_DEV
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UsbCommandAddr = USBCMD;
Status = ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
UsbCommandReg |= USBCMD_RS;
Status = WriteEhcOperationalReg (
HcDev,
UsbCommandAddr,
UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
exit:
return Status;
}
BOOLEAN
IsFrameListProgrammable (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Whether frame list is programmable
Arguments:
HcDev - USB2_HC_DEV
Returns:
TRUE Programmable
FALSE Unprogrammable
--*/
{
BOOLEAN Value;
UINT32 HcCapParamsAddr;
UINT32 HcCapParamsReg;
HcCapParamsAddr = HCCPARAMS;
ReadEhcCapabiltiyReg(
HcDev,
HcCapParamsAddr,
&HcCapParamsReg
);
if (HcCapParamsReg & HCCP_PFLF) {
Value = TRUE;
} else {
Value = FALSE;
}
return Value;
}
BOOLEAN
IsPeriodicScheduleEnabled (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Whether periodic schedule is enabled
Arguments:
HcDev - USB2_HC_DEV
Returns:
TRUE Enabled
FALSE Disabled
--*/
{
BOOLEAN Value;
UINT32 UsbStatusAddr;
UINT32 UsbStatusReg;
UsbStatusAddr = USBSTS;
ReadEhcOperationalReg (
HcDev,
UsbStatusAddr,
&UsbStatusReg
);
if (UsbStatusReg & USBSTS_PSS) {
Value = TRUE;
} else {
Value = FALSE;
}
return Value;
}
BOOLEAN
IsAsyncScheduleEnabled (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Whether asynchronous schedule is enabled
Arguments:
HcDev - USB2_HC_DEV
Returns:
TRUE Enabled
FALSE Disabled
--*/
{
BOOLEAN Value;
UINT32 UsbStatusAddr;
UINT32 UsbStatusReg;
UsbStatusAddr = USBSTS;
ReadEhcOperationalReg (
HcDev,
UsbStatusAddr,
&UsbStatusReg
);
if (UsbStatusReg & USBSTS_ASS) {
Value = TRUE;
} else {
Value = FALSE;
}
return Value;
}
BOOLEAN
IsEhcPortEnabled (
IN USB2_HC_DEV *HcDev,
IN UINT8 PortNum
)
/*++
Routine Description:
Whether port is enabled
Arguments:
HcDev - USB2_HC_DEV
Returns:
TRUE Enabled
FALSE Disabled
--*/
{
UINT32 PortStatusControlAddr;
UINT32 PortStatusControlReg;
PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));
ReadEhcOperationalReg (
HcDev,
PortStatusControlAddr,
&PortStatusControlReg
);
return ((BOOLEAN) ((PortStatusControlReg & PORTSC_PED) ? TRUE : FALSE));
}
BOOLEAN
IsEhcReseted (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Whether Ehc is reseted
Arguments:
HcDev - USB2_HC_DEV
Returns:
TRUE Reseted
FALSE Unreseted
--*/
{
BOOLEAN Value;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UsbCommandAddr = USBCMD;
ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (UsbCommandReg & USBCMD_HCRESET) {
Value = FALSE;
} else {
Value = TRUE;
}
return Value;
}
BOOLEAN
IsEhcHalted (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Whether Ehc is halted
Arguments:
HcDev - USB2_HC_DEV
Returns:
TRUE Halted
FALSE Not halted
--*/
{
BOOLEAN Value;
UINT32 UsbStatusAddr;
UINT32 UsbStatusReg;
UsbStatusAddr = USBSTS;
ReadEhcOperationalReg (
HcDev,
UsbStatusAddr,
&UsbStatusReg
);
if (UsbStatusReg & USBSTS_HCH) {
Value = TRUE;
} else {
Value = FALSE;
}
return Value;
}
BOOLEAN
IsEhcSysError (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Whether Ehc is system error
Arguments:
HcDev - USB2_HC_DEV
Returns:
TRUE System error
FALSE No system error
--*/
{
BOOLEAN Value;
UINT32 UsbStatusAddr;
UINT32 UsbStatusReg;
UsbStatusAddr = USBSTS;
ReadEhcOperationalReg (
HcDev,
UsbStatusAddr,
&UsbStatusReg
);
if (UsbStatusReg & USBSTS_HSE) {
Value = TRUE;
} else {
Value = FALSE;
}
return Value;
}
BOOLEAN
IsHighSpeedDevice (
IN EFI_USB2_HC_PROTOCOL *This,
IN UINT8 PortNum
)
/*++
Routine Description:
Whether high speed device attached
Arguments:
HcDev - USB2_HC_DEV
Returns:
TRUE High speed
FALSE Full speed
--*/
{
USB2_HC_DEV *HcDev;
UINT32 PortStatusControlAddr;
UINT32 PortStatusControlReg;
HcDev = USB2_HC_DEV_FROM_THIS (This);
PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));
//
// Set port reset bit
//
ReadEhcOperationalReg (
HcDev,
PortStatusControlAddr,
&PortStatusControlReg
);
//
// Make sure Host Controller not halt before reset it
//
if (IsEhcHalted (HcDev)) {
StartScheduleExecution (HcDev);
WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT);
}
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg |= PORTSC_PR;
//
// Set one to PortReset bit must also set zero to PortEnable bit
//
PortStatusControlReg &= ~PORTSC_PED;
WriteEhcOperationalReg (
HcDev,
PortStatusControlAddr,
PortStatusControlReg
);
//
// Set Port reset recovery time
//
gBS->Stall (EHCI_SET_PORT_RESET_RECOVERY_TIME);
//
// Clear port reset bit
//
ReadEhcOperationalReg (
HcDev,
PortStatusControlAddr,
&PortStatusControlReg
);
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg &= ~PORTSC_PR;
WriteEhcOperationalReg (
HcDev,
PortStatusControlAddr,
PortStatusControlReg
);
//
// Clear port reset recovery time
//
gBS->Stall (EHCI_CLEAR_PORT_RESET_RECOVERY_TIME);
return ((BOOLEAN) (IsEhcPortEnabled (HcDev, PortNum) ? TRUE : FALSE));
}
EFI_STATUS
WaitForEhcReset (
IN USB2_HC_DEV *HcDev,
IN UINTN Timeout
)
/*++
Routine Description:
wait for Ehc reset or timeout
Arguments:
HcDev - USB2_HC_DEV
Timeout - timeout threshold
Returns:
EFI_SUCCESS Success
EFI_TIMEOUT Timeout
--*/
{
EFI_STATUS Status;
UINTN Delay;
//
// Timeout is in US unit
//
Delay = (Timeout / 50) + 1;
do {
if (IsEhcReseted (HcDev)) {
Status = EFI_SUCCESS;
goto exit;
}
gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
} while (Delay--);
Status = EFI_TIMEOUT;
exit:
return Status;
}
EFI_STATUS
WaitForEhcHalt (
IN USB2_HC_DEV *HcDev,
IN UINTN Timeout
)
/*++
Routine Description:
wait for Ehc halt or timeout
Arguments:
HcDev - USB2_HC_DEV
Timeout - timeout threshold
Returns:
EFI_SUCCESS Success
EFI_TIMEOUT Timeout
--*/
{
EFI_STATUS Status;
UINTN Delay;
//
// Timeout is in US unit
//
Delay = (Timeout / 50) + 1;
do {
if (IsEhcHalted (HcDev)) {
Status = EFI_SUCCESS;
goto exit;
}
gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
} while (Delay--);
Status = EFI_TIMEOUT;
exit:
return Status;
}
EFI_STATUS
WaitForEhcNotHalt (
IN USB2_HC_DEV *HcDev,
IN UINTN Timeout
)
/*++
Routine Description:
wait for Ehc not halt or timeout
Arguments:
HcDev - USB2_HC_DEV
Timeout - timeout threshold
Returns:
EFI_SUCCESS Success
EFI_TIMEOUT Timeout
--*/
{
EFI_STATUS Status;
UINTN Delay;
//
// Timeout is in US unit
//
Delay = (Timeout / 50) + 1;
do {
if (!IsEhcHalted (HcDev)) {
Status = EFI_SUCCESS;
goto exit;
}
gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
} while (Delay--);
Status = EFI_TIMEOUT;
exit:
return Status;
}
EFI_STATUS
WaitForAsyncScheduleEnable (
IN USB2_HC_DEV *HcDev,
IN UINTN Timeout
)
/*++
Routine Description:
Wait for Ehc asynchronous schedule enable or timeout
Arguments:
HcDev - USB2_HC_DEV
Timeout - timeout threshold
Returns:
EFI_SUCCESS Success
EFI_TIMEOUT Timeout
--*/
{
EFI_STATUS Status;
UINTN Delay;
//
// Timeout is in US unit
//
Delay = (Timeout / 50) + 1;
do {
if (IsAsyncScheduleEnabled (HcDev)) {
Status = EFI_SUCCESS;
goto exit;
}
gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
} while (Delay--);
Status = EFI_TIMEOUT;
exit:
return Status;
}
EFI_STATUS
WaitForAsyncScheduleDisable (
IN USB2_HC_DEV *HcDev,
IN UINTN Timeout
)
/*++
Routine Description:
Wait for Ehc asynchronous schedule disable or timeout
Arguments:
HcDev - USB2_HC_DEV
Timeout - timeout threshold
Returns:
EFI_SUCCESS Success
EFI_TIMEOUT Timeout
--*/
{
EFI_STATUS Status;
UINTN Delay;
//
// Timeout is in US unit
//
Delay = (Timeout / 50) + 1;
do {
if (!IsAsyncScheduleEnabled (HcDev)) {
Status = EFI_SUCCESS;
goto exit;
}
gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
} while (Delay--);
Status = EFI_TIMEOUT;
exit:
return Status;
}
EFI_STATUS
WaitForPeriodicScheduleEnable (
IN USB2_HC_DEV *HcDev,
IN UINTN Timeout
)
/*++
Routine Description:
Wait for Ehc periodic schedule enable or timeout
Arguments:
HcDev - USB2_HC_DEV
Timeout - timeout threshold
Returns:
EFI_SUCCESS Success
EFI_TIMEOUT Timeout
--*/
{
EFI_STATUS Status;
UINTN Delay;
//
// Timeout is in US unit
//
Delay = (Timeout / 50) + 1;
do {
if (IsPeriodicScheduleEnabled (HcDev)) {
Status = EFI_SUCCESS;
goto exit;
}
gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
} while (Delay--);
Status = EFI_TIMEOUT;
exit:
return Status;
}
EFI_STATUS
WaitForPeriodicScheduleDisable (
IN USB2_HC_DEV *HcDev,
IN UINTN Timeout
)
/*++
Routine Description:
Wait for periodic schedule disable or timeout
Arguments:
HcDev - USB2_HC_DEV
Timeout - timeout threshold
Returns:
EFI_SUCCESS Success
EFI_TIMEOUT Timeout
--*/
{
EFI_STATUS Status;
UINTN Delay;
//
// Timeout is in US unit
//
Delay = (Timeout / 50) + 1;
do {
if (!IsPeriodicScheduleEnabled (HcDev)) {
Status = EFI_SUCCESS;
goto exit;
}
gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
} while (Delay--);
Status = EFI_TIMEOUT;
exit:
return Status;
}
EFI_STATUS
WaitForEhcDoorbell (
IN USB2_HC_DEV *HcDev,
IN UINTN Timeout
)
/*++
Routine Description:
Wait for periodic schedule disable or timeout
Arguments:
HcDev - USB2_HC_DEV
Timeout - timeout threshold
Returns:
EFI_SUCCESS Success
EFI_TIMEOUT Timeout
--*/
{
EFI_STATUS Status;
UINT32 UsbCommandAddr;
UINT32 UsbCommandReg;
UINTN Delay;
UsbCommandAddr = USBCMD;
Delay = (Timeout / 50) + 1;
do {
Status = ReadEhcOperationalReg (
HcDev,
UsbCommandAddr,
&UsbCommandReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
if (!(UsbCommandReg & USBCMD_IAAD)) {
break;
}
} while (--Delay);
if (0 == Delay) {
Status = EFI_TIMEOUT;
}
exit:
return Status;
}