/*++ 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; }