]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c
Add DevicePathUtilities DevicePathToText DevciePathFromText USB2HostController protocols
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / Ehci / Dxe / EhciReg.c
diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c
new file mode 100644 (file)
index 0000000..9ce816e
--- /dev/null
@@ -0,0 +1,1539 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                     \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+    Ehchlp.c\r
+    \r
+Abstract: \r
+    \r
+\r
+Revision History\r
+--*/\r
+\r
+#include "Ehci.h"\r
+\r
+\r
+EFI_STATUS\r
+ReadEhcCapabiltiyReg (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINT32                  CapabiltiyRegAddr,\r
+  IN OUT UINT32              *Data\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Read  Ehc Capabitlity register\r
+  \r
+Arguments:\r
+\r
+  HcDev              - USB2_HC_DEV \r
+  CapabiltiyRegAddr  - Ehc Capability register address\r
+  Data               - A pointer to data read from register\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS        Success\r
+  EFI_DEVICE_ERROR   Fail\r
+    \r
+--*/\r
+{\r
+  return HcDev->PciIo->Mem.Read (\r
+                             HcDev->PciIo,\r
+                             EfiPciIoWidthUint32,\r
+                             USB_BAR_INDEX,\r
+                             (UINT64) CapabiltiyRegAddr,\r
+                             1,\r
+                             Data\r
+                             );\r
+}\r
+\r
+EFI_STATUS\r
+ReadEhcOperationalReg (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINT32                  OperationalRegAddr,\r
+  IN OUT UINT32              *Data\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Read  Ehc Operation register\r
+  \r
+Arguments:\r
+\r
+  HcDev                - USB2_HC_DEV \r
+  OperationalRegAddr   - Ehc Operation register address\r
+  Data                 - A pointer to data read from register\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS        Success\r
+  EFI_DEVICE_ERROR   Fail\r
+    \r
+--*/\r
+{\r
+  ASSERT (mUsbCapabilityLen);\r
+  return HcDev->PciIo->Mem.Read (\r
+                             HcDev->PciIo,\r
+                             EfiPciIoWidthUint32,\r
+                             USB_BAR_INDEX,\r
+                             (UINT64) (OperationalRegAddr + mUsbCapabilityLen),\r
+                             1,\r
+                             Data\r
+                             );\r
+}\r
+\r
+EFI_STATUS\r
+WriteEhcOperationalReg (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINT32                  OperationalRegAddr,\r
+  IN UINT32                  Data\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Write  Ehc Operation register\r
+  \r
+Arguments:\r
+\r
+  HcDev                - USB2_HC_DEV \r
+  OperationalRegAddr   - Ehc Operation register address\r
+  Data                 - 32bit write to register\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS        Success\r
+  EFI_DEVICE_ERROR   Fail\r
+  \r
+--*/\r
+{\r
+  ASSERT (mUsbCapabilityLen);\r
+  return HcDev->PciIo->Mem.Write (\r
+                             HcDev->PciIo,\r
+                             EfiPciIoWidthUint32,\r
+                             USB_BAR_INDEX,\r
+                             (UINT64) (OperationalRegAddr + mUsbCapabilityLen),\r
+                             1,\r
+                             &Data\r
+                             );\r
+}\r
+\r
+EFI_STATUS\r
+GetCapabilityLen (\r
+  IN USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get the length of capability register\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+    \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      CapabilityLenAddr;\r
+\r
+  CapabilityLenAddr = CAPLENGTH;\r
+\r
+  Status = ReadEhcCapabiltiyReg (\r
+             HcDev,\r
+             CapabilityLenAddr,\r
+             &mUsbCapabilityLen\r
+             );\r
+  mUsbCapabilityLen = (UINT8) mUsbCapabilityLen;\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SetFrameListLen (\r
+  IN USB2_HC_DEV     *HcDev,\r
+  IN UINTN           Length\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set the length of Frame List\r
+  \r
+Arguments:\r
+\r
+  HcDev    - USB2_HC_DEV \r
+  Length   - the required length of frame list\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS            Success\r
+  EFI_INVALID_PARAMETER  Invalid parameter\r
+  EFI_DEVICE_ERROR       Fail\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      UsbCommandAddr;\r
+  UINT32      UsbCommandReg;\r
+\r
+  UsbCommandAddr = USBCMD;\r
+\r
+  if (256 != Length && 512 != Length) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto exit;\r
+  }\r
+\r
+  Status = ReadEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             &UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto exit;\r
+  }\r
+\r
+  if (256 == Length) {\r
+    UsbCommandReg |= USBCMD_FLS_256;\r
+  } else {\r
+    UsbCommandReg |= USBCMD_FLS_512;\r
+  }\r
+\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SetFrameListBaseAddr (\r
+  IN USB2_HC_DEV     *HcDev,\r
+  IN UINT32          FrameBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set base address of frame list first entry\r
+  \r
+Arguments:\r
+\r
+  HcDev        - USB2_HC_DEV \r
+  FrameBuffer  - base address of first entry of frame list\r
+  \r
+Returns:\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      PeriodicListBaseAddr;\r
+  UINT32      PeriodicListBaseReg;\r
+\r
+  Status                = EFI_SUCCESS;\r
+  PeriodicListBaseAddr  = PERIODICLISTBASE;\r
+  PeriodicListBaseReg   = FrameBuffer & 0xfffff000;\r
+\r
+  if (IsEhcHalted (HcDev)) {\r
+\r
+    Status = WriteEhcOperationalReg (\r
+               HcDev,\r
+               PeriodicListBaseAddr,\r
+               PeriodicListBaseReg\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto exit;\r
+    }\r
+\r
+  }\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SetAsyncListAddr (\r
+  IN USB2_HC_DEV        *HcDev,\r
+  IN EHCI_QH_ENTITY     *QhPtr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set address of first Async schedule Qh\r
+  \r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV \r
+  QhPtr   - A pointer to first Qh in the Async schedule\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+    \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      AsyncListAddr;\r
+  UINT32      AsyncListReg;\r
+\r
+  AsyncListAddr = ASYNCLISTADDR;\r
+  AsyncListReg  = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh));\r
+\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             AsyncListAddr,\r
+             AsyncListReg\r
+             );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SetCtrlDataStructSeg (\r
+  IN USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set register of control and data structure segment\r
+  \r
+Arguments:\r
+\r
+  HcDev  - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+  \r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      CtrlDsSegmentAddr;\r
+  UINT32      CtrlDsSegmentReg;\r
+\r
+  CtrlDsSegmentAddr = CTRLDSSGMENT;\r
+  CtrlDsSegmentReg  = HcDev->High32BitAddr;\r
+\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             CtrlDsSegmentAddr,\r
+             CtrlDsSegmentReg\r
+             );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SetPortRoutingEhc (\r
+  IN USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set Ehc port routing bit\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+    \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      ConfigFlagAddr;\r
+  UINT32      ConfigFlagReg;\r
+\r
+  ConfigFlagAddr = CONFIGFLAG;\r
+\r
+  Status = ReadEhcOperationalReg (\r
+             HcDev,\r
+             ConfigFlagAddr,\r
+             &ConfigFlagReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto exit;\r
+  }\r
+\r
+  ConfigFlagReg |= CONFIGFLAG_CF;\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             ConfigFlagAddr,\r
+             ConfigFlagReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SetEhcDoorbell (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set Ehc door bell bit\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+     \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      UsbCommandAddr;\r
+  UINT32      UsbCommandReg;\r
+\r
+  UsbCommandAddr = USBCMD;\r
+\r
+  Status = ReadEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             &UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto exit;\r
+  }\r
+\r
+  UsbCommandReg |= USBCMD_IAAD;\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+ClearEhcAllStatus (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Clear Ehc all status bits\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+     \r
+--*/\r
+{\r
+  UINT32  UsbStatusAddr;\r
+\r
+  UsbStatusAddr = USBSTS;\r
+\r
+  return WriteEhcOperationalReg (\r
+           HcDev,\r
+           UsbStatusAddr,\r
+           0x003F\r
+           );\r
+}\r
+\r
+EFI_STATUS\r
+EnablePeriodicSchedule (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Enable periodic schedule\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+   \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      UsbCommandAddr;\r
+  UINT32      UsbCommandReg;\r
+\r
+  UsbCommandAddr = USBCMD;\r
+\r
+  Status = ReadEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             &UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto exit;\r
+  }\r
+\r
+  UsbCommandReg |= USBCMD_PSE;\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+DisablePeriodicSchedule (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Disable periodic schedule\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+   \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      UsbCommandAddr;\r
+  UINT32      UsbCommandReg;\r
+\r
+  UsbCommandAddr = USBCMD;\r
+\r
+  Status = ReadEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             &UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  UsbCommandReg &= ~USBCMD_PSE;\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EnableAsynchronousSchedule (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Enable asynchrounous schedule\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+    \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      UsbCommandAddr;\r
+  UINT32      UsbCommandReg;\r
+\r
+  UsbCommandAddr = USBCMD;\r
+\r
+  Status = ReadEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             &UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto exit;\r
+  }\r
+\r
+  UsbCommandReg |= USBCMD_ASE;\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+DisableAsynchronousSchedule (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Disable asynchrounous schedule\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+   \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      UsbCommandAddr;\r
+  UINT32      UsbCommandReg;\r
+\r
+  UsbCommandAddr = USBCMD;\r
+\r
+  Status = ReadEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             &UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  UsbCommandReg &= ~USBCMD_ASE;\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+ResetEhc (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Reset Ehc\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+   \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      UsbCommandAddr;\r
+  UINT32      UsbCommandReg;\r
+\r
+  UsbCommandAddr = USBCMD;\r
+\r
+  Status = ReadEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             &UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto exit;\r
+  }\r
+\r
+  UsbCommandReg |= USBCMD_HCRESET;\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+StartScheduleExecution (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Start Ehc schedule execution\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS       Success\r
+  EFI_DEVICE_ERROR  Fail\r
+   \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      UsbCommandAddr;\r
+  UINT32      UsbCommandReg;\r
+\r
+  UsbCommandAddr = USBCMD;\r
+\r
+  Status = ReadEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             &UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto exit;\r
+  }\r
+\r
+  UsbCommandReg |= USBCMD_RS;\r
+  Status = WriteEhcOperationalReg (\r
+             HcDev,\r
+             UsbCommandAddr,\r
+             UsbCommandReg\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+BOOLEAN\r
+IsFrameListProgrammable (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Whether frame list is programmable\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  TRUE   Programmable\r
+  FALSE  Unprogrammable\r
+  \r
+--*/\r
+{\r
+  BOOLEAN Value;\r
+  UINT32  HcCapParamsAddr;\r
+  UINT32  HcCapParamsReg;\r
+\r
+  HcCapParamsAddr = HCCPARAMS;\r
+\r
+  ReadEhcOperationalReg (\r
+    HcDev,\r
+    HcCapParamsAddr,\r
+    &HcCapParamsReg\r
+    );\r
+\r
+  if (HcCapParamsReg & HCCP_PFLF) {\r
+    Value = TRUE;\r
+  } else {\r
+    Value = FALSE;\r
+  }\r
+\r
+  return Value;\r
+}\r
+\r
+BOOLEAN\r
+IsPeriodicScheduleEnabled (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Whether periodic schedule is enabled\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  TRUE    Enabled\r
+  FALSE   Disabled\r
+  \r
+--*/\r
+{\r
+  BOOLEAN Value;\r
+  UINT32  UsbStatusAddr;\r
+  UINT32  UsbStatusReg;\r
+\r
+  UsbStatusAddr = USBSTS;\r
+\r
+  ReadEhcOperationalReg (\r
+    HcDev,\r
+    UsbStatusAddr,\r
+    &UsbStatusReg\r
+    );\r
+\r
+  if (UsbStatusReg & USBSTS_PSS) {\r
+    Value = TRUE;\r
+  } else {\r
+    Value = FALSE;\r
+  }\r
+\r
+  return Value;\r
+}\r
+\r
+BOOLEAN\r
+IsAsyncScheduleEnabled (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Whether asynchronous schedule is enabled\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  TRUE   Enabled\r
+  FALSE  Disabled\r
+  \r
+--*/\r
+{\r
+  BOOLEAN Value;\r
+  UINT32  UsbStatusAddr;\r
+  UINT32  UsbStatusReg;\r
+\r
+  UsbStatusAddr = USBSTS;\r
+\r
+  ReadEhcOperationalReg (\r
+    HcDev,\r
+    UsbStatusAddr,\r
+    &UsbStatusReg\r
+    );\r
+\r
+  if (UsbStatusReg & USBSTS_ASS) {\r
+    Value = TRUE;\r
+  } else {\r
+    Value = FALSE;\r
+  }\r
+\r
+  return Value;\r
+}\r
+\r
+BOOLEAN\r
+IsEhcPortEnabled (\r
+  IN  USB2_HC_DEV     *HcDev,\r
+  IN  UINT8           PortNum\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Whether port is enabled\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  TRUE   Enabled\r
+  FALSE  Disabled\r
+  \r
+--*/\r
+{\r
+  UINT32  PortStatusControlAddr;\r
+  UINT32  PortStatusControlReg;\r
+\r
+  PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));\r
+\r
+  ReadEhcOperationalReg (\r
+    HcDev,\r
+    PortStatusControlAddr,\r
+    &PortStatusControlReg\r
+    );\r
+\r
+  return ((PortStatusControlReg & PORTSC_PED) ? TRUE : FALSE);\r
+}\r
+\r
+BOOLEAN\r
+IsEhcReseted (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Whether Ehc is reseted\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  TRUE   Reseted\r
+  FALSE  Unreseted\r
+  \r
+--*/\r
+{\r
+  BOOLEAN Value;\r
+  UINT32  UsbCommandAddr;\r
+  UINT32  UsbCommandReg;\r
+\r
+  UsbCommandAddr = USBCMD;\r
+\r
+  ReadEhcOperationalReg (\r
+    HcDev,\r
+    UsbCommandAddr,\r
+    &UsbCommandReg\r
+    );\r
+\r
+  if (UsbCommandReg & USBCMD_HCRESET) {\r
+    Value = FALSE;\r
+  } else {\r
+    Value = TRUE;\r
+  }\r
+\r
+  return Value;\r
+}\r
+\r
+BOOLEAN\r
+IsEhcHalted (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Whether Ehc is halted\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  TRUE   Halted\r
+  FALSE  Not halted\r
+  \r
+--*/\r
+{\r
+  BOOLEAN Value;\r
+  UINT32  UsbStatusAddr;\r
+  UINT32  UsbStatusReg;\r
+\r
+  UsbStatusAddr = USBSTS;\r
+\r
+  ReadEhcOperationalReg (\r
+    HcDev,\r
+    UsbStatusAddr,\r
+    &UsbStatusReg\r
+    );\r
+\r
+  if (UsbStatusReg & USBSTS_HCH) {\r
+    Value = TRUE;\r
+  } else {\r
+    Value = FALSE;\r
+  }\r
+\r
+  return Value;\r
+}\r
+\r
+BOOLEAN\r
+IsEhcSysError (\r
+  IN  USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Whether Ehc is system error\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  TRUE   System error\r
+  FALSE  No system error\r
+  \r
+--*/\r
+{\r
+  BOOLEAN Value;\r
+  UINT32  UsbStatusAddr;\r
+  UINT32  UsbStatusReg;\r
+\r
+  UsbStatusAddr = USBSTS;\r
+\r
+  ReadEhcOperationalReg (\r
+    HcDev,\r
+    UsbStatusAddr,\r
+    &UsbStatusReg\r
+    );\r
+\r
+  if (UsbStatusReg & USBSTS_HSE) {\r
+    Value = TRUE;\r
+  } else {\r
+    Value = FALSE;\r
+  }\r
+\r
+  return Value;\r
+}\r
+\r
+BOOLEAN\r
+IsHighSpeedDevice (\r
+  IN EFI_USB2_HC_PROTOCOL *This,\r
+  IN UINT8                PortNum \r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Whether high speed device attached\r
+  \r
+Arguments:\r
+\r
+  HcDev - USB2_HC_DEV \r
+  \r
+Returns:\r
+\r
+  TRUE   High speed\r
+  FALSE  Full speed\r
+  \r
+--*/\r
+{\r
+  USB2_HC_DEV          *HcDev;\r
+  UINT32               PortStatusControlAddr;\r
+  UINT32               PortStatusControlReg;\r
+  \r
+  HcDev = USB2_HC_DEV_FROM_THIS (This);\r
+  PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));\r
+\r
+  //\r
+  // Set port reset bit\r
+  //\r
+  ReadEhcOperationalReg (\r
+    HcDev,\r
+    PortStatusControlAddr,\r
+    &PortStatusControlReg\r
+    );\r
+  //\r
+  // Make sure Host Controller not halt before reset it\r
+  //\r
+  if (IsEhcHalted (HcDev)) {\r
+    StartScheduleExecution (HcDev);\r
+    WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT);\r
+  }\r
+  PortStatusControlReg &= 0xffffffd5;\r
+  PortStatusControlReg |= PORTSC_PR;\r
+  //\r
+  // Set one to PortReset bit must also set zero to PortEnable bit\r
+  //\r
+  PortStatusControlReg &= ~PORTSC_PED;\r
+  WriteEhcOperationalReg (\r
+    HcDev,\r
+    PortStatusControlAddr,\r
+    PortStatusControlReg\r
+    );\r
+\r
+  //\r
+  // Set Port reset recovery time\r
+  //\r
+  gBS->Stall (EHCI_SET_PORT_RESET_RECOVERY_TIME);\r
+\r
+  //\r
+  // Clear port reset bit\r
+  //\r
+  ReadEhcOperationalReg (\r
+    HcDev,\r
+    PortStatusControlAddr,\r
+    &PortStatusControlReg\r
+    );\r
+  PortStatusControlReg &= 0xffffffd5;\r
+  PortStatusControlReg &= ~PORTSC_PR;\r
+  WriteEhcOperationalReg (\r
+    HcDev,\r
+    PortStatusControlAddr,\r
+    PortStatusControlReg\r
+    );\r
+\r
+  //\r
+  // Clear port reset recovery time\r
+  //\r
+  gBS->Stall (EHCI_CLEAR_PORT_RESET_RECOVERY_TIME);\r
+\r
+  return (IsEhcPortEnabled (HcDev, PortNum) ? TRUE : FALSE);\r
+}\r
+\r
+EFI_STATUS\r
+WaitForEhcReset (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINTN                   Timeout\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  wait for Ehc reset or timeout\r
+  \r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV \r
+  Timeout - timeout threshold\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS    Success\r
+  EFI_TIMEOUT    Timeout\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Delay;\r
+\r
+  //\r
+  // Timeout is in US unit\r
+  //\r
+  Delay = (Timeout / 50) + 1;\r
+  do {\r
+\r
+    if (IsEhcReseted (HcDev)) {\r
+      Status = EFI_SUCCESS;\r
+      goto exit;\r
+    }\r
+    gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
+\r
+  } while (Delay--);\r
+\r
+  Status = EFI_TIMEOUT;\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+WaitForEhcHalt (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINTN                   Timeout\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  wait for Ehc halt or timeout\r
+  \r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV \r
+  Timeout - timeout threshold\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS    Success\r
+  EFI_TIMEOUT    Timeout\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Delay;\r
+\r
+  //\r
+  // Timeout is in US unit\r
+  //\r
+  Delay = (Timeout / 50) + 1;\r
+  do {\r
+\r
+    if (IsEhcHalted (HcDev)) {\r
+      Status = EFI_SUCCESS;\r
+      goto exit;\r
+    }\r
+    gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
+\r
+  } while (Delay--);\r
+\r
+  Status = EFI_TIMEOUT;\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+WaitForEhcNotHalt (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINTN                   Timeout\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  wait for Ehc not halt or timeout\r
+  \r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV \r
+  Timeout - timeout threshold\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS    Success\r
+  EFI_TIMEOUT    Timeout\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Delay;\r
+\r
+  //\r
+  // Timeout is in US unit\r
+  //\r
+  Delay = (Timeout / 50) + 1;\r
+  do {\r
+\r
+    if (!IsEhcHalted (HcDev)) {\r
+      Status = EFI_SUCCESS;\r
+      goto exit;\r
+    }\r
+    gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
+\r
+  } while (Delay--);\r
+\r
+  Status = EFI_TIMEOUT;\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+WaitForAsyncScheduleEnable (\r
+  IN  USB2_HC_DEV            *HcDev,\r
+  IN UINTN                   Timeout\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Wait for Ehc asynchronous schedule enable or timeout\r
+  \r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV \r
+  Timeout - timeout threshold\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS    Success\r
+  EFI_TIMEOUT    Timeout\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Delay;\r
+\r
+  //\r
+  // Timeout is in US unit\r
+  //\r
+  Delay = (Timeout / 50) + 1;\r
+  do {\r
+\r
+    if (IsAsyncScheduleEnabled (HcDev)) {\r
+      Status = EFI_SUCCESS;\r
+      goto exit;\r
+    }\r
+    gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
+\r
+  } while (Delay--);\r
+\r
+  Status = EFI_TIMEOUT;\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+WaitForAsyncScheduleDisable (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINTN                   Timeout\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Wait for Ehc asynchronous schedule disable or timeout\r
+  \r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV \r
+  Timeout - timeout threshold\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS    Success\r
+  EFI_TIMEOUT    Timeout\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Delay;\r
+\r
+  //\r
+  // Timeout is in US unit\r
+  //\r
+  Delay = (Timeout / 50) + 1;\r
+  do {\r
+\r
+    if (!IsAsyncScheduleEnabled (HcDev)) {\r
+      Status = EFI_SUCCESS;\r
+      goto exit;\r
+    }\r
+    gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
+\r
+  } while (Delay--);\r
+\r
+  Status = EFI_TIMEOUT;\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+WaitForPeriodicScheduleEnable (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINTN                   Timeout\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Wait for Ehc periodic schedule enable or timeout\r
+  \r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV \r
+  Timeout - timeout threshold\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS    Success\r
+  EFI_TIMEOUT    Timeout\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Delay;\r
+\r
+  //\r
+  // Timeout is in US unit\r
+  //\r
+  Delay = (Timeout / 50) + 1;\r
+  do {\r
+\r
+    if (IsPeriodicScheduleEnabled (HcDev)) {\r
+      Status = EFI_SUCCESS;\r
+      goto exit;\r
+    }\r
+    gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
+\r
+  } while (Delay--);\r
+\r
+  Status = EFI_TIMEOUT;\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+WaitForPeriodicScheduleDisable (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINTN                   Timeout\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Wait for periodic schedule disable or timeout\r
+  \r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV \r
+  Timeout - timeout threshold\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS    Success\r
+  EFI_TIMEOUT    Timeout\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Delay;\r
+\r
+  //\r
+  // Timeout is in US unit\r
+  //\r
+  Delay = (Timeout / 50) + 1;\r
+  do {\r
+\r
+    if (!IsPeriodicScheduleEnabled (HcDev)) {\r
+      Status = EFI_SUCCESS;\r
+      goto exit;\r
+    }\r
+    gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
+\r
+  } while (Delay--);\r
+\r
+  Status = EFI_TIMEOUT;\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+WaitForEhcDoorbell (\r
+  IN USB2_HC_DEV             *HcDev,\r
+  IN UINTN                   Timeout\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Wait for periodic schedule disable or timeout\r
+\r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV \r
+  Timeout - timeout threshold\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS    Success\r
+  EFI_TIMEOUT    Timeout\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      UsbCommandAddr;\r
+  UINT32      UsbCommandReg;\r
+  UINTN       Delay;\r
+\r
+  UsbCommandAddr  = USBCMD;\r
+  Delay           = (Timeout / 50) + 1;\r
+  \r
+  do {\r
+    Status = ReadEhcOperationalReg (\r
+               HcDev,\r
+               UsbCommandAddr,\r
+               &UsbCommandReg\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto exit;\r
+    }\r
+    if (!(UsbCommandReg & USBCMD_IAAD)) {\r
+      break;\r
+    }\r
+       \r
+  } while (--Delay);\r
+\r
+  if (0 == Delay) {\r
+    Status = EFI_TIMEOUT;\r
+  }\r
+\r
+exit:\r
+  return Status;\r
+}\r