]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
MdeModulePkg/XhciDxe: Dump the CMD/EVENT/INT/BULK ring information
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / XhciSched.c
index 370d9b81b25dececea36099668bedccbd92d8174..f7f3409686b8c9d13484b0f2cbb571475b63809b 100644 (file)
@@ -2,7 +2,7 @@
 \r
   XHCI transfer scheduling routines.\r
 \r
-Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>\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
@@ -295,7 +295,7 @@ XhcCreateTransferTrb (
       TrbStart->TrbCtrSetup.wValue        = Urb->Request->Value;\r
       TrbStart->TrbCtrSetup.wIndex        = Urb->Request->Index;\r
       TrbStart->TrbCtrSetup.wLength       = Urb->Request->Length;\r
-      TrbStart->TrbCtrSetup.Lenth         = 8;\r
+      TrbStart->TrbCtrSetup.Length        = 8;\r
       TrbStart->TrbCtrSetup.IntTarget     = 0;\r
       TrbStart->TrbCtrSetup.IOC           = 1;\r
       TrbStart->TrbCtrSetup.IDT           = 1;\r
@@ -321,7 +321,7 @@ XhcCreateTransferTrb (
         TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
         TrbStart->TrbCtrData.TRBPtrLo  = XHC_LOW_32BIT(Urb->DataPhy);\r
         TrbStart->TrbCtrData.TRBPtrHi  = XHC_HIGH_32BIT(Urb->DataPhy);\r
-        TrbStart->TrbCtrData.Lenth     = (UINT32) Urb->DataLen;\r
+        TrbStart->TrbCtrData.Length    = (UINT32) Urb->DataLen;\r
         TrbStart->TrbCtrData.TDSize    = 0;\r
         TrbStart->TrbCtrData.IntTarget = 0;\r
         TrbStart->TrbCtrData.ISP       = 1;\r
@@ -387,7 +387,7 @@ XhcCreateTransferTrb (
         TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
         TrbStart->TrbNormal.TRBPtrLo  = XHC_LOW_32BIT((UINT8 *) Urb->DataPhy + TotalLen);\r
         TrbStart->TrbNormal.TRBPtrHi  = XHC_HIGH_32BIT((UINT8 *) Urb->DataPhy + TotalLen);\r
-        TrbStart->TrbNormal.Lenth     = (UINT32) Len;\r
+        TrbStart->TrbNormal.Length    = (UINT32) Len;\r
         TrbStart->TrbNormal.TDSize    = 0;\r
         TrbStart->TrbNormal.IntTarget = 0;\r
         TrbStart->TrbNormal.ISP       = 1;\r
@@ -422,7 +422,7 @@ XhcCreateTransferTrb (
         TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
         TrbStart->TrbNormal.TRBPtrLo  = XHC_LOW_32BIT((UINT8 *) Urb->DataPhy + TotalLen);\r
         TrbStart->TrbNormal.TRBPtrHi  = XHC_HIGH_32BIT((UINT8 *) Urb->DataPhy + TotalLen);\r
-        TrbStart->TrbNormal.Lenth     = (UINT32) Len;\r
+        TrbStart->TrbNormal.Length    = (UINT32) Len;\r
         TrbStart->TrbNormal.TDSize    = 0;\r
         TrbStart->TrbNormal.IntTarget = 0;\r
         TrbStart->TrbNormal.ISP       = 1;\r
@@ -604,8 +604,6 @@ XhcInitSched (
   XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET, XHC_LOW_32BIT(CmdRingPhy));\r
   XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET + 4, XHC_HIGH_32BIT (CmdRingPhy));\r
 \r
-  DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_CRCR=0x%x\n", Xhc->CmdRing.RingSeg0));\r
-\r
   //\r
   // Disable the 'interrupter enable' bit in USB_CMD\r
   // and clear IE & IP bit in all Interrupter X Management Registers.\r
@@ -620,7 +618,10 @@ XhcInitSched (
   // Allocate EventRing for Cmd, Ctrl, Bulk, Interrupt, AsynInterrupt transfer\r
   //\r
   CreateEventRing (Xhc, &Xhc->EventRing);\r
-  DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_EVENTRING=0x%x\n", Xhc->EventRing.EventRingSeg0));\r
+  DEBUG ((DEBUG_INFO, "XhcInitSched: Created CMD ring [%p~%p) EVENT ring [%p~%p)\n",\r
+    Xhc->CmdRing.RingSeg0,        (UINTN)Xhc->CmdRing.RingSeg0 + sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER,\r
+    Xhc->EventRing.EventRingSeg0, (UINTN)Xhc->EventRing.EventRingSeg0 + sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER\r
+    ));\r
 }\r
 \r
 /**\r
@@ -645,12 +646,8 @@ XhcRecoverHaltedEndpoint (
   )\r
 {\r
   EFI_STATUS                  Status;\r
-  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;\r
-  CMD_TRB_RESET_ENDPOINT      CmdTrbResetED;\r
-  CMD_SET_TR_DEQ_POINTER      CmdSetTRDeq;\r
   UINT8                       Dci;\r
   UINT8                       SlotId;\r
-  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
 \r
   Status = EFI_SUCCESS;\r
   SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
@@ -665,17 +662,7 @@ XhcRecoverHaltedEndpoint (
   //\r
   // 1) Send Reset endpoint command to transit from halt to stop state\r
   //\r
-  ZeroMem (&CmdTrbResetED, sizeof (CmdTrbResetED));\r
-  CmdTrbResetED.CycleBit = 1;\r
-  CmdTrbResetED.Type     = TRB_TYPE_RESET_ENDPOINT;\r
-  CmdTrbResetED.EDID     = Dci;\r
-  CmdTrbResetED.SlotId   = SlotId;\r
-  Status = XhcCmdTransfer (\r
-             Xhc,\r
-             (TRB_TEMPLATE *) (UINTN) &CmdTrbResetED,\r
-             XHC_GENERIC_TIMEOUT,\r
-             (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
-             );\r
+  Status = XhcResetEndpoint(Xhc, SlotId, Dci);\r
   if (EFI_ERROR(Status)) {\r
     DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Reset Endpoint Failed, Status = %r\n", Status));\r
     goto Done;\r
@@ -684,22 +671,70 @@ XhcRecoverHaltedEndpoint (
   //\r
   // 2)Set dequeue pointer\r
   //\r
-  ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));\r
-  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring->RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER));\r
-  CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (PhyAddr) | Urb->Ring->RingPCS;\r
-  CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
-  CmdSetTRDeq.CycleBit = 1;\r
-  CmdSetTRDeq.Type     = TRB_TYPE_SET_TR_DEQUE;\r
-  CmdSetTRDeq.Endpoint = Dci;\r
-  CmdSetTRDeq.SlotId   = SlotId;\r
-  Status = XhcCmdTransfer (\r
-             Xhc,\r
-             (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,\r
-             XHC_GENERIC_TIMEOUT,\r
-             (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
-             );\r
+  Status = XhcSetTrDequeuePointer(Xhc, SlotId, Dci, Urb);\r
   if (EFI_ERROR(Status)) {\r
-    DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Set Dequeue Pointer Failed, Status = %r\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Set Transfer Ring Dequeue Pointer Failed, Status = %r\n", Status));\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // 3)Ring the doorbell to transit from stop to active\r
+  //\r
+  XhcRingDoorBell (Xhc, SlotId, Dci);\r
+\r
+Done:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  System software shall use a Stop Endpoint Command (section 4.6.9) and the Set TR Dequeue Pointer\r
+  Command (section 4.6.10) to remove the timed-out TDs from the xHC transfer ring. The next write to\r
+  the Doorbell of the Endpoint will transition the Endpoint Context from the Stopped to the Running\r
+  state.\r
+\r
+  @param  Xhc                   The XHCI Instance.\r
+  @param  Urb                   The urb which doesn't get completed in a specified timeout range.\r
+\r
+  @retval EFI_SUCCESS           The dequeuing of the TDs is successful.\r
+  @retval Others                Failed to stop the endpoint and dequeue the TDs.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcDequeueTrbFromEndpoint (\r
+  IN  USB_XHCI_INSTANCE   *Xhc,\r
+  IN  URB                 *Urb\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINT8                       Dci;\r
+  UINT8                       SlotId;\r
+\r
+  Status = EFI_SUCCESS;\r
+  SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
+  if (SlotId == 0) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\r
+  ASSERT (Dci < 32);\r
+  \r
+  DEBUG ((EFI_D_INFO, "Stop Slot = %x,Dci = %x\n", SlotId, Dci));\r
+\r
+  //\r
+  // 1) Send Stop endpoint command to stop xHC from executing of the TDs on the endpoint\r
+  //\r
+  Status = XhcStopEndpoint(Xhc, SlotId, Dci);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Stop Endpoint Failed, Status = %r\n", Status));\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // 2)Set dequeue pointer\r
+  //\r
+  Status = XhcSetTrDequeuePointer(Xhc, SlotId, Dci, Urb);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Set Transfer Ring Dequeue Pointer Failed, Status = %r\n", Status));\r
     goto Done;\r
   }\r
 \r
@@ -943,41 +978,42 @@ XhcFreeSched (
 }\r
 \r
 /**\r
-  Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list.\r
+  Check if the Trb is a transaction of the URB.\r
 \r
-  @param Xhc    The XHCI Instance.\r
-  @param Trb    The TRB to be checked.\r
-  @param Urb    The pointer to the matched Urb.\r
+  @param Trb    The TRB to be checked\r
+  @param Urb    The URB to be checked.\r
 \r
-  @retval TRUE  The Trb is matched with a transaction of the URBs in the async list.\r
-  @retval FALSE The Trb is not matched with any URBs in the async list.\r
+  @retval TRUE  It is a transaction of the URB.\r
+  @retval FALSE It is not any transaction of the URB.\r
 \r
 **/\r
 BOOLEAN\r
-IsAsyncIntTrb (\r
+IsTransferRingTrb (\r
   IN  USB_XHCI_INSTANCE   *Xhc,\r
   IN  TRB_TEMPLATE        *Trb,\r
-  OUT URB                 **Urb\r
+  IN  URB                 *Urb\r
   )\r
 {\r
-  LIST_ENTRY              *Entry;\r
-  LIST_ENTRY              *Next;\r
-  TRB_TEMPLATE            *CheckedTrb;\r
-  URB                     *CheckedUrb;\r
-  UINTN                   Index;\r
+  LINK_TRB      *LinkTrb;\r
+  TRB_TEMPLATE  *CheckedTrb;\r
+  UINTN         Index;\r
+  EFI_PHYSICAL_ADDRESS PhyAddr;\r
 \r
-  EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) {\r
-    CheckedUrb = EFI_LIST_CONTAINER (Entry, URB, UrbList);\r
-    CheckedTrb = CheckedUrb->TrbStart;\r
-    for (Index = 0; Index < CheckedUrb->TrbNum; Index++) {\r
-      if (Trb == CheckedTrb) {\r
-        *Urb = CheckedUrb;\r
-        return TRUE;\r
-      }\r
-      CheckedTrb++;\r
-      if ((UINTN)CheckedTrb >= ((UINTN) CheckedUrb->Ring->RingSeg0 + sizeof (TRB_TEMPLATE) * CheckedUrb->Ring->TrbNumber)) {\r
-        CheckedTrb = (TRB_TEMPLATE*) CheckedUrb->Ring->RingSeg0;\r
-      }\r
+  CheckedTrb = Urb->TrbStart;\r
+  for (Index = 0; Index < Urb->TrbNum; Index++) {\r
+    if (Trb == CheckedTrb) {\r
+      return TRUE;\r
+    }\r
+    CheckedTrb++;\r
+    //\r
+    // If the checked TRB is the link TRB at the end of the transfer ring,\r
+    // recircle it to the head of the ring.\r
+    //\r
+    if (CheckedTrb->Type == TRB_TYPE_LINK) {\r
+      LinkTrb = (LINK_TRB *) CheckedTrb;\r
+      PhyAddr = (EFI_PHYSICAL_ADDRESS)(LinkTrb->PtrLo | LShiftU64 ((UINT64) LinkTrb->PtrHi, 32));\r
+      CheckedTrb = (TRB_TEMPLATE *)(UINTN) UsbHcGetHostAddrForPciAddr (Xhc->MemPool, (VOID *)(UINTN) PhyAddr, sizeof (TRB_TEMPLATE));\r
+      ASSERT (CheckedTrb == Urb->Ring->RingSeg0);\r
     }\r
   }\r
 \r
@@ -985,38 +1021,39 @@ IsAsyncIntTrb (
 }\r
 \r
 /**\r
-  Check if the Trb is a transaction of the URB.\r
+  Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list.\r
 \r
-  @param Trb    The TRB to be checked\r
-  @param Urb    The transfer ring to be checked.\r
+  @param Xhc    The XHCI Instance.\r
+  @param Trb    The TRB to be checked.\r
+  @param Urb    The pointer to the matched Urb.\r
 \r
-  @retval TRUE  It is a transaction of the URB.\r
-  @retval FALSE It is not any transaction of the URB.\r
+  @retval TRUE  The Trb is matched with a transaction of the URBs in the async list.\r
+  @retval FALSE The Trb is not matched with any URBs in the async list.\r
 \r
 **/\r
 BOOLEAN\r
-IsTransferRingTrb (\r
+IsAsyncIntTrb (\r
+  IN  USB_XHCI_INSTANCE   *Xhc,\r
   IN  TRB_TEMPLATE        *Trb,\r
-  IN  URB                 *Urb\r
+  OUT URB                 **Urb\r
   )\r
 {\r
-  TRB_TEMPLATE  *CheckedTrb;\r
-  UINTN         Index;\r
-\r
-  CheckedTrb = Urb->Ring->RingSeg0;\r
-\r
-  ASSERT (Urb->Ring->TrbNumber == CMD_RING_TRB_NUMBER || Urb->Ring->TrbNumber == TR_RING_TRB_NUMBER);\r
+  LIST_ENTRY              *Entry;\r
+  LIST_ENTRY              *Next;\r
+  URB                     *CheckedUrb;\r
 \r
-  for (Index = 0; Index < Urb->Ring->TrbNumber; Index++) {\r
-    if (Trb == CheckedTrb) {\r
+  EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) {\r
+    CheckedUrb = EFI_LIST_CONTAINER (Entry, URB, UrbList);\r
+    if (IsTransferRingTrb (Xhc, Trb, CheckedUrb)) {\r
+      *Urb = CheckedUrb;\r
       return TRUE;\r
     }\r
-    CheckedTrb++;\r
   }\r
 \r
   return FALSE;\r
 }\r
 \r
+\r
 /**\r
   Check the URB's execution result and update the URB's\r
   result accordingly.\r
@@ -1027,7 +1064,7 @@ IsTransferRingTrb (
   @return Whether the result of URB transfer is finialized.\r
 \r
 **/\r
-EFI_STATUS\r
+BOOLEAN\r
 XhcCheckUrbResult (\r
   IN  USB_XHCI_INSTANCE   *Xhc,\r
   IN  URB                 *Urb\r
@@ -1058,7 +1095,6 @@ XhcCheckUrbResult (
 \r
   if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
     Urb->Result |= EFI_USB_ERR_SYSTEM;\r
-    Status       = EFI_DEVICE_ERROR;\r
     goto EXIT;\r
   }\r
 \r
@@ -1094,7 +1130,7 @@ XhcCheckUrbResult (
     // This way is used to avoid that those completed async transfer events don't get\r
     // handled in time and are flushed by newer coming events.\r
     //\r
-    if (IsTransferRingTrb (TRBPtr, Urb)) {\r
+    if (IsTransferRingTrb (Xhc, TRBPtr, Urb)) {\r
       CheckedUrb = Urb;\r
     } else if (IsAsyncIntTrb (Xhc, TRBPtr, &AsyncUrb)) {    \r
       CheckedUrb = AsyncUrb;\r
@@ -1130,14 +1166,14 @@ XhcCheckUrbResult (
       case TRB_COMPLETION_SHORT_PACKET:\r
       case TRB_COMPLETION_SUCCESS:\r
         if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) {\r
-          DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: short packet happens!\n"));\r
+          DEBUG ((EFI_D_VERBOSE, "XhcCheckUrbResult: short packet happens!\n"));\r
         }\r
 \r
         TRBType = (UINT8) (TRBPtr->Type);\r
         if ((TRBType == TRB_TYPE_DATA_STAGE) ||\r
             (TRBType == TRB_TYPE_NORMAL) ||\r
             (TRBType == TRB_TYPE_ISOCH)) {\r
-          CheckedUrb->Completed += (CheckedUrb->DataLen - EvtTrb->Lenth);\r
+          CheckedUrb->Completed += (((TRANSFER_TRB_NORMAL*)TRBPtr)->Length - EvtTrb->Length);\r
         }\r
 \r
         break;\r
@@ -1189,7 +1225,7 @@ EXIT:
     XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (PhyAddr));\r
   }\r
 \r
-  return Status;\r
+  return Urb->Finished;\r
 }\r
 \r
 \r
@@ -1216,9 +1252,10 @@ XhcExecTransfer (
 {\r
   EFI_STATUS              Status;\r
   UINTN                   Index;\r
-  UINT                  Loop;\r
+  UINT64                  Loop;\r
   UINT8                   SlotId;\r
   UINT8                   Dci;\r
+  BOOLEAN                 Finished;\r
 \r
   if (CmdTransfer) {\r
     SlotId = 0;\r
@@ -1241,8 +1278,8 @@ XhcExecTransfer (
   XhcRingDoorBell (Xhc, SlotId, Dci);\r
 \r
   for (Index = 0; Index < Loop; Index++) {\r
-    Status = XhcCheckUrbResult (Xhc, Urb);\r
-    if (Urb->Finished) {\r
+    Finished = XhcCheckUrbResult (Xhc, Urb);\r
+    if (Finished) {\r
       break;\r
     }\r
     gBS->Stall (XHC_1_MICROSECOND);\r
@@ -1250,6 +1287,9 @@ XhcExecTransfer (
 \r
   if (Index == Loop) {\r
     Urb->Result = EFI_USB_ERR_TIMEOUT;\r
+    Status      = EFI_TIMEOUT;\r
+  } else if (Urb->Result != EFI_USB_NOERROR) {\r
+    Status      = EFI_DEVICE_ERROR;\r
   }\r
 \r
   return Status;\r
@@ -1278,6 +1318,7 @@ XhciDelAsyncIntTransfer (
   LIST_ENTRY              *Next;\r
   URB                     *Urb;\r
   EFI_USB_DATA_DIRECTION  Direction;\r
+  EFI_STATUS              Status;\r
 \r
   Direction = ((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut;\r
   EpNum    &= 0x0F;\r
@@ -1289,6 +1330,15 @@ XhciDelAsyncIntTransfer (
     if ((Urb->Ep.BusAddr == BusAddr) &&\r
         (Urb->Ep.EpAddr == EpNum) &&\r
         (Urb->Ep.Direction == Direction)) {\r
+      //\r
+      // Device doesn't finish the IntTransfer until real data comes\r
+      // So the TRB should be removed as well.\r
+      //\r
+      Status = XhcDequeueTrbFromEndpoint (Xhc, Urb);\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((EFI_D_ERROR, "XhciDelAsyncIntTransfer: XhcDequeueTrbFromEndpoint failed\n"));\r
+      }\r
+\r
       RemoveEntryList (&Urb->UrbList);\r
       FreePool (Urb->Data);\r
       XhcFreeUrb (Xhc, Urb);\r
@@ -1313,9 +1363,20 @@ XhciDelAllAsyncIntTransfers (
   LIST_ENTRY              *Entry;\r
   LIST_ENTRY              *Next;\r
   URB                     *Urb;\r
+  EFI_STATUS              Status;\r
 \r
   EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) {\r
     Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList);\r
+\r
+    //\r
+    // Device doesn't finish the IntTransfer until real data comes\r
+    // So the TRB should be removed as well.\r
+    //\r
+    Status = XhcDequeueTrbFromEndpoint (Xhc, Urb);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "XhciDelAllAsyncIntTransfers: XhcDequeueTrbFromEndpoint failed\n"));\r
+    }\r
+\r
     RemoveEntryList (&Urb->UrbList);\r
     FreePool (Urb->Data);\r
     XhcFreeUrb (Xhc, Urb);\r
@@ -2074,6 +2135,10 @@ XhcInitializeDeviceSlot (
   // 8) Issue an Address Device Command for the Device Slot, where the command points to the Input\r
   //    Context data structure described above.\r
   //\r
+  // Delay 10ms to meet TRSTRCY delay requirement in usb 2.0 spec chapter 7.1.7.5 before sending SetAddress() request\r
+  // to device.\r
+  //\r
+  gBS->Stall (XHC_RESET_RECOVERY_DELAY);\r
   ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));\r
   PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));\r
   CmdTrbAddr.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
@@ -2280,6 +2345,10 @@ XhcInitializeDeviceSlot64 (
   // 8) Issue an Address Device Command for the Device Slot, where the command points to the Input\r
   //    Context data structure described above.\r
   //\r
+  // Delay 10ms to meet TRSTRCY delay requirement in usb 2.0 spec chapter 7.1.7.5 before sending SetAddress() request\r
+  // to device.\r
+  //\r
+  gBS->Stall (XHC_RESET_RECOVERY_DELAY);\r
   ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));\r
   PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));\r
   CmdTrbAddr.PtrLo    = XHC_LOW_32BIT (PhyAddr);\r
@@ -2559,6 +2628,11 @@ XhcInitializeEndpointContext (
       EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
     }\r
 \r
+    if (EpDesc->Length < sizeof (USB_ENDPOINT_DESCRIPTOR)) {\r
+      EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+      continue;\r
+    }\r
+\r
     EpAddr    = (UINT8)(EpDesc->EndpointAddress & 0x0F);\r
     Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);\r
 \r
@@ -2595,6 +2669,11 @@ XhcInitializeEndpointContext (
           EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));\r
           Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
           CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);\r
+          DEBUG ((DEBUG_INFO, "Endpoint[%x]: Created BULK ring [%p~%p)\n",\r
+                  EpDesc->EndpointAddress,\r
+                  EndpointTransferRing->RingSeg0,\r
+                  (UINTN) EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE)\r
+                  ));\r
         }\r
 \r
         break;\r
@@ -2606,7 +2685,26 @@ XhcInitializeEndpointContext (
           InputContext->EP[Dci-1].CErr   = 0;\r
           InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
         }\r
-        break;\r
+        //\r
+        // Get the bInterval from descriptor and init the the interval field of endpoint context.\r
+        // Refer to XHCI 1.1 spec section 6.2.3.6.\r
+        //\r
+        if (DeviceSpeed == EFI_USB_SPEED_FULL) {\r
+          Interval = EpDesc->Interval;\r
+          ASSERT (Interval >= 1 && Interval <= 16);\r
+          InputContext->EP[Dci-1].Interval = Interval + 2;\r
+        } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+          Interval = EpDesc->Interval;\r
+          ASSERT (Interval >= 1 && Interval <= 16);\r
+          InputContext->EP[Dci-1].Interval = Interval - 1;\r
+        }\r
+\r
+        //\r
+        // Do not support isochronous transfer now.\r
+        //\r
+        DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext: Unsupport ISO EP found, Transfer ring is not allocated.\n"));\r
+        EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+        continue;\r
       case USB_ENDPOINT_INTERRUPT:\r
         if (Direction == EfiUsbDataIn) {\r
           InputContext->EP[Dci-1].CErr   = 3;\r
@@ -2644,13 +2742,23 @@ XhcInitializeEndpointContext (
           EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));\r
           Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
           CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);\r
+          DEBUG ((DEBUG_INFO, "Endpoint[%x]: Created INT ring [%p~%p)\n",\r
+                  EpDesc->EndpointAddress,\r
+                  EndpointTransferRing->RingSeg0,\r
+                  (UINTN) EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE)\r
+                  ));\r
         }\r
         break;\r
 \r
       case USB_ENDPOINT_CONTROL:\r
+        //\r
+        // Do not support control transfer now.\r
+        //\r
+        DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext: Unsupport Control EP found, Transfer ring is not allocated.\n"));\r
       default:\r
-        ASSERT (0);\r
-        break;\r
+        DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext: Unknown EP found, Transfer ring is not allocated.\n"));\r
+        EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+        continue;\r
     }\r
 \r
     PhyAddr = UsbHcGetPciAddrForHostAddr (\r
@@ -2658,8 +2766,8 @@ XhcInitializeEndpointContext (
                 ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,\r
                 sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
                 );\r
-    PhyAddr &= ~(0x0F);\r
-    PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;\r
+    PhyAddr &= ~((EFI_PHYSICAL_ADDRESS)0x0F);\r
+    PhyAddr |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;\r
     InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);\r
     InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
 \r
@@ -2712,6 +2820,11 @@ XhcInitializeEndpointContext64 (
       EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
     }\r
 \r
+    if (EpDesc->Length < sizeof (USB_ENDPOINT_DESCRIPTOR)) {\r
+      EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+      continue;\r
+    }\r
+\r
     EpAddr    = (UINT8)(EpDesc->EndpointAddress & 0x0F);\r
     Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);\r
 \r
@@ -2748,6 +2861,11 @@ XhcInitializeEndpointContext64 (
           EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));\r
           Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
           CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);\r
+          DEBUG ((DEBUG_INFO, "Endpoint64[%x]: Created BULK ring [%p~%p)\n",\r
+                  EpDesc->EndpointAddress,\r
+                  EndpointTransferRing->RingSeg0,\r
+                  (UINTN) EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE)\r
+                  ));\r
         }\r
 \r
         break;\r
@@ -2759,7 +2877,26 @@ XhcInitializeEndpointContext64 (
           InputContext->EP[Dci-1].CErr   = 0;\r
           InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
         }\r
-        break;\r
+        //\r
+        // Get the bInterval from descriptor and init the the interval field of endpoint context.\r
+        // Refer to XHCI 1.1 spec section 6.2.3.6.\r
+        //\r
+        if (DeviceSpeed == EFI_USB_SPEED_FULL) {\r
+          Interval = EpDesc->Interval;\r
+          ASSERT (Interval >= 1 && Interval <= 16);\r
+          InputContext->EP[Dci-1].Interval = Interval + 2;\r
+        } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+          Interval = EpDesc->Interval;\r
+          ASSERT (Interval >= 1 && Interval <= 16);\r
+          InputContext->EP[Dci-1].Interval = Interval - 1;\r
+        }\r
+\r
+        //\r
+        // Do not support isochronous transfer now.\r
+        //\r
+        DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext64: Unsupport ISO EP found, Transfer ring is not allocated.\n"));\r
+        EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+        continue;\r
       case USB_ENDPOINT_INTERRUPT:\r
         if (Direction == EfiUsbDataIn) {\r
           InputContext->EP[Dci-1].CErr   = 3;\r
@@ -2797,13 +2934,23 @@ XhcInitializeEndpointContext64 (
           EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));\r
           Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
           CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);\r
+          DEBUG ((DEBUG_INFO, "Endpoint64[%x]: Created INT ring [%p~%p)\n",\r
+                  EpDesc->EndpointAddress,\r
+                  EndpointTransferRing->RingSeg0,\r
+                  (UINTN) EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE)\r
+                  ));\r
         }\r
         break;\r
 \r
       case USB_ENDPOINT_CONTROL:\r
+        //\r
+        // Do not support control transfer now.\r
+        //\r
+        DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext64: Unsupport Control EP found, Transfer ring is not allocated.\n"));\r
       default:\r
-        ASSERT (0);\r
-        break;\r
+        DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext64: Unknown EP found, Transfer ring is not allocated.\n"));\r
+        EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+        continue;\r
     }\r
 \r
     PhyAddr = UsbHcGetPciAddrForHostAddr (\r
@@ -2811,8 +2958,8 @@ XhcInitializeEndpointContext64 (
                 ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,\r
                 sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
                 );\r
-    PhyAddr &= ~(0x0F);\r
-    PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;\r
+    PhyAddr &= ~((EFI_PHYSICAL_ADDRESS)0x0F);\r
+    PhyAddr |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;\r
     InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);\r
     InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
 \r
@@ -2871,6 +3018,11 @@ XhcSetConfigCmd (
       IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
     }\r
 \r
+    if (IfDesc->Length < sizeof (USB_INTERFACE_DESCRIPTOR)) {\r
+      IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+      continue;\r
+    }\r
+\r
     Dci = XhcInitializeEndpointContext (Xhc, SlotId, DeviceSpeed, InputContext, IfDesc);\r
     if (Dci > MaxDci) {\r
       MaxDci = Dci;\r
@@ -2956,6 +3108,11 @@ XhcSetConfigCmd64 (
       IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
     }\r
 \r
+    if (IfDesc->Length < sizeof (USB_INTERFACE_DESCRIPTOR)) {\r
+      IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+      continue;\r
+    }\r
+\r
     Dci = XhcInitializeEndpointContext64 (Xhc, SlotId, DeviceSpeed, InputContext, IfDesc);\r
     if (Dci > MaxDci) {\r
       MaxDci = Dci;\r
@@ -3038,6 +3195,105 @@ XhcStopEndpoint (
   return Status;\r
 }\r
 \r
+/**\r
+  Reset endpoint through XHCI's Reset_Endpoint cmd.\r
+\r
+  @param  Xhc                   The XHCI Instance.\r
+  @param  SlotId                The slot id to be configured.\r
+  @param  Dci                   The device context index of endpoint.\r
+\r
+  @retval EFI_SUCCESS           Reset endpoint successfully.\r
+  @retval Others                Failed to reset endpoint.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcResetEndpoint (\r
+  IN USB_XHCI_INSTANCE      *Xhc,\r
+  IN UINT8                  SlotId,\r
+  IN UINT8                  Dci\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;\r
+  CMD_TRB_RESET_ENDPOINT      CmdTrbResetED;\r
+\r
+  DEBUG ((EFI_D_INFO, "XhcResetEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci));\r
+\r
+  //\r
+  // Send stop endpoint command to transit Endpoint from running to stop state\r
+  //\r
+  ZeroMem (&CmdTrbResetED, sizeof (CmdTrbResetED));\r
+  CmdTrbResetED.CycleBit = 1;\r
+  CmdTrbResetED.Type     = TRB_TYPE_RESET_ENDPOINT;\r
+  CmdTrbResetED.EDID     = Dci;\r
+  CmdTrbResetED.SlotId   = SlotId;\r
+  Status = XhcCmdTransfer (\r
+             Xhc,\r
+             (TRB_TEMPLATE *) (UINTN) &CmdTrbResetED,\r
+             XHC_GENERIC_TIMEOUT,\r
+             (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcResetEndpoint: Reset Endpoint Failed, Status = %r\n", Status));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Set transfer ring dequeue pointer through XHCI's Set_Tr_Dequeue_Pointer cmd.\r
+\r
+  @param  Xhc                   The XHCI Instance.\r
+  @param  SlotId                The slot id to be configured.\r
+  @param  Dci                   The device context index of endpoint.\r
+  @param  Urb                   The dequeue pointer of the transfer ring specified\r
+                                by the urb to be updated.\r
+\r
+  @retval EFI_SUCCESS           Set transfer ring dequeue pointer succeeds.\r
+  @retval Others                Failed to set transfer ring dequeue pointer.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSetTrDequeuePointer (\r
+  IN USB_XHCI_INSTANCE      *Xhc,\r
+  IN UINT8                  SlotId,\r
+  IN UINT8                  Dci,\r
+  IN URB                    *Urb\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;\r
+  CMD_SET_TR_DEQ_POINTER      CmdSetTRDeq;\r
+  EFI_PHYSICAL_ADDRESS        PhyAddr;\r
+\r
+  DEBUG ((EFI_D_INFO, "XhcSetTrDequeuePointer: Slot = 0x%x, Dci = 0x%x, Urb = 0x%x\n", SlotId, Dci, Urb));\r
+\r
+  //\r
+  // Send stop endpoint command to transit Endpoint from running to stop state\r
+  //\r
+  ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));\r
+  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring->RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER));\r
+  CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (PhyAddr) | Urb->Ring->RingPCS;\r
+  CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (PhyAddr);\r
+  CmdSetTRDeq.CycleBit = 1;\r
+  CmdSetTRDeq.Type     = TRB_TYPE_SET_TR_DEQUE;\r
+  CmdSetTRDeq.Endpoint = Dci;\r
+  CmdSetTRDeq.SlotId   = SlotId;\r
+  Status = XhcCmdTransfer (\r
+             Xhc,\r
+             (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,\r
+             XHC_GENERIC_TIMEOUT,\r
+             (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "XhcSetTrDequeuePointer: Set TR Dequeue Pointer Failed, Status = %r\n", Status));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Set interface through XHCI's Configure_Endpoint cmd.\r
 \r
@@ -3105,7 +3361,7 @@ XhcSetInterface (
 \r
   IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
   while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) {\r
-    if (IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) {\r
+    if ((IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) && (IfDesc->Length >= sizeof (USB_INTERFACE_DESCRIPTOR))) {\r
       if (IfDesc->InterfaceNumber == (UINT8) Request->Index) {\r
         if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) {\r
           //\r
@@ -3145,6 +3401,11 @@ XhcSetInterface (
         EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
       }\r
 \r
+      if (EpDesc->Length < sizeof (USB_ENDPOINT_DESCRIPTOR)) {\r
+        EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+        continue;\r
+      }\r
+\r
       EpAddr    = (UINT8) (EpDesc->EndpointAddress & 0x0F);\r
       Direction = (UINT8) ((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);\r
 \r
@@ -3302,7 +3563,7 @@ XhcSetInterface64 (
 \r
   IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
   while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) {\r
-    if (IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) {\r
+    if ((IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) && (IfDesc->Length >= sizeof (USB_INTERFACE_DESCRIPTOR))) {\r
       if (IfDesc->InterfaceNumber == (UINT8) Request->Index) {\r
         if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) {\r
           //\r
@@ -3342,6 +3603,11 @@ XhcSetInterface64 (
         EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
       }\r
 \r
+      if (EpDesc->Length < sizeof (USB_ENDPOINT_DESCRIPTOR)) {\r
+        EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+        continue;\r
+      }\r
+\r
       EpAddr    = (UINT8) (EpDesc->EndpointAddress & 0x0F);\r
       Direction = (UINT8) ((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);\r
 \r