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